provision.config.inc 7.74 KB
Newer Older
1 2 3 4 5 6 7 8 9
<?php

// $Id$

/**
 * Provision configuration generation classes.
 */

class provisionConfig {
drumm's avatar
drumm committed
10 11 12 13
  /**
   * Template file, a PHP file which will have access to $this and variables
   * as defined in $data.
   */
14
  public $template = null;
drumm's avatar
drumm committed
15 16 17 18

  /**
   * Associate array of variables to make available to the template.
   */
19
  public $data = array();
drumm's avatar
drumm committed
20 21

  /**
22
   * A provisionContext object thie configuration relates to.
drumm's avatar
drumm committed
23
   *
24
   * @var provisionContext
drumm's avatar
drumm committed
25
   */
26
  public $owner = null;
drumm's avatar
drumm committed
27 28 29 30

  /**
   * If set, replaces file name in log messages.
   */
31
  public $description = null;
drumm's avatar
drumm committed
32 33 34 35

  /**
   * Octal Unix mode for permissons of the created file.
   */
36
  protected $mode = NULL;
drumm's avatar
drumm committed
37 38 39 40

  /**
   * Unix group name for the created file.
   */
41
  protected $group = NULL;
42

drumm's avatar
drumm committed
43 44 45 46
  /**
   * Forward $this->... to $this->owner->...
   * object.
   */
47
  function __get($name) {
48 49
    if (isset($this->owner)) {
      return $this->owner->$name;
50 51
    }
  }
drumm's avatar
drumm committed
52 53 54 55 56

  /**
   * Constructor, overriding not recommended.
   *
   * @param $owner
57
   *   An alias name for d(), the provisionContext that this configuration
drumm's avatar
drumm committed
58 59 60 61 62
   *   is relevant to.
   * @param $data
   *   An associative array to potentiall manipulate in process() and make
   *   available as variables to the template.
   */
63
  function __construct($owner, $data = array()) {
64 65 66
    if (is_null($this->template)) {
      throw(exception);
    }
67

68
    $this->data = $this->parse();
69
    if (sizeof($data)) {
70
      $this->data = array_merge($this->data, $data);
71
    }
72 73 74

    // Accept both a reference and an alias name for the owner.
    $this->owner = is_object($owner) ? $owner : d($owner);
drumm's avatar
drumm committed
75 76
  }

77 78 79 80 81 82 83
  /**
   * Parse the existing config to load data
   *
   * This is called in the constructor, and should take care of
   * opening the file and parsing it into the data array.
   */
  function parse() {
84
    return array();
85 86
  }

87
  /**
drumm's avatar
drumm committed
88
   * Process and add to $data before writing the configuration.
89
   *
drumm's avatar
drumm committed
90
   * This is a stub to be implemented by subclasses.
91
   */
92 93 94 95
  function process() {
    return true;
  }

96
  /**
drumm's avatar
drumm committed
97
   * The filename where the configuration is written.
98
   * 
drumm's avatar
drumm committed
99
   * This is a stub to be implemented by subclasses.
100
   */
101 102 103 104
  function filename() {
    return false;
  }

drumm's avatar
drumm committed
105 106 107
  /**
   * Load template from filename().
   */
108 109 110 111 112 113 114 115 116 117 118 119 120 121
  private function load_template() {
    $reflect = new reflectionObject($this);
    $base_dir = dirname($reflect->getFilename());

    if (isset($this->template)) {
      $file = $base_dir . '/' . $this->template;
      drush_log("Template loaded: $file");
      if (file_exists($file) && is_readable($file)) {
        return file_get_contents($file);
      }
    }
    return false;
  }

drumm's avatar
drumm committed
122 123 124 125
  /**
   * Render template, making variables available from $variables associative
   * array.
   */
126 127 128 129 130 131 132 133 134 135 136
  private function render_template($template, $variables) {
    drush_errors_off();
    extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
    ob_start();                      // Start output buffering
    eval('?>'. $template);                 // Generate content
    $contents = ob_get_contents();   // Get the contents of the buffer
    ob_end_clean();                  // End buffering and discard
    drush_errors_on();
    return $contents;                // Return the contents
  }

drumm's avatar
drumm committed
137 138 139 140 141 142 143 144 145 146
  /**
   * Write out this configuration.
   *
   * 1. Make sure parent directory exists and is writable.
   * 2. Load template with load_template().
   * 3. Process $data with process().
   * 4. Make existing file writable if necessary and possible.
   * 5. Render template with $this and $data and write out to filename().
   * 6. If $mode and/or $group are set, apply them for the new file.
   */
147 148
  function write() {
    $filename = $this->filename();
drumm's avatar
drumm committed
149
    // Make directory structure if it does not exist.
150 151
    if (!provision_file()->exists(dirname($filename))->status()) {
      provision_file()->mkdir(dirname($filename))
drumm's avatar
drumm committed
152 153 154 155
        ->succeed('Created directory @path.')
        ->fail('Could not create directory @path.');
    }

156 157 158 159 160
    if ($filename && is_writeable(dirname($filename))) {
      // manipulate data before passing to template.
      $this->process();

      if ($template = $this->load_template()) {
161
        // Make sure we can write to the file
162 163
        if (!is_null($this->mode) && !($this->mode & 0200) && provision_file()->exists($filename)->status()) {
          provision_file()->chmod($filename, $this->mode | 0200)
164 165 166 167
            ->succeed('Changed permissions of @path to @perm')
            ->fail('Could not change permissions of @path to @perm');
        }

drumm's avatar
drumm committed
168
        provision_file()->file_put_contents($filename, $this->render_template($template, $this->data))
169 170 171 172
          ->succeed('Generated config ' . (empty($this->description) ? $filename : $this->description), 'success');

        // Change the permissions of the file if needed
        if (!is_null($this->mode)) {
173
          provision_file()->chmod($filename, $this->mode)
174 175 176 177
            ->succeed('Changed permissions of @path to @perm')
            ->fail('Could not change permissions of @path to @perm');
        }
        if (!is_null($this->group)) {
178
          provision_file()->chgrp($filename, $this->group)
179 180
            ->succeed('Change group ownership of @path to @gid')
            ->fail('Could not change group ownership of @path to @gid');
181 182 183 184 185
        }
      }
    }
  }

drumm's avatar
drumm committed
186 187 188
  /**
   * Remove configuration file as specified by filename().
   */
189
  function unlink() {
190
    provision_file()->unlink($this->filename())->status();
191 192
  }
}
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

/**
 * Specialized class to handle the creation of drushrc.php files.
 *
 * This is based on the drush_save_config code, but has been abstracted
 * for our purposes.
 */ 
class provisionConfig_drushrc extends provisionConfig {
  public $template = 'provision_drushrc.tpl.php';
  public $description = 'Drush configuration file';
  protected $mode = 0400;
  protected $context_name = 'drush';

  function filename() {
    return _drush_config_file($this->context_name);
  }

210 211
  function __construct($owner, $data = array()) {
    parent::__construct($owner, $data);
212 213
    $this->load_data();
  }
214

215
  function load_data() {
216 217 218 219 220 221 222 223 224 225 226
    // we fetch the context to pass into the template based on the context name
    $this->data = array_merge(drush_get_context($this->context_name), $this->data);
  }

  function process() {
    unset($this->data['context-path']);
    unset($this->data['config-file']);
    $this->data['option_keys'] = array_keys($this->data);
  }
}

227 228 229
/**
 * Class to write an alias records.
 */
230
class provisionConfig_drushrc_alias extends provisionConfig_drushrc {
drumm's avatar
drumm committed
231 232
  public $template = 'provision_drushrc_alias.tpl.php';

233
  /**
drumm's avatar
drumm committed
234 235 236 237
   * @param $name
   *   String '\@name' for named context.
   * @param $options
   *   Array of string option names to save.
238
   */
239 240
  function __construct($owner, $data = array()) {
    parent::__construct($owner, $data);
drumm's avatar
drumm committed
241
    $this->data = array(
242
      'aliasname' => ltrim($owner, '@'),
243
      'options' => $data,
drumm's avatar
drumm committed
244
    );
245 246 247
  }

  function filename() {
drumm's avatar
drumm committed
248
    return drush_server_home() . '/.drush/' . $this->data['aliasname'] . '.alias.drushrc.php'; 
249 250 251
  }
}

252 253 254 255 256 257 258 259
/**
 * Server level config for drushrc.php files.
 */
class provisionConfig_drushrc_server extends provisionConfig_drushrc {
  protected $context_name = 'user';
  public $description = 'Server drush configuration';
}

260 261 262 263 264 265
/**
 * Class for writing $platform/drushrc.php files.
 */
class provisionConfig_drushrc_platform extends provisionConfig_drushrc {
  protected $context_name = 'drupal';
  public $description = 'Platform Drush configuration file';
266 267 268 269

  function filename() {
    return $this->root . '/drushrc.php';
  }
270 271 272 273 274 275 276 277 278
}

/**
 * Class for writing $platform/sites/$url/drushrc.php files.
 */
class provisionConfig_drushrc_site extends provisionConfig_drushrc {
  protected $context_name = 'site';
  public $template = 'provision_drushrc_site.tpl.php';
  public $description = 'Site Drush configuration file';
279 280 281 282

  function filename() {
    return $this->site_path . '/drushrc.php';
  }
283 284
}