provision.service.inc 8.11 KB
Newer Older
Adrian Rossouw's avatar
Adrian Rossouw committed
1 2
<?php

3
require_once('provision.inc');
4

5 6 7 8
require_once DRUSH_BASE_PATH . '/commands/core/rsync.core.inc';


class provisionService extends provisionChainedState {
9
  protected $server = '@server_master';
10
  public $context;
11

12
  protected $service = null;
13
  protected $application_name = null;
14 15 16 17

  protected $has_restart_cmd = FALSE;
  protected $has_port = FALSE;

18
  protected $configs = array();
19

20
  
21
  protected $config_cache = array();
22
  private $_config = null;
23

24 25 26 27 28 29 30 31 32 33

  /**
   * Implement the __call magic method.
   *
   * This implementation is really simple. It simply return null if the
   * method doesn't exist.
   *
   * This is used so that we can create methods for drush commands, and
   * can fail safely.
   */
34 35
  function __call($name, $args = array()) {
    return provision::method_invoke($this, $name, $args);
36 37 38
  }


39
  function init() {
40 41 42 43 44

  }

  // All services have the ability to have an associated restart command and listen port.
  function init_server() {
45 46 47 48 49 50 51 52 53 54 55
    if (!is_null($this->service)) {
      if ($this->has_port) {
        $this->server->setProperty($this->service . '_port', $this->default_port());
      }
      if ($this->has_restart_cmd) {
        $this->server->setProperty($this->service . '_restart_cmd', $this->default_restart_cmd());
      }
    }
    return TRUE;
  }

56 57 58 59 60 61 62 63 64
  function init_platform() {

  }

  function init_site() {

  }


65 66 67 68 69 70 71 72
  function default_port() {
    return false;
  }

  function default_restart_cmd() {
    return false;
  }

73 74 75 76 77 78 79 80 81
  /**
   * Set the currently active configuration object.
   *
   * @param $config
   *   String: Name of config file. The key to the $this->configs array.
   * @param $data
   *   Any optional information to be made available to templates. If a string, it will be
   *   turned into an array with the 'name' property the value of the string.
   */
82 83
  function config($config, $data = array()) {
    $this->_config = null;
84 85 86 87
    
    if (!is_array($data) && is_string($data)) {
      $data = array('name' => $data);
    }
88

89 90 91 92 93 94 95
    if (!isset($this->config_cache[$this->context->name][$config])) {
      foreach ((array) $this->configs[$config] as $class) {
        $this->config_cache[$this->context->name][$config] = new $class($this->context, array_merge($this->config_data($config), $data));
      }
    }

    if (isset($this->config_cache[$this->context->name][$config])) {
96
      $this->_config = $this->config_cache[$this->context->name][$config];
97
    }
98

99 100 101
    return $this;
  }

102 103 104
  /**
   * Unlink the currently active config file.
   */
105 106 107 108
  function unlink() {
    if (is_object($this->_config)) {
      $this->_config->unlink();
    }
109

110 111 112
    return $this;
  }

113 114 115
  /**
   * Write the currently active config file.
   */
116 117 118 119 120 121 122 123
  function write() {
    if (is_object($this->_config)) {
      $this->_config->write();
    }

    return $this;
  }

124 125 126
  /**
   * Set a record on the data store of the currently active config file (if applicable).
   */
127 128 129 130 131 132 133
  function record_set($arg1, $arg2 = null) {
    if (is_object($this->_config)) {
      if (is_object($this->_config->store)) {
        if (is_array($arg1)) {
          $this->_config->store->records = array_merge($this->_config->store->records, $arg1);
        }
        elseif (!is_numeric($arg1)) {
134 135 136 137 138 139 140 141 142 143 144
          if (is_array($arg2)) {
            if (!is_array($this->_config->store->loaded_records[$arg1])) {
              $this->_config->store->loaded_records[$arg1] = array();
            }
            if (!is_array($this->_config->store->records[$arg1])) {
              $this->_config->store->records[$arg1] = array();
            }
            $this->_config->store->records[$arg1] = array_merge($this->_config->store->loaded_records[$arg1], $this->_config->store->records[$arg1], $arg2);
          } else {
            $this->_config->store->records[$arg1] = $arg2;
          }
145 146 147 148 149 150
        }
      }
    }
    return $this;
  }

151 152 153
  /**
   * Delete a record from the data store of the currently active config file (if applicable).
   */
154 155
  function record_del($record) {
    return $this->record_set($record, null);
156 157
  }

158 159 160
  /**
   * Check if a record exists in the data store of the currently active config file (if applicable).
   */
161 162 163 164 165 166 167 168 169
  function record_exists($record) {
    if (is_object($this->_config)) {
      if (is_object($this->_config->store)) {
        return array_key_exists($record, $this->_config->store->merged_records());
      }
    }
    return FALSE;
  }

170 171 172
  /**
   * Fetch record(s) from the data store of the currently active config file (if applicable).
   */
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
  function record_get($key = null, $default = null) {
    if (is_object($this->_config)) {
      if (is_object($this->_config->store)) {
        $records = $this->_config->store->merged_records();

        if (is_null($key)) {
          return $records;
        }

        if (isset($records[$key])) {
          return $records[$key];
        }
      }
    }
    return $default;
  }


191 192 193 194 195 196
  /**
   * Generate a configuration file.
   *
   * This method will fetch the class to instantiate from the internal
   * $this->configs control array.
   */
197 198
  function create_config($config, $data = array()) {
    $this->config($config, $data)->write();
199 200 201
  }

  /**
202
   * Delete a configuration file.
203 204 205 206
   * 
   * This method will fetch the class to instantiate from the internal
   * $this->configs control array.
   */
207
  function delete_config($config, $data = array()) {
208
    $this->config($config, $data)->unlink();
209 210 211 212 213 214 215
  }

  /**
   * Fetch extra information the service wants to pass to he config file classes.
   */
  function config_data($config = null, $class = null) {
    $data = array();
216
    // Always pass the server this service is running on to configs.
217
    $data['server'] = $this->server;
218 219 220 221 222

    if (!is_null($this->application_name)) {
      // This value may be useful to standardize paths in config files.
      $data['application_name'] = $this->application_name;
    }
223 224 225
    return $data;
  }

226

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  /**
   * Restart the service using the provided restart command.
   */
  function restart() {
    // Only attempt to restart real services can have restart commands.
    if (!is_null($this->service) && $this->has_restart_cmd) {
      $service = (!is_null($this->application_name)) ? $this->application_name : $this->service;

      // Only attempt to restart if the command has been filled in.
      if ($cmd = $this->server->{"{$this->service}_restart_cmd"}) {
        if ($this->server->shell_exec($cmd)) {
          drush_log(dt('%service on %server has been restarted', array(
            '%service' => $service,
            '%server' => $this->server->remote_host))
          );

          return TRUE;
        }
        else {
          drush_log(dt('%service on %server could not be restarted.'.
            ' Changes might not be available until this has been done. (error: %msg)', array(
            '%service' => $service,
            '%server' => $this->server->remote_host, 
            '%msg' => join("\n", drush_shell_exec_output()))), 'warning');
        }
      }
    }
    return FALSE;
  }
256

257
  function __construct($server) {
258
    $this->server = is_object($server) ? $server : d($server);
259
  }
260

261 262 263
  /**
   * Set the currently active context of the service.
   */
264 265
  function setContext($context) {
    $this->context = is_object($context) ? $context : d($context);
266 267
  }

268 269 270
  /**
   * Sync filesystem changes to the server hosting this service.
   */
drumm's avatar
drumm committed
271 272
  function sync($path = NULL, $additional_options = array()) {
    return $this->server->sync($path, $additional_options);
273 274
  }

275 276 277 278
  function fetch($path = NULL) {
    return $this->server->fetch($path);
  }

279 280
  function verify() {
    return TRUE;
281 282
  }

drumm's avatar
drumm committed
283 284 285 286 287 288 289 290 291
  /**
   * Return service-specific configuration options for help.
   *
   * @return
   *   array('--option' => 'description')
   */
  static function option_documentation() {
    return array();
  }
292
}
293

294 295 296 297 298 299 300
/**
 * Null service class.
 *
 * Not all services are necessary or turned on.
 * This class ensures that not having a specific service
 * doesnt result in catastrophic failure.
 */
Adrian Rossouw's avatar
Adrian Rossouw committed
301
class provisionService_null extends provisionService {
302 303 304 305 306 307 308 309 310

  function __get($name) {
    return false;
  }

  function __call($name, $args) {
    return false;
  }

311 312 313 314 315 316 317
  /**
   * Null services do not synch files to the remote server,
   * because they have no associated config files.
   */
  function sync() {
    return null;
  }
Adrian Rossouw's avatar
Adrian Rossouw committed
318 319
}