diff -u b/core/includes/module.inc b/core/includes/module.inc --- b/core/includes/module.inc +++ b/core/includes/module.inc @@ -1165,5 +1165,5 @@ } else { - KeyValueFactory::get('system.module.schema')->set($module, $weight); + KeyValueFactory::get('system.module.weight')->set($module, $weight); } } diff -u b/core/modules/field/field.module b/core/modules/field/field.module --- b/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -339,7 +339,10 @@ * required if there are any active fields of that type. */ function field_system_info_alter(&$info, $file, $type) { - if ($type == 'module' && module_hook($file->name, 'field_info')) { + // module_hook() relies on the very function this is called from: + // system_rebuild_module_data(). + $function = $file->name . '_field_info'; + if ($type == 'module' && function_exists($function)) { try { $fields = field_read_fields(array('module' => $file->name), array('include_deleted' => TRUE)); } diff -u b/core/modules/system/system.module b/core/modules/system/system.module --- b/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2684,12 +2684,20 @@ $modules = array(); // If this is the first time, start with all modules. if (empty($module_store)) { + // During a test run no modules can move, no info files can change so + // speed up test runs by only finding and parsing once. + if (drupal_valid_test_ua() && ($data = state()->get(__FUNCTION__))) { + $module_store = $data['module_store']; + $profiles_seen = $data['profiles_seen']; + } + } + if (empty($module_store)) { // Find modules and installation profiles. As these are files, they can't // change within a request. However, it does depend on $profile. $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0); } - // If this profile is not yet seen, add it. - if (empty($profiles_seen[$profile])) { + // If this profile is not yet parsed, add it. + if (!isset($profiles_seen[$profile])) { $profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles', 'name', 0); // Include the install profile in modules that are loaded. $modules[$profile] = $profiles[$profile]; @@ -2748,6 +2756,12 @@ } // Store the processed modules. $module_store += $modules; + if (drupal_valid_test_ua()) { + state()->set(__FUNCTION__, array( + 'module_store' => $module_store, + 'profiles_seen' => $profiles_seen, + )); + } } $modules = $module_store; // Do not return the non-active profile modules. Typically at most one: when @@ -2776,27 +2790,25 @@ $modules = _system_rebuild_module_data(); ksort($modules); // Add status, weight and schema. - $enabled_modules = module_config()->get(); - $all_data = array( - 'weight' => KeyValueFactory::get('system.module.weight')->getAll(), - 'schema_version' => KeyValueFactory::get('system.module.schema')->getAll(), - ); foreach ($modules as $module => $record) { - // Set defaults. + // Set defaults and name. + $record->name = $module; $record->weight = 0; $record->status = 0; $record->schema_version = SCHEMA_UNINSTALLED; - // Copy schema version for installed and nonzero weight for disabled. - foreach ($all_data as $key => $data) { - if (isset($data[$module])) { - $record->$key = $data[$module]; - } - } - // Copy enabled weight and status. - if (isset($enabled_modules[$module])) { - $record->status = 1; - $record->weight = $enabled_modules[$module]; - } + } + // Installed schema versions. + foreach (KeyValueFactory::get('system.module.schema')->getAll() as $module => $schema_version) { + $modules[$module]->schema_version = $schema_version; + } + // Disabled weights. + foreach (KeyValueFactory::get('system.module.weight')->getAll() as $module => $weight) { + $modules[$module]->weight = $weight; + } + // Enabled status and weights. + foreach (module_config()->get() as $module => $weight) { + $modules[$module]->status = 1; + $modules[$module]->weight = $weight; } $modules = _module_build_dependencies($modules); // As noted above, system_list_reset() deletes $modules_cache so the order @@ -2804,18 +2816,23 @@ system_list_reset(); $modules_cache['data'] = $modules; } - if (isset($modules_cache['data']) && !isset($modules_cache['info_alter']) && drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) { + if (!isset($modules_cache['info_alter']) && drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) { // Invoke hook_system_info_alter() to give installed modules a chance to // modify the data in the .info files if necessary. It is not possible to // use drupal_alter() which relies on system_list() which relies on this // function. $type = 'module'; - foreach (module_config()->get() as $module) { + // It is not impossible a function resets the modules cache. Keep it. + $modules = $modules_cache['data']; + foreach (module_config()->get() as $module => $weight) { $function = $module .'_system_info_alter'; if (function_exists($function)) { - $function($modules_cache['data'][$module]->info, $modules_cache['data'][$module], $type); + foreach ($modules as $record) { + $function($record->info, $record, $type); + } } } + $modules_cache['data'] = $modules; $profile = drupal_get_profile(); if (isset($modules_cache['data'][$profile])) { // The install profile is required, if it's a valid module.