Index: update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.158 diff -u -F^f -r1.158 update.php --- update.php 11 Oct 2005 20:46:17 -0000 1.158 +++ update.php 1 Nov 2005 04:40:25 -0000 @@ -17,49 +17,156 @@ // Enforce access checking? $access_check = TRUE; -if (!ini_get("safe_mode")) { - set_time_limit(180); + +define('SCHEMA', 0); +define('SCHEMA_MIN', 1); + +/** + * Includes install files. + */ +function update_include_install_files() { + // The system module (Drupal core) is currently a special case + include_once './database/updates.inc'; + + foreach (module_list() as $module) { + $install_file = './'. drupal_get_path('module', $module) .'/'. $module .'.install'; + if (is_file($install_file)) { + include_once $install_file; + } + } +} + +function update_sql($sql) { + $result = db_query($sql); + return array('success' => $result !== FALSE, 'query' => check_plain($sql)); +} + +/** + * If the schema version for Drupal core is stored in the the variables table + * (4.6.x and earlier) move it to the schema_version column of the system + * table. + */ +function update_fix_schema_version() { + if ($update_start = variable_get('update_start', FALSE)) { + $sql_updates = array( + '2004-10-31: first update since Drupal 4.5.0 release' => 110, + '2004-11-07' => 111, '2004-11-15' => 112, '2004-11-28' => 113, + '2004-12-05' => 114, '2005-01-07' => 115, '2005-01-14' => 116, + '2005-01-18' => 117, '2005-01-19' => 118, '2005-01-20' => 119, + '2005-01-25' => 120, '2005-01-26' => 121, '2005-01-27' => 122, + '2005-01-28' => 123, '2005-02-11' => 124, '2005-02-23' => 125, + '2005-03-03' => 126, '2005-03-18' => 127, '2005-03-21' => 128, + '2005-04-08: first update since Drupal 4.6.0 release' => 129, + '2005-04-10' => 130, '2005-04-11' => 131, '2005-04-14' => 132, + '2005-04-24' => 133, '2005-04-30' => 134, '2005-05-06' => 135, + '2005-05-08' => 136, '2005-05-09' => 137, '2005-05-10' => 138, + '2005-05-11' => 139, '2005-05-12' => 140, '2005-05-22' => 141, + '2005-07-29' => 142, '2005-07-30' => 143, '2005-08-08' => 144, + '2005-08-15' => 145, '2005-08-25' => 146, '2005-09-07' => 147, + '2005-09-18' => 148, '2005-09-27' => 149, '2005-10-15' => 150 + ); + db_query('ALTER TABLE {system} ADD schema_version smallint(2) unsigned not null'); + update_set_installed_version('system', $sql_updates[$update_start]); + variable_del('update_start'); + } +} + +function update_data($module, $number) { + $ret = module_invoke($module, 'update_'. $number); + + // Save the query and results for display by update_finished_page(). + if (!isset($_SESSION['update_results'])) { + $_SESSION['update_results'] = array(); + } + else if (!isset($_SESSION['update_results'][$module])) { + $_SESSION['update_results'][$module] = array(); + } + $_SESSION['update_results'][$module][$number] = $ret; + + // Update the installed version + update_set_installed_version($module, $number); +} + +/** + * Returns an array of availiable schema versions for a module. + * + * @param $module + * A module name. + * @return + * If the module has updates, an array of available updates. Otherwise, + * FALSE. + */ +function update_get_versions($module) { + if (!($max = module_invoke($module, 'version', SCHEMA))) { + return FALSE; + } + if (!($min = module_invoke($module, 'version', SCHEMA_MIN))) { + $min = 1; + } + return range($min, $max); } -include_once './database/updates.inc'; +/** + * Returns the currently installed schema version for a module. + * + * @param $module + * A module name. + * @return + * The currently installed schema version. + */ +function update_get_installed_version($module, $reset = FALSE) { + static $versions; -function update_data($start) { - global $sql_updates; - $output = ''; - $sql_updates = array_slice($sql_updates, ($start-- ? $start : 0)); - foreach ($sql_updates as $date => $func) { - $output .= '
';
- $ret = $func();
- foreach ($ret as $return) {
- $output .= $return[1];
+ if ($reset) {
+ unset($versions);
+ }
+
+ if (!$versions) {
+ $versions = array();
+ $result = db_query("SELECT name, schema_version FROM {system} WHERE type = 'module'");
+ while ($row = db_fetch_object($result)) {
+ $versions[$row->name] = $row->schema_version;
}
- variable_set("update_start", $date);
- $output .= "\n";
}
- db_query('DELETE FROM {cache}');
- return $output;
+
+ return $versions[$module];
}
-function update_selection_page() {
- global $sql_updates;
+/**
+ * Update the installed version information for a module.
+ *
+ * @param $module
+ * A module name.
+ * @param $version
+ * The new schema version.
+ */
+function update_set_installed_version($module, $version) {
+ db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module);
+}
+
+function update_advanced_selection_page() {
+ update_fix_schema_version();
+
+ $form = array();
+ $form['start'] = array('#tree' => TRUE);
+ foreach (module_list() as $module) {
+ if (module_hook($module, 'version')) {
+ $updates = drupal_map_assoc(update_get_versions($module));
+ $updates[] = 'No updates available';
+
+ $form['start'][$module] = array(
+ '#type' => 'select',
+ '#title' => t('%name module', array('%name' => $module)),
+ '#default_value' => array_search(update_get_installed_version($module), $updates) + 1,
+ '#options' => $updates,
+ '#description' => t('This defaults to the first available update since the last update you performed.')
+ );
+ }
+ }
- $start = variable_get("update_start", 0);
- $i = 1;
- foreach ($sql_updates as $date => $sql) {
- $dates[$i++] = $date;
- if ($date == $start) {
- $selected = $i;
- }
- }
- $dates[$i] = "No updates available";
-
- // make update form and output it.
- $form['start'] = array(
- '#type' => 'select',
- '#title' => t('Perform updates from'),
- '#default_value' => (isset($selected) ? $selected : -1),
- '#options' => $dates,
- '#description' => t('This defaults to the first available update since the last update you performed.')
+ $form['has_js'] = array(
+ '#type' => 'hidden',
+ '#default_value' => FALSE
);
$form['submit'] = array(
'#type' => 'submit',
@@ -67,21 +174,133 @@ function update_selection_page() {
);
drupal_set_title('Drupal database update');
+ drupal_add_js('misc/update.js');
return drupal_get_form('update_script_selection_form', $form);
}
+function update_update_page() {
+ // Set the installed version so updates start at the correct place.
+ $_SESSION['update_remaining'] = array();
+ foreach ($_POST['edit']['start'] as $module => $version) {
+ update_set_installed_version($module, $version - 1);
+ $max_version = max(update_get_versions($module));
+ if ($version <= $max_version) {
+ foreach (range($version, $max_version) as $update) {
+ $_SESSION['update_remaining'][] = array('module' => $module, 'version' => $update);
+ }
+ }
+ }
+ $_SESSION['update_total'] = count($_SESSION['update_remaining']);
+
+ if ($_POST['edit']['has_js']) {
+ return update_progress_page();
+ }
+ else {
+ return update_progress_page_nojs();
+ }
+}
+
+function update_progress_page() {
+ drupal_add_js('misc/progress.js');
+ drupal_add_js('misc/update.js');
+
+ drupal_set_title('Updating');
+ $output = '';
+ $output .= 'Updating your site will take a few seconds.
'; + return $output; +} + +/** + * Perform updates for one second or until finished. + * + * @return + * An array indicating the status after doing updates. The first element is + * the overall percent finished. The second element is a status message. + */ function update_do_updates() { - $edit = $_POST['edit']; + foreach ($_SESSION['update_remaining'] as $key => $update) { + update_data($update['module'], $update['version']); + unset($_SESSION['update_remaining'][$key]); + if (timer_read('page') > 1000) { + break; + } + } + + if ($_SESSION['update_total']) { + $percent = floor(($_SESSION['update_total'] - count($_SESSION['update_remaining'])) / $_SESSION['update_total'] * 100); + } + else { + $percent = 100; + } + return array($percent, 'Updating '. $update['module'] .' module'); +} + +function update_do_update_page() { + // HTTP Post required + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + drupal_set_message('HTTP Post is required.', 'error'); + drupal_set_title('Error'); + return ''; + } + + print implode('|', update_do_updates()); +} + +function update_progress_page_nojs() { + $new_op = 'do_update_nojs'; + if ($_SERVER['REQUEST_METHOD'] == 'GET') { + list($percent, $message) = update_do_updates(); + if ($percent == 100) { + $new_op = 'finished'; + } + } + else { + // This is the first page so return some output immediately. + $percent = 0; + $message = 'Starting updates...'; + } + + drupal_set_html_head(''); + drupal_set_title('Updating'); + $output = theme('progress_bar', $percent, $message); + $output .= 'Updating your site will take a few seconds.
'; + + return $output; +} + +function update_finished_page() { drupal_set_title('Drupal database update'); // NOTE: we can't use l() here because the URL would point to 'update.php?q=admin'. - $links[] = "main page"; - $links[] = "administration pages"; + $links[] = 'main page'; + $links[] = 'administration pages'; $output = theme('item_list', $links); - $output .= update_data($edit['start']); - $output .= 'Updates were attempted. If you see no failures above, you may proceed happily to the administration pages. Otherwise, you may need to update your database manually.
'; + $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.
'; if ($GLOBALS['access_check'] == FALSE) { $output .= "Reminder: don't forget to set the \$access_check value at the top of update.php back to TRUE.";
}
+
+ // Output a list of queryies executed
+ if ($_SESSION['update_results']) {
+ $output .= '
For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.
'; @@ -108,35 +327,55 @@ function update_access_denied_page() { '; } +// The database-level bootstrapping initializes and loads any global $conf from +// settings.php include_once './includes/bootstrap.inc'; -drupal_maintenance_theme(); +drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); -if (isset($_GET["op"])) { - drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); +// Remove on-screen error reporting +global $conf; +if (!isset($conf['error_level'])) { + $conf['error_level'] = 0; +} - // Access check: - if (($access_check == 0) || ($user->uid == 1)) { - $op = isset($_POST['op']) ? $_POST['op'] : ''; - switch ($op) { - case 'Update': - $output = update_do_updates(); - break; - - default: - $output = update_selection_page(); - break; - } - } - else { - $output = update_access_denied_page(); +// Initialize the rest of the Drupal +drupal_maintenance_theme(); +drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + +// Access check: +if (($access_check == FALSE) || ($user->uid == 1)) { + update_include_install_files(); + $op = isset($_REQUEST['op']) ? $_REQUEST['op'] : ''; + switch ($op) { + case 'Update': + $output = update_update_page(); + break; + + case 'finished': + $output = update_finished_page(); + break; + + case 'do_update': + $output = update_do_update_page(); + break; + + case 'do_update_nojs': + $output = update_progress_page_nojs(); + break; + + case 'selection': + $output = update_advanced_selection_page(); + break; + + default: + $output = update_info_page(); + break; } } else { - drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); - $output = update_info_page(); + $output = update_access_denied_page(); } if (isset($output)) { print theme('maintenance_page', $output); } - Index: database/updates.inc =================================================================== RCS file: /cvs/drupal/drupal/database/updates.inc,v retrieving revision 1.140 diff -u -F^f -r1.140 updates.inc --- database/updates.inc 22 Oct 2005 15:14:46 -0000 1.140 +++ database/updates.inc 1 Nov 2005 04:40:25 -0000 @@ -25,52 +25,17 @@ * */ -// Define the various updates in an array("date : comment" => "function"); -$sql_updates = array( - "2004-10-31: first update since Drupal 4.5.0 release" => "update_110", - "2004-11-07" => "update_111", - "2004-11-15" => "update_112", - "2004-11-28" => "update_113", - "2004-12-05" => "update_114", - "2005-01-07" => "update_115", - "2005-01-14" => "update_116", - "2005-01-18" => "update_117", - "2005-01-19" => "update_118", - "2005-01-20" => "update_119", - "2005-01-25" => "update_120", - "2005-01-26" => "update_121", - "2005-01-27" => "update_122", - "2005-01-28" => "update_123", - "2005-02-11" => "update_124", - "2005-02-23" => "update_125", - "2005-03-03" => "update_126", - "2005-03-18" => "update_127", - "2005-03-21" => "update_128", - "2005-04-08: first update since Drupal 4.6.0 release" => "update_129", - "2005-04-10" => "update_130", - "2005-04-11" => "update_131", - "2005-04-14" => "update_132", - "2005-04-24" => "update_133", - "2005-04-30" => "update_134", - "2005-05-06" => "update_135", - "2005-05-08" => "update_136", - "2005-05-09" => "update_137", - "2005-05-10" => "update_138", - "2005-05-11" => "update_139", - "2005-05-12" => "update_140", - "2005-05-22" => "update_141", - "2005-07-29" => "update_142", - "2005-07-30" => "update_143", - "2005-08-08" => "update_144", - "2005-08-15" => "update_145", - "2005-08-25" => "update_146", - "2005-09-07" => "update_147", - "2005-09-18" => "update_148", - "2005-09-27" => "update_149", - "2005-10-15" => "update_150" -); +function system_version($type) { + switch ($type) { + case SCHEMA: + return 150; -function update_110() { + case SCHEMA_MIN: + return 110; + } +} + +function system_update_110() { $ret = array(); // TODO: needs PGSQL version @@ -154,7 +119,7 @@ function update_110() { return $ret; } -function update_111() { +function system_update_111() { $ret = array(); $ret[] = update_sql("DELETE FROM {variable} WHERE name LIKE 'throttle_%'"); @@ -169,7 +134,7 @@ function update_111() { return $ret; } -function update_112() { +function system_update_112() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -190,7 +155,7 @@ function update_112() { return $ret; } -function update_113() { +function system_update_113() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -221,7 +186,7 @@ function update_113() { return $ret; } -function update_114() { +function system_update_114() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("CREATE TABLE {queue} ( @@ -275,7 +240,7 @@ function update_114() { return $ret; } -function update_115() { +function system_update_115() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {watchdog} ADD severity tinyint(3) unsigned NOT NULL default '0'"); @@ -289,11 +254,11 @@ function update_115() { return $ret; } -function update_116() { +function system_update_116() { return array(update_sql("DELETE FROM {system} WHERE name = 'admin'")); } -function update_117() { +function system_update_117() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("CREATE TABLE {vocabulary_node_types} ( @@ -310,7 +275,7 @@ function update_117() { return $ret; } -function update_118() { +function system_update_118() { $ret = array(); $result = db_query('SELECT vid, nodes FROM {vocabulary}'); while ($vocabulary = db_fetch_object($result)) { @@ -327,7 +292,7 @@ function update_118() { return $ret; } -function update_119() { +function system_update_119() { $ret = array(); foreach (node_get_types() as $type => $name) { @@ -358,7 +323,7 @@ function update_119() { return $ret; } -function update_120() { +function system_update_120() { $ret = array(); // Rewrite old URL aliases. Works for both PostgreSQL and MySQL @@ -374,7 +339,7 @@ function update_120() { return $ret; } -function update_121() { +function system_update_121() { $ret = array(); // Remove the unused page table. @@ -383,7 +348,7 @@ function update_121() { return $ret; } -function update_122() { +function system_update_122() { $ret = array(); $ret[] = update_sql("ALTER TABLE {blocks} ADD types text"); @@ -391,7 +356,7 @@ function update_122() { } -function update_123() { +function system_update_123() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -413,7 +378,7 @@ function update_123() { return $ret; } -function update_124() { +function system_update_124() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -461,7 +426,7 @@ function update_124() { return $ret; } -function update_125() { +function system_update_125() { // Postgres only update. $ret = array(); @@ -480,7 +445,7 @@ function update_125() { return $ret; } -function update_126() { +function system_update_126() { variable_set('forum_block_num_0', variable_get('forum_block_num', 5)); variable_set('forum_block_num_1', variable_get('forum_block_num', 5)); variable_del('forum_block_num'); @@ -488,7 +453,7 @@ function update_126() { return array(); } -function update_127() { +function system_update_127() { $ret = array(); if ($GLOBALS['db_type'] == 'pgsql') { $ret[] = update_sql("ALTER TABLE {poll} RENAME voters TO polled"); @@ -499,7 +464,7 @@ function update_127() { return $ret; } -function update_128() { +function system_update_128() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -512,7 +477,7 @@ function update_128() { return $ret; } -function update_129() { +function system_update_129() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -525,7 +490,7 @@ function update_129() { return $ret; } -function update_130() { +function system_update_130() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp"); @@ -536,7 +501,7 @@ function update_130() { return $ret; } -function update_131() { +function system_update_131() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -551,7 +516,7 @@ function update_131() { return $ret; } -function update_132() { +function system_update_132() { /** * PostgreSQL only update. */ @@ -574,7 +539,7 @@ function update_132() { return $ret; } -function update_133() { +function system_update_133() { $ret[] = update_sql("CREATE TABLE {contact} ( subject varchar(255) NOT NULL default '', recipients longtext NOT NULL default '', @@ -593,7 +558,7 @@ function update_133() { return $ret; } -function update_134() { +function system_update_134() { if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql('ALTER TABLE {blocks} DROP types'); } @@ -604,7 +569,7 @@ function update_134() { return $ret; } -function update_135() { +function system_update_135() { $result = db_query("SELECT delta FROM {blocks} WHERE module = 'aggregator'"); while ($block = db_fetch_object($result)) { list($type, $id) = explode(':', $block->delta); @@ -613,7 +578,7 @@ function update_135() { return array(); } -function update_136() { +function system_update_136() { $ret = array(); $ret[] = update_sql("ALTER TABLE {users} CHANGE COLUMN changed access int(11) NOT NULL default '0'"); $ret[] = update_sql('UPDATE {users} SET access = login WHERE login > created'); @@ -621,7 +586,7 @@ function update_136() { return $ret; } -function update_137() { +function system_update_137() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -638,20 +603,20 @@ function update_137() { return $ret; } -function update_138() { +function system_update_138() { $ret = array(); // duplicate of update_97 which never got into the default database.* files. $ret[] = update_sql("INSERT INTO {url_alias} (src, dst) VALUES ('node/feed', 'rss.xml')"); return $ret; } -function update_139() { +function system_update_139() { $ret = array(); $ret[] = update_sql("ALTER TABLE {accesslog} ADD timer int(10) unsigned NOT NULL default '0'"); return $ret; } -function update_140() { +function system_update_140() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -663,7 +628,7 @@ function update_140() { return $ret; } -function update_141() { +function system_update_141() { $ret = array(); variable_del('upload_maxsize_total'); @@ -671,13 +636,13 @@ function update_141() { return $ret; } -function update_142() { +function system_update_142() { $ret = array(); $ret[] = update_sql("ALTER TABLE {watchdog} ADD COLUMN referer varchar(128) NOT NULL"); return $ret; } -function update_143() { +function system_update_143() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -691,7 +656,7 @@ function update_143() { return $ret; } -function update_144() { +function system_update_144() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {node} CHANGE type type VARCHAR(32) NOT NULL"); @@ -707,7 +672,7 @@ function update_144() { return $ret; } -function update_145() { +function system_update_145() { $default_theme = variable_get('theme_default', 'bluemarine'); $ret = array(); $ret[] = update_sql("ALTER TABLE {blocks} CHANGE region region varchar(64) default 'left' NOT NULL"); @@ -729,7 +694,7 @@ function update_145() { return $ret; } -function update_146() { +function system_update_146() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { @@ -787,7 +752,7 @@ function update_146() { while ($row = db_fetch_object($result)) { db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $row->log, $row->nid); } - + if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {book} DROP log"); $ret[] = update_sql("ALTER TABLE {node} DROP teaser"); @@ -801,7 +766,7 @@ function update_146() { return $ret; } -function update_147() { +function system_update_147() { $ret = array(); // this update is mysql only, pgsql should get it right in the first try. @@ -812,7 +777,7 @@ function update_147() { return $ret; } -function update_148() { +function system_update_148() { $ret = array(); // Add support for tracking users' session ids (useful for tracking anon users) @@ -826,12 +791,12 @@ function update_148() { case 'mysqli': $ret[] = update_sql("ALTER TABLE {accesslog} ADD sid varchar(32) NOT NULL default ''"); break; - } + } return $ret; } -function update_149() { +function system_update_149() { $ret = array(); switch ($GLOBALS['db_type']) { @@ -847,7 +812,7 @@ function update_149() { return $ret; } -function update_150() { +function system_update_150() { $ret = array(); $ret[] = update_sql("DELETE FROM {variable} WHERE name = 'node_cron_last'"); @@ -918,16 +883,3 @@ function update_150() { } return $ret; } - -function update_sql($sql) { - $edit = $_POST["edit"]; - $result = db_query($sql); - if ($result) { - return array('1', check_plain($sql) ."\nOK\n"); - } - else { - return array('0', check_plain($sql) ."\nFAILED\n"); - } -} - -?> Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.39 diff -u -F^f -r1.39 database.mysql.inc --- includes/database.mysql.inc 20 Oct 2005 21:30:50 -0000 1.39 +++ includes/database.mysql.inc 1 Nov 2005 04:40:25 -0000 @@ -105,7 +105,7 @@ function _db_query($query, $debug = 0) { return $result; } else { - trigger_error(mysql_error() ."\nquery: ". htmlspecialchars($query), E_USER_ERROR); + trigger_error(mysql_error() ."\nquery: ". htmlspecialchars($query), E_USER_WARNING); return FALSE; } } Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.263 diff -u -F^f -r1.263 theme.inc --- includes/theme.inc 22 Oct 2005 15:14:46 -0000 1.263 +++ includes/theme.inc 1 Nov 2005 04:40:25 -0000 @@ -1010,6 +1010,16 @@ function theme_username($object) { return $output; } +function theme_progress_bar($percent, $message) { + $output = '