Commit 331ace95 authored by Adrian Rossouw's avatar Adrian Rossouw Committed by adrian

Provide a layer of conditional includes for specific Drupal versions. One...

Provide a layer of conditional includes for specific Drupal versions. One provision install can now drive Drupal 5, 6 and 7 platforms, without needing anything additional downloaded.
parent 779e38c2
......@@ -73,6 +73,5 @@ function provision_drupal_provision_deploy_rollback(&$data, $url) {
function provision_drupal_provision_post_deploy(&$data, $url) {
provision_invoke('update', $data, $url);
$cmd = sprintf("php %s/drupal_deploy.php %s %s", dirname(__FILE__), $url, $data['old_site_url']);
provision_exec($cmd, $data);
provision_platform_include(dirname(__FILE__), 'deploy');
}
<?php
if (is_array($GLOBALS['db_url'])) {
$db_url = $GLOBALS['db_url']['default'];
}
if ($parts = @parse_url($db_url)) {
$data['db_type'] = $parts['scheme'];
$data['db_user'] = $parts['user'];
$data['db_host'] = $parts['host'];
$data['db_passwd'] = $parts['pass'];
$data['db_name'] = substr($parts['path'], 1);
$data['profile'] = variable_get('install_profile', 'default');
$has_locale = db_result(db_query("SELECT status FROM {system} WHERE type='module' AND name='locale'"));
if ($has_locale) {
$locale = db_result(db_query("SELECT locale FROM {locales_meta} WHERE isdefault=1 AND enabled=1"));
}
$data['language'] = ($locale) ? ($locale) : 'en';
}
<?php
/**
* @file
* Rebuild all the caches
*/
$GLOBALS['url'] = $data['site_url'];
$GLOBALS['profile'] = $data['profile'];
$GLOBALS['install_locale'] = $data['language'];
$GLOBALS['client_email'] = $data['client_email'];
require_once 'includes/install.inc';
/**
* Verify if Drupal is installed.
*/
function install_verify_drupal() {
$result = @db_query("SELECT name FROM {system} WHERE name = 'system'");
return $result && db_result($result) == 'system';
}
/**
* Verify existing settings.php
*/
function install_verify_settings() {
global $db_prefix, $db_type, $db_url;
// Verify existing settings (if any).
if ($db_url != 'mysql://username:password@localhost/databasename') {
// We need this because we want to run form_get_errors.
$url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
$db_user = urldecode($url['user']);
$db_pass = urldecode($url['pass']);
$db_host = urldecode($url['host']);
$db_port = isset($url['port']) ? urldecode($url['port']) : '';
$db_path = ltrim(urldecode($url['path']), '/');
$settings_file = './'. conf_path() .'/settings.php';
return TRUE;
}
return FALSE;
}
function install_send_welcome_mail($url, $profile, $language, $client_email) {
// create the admin account or change some parameters if the install profile
// already created one
$account = user_load(array('uid' => 1));
if (!$account) {
$account = new stdClass();
}
$edit['name'] = 'admin';
$edit['pass'] = user_password();
$edit['mail'] = $client_email;
$edit['status'] = 1;
$account = user_save($account, $edit);
// Mail one time login URL and instructions.
$from = variable_get('site_mail', ini_get('sendmail_from'));
$onetime = user_pass_reset_url($account);
$variables = array(
'!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!login_url' => $onetime,
'!uri' => $base_url, '!uri_brief' => preg_replace('!^https?://!', '', $base_url), '!mailto' => $account->mail,
'!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE),
'!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE));
// allow the profile to override welcome email text
if (file_exists("./profiles/$profile/provision_welcome_mail.inc")) {
require_once "./profiles/$profile/provision_welcome_mail.inc";
$mailkey = 'welcome-mail-admin';
}
elseif (file_exists(dirname(__FILE__) . '/provision_welcome_mail.inc')) {
/** use the module provided welcome email
* We can not use drupal_get_path here,
* as we are connected to the provisioned site's database
*/
require_once dirname(__FILE__) . '/provision_welcome_mail.inc';
$mailkey = 'welcome-mail-admin';
}
else {
// last resort use the user-pass mail text
$mailkey = 'user-pass';
}
if ($mailkey == 'welcome-mail-admin') {
$subject = st($mail['subject'], $variables);
$body = st($mail['body'], $variables);
}
else {
$subject = _user_mail_text('pass_subject', $variables);
$body = _user_mail_text('pass_body', $variables);
}
$mail_success = drupal_mail($mailkey, $account->mail, $subject, $body, $from);
if ($mail_success) {
provision_log('message', t('Sent welcome mail to @client', array('@client' => $client_email)));
}
else {
provision_log('notice', t('Could not send welcome mail to @client', array('@client' => $client_email)));
}
provision_log('message', t('Login url: !onetime', array('!onetime' => $onetime)));
}
function install_main() {
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
// This must go after drupal_bootstrap(), which unsets globals!
global $profile, $install_locale, $client_email;
require_once './modules/system/system.install';
require_once './includes/file.inc';
// Check existing settings.php.
$verify = install_verify_settings();
// Drupal may already be installed.
if ($verify) {
// Establish a connection to the database.
require_once './includes/database.inc';
db_set_active();
// Check if Drupal is installed.
if (install_verify_drupal()) {
provision_set_error(PROVISION_SITE_INSTALLED);
provision_log('error', st('Site is already installed'));
return FALSE;
}
}
else {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
provision_log('error', st('Config file could not be loaded'));
return FALSE;
}
// 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');
provision_log("install", st("Installing Drupal schema"));
// Load the profile.
require_once "./profiles/$profile/$profile.profile";
provision_log("install", st("Loading @profile install profile", array("@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['descristion'] .' ('. 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, $install_locale);
if (!$modules) {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
return FALSE;
}
foreach ($modules as $module) {
provision_log("success", st("Installing module : @module", array("@module" => $module)));
}
// Perform actual installation defined in the profile.
drupal_install_profile($profile, $modules);
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// Show profile finalization info.
$function = $profile .'_profile_final';
if (function_exists($function)) {
// More steps required
$profile_message = $function();
}
variable_set('install_profile', $profile);
if ($client_email) {
install_send_welcome_mail($url, $profile, $language, $client_email);
}
}
install_main();
<?php
// $Id$
/**
* @file
* Update.php for provisioned sites.
* This file is a derivative of the standard drupal update.php,
* which has been modified to allow being run from the command
* line.
*/
ob_start();
include_once("update.php");
ob_end_clean();
function update_main() {
include_once './includes/install.inc';
drupal_load_updates();
update_fix_schema_version();
update_fix_watchdog_115();
update_fix_watchdog();
update_fix_sessions();
$start = array();
foreach (module_list() as $module) {
$updates = drupal_get_schema_versions($module);
if ($updates !== FALSE) {
$updates = drupal_map_assoc($updates);
$updates[] = 'No updates available';
$default = drupal_get_installed_schema_version($module);
foreach (array_keys($updates) as $update) {
if ($update > $default) {
$default = $update;
break;
}
}
$start[$module] = $default;
}
}
$update_results = array();
foreach ($start as $module => $version) {
drupal_set_installed_schema_version($module, $version - 1);
$updates = drupal_get_schema_versions($module);
$max_version = max($updates);
if ($version <= $max_version) {
provision_log('notice', pt('Updating module @module from schema version @start to schema version @max', array('@module' => $module, '@start' => $version - 1, '@max' => $max_version)));
foreach ($updates as $update) {
$finished = FALSE;
if ($update >= $version) {
while (!$finished) {
// do update
$ret = module_invoke($module, 'update_' . $update);
// Assume the update finished unless the update results indicate otherwise.
foreach ($ret as $info) {
if (!$info['success']) {
provision_set_error('PROVISION_DB_ERROR');
}
provision_log( ($info['success']) ? 'success' : 'error', $info['query']);
}
$finished = 1;
if (isset($ret['#finished'])) {
$finished = $ret['#finished'];
unset($ret['#finished']);
}
}
drupal_set_installed_schema_version($module, $update);
}
}
}
else {
provision_log("notice", pt('No updates for @module module', array('@module' => $module)));
}
}
}
update_main();
<?php
require_once(dirname(__FILE__) . '/../provision.inc');
if ($argv[1]) {
provision_external_init($argv[1]);
}
else {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
provision_log("error", "USAGE: import.php url\n");
}
if ($parts = @parse_url($GLOBALS['db_url'])) {
$data['db_type'] = $parts['scheme'];
$data['db_user'] = $parts['user'];
......@@ -20,4 +11,3 @@ if ($parts = @parse_url($GLOBALS['db_url'])) {
$language = language_default();
$data['language'] = $language->language;
}
provision_output($data);
......@@ -4,22 +4,13 @@
* Rebuild all the caches
*/
require_once(dirname(__FILE__) . '/../provision.inc');
if (sizeof($argv) == 5) {
// Fake the necessary HTTP headers that Drupal needs:
provision_external_init($argv[1], FALSE);
$GLOBALS['url'] = $argv[1];
$GLOBALS['profile'] = $argv[2];
$GLOBALS['install_locale'] = $argv[3];
$GLOBALS['client_email'] = $argv[4];
require_once 'includes/install.inc';
define('MAINTENANCE_MODE', 'install');
}
else {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
provision_log("error", "USAGE: install.php url profile locale email\n");
}
$GLOBALS['url'] = $data['site_url'];
$GLOBALS['profile'] = $data['profile'];
$GLOBALS['install_locale'] = $data['language'];
$GLOBALS['client_email'] = $data['client_email'];
require_once 'includes/install.inc';
define('MAINTENANCE_MODE', 'install');
/**
* Verify if Drupal is installed.
......@@ -316,6 +307,4 @@ function install_main() {
install_send_welcome_mail($url, $profile, $instal_locale, $client_email);
}
}
$data = array();
install_main($url, $data);
provision_output($data);
install_main();
<?php
global $databases;
if ($db = $databases['default']['default']) {
$data['db_type'] = $db['driver'];
$data['db_user'] = $db['username'];
$data['db_host'] = $db['host'];
$data['db_passwd'] = $db['password'];
$data['db_name'] = $db['database'];
$data['profile'] = variable_get('install_profile', 'default');
$language = language_default();
$data['language'] = $language->language;
}
This diff is collapsed.
<?php
// $Id$
/**
* @file
* Update.php for provisioned sites.
* This file is a derivative of the standard drupal update.php,
* which has been modified to allow being run from the command
* line.
*/
ob_start();
$_REQUEST['op'] = 'info';
include_once("update.php");
ob_end_clean();
function update_main() {
include_once './includes/install.inc';
include_once './includes/batch.inc';
drupal_load_updates();
update_fix_d6_requirements();
update_fix_compatibility();
$start = array();
$modules = drupal_get_installed_schema_version(NULL, FALSE, TRUE);
foreach ($modules as $module => $schema_version) {
$updates = drupal_get_schema_versions($module);
// Skip incompatible module updates completely, otherwise test schema versions.
if (!update_check_incompatibility($module) && $updates !== FALSE && $schema_version >= 0) {
// module_invoke returns NULL for nonexisting hooks, so if no updates
// are removed, it will == 0.
$last_removed = module_invoke($module, 'update_last_removed');
if ($schema_version < $last_removed) {
provision_set_error(PROVISION_INSTALL_ERROR);
provision_log('error', pt( $module .' module can not be updated. Its schema version is '. $schema_version .'. Updates up to and including '. $last_removed .' have been removed in this release. In order to update '. $module .' module, you will first <a href="http://drupal.org/upgrade">need to upgrade</a> to the last version in which these updates were available.'));
continue;
}
$updates = drupal_map_assoc($updates);
$updates[] = 'No updates available';
$default = $schema_version;
foreach (array_keys($updates) as $update) {
if ($update > $schema_version) {
$default = $update;
break;
}
}
$start[$module] = $default;
}
}
if (sizeof($start)) {
$operations = array();
foreach ($start as $module => $version) {
drupal_set_installed_schema_version($module, $version - 1);
$updates = drupal_get_schema_versions($module);
$max_version = max($updates);
if ($version <= $max_version) {
provision_log('notice', pt('Updating module @module from schema version @start to schema version @max', array('@module' => $module, '@start' => $version - 1, '@max' => $max_version)));
foreach ($updates as $update) {
if ($update >= $version) {
$operations[] = array('_update_do_one', array($module, $update));
}
}
}
else {
provision_log('notice', pt('No updates for module @module', array('@module' => $module)));
}
}
$batch = array(
'operations' => $operations,
'title' => 'Updating',
'init_message' => 'Starting updates',
'error_message' => 'An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.',
'finished' => 'update_finished',
);
batch_set($batch);
$batch =& batch_get();
$batch['progressive'] = FALSE;
batch_process();
}
else {
provision_log('notice', pt('No outstanding updates'));
}
}
/**
* A simplified version of the batch_do_one function from update.php
*
* This does not mess with sessions and the like, as it will be used
* from the command line
*/
function _update_do_one($module, $number, &$context) {
// If updates for this module have been aborted
// in a previous step, go no further.
if (!empty($context['results'][$module]['#abort'])) {
return;
}
$function = $module .'_update_'. $number;
if (function_exists($function)) {
$ret = $function($context['sandbox']);
}
foreach ($ret as $info) {
if (!$info['success']) {
provision_set_error('PROVISION_DB_ERROR');
}
provision_log( ($info['success']) ? 'success' : 'error', $info['query']);
}
if (isset($ret['#finished'])) {
$context['finished'] = $ret['#finished'];
unset($ret['#finished']);
}
if ($context['finished'] == 1 && empty($context['results'][$module]['#abort'])) {
drupal_set_installed_schema_version($module, $number);
}
}
update_main();
......@@ -4,16 +4,6 @@
* @file
* Rebuild all the caches
*/
require_once(dirname(__FILE__) . '/../provision.inc');
if ($argv[1]) {
provision_external_init($argv[1]);
}
else {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
provision_log("error", "USAGE: clear.php url\n");
}
cache_clear_all();
provision_log('notice', t('Cleared all caches'));
......@@ -31,6 +21,3 @@ provision_log('notice', t('Rebuild node access cache'));
menu_rebuild();
provision_log('notice', t('Rebuild menu cache'));
$data = array();
provision_output($data);
<?php
// $Id$
require_once(dirname(__FILE__) . '/../provision.inc');
$new_url = $data['site_url'];
$old_url = $data['old_site_url'];
if (sizeof($argv) == 3) {
// Fake the necessary HTTP headers that Drupal needs:
$new_url = $argv[1];
$data = provision_external_init($argv[1]);
$old_url = $argv[2];
}
else {
provision_set_error(PROVISION_FRAMEWORK_ERROR);
provision_log("error", "USAGE: drupal_deply.php new_url old_url\n");
provision_output($data);
}
/**
* @file
......@@ -30,6 +20,4 @@ db_query("UPDATE {files} SET filepath=replace(filepath, 'sites/%', 'sites/%')",
db_query("UPDATE {users} SET picture = replace(picture, 'sites/%s', 'sites/%s')", $old_url, $new_url);
variable_set('files_directory_path', "sites/$new_url/files");
variable_set('files_directory_temp', "sites/$new_url/files/tmp");
$data = array();
provision_output($data);
<?php
// $Id$
require_once(dirname(__FILE__) . '/../provision.inc');
require_once('provision_drupal.drush.inc');
$url = ($argv[1]) ? $argv[1] : null;
provision_external_init($url);
$data['modules'] = module_rebuild_cache();
// Find theme engines
$data['engines'] = drupal_system_listing('\.engine$', 'themes/engines');
$data['themes'] = system_theme_data();
provision_output($data);
......@@ -18,9 +18,7 @@ function provision_drupal_provision_import_validate() {
* Import the information about the existing site, and return it in the $data context array
*/
function provision_drupal_provision_import(&$data, $url = NULL) {
$info = _provision_drupal_import_site($data, $url);
if ($info['installed']) {
provision_log("notice", "Returning information for $url");
}
provision_internal_init($url);
provision_platform_include(dirname(__FILE__), 'import');
}
......@@ -36,9 +36,8 @@ function provision_drupal_provision_pre_install(&$data, $url = NULL) {
function provision_drupal_provision_install(&$data, $url = NULL) {
// Requires at least the database settings to complete.
_provision_drupal_create_settings_file($data, $url);
$cmd = sprintf("php %s/drupal_install.php %s %s %s %s", dirname(__FILE__), escapeshellarg($url), escapeshellarg($data['profile']), escapeshellarg($data['language']), escapeshellarg($data['client_email']));
provision_exec($cmd, $data);
provision_internal_init($url, FALSE);
provision_platform_include(dirname(__FILE__), 'install');
}
/**
......
......@@ -212,9 +212,11 @@ function _provision_drupal_create_directories($url, $profile = NULL) {
* Runs an external script to reload all the various drupal caches
*/
function _provision_drupal_rebuild_caches(&$data, $url = NULL) {
if ($url) {
$cmd = sprintf("php %s/drupal_clear.php %s", dirname(__FILE__), escapeshellarg($url));
provision_exec($cmd, $data);
if (PLATFORM_CONTEXT_SITE) {
ini_set('error_reporting', E_ALL);
ini_set('display_errors', TRUE);
provision_internal_init($url);
provision_platform_include(dirname(__FILE__), 'clear');
}
}
......@@ -324,7 +326,7 @@ function _provision_drupal_variable_get($name, $default) {
* Create and remove symlinks for each of the possible domain aliases of an existing site
*/
function _provision_drupal_maintain_aliases($data, $url) {
if (PROVISION_PLATFORM_SITE) {
if (PROVISION_CONTEXT_SITE) {
$old_aliases = array();
if ($old_data = provision_load_site_data($url)) {
if (is_array($old_data['aliases'])) {
......
$databases['default']['default'] = array(
'driver' => '<?php print $db_type; ?>',
'database' => '<?php print $db_name; ?>',
'username' => '<?php print $db_user; ?>',
'password' => '<?php print $db_passwd; ?>',
'host' => '<?php print $db_host ?>',
);
$db_url = '<?php print "$db_type://$db_user:$db_passwd@$db_host/$db_name"; ?>';
$profile = "<?php print $profile ?>";
/**
* PHP settings:
......
......@@ -7,5 +7,5 @@ function provision_drupal_provision_update_validate() {
function provision_drupal_provision_update(&$data, $url) {
provision_internal_init($data['site_url'], false);
include_once(sprintf('%s/drupal_update.inc', dirname(__FILE__)));
provision_platform_include(dirname(__FILE__), 'update');
}
......@@ -26,7 +26,6 @@ function provision_drupal_provision_verify(&$data, $url = null) {
provision_log('notice', dt("This platform is running @short_name @version",
array('@short_name' => 'drupal', '@version' => VERSION)));
$data['profiles'] = _provision_find_profiles();
$cmd = sprintf("php %s/drupal_verify.php", dirname(__FILE__));
}
else {
// This is the actual drupal provisioning requirements.
......@@ -34,8 +33,8 @@ function provision_drupal_provision_verify(&$data, $url = null) {
_provision_drupal_maintain_aliases($data, $url);
// Requires at least the database settings to complete.
_provision_drupal_create_settings_file($data, $url);
#$cmd = sprintf("php %s/drupal_verify.php %s", dirname(__FILE__), $url);
#provision_exec($cmd, $data);
// provision_internal_init($url);
// provision_platform_include(dirname(__FILE__), 'verify');
}
if (is_array($data['modules'])) {
// get the correct version names for everything.
......
......@@ -170,8 +170,6 @@ function provision_parse_output($string) {
* An associative array containing additional data to be returned from the command. @see provision_stats_stats()
*/
function provision_output($data = array()) {
$return = $extra;
$return['site'] = $data;
$error = provision_get_error();
if (!$error) {
......@@ -689,9 +687,14 @@ function provision_proc_open($cmd, &$data = NULL) {
}
fclose($pipes[0]);
$info = stream_get_meta_data($pipes[1]);
stream_set_blocking($pipes[0], TRUE);
stream_set_timeout($pipes[1], 1);
while (! ($string = stream_get_contents($pipes[1]))) {
sleep(1);
$stream = '';
while (!feof($pipes[1]) && !$info['timed_out']) {
$string .= fgets($pipes[1], 4096);
$info = stream_get_meta_data($pipes[1]);
ob_flush();
flush();
};
fclose($pipes[1]);
$code = proc_close($process);
......@@ -782,6 +785,7 @@ function provision_external_init($url, $bootstrap = TRUE) {
$_SERVER['REQUEST_METHOD'] = NULL;
$_SERVER['SERVER_SOFTWARE'] = NULL;
define('DRUPAL_ROOT', realpath('.'));
define('PROVISION_DRUSH_BACKEND', true);
if ($bootstrap) {
include_once('includes/bootstrap.inc');
......@@ -801,14 +805,13 @@ function provision_internal_init($url, $bootstrap = TRUE) {
$url = ($url) ? $url : 'default';
$drupal_base_url = parse_url(sprintf("http://" . $url));
$_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
$_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/install.php';
$_SERVER['PHP_SELF'] = '/index.php';
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
$_SERVER['REMOTE_ADDR'] = '';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['REQUEST_METHOD'] = NULL;
$_SERVER['SERVER_SOFTWARE'] = NULL;
if ($bootstrap) {
include_once('includes/bootstrap.inc');
include_once('./includes/bootstrap.inc');
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
}
......@@ -837,3 +840,24 @@ function provision_password($length = 10) {
return $pass;
}
function provision_platform_include($path, $command, $version = null, $platform = 'drupal') {
$version = ($version) ? $version : drush_drupal_major_version();
$options[] = sprintf("%s_%s_%s", $platform, $version, $command);
$options[] = sprintf("%s_%s", $platform, $command);
$options[] = sprintf("%s", $command);
$match = false;
foreach ($options as $option) {
$file = sprintf("%s/%s.inc", $path, $option);
if (file_exists($file)) {
$match = $file;
break;