Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.10 diff -u -r1.10 install.php --- install.php 23 Aug 2006 08:25:43 -0000 1.10 +++ install.php 23 Aug 2006 16:50:33 -0000 @@ -421,8 +421,6 @@ */ function install_complete($profile) { global $base_url; - // Store install profile for later use. - variable_set('install_profile', $profile); // Bootstrap newly installed Drupal, while preserving existing messages. $messages = $_SESSION['messages']; Index: update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.200 diff -u -r1.200 update.php --- update.php 18 Aug 2006 18:58:44 -0000 1.200 +++ update.php 23 Aug 2006 16:47:48 -0000 @@ -200,7 +200,7 @@ db_query('UPDATE {system} SET schema_version = 0 WHERE status = 1'); // Set schema version for core - drupal_set_installed_schema_version('system', $sql_updates[$update_start]); + drupal_set_installed_schema_version('module', 'system', $sql_updates[$update_start]); variable_del('update_start'); } } @@ -216,7 +216,7 @@ function update_fix_sessions() { $ret = array(); - if (drupal_get_installed_schema_version('system') < 130 && !variable_get('update_sessions_fixed', FALSE)) { + if (drupal_get_installed_schema_version('module', 'system') < 130 && !variable_get('update_sessions_fixed', FALSE)) { if ($GLOBALS['db_type'] == 'mysql') { db_query("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp"); } @@ -236,7 +236,7 @@ * when update 115 is removed. It is part of the Drupal 4.5 to 4.7 migration. */ function update_fix_watchdog_115() { - if (drupal_get_installed_schema_version('system') < 115 && !variable_get('update_watchdog_115_fixed', FALSE)) { + if (drupal_get_installed_schema_version('module', 'system') < 115 && !variable_get('update_watchdog_115_fixed', FALSE)) { if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {watchdog} ADD severity tinyint(3) unsigned NOT NULL default '0'"); } @@ -259,7 +259,7 @@ * when update 142 is removed. It is part of the Drupal 4.6 to 4.7 migration. */ function update_fix_watchdog() { - if (drupal_get_installed_schema_version('system') < 142 && !variable_get('update_watchdog_fixed', FALSE)) { + if (drupal_get_installed_schema_version('module', 'system') < 142 && !variable_get('update_watchdog_fixed', FALSE)) { switch ($GLOBALS['db_type']) { case 'pgsql': $ret = array(); @@ -279,16 +279,25 @@ * Perform one update and store the results which will later be displayed on * the finished page. * - * @param $module - * The module whose update will be run. + * @param $type + * Type of item to be updated, e.g., 'module' or 'profile'. + * @param $name + * The item whose update will be run. * @param $number * The update number to run. - * * @return * TRUE if the update was finished. Otherwise, FALSE. */ -function update_data($module, $number) { - $ret = module_invoke($module, 'update_'. $number); +function update_data($type, $name, $number) { + switch($type) { + case 'module': + $ret = module_invoke($name, 'update_'. $number); + break; + default: + $function = $name .'_'. $type .'_update_'. $number; + $ret = function_exists($function) ? $function() : NULL; + break; + } // Assume the update finished unless the update results indicate otherwise. $finished = 1; if (isset($ret['#finished'])) { @@ -300,17 +309,20 @@ if (!isset($_SESSION['update_results'])) { $_SESSION['update_results'] = array(); } - if (!isset($_SESSION['update_results'][$module])) { - $_SESSION['update_results'][$module] = array(); + if (!isset($_SESSION['update_results'][$type])) { + $_SESSION['update_results'][$type] = array(); + } + if (!isset($_SESSION['update_results'][$type][$name])) { + $_SESSION['update_results'][$type][$name] = array(); } - if (!isset($_SESSION['update_results'][$module][$number])) { - $_SESSION['update_results'][$module][$number] = array(); + if (!isset($_SESSION['update_results'][$type][$name][$number])) { + $_SESSION['update_results'][$type][$name][$number] = array(); } - $_SESSION['update_results'][$module][$number] = array_merge($_SESSION['update_results'][$module][$number], $ret); + $_SESSION['update_results'][$type][$name][$number] = array_merge($_SESSION['update_results'][$type][$name][$number], $ret); if ($finished == 1) { // Update the installed version - drupal_set_installed_schema_version($module, $number); + drupal_set_installed_schema_version($type, $name, $number); } return $finished; @@ -338,28 +350,56 @@ '#collapsed' => TRUE, ); + $form['start']['module'] = array( + '#tree' => TRUE, + '#type' => 'fieldset', + '#title' => 'Modules', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); + // Ensure system.module's updates appear first - $form['start']['system'] = array(); + $form['start']['module']['system'] = array(); + + $form['start']['profile'] = array( + '#tree' => TRUE, + '#type' => 'fieldset', + '#title' => 'Profiles', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); - 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; + // Modules and install profiles are the two system item types that support + // updates. + foreach(array('module', 'profile') as $type) { + switch($type) { + case 'module': + $items = module_list(); + break; + case 'profile': + $items = array(drupal_get_installed_profile()); + break; + } + foreach ($items as $name) { + $updates = drupal_get_schema_versions($type, $name); + if ($updates !== FALSE) { + $updates = drupal_map_assoc($updates); + $updates[] = 'No updates available'; + $default = drupal_get_installed_schema_version($type, $name); + foreach (array_keys($updates) as $update) { + if ($update > $default) { + $default = $update; + break; + } } - } - $form['start'][$module] = array( - '#type' => 'select', - '#title' => $module . ' module', - '#default_value' => $default, - '#options' => $updates, - ); + $form['start'][$type][$name] = array( + '#type' => 'select', + '#title' => $name .' '. $type, + '#default_value' => $default, + '#options' => $updates, + ); + } } } @@ -377,14 +417,16 @@ function update_update_page() { // Set the installed version so updates start at the correct place. - foreach ($_POST['edit']['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) { - foreach ($updates as $update) { - if ($update >= $version) { - $_SESSION['update_remaining'][] = array('module' => $module, 'version' => $update); + foreach ($_POST['edit']['start'] as $type => $item) { + foreach ($item as $name => $version) { + drupal_set_installed_schema_version($type, $name, $version - 1); + $updates = drupal_get_schema_versions($type, $name); + $max_version = max($updates); + if ($version <= $max_version) { + foreach ($updates as $update) { + if ($update >= $version) { + $_SESSION['update_remaining'][] = array('type' => $type, 'name' => $name, 'version' => $update); + } } } } @@ -421,7 +463,7 @@ */ function update_do_updates() { while (($update = reset($_SESSION['update_remaining']))) { - $update_finished = update_data($update['module'], $update['version']); + $update_finished = update_data($update['type'], $update['name'], $update['version']); if ($update_finished == 1) { // Dequeue the completed update. unset($_SESSION['update_remaining'][key($_SESSION['update_remaining'])]); @@ -440,11 +482,11 @@ } // When no updates remain, clear the cache. - if (!isset($update['module'])) { + if (!isset($update['type'])) { db_query('DELETE FROM {cache}'); } - return array($percentage, isset($update['module']) ? 'Updating '. $update['module'] .' module' : 'Updating complete'); + return array($percentage, isset($update['name']) ? 'Updating '. $update['name'] .' '. $update['type'] : 'Updating complete'); } /** @@ -515,7 +557,7 @@ } else { $update = reset($_SESSION['update_remaining']); - $output = '

The update process was aborted prematurely while running update #'. $update['version'] .' in '. $update['module'] .'.module. All other errors have been logged. You may need to check the watchdog database table manually.

'; + $output = '

The update process was aborted prematurely while running update #'. $update['version'] .' in '. $update['name'] .'.'. $update['type'] .'. All other errors have been logged. You may need to check the watchdog database table manually.

'; } if ($GLOBALS['access_check'] == FALSE) { @@ -528,23 +570,25 @@ if ($_SESSION['update_results']) { $output .= '
'; $output .= '

The following queries were executed

'; - foreach ($_SESSION['update_results'] as $module => $updates) { - $output .= '

'. $module .' module

'; - foreach ($updates as $number => $queries) { - $output .= '

Update #'. $number .'

'; - $output .= ''; } } $output .= '
'; Index: includes/install.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.inc,v retrieving revision 1.16 diff -u -r1.16 install.inc --- includes/install.inc 23 Aug 2006 08:25:44 -0000 1.16 +++ includes/install.inc 23 Aug 2006 16:50:21 -0000 @@ -20,27 +20,33 @@ define('FILE_NOT_EXECUTABLE', 128); /** - * Initialize the update system by loading all installed module's .install files. + * Initialize the update system by loading all installed modules' and profiles' .install files. */ function drupal_load_updates() { foreach (module_list() as $module) { module_load_install($module); } + drupal_load_profile_install(drupal_get_installed_profile()); } /** - * Returns an array of available schema versions for a module. + * Returns an array of available schema versions for a system item. * - * @param $module - * A module name. + * @param $type + * Type of the item, e.g., 'module' or 'profile'. + * @param $name + * Name of the system item. * @return * If the module has updates, an array of available updates. Otherwise, * FALSE. */ -function drupal_get_schema_versions($module) { +function drupal_get_schema_versions($type, $name) { $functions = get_defined_functions(); foreach ($functions['user'] as $function) { - if (strpos($function, $module .'_update_') === 0) { + // Module update functions are named modulename_update_x(), while other + // system items' update functions are named, e.g., profilename_profile_update(). + $prefix = (($type == 'module') ? $name : $name .'_'. $type) .'_update_'; + if (strpos($function, $prefix) === 0) { $version = substr($function, strlen($module .'_update_')); if (is_numeric($version)) { $updates[] = $version; @@ -54,41 +60,45 @@ } /** - * Returns the currently installed schema version for a module. + * Returns the currently installed schema version for a system item. * - * @param $module - * A module name. + * @param $type + * Type of the item, e.g., 'module' or 'profile'. + * @param $name + * Name of the system item. * @return * The currently installed schema version. */ -function drupal_get_installed_schema_version($module, $reset = FALSE) { - static $versions; +function drupal_get_installed_schema_version($type, $name, $reset = FALSE) { + static $versions = array(); if ($reset) { - unset($versions); + unset($versions[$type]); } - if (!$versions) { - $versions = array(); - $result = db_query("SELECT name, schema_version FROM {system} WHERE type = 'module'"); + if (!$versions[$type]) { + $versions[$type] = array(); + $result = db_query("SELECT name, schema_version FROM {system} WHERE type = '%s'", $type); while ($row = db_fetch_object($result)) { - $versions[$row->name] = $row->schema_version; + $versions[$type][$row->name] = $row->schema_version; } } - return $versions[$module]; + return $versions[$type][$name]; } /** - * Update the installed version information for a module. + * Update the installed version information for a system item. * - * @param $module - * A module name. + * @param $type + * Type of the item, e.g., 'module' or 'profile'. + * @param $name + * Name of the system item. * @param $version * The new schema version. */ -function drupal_set_installed_schema_version($module, $version) { - db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module); +function drupal_set_installed_schema_version($type, $name, $version) { + db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s' AND type = '%s'", $version, $name, $type); } /** @@ -249,16 +259,19 @@ } /** - * Verify a profile for installation. + * Return the name of the currently installed profile. + */ +function drupal_get_installed_profile() { + return db_result(db_query("SELECT name FROM {system} WHERE type = 'profile' AND status = 1")); +} + +/** + * Load a profile's include file. * * @param profile - * Name of profile to verify. - * @return - * The list of modules to install. + * Name of profile to include. */ -function drupal_verify_profile($profile) { - include_once './includes/file.inc'; - +function drupal_load_profile_install($profile) { $profile_file = "./profiles/$profile/$profile.profile"; if (!isset($profile) || !file_exists($profile_file)) { @@ -266,6 +279,20 @@ } require_once($profile_file); +} + +/** + * Verify a profile for installation. + * + * @param profile + * Name of profile to verify. + * @return + * The list of modules to install. + */ +function drupal_verify_profile($profile) { + include_once './includes/file.inc'; + + drupal_load_profile_install($profile); // Get a list of modules required by this profile. $function = $profile .'_profile_modules'; @@ -317,8 +344,29 @@ if (function_exists($function)) { $function(); } + + // Register the profile. + db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $profile, '', 'profile', "profiles/$profile/$profile.profile", 1, 0, 0); + drupal_set_installed_schema_version('profile', $profile, SCHEMA_INSTALLED); + } +/** + * Calls the install function and updates the system table for a given profile. + * + * @param module + * The module to install. + */ +function _drupal_install_profile($profile) { + db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $profile, '', 'profile', "profiles/$profile/$profile.profile", 1, 0, 0); + + if (drupal_get_installed_schema_version('profile', $profile, TRUE) == SCHEMA_UNINSTALLED) { + drupal_load_install_profile($profile); + module_invoke($module, 'install'); + $versions = drupal_get_schema_versions('profile', $profile); + drupal_set_installed_schema_version('profile', $profile, $versions ? max($versions) : SCHEMA_INSTALLED); + } +} /** * Execute the install scripts for a set of modules. Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.349 diff -u -r1.349 system.module --- modules/system/system.module 23 Aug 2006 04:40:57 -0000 1.349 +++ modules/system/system.module 23 Aug 2006 04:57:06 -0000 @@ -1275,7 +1275,7 @@ $new_modules = array(); foreach ($edit['status'] as $key => $choice) { if ($choice) { - if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) { + if (drupal_get_installed_schema_version('module', $key) == SCHEMA_UNINSTALLED) { $new_modules[] = $key; } else {