From 38e4c1ae91545d0c45885966cad694660010068d Mon Sep 17 00:00:00 2001 From: Steven Wittens <steven@10.no-reply.drupal.org> Date: Thu, 3 Aug 2006 01:02:51 +0000 Subject: [PATCH] #76209: (Eaton et al) - Make installer code integrate better with module.inc / system.module - Fix schema version bug when installing core --- includes/bootstrap.inc | 7 ++- includes/install.inc | 117 ++++++++++++++++++----------------- includes/module.inc | 92 +++++++++++++++++++++++++++ install.php | 3 +- modules/system/system.module | 56 +++++------------ modules/user/user.module | 4 -- sites/default/settings.php | 2 +- 7 files changed, 175 insertions(+), 106 deletions(-) diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 826818a553dd..fd4f7bd54be9 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -192,11 +192,14 @@ function conf_init() { * @param $filename * The filename of the item if it is to be set explicitly rather * than by consulting the database. + * @param $check_db + * Allows the database search to be skipped (useful for pre-bootstrap + * checks where configuration paths must still be respected). * * @return * The filename of the requested item. */ -function drupal_get_filename($type, $name, $filename = NULL) { +function drupal_get_filename($type, $name, $filename = NULL, $check_db = TRUE) { static $files = array(); if (!isset($files[$type])) { @@ -209,7 +212,7 @@ function drupal_get_filename($type, $name, $filename = NULL) { elseif (isset($files[$type][$name])) { // nothing } - elseif (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file)) { + elseif ($check_db && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { $files[$type][$name] = $file; } else { diff --git a/includes/install.inc b/includes/install.inc index d3aa86a4f21d..68593e86f7be 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -24,10 +24,7 @@ */ function drupal_load_updates() { foreach (module_list() as $module) { - $install_file = './'. drupal_get_path('module', $module) .'/'. $module .'.install'; - if (is_file($install_file)) { - include_once $install_file; - } + module_load_install($module); } } @@ -252,14 +249,14 @@ function drupal_get_install_files($module_list = array()) { } /** - * Install a profile. + * Verify a profile for installation. * * @param profile - * Name of profile to install. + * Name of profile to verify. + * @return + * The list of modules to install. */ -function drupal_install_profile($profile) { - global $db_type; - +function drupal_verify_profile($profile) { include_once './includes/file.inc'; $profile_file = "./profiles/$profile.profile"; @@ -270,75 +267,84 @@ function drupal_install_profile($profile) { require_once($profile_file); - // Get a list of modules absolutely required by Drupal. - $bootstrap_list = array('system'); - // Get a list of modules required by this profile. $function = $profile .'_profile_modules'; - $module_list = $function(); - - // If anyone has added modules that we automatically install, filter them out. - $module_list = array_diff($module_list, $bootstrap_list); - + $module_list = array_merge(array('system'), $function()); + // Verify that all required modules exist. - $bootstrap_modules = drupal_find_modules($bootstrap_list); - $profile_modules = drupal_find_modules($module_list); + $modules_present = TRUE; + foreach ($module_list as $module) { + $module_path = dirname(drupal_get_filename('module', $module, NULL, FALSE)); + if (!$module_path) { + drupal_set_message(st('The %module module is required but was not found. Please move it into the <em>modules</em> subdirectory.', array('%module' => $module)), 'error'); + $modules_present = FALSE; + } + } + + return $modules_present ? $module_list : NULL; +} - // Install the essential system modules and bootstrap Drupal. - drupal_install_modules($bootstrap_list); +/** + * Install a profile (i.e. a set of modules) from scratch. + * The profile must be verified first using drupal_verify_profile(). + * + * @param profile + * The name of the profile to install. + * @param module_list + * An array of modules to install. + */ +function drupal_install_profile($profile, $module_list) { + // The system module is a special case; we can't bootstrap until it's + // installed, so we can't use the normal installation function. + $module_list = array_diff($module_list, array('system')); + + $system_path = dirname(drupal_get_filename('module', 'system', NULL, FALSE)); + require_once './' . $system_path . '/system.install'; + module_invoke('system', 'install'); + $system_versions = drupal_get_schema_versions('system'); + $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; + db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', 'module', '', 1, 0, 0, %d)", $system_path . '/system.module', 'system', $system_version); + + // Now that we've installed things properly, bootstrap the full Drupal environment drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // Install schemas for profile and all its modules. + module_rebuild_cache(); + drupal_install_modules($module_list); + + // And now, run the profile's install function. $function = $profile .'_install'; if (function_exists($function)) { $function(); } - - drupal_install_modules($module_list); - - // Enable the modules required by the profile. - db_query("DELETE FROM {system} WHERE type = 'module'"); - $modules = array_merge($bootstrap_modules, $profile_modules); - foreach ($modules as $module) { - db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', 'module', '', 1, 0, 0, 0)", $module->filename, $module->name); - } } /** - * Finds the file paths for a set of modules. + * Execute the install scripts for a set of modules. * * @param module_list - * The modules to locate. - * @return - * An array containing file information for the modules. + * The modules to install. */ -function drupal_find_modules($module_list = array()) { - $modules = array(); - foreach ($module_list as $current) { - $module = file_scan_directory('./modules', "^$current.module$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0); - if (empty($module)) { - drupal_set_message(st('The %module module is required but was not found. Please move the file %file into the <em>modules</em> subdirectory.', array('%module' => $current, '%file' => $current .'.module')), 'error'); - } - else { - $modules = array_merge($modules, $module); - } +function drupal_install_modules($module_list = array()) { + foreach ($module_list as $module) { + drupal_install_module($module); } - return $modules; } /** - * Execute the install scripts for a set of modules. + * Calls the install function and updates the system table for a given module. * - * @param module_list - * The modules to install. + * @param module + * The module to install. */ -function drupal_install_modules($module_list = array()) { - // Get a list of all .install files. - $installs = drupal_get_install_files($module_list); - foreach ($installs as $install) { - require_once $install->filename; - module_invoke($install->name, 'install'); +function drupal_install_module($module) { + if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { + module_load_install($module); + module_invoke($module, 'install'); + $versions = drupal_get_schema_versions($module); + drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); + module_enable($module); } } @@ -349,9 +355,6 @@ function drupal_install_modules($module_list = array()) { * The file to check for. * @param $mask * An optional bitmask created from various FILE_* constants. - * @param $message_type - * The type of message to create, can be error or status. Passed on to drupal_set_message as second parameter. - * Set to NULL to not output any messages at all. * @param $type * The type of file. Can be file (default), dir, or link. * @return diff --git a/includes/module.inc b/includes/module.inc index 5a05283b67c2..b4136aaa3529 100644 --- a/includes/module.inc +++ b/includes/module.inc @@ -87,6 +87,47 @@ function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_ return $list; } +/** + * Rebuild the database cache of module files. + * + * @return + * The array of filesystem objects used to rebuild the cache. + */ +function module_rebuild_cache() { + // Get current list of modules + $files = system_listing('\.module$', 'modules', 'name', 0); + + // Extract current files from database. + system_get_files_database($files, 'module'); + + ksort($files); + + foreach ($files as $filename => $file) { + drupal_get_filename('module', $file->name, $file->filename); + drupal_load('module', $file->name); + + // log the critical hooks implemented by this module + $bootstrap = 0; + foreach (bootstrap_hooks() as $hook) { + if (module_hook($file->name, $hook)) { + $bootstrap = 1; + break; + } + } + + // Update the contents of the system table: + if (isset($file->status) || (isset($file->old_filename) && $file->old_filename != $file->filename)) { + db_query("UPDATE {system} SET description = '%s', name = '%s', filename = '%s', bootstrap = %d WHERE filename = '%s'", $file->description, $file->name, $file->filename, $bootstrap, $file->old_filename); + } + else { + // This is a new module. + db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->description, 'module', $file->filename, $file->status, $file->throttle, $bootstrap); + } + } + + return $files; +} + /** * Determine whether a given module exists. * @@ -100,6 +141,57 @@ function module_exist($module) { return array_key_exists($module, $list); } +/** + * Load a module's installation hooks. + */ +function module_load_install($module) { + // Make sure the installation API is available + include_once './includes/install.inc'; + + $install_file = './'. drupal_get_path('module', $module) .'/'. $module .'.install'; + if (is_file($install_file)) { + include_once $install_file; + } +} + +/** + * Enable a given module. + * + * @param $module + * Enable a given module and call its enable hook. + */ +function module_enable($module) { + $existing = db_fetch_object(db_query("SELECT name, status FROM {system} WHERE type = 'module' AND name = '%s'", $module)); + if ($existing->status === '0') { + module_load_install($module); + db_query("UPDATE {system} SET status = 1, throttle = 0 WHERE type = 'module' AND name = '%s'", $module); + drupal_load('module', $module); + module_invoke($module, 'enable'); + return TRUE; + } + else { + return FALSE; + } +} + +/** + * Disable a given module and call its disable hook. + * + * @param $module + * The name of the module (without the .module extension). + */ +function module_disable($module) { + if (module_exist($module)) { + module_load_install($module); + module_invoke($module, 'disable'); + db_query("UPDATE {system} SET status = 0, throttle = 0 WHERE type = 'module' AND name = '%s'", $module); + return TRUE; + } + else { + return FALSE; + } +} + /** * @defgroup hooks Hooks * @{ diff --git a/install.php b/install.php index 3b190db3dd9f..ed1636af6742 100644 --- a/install.php +++ b/install.php @@ -62,7 +62,8 @@ function install_main() { } // Perform actual installation defined in the profile. - drupal_install_profile($profile); + $modules = drupal_verify_profile($profile); + drupal_install_profile($profile, $modules); // Warn about settings.php permissions risk $settings_file = './'. conf_path() .'/settings.php'; diff --git a/modules/system/system.module b/modules/system/system.module index 56950f5ebcd5..e19ed56e5423 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -1154,12 +1154,7 @@ function system_themes_submit($form_id, $values) { */ function system_modules() { // Get current list of modules - $files = system_listing('\.module$', 'modules', 'name', 0); - - // Extract current files from database. - system_get_files_database($files, 'module'); - - ksort($files); + $files = module_rebuild_cache(); foreach ($files as $filename => $file) { drupal_get_filename('module', $file->name, $file->filename); @@ -1176,27 +1171,8 @@ function system_modules() { if ($file->throttle) { $throttle[] = $file->name; } - - // log the critical hooks implemented by this module - $bootstrap = 0; - foreach (bootstrap_hooks() as $hook) { - if (module_hook($file->name, $hook)) { - $bootstrap = 1; - break; - } - } - - // Update the contents of the system table: - if (isset($file->status) || (isset($file->old_filename) && $file->old_filename != $file->filename)) { - db_query("UPDATE {system} SET description = '%s', name = '%s', bootstrap = %d, filename = '%s' WHERE filename = '%s'", $file->description, $file->name, $bootstrap, $file->filename, $file->old_filename); - } - else { - // This is a new module. - db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->description, 'module', $file->filename, $file->status, $file->throttle, $bootstrap); - } } - // Handle status checkboxes, including overriding the generated // checkboxes for required modules. $form['status'] = array('#type' => 'checkboxes', '#default_value' => $status, '#options' => $options); @@ -1246,16 +1222,26 @@ function theme_system_modules($form) { function system_modules_submit($form_id, $edit) { - db_query("UPDATE {system} SET status = 0, throttle = 0 WHERE type = 'module'"); - + include_once './includes/install.inc'; $new_modules = array(); foreach ($edit['status'] as $key => $choice) { if ($choice) { - db_query("UPDATE {system} SET status = 1 WHERE type = 'module' AND name = '%s'", $key); - if (!module_exist($key)) { + if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) { $new_modules[] = $key; } + else { + module_enable($key); + } } + else { + module_disable($key); + } + } + + module_list(TRUE, FALSE); + + foreach ($new_modules as $module) { + drupal_install_module($module); } if (is_array($edit['throttle'])) { @@ -1266,18 +1252,6 @@ function system_modules_submit($form_id, $edit) { } } - module_list(TRUE, FALSE); - - include './includes/install.inc'; - foreach ($new_modules as $module) { - // Set the installed schema version for newly-enabled modules - $versions = drupal_get_schema_versions($module); - if (drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED) { - drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); - module_invoke($module, 'install'); - } - } - menu_rebuild(); drupal_set_message(t('The configuration options have been saved.')); diff --git a/modules/user/user.module b/modules/user/user.module index a4d120e72f5b..e95a8921a081 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -1207,10 +1207,6 @@ function user_register_submit($form_id, $form_values) { drupal_set_message(t('<p>Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the <a href="%settings">site information settings page</a>.</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass, '%settings' => url('admin/settings/site-information')))); user_authenticate($account->name, trim($pass)); - // Set the installed schema version of the system module to the most recent version. - include_once './includes/install.inc'; - drupal_set_installed_schema_version('system', max(drupal_get_schema_versions('system'))); - return 'user/1/edit'; } else { diff --git a/sites/default/settings.php b/sites/default/settings.php index 5fe047700c84..15f4083265b7 100644 --- a/sites/default/settings.php +++ b/sites/default/settings.php @@ -84,7 +84,7 @@ * $db_url = 'mysqli://username:password@localhost/databasename'; * $db_url = 'pgsql://username:password@localhost/databasename'; */ -$db_url = 'mysql://username:password@localhost/databasename'; +$db_url = 'mysql://bonsai_tree:leafy@localhost/bonsai_install'; $db_prefix = ''; /** -- GitLab