#!/usr/bin/env php drupal_get_installed_schema_version($module); } function update_show_updates($updates) { echo t('Modules Requiring Updates:') ."\n\n"; $files = module_rebuild_cache(); foreach ($updates as $module => $update_list) { echo "{$files[$module]->info['name']} ({$files[$module]->name})\n"; echo " ". t('Pending Updates:') .' '. implode(',', $update_list) ."\n\n"; } } function update_show_versions() { $files = module_rebuild_cache(); printf("%-20s %-20s %-19s %5s\n\n", 'Name', 'Module', 'Version', 'Schema'); foreach ($files as $module => $file) { printf("%-20s %-20s %-19s %5s\n", $file->info['name'], $module, $file->info['version'], $file->schema_version); } } function update_do_updates($updates) { global $results, $maintenance; $results = array(); if ($maintenance) { variable_set('site_offline', 1); if (!empty($message)) { variable_set('site_offine_message', $message); } } $operations = array(); foreach ($updates as $module => $update_list) { foreach ($update_list as $update) { $operations[] = array('update_sh_do_one', array($module, $update)); } } // Since this is running from the shell, we want to turn progressive off. $_init_batch =& batch_get(); if (empty($_init_batch)) { $_init_batch = array( 'sets' => array(), 'progressive' => FALSE, ); } $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_sh_finished', 'progressive' => FALSE, ); batch_set($batch); batch_process(); if ($_SESSION['update_success']) { $output = 'Updates were attempted. If you see no failures below, you may proceed happily to the administration pages. Otherwise, you may need to update your database manually.'. $log_message ."\n"; } else { list($module, $version) = array_pop(reset($_SESSION['updates_remaining'])); $output = 'The update process was aborted prematurely while running update #'. $version .' in '. $module .'.module.'. $log_message; if (module_exists('dblog')) { $output .= ' You may need to check the watchdog database table manually.'; } $output .= "\n"; } // Output a list of queries executed $update_ok = TRUE; if (!empty($_SESSION['update_results'])) { $output .= "The following queries were executed\n\n"; foreach ($_SESSION['update_results'] as $module => $updates) { $output .= $module ." module\n"; foreach ($updates as $number => $queries) { if ($number != '#abort') { $output .= 'Update #'. $number ."\n"; foreach ($queries as $query) { if ($query['success']) { $output .= '* '. htmlspecialchars_decode(html_entity_decode($query['query'])) ."\n"; } else { $update_ok = FALSE; $output .= '* Failed: '. htmlspecialchars_decode(html_entity_decode($query['query'])) ."\n"; } } if (!count($queries)) { $output .= "* No queries\n"; } } } } echo $output; } unset($_SESSION['update_results']); unset($_SESSION['update_success']); if ($maintenance && $update_ok) { variable_del('site_offline'); if (!empty($message)) { variable_del('site_offine_message'); } } return $update_ok; } function update_sh_do_one($module, $number, &$context) { global $dryrun, $results; // 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 (!$dryrun && function_exists($function)) { $ret = $function($context['sandbox']); } if (isset($ret['#finished'])) { $context['finished'] = $ret['#finished']; unset($ret['#finished']); } if (!isset($context['results'][$module])) { $context['results'][$module] = array(); } if (!isset($context['results'][$module][$number])) { $context['results'][$module][$number] = array(); } $context['results'][$module][$number] = array_merge($context['results'][$module][$number], $ret); if (!empty($ret['#abort'])) { $context['results'][$module]['#abort'] = TRUE; } // Record the schema update if it was completed successfully. if ($context['finished'] == 1 && empty($context['results'][$module]['#abort'])) { drupal_set_installed_schema_version($module, $number); } $context['message'] = 'Updating '. check_plain($module) .' module'; } function update_sh_finished($success, $results, $operations) { // clear the caches in case the data has been updated. drupal_flush_all_caches(); $_SESSION['update_results'] = $results; $_SESSION['update_success'] = $success; $_SESSION['updates_remaining'] = $operations; } $script = basename(array_shift($_SERVER['argv'])); $shortopts = 'hr:s:lum::dve'; $longopts = array('help', 'root:', 'site:', 'list', 'update', 'maintenance::', 'dry-run', 'verbose', 'versions'); $args = @getopt($shortopts, $longopts); if (isset($args['h']) || isset($args['help'])) { echo <<" Example: {$script} "http://mysite.org/node" All arguments are long options. -h, --help This page. -r, --root Set the working directory for the script to the specified path. To execute Drupal this has to be the root directory of your Drupal installation, f.e. /home/www/foo/drupal (assuming Drupal running on Unix). Current directory is not required. Use surrounding quotation marks on Windows. -s, --site Used to specify with site will be used for the upgrade. If no site is selected then default will be used. -l, --list List all pending updates. If there are updates available then the script with exit with a 1 return flag -u, --update Process all pending updates. If there are any updates are not processed successfully then the script with exit with a return flag of 1. -m, --maintenance Set the site into maintenance while the updates are being run. If there are any failures, the site will remain in maintenance mode. An optional message can be specified which will set the message on the maintenance screen. -d, --dry-run No updates will be run but the system will pretend to do the updates -v, --verbose This option displays the options as they are set, but will produce errors from setting the session. -e, --versions List the versions of all the modules in the system. To run this script without --root argument invoke it from the root directory of your Drupal installation with ./scripts/{$script} \n EOF; if (version_compare(phpversion(), '5.3.0', 'le')) { echo "Warning: This version of PHP doesn't support long options\n"; } exit; } // define default settings $_SERVER['HTTP_HOST'] = 'default'; $_SERVER['PHP_SELF'] = '/update.php'; $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_SOFTWARE'] = 'PHP CLI'; $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['QUERY_STRING'] = ''; $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/'; $_SERVER['SCRIPT_NAME'] = '/'. basename($_SERVER['SCRIPT_NAME']); // toggle verbose mode $_verbose_mode = isset($args['h']) || isset($args['help']) ? TRUE : FALSE; $dryrun = FALSE; $maintenance = FALSE; $message = NULL; // parse invocation arguments if (isset($args['r']) || isset($args['root'])) { // change working directory $path = isset($args['r']) ? $args['r'] : $args['root']; if (is_dir($path)) { chdir($path); if ($_verbose_mode) { echo "cwd changed to: {$path}\n"; } } else { echo "\nERROR: {$path} not found.\n\n"; } } if (isset($args['s']) || isset($args['site'])) { $site = isset($args['s']) ? $args['s'] : $args['site']; if (file_exists('./sites/'. $site)) { $_SERVER['HTTP_HOST'] = $site; $_SERVER['PHP_SELF'] = $_SERVER['REQUEST_URI'] = '/update.php'; } else { echo "ERROR: Unable to locate site {$site}\n"; exit(1); } } $dryrun = (isset($args['d']) || isset($args['dry-run'])) ? TRUE : FALSE; if (isset($args['m']) || isset($args['maintenance'])) { $maintenance = TRUE; $opt = isset($args['m']) ? $args['m'] : $args['maintenance']; if (is_string($opt)) { $message = $opt; } } include_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); include_once './includes/install.inc'; include_once './includes/form.inc'; drupal_load_updates(); $user = user_load(array('uid' => 1)); foreach ($args as $arg => $option) { switch ($arg) { case 'l': case 'list': if ($updates = drupal_get_updates()) { update_show_updates($updates); exit(1); } else { echo t('No Updates available') ."\n"; } break 2; case 'e': case 'versions': update_show_versions(); break 2; case 'u': case 'update': if ($updates = drupal_get_updates()) { if (!update_do_updates($updates)) { exit(1); } } break 2; } } exit();