Commit 1f9077ee authored by Dries's avatar Dries

- Patch #147000 by Berdir: unify and rewrite module_rebuild_cache() and system_theme_data().

parent 36e3d552
...@@ -4555,10 +4555,10 @@ function drupal_flush_all_caches() { ...@@ -4555,10 +4555,10 @@ function drupal_flush_all_caches() {
// If invoked from update.php, we must not update the theme information in the // If invoked from update.php, we must not update the theme information in the
// database, or this will result in all themes being disabled. // database, or this will result in all themes being disabled.
if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') { if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
_system_theme_data(); _system_get_theme_data();
} }
else { else {
system_theme_data(); system_get_theme_data();
} }
drupal_theme_rebuild(); drupal_theme_rebuild();
......
...@@ -495,7 +495,7 @@ function drupal_verify_profile($profile, $locale) { ...@@ -495,7 +495,7 @@ function drupal_verify_profile($profile, $locale) {
* Normally just testing wants to set this to TRUE. * Normally just testing wants to set this to TRUE.
*/ */
function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) { 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)); $module_list = array_flip(array_values($module_list));
do { do {
$moved = FALSE; $moved = FALSE;
...@@ -592,7 +592,7 @@ function drupal_install_system() { ...@@ -592,7 +592,7 @@ function drupal_install_system() {
->execute(); ->execute();
// Now that we've installed things properly, bootstrap the full Drupal environment // Now that we've installed things properly, bootstrap the full Drupal environment
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
module_rebuild_cache(); system_get_module_data();
} }
/** /**
......
...@@ -75,75 +75,6 @@ function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) { ...@@ -75,75 +75,6 @@ function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) {
return $list; 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. * Find dependencies any level deep and fill in required by information too.
* *
......
...@@ -528,7 +528,7 @@ function list_themes($refresh = FALSE) { ...@@ -528,7 +528,7 @@ function list_themes($refresh = FALSE) {
} }
else { else {
// Scan the installation when the database should not be read. // Scan the installation when the database should not be read.
$themes = _system_theme_data(); $themes = _system_get_theme_data();
} }
foreach ($themes as $theme) { foreach ($themes as $theme) {
......
...@@ -223,7 +223,7 @@ function template_preprocess_maintenance_page(&$variables) { ...@@ -223,7 +223,7 @@ function template_preprocess_maintenance_page(&$variables) {
global $theme; global $theme;
// Retrieve the theme data to list all available regions. // 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']; $regions = $theme_data[$theme]->info['regions'];
// Get all region content set with drupal_add_region_content(). // Get all region content set with drupal_add_region_content().
......
...@@ -642,7 +642,7 @@ function install_tasks($profile, $task) { ...@@ -642,7 +642,7 @@ function install_tasks($profile, $task) {
// Install profile modules. // Install profile modules.
if ($task == 'profile-install') { if ($task == 'profile-install') {
$modules = variable_get('install_profile_modules', array()); $modules = variable_get('install_profile_modules', array());
$files = module_rebuild_cache(); $files = system_get_module_data();
variable_del('install_profile_modules'); variable_del('install_profile_modules');
$operations = array(); $operations = array();
foreach ($modules as $module) { foreach ($modules as $module) {
......
...@@ -47,7 +47,7 @@ function help_page($name) { ...@@ -47,7 +47,7 @@ function help_page($name) {
function help_links_as_list() { function help_links_as_list() {
$empty_arg = drupal_help_arg(); $empty_arg = drupal_help_arg();
$module_info = module_rebuild_cache(); $module_info = system_get_module_data();
$modules = array(); $modules = array();
foreach (module_implements('help', TRUE) as $module) { foreach (module_implements('help', TRUE) as $module) {
......
...@@ -211,7 +211,7 @@ function simpletest_get_all_tests() { ...@@ -211,7 +211,7 @@ function simpletest_get_all_tests() {
if (!isset($classes)) { if (!isset($classes)) {
require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php'; require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
$files = array(); $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); $module_path = drupal_get_path('module', $module);
$test = $module_path . "/$module.test"; $test = $module_path . "/$module.test";
if (file_exists($test)) { if (file_exists($test)) {
......
...@@ -86,7 +86,7 @@ function system_admin_menu_block_page() { ...@@ -86,7 +86,7 @@ function system_admin_menu_block_page() {
*/ */
function system_admin_by_module() { function system_admin_by_module() {
$modules = module_rebuild_cache(); $modules = system_get_module_data();
$menu_items = array(); $menu_items = array();
$help_arg = module_exists('help') ? drupal_help_arg() : FALSE; $help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
...@@ -141,7 +141,7 @@ function system_settings_overview() { ...@@ -141,7 +141,7 @@ function system_settings_overview() {
function system_themes_form() { function system_themes_form() {
drupal_clear_css_cache(); drupal_clear_css_cache();
$themes = system_theme_data(); $themes = system_get_theme_data();
uasort($themes, 'system_sort_modules_by_info_name'); uasort($themes, 'system_sort_modules_by_info_name');
$status = array(); $status = array();
...@@ -325,7 +325,7 @@ function system_theme_settings(&$form_state, $key = '') { ...@@ -325,7 +325,7 @@ function system_theme_settings(&$form_state, $key = '') {
if ($key) { if ($key) {
$settings = theme_get_settings($key); $settings = theme_get_settings($key);
$var = str_replace('/', '_', 'theme_' . $key . '_settings'); $var = str_replace('/', '_', 'theme_' . $key . '_settings');
$themes = system_theme_data(); $themes = system_get_theme_data();
$features = $themes[$key]->info['features']; $features = $themes[$key]->info['features'];
} }
else { else {
...@@ -580,7 +580,7 @@ function system_modules($form_state = array()) { ...@@ -580,7 +580,7 @@ function system_modules($form_state = array()) {
node_types_rebuild(); node_types_rebuild();
cache_clear_all('schema', 'cache'); cache_clear_all('schema', 'cache');
// Get current list of modules. // Get current list of modules.
$files = module_rebuild_cache(); $files = system_get_module_data();
// Remove hidden modules from display list. // Remove hidden modules from display list.
foreach ($files as $filename => $file) { foreach ($files as $filename => $file) {
...@@ -761,7 +761,7 @@ function _system_modules_build_row($info, $extra) { ...@@ -761,7 +761,7 @@ function _system_modules_build_row($info, $extra) {
* Display confirmation form for required modules. * Display confirmation form for required modules.
* *
* @param $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 * @param $storage
* The contents of $form_state['storage']; an array with two * The contents of $form_state['storage']; an array with two
* elements: the list of required modules and the list of status * elements: the list of required modules and the list of status
...@@ -819,7 +819,7 @@ function system_modules_submit($form, &$form_state) { ...@@ -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 // Get a list of all modules, it will be used to find which module requires
// which. // which.
$files = module_rebuild_cache(); $files = system_get_module_data();
// The modules to be enabled. // The modules to be enabled.
$modules_to_be_enabled = array(); $modules_to_be_enabled = array();
......
...@@ -530,7 +530,7 @@ function hook_mail_alter(&$message) { ...@@ -530,7 +530,7 @@ function hook_mail_alter(&$message) {
/** /**
* Alter the information parsed from module and theme .info files * 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 * 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(). * generated by reading the .info file with drupal_parse_info_file().
* *
......
...@@ -353,7 +353,7 @@ function system_install() { ...@@ -353,7 +353,7 @@ function system_install() {
} }
// Load system theme data appropriately. // 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 // 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 // uid 2 which is not what we want. So we insert the first user here, the
...@@ -1542,8 +1542,8 @@ function system_update_6008() { ...@@ -1542,8 +1542,8 @@ function system_update_6008() {
db_drop_field($ret, 'system', 'description'); db_drop_field($ret, 'system', 'description');
// Rebuild system table contents. // Rebuild system table contents.
module_rebuild_cache(); system_get_module_data();
system_theme_data(); system_get_theme_data();
return $ret; return $ret;
} }
...@@ -1614,8 +1614,8 @@ function system_update_6012() { ...@@ -1614,8 +1614,8 @@ function system_update_6012() {
*/ */
function system_update_6013() { function system_update_6013() {
// Rebuild system table contents. // Rebuild system table contents.
module_rebuild_cache(); system_get_module_data();
system_theme_data(); system_get_theme_data();
return array(array('success' => TRUE, 'query' => 'Cache rebuilt.')); return array(array('success' => TRUE, 'query' => 'Cache rebuilt.'));
} }
......
...@@ -1159,9 +1159,8 @@ function system_get_files_database(&$files, $type) { ...@@ -1159,9 +1159,8 @@ function system_get_files_database(&$files, $type) {
foreach ($result as $file) { foreach ($result as $file) {
if (isset($files[$file->name]) && is_object($files[$file->name])) { if (isset($files[$file->name]) && is_object($files[$file->name])) {
$file->filepath = $file->filename; $file->filepath = $file->filename;
$file->old_filepath = $file->filepath;
foreach ($file as $key => $value) { 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; $files[$file->name]->$key = $value;
} }
} }
...@@ -1170,75 +1169,139 @@ function system_get_files_database(&$files, $type) { ...@@ -1170,75 +1169,139 @@ function system_get_files_database(&$files, $type) {
} }
/** /**
* Prepare defaults for themes. * Updates the records in the system table based on the files array.
* *
* @return * @param $files
* An array of default themes settings. * An array of files.
* @param $type
* The type of the files.
*/ */
function system_theme_default() { function system_update_files_database(&$files, $type) {
return array( $result = db_query("SELECT * FROM {system} WHERE type = :type", array(':type' => $type));
'regions' => array(
'left' => 'Left sidebar', // Add all files that need to be deleted to a DatabaseCondition.
'right' => 'Right sidebar', $delete = db_or();
'content' => 'Content', foreach ($result as $file) {
'header' => 'Header', if (isset($files[$file->name]) && is_object($files[$file->name])) {
'footer' => 'Footer', // Keep the old filename from the database in case the file has moved.
'highlight' => 'Highlighted content', $old_filename = $file->filename;
'help' => 'Help',
), $updated_fields = array();
'description' => '',
'features' => array( // Handle info specially, compare the serialized value.
'comment_user_picture', $serialized_info = serialize($files[$file->name]->info);
'comment_user_verification', if ($serialized_info != $file->info) {
'favicon', $updated_fields['info'] = $serialized_info;
'logo', }
'name', unset($file->info);
'node_user_picture',
'search', // Scan remaining fields to find only the updated values.
'slogan', foreach ($file as $key => $value) {
'main_menu', if (isset($files[$file->name]->$key) && $files[$file->name]->$key != $value) {
'secondary_menu', $updated_fields[$key] = $files[$file->name]->$key;
), }
'screenshot' => 'screenshot.png', }
'php' => DRUPAL_MINIMUM_PHP,
); // 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 * @return
* Array of all available themes and their data. * An associative array of module information.
*/ */
function system_theme_data() { function _system_get_module_data() {
// Scan the installation theme .info files and their engines. // Find modules
$themes = _system_theme_data(); $modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
// Extract current files from database. // Set defaults for module info.
system_get_files_database($themes, 'theme'); $defaults = array(
'dependencies' => array(),
'dependents' => array(),
'description' => '',
'version' => NULL,
'php' => DRUPAL_MINIMUM_PHP,
);
db_delete('system') // Read info files for each module.
->condition('type', 'theme') foreach ($modules as $key => $module) {
->execute(); // 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')); // Skip modules that don't provide info.
foreach ($themes as $theme) { if (empty($module->info)) {
if (!isset($theme->owner)) { unset($modules[$key]);
$theme->owner = ''; continue;
} }
$query->values(array( // Merge in defaults and save.
'name' => $theme->name, $modules[$key]->info = $module->info + $defaults;
'owner' => $theme->owner,
'info' => serialize($theme->info), // Invoke hook_system_info_alter() to give installed modules a chance to
'type' => 'theme', // modify the data in the .info files if necessary.
'filename' => $theme->filename, drupal_alter('system_info', $modules[$key]->info, $modules[$key]);
'status' => isset($theme->status) ? $theme->status : 0,
));
} }
$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() { ...@@ -1247,7 +1310,7 @@ function system_theme_data() {
* @return * @return
* An associative array of themes information. * An associative array of themes information.
*/ */
function _system_theme_data() { function _system_get_theme_data() {
static $themes_info = array(); static $themes_info = array();
if (empty($themes_info)) { if (empty($themes_info)) {
...@@ -1256,7 +1319,37 @@ function _system_theme_data() { ...@@ -1256,7 +1319,37 @@ function _system_theme_data() {
// Find theme engines // Find theme engines
$engines = drupal_system_listing('/\.engine$/', 'themes/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(); $sub_themes = array();
// Read info files for each theme // Read info files for each theme
...@@ -1339,6 +1432,20 @@ function _system_theme_data() { ...@@ -1339,6 +1432,20 @@ function _system_theme_data() {
return $themes_info; 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 * Recursive function to find the top level base theme. Themes can inherit
* templates and function implementations from earlier themes. * templates and function implementations from earlier themes.
......
...@@ -36,8 +36,8 @@ function update_get_projects() { ...@@ -36,8 +36,8 @@ function update_get_projects() {
$projects = update_project_cache('update_project_projects'); $projects = update_project_cache('update_project_projects');
if (empty($projects)) { if (empty($projects)) {
// Still empty, so we have to rebuild the cache.