provision_drupal.drush.inc 12.4 KB
Newer Older
1
<?php
2
// $Id$
3 4 5 6 7 8 9 10
/**
 * @file
 * Drupal specific functions for the provisioning framework.
 *
 * This module is responsible for the creation and maintenance of the drupal settings.php file, the sites directory structure
 * and all the install api code. 
 */

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
define('PROVISION_BACKUP_PATH_NOT_FOUND', 'PROVISION_BACKUP_PATH_NOT_FOUND');
define('PROVISION_BACKUP_FAILED', 'PROVISION_BACKUP_FAILED');
define('PROVISION_DRUPAL_INSTALL_FAILED', 'PROVISION_DRUPAL_INSTALL_FAILED');
define('PROVISION_DRUPAL_UPDATE_FAILED', 'PROVISION_DRUPAL_UPDATE_FAILED');
define('PROVISION_DRUPAL_INSTALL_MISSING_REQUIREMENTS', 'PROVISION_DRUPAL_INSTALL_MISSING_REQUIREMENTS');
define('PROVISION_DRUPAL_SITE_INSTALLED', 'PROVISION_DRUPAL_SITE_INSTALLED');
define('PROVISION_DRUPAL_SITE_NOT_FOUND', 'PROVISION_DRUPAL_SITE_NOT_FOUND');
define('PROVISION_CONFIG_NOT_VALID', 'PROVISION_CONFIG_NOT_VALID');
define('PROVISION_REQUIRES_URL', 'PROVISION_REQUIRES_URL');

function provision_drupal_drush_help($section) {
  switch ($section) {
    case 'error:PROVISION_CONFIG_NOT_VALID' : 
      return dt('Config file could not be loaded.');
    case 'error:PROVISION_DRUPAL_SITE_INSTALLED' : 
      return dt('Site has already been installed.');
    case 'error:PROVISION_DRUPAL_SITE_NOT_FOUND' : 
      return dt('Site was not found.');
    case 'error:PROVISION_DRUPAL_INSTALL_FAILED' : 
      return dt('Could not complete Drupal installation.');
    case 'error:PROVISION_DRUPAL_UPDATE_FAILED' : 
      return dt('Could not complete Drupal update.');
    case 'error:PROVISION_BACKUP_PATH_NOT_FOUND' :
      return dt("Backup directory does not exist.");
    case 'error:PROVISION_DRUPAL_INSTALL_MISSING_REQUIREMENTS' :
      return dt("Could not meet the requirements for installing the drupal profile");
    case 'error:PROVISION_REQUIRES_URL' : 
      return dt('You need to specify the URL argument for this command');
  }

}

43 44 45 46 47 48
/**
 * Initialize the platform / site
 *
 * This function is executed by provision_invoke, and is responsible
 * for populating the $data context array
 */
49
function provision_drupal_provision_init($url = NULL) {
50

51
  if ($url) {
52 53 54 55 56 57
    drush_set_option('uri' , 'http://' . $url);
    provision_load_site_data($url);
    drush_set_default('site_url', $url);
    drush_set_default('profile', 'default');
    drush_set_default('language', 'en');
    drush_set_default('aliases', array());
58
  }
59

60 61 62 63 64 65 66 67 68 69 70
  define('PROVISION_CONTEXT_SITE', ($url) ? TRUE : FALSE);
  define('PROVISION_CONTEXT_PLATFORM', !PROVISION_CONTEXT_SITE);
}

/**
 * Finalize the platform / site
 *
 * This will run only if there were no errors in any of the previous hooks,
 * and will allow us to cache the successful settings to the site.php/ drushrc.php
 * files for future runs.
 */
71
function provision_drupal_provision_finalize($url = NULL) {
72

73
  if (PROVISION_CONTEXT_SITE) {
74 75
    if (drush_get_option('installed')) {
      drush_set_option('site_url', drush_get_option('site_url'), 'site');
76
      drush_set_option('site_id', drush_get_option('site_id'), 'site');
77
      provision_save_site_data($url);
Adrian Rossouw's avatar
Adrian Rossouw committed
78
    }
79 80 81 82 83 84 85 86 87 88 89 90
  }
  else {
    _provision_generate_config();
  }
}

/**
 * Some commands need to have a url to operate on.
 *  This prints out a message to that effect.
 */
function _provision_drupal_url_required() {
  if (PROVISION_CONTEXT_PLATFORM) {
91
    drush_set_error(PROVISION_REQUIRES_URL);
92 93 94 95 96 97 98 99 100 101
  }
}

/**
 * Validate a site exists, ie: has a settings.php file
 *
 * This will return an error for sites that haven't been created yet
 */
function _provision_drupal_valid_site() {
  if (PROVISION_CONTEXT_SITE) {
102
    if (!_provision_drupal_site_exists(drush_get_option('site_url'))) {
103
      drush_set_error(PROVISION_DRUPAL_SITE_NOT_FOUND);
104 105
    }
  }
106 107
}

108 109 110 111 112 113 114 115 116 117 118 119
/**
 * Test to see if the site settings.php exists
 *
 * @param url
 *   The url of the site to check
 * @return
 *   If the file exists, return TRUE, else return FALSE.
 */
function _provision_drupal_site_exists($url) {
  return file_exists("sites/$url/settings.php");
}

120 121 122 123 124 125 126 127

/**
 * Validate a site has been installed, by checking it's site.php file. 
 *
 * This will return an error for sites that haven't been installed yet
 */
function _provision_drupal_valid_installed_site() {
  if (PROVISION_CONTEXT_SITE) {
128
    if (!_provision_drupal_site_installed(drush_get_option('site_url'))) {
129
      drush_set_error(PROVISION_DRUPAL_SITE_NOT_FOUND);
130 131 132 133 134 135
    }
  }
}

function _provision_drupal_valid_not_installed_site() {
  if (PROVISION_CONTEXT_SITE) {
136
    if (_provision_drupal_site_installed(drush_get_option('site_url'))) {
137
      drush_set_error(PROVISION_DRUPAL_SITE_INSTALLED);
Adrian Rossouw's avatar
Adrian Rossouw committed
138 139 140
    }
  }
}
141 142

/**
143
 * Test to see if the site has a site.php and has it set to 'installed'
144
 */
145 146
function _provision_drupal_site_installed($url) {
  if (_provision_drupal_site_exists($url)) {
147 148
    provision_load_site_data($url);
    return drush_get_option('installed');
149
  }
150
  return FALSE;
151 152
}

153 154 155 156 157 158 159
/**
 * The default template to use while generating config files.
 *
 * @return
 *   The default template for the config file
 */
function _provision_drupal_default_template() {
160
  return file_get_contents(dirname(__FILE__) .'/provision_drupal_settings.tpl.php');
161 162 163 164 165 166 167 168 169 170 171
}

/**
 * Generate a settings file for the site.
 *
 * @param url
 *   The url of the site being invoked.
 * @param data
 *   A reference to the associated array containing the data for the site. This needs to be a reference, 
 *   because the modules might provide additional information about the site.
 */
172 173 174 175 176 177 178 179 180 181
function _provision_drupal_create_settings_file($url = NULL) {
  $options = drush_get_merged_options();

  $options['extra_config'] = "# Extra configuration from modules:\n";
  foreach (drush_command_implements('provision_drupal_config') as $module) {
    $options['extra_config'] .= "# -- $module settings --\n";
    $options['extra_config'] .= module_invoke($module, 'provision_drupal_config', $url) . "\n";
  }


182
  drush_log(dt("Generate settings.php file"));
183
  if (provision_path("exists", "sites/$url/settings.php")) {
184
    provision_path("chmod", "sites/$url/settings.php", 0640,
185 186
      dt('Changed permissions of settings.php to @confirm'),
      dt('Could not change permissions of settings.php to @confirm'));
187 188
  }

189
  $fp = fopen("sites/$url/settings.php", "w");
190
  $text =  _provision_drupal_default_template();
191
  fwrite($fp, "<?php\n". provision_render_config($text, $options));
192
  fclose($fp);
193

194
  # Change the permissions of the file
195
  provision_path("chmod", "sites/$url/settings.php", 0440,
196 197
    dt('Changed permissions of settings.php to @confirm'),
    dt('Could not change permissions of settings.php to @confirm'));
198 199

  provision_path("chgrp", "sites/$url/settings.php", drush_get_option('web_group'),
200 201
    dt('Change group ownership of settings.php to @confirm'),
    dt('Could not change group ownership of settings.php to @confirm'));
202 203 204 205 206 207 208
}

/**
 * Create the directories needed to host a drupal site
 * 
 * Also maintains permissions on existing directories.
 */
209
function _provision_drupal_create_directories($url, $profile = NULL) {  
210
  $paths = array(
211
    "sites/$url"                 => 0755,
212
    "sites/$url/files"           => 02770,
213 214 215
    "sites/$url/files/tmp"       => 02770,
    "sites/$url/files/images"    => 02770,
    "sites/$url/files/pictures"  => 02770,
216 217 218 219 220 221 222 223
    "sites/$url/themes"          => 0755,
    "sites/$url/modules"         => 0755,  
  );
  $grps = array(
    "sites/$url/files",
    "sites/$url/files/tmp",
    "sites/$url/files/images",
    "sites/$url/files/pictures",
224 225 226 227
  );

  foreach ($paths as $path => $perm) {
    if (!is_dir($path)) {
228
      provision_path("mkdir", $path, TRUE, 
229 230
        dt("Created <code>@path</code>"),
        dt("Could not create <code>@path</code>"),
231
        DRUSH_PERM_ERROR);
232
    }
233 234

    provision_path("chmod", $path, $perm, 
235 236
      dt("Changed permissions of <code>@path</code> to @confirm"),
      dt("Could not change permissions <code>@path</code> to @confirm"),
237
      DRUSH_PERM_ERROR);
238 239
  }
  foreach ($grps as $path) {
240
      provision_path("chown", $path, drush_get_option('script_user'), 
241 242
      dt("Changed ownership of <code>@path</code>"),
      dt("Could not change ownership <code>@path</code>"),
243
      DRUSH_PERM_ERROR );
244
    provision_path("chgrp", $path, drush_get_option('web_group'),
245 246
      dt("Changed group ownership of <code>@path</code>"),
      dt("Could not change group ownership <code>@path</code>"));
247 248 249
  }
}

250 251 252
/**
 * Runs an external script to reload all the various drupal caches
 */
253
function _provision_drupal_rebuild_caches($url = NULL) {
254
  if (PROVISION_CONTEXT_SITE) {
255 256
    #drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_FULL);

257
    provision_platform_include(dirname(__FILE__), 'clear');
258
  }
Adrian Rossouw's avatar
Adrian Rossouw committed
259 260
}

261

262 263 264 265 266 267
/**
 * Find available profiles on this platform.
 */
function _provision_find_profiles() {
  include_once('includes/install.inc');

268
  if (!$dir = opendir("./profiles")) {
269
    drush_log(dt("Cannot find profiles directory"), 'error');
270 271 272
    return FALSE;
  }
  while (FALSE !== ($name = readdir($dir))) {
273
    $languages = array();
274 275 276 277 278 279 280 281
    $file = "./profiles/$name/$name.profile";
    if ($name == '..' || $name == '.' || !file_exists($file)) {
      continue;
    }
    $profile = new stdClass();
    $profile->name = $name;
    $profile->filename = $file;

282 283 284 285 286
    require_once($profile->filename);
    $func = $profile->name . "_profile_details";
    if (function_exists($func)) {
      $profile->info =  $func();
    }
287

288
    $languages['en'] = 1;
289
    // Find languages available
290
    $files = array_keys(drush_scan_directory('./profiles/' . $name . '/translations', '\.po$', array('.', '..', 'CVS'), 0, FALSE, 'filepath'));
Adrian Rossouw's avatar
Adrian Rossouw committed
291
    $files = array_merge($files, array_keys(drush_scan_directory('./profiles/' . $name , '\.po$', array('.', '..', 'CVS'), 0, FALSE, 'filepath')));
292 293 294 295 296
    if (is_array($files)) {
      foreach ($files as $file) {
        if (preg_match('!(/|\.)([^\./]+)\.po$!', $file, $langcode)) {
          $languages[$langcode[2]] = 1; // use the language name as an index to weed out duplicates
        }
297 298
      }
    }
Adrian Rossouw's avatar
Adrian Rossouw committed
299
    $profile->info['languages'] = array_keys($languages);
anarcat's avatar
anarcat committed
300
    $return[$name] = $profile;
301
    drush_log(dt('found install profile %name', array('%name' => $name)));
302
  }
303

304 305 306 307
  return $return;

}

308
function provision_drupal_find_sites() {
309 310 311
  if ($dir = opendir("./sites")) {
    while (FALSE !== ($subdir = readdir($dir))) {
      $file = "./sites/$subdir/settings.php";
312
      if (file_exists("$file") && ($subdir != 'default') && !is_link("./sites/$subdir")) {
313 314 315
        $sites[$subdir] = $file;
      }
    }
316
    closedir($dir);
317
  } else {
318
    drush_log(dt("Cannot find sites directory"), 'error');
319
    $sites = FALSE;
320 321
  }
  return $sites;
322 323
}

Adrian Rossouw's avatar
Adrian Rossouw committed
324 325
function _provision_drupal_get_cvs_versions($files) {
  foreach ($files as $modulename => $file) {
326 327 328
      $project = array();
      $project['filename'] = $file->filename;
      $project['name'] = $file->name;
329
      $file->info['description'] = str_replace("\n", "", $file->info['description']);
330 331 332 333 334
      if (empty($project['project'])) {
        $project['project'] = cvs_deploy_get_project_name($project);
      }
      _cvs_deploy_version_alter($file->info['version'], $project);
      $name = ($project['project']) ? $project['project'] : $modulename;
Adrian Rossouw's avatar
Adrian Rossouw committed
335
      $files[$name] = $file; 
336
  }
337

Adrian Rossouw's avatar
Adrian Rossouw committed
338
  return $files;
339
}
340

341 342 343
/**
 * Create and remove symlinks for each of the possible domain aliases of an existing site
 */
344
function _provision_drupal_maintain_aliases($url) {
345
  if (PROVISION_CONTEXT_SITE) {
346 347 348 349 350 351
    $old_aliases = drush_get_option('aliases', array(), 'site');
    /**
     * First we remove all the old aliases
     */
    if (is_array($old_aliases)) {
      _provision_drupal_delete_aliases($old_aliases);
352
    }
353 354 355 356 357 358


    $aliases = drush_get_option('aliases');
    if (is_array($aliases)) {
      foreach($aliases as $alias) {
        provision_path("symlink", $url, drush_get_option('docroot_path') . "/sites/" . $alias, 
359 360
          dt("Created symlink for alias @alias", array("@alias" => $alias)), 
          dt("Could not create symlink for alias @alias", array("@alias" => $alias)));
361 362 363 364 365 366 367 368 369 370
      }
    }
  }
}

/**
 * Delete a list of aliases
 */
function _provision_drupal_delete_aliases($aliases) {
  foreach ($aliases as $alias) {
371
    provision_path("unlink", drush_get_option('docroot_path') . "/sites/" . $alias, TRUE,
372 373
          dt("Removed symlink for alias @alias", array("@alias" => $alias)), 
          dt("Could not remove symlink for alias @alias", array("@alias" => $alias)));
374 375
  }
}
376

377
function provision_drupal_install_log($ret) {
378 379 380 381 382 383 384 385
  if (sizeof($ret)) {
    foreach ($ret as $info) {
      if (is_array($info)) {
        if (!$info['success']) {
          drush_set_error(PROVISION_DRUPAL_INSTALL_FAILED, $msg);
        }
        drush_log($info['query'], ($info['success']) ? 'success' : 'error');
      }
386 387 388
    }
  }
}
389