diff --git a/includes/common.inc b/includes/common.inc index 35a1ccf46c11af27ee151b27b44669c05aafeb9a..5f5f9b66e255cf49c674daca9ef094e97a82a664 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -4555,10 +4555,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(); diff --git a/includes/install.inc b/includes/install.inc index 5f296477bb90c05e05d35b6c89205f2365dd23ae..03ee3e4bda80acb81bc544299f3fdbdcbb2c708e 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -495,7 +495,7 @@ function drupal_verify_profile($profile, $locale) { * 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(); } /** diff --git a/includes/module.inc b/includes/module.inc index aea3c8f9688d801b5d7eb80eb822d1444211d65f..e0b3ceaad04cea3c773037b92b60b21eaf1403e1 100644 --- a/includes/module.inc +++ b/includes/module.inc @@ -75,75 +75,6 @@ function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) { 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, 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. * diff --git a/includes/theme.inc b/includes/theme.inc index f82e9b00d1d70ea4931033c73acf5e2353c852ec..a723e6fe3de51c732f33c6ffd4ab70922f599432 100644 --- a/includes/theme.inc +++ b/includes/theme.inc @@ -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) { diff --git a/includes/theme.maintenance.inc b/includes/theme.maintenance.inc index 915a5794bed27c6309b298d36df1cbd9b40e5460..3267e1d01b48149d5954c78bc8aea6fd5ee26dac 100644 --- a/includes/theme.maintenance.inc +++ b/includes/theme.maintenance.inc @@ -223,7 +223,7 @@ function template_preprocess_maintenance_page(&$variables) { 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(). diff --git a/install.php b/install.php index d122cbab8b8de3c6f7fff5bceabe4df4b419dce9..447e38266bd3a03f10ff129692d832c74ab50f02 100644 --- a/install.php +++ b/install.php @@ -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) { diff --git a/modules/help/help.admin.inc b/modules/help/help.admin.inc index f3f0041c3ddb3e1d1967baab198d3a44ab07da29..3de153de6356cb6d93281e7bd1d0b6d8d0a7b33e 100644 --- a/modules/help/help.admin.inc +++ b/modules/help/help.admin.inc @@ -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) { diff --git a/modules/simpletest/simpletest.module b/modules/simpletest/simpletest.module index 91d82aa86882d230554980457c5a89c468a2a3a3..1300c24169d60b04f7a5468f4fab18c53a656e45 100644 --- a/modules/simpletest/simpletest.module +++ b/modules/simpletest/simpletest.module @@ -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)) { diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index 1ff8bdf9e3624e7f6ee368c589cf593e4f869bbf..5fe1c2424c41de6c6b998df9b4ddffcb7604c5e1 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -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_state, $key = '') { 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 = array()) { 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, $extra) { * 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, &$form_state) { // 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(); diff --git a/modules/system/system.api.php b/modules/system/system.api.php index 0fa5aeea350d13f7b24229aa65dbdecf135db436..0efcedbc3536136a8e8f1da5fd8b8c23f27380da 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -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(). * diff --git a/modules/system/system.install b/modules/system/system.install index 8f856e1d79bf836d33450cab63d4e05c86059da8..5a68e7007e10783971803fbe6b086b55560d048b 100644 --- a/modules/system/system.install +++ b/modules/system/system.install @@ -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.')); } diff --git a/modules/system/system.module b/modules/system/system.module index 767981c82efedd39956b5f42b8cfc955b4ac5f4e..4635a3d3f76d8a831fa9e911914211d7a29cef00 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -1159,9 +1159,8 @@ function system_get_files_database(&$files, $type) { 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; } } @@ -1170,75 +1169,139 @@ function system_get_files_database(&$files, $type) { } /** - * Prepare defaults for themes. - * - * @return - * An array of default themes settings. + * 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_theme_default() { - return 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', - 'comment_user_verification', - 'favicon', - 'logo', - 'name', - 'node_user_picture', - 'search', - 'slogan', - 'main_menu', - 'secondary_menu', - ), - 'screenshot' => 'screenshot.png', - 'php' => DRUPAL_MINIMUM_PHP, - ); +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(); } /** - * Collect data about all currently available themes. + * Helper function to scan and collect module .info data. * * @return - * Array of all available themes and their data. + * An associative array of module information. */ -function system_theme_data() { - // Scan the installation theme .info files and their engines. - $themes = _system_theme_data(); +function _system_get_module_data() { + // Find modules + $modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0); - // Extract current files from database. - system_get_files_database($themes, 'theme'); + // Set defaults for module info. + $defaults = array( + 'dependencies' => array(), + 'dependents' => array(), + 'description' => '', + 'version' => NULL, + 'php' => DRUPAL_MINIMUM_PHP, + ); - db_delete('system') - ->condition('type', 'theme') - ->execute(); + // 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'); - $query = db_insert('system')->fields(array('name', 'owner', 'info', 'type', 'filename', 'status')); - foreach ($themes as $theme) { - if (!isset($theme->owner)) { - $theme->owner = ''; + // Skip modules that don't provide info. + if (empty($module->info)) { + unset($modules[$key]); + continue; } - $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, - )); + // 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]); } - $query->execute(); - return $themes; + return $modules; +} + +/** + * Collect data about all currently available modules. + * + * @return + * Array of all available modules and their data. + */ +function system_get_module_data() { + $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; } /** @@ -1247,7 +1310,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)) { @@ -1256,7 +1319,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 @@ -1339,6 +1432,20 @@ function _system_theme_data() { return $themes_info; } +/** + * 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. diff --git a/modules/update/update.compare.inc b/modules/update/update.compare.inc index e2186e7f296260692ea3025a46d9832277b70910..c198c7d49f2546c9c9b91100ae7431ed2e40ba1e 100644 --- a/modules/update/update.compare.inc +++ b/modules/update/update.compare.inc @@ -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'); // Allow other modules to alter projects before fetching and comparing. drupal_alter('update_projects', $projects); // Cache the site's project data for at most 1 hour. diff --git a/update.php b/update.php index a0fb6d9248c259227fa04c6de33ee9b3346fd34b..95ff18d5157d4cb77f76213addaa360d70c2b17d 100644 --- a/update.php +++ b/update.php @@ -499,8 +499,8 @@ function update_check_incompatibility($name, $type = 'module') { // 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])) {