write();
}
class provisionConfig_drupal_settings extends provisionConfig {
public $template = 'provision_drupal_settings.tpl.php';
public $description = 'Drupal settings.php file';
protected $mode = 0440;
function filename() {
return $this->data['sites_path'] . '/' . $this->data['site_url'] . '/settings.php';
}
function process() {
if (drush_drupal_major_version() >= 7) {
$this->data['db_type'] = ($this->data['db_type'] == 'mysqli') ? 'mysql' : $this->data['db_type'];
}
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_drupal_config', $this->data['site_url'], $this->data));
$this->group = drush_get_option('web_group');
}
}
/**
* Create the directories needed to host a drupal site
*
* Also maintains permissions on existing directories.
*/
function _provision_drupal_create_directories($url, $profile = NULL) {
# those directories will be created and their modes changed
$mkdir = array(
"sites/$url" => 0755,
# those should be writable by the aegir primary group to ease development
"sites/$url/themes" => 02775,
"sites/$url/modules" => 02775,
"sites/$url/libraries" => 02775, # http://drupal.org/node/496240
// d7 support
"sites/$url/private" => 0755,
"sites/$url/private/files" => 02770,
"sites/$url/private/temp" => 02770,
);
$chown = array();
$chgrp = array();
// special case: platform. do not handle files dir
if ($url != 'all') {
$mkdir["sites/$url/files"] = 02770;
$mkdir["sites/$url/files/tmp"] = 02770;
$mkdir["sites/$url/files/images"] = 02770;
$mkdir["sites/$url/files/pictures"] = 02770;
# the owner/group of those directories will be changed recursively
$chown["sites/$url/files"] = drush_get_option('script_user');
$chgrp["sites/$url/files"] = drush_get_option('web_group');
$chown["sites/$url/private"] = drush_get_option('script_user');
$chgrp["sites/$url/private/files"] = drush_get_option('web_group');
$chgrp["sites/$url/private/temp"] = drush_get_option('web_group');
}
foreach ($mkdir as $path => $perm) {
if (!is_dir($path)) {
provision_service('file')->mkdir($path)
->succeed('Created @path
')
->fail('Could not create @path
', 'DRUSH_PERM_ERROR');
}
provision_service('file')->chmod($path, $perm, TRUE)
->succeed('Changed permissions of @path
to @perm')
->fail('Could not change permissions @path
to @perm');
}
foreach ($chown as $path => $owner) {
provision_service('file')->chown($path, $owner, TRUE)
->succeed('Changed ownership of @path
to @uid')
->fail('Could not change ownership @path
', 'DRUSH_PERM_ERROR');
}
foreach ($chgrp as $path => $group) {
provision_service('file')->chgrp($path, $group, TRUE)
->succeed('Changed group ownership of @path
to @gid')
->fail('Could not change group ownership @path
');
}
}
/**
* Runs an external script to reload all the various drupal caches
*/
function _provision_drupal_rebuild_caches($url = NULL) {
if (PROVISION_CONTEXT_SITE) {
drush_include_engine('drupal', 'clear');
}
}
/**
* Find available profiles on this platform.
*/
function _provision_find_profiles() {
include_once('includes/install.inc');
if (!$dir = opendir("./profiles")) {
drush_log(dt("Cannot find profiles directory"), 'error');
return FALSE;
}
while (FALSE !== ($name = readdir($dir))) {
$languages = array();
$file = "./profiles/$name/$name.profile";
if ($name == '..' || $name == '.' || !file_exists($file)) {
continue;
}
$profile = new stdClass();
$profile->name = $name;
$profile->filename = $file;
_provision_cvs_deploy($profile);
require_once($profile->filename);
$func = $profile->name . "_profile_details";
if (function_exists($func)) {
$profile->info = $func();
}
$languages['en'] = 1;
// Find languages available
$files = array_keys(drush_scan_directory('./profiles/' . $name . '/translations', '/\.po$/', array('.', '..', 'CVS'), 0, FALSE, 'filepath'));
$files = array_merge($files, array_keys(drush_scan_directory('./profiles/' . $name , '/\.po$/', array('.', '..', 'CVS'), 0, FALSE, 'filepath')));
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
}
}
}
$profile->info['languages'] = array_keys($languages);
// Drupal 7 renamed the default install profile to 'standard'
// Aegir now allows projects to specify an "old short name" to provide an upgrade path when projects get renamed.
if ($profile->name == 'standard') {
$profile->info['old_short_name'] = 'default';
}
$return[$name] = $profile;
drush_log(dt('Found install profile %name', array('%name' => $name)));
}
return $return;
}
function provision_drupal_find_sites() {
if ($dir = opendir("./sites")) {
while (FALSE !== ($subdir = readdir($dir))) {
// skip internal directory pointers
if ($subdir != '.' && $subdir != '..') {
$file = "./sites/$subdir/settings.php";
if (file_exists("$file") && ($subdir != 'default') && !is_link("./sites/$subdir")) {
$sites[$subdir] = $file;
}
}
}
closedir($dir);
} else {
drush_log(dt("Cannot find sites directory"), 'error');
$sites = FALSE;
}
return $sites;
}
function _provision_drupal_get_cvs_versions($files) {
foreach ($files as $modulename => $file) {
$project = array();
$project['filename'] = $file->filename;
$project['name'] = $file->name;
$file->info['description'] = str_replace("\n", "", $file->info['description']);
if (!isset($project['project'])) {
$project['project'] = cvs_deploy_get_project_name($project);
}
_cvs_deploy_version_alter($file->info['version'], $project);
$name = !empty($project['project']) ? $project['project'] : $modulename;
$files[$name] = $file;
}
return $files;
}
/**
* Create and remove symlinks for each of the possible domain aliases of an existing site
*/
function _provision_drupal_maintain_aliases($url) {
if (PROVISION_CONTEXT_SITE) {
// First we delete all the old aliases
drush_set_option('aliases', drush_get_option('aliases'), 'site');
_provision_drupal_delete_aliases(drush_get_option('aliases', array(), 'site'), false);
if (!drush_get_option('redirection')) {
$aliases = drush_get_option('aliases');
if (!is_array($aliases)) {
$aliases = explode(",", $aliases);
}
foreach($aliases as $alias) {
if (trim($alias)) {
provision_service('file')->symlink($url, drush_get_option('docroot_path') . '/sites/' . $alias)
->succeed('Created symlink for alias @target')
->fail('Could not create symlink for alias @target');
}
}
}
}
}
/**
* Delete a list of aliases
*/
function _provision_drupal_delete_aliases($aliases, $silent = false) {
if (!is_array($aliases)) {
$aliases = explode(",", $aliases);
}
if ($silent) {
$error = NULL;
}
else {
$error = 'Could not remove symlink for alias @path';
}
foreach ($aliases as $alias) {
if ($alias = trim($alias)) {
provision_service('file')->unlink(drush_get_option('docroot_path') . '/sites/' . $alias)
->succeed('Removed symlink for alias @path')
->fail($error);
}
}
}
require_once('cvs_deploy.inc');
function provision_find_packages() {
// Load the version specific include files.
drush_include_engine('drupal', 'packages', drush_drupal_major_version());
$packages['base'] = _provision_find_packages('base');
// Create a package for the Drupal release
$packages['base']['platforms'] = _provision_find_platforms();
// Find install profiles.
$profiles = _provision_find_profiles();
drush_set_option('profiles', array_keys((array) $profiles), 'drupal');
// Iterate through the install profiles, finding the profile specific packages
foreach ($profiles as $profile => $info) {
_provision_cvs_deploy($info);
if (!$info->version) {
$info->version = drush_drupal_version();
}
$packages['base']['profiles'][$profile] = $info;
$packages['profiles'][$profile] = _provision_find_packages('profiles', $profile);
}
return $packages;
}
function _provision_find_platforms() {
return array(
'drupal' => array(
'short_name' => 'drupal', 'version' => drush_drupal_version(),
'description' => dt("This platform is running @short_name @version", array('@short_name' => 'Drupal', '@version' => VERSION))));
}
/**
* A small helper function to reduce code duplication
*/
function _provision_find_packages($scope, $key = '') {
$packages = array();
$scope_text = ($key) ? "$scope/$key" : $scope;
foreach (array('modules', 'themes') as $type) {
$packages[$type] = array();
$func = "_provision_drupal_find_$type";
$result = $func($scope, $key);
if (sizeof($result)) {
$packages[$type] = $result;
drush_log(dt("Found !count !type in !scope",
array('!count' => sizeof($result),
'!scope' => $scope_text, '!type' => $type)));
}
}
return $packages;
}
/**
* Map the system table to a packages multi-dimensional array component
*/
function provision_drupal_system_map() {
// Load the version specific include files.
drush_include_engine('drupal', 'packages');
$profiles = _provision_find_profiles();
foreach ($profiles as $profile => $info) {
_provision_cvs_deploy($info);
if (!$info->version) {
$info->version = drush_drupal_version();
}
$profiles[$profile] = $info;
}
$packages['platforms'] = _provision_find_platforms();
$profile = drush_get_option('profile');
$packages['profiles'][$profile] = $profiles[$profile];
$packages['profiles'][$profile]->status = 1;
foreach (_provision_system_query("module") as $module) {
$frags = explode("/", $module->filename);
// ignore site-specific modules
if ($frags[0] == 'sites' && $frags[1] != 'all') {
continue;
}
$info_file = sprintf("%s/%s.info", dirname($module->filename), $module->name);
$module->info = provision_parse_info_file($info_file);
_provision_cvs_deploy($module);
$module->filename = realpath($module->filename);
if ($module->schema_version == -1) {
$module->schema_version = 0;
}
$packages['modules'][$module->name] = $module;
}
drush_log(dt("Found !count modules", array('!count' => sizeof($packages['modules']))));
// XXX: mostly a copy-paste from above
foreach (_provision_system_query("theme") as $theme) {
$frags = explode("/", $theme->filename);
// ignore site-specific themes
if ($frags[0] == 'sites' && $frags[1] != 'all') {
continue;
}
$info_file = sprintf("%s/%s.info", dirname($theme->filename), $theme->name);
$theme->info = provision_parse_info_file($info_file);
_provision_cvs_deploy($theme);
$theme->filename = realpath($theme->filename);
if ($theme->schema_version == -1) {
$theme->schema_version = 0;
}
$packages['themes'][$theme->name] = $theme;
}
drush_log(dt("Found !count themes", array('!count' => sizeof($packages['themes']))));
return $packages;
}
/**
* Retrieve a list of paths to search in a certain scope
*/
function _provision_drupal_search_paths($scope, $key = '', $type = 'modules') {
$searchpaths = array();
$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
switch ($scope) {
case 'base' :
$searchpaths[] = sprintf("%s/%s", $drupal_root, $type);
$searchpaths[] = sprintf("%s/sites/all/%s", $drupal_root, $type);
break;
default :
if ($key) {
$searchpaths[] = sprintf("%s/%s/%s/%s", $drupal_root, $scope, $key, $type);
}
break;
}
return $searchpaths;
}
/**
* Find modules in a certain scope.
*
* This function is general enough that it works for all supported
* versions of Drupal.
*/
function _provision_drupal_find_modules($scope, $key = '') {
$paths = _provision_drupal_search_paths($scope, $key, 'modules');
$files = array();
foreach ($paths as $path) {
$files = array_merge($files, drush_scan_directory($path, "/\.module$/", array('.', '..', 'CVS', '.svn'), 0, true, 'name'));
}
foreach ($files as $name => $info) {
$install_file = sprintf("%s/%s.install", dirname($info->filename), $name);
$schema_version = 0;
if (file_exists($install_file)) {
$source = file_get_contents(trim($install_file));
$source = str_replace("\r\n", "\n", $source);
$source = str_replace("\r", "\n", $source);
$function_matches = array();
preg_match_all('!function\s*&?([a-zA-Z0-9_]+)_update_([0-9]+)\s*\(.*?\s*\{!', $source, $function_matches);
if (sizeof($function_matches[0])) {
$schema_version = max($function_matches[2]);
}
}
$info_file = sprintf("%s/%s.info", dirname($info->filename), $name);
$files[$name]->info = provision_parse_info_file($info_file);
$files[$name]->schema_version = $schema_version;
_provision_cvs_deploy($files[$name]);
}
return $files;
}
function provision_parse_info_file($filename) {
$info = array();
$defaults = array(
'dependencies' => array(),
'description' => '',
'version' => NULL,
'php' => DRUPAL_MINIMUM_PHP,
);
if (file_exists($filename)) {
$info = _provision_drupal_parse_info_file($filename);
}
// Merge in defaults and return
return $info + $defaults;
}
/**
* Set up the $_SERVER environment variable so that drupal can correctly parse the settings.php file.
* The real credentials are stored in the Apache vhost of the relevant site, to prevent leaking of
* sensitive data to site administrators with PHP access who might otherwise access such credentials
* potentially of other sites' settings.php in a multisite set-up.
*/
function provision_prepare_environment() {
$fields = array('db_type', 'db_host', 'db_user', 'db_passwd', 'db_name');
foreach ($fields as $key) {
$_SERVER[$key] = drush_get_option($key, null, 'site');
}
// As of Drupal 7 there is no more mysqli type
if (drush_drupal_major_version() >= 7) {
$_SERVER['db_type'] = ($_SERVER['db_type'] == 'mysqli') ? 'mysql' : $_SERVER['db_type'];
}
}