Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.176 diff -u -p -r1.176 install.php --- install.php 2 Jun 2009 06:58:15 -0000 1.176 +++ install.php 5 Jun 2009 11:58:58 -0000 @@ -642,7 +642,7 @@ function install_tasks($profile, $task) // Install profile modules. if ($task == 'profile-install') { $modules = variable_get('install_profile_modules', array()); - $files = module_rebuild_cache(); + $files = system_get_module_data(); variable_del('install_profile_modules'); $operations = array(); foreach ($modules as $module) { Index: update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.286 diff -u -p -r1.286 update.php --- update.php 2 Jun 2009 06:58:15 -0000 1.286 +++ update.php 5 Jun 2009 11:58:59 -0000 @@ -499,8 +499,8 @@ function update_check_incompatibility($n // Store values of expensive functions for future use. if (empty($themes) || empty($modules)) { - $themes = _system_theme_data(); - $modules = module_rebuild_cache(); + $themes = _system_get_theme_data(); + $modules = system_get_module_data(); } if ($type == 'module' && isset($modules[$name])) { Index: includes/registry.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/registry.inc,v retrieving revision 1.16 diff -u -p -r1.16 registry.inc --- includes/registry.inc 16 May 2009 16:04:42 -0000 1.16 +++ includes/registry.inc 5 Jun 2009 11:58:59 -0000 @@ -40,15 +40,10 @@ function _registry_rebuild() { // Reset the resources cache. _registry_get_resource_name(); - // Get current list of modules and their files. - $modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0); - system_get_files_database($modules, 'module'); // Get the list of files we are going to parse. $files = array(); - foreach ($modules as $module) { + foreach (system_get_module_data() as $module) { if ($module->status) { - // Parse .info file only for enabled modules. - $module->info = drupal_parse_info_file(dirname($module->filepath) . '/' . $module->name . '.info'); $dir = dirname($module->filepath); foreach ($module->info['files'] as $file) { $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.917 diff -u -p -r1.917 common.inc --- includes/common.inc 3 Jun 2009 02:50:21 -0000 1.917 +++ includes/common.inc 5 Jun 2009 11:59:03 -0000 @@ -4529,10 +4529,10 @@ function drupal_flush_all_caches() { // If invoked from update.php, we must not update the theme information in the // database, or this will result in all themes being disabled. if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') { - _system_theme_data(); + _system_get_theme_data(); } else { - system_theme_data(); + system_get_theme_data(); } drupal_theme_rebuild(); Index: includes/install.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.inc,v retrieving revision 1.91 diff -u -p -r1.91 install.inc --- includes/install.inc 24 May 2009 17:39:30 -0000 1.91 +++ includes/install.inc 5 Jun 2009 11:59:03 -0000 @@ -495,7 +495,7 @@ function drupal_verify_profile($profile, * Normally just testing wants to set this to TRUE. */ function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) { - $files = module_rebuild_cache(); + $files = system_get_module_data(); $module_list = array_flip(array_values($module_list)); do { $moved = FALSE; @@ -592,7 +592,7 @@ function drupal_install_system() { ->execute(); // Now that we've installed things properly, bootstrap the full Drupal environment drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); - module_rebuild_cache(); + system_get_module_data(); } /** Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.142 diff -u -p -r1.142 module.inc --- includes/module.inc 24 May 2009 17:39:30 -0000 1.142 +++ includes/module.inc 5 Jun 2009 11:59:03 -0000 @@ -76,75 +76,6 @@ function module_list($refresh = FALSE, $ } /** - * 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, including uninstalled modules. - $files = drupal_system_listing('/\.module$/', 'modules', 'name', 0); - - // Extract current files from database. - system_get_files_database($files, 'module'); - - ksort($files); - - // Set defaults for module info - $defaults = array( - 'dependencies' => array(), - 'dependents' => array(), - 'description' => '', - 'package' => 'Other', - 'version' => NULL, - 'php' => DRUPAL_MINIMUM_PHP, - 'files' => array(), - ); - - foreach ($files as $filepath => $file) { - // Look for the info file. - $file->info = drupal_parse_info_file(dirname($file->filepath) . '/' . $file->name . '.info'); - - // Skip modules that don't provide info. - if (empty($file->info)) { - unset($files[$filepath]); - continue; - } - // Merge in defaults and save. - $files[$filepath]->info = $file->info + $defaults; - - // Invoke hook_system_info_alter() to give installed modules a chance to - // modify the data in the .info files if necessary. - drupal_alter('system_info', $files[$filepath]->info, $files[$filepath]); - - // Update the contents of the system table: - if (isset($file->status) || (isset($file->old_filepath) && $file->old_filepath != $file->filepath)) { - db_update('system') - ->fields(array( - 'info' => serialize($files[$filepath]->info), - 'name' => $file->name, - 'filename' => $file->filepath)) - ->condition('filename', $file->old_filepath) - ->execute(); - } - else { - // This is a new module. - $files[$filepath]->status = 0; - db_insert('system') - ->fields(array( - 'name' => $file->name, - 'info' => serialize($files[$filepath]->info), - 'type' => 'module', - 'filename' => $file->filepath, - 'status' => 0)) - ->execute(); - } - } - $files = _module_build_dependencies($files); - return $files; -} - -/** * Find dependencies any level deep and fill in required by information too. * * @param $files Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.493 diff -u -p -r1.493 theme.inc --- includes/theme.inc 2 Jun 2009 03:57:22 -0000 1.493 +++ includes/theme.inc 5 Jun 2009 11:59:03 -0000 @@ -528,7 +528,7 @@ function list_themes($refresh = FALSE) { } else { // Scan the installation when the database should not be read. - $themes = _system_theme_data(); + $themes = _system_get_theme_data(); } foreach ($themes as $theme) { Index: includes/theme.maintenance.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v retrieving revision 1.29 diff -u -p -r1.29 theme.maintenance.inc --- includes/theme.maintenance.inc 28 May 2009 16:44:05 -0000 1.29 +++ includes/theme.maintenance.inc 5 Jun 2009 11:59:03 -0000 @@ -223,7 +223,7 @@ function template_preprocess_maintenance global $theme; // Retrieve the theme data to list all available regions. - $theme_data = _system_theme_data(); + $theme_data = _system_get_theme_data(); $regions = $theme_data[$theme]->info['regions']; // Get all region content set with drupal_add_region_content(). Index: modules/help/help.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/help/help.admin.inc,v retrieving revision 1.8 diff -u -p -r1.8 help.admin.inc --- modules/help/help.admin.inc 18 Feb 2009 14:28:22 -0000 1.8 +++ modules/help/help.admin.inc 5 Jun 2009 11:59:03 -0000 @@ -47,7 +47,7 @@ function help_page($name) { function help_links_as_list() { $empty_arg = drupal_help_arg(); - $module_info = module_rebuild_cache(); + $module_info = system_get_module_data(); $modules = array(); foreach (module_implements('help', TRUE) as $module) { Index: modules/simpletest/simpletest.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v retrieving revision 1.52 diff -u -p -r1.52 simpletest.module --- modules/simpletest/simpletest.module 30 May 2009 11:17:32 -0000 1.52 +++ modules/simpletest/simpletest.module 5 Jun 2009 11:59:03 -0000 @@ -211,7 +211,7 @@ function simpletest_get_all_tests() { if (!isset($classes)) { require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php'; $files = array(); - foreach (array_keys(module_rebuild_cache()) as $module) { + foreach (array_keys(system_get_module_data()) as $module) { $module_path = drupal_get_path('module', $module); $test = $module_path . "/$module.test"; if (file_exists($test)) { Index: modules/system/system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.152 diff -u -p -r1.152 system.admin.inc --- modules/system/system.admin.inc 2 Jun 2009 06:58:17 -0000 1.152 +++ modules/system/system.admin.inc 5 Jun 2009 11:59:05 -0000 @@ -86,7 +86,7 @@ function system_admin_menu_block_page() */ function system_admin_by_module() { - $modules = module_rebuild_cache(); + $modules = system_get_module_data(); $menu_items = array(); $help_arg = module_exists('help') ? drupal_help_arg() : FALSE; @@ -141,7 +141,7 @@ function system_settings_overview() { function system_themes_form() { drupal_clear_css_cache(); - $themes = system_theme_data(); + $themes = system_get_theme_data(); uasort($themes, 'system_sort_modules_by_info_name'); $status = array(); @@ -325,7 +325,7 @@ function system_theme_settings(&$form_st if ($key) { $settings = theme_get_settings($key); $var = str_replace('/', '_', 'theme_' . $key . '_settings'); - $themes = system_theme_data(); + $themes = system_get_theme_data(); $features = $themes[$key]->info['features']; } else { @@ -580,7 +580,7 @@ function system_modules($form_state = ar node_types_rebuild(); cache_clear_all('schema', 'cache'); // Get current list of modules. - $files = module_rebuild_cache(); + $files = system_get_module_data(); // Remove hidden modules from display list. foreach ($files as $filename => $file) { @@ -761,7 +761,7 @@ function _system_modules_build_row($info * Display confirmation form for required modules. * * @param $modules - * Array of module file objects as returned from module_rebuild_cache(). + * Array of module file objects as returned from system_get_module_data(). * @param $storage * The contents of $form_state['storage']; an array with two * elements: the list of required modules and the list of status @@ -819,7 +819,7 @@ function system_modules_submit($form, &$ // Get a list of all modules, it will be used to find which module requires // which. - $files = module_rebuild_cache(); + $files = system_get_module_data(); // The modules to be enabled. $modules_to_be_enabled = array(); Index: modules/system/system.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v retrieving revision 1.39 diff -u -p -r1.39 system.api.php --- modules/system/system.api.php 4 Jun 2009 03:33:28 -0000 1.39 +++ modules/system/system.api.php 5 Jun 2009 11:59:06 -0000 @@ -530,7 +530,7 @@ function hook_mail_alter(&$message) { /** * Alter the information parsed from module and theme .info files * - * This hook is invoked in module_rebuild_cache() and in system_theme_data(). + * This hook is invoked in _system_get_module_data() and in _system_get_theme_data(). * A module may implement this hook in order to add to or alter the data * generated by reading the .info file with drupal_parse_info_file(). * Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.338 diff -u -p -r1.338 system.install --- modules/system/system.install 4 Jun 2009 03:33:28 -0000 1.338 +++ modules/system/system.install 5 Jun 2009 11:59:09 -0000 @@ -353,7 +353,7 @@ function system_install() { } // Load system theme data appropriately. - system_theme_data(); + system_get_theme_data(); // Inserting uid 0 here confuses MySQL -- the next user might be created as // uid 2 which is not what we want. So we insert the first user here, the @@ -1542,8 +1542,8 @@ function system_update_6008() { db_drop_field($ret, 'system', 'description'); // Rebuild system table contents. - module_rebuild_cache(); - system_theme_data(); + system_get_module_data(); + system_get_theme_data(); return $ret; } @@ -1614,8 +1614,8 @@ function system_update_6012() { */ function system_update_6013() { // Rebuild system table contents. - module_rebuild_cache(); - system_theme_data(); + system_get_module_data(); + system_get_theme_data(); return array(array('success' => TRUE, 'query' => 'Cache rebuilt.')); } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.707 diff -u -p -r1.707 system.module --- modules/system/system.module 4 Jun 2009 03:33:28 -0000 1.707 +++ modules/system/system.module 5 Jun 2009 11:59:09 -0000 @@ -1144,9 +1144,8 @@ function system_get_files_database(&$fil foreach ($result as $file) { if (isset($files[$file->name]) && is_object($files[$file->name])) { $file->filepath = $file->filename; - $file->old_filepath = $file->filepath; foreach ($file as $key => $value) { - if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) { + if (!isset($files[$file->name]->key)) { $files[$file->name]->$key = $value; } } @@ -1155,75 +1154,143 @@ function system_get_files_database(&$fil } /** - * Prepare defaults for themes. + * Updates the records in the system table based on the files array. + * + * @param $files + * An array of files. + * @param $type + * The type of the files. + */ +function system_update_files_database(&$files, $type) { + $result = db_query("SELECT * FROM {system} WHERE type = :type", array(':type' => $type)); + + // Add all files that need to be deleted to a DatabaseCondition. + $delete = db_or(); + foreach ($result as $file) { + if (isset($files[$file->name]) && is_object($files[$file->name])) { + // Keep the old filename from the database in case the file has moved. + $old_filename = $file->filename; + + $updated_fields = array(); + + // Handle info specially, compare the serialized value. + $serialized_info = serialize($files[$file->name]->info); + if ($serialized_info != $file->info) { + $updated_fields['info'] = $serialized_info; + } + unset($file->info); + + // Scan remaining fields to find only the updated values. + foreach ($file as $key => $value) { + if (isset($files[$file->name]->$key) && $files[$file->name]->$key != $value) { + $updated_fields[$key] = $files[$file->name]->$key; + } + } + + // Update the record. + if (count($updated_fields)) { + db_update('system') + ->fields($updated_fields) + ->condition('filename', $old_filename) + ->execute(); + } + + // Indiciate that the file exists already. + $files[$file->name]->exists = TRUE; + } + else { + // File is not found in file system, so delete record from the system table. + $delete->condition('filename', $file->filename); + } + } + + if (count($delete) > 0) { + // Delete all missing files from the system table + db_delete('system') + ->condition($delete) + ->execute(); + } + + // All remaining files are not in the system table, so we need to add them. + $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info')); + foreach($files as &$file) { + if (isset($file->exists)) { + unset($file->exists); + } + else { + $query->values(array( + 'filename' => $file->filepath, + 'name' => $file->name, + 'type' => $type, + 'owner' => isset($file->owner) ? $file->owner : '', + 'info' => serialize($file->info), + )); + $file->type = $type; + $file->status = 0; + $file->schema_version = -1; + } + } + $query->execute(); +} + +/** + * Helper function to scan and collect module .info data. * * @return - * An array of default themes settings. + * An associative array of module information. */ -function system_theme_default() { - return array( - 'regions' => array( - 'left' => 'Left sidebar', - 'right' => 'Right sidebar', - 'content' => 'Content', - 'header' => 'Header', - 'footer' => 'Footer', - 'highlight' => 'Highlighted content', - 'help' => 'Help', - ), +function _system_get_module_data() { + // Find modules + $modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0); + + // Set defaults for module info. + $defaults = array( + 'dependencies' => array(), + 'dependents' => array(), 'description' => '', - 'features' => array( - 'comment_user_picture', - 'comment_user_verification', - 'favicon', - 'logo', - 'name', - 'node_user_picture', - 'search', - 'slogan', - 'main_menu', - 'secondary_menu', - ), - 'screenshot' => 'screenshot.png', + 'version' => NULL, 'php' => DRUPAL_MINIMUM_PHP, ); + + // Read info files for each module. + foreach ($modules as $key => $module) { + // Look for the info file. + $module->info = drupal_parse_info_file(dirname($module->filepath) . '/' . $module->name . '.info'); + + // Skip modules that don't provide info. + if (empty($module->info)) { + unset($modules[$key]); + continue; + } + + // Merge in defaults and save. + $modules[$key]->info = $module->info + $defaults; + + // Invoke hook_system_info_alter() to give installed modules a chance to + // modify the data in the .info files if necessary. + drupal_alter('system_info', $modules[$key]->info, $modules[$key]); + } + + return $modules; } /** - * Collect data about all currently available themes. + * Collect data about all currently available modules. * * @return - * Array of all available themes and their data. + * Array of all available modules and their data. */ -function system_theme_data() { - // Scan the installation theme .info files and their engines. - $themes = _system_theme_data(); - - // Extract current files from database. - system_get_files_database($themes, 'theme'); - - db_delete('system') - ->condition('type', 'theme') - ->execute(); - - $query = db_insert('system')->fields(array('name', 'owner', 'info', 'type', 'filename', 'status')); - foreach ($themes as $theme) { - if (!isset($theme->owner)) { - $theme->owner = ''; - } - - $query->values(array( - 'name' => $theme->name, - 'owner' => $theme->owner, - 'info' => serialize($theme->info), - 'type' => 'theme', - 'filename' => $theme->filename, - 'status' => isset($theme->status) ? $theme->status : 0, - )); - } - $query->execute(); - - return $themes; +function system_get_module_data() { + $modules = &drupal_static(__FUNCTION__, array()); + if (!empty($modules)) { + return $modules; + } + $modules = _system_get_module_data(); + ksort($modules); + system_get_files_database($modules, 'module'); + system_update_files_database($modules, 'module'); + $modules = _module_build_dependencies($modules); + return $modules; } /** @@ -1232,7 +1299,7 @@ function system_theme_data() { * @return * An associative array of themes information. */ -function _system_theme_data() { +function _system_get_theme_data() { static $themes_info = array(); if (empty($themes_info)) { @@ -1241,7 +1308,37 @@ function _system_theme_data() { // Find theme engines $engines = drupal_system_listing('/\.engine$/', 'themes/engines'); - $defaults = system_theme_default(); + // Set defaults for theme info. + $defaults = array( + 'regions' => array( + 'left' => 'Left sidebar', + 'right' => 'Right sidebar', + 'content' => 'Content', + 'header' => 'Header', + 'footer' => 'Footer', + 'highlight' => 'Highlighted content', + 'help' => 'Help', + ), + 'description' => '', + 'features' => array( + 'comment_user_picture', + 'favicon', + 'mission', + 'logo', + 'name', + 'node_user_picture', + 'search', + 'slogan', + 'main_menu', + 'secondary_menu', + ), + 'stylesheets' => array( + 'all' => array('style.css') + ), + 'scripts' => array('script.js'), + 'screenshot' => 'screenshot.png', + 'php' => DRUPAL_MINIMUM_PHP, + ); $sub_themes = array(); // Read info files for each theme @@ -1325,6 +1422,20 @@ function _system_theme_data() { } /** + * Collect data about all currently available themes. + * + * @return + * Array of all available themes and their data. + */ +function system_get_theme_data() { + $themes = _system_get_theme_data(); + ksort($themes); + system_get_files_database($themes, 'theme'); + system_update_files_database($themes, 'theme'); + return $themes; +} + +/** * Recursive function to find the top level base theme. Themes can inherit * templates and function implementations from earlier themes. * Index: modules/update/update.compare.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/update/update.compare.inc,v retrieving revision 1.18 diff -u -p -r1.18 update.compare.inc --- modules/update/update.compare.inc 24 May 2009 17:39:35 -0000 1.18 +++ modules/update/update.compare.inc 5 Jun 2009 11:59:09 -0000 @@ -36,8 +36,8 @@ function update_get_projects() { $projects = update_project_cache('update_project_projects'); if (empty($projects)) { // Still empty, so we have to rebuild the cache. - _update_process_info_list($projects, module_rebuild_cache(), 'module'); - _update_process_info_list($projects, system_theme_data(), 'theme'); + _update_process_info_list($projects, system_get_module_data(), 'module'); + _update_process_info_list($projects, system_get_theme_data(), 'theme'); // Cache the site's project data for at most 1 hour. _update_cache_set('update_project_projects', $projects, REQUEST_TIME + 3600); }