t("Drupal sites")); } /** * Implentation of hook_provision_configure() * @TODO: PROPER profile support function provision_drupal_provision_configure() { $profiles = file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS'), 0, TRUE, 'name', 0); // Don't need to choose profile if only one available. if (sizeof($profiles) == 1) { $profile = array_pop($profiles); $form['default_profile'] = array('#type' => 'value', '#value' => $profile->name); } elseif (sizeof($profiles) > 1) { foreach ($profiles as $profile) { if ($_POST['profile'] == $profile->name) { $options[$profile->name] = $profile->name; } } $form['provision_default_profile'] = array( '#type' => 'radios', '#title' => t('Default install profile'), '#description' => t('New sites will be created with the following install profile'), '#options' => $options, '#default_value' => variable_get('provision_default_profile', 'default'), ); } return $form; } //*/ /** * Implementation of hook_provision_templates */ function provision_drupal_provision_templates() { // settings template } /** * @} End "ingroup provisionui" */ /** * 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"); } function _provision_drupal_site_installed($url) { if (_provision_drupal_site_exists($url)) { if ($data = provision_load_site_data($url)) { return isset($data['site_installed']) ? $data['site_installed'] : FALSE; } } return false; } /** * Implentation of hook_provision_backup() */ function provision_drupal_provision_backup($url, $data) { // Adds the site directory into the backup file provision_log("backup", "Adding sites directory to $data[backup_file].gz"); $result = provision_shell_exec("cd %s; tar -rf %s * ", "sites/$url", $data['backup_file']); if (!$result) { provision_log("error", "Could not back up sites directory for drupal"); provision_set_error(PROVISION_FRAMEWORK_ERROR); } } /** * The default template to use while generating config files. * * @return * The default template for the config file */ function _provision_drupal_default_template() { return file_get_contents(drupal_get_path('module', 'provision_drupal') . '/provision_drupal_settings.tpl.php'); } /** * 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. */ function _provision_drupal_create_settings_file($url, &$data) { provision_log('notice', t("Generate settings.php file")); if (provision_path("exists", "sites/$url/settings.php")) { provision_path("chmod", "sites/$url/settings.php", 0750, t('Changed permissions of settings.php to @confirm'), t('Could not change permissions of settings.php to @confirm')); } $fp = fopen("sites/$url/settings.php", "w"); $text = variable_get('provision_drupal_settings_template', _provision_drupal_default_template()); fwrite($fp, " 0750, "sites/$url/files" => 02750, "sites/$url/files/tmp" => 02770, "sites/$url/files/images" => 02770, "sites/$url/files/pictures" => 02770, "sites/$url/themes" => 02750, "sites/$url/modules" => 02750, ); foreach ($paths as $path => $perm) { if (!is_dir($path)) { provision_path("mkdir", $path, true, t("Created @path"), t("Could not create @path"), PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); } provision_path("chown", $path, PROVISION_SCRIPT_USER, t("Changed ownership of @path"), t("Could not change ownership @path"), PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); provision_path("chgrp", $path, PROVISION_WEB_GROUP, t("Changed group ownership of @path"), t("Could not change group ownership @path")); provision_path("chmod", $path, $perm, t("Changed permissions of @path to @confirm"), t("Could not change permissions @path to @confirm"), PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); } } /** * Switch the active database to the newly created database * * This function tricks Drupal into thinking that it's running on an uninstalled site, * so that it can cleanly install the database schema. It also handles switching back to the * main provisioning site. */ function _provision_drupal_switch_active_site($url = null) { static $backups; if ($url) { /* Pretend to be the site being installed */ // Fake the necessary HTTP headers that Drupal needs: $drupal_base_url = parse_url($url); $_SERVER['HTTP_HOST'] = $drupal_base_url['host']; $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php'; $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF']; $_SERVER['REMOTE_ADDR'] = NULL; $_SERVER['REQUEST_METHOD'] = NULL; /** * This code is sourced from bootstrap.inc. I am trying to avoid patching core, but it might * be smarter to make a small patch to allow core to re-initialize itself more easily */ // Export the following settings.php variables to the global namespace global $base_url, $base_path, $base_root; global $cookie_domain, $conf, $profile, $profile, $db_prefix; # This is just for backup, to be able to restore to the old DRUSH system. $backups = compact("active_db", "base_url", "base_path", "db_prefix", "cookie_domain", "conf", "profile"); include_once $_SERVER['DOCUMENT_ROOT'] .'sites/' . $url . '/settings.php'; // Create base URL $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; $base_url = $base_root .= '://'. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']); if ($dir = trim(dirname($_SERVER['SCRIPT_NAME']), '\,/')) { $base_path = "/$dir"; $base_url .= $base_path; $base_path .= '/'; } else { $base_path = '/'; } provision_set_active_db($db_url); } else { /** * Restore everything to the way it was before we switched sites. */ // Fake the necessary HTTP headers that Drupal needs: $drupal_base_url = parse_url(DRUSH_URI); $_SERVER['HTTP_HOST'] = $drupal_base_url['host']; $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php'; $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF']; $_SERVER['REMOTE_ADDR'] = NULL; $_SERVER['REQUEST_METHOD'] = NULL; global $base_url, $base_path, $base_root; // Export the following settings.php variables to the global namespace global $db_prefix, $cookie_domain, $conf, $profile; # This is just for backup, to be able to restore to the old DRUSH system. extract($backups, EXTR_OVERWRITE); provision_set_active_db(); } } function provision_drupal_provision_post_restore($url, $data) { _provision_drupal_create_settings_file($url, $data); } function provision_drupal_provision_restore($url, $data) { $old = PROVISION_SITES_PATH . "/$url.restore"; $new = PROVISION_SITES_PATH . "/$url"; provision_path("switch_paths", $old, $new , t('Swapping out the @path and @confirm directories was successful.'), t('Swapping the @path and @confirm directories has failed.'), PROVISION_PERM_ERROR); // make sure it has the latest site data available provision_save_site_data($url, $data); } // Luckily this is reversable =) function provision_drupal_provision_restore_rollback($url, $data) { provision_drupal_provision_restore($url, $data); } /** * Force drupal to load the modules it expects to find on an uninstalled site */ function _provision_drupal_force_load_modules($url = null) { static $backup_list; if ($url) { $backup_list = module_list(); require_once './modules/system/system.install'; require_once './includes/file.inc'; require_once './includes/install.inc'; // Load module basics (needed for hook invokes). include_once './includes/module.inc'; $module_list['system']['filename'] = 'modules/system/system.module'; $module_list['filter']['filename'] = 'modules/filter/filter.module'; module_list(TRUE, FALSE, FALSE, $module_list); drupal_load('module', 'system'); drupal_load('module', 'filter'); #should i load all the other modules? i don't know .=\ } else { module_list(TRUE, FALSE, FALSE, $backup_list); } } /** * Install the drupal schema and install profile */ function _provision_drupal_install_schema($profile, $language = 'en') { include_once('includes/locale.inc'); $GLOBALS['profile'] = $profile; $GLOBALS['install_locale'] = $language; provision_log("install", t("Installing Drupal schema")); // Load the profile. require_once "./profiles/$profile/$profile.profile"; $requirements = drupal_check_profile($profile); $severity = drupal_requirements_severity($requirements); // If there are issues, report them. if ($severity == REQUIREMENT_ERROR) { foreach ($requirements as $requirement) { if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { drupal_set_message($requirement['description'] .' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')', 'error'); } } return false; } // Verify existence of all required modules. $modules = drupal_verify_profile($profile, $language); if (!$modules) { provision_set_error(PROVISION_FRAMEWORK_ERROR); return false; } // Perform actual installation defined in the profile. drupal_install_profile($profile, $modules); // Show profile finalization info. $function = $profile .'_profile_final'; if (function_exists($function)) { // More steps required $profile_message = $function(); } } /** * implementation of provision_verify */ function provision_drupal_provision_verify($url, &$data) { provision_path("writable", "sites", true, t("Drupal sites directory is writable by the provisioning script"), t("Drupal sites directory is not writable by the provisioning script"), PROVISION_PERM_ERROR); $exists = _provision_create_dir(PROVISION_DRUSHRC_PATH, t('Drush configuration path'), 0700); $data['modules'] = _provision_drupal_get_cvs_versions(module_rebuild_cache()); // Find theme engines $data['engines'] = drupal_system_listing('\.engine$', 'themes/engines'); $data['profiles'] = _provision_find_profiles(); $data['themes'] = system_theme_data(); $sites = provision_drupal_find_sites(); $data['sites'] = array_keys($sites); // return list of hosted sites. used to determine whether or not to import. } /** * Find available profiles on this platform. */ function _provision_find_profiles() { include_once('includes/install.inc'); $profiles = file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS', '.svn'), 0, TRUE, 'name', 0); foreach ($profiles as $key => $profile) { require_once($profile->filename); $func = $profile->name . "_profile_details"; if (function_exists($func)) { $profile->info = $func(); } // Find languages available $languages = array_keys(file_scan_directory('./profiles/' . $key, '\.po$', array('.', '..', 'CVS'), 0, FALSE, 'name')); array_unshift($languages, 'en'); $profile->info['languages'] = $languages; $return[$key] = $profile; } return $return; } /** * Remove any directories for the site in sites * This can't be rolled back. so won't even try. */ function provision_drupal_provision_delete($url, $data) { return _provision_recursive_delete("sites/$url"); } function provision_drupal_find_sites() { $sitephp = file_scan_directory('./sites', 'settings\.php$', array('.', '..', 'CVS', '.svn'), 0, TRUE, 'filename', 0); foreach ($sitephp as $file => $info) { $path = explode("/", $file); array_pop($path); $sites[array_pop($path)] = $file; } return $sites; } function _provision_drupal_get_cvs_versions($files) { foreach ($files as $modulename => $file) { $project = array(); $project['filename'] = $file->filename; $project['name'] = $file->name; 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; $files[$name] = $file; } return $files; } function provision_drupal_provision_import($url, &$data) { $sites = provision_drupal_find_sites(); foreach ($sites as $site => $file) { if ($site != 'default') { $info = _provision_drupal_import_site($site); if ($info['site_installed']) { provision_log("notice", "Returning information for $site"); $data['sites'][$site] = $info; } } } //Just make sure our ini settings and the like aren't wiped out. include(conf_path() . "/settings.php"); } function _provision_drupal_import_site($url) { if (!($data = provision_get_site_data($url))) { $data = array(); // initialize site data to empty array } include("sites/$url/settings.php"); if ($parts = @parse_url($db_url)) { $data['site_db_type'] = $parts['scheme']; $data['site_db_user'] = $parts['user']; $data['site_db_host'] = $parts['host']; $data['site_db_passwd'] = $parts['pass']; $data['site_db_name'] = substr($parts['path'], 1); /** * We need to be running AS the site to be able to see what profile it is installed with. * * This information is no longer stored in settings.php */ _provision_drupal_switch_active_site($url); $data['site_profile'] = variable_get('install_profile', 'default'); _provision_drupal_switch_active_site(); $data['site_installed'] = TRUE; } provision_save_site_data($url, $data); return $data; }