diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index c81ccf1..8ec2539 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -888,9 +888,10 @@ function drupal_get_filename($type, $name, $filename = NULL) { else { // Verify that we have an keyvalue service before using it. This is required // because this function is called during installation. + // @todo Inject database connection into KeyValueStore\DatabaseStorage. if (drupal_container()->hasDefinition('keyvalue') && function_exists('db_query')) { try { - $file_list = state()->get('system.' . $type . '_file_list'); + $file_list = state()->get('system.' . $type . '.files'); if ($file_list && isset($file_list[$name]) && file_exists(DRUPAL_ROOT . '/' . $file_list[$name])) { $files[$type][$name] = $file_list[$name]; } @@ -901,7 +902,6 @@ function drupal_get_filename($type, $name, $filename = NULL) { // completely. } } - // Fallback to searching the filesystem if the database could not find the // file or the file returned by the database is not found. if (!isset($files[$type][$name])) { @@ -2101,15 +2101,14 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) { ); // Not drupal_static(), because the only legitimate API to control this is to // call drupal_bootstrap() with a new phase parameter. - static $final_phase = -1; + static $final_phase; // Not drupal_static(), because it's impossible to roll back to an earlier // bootstrap state. static $stored_phase = -1; - // When not recursing, store the phase name so it's not forgotten during - // recursion. Additionally, ensure that $final_phase is never rolled back to an - // earlier bootstrap state. - if ($new_phase && $phase > $final_phase) { + // When not recursing, store the phase name so it's not forgotten while + // recursing. + if ($new_phase) { $final_phase = $phase; } if (isset($phase)) { @@ -2390,7 +2389,7 @@ function _drupal_bootstrap_page_header() { * @see drupal_bootstrap() */ function drupal_get_bootstrap_phase() { - return drupal_bootstrap(NULL, FALSE); + return drupal_bootstrap(); } /** @@ -2461,6 +2460,8 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) { $container ->register('config.storage.staging', 'Drupal\Core\Config\FileStorage') ->addArgument(config_get_config_directory(CONFIG_STAGING_DIRECTORY)); + + // KeyValueStore. $container ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory'); } @@ -2479,7 +2480,7 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) { * @return Drupal\Core\KeyValueStore\KeyValueStoreInterface */ function state() { - return drupal_container()->get('keyvalue')->get('state.storage'); + return drupal_container()->get('keyvalue')->get('state'); } /** diff --git a/core/includes/common.inc b/core/includes/common.inc index df744b3..b3dc9cb 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -6824,12 +6824,18 @@ function drupal_flush_all_caches() { // None currently; kept if any static caches need to be reset in the future. // Rebuild module and theme data. - system_list_reset(); + system_rebuild_module_data(); + system_rebuild_theme_data(); // Ensure that all modules that are currently supposed to be enabled are // actually loaded. module_load_all(); + // Update the list of bootstrap modules. + // Allows developers to get new hook_boot() implementations registered without + // having to write a hook_update_N() function. + _system_update_bootstrap_status(); + // Rebuild the schema and cache a fully-built schema based on new module data. // This is necessary for any invocation of index.php, because setting cache // table entries requires schema information and that occurs during bootstrap diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index e57fadb..ac94175 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -322,9 +322,9 @@ function install_begin_request(&$install_state) { $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') ->addArgument(new Reference('config.storage')) ->addArgument(new Reference('dispatcher')); + // @todo State service is gone; needs keyvalue + NullStorage replacement. $container - ->register('state.storage', 'Drupal\Core\KeyValueStore\DatabaseStorage') - ->addArgument('state'); + ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory'); drupal_container($container); } diff --git a/core/includes/install.inc b/core/includes/install.inc index 860ac3d..c242cbc 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -6,7 +6,6 @@ */ use Drupal\Core\Database\Database; -use Drupal\Core\KeyValueStore\KeyValueFactory; use Drupal\locale\Gettext; /** @@ -409,18 +408,24 @@ function drupal_install_system() { $system_path = drupal_get_path('module', 'system'); require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; - if ($system_versions = drupal_get_schema_versions('system')) { - drupal_container() - ->get('keyvalue') - ->get('system.module.schema') - ->set('system', max($system_versions)); - } + $system_versions = drupal_get_schema_versions('system'); + $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; + drupal_container() + ->get('keyvalue') + ->get('system.schema') + ->set('system', $system_version); + + // Enable System module. + // System module needs to be enabled and the system/module lists need to be + // reset first in order to allow config_install_default_config() to invoke + // config import callbacks. + // @todo Installation profiles may override the system.module config object. + // @todo Config\InstallStorage should actually throw an exception on write, why does this work? config('system.module') - ->set('system', 0) + ->set('enabled.system', 0) ->save(); - // Clear out module list and hook implementation statics before calling - // system_rebuild_theme_data(). + // Clear out module list and hook implementation statics. system_list_reset(); module_list_reset(); module_implements_reset(); diff --git a/core/includes/module.inc b/core/includes/module.inc index 30fa096..17f087c 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -6,23 +6,32 @@ */ use Drupal\Component\Graph\Graph; -use Drupal\Core\KeyValueStore\KeyValueFactory; /** - * Loads all the modules that have been enabled in the system table. + * Loads all enabled modules. * * @param bool $bootstrap * Whether to load only the reduced set of modules loaded in "bootstrap mode" * for cached pages. See bootstrap.inc. Pass NULL to only check the current * status without loading of modules. + * @param bool $reset + * (optional) Internal use only. Whether to reset the internal statically + * cached flag of whether modules have been loaded. If TRUE, all modules are + * (re)loaded in the same call. Used by the testing framework to override and + * persist a limited module list for the duration of a unit test (in which no + * module system exists). * * @return bool * A Boolean indicating whether all modules have been loaded. This means all * modules; the load status of bootstrap modules cannot be checked. */ -function module_load_all($bootstrap = FALSE) { +function module_load_all($bootstrap = FALSE, $reset = FALSE) { static $has_run = FALSE; + if ($reset) { + $has_run = FALSE; + } + // Unless $boostrap is NULL, load the requested set of modules. if (isset($bootstrap) && !$has_run) { $type = $bootstrap ? 'bootstrap' : 'module_enabled'; @@ -123,6 +132,11 @@ function module_list_reset() { * * @see module_list() * @see list_themes() + * + * @todo There are too many layers/levels of caching involved for system_list() + * data. Consider to add a config($name, $cache = TRUE) argument to allow + * callers like this to force-disable any possible configuration storage + * caching, or some other direct access to circumvent it/take it over. */ function system_list($type) { $lists = &drupal_static(__FUNCTION__); @@ -135,20 +149,22 @@ function system_list($type) { return $lists['bootstrap']; } if ($cached = cache('bootstrap')->get('bootstrap_modules')) { - $lists['bootstrap'] = $cached->data; - // To avoid a separate database lookup for the filepath, prime the - // drupal_get_filename() static cache for bootstrap modules only. - // The rest is stored separately to keep the bootstrap module cache small. - foreach ($lists['bootstrap'] as $module => $filename) { - _system_list_warm('module', $module, $filename); - } + $bootstrap_list = $cached->data; } else { - $lists = _system_list_prepare(); + $bootstrap_list = state()->get('system.module.bootstrap') ?: array(); + cache('bootstrap')->set('bootstrap_modules', $bootstrap_list); + } + // To avoid a separate database lookup for the filepath, prime the + // drupal_get_filename() static cache for bootstrap modules only. + // The rest is stored separately to keep the bootstrap module cache small. + foreach ($bootstrap_list as $name => $filename) { + drupal_classloader_register($name, dirname($filename)); + drupal_get_filename('module', $name, $filename); } // We only return the module names here since module_list() doesn't need // the filename itself. - $lists['bootstrap'] = array_keys($lists['bootstrap']); + $lists['bootstrap'] = array_keys($bootstrap_list); } // Otherwise build the list for enabled modules and themes. elseif (!isset($lists['module_enabled'])) { @@ -156,130 +172,94 @@ function system_list($type) { $lists = $cached->data; } else { - $lists = _system_list_prepare(); - $lists['bootstrap'] = array_keys($lists['bootstrap']); - } - foreach ($lists['filepaths'] as $item) { - _system_list_warm($item['type'], $item['name'], $item['filepath']); - } - } - - return $lists[$type]; -} - -/** - * Prepares the system list data structure. - * - * @return - * An associative array of modules and themes, keyed by list type: bootstrap, - * module_enabled, theme, filepaths. - */ -function _system_list_prepare() { - // The module name (rather than the filename) is used as the fallback - // weighting in order to guarantee consistent behavior across different - // Drupal installations, which might have modules installed in different - // locations in the file system. The ordering here must also be - // consistent with the one used in module_implements(). - $enabled_themes = config('system.theme')->get(); - $enabled_modules = config('system.module')->get(); - _system_list_warm('module', 'system', 'core/modules/system.module', TRUE); - - $module_file_list = state()->get('system.module_file_list'); - $theme_data = state()->get('system.themes'); - // As themes do not need to be installed to be used there is an issue during - // installation. The state entry for system.themes does not exist and we need - // theme data in order for installation to work. This will be resolved by - // http://drupal.org/node/1067408. - if (empty($theme_data)) { - $theme_data = system_rebuild_theme_data(FALSE); - } - $lists = array( - 'bootstrap' => array(), - 'module_enabled' => array(), - 'theme' => array(), - 'filepaths' => array(), - ); - foreach ($theme_data as $key => $theme) { - $lists['theme'][$key] = $theme; - $status = isset($enabled_themes[$key]); - $lists['theme'][$key]->status = $status; - $lists['theme'][$key]->name = $key; - // Build a list of filenames so drupal_get_filename can use it. - if ($status) { - $lists['filepaths'][] = array( - 'type' => 'theme', - 'name' => $key, - 'filepath' => $theme->filename + $lists = array( + 'module_enabled' => array(), + 'theme' => array(), + 'filepaths' => array(), ); - } - } - foreach ($lists['theme'] as $key => $theme) { - if (!empty($theme->info['base theme'])) { - // Make a list of the theme's base themes. - require_once DRUPAL_ROOT . '/core/includes/theme.inc'; - $lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key); - // Don't proceed if there was a problem with the root base theme. - if (!current($lists['theme'][$key]->base_themes)) { - continue; - } - // Determine the root base theme. - $base_key = key($lists['theme'][$key]->base_themes); - // Add to the list of sub-themes for each of the theme's base themes. - foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) { - $lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name']; + // The module name (rather than the filename) is used as the fallback + // weighting in order to guarantee consistent behavior across different + // Drupal installations, which might have modules installed in different + // locations in the file system. The ordering here must also be + // consistent with the one used in module_implements(). + $enabled_modules = config('system.module')->get('enabled'); + $module_files = state()->get('system.module.files'); + foreach ($enabled_modules as $name => $weight) { + // Build a list of all enabled modules. + $lists['module_enabled'][$name] = $name; + // Build a list of filenames so drupal_get_filename can use it. + $lists['filepaths'][] = array( + 'type' => 'module', + 'name' => $name, + 'filepath' => $module_files[$name], + ); } - // Add the base theme's theme engine info. - $lists['theme'][$key]->info['engine'] = $lists['theme'][$base_key]->info['engine']; - } - else { - // A plain theme is its own base theme. - $base_key = $key; - } - // Set the theme engine prefix. - $lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine']; - } - foreach ($enabled_modules as $name => $weight) { - // Build a list of all enabled modules. - $lists['module_enabled'][$name] = $name; - $filename = $module_file_list[$name]; - // Build a list of filenames so drupal_get_filename can use it. - $lists['filepaths'][] = array( - 'type' => 'module', - 'name' => $name, - 'filepath' => $filename, - ); - _system_list_warm('module', $name, $filename, TRUE); - foreach (bootstrap_hooks() as $hook) { - if (function_exists($name .'_' . $hook)) { - $lists['bootstrap'][$name] = $filename; + // Build a list of themes. + $enabled_themes = config('system.theme')->get('enabled'); + //$theme_files = state()->get('system.theme.files'); + // @todo Themes include all themes, including disabled/uninstalled. This + // system.theme.data state will go away entirely as soon as themes have + // a proper installation status. + // @see http://drupal.org/node/1067408 + $theme_data = state()->get('system.theme.data'); + if (empty($theme_data)) { + // system_list() may be called from _drupal_bootstrap_code() and + // module_load_all(), in which case system.module is not loaded yet. + // Prevent a filesystem scan in drupal_load() and include it directly. + require_once DRUPAL_ROOT . '/core/modules/system/system.module'; + $theme_data = system_rebuild_theme_data(); + } + foreach ($theme_data as $name => $theme) { + $theme->status = (int) isset($enabled_themes[$name]); + $lists['theme'][$name] = $theme; + // Build a list of filenames so drupal_get_filename can use it. + if (isset($enabled_themes[$name])) { + $lists['filepaths'][] = array( + 'type' => 'theme', + 'name' => $name, + 'filepath' => $theme->filename, + ); + } + } + // @todo Move into list_themes(). Read info for a particular requested + // theme from state instead. + foreach ($lists['theme'] as $key => $theme) { + if (!empty($theme->info['base theme'])) { + // Make a list of the theme's base themes. + require_once DRUPAL_ROOT . '/core/includes/theme.inc'; + $lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key); + // Don't proceed if there was a problem with the root base theme. + if (!current($lists['theme'][$key]->base_themes)) { + continue; + } + // Determine the root base theme. + $base_key = key($lists['theme'][$key]->base_themes); + // Add to the list of sub-themes for each of the theme's base themes. + foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) { + $lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name']; + } + // Add the base theme's theme engine info. + $lists['theme'][$key]->info['engine'] = $lists['theme'][$base_key]->info['engine']; + } + else { + // A plain theme is its own base theme. + $base_key = $key; + } + // Set the theme engine prefix. + $lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine']; } + cache('bootstrap')->set('system_list', $lists); + } + // To avoid a separate database lookup for the filepath, prime the + // drupal_get_filename() static cache with all enabled modules and themes. + foreach ($lists['filepaths'] as $item) { + drupal_get_filename($item['type'], $item['name'], $item['filepath']); + drupal_classloader_register($item['name'], dirname($item['filepath'])); } } - cache('bootstrap')->set('system_list', $lists); - cache('bootstrap')->set('bootstrap_modules', $lists['bootstrap']); - - return $lists; -} -/** - * Prepares a module for loading and optionally calls drupal_load(). - * - * @param string $type - * The type of the extension (i.e. theme, theme_engine, module, profile). - * @param string $name - * The name of the extension. - * @param string $filename - * The filename of the extension. - * @param bool $load - * (optional) Call drupal_load() for the extension. Defaults to FALSE. - */ -function _system_list_warm($type, $name, $filename, $load = FALSE) { - drupal_classloader_register($name, dirname($filename)); - drupal_get_filename($type, $name, $filename); - if ($load) { - drupal_load($type, $name); - } + return $lists[$type]; } /** @@ -291,6 +271,14 @@ function system_list_reset() { drupal_static_reset('list_themes'); cache('bootstrap')->deleteMultiple(array('bootstrap_modules', 'system_list')); cache()->delete('system_info'); + // Remove last known theme data state. + // This causes system_list() to call system_rebuild_theme_data() on its next + // invocation. When enabling a module that implements hook_system_info_alter() + // to inject a new (testing) theme or manipulate an existing theme, then that + // will cause system_list_reset() to be called, but theme data is not + // necessarily rebuilt afterwards. + // @todo Obsolete with proper installation status for themes. + state()->delete('system.theme.data'); } /** @@ -399,7 +387,7 @@ function module_load_include($type, $module, $name = NULL) { } /** - * Loads an include file for each module enabled in the {system} table. + * Loads an include file for each enabled module. */ function module_load_all_includes($type, $name = NULL) { $modules = module_list(); @@ -445,28 +433,27 @@ function module_load_all_includes($type, $name = NULL) { * @see hook_modules_enabled() */ function module_enable($module_list, $enable_dependencies = TRUE) { - // Get all module data so we can find dependencies, sort and copy to the - // installed modules config. - $all_modules = system_rebuild_module_data(); if ($enable_dependencies) { + // Get all module data so we can find dependencies and sort. + $module_data = system_rebuild_module_data(); // Create an associative array with weights as values. $module_list = array_flip(array_values($module_list)); while (list($module) = each($module_list)) { - if (!isset($all_modules[$module])) { + if (!isset($module_data[$module])) { // This module is not found in the filesystem, abort. return FALSE; } - if ($all_modules[$module]->status) { + if ($module_data[$module]->status) { // Skip already enabled modules. unset($module_list[$module]); continue; } - $module_list[$module] = $all_modules[$module]->sort; + $module_list[$module] = $module_data[$module]->sort; // Add dependencies to the list, with a placeholder weight. // The new modules will be processed as the while loop continues. - foreach (array_keys($all_modules[$module]->requires) as $dependency) { + foreach (array_keys($module_data[$module]->requires) as $dependency) { if (!isset($module_list[$dependency])) { $module_list[$dependency] = 0; } @@ -488,24 +475,24 @@ function module_enable($module_list, $enable_dependencies = TRUE) { $modules_installed = array(); $modules_enabled = array(); - $schema_store = drupal_container()->get('keyvalue')->get('system.module.schema'); + $schema_store = drupal_container()->get('keyvalue')->get('system.schema'); + $module_config = config('system.module'); + $disabled_config = config('system.module.disabled'); foreach ($module_list as $module) { - $config = config('system.module'); - $disabled_config = config('system.module.disabled'); // Only process modules that are not already enabled. $enabled = TRUE; $weight = 0; if (!$schema_store->get($module)) { $enabled = FALSE; } - elseif (!$config->get($module)) { + elseif (!$module_config->get("enabled.$module")) { $enabled = FALSE; $weight = $disabled_config->get($module); } if (!$enabled) { - $config - ->set($module, $weight) - ->setData(module_config_sort($config->get())) + $module_config + ->set("enabled.$module", $weight) + ->set('enabled', module_config_sort($module_config->get('enabled'))) ->save(); if ($weight) { $disabled_config @@ -519,6 +506,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) { // Refresh the module list to include it. system_list_reset(); module_implements_reset(); + _system_update_bootstrap_status(); // Refresh the schema to include it. drupal_get_schema(NULL, TRUE); // Update the theme registry to include it. @@ -624,20 +612,18 @@ function module_disable($module_list, $disable_dependents = TRUE) { $invoke_modules = array(); + $module_config = config('system.module'); + $disabled_config = config('system.module.disabled'); foreach ($module_list as $module) { if (module_exists($module)) { - $config = config('system.module'); - $disabled_config = config('system.module.disabled'); module_load_install($module); module_invoke($module, 'disable'); - if ($weight = $config->get($module)) { - $disabled_config - ->set($module, $weight) - ->save(); - } - $config - ->clear($module) - ->setData(module_config_sort($config->get())) + $disabled_config + ->set($module, $module_config->get($module)) + ->save(); + $module_config + ->clear("enabled.$module") + ->set('enabled', module_config_sort($module_config->get('enabled'))) ->save(); $invoke_modules[] = $module; watchdog('system', '%module module disabled.', array('%module' => $module), WATCHDOG_INFO); @@ -652,6 +638,7 @@ function module_disable($module_list, $disable_dependents = TRUE) { // Invoke hook_modules_disabled before disabling modules, // so we can still call module hooks to get information. module_invoke_all('modules_disabled', $invoke_modules); + _system_update_bootstrap_status(); // Update the theme registry to remove the newly-disabled module. drupal_theme_rebuild(); } @@ -706,7 +693,7 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE) } $storage = drupal_container()->get('config.storage'); - $schema_store = drupal_container()->get('keyvalue')->get('system.module.schema'); + $schema_store = drupal_container()->get('keyvalue')->get('system.schema'); $disabled_config = config('system.module.disabled'); foreach ($module_list as $module) { // Uninstall the module. @@ -1197,36 +1184,29 @@ function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { /** * Sets weight of a particular module. * + * The weight of uninstalled modules cannot be changed. + * * @param string $module * The name of the module (without the .module extension). * @param int $weight * An integer representing the weight of the module. */ function module_set_weight($module, $weight) { - $config = config('system.module'); - - // If the module is enabled it will be in the system.module config file. - if ($config->get($module) !== NULL) { - $config - ->set($module, $weight) - ->setData(module_config_sort($config->get())) + // Update the module weight in the config file that contains it. + $module_config = config('system.module'); + if ($module_config->get("enabled.$module") !== NULL) { + $module_config + ->set("enabled.$module", $weight) + ->set('enabled', module_config_sort($module_config->get('enabled'))) ->save(); + return; } - // Before writing to the system.module.disabled file ensure that the module - // has been previously enabled. - else if (drupal_container()->get('keyvalue')->get('system.module.schema')->get($module) !== FALSE) { - $config_disabled = config('system.module.disabled'); - // Only save non-zero weights to the system.module.disabled config file. - if ($weight) { - $config_disabled - ->set($module, $weight) - ->save(); - } - else { - $config_disabled - ->clear($module) - ->save(); - } + $disabled_config = config('system.module.disabled'); + if ($disabled_config->get($module) !== NULL) { + $disabled_config + ->set($module, $weight) + ->save(); + return; } } diff --git a/core/includes/schema.inc b/core/includes/schema.inc index b9ec5ea..f46739c 100644 --- a/core/includes/schema.inc +++ b/core/includes/schema.inc @@ -7,7 +7,6 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Database\Database; -use Drupal\Core\KeyValueStore\KeyValueFactory; use Drupal\Core\Utility\SchemaCache; /** @@ -16,6 +15,16 @@ */ /** + * Indicates that a module has not been installed yet. + */ +const SCHEMA_UNINSTALLED = -1; + +/** + * Indicates that a module has been installed. + */ +const SCHEMA_INSTALLED = 0; + +/** * Gets the schema definition of a table, or the whole database schema. * * The returned schema will include any modifications made by any @@ -157,7 +166,7 @@ function drupal_get_schema_versions($module) { * @param string $module * A module name. * @param bool $reset - * Set to TRUE after modifying the system table. + * Set to TRUE after installing or uninstalling an extension. * @param bool $array * Set to TRUE if you want to get information about all modules in the * system. @@ -174,8 +183,8 @@ function drupal_get_installed_schema_version($module, $reset = FALSE, $array = F } if (!$versions) { - if (!$versions = drupal_container()->get('keyvalue')->get('system.module.schema')->getAll()) { - $versions= array(); + if (!$versions = drupal_container()->get('keyvalue')->get('system.schema')->getAll()) { + $versions = array(); } } @@ -196,7 +205,7 @@ function drupal_get_installed_schema_version($module, $reset = FALSE, $array = F * The new schema version. */ function drupal_set_installed_schema_version($module, $version) { - drupal_container()->get('keyvalue')->get('system.module.schema')->set($module, $version); + drupal_container()->get('keyvalue')->get('system.schema')->set($module, $version); // Reset the static cache of module schema versions. drupal_get_installed_schema_version(NULL, TRUE); } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d57b323..06e99fb 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1412,19 +1412,19 @@ function theme_render_template($template_file, $variables) { */ function theme_enable($theme_list) { drupal_clear_css_cache(); - $config = config('system.theme'); + $theme_config = config('system.theme'); + $disabled_themes = config('system.theme.disabled'); foreach ($theme_list as $key) { - // The value is not used, it needs to be consistent with - // config('system.module') which uses the value for weight so set all of - // them to the same value. 1 looks like 'enabled' so let's use that. - $config->set($key, 1); + // The value is not used; the weight is ignored for themes currently. + $theme_config->set("enabled.$key", 0); + $disabled_themes->clear($key); // Install default configuration of the theme. config_install_default_config('theme', $key); } - $config->save(); + $theme_config->save(); + $disabled_themes->save(); - system_list_reset(); - system_rebuild_theme_data(TRUE); + list_themes(TRUE); menu_router_rebuild(); drupal_theme_rebuild(); @@ -1449,11 +1449,15 @@ function theme_disable($theme_list) { drupal_clear_css_cache(); - $config = config('system.theme'); + $theme_config = config('system.theme'); + $disabled_themes = config('system.theme.disabled'); foreach ($theme_list as $key) { - $config->clear($key); + // The value is not used; the weight is ignored for themes currently. + $theme_config->clear("enabled.$key"); + $disabled_themes->set($key, 0); } - $config->save(); + $theme_config->save(); + $disabled_themes->save(); list_themes(TRUE); menu_router_rebuild(); diff --git a/core/includes/update.inc b/core/includes/update.inc index e36b9ef..1dc1548 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -18,32 +18,28 @@ * Upgrades from Drupal 7 to Drupal 8 require that Drupal 7 be running * the most recent version, or the upgrade could fail. We can't easily * check the Drupal 7 version once the update process has begun, so instead - * we check the schema version of system.module in the system table. + * we check the schema version of system.module. */ const REQUIRED_D7_SCHEMA_VERSION = '7069'; /** - * Disable any items in the {system} table that are not core compatible. + * Disables any extensions that are incompatible with the current core version. */ function update_fix_compatibility() { foreach (array('module', 'theme') as $type) { $config = config("system.$type"); $save = FALSE; - foreach ($config->get() as $name => $weight) { + foreach ($config->get('enabled') as $name => $weight) { if (update_check_incompatibility($name, $type)) { - $config->clear($name); + $config->clear("enabled.$name"); $save = TRUE; } } if ($save) { if ($type == 'module') { - $config - ->setData(module_config_sort($config->get())) - ->save(); - } - else { - $config->save(); + $config->set('enabled', module_config_sort($config->get('enabled'))); } + $config->save(); } } } @@ -141,6 +137,10 @@ function update_prepare_d8_bootstrap() { ); update_extra_requirements($requirements); + // @todo update.php stages seem to be completely screwed up; the initial + // requirements check is not supposed to change the system. All of the + // following code seems to have been mistakenly/unknowingly added here and + // does not belong into update_prepare_d8_bootstrap(). if ($has_required_schema) { if (!db_table_exists('key_value')) { $specs = array( @@ -176,44 +176,81 @@ function update_prepare_d8_bootstrap() { // process. drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES); + // Update the 'language_default' system variable, if configured. + // Required to run before drupal_install_config_directories(), since that + // triggers a call into system_stream_wrappers(), which calls t(), which + // calls into language_default(). + $language_default = variable_get('language_default'); + if (!empty($language_default) && (isset($language_default->langcode) || isset($language_default->language))) { + if (!isset($language_default->langcode)) { + $language_default->langcode = $language_default->language; + } + unset($language_default->language); + // In D8, the 'language_default' is not anymore an object, but an array, + // so make sure that the new value that is saved into this variable is an + // array. + variable_set('language_default', (array) $language_default); + } + + // @todo Race-condition: drupal_install_config_directories() calls into + // install_ensure_config_directory(), which calls into + // file_prepare_directory(), whichs calls into file_get_stream_wrappers(), + // which attempts to invoke hooks with a non-existing module/hook system. + include_once DRUPAL_ROOT . '/core/includes/module.inc'; + $module_list['system']['filename'] = 'core/modules/system/system.module'; + module_list(NULL, $module_list); + require_once DRUPAL_ROOT . '/' . $module_list['system']['filename']; // Ensure the configuration directories exist and are writable, or create // them. If the directories have not been specified in settings.php and // created manually already, and either directory cannot be created by the // web server, an exception will be thrown, halting the update. drupal_install_config_directories(); - $configs = array( - 'module' => config('system.module'), - 'disabled_module' => config('system.module.disabled'), - 'theme' => config('system.theme'), - ); - $schema_store = drupal_container()->get('keyvalue')->get('system.module.schema'); + + $module_config = config('system.module'); + $disabled_modules = config('system.module.disabled'); + $theme_config = config('system.theme'); + $disabled_themes = config('system.theme.disabled'); + $schema_store = drupal_container()->get('keyvalue')->get('system.schema'); + + // Load system.module, because update_prepare_d8_bootstrap() is called in + // the initial minimal update.php bootstrap that performs the core + // requirements check. + require_once DRUPAL_ROOT . '/core/modules/system/system.module'; + + // Retrieve all installed extensions from the {system} table. + // Uninstalled extensions are ignored and not converted. $result = db_query('SELECT name, status, weight, schema_version, type FROM {system} WHERE type = :theme OR (type = :module AND schema_version <> :schema_uninstalled)', array( ':theme' => 'theme', ':module' => 'module', ':schema_uninstalled' => SCHEMA_UNINSTALLED, )); - - // We include system.module because update.php does not always include - // it. - require_once DRUPAL_ROOT . '/core/modules/system/system.module'; - $module_data = system_rebuild_module_data(); - - // Loop through each extension from the system table. - foreach ($result as $file) { - if ($file->status && isset($module_data[$file->name])) { - $configs[$file->type]->set($file->name, $file->type == 'module' ? $file->weight : 1); + $module_data = _system_rebuild_module_data(); + + // Migrate each extension into configuration, varying by the extension's + // status, and record its schema version. + foreach ($result as $record) { + if ($record->type == 'module') { + if ($record->status && isset($module_data[$record->name])) { + $module_config->set('enabled.' . $record->name, $record->weight); + } + else { + $disabled_modules->set($record->name, $record->weight); + } } - if ($file->type == 'module') { - $schema_store->set($file->name, $file->schema_version); - if (!$file->status && $file->weight) { - $configs['disabled_module']->set($file->name, $file->weight); + elseif ($record->type == 'theme') { + if ($record->status) { + $theme_config->set('enabled.' . $record->name, 0); + } + else { + $disabled_themes->set($record->name, 0); } } + $schema_store->set($record->name, $record->schema_version); } - $configs['module']->setData(module_config_sort($configs['module']->get())); - foreach ($configs as $config) { - $config->save(); - } + $module_config->set('enabled', module_config_sort($module_config->get('enabled')))->save(); + $disabled_modules->save(); + $theme_config->save(); + $disabled_themes->save(); // Update the dynamic include paths that might be used before running the // proper update functions. @@ -322,19 +359,6 @@ function update_prepare_d8_language() { db_change_field('language', 'language', 'langcode', $langcode_spec, array('primary key' => array('langcode'))); } - // Update the 'language_default' system variable, if configured. - $language_default = variable_get('language_default'); - if (!empty($language_default) && (isset($language_default->langcode) || isset($language_default->language))) { - if (!isset($language_default->langcode)) { - $language_default->langcode = $language_default->language; - } - unset($language_default->language); - // In D8, the 'language_default' is not anymore an object, but an array, - // so make sure that the new value that is saved into this variable is an - // array. - variable_set('language_default', (array) $language_default); - } - // Adds the locked column and saves the special languages. if (!db_field_exists('language', 'locked')) { $locked_spec = array( @@ -399,7 +423,7 @@ function update_fix_d8_requirements() { * Helper function to install a new module in Drupal 8 via hook_update_N(). */ function update_module_enable(array $modules) { - $store = drupal_container()->get('keyvalue')->get('system.module.schema'); + $schema_store = drupal_container()->get('keyvalue')->get('system.schema'); foreach ($modules as $module) { // Check for initial schema and install it. The schema version of a newly // installed module is always 0. Using 8000 here would be inconsistent @@ -413,12 +437,18 @@ function update_module_enable(array $modules) { } } // Enable the module with a weight of 0. - config('system.module') - ->set($module, 0) + $module_config = config('system.module'); + $module_config + ->set("enabled.$module", 0) + ->set('enabled', module_config_sort($module_config->get('enabled'))) + ->save(); + // Ensure the module is not contained in disabled modules. + config('system.module.disabled') + ->clear($module) ->save(); // Change the schema version from SCHEMA_UNINSTALLED to 0, so any module // updates since the module's inception are executed in a core upgrade. - $store->set($module, 0); + $schema_store->set($module, 0); // system_list_reset() is in module.inc but that would only be available // once the variable bootstrap is done. @@ -953,7 +983,7 @@ function update_retrieve_dependencies() { $return = array(); // Get a list of installed modules, arranged so that we invoke their hooks in // the same order that module_invoke_all() does. - foreach (config('system.module')->get() as $module => $data) { + foreach (config('system.module')->get('enabled') as $module => $weight) { $function = $module . '_update_dependencies'; if (function_exists($function)) { $result = $function(); diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php index 897855e..864697f 100644 --- a/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php @@ -1,20 +1,29 @@ stores[$collection])) { + $this->stores[$collection] = new DatabaseStorage($collection); + } + return $this->stores[$collection]; } } diff --git a/core/lib/Drupal/Core/Updater/Theme.php b/core/lib/Drupal/Core/Updater/Theme.php index 16bb515..4bd716a 100644 --- a/core/lib/Drupal/Core/Updater/Theme.php +++ b/core/lib/Drupal/Core/Updater/Theme.php @@ -72,7 +72,7 @@ public static function canUpdate($project_name) { * Overrides Drupal\Core\Updater\Updater::postInstall(). */ public function postInstall() { - // Update the system table. + // Update the theme info. clearstatcache(); system_rebuild_theme_data(); } diff --git a/core/modules/action/lib/Drupal/action/Tests/LoopTest.php b/core/modules/action/lib/Drupal/action/Tests/LoopTest.php index fce4f2d..9f3a959 100644 --- a/core/modules/action/lib/Drupal/action/Tests/LoopTest.php +++ b/core/modules/action/lib/Drupal/action/Tests/LoopTest.php @@ -67,6 +67,7 @@ protected function triggerActions() { $expected[] = 'Stack overflow: too many calls to actions_do(). Aborting to prevent infinite recursion.'; $result = db_query("SELECT message FROM {watchdog} WHERE type = 'action_loop_test' OR type = 'action' ORDER BY wid"); + $loop_started = FALSE; foreach ($result as $row) { $expected_message = array_shift($expected); $this->assertEqual($row->message, $expected_message, format_string('Expected message %expected, got %message.', array('%expected' => $expected_message, '%message' => $row->message))); diff --git a/core/modules/block/block.install b/core/modules/block/block.install index 5ad23aa..ee72e0f 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -213,6 +213,7 @@ function block_schema() { * Implements hook_install(). */ function block_install() { + // Block should go first so that other modules can alter its output // during hook_page_alter(). Almost everything on the page is a block, // so before block module runs, there will not be much to alter. diff --git a/core/modules/help/lib/Drupal/help/Tests/HelpTest.php b/core/modules/help/lib/Drupal/help/Tests/HelpTest.php index 260768a..7d5d20e 100644 --- a/core/modules/help/lib/Drupal/help/Tests/HelpTest.php +++ b/core/modules/help/lib/Drupal/help/Tests/HelpTest.php @@ -108,10 +108,8 @@ protected function verifyHelp($response = 200) { protected function getModuleList() { $modules = array(); $module_data = system_rebuild_module_data(); - foreach (config('system.module')->get() as $module => $data) { - if (file_exists($module_data[$module]->filename) && function_exists($module . '_help')) { - $modules[$module] = $module_data[$module]->info['name']; - } + foreach (module_implements('help') as $module) { + $modules[$module] = $module_data[$module]->info['name']; } return $modules; } diff --git a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php index ee40928..77aa4dd 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php @@ -36,16 +36,7 @@ public function __construct($langcode, $context) { // Add the current user's role IDs to the cache key, this ensures that, for // example, strings for admin menu items and settings forms are not cached // for anonymous users. - if (isset($GLOBALS['user'])) { - $rids = implode(':', array_keys($GLOBALS['user']->roles)); - } - else { - // If there is no global user, surely it's an anonymous user. For - // example, during update install_ensure_config_directory() calls for - // stream wrappers which calls locale_stream_wrappers() which has t() - // calls in it. - $rids = DRUPAL_ANONYMOUS_RID; - } + $rids = implode(':', array_keys($GLOBALS['user']->roles)); parent::__construct("locale:$langcode:$context:$rids", 'cache', array('locale' => TRUE)); } diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php index 323c55d..1d2ec67 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php @@ -47,11 +47,12 @@ function testLocaleCompare() { // modules not hidden. locale_test_system_info_alter() modifies the project // info of the locale_test and locale_test_disabled modules. variable_set('locale_translation_test_system_info_alter', TRUE); - // Reset system lists to reflect changes. + + // Reset static system list caches to reflect info changes. + drupal_static_reset('locale_translation_project_list'); system_list_reset(); // Check if interface translation data is collected from hook_info. - drupal_static_reset('locale_translation_project_list'); $projects = locale_translation_project_list(); $this->assertEqual($projects['locale_test']['info']['interface translation server pattern'], 'core/modules/locale/test/modules/locale_test/%project-%version.%language.po', 'Interface translation parameter found in project info.'); $this->assertEqual($projects['locale_test']['name'] , 'locale_test', format_string('%key found in project info.', array('%key' => 'interface translation project'))); @@ -77,8 +78,6 @@ function testLocaleCompare() { // Return the locale test modules back to their hidden state. variable_del('locale_translation_test_system_info_alter'); - // Reset system lists to reflect changes. - system_list_reset(); } } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index a10324e..aeff65e 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -831,6 +831,7 @@ protected function tearDown() { // Reset module list and module load status. module_list_reset(); + module_load_all(FALSE, TRUE); // Restore original in-memory configuration. $conf = $this->originalConf; diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 71311af..016ffd0 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -9,6 +9,7 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Database\Database; +use Drupal\Core\Database\ConnectionNotDefinedException; use PDO; use stdClass; use DOMDocument; @@ -1065,8 +1066,7 @@ protected function drupalGet($path, array $options = array(), array $headers = a // options set, it might change the GET into a POST. Make sure we clear out // previous options. $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers)); - // Ensure that any changes to variables in the other thread are picked up. - $this->refreshVariables(); + $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up. // Replace original page output with new output from redirected page(s). if ($new = $this->checkForMetaRefresh()) { diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 98b62c9..2388601 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -1,7 +1,6 @@ $data) { - $dirname = dirname($data->filename); + $module_data = system_rebuild_module_data(); + $all_data = $module_data + system_rebuild_theme_data(); + foreach ($all_data as $name => $data) { // Build directory in which the test files would reside. - $tests_dir = DRUPAL_ROOT . '/' . $dirname . '/lib/Drupal/' . $name . '/Tests'; + $tests_dir = DRUPAL_ROOT . '/' . dirname($data->filename) . '/lib/Drupal/' . $name . '/Tests'; // Scan it for test files if it exists. if (is_dir($tests_dir)) { $files = file_scan_directory($tests_dir, '/.*\.php/'); if (!empty($files)) { - $basedir = DRUPAL_ROOT . '/' . $dirname . '/lib/'; + $basedir = DRUPAL_ROOT . '/' . dirname($data->filename) . '/lib/'; foreach ($files as $file) { // Convert the file name into the namespaced class name. $replacements = array( @@ -389,21 +384,14 @@ function simpletest_test_get_all() { /** * Registers namespaces for disabled modules. */ -function simpletest_classloader_register($module_data = NULL) { - if (!$module_data) { - // This is only needed to register namespaces and it is safe to - // re-register existing namespaces so go with raw data. - $module_data = _system_rebuild_module_data('simpletest_module_data'); - } - foreach ($module_data as $name => $data) { +function simpletest_classloader_register() { + $all_data = system_rebuild_module_data(); + $all_data += system_rebuild_theme_data(); + foreach ($all_data as $name => $data) { drupal_classloader_register($name, dirname($data->filename)); } } -function simpletest_prepare_module_data() { - _system_rebuild_module_data('simpletest_module_data', TRUE); -} - /** * Generate test file. */ diff --git a/core/modules/system/config/system.module.yml b/core/modules/system/config/system.module.yml new file mode 100644 index 0000000..696bedc --- /dev/null +++ b/core/modules/system/config/system.module.yml @@ -0,0 +1,2 @@ +enabled: + system: '0' diff --git a/core/modules/system/config/system.theme.yml b/core/modules/system/config/system.theme.yml new file mode 100644 index 0000000..40fad06 --- /dev/null +++ b/core/modules/system/config/system.theme.yml @@ -0,0 +1,2 @@ +enabled: + stark: '0' diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php index f85750b..60db2b3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php @@ -7,12 +7,10 @@ namespace Drupal\system\Tests\Database; -use Drupal\simpletest\WebTestBase; - /** * Range query tests. */ -class RangeQueryTest extends WebTestBase { +class RangeQueryTest extends DatabaseTestBase { /** * Modules to enable. @@ -34,12 +32,12 @@ public static function getInfo() { */ function testRangeQuery() { // Test if return correct number of rows. - $range_rows = db_query_range("SELECT name FROM {variable} ORDER BY name", 2, 3)->fetchAll(); + $range_rows = db_query_range("SELECT name FROM {test} ORDER BY name", 1, 3)->fetchAll(); $this->assertEqual(count($range_rows), 3, 'Range query work and return correct number of rows.'); // Test if return target data. - $raw_rows = db_query('SELECT name FROM {variable} ORDER BY name')->fetchAll(); - $raw_rows = array_slice($raw_rows, 2, 3); - $this->assertEqual($range_rows, $raw_rows, 'Range query work and return target data.'); + $raw_rows = db_query('SELECT name FROM {test} ORDER BY name')->fetchAll(); + $raw_rows = array_slice($raw_rows, 1, 3); + $this->assertEqual($range_rows, $raw_rows); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php index 110f5a8..7c2d0d0 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php @@ -7,12 +7,10 @@ namespace Drupal\system\Tests\Database; -use Drupal\simpletest\WebTestBase; - /** * Temporary query tests. */ -class TemporaryQueryTest extends WebTestBase { +class TemporaryQueryTest extends DatabaseTestBase { /** * Modules to enable. @@ -43,7 +41,7 @@ function testTemporaryQuery() { $this->drupalGet('database_test/db_query_temporary'); $data = json_decode($this->drupalGetContent()); if ($data) { - $this->assertEqual($this->countTableRows("filter"), $data->row_count, 'The temporary table contains the correct amount of rows.'); + $this->assertEqual($this->countTableRows('test'), $data->row_count, 'The temporary table contains the correct amount of rows.'); $this->assertFalse(db_table_exists($data->table_name), 'The temporary table is, indeed, temporary.'); } else { @@ -51,10 +49,10 @@ function testTemporaryQuery() { } // Now try to run two db_query_temporary() in the same request. - $table_name_system = db_query_temporary('SELECT name FROM {variable}', array()); - $table_name_users = db_query_temporary('SELECT uid FROM {users}', array()); + $table_name_test = db_query_temporary('SELECT name FROM {test}', array()); + $table_name_task = db_query_temporary('SELECT pid FROM {test_task}', array()); - $this->assertEqual($this->countTableRows($table_name_system), $this->countTableRows("variable"), 'A temporary table was created successfully in this request.'); - $this->assertEqual($this->countTableRows($table_name_users), $this->countTableRows("users"), 'A second temporary table was created successfully in this request.'); + $this->assertEqual($this->countTableRows($table_name_test), $this->countTableRows('test'), 'A temporary table was created successfully in this request.'); + $this->assertEqual($this->countTableRows($table_name_task), $this->countTableRows('test_task'), 'A second temporary table was created successfully in this request.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php index 6867ae8..e328712 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Module/VersionTest.php @@ -62,8 +62,9 @@ function testModuleVersions() { // Testing extra version. Incompatible. 'common_test (>2.4-rc0)', ); - foreach ($dependencies as $i => $dependency) { - variable_set('dependency', $dependency); + variable_set('dependencies', $dependencies); + $n = count($dependencies); + for ($i = 0; $i < $n; $i++) { $this->drupalGet('admin/modules'); $checkbox = $this->xpath('//input[@id="edit-modules-testing-module-test-enable"]'); $this->assertEqual(!empty($checkbox[0]['disabled']), $i % 2, $dependencies[$i]); diff --git a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php index 603af18..8d004ab 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php @@ -22,20 +22,21 @@ public static function getInfo() { } /** - * Tests that {system}.info is rebuilt after a module that implements + * Tests that theme .info data is rebuild after enabling a module. + * + * Tests that info data is rebuilt after a module that implements * hook_system_info_alter() is enabled. Also tests if core *_list() functions * return freshly altered info. */ function testSystemInfoAlter() { - // Enable seven and the test module. Flush all caches, which we assert is - // the only thing necessary to use the rebuilt {system}.info. + // Enable seven and the test module. theme_enable(array('seven')); module_enable(array('module_test'), FALSE); - $this->resetAll(); $this->assertTrue(module_exists('module_test'), t('Test module is enabled.')); + // Verify that the rebuilt and altered theme info is returned. $info = system_get_info('theme', 'seven'); - $this->assertTrue(isset($info['regions']['test_region']), t('Altered theme info was added to {system}.info.')); + $this->assertTrue(isset($info['regions']['test_region']), t('Altered theme info was returned by system_get_info().')); $seven_regions = system_region_list('seven'); $this->assertTrue(isset($seven_regions['test_region']), t('Altered theme info was returned by system_region_list().')); $system_list_themes = system_list('theme'); @@ -44,13 +45,12 @@ function testSystemInfoAlter() { $list_themes = list_themes(); $this->assertTrue(isset($list_themes['seven']->info['regions']['test_region']), t('Altered theme info was returned by list_themes().')); - // Disable the module and verify that {system}.info is rebuilt without it. + // Disable the module and verify that rebuilt .info does not contain it. module_disable(array('module_test'), FALSE); - $this->resetAll(); $this->assertFalse(module_exists('module_test'), t('Test module is disabled.')); $info = system_get_info('theme', 'seven'); - $this->assertFalse(isset($info['regions']['test_region']), t('Altered theme info was removed from {system}.info.')); + $this->assertFalse(isset($info['regions']['test_region']), t('Altered theme info was not returned by system_get_info().')); $seven_regions = system_region_list('seven'); $this->assertFalse(isset($seven_regions['test_region']), t('Altered theme info was not returned by system_region_list().')); $system_list_themes = system_list('theme'); diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php index 918eb96..f3275a7 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php @@ -129,10 +129,10 @@ function testThemeSystem() { // Since visiting update.php triggers a rebuild of the theme system from an // unusual maintenance mode environment, we check that this rebuild did not // put any incorrect information about the themes into the database. - $original_theme_data = config('system.theme')->get(); + $original_theme_data = config('system.theme')->get('enabled'); $this->drupalLogin($this->update_user); $this->drupalGet($this->update_url, array('external' => TRUE)); - $final_theme_data = config('system.theme')->get(); + $final_theme_data = config('system.theme')->get('enabled'); $this->assertEqual($original_theme_data, $final_theme_data, t('Visiting update.php does not alter the information about themes stored in the database.')); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php index 2c64b08..6c32faa 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php @@ -243,6 +243,7 @@ protected function performUpgrade($register_errors = TRUE) { // but not on the test client. system_list_reset(); module_implements_reset(); + module_load_all(FALSE, TRUE); // Rebuild caches. // @todo Remove the try/catch when UpgradePathTestBase::setup() is fixed to @@ -264,13 +265,13 @@ protected function performUpgrade($register_errors = TRUE) { /** * Gets update.php without calling url(). * - * This function is necessary because drupalGet calls t() before the - * database is ready for that. + * Required since WebTestBase::drupalGet() calls t(), which calls into + * system_list(), from the parent site/test runner, before update.php is even + * executed. + * + * @see WebTestBase::drupalGet() */ protected function getUpdatePhp() { - // We re-using a CURL connection here. If that connection still has certain - // options set, it might change the GET into a POST. Make sure we clear out - // previous options. $path = $GLOBALS['base_url'] . '/core/update.php'; $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => $path, CURLOPT_NOBODY => FALSE)); // Ensure that any changes to variables in the other thread are picked up. @@ -280,9 +281,17 @@ protected function getUpdatePhp() { if ($new = $this->checkForMetaRefresh()) { $out = $new; } - $this->verbose('GET request to: update.php' . + // @todo WebTestBase::verbose() cannot be called here yet, since Simpletest + // verbose output parameters are not prepared before test execution and + // instead determined at runtime; i.e., file_create_url() calls into + // system_list(), before update.php has upgraded the system list. + // @see http://drupal.org/node/1611430 + /* + $this->verbose('GET request to: ' . $path . '
Ending URL: ' . $this->getUrl() . '
' . $out); + */ return $out; } + } diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index ff9a59a..1c6dc89 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -792,9 +792,8 @@ function system_modules($form, $form_state = array()) { // Remove hidden modules from display list. $visible_files = $files; - $profile = drupal_get_profile(); foreach ($visible_files as $filename => $file) { - if (!empty($file->info['hidden']) || $filename == $profile) { + if (!empty($file->info['hidden'])) { unset($visible_files[$filename]); } } diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index dd263cd..0f6d668 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -2167,10 +2167,7 @@ function hook_cache_flush() { * @see drupal_flush_all_caches() */ function hook_rebuild() { - // Rehash blocks for active themes. We don't use list_themes() here, - // because if MAINTENANCE_MODE is defined it skips reading the database, - // and we can't tell which themes are active. - $themes = db_query("SELECT name FROM {system} WHERE type = 'theme' AND status = 1"); + $themes = list_themes(); foreach ($themes as $theme) { _block_rehash($theme->name); } @@ -2983,8 +2980,8 @@ function hook_update_last_removed() { * - variables that the module has set using variable_set() or system_settings_form() * - modifications to existing tables * - * The module should not remove its entry from the {system} table. Database - * tables defined by hook_schema() will be removed automatically. + * The module should not remove its entry from the module configuration. + * Database tables defined by hook_schema() will be removed automatically. * * The uninstall hook must be implemented in the module's .install file. It * will fire when the module gets uninstalled but before the module's database diff --git a/core/modules/system/system.install b/core/modules/system/system.install index c7b5ad5..e2b1eee 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -435,15 +435,6 @@ function system_requirements($phase) { if ($phase == 'update') { $profile = drupal_get_profile(); $files = system_rebuild_module_data(); - // Build dependencies based on non-system_info_alter-ed info files - // if we are fired before the alter could even run. - if (drupal_get_bootstrap_phase() < DRUPAL_BOOTSTRAP_CODE) { - foreach ($files as $record) { - $record->info = $record->parsed_info; - } - $files = _module_build_dependencies($files); - } - foreach ($files as $module => $file) { // Ignore disabled modules and installation profiles. if (!$file->status || $module == $profile) { @@ -519,7 +510,6 @@ function system_install() { // Enable the default theme. Can't use theme_enable() this early in // installation. variable_set('theme_default', 'stark'); - config('system.theme')->set('stark', 1)->save(); config_install_default_config('theme', 'stark'); // Populate the cron key variable. diff --git a/core/modules/system/system.module b/core/modules/system/system.module index a07a4db..cc8fc9c 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -12,16 +12,6 @@ use Symfony\Component\HttpFoundation\Response; /** - * Indicates that a module has not been installed yet. - */ -const SCHEMA_UNINSTALLED = -1; - -/** - * Indicates that a module has been installed. - */ -const SCHEMA_INSTALLED = 0; - -/** * Maximum age of temporary files in seconds. */ const DRUPAL_MAXIMUM_TEMP_FILE_AGE = 21600; @@ -2665,8 +2655,8 @@ function system_check_directory($form_element) { /** * Returns an array of information about enabled modules or themes. * - * This function returns the information from the {system} table corresponding - * to the cached contents of the .info file for each active module or theme. + * This function returns the contents of the .info file for each enabled module + * or theme. * * @param $type * Either 'module' or 'theme'. @@ -2686,16 +2676,20 @@ function system_check_directory($form_element) { */ function system_get_info($type, $name = NULL) { $info = array(); - $function = 'system_rebuild_' . $type . '_data'; - $data = $function(); - foreach (array_keys(config("system.$type")->get()) as $enabled) { - $info[$enabled] = $data[$enabled]->info; + if ($type == 'module') { + $data = system_rebuild_module_data(); + foreach (module_list() as $module) { + $info[$module] = $data[$module]->info; + } } - $profile = drupal_get_profile(); - if (isset($info[$profile]) && !isset($info[$profile]['distribution_name'])) { - $info[$profile]['distribution_name'] = 'Drupal'; + else { + $list = system_list($type); + foreach ($list as $shortname => $item) { + if (!empty($item->status)) { + $info[$shortname] = $item->info; + } + } } - if (isset($name)) { return isset($info[$name]) ? $info[$name] : array(); } @@ -2729,97 +2723,81 @@ function system_get_module_info($property) { * @return * An associative array of module information. */ -function _system_rebuild_module_data($state_name = FALSE, $save = FALSE) { - static $module_store = array(), $profiles_seen; +function _system_rebuild_module_data() { + // Find modules + $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0); + + // Find installation profiles. + $profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles', 'name', 0); + // Include the installation profile in modules that are loaded. $profile = drupal_get_profile(); - // Find modules not yet processed. - $modules = array(); - if (empty($module_store) && ($state_name || drupal_valid_test_ua()) && ($data = state()->get($state_name ?: __FUNCTION__))) { - // During a test run no modules can move, no info files can change so - // speed up test runs by only finding and parsing once. - $module_store = $data['module_store']; - $profiles_seen = $data['profiles_seen']; - } - // If this is the first time, start with all modules. - 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 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]; - // Install profile hooks are always executed last. - $modules[$profile]->weight = 1000; - $profiles_seen[$profile] = TRUE; - } - // Now process the modules if necessary. - if ($modules) { - // Set defaults for module info. - $defaults = array( - 'dependencies' => array(), - 'description' => '', - 'package' => 'Other', - 'version' => NULL, - 'php' => DRUPAL_MINIMUM_PHP, - 'files' => array(), - 'bootstrap' => 0, - ); - // Read info files for each module. - foreach ($modules as $key => $module) { - // The module system uses the key 'filename' instead of 'uri' so copy the - // value so it will be used by the modules system. - $modules[$key]->filename = $module->uri; - - // Look for the info file. - $module->parsed_info = drupal_parse_info_file(dirname($module->uri) . '/' . $module->name . '.info'); - - // Add the info file modification time, so it becomes available for - // contributed modules to use for ordering module lists. - $module->parsed_info['mtime'] = filemtime(dirname($module->uri) . '/' . $module->name . '.info'); - - // Skip modules that don't provide info. - if (empty($module->parsed_info)) { - unset($modules[$key]); - continue; - } + $modules[$profile] = $profiles[$profile]; - // Merge in defaults and save. - $modules[$key]->parsed_info = $module->parsed_info + $defaults; + // Installation profile hooks are always executed last. + $modules[$profile]->weight = 1000; - // Prefix stylesheets and scripts with module path. - $path = dirname($module->uri); - if (isset($module->parsed_info['stylesheets'])) { - $module->parsed_info['stylesheets'] = _system_info_add_path($module->parsed_info['stylesheets'], $path); - } - if (isset($module->parsed_info['scripts'])) { - $module->parsed_info['scripts'] = _system_info_add_path($module->parsed_info['scripts'], $path); - } + // Set defaults for module info. + $defaults = array( + 'dependencies' => array(), + 'description' => '', + 'package' => 'Other', + 'version' => NULL, + 'php' => DRUPAL_MINIMUM_PHP, + 'files' => array(), + 'bootstrap' => 0, + ); - // Install profiles are hidden by default, unless explicitly specified - // otherwise in the .info file. - if ($key == $profile && !isset($modules[$key]->info['hidden'])) { - $modules[$key]->info['hidden'] = TRUE; - } + // Read info files for each module. + foreach ($modules as $key => $module) { + // The module system uses the key 'filename' instead of 'uri' so copy the + // value so it will be used by the modules system. + $modules[$key]->filename = $module->uri; + + // Look for the info file. + $module->info = drupal_parse_info_file(dirname($module->uri) . '/' . $module->name . '.info'); + + // Add the info file modification time, so it becomes available for + // contributed modules to use for ordering module lists. + $module->info['mtime'] = filemtime(dirname($module->uri) . '/' . $module->name . '.info'); + + // Skip modules that don't provide info. + if (empty($module->info)) { + unset($modules[$key]); + continue; } - // Store the processed modules. - $module_store += $modules; - } - if ($save || ($modules && drupal_valid_test_ua())) { - state()->set($state_name ?: __FUNCTION__, array( - 'module_store' => $module_store, - 'profiles_seen' => $profiles_seen, - )); + + // Merge in defaults and save. + $modules[$key]->info = $module->info + $defaults; + + // Prefix stylesheets and scripts with module path. + $path = dirname($module->uri); + if (isset($module->info['stylesheets'])) { + $module->info['stylesheets'] = _system_info_add_path($module->info['stylesheets'], $path); + } + if (isset($module->info['scripts'])) { + $module->info['scripts'] = _system_info_add_path($module->info['scripts'], $path); + } + + // Installation profiles are hidden by default, unless explicitly specified + // otherwise in the .info file. + if ($key == $profile && !isset($modules[$key]->info['hidden'])) { + $modules[$key]->info['hidden'] = TRUE; + } + + // Invoke hook_system_info_alter() to give installed modules a chance to + // modify the data in the .info files if necessary. + $type = 'module'; + drupal_alter('system_info', $modules[$key]->info, $modules[$key], $type); } - $modules = $module_store; - // Do not return the non-active profile modules. Typically at most one: when - // testing switches the profile. - foreach ($profiles_seen as $key => $value) { - if ($key != $profile) { - unset($modules[$key]); + + if (isset($modules[$profile])) { + // The installation profile is required, if it's a valid module. + $modules[$profile]->info['required'] = TRUE; + // Add a default distribution name if the profile did not provide one. This + // matches the default value used in install_profile_info(). + if (!isset($modules[$profile]->info['distribution_name'])) { + $modules[$profile]->info['distribution_name'] = 'Drupal'; } } @@ -2832,75 +2810,51 @@ function _system_rebuild_module_data($state_name = FALSE, $save = FALSE) { * @return * Array of all available modules and their data. */ -function system_rebuild_module_data($reset = TRUE) { - $modules_cache = &drupal_static(__FUNCTION__, array()); +function system_rebuild_module_data() { + $modules_cache = &drupal_static(__FUNCTION__); // Only rebuild once per request. $modules and $modules_cache cannot be // combined into one variable, because the $modules_cache variable is reset by // reference from system_list_reset() during the rebuild. - if (!isset($modules_cache['data'])) { + if (!isset($modules_cache)) { $modules = _system_rebuild_module_data(); - $module_file_list = array(); + $files = array(); ksort($modules); - // Add status, weight and schema. + // Add name, status, weight, and schema version. + $enabled_modules = config('system.module')->get('enabled'); + $disabled_modules = config('system.module.disabled')->get(); + $all_modules = $enabled_modules + $disabled_modules; foreach ($modules as $module => $record) { - // Set defaults and name. $record->name = $module; - $record->weight = 0; - $record->status = 0; + $record->weight = isset($all_modules[$module]) ? $all_modules[$module] : 0; + $record->status = (int) isset($enabled_modules[$module]); $record->schema_version = SCHEMA_UNINSTALLED; - $module_file_list[$module] = $record->filename; - } - // Enabled status and weights. - foreach (config('system.module')->get() as $module => $weight) { - $modules[$module]->status = 1; - $modules[$module]->weight = $weight; - } - // As noted above, system_list_reset() deletes $modules_cache so the order - // here is important. - if ($reset) { - system_list_reset(); - } - $modules_cache['data'] = $modules; - // Store module filenames so that if can be retrieved during system_list() - // without a rebuild or drupal_get_filename() without scanning directories. - state()->set('system.module_file_list', $module_file_list); - } - // Running the info alter function is not possible before full bootstrap. - if (!isset($modules_cache['info_alter']) && drupal_get_bootstrap_phase() >= DRUPAL_BOOTSTRAP_CODE) { - // 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'; - // It is not impossible a function resets the modules cache. Keep it. - $modules = $modules_cache['data']; - foreach ($modules as $record) { - // Copy parsed info. - $record->info = $record->parsed_info; - } - foreach (config('system.module')->get() as $module => $weight) { - $function = $module .'_system_info_alter'; - if (function_exists($function)) { - foreach ($modules as $record) { - $function($record->info, $record, $type); - } - } + $files[$module] = $record->filename; } $modules = _module_build_dependencies($modules); - $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. - $modules_cache['data'][$profile]->info['required'] = TRUE; - // Add a default distribution name if the profile did not provide one. This - // matches the default value used in install_profile_info(). - if (!isset($modules_cache['data'][$profile]->info['distribution_name'])) { - $modules_cache['data'][$profile]->info['distribution_name'] = 'Drupal'; - } + $modules_cache = $modules; + + // Store filenames to allow system_list() and drupal_get_filename() to + // retrieve them without having to rebuild or scan the filesystem. + state()->set('system.module.files', $files); + } + return $modules_cache; +} + +/** + * Refreshes the list of bootstrap modules. + * + * This is called internally by module_enable/disable() to flag modules that + * implement hooks used during bootstrap, such as hook_boot(). These modules + * are loaded earlier to invoke the hooks. + */ +function _system_update_bootstrap_status() { + $bootstrap_modules = array(); + foreach (bootstrap_hooks() as $hook) { + foreach (module_implements($hook) as $module) { + $bootstrap_modules[$module] = drupal_get_filename('module', $module); } - $modules_cache['info_alter'] = TRUE; } - return $modules_cache['data']; + state()->set('system.module.bootstrap', $bootstrap_modules); } /** @@ -2950,11 +2904,9 @@ function _system_rebuild_theme_data() { ); $sub_themes = array(); - $theme_file_list = array(); // Read info files for each theme foreach ($themes as $key => $theme) { $themes[$key]->filename = $theme->uri; - $theme_file_list[$key] = $theme->uri; $themes[$key]->info = drupal_parse_info_file($theme->uri) + $defaults; // Add the info file modification time, so it becomes available for @@ -2995,11 +2947,7 @@ function _system_rebuild_theme_data() { $themes[$key]->info['screenshot'] = $path . '/' . $themes[$key]->info['screenshot']; } } - // Store theme filenames so that if can be retrieved during - // drupal_get_filename() without scanning directories. - if (drupal_container()->hasDefinition('keyvalue') && function_exists('db_query')) { - state()->set('system.theme_file_list', $theme_file_list); - } + // Now that we've established all our master themes, go back and fill in data // for subthemes. foreach ($sub_themes as $key) { @@ -3035,19 +2983,30 @@ function _system_rebuild_theme_data() { * @return * Array of all available themes and their data. */ -function system_rebuild_theme_data($reset = TRUE) { +function system_rebuild_theme_data() { $themes = _system_rebuild_theme_data(); ksort($themes); - $themes_status = config('system.theme')->get(); - foreach ($themes as $theme => $data) { - $data->status = isset($themes_status[$theme]); - } - if ($reset) { - system_list_reset(); + // @todo This function has no business in determining/setting the status of + // a theme, but various other functions expect it to return themes with a + // $status property. system_list() stores the return value of this function + // in state, and ensures to set/override the $status property for each theme + // based on the current config. Remove this code here when themes have a + // proper installation status. + // @see http://drupal.org/node/1067408 + $enabled_themes = config('system.theme')->get('enabled'); + $files = array(); + foreach ($themes as $name => $theme) { + $theme->status = (int) isset($enabled_themes[$name]); + $files[$name] = $theme->filename; } - // Store theme data so that if can be retrieved during system_list() without - // a rebuild. - state()->set('system.themes', $themes); + // Replace last known theme data state. + // @todo Obsolete with proper installation status for themes. + state()->set('system.theme.data', $themes); + + // Store filenames to allow system_list() and drupal_get_filename() to + // retrieve them without having to rebuild or scan the filesystem. + state()->set('system.theme.files', $files); + return $themes; } diff --git a/core/modules/system/tests/modules/database_test/database_test.module b/core/modules/system/tests/modules/database_test/database_test.module index 93135c9..339f1f9 100644 --- a/core/modules/system/tests/modules/database_test/database_test.module +++ b/core/modules/system/tests/modules/database_test/database_test.module @@ -84,7 +84,7 @@ function database_test_menu() { * table should automatically dropped. */ function database_test_db_query_temporary() { - $table_name = db_query_temporary('SELECT status FROM {filter}', array()); + $table_name = db_query_temporary('SELECT age FROM {test}', array()); return new JsonResponse(array( 'table_name' => $table_name, 'row_count' => db_select($table_name)->countQuery()->execute()->fetchField(), diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module index ef06cb7..4949aec 100644 --- a/core/modules/system/tests/modules/system_test/system_test.module +++ b/core/modules/system/tests/modules/system_test/system_test.module @@ -247,10 +247,11 @@ function system_test_exit() { function system_test_system_info_alter(&$info, $file, $type) { // We need a static otherwise the last test will fail to alter common_test. static $test; - if (($dependency = variable_get('dependency', array())) || $test) { + if (($dependencies = variable_get('dependencies', array())) || $test) { if ($file->name == 'module_test') { $info['hidden'] = FALSE; - $info['dependencies'][] = $dependency; + $info['dependencies'][] = array_shift($dependencies); + variable_set('dependencies', $dependencies); $test = TRUE; } if ($file->name == 'common_test') { diff --git a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php index baac1da..4f51883 100644 --- a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php +++ b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php @@ -204,15 +204,13 @@ function testUpdateBaseThemeSecurityUpdate() { function testUpdateShowDisabledThemes() { $update_settings = config('update.settings'); // Make sure all the update_test_* themes are disabled. - $config = config('system.theme'); - foreach ($config->get() as $theme => $weight) { + $theme_config = config('system.theme'); + foreach ($theme_config->get('enabled') as $theme => $weight) { if (preg_match('/^update_test_/', $theme)) { - $config->clear($theme); + $theme_config->clear("enabled.$theme"); } } - $config - ->setData(module_config_sort($config->get())) - ->save(); + $theme_config->save(); // Define the initial state for core and the test contrib themes. $system_info = array( diff --git a/core/modules/update/update.authorize.inc b/core/modules/update/update.authorize.inc index d22f235..4557453 100644 --- a/core/modules/update/update.authorize.inc +++ b/core/modules/update/update.authorize.inc @@ -66,7 +66,8 @@ function update_authorize_run_update($filetransfer, $projects) { * The FileTransfer object created by authorize.php for use during this * operation. * @param string $project - * The canonical project short name (e.g., {system}.name). + * The canonical project short name; i.e., the name of the module, theme, or + * profile. * @param string $updater_name * The name of the Drupal\Core\Updater\Updater class to use for installing * this project. diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 7a5bbb1..2395a84 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -68,9 +68,6 @@ simpletest_script_reporter_init(); -// Prime module data. -simpletest_prepare_module_data(); - // Execute tests. simpletest_script_execute_batch(simpletest_script_get_test_list());