diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index b58ec36..c81ccf1 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -886,37 +886,57 @@ function drupal_get_filename($type, $name, $filename = NULL) { // nothing } else { - // We have a consistent directory naming: modules, themes... - $dir = $type . 's'; - if ($type == 'theme_engine') { - $dir = 'themes/engines'; - $extension = 'engine'; - } - elseif ($type == 'theme') { - $extension = 'info'; - } - // Profiles are converted into modules in system_rebuild_module_data(). - // @todo Remove false-exposure of profiles as modules. - elseif ($original_type == 'profile') { - $dir = 'profiles'; - $extension = 'profile'; - } - else { - $extension = $type; + // Verify that we have an keyvalue service before using it. This is required + // because this function is called during installation. + if (drupal_container()->hasDefinition('keyvalue') && function_exists('db_query')) { + try { + $file_list = state()->get('system.' . $type . '_file_list'); + if ($file_list && isset($file_list[$name]) && file_exists(DRUPAL_ROOT . '/' . $file_list[$name])) { + $files[$type][$name] = $file_list[$name]; + } + } + catch (Exception $e) { + // The keyvalue service raise an exception due because the backend might + // be down. We have a fallback for this case so we hide the error + // completely. + } } - if (!isset($dirs[$dir][$extension])) { - $dirs[$dir][$extension] = TRUE; - if (!function_exists('drupal_system_listing')) { - require_once DRUPAL_ROOT . '/core/includes/common.inc'; + // 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])) { + // We have a consistent directory naming: modules, themes... + $dir = $type . 's'; + if ($type == 'theme_engine') { + $dir = 'themes/engines'; + $extension = 'engine'; + } + elseif ($type == 'theme') { + $extension = 'info'; } - // Scan the appropriate directories for all files with the requested - // extension, not just the file we are currently looking for. This - // prevents unnecessary scans from being repeated when this function is - // called more than once in the same page request. - $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0); - foreach ($matches as $matched_name => $file) { - $files[$type][$matched_name] = $file->uri; + // Profiles are converted into modules in system_rebuild_module_data(). + // @todo Remove false-exposure of profiles as modules. + elseif ($original_type == 'profile') { + $dir = 'profiles'; + $extension = 'profile'; + } + else { + $extension = $type; + } + + if (!isset($dirs[$dir][$extension])) { + $dirs[$dir][$extension] = TRUE; + if (!function_exists('drupal_system_listing')) { + require_once DRUPAL_ROOT . '/core/includes/common.inc'; + } + // Scan the appropriate directories for all files with the requested + // extension, not just the file we are currently looking for. This + // prevents unnecessary scans from being repeated when this function is + // called more than once in the same page request. + $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0); + foreach ($matches as $matched_name => $file) { + $files[$type][$matched_name] = $file->uri; + } } } } diff --git a/core/includes/install.inc b/core/includes/install.inc index 483a4f2..860ac3d 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -417,7 +417,6 @@ function drupal_install_system() { } config('system.module') ->set('system', 0) - ->call('module_config_sort') ->save(); // Clear out module list and hook implementation statics before calling diff --git a/core/includes/module.inc b/core/includes/module.inc index e683377..30fa096 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -505,7 +505,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) { if (!$enabled) { $config ->set($module, $weight) - ->call('module_config_sort') + ->setData(module_config_sort($config->get())) ->save(); if ($weight) { $disabled_config @@ -637,7 +637,7 @@ function module_disable($module_list, $disable_dependents = TRUE) { } $config ->clear($module) - ->call('module_config_sort') + ->setData(module_config_sort($config->get())) ->save(); $invoke_modules[] = $module; watchdog('system', '%module module disabled.', array('%module' => $module), WATCHDOG_INFO); @@ -1209,8 +1209,8 @@ function module_set_weight($module, $weight) { if ($config->get($module) !== NULL) { $config ->set($module, $weight) - ->call('module_config_sort') - ->save(); + ->setData(module_config_sort($config->get())) + ->save(); } // Before writing to the system.module.disabled file ensure that the module // has been previously enabled. diff --git a/core/includes/update.inc b/core/includes/update.inc index d238fc8..e36b9ef 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -38,7 +38,7 @@ function update_fix_compatibility() { if ($save) { if ($type == 'module') { $config - ->call('module_config_sort') + ->setData(module_config_sort($config->get())) ->save(); } else { @@ -210,7 +210,7 @@ function update_prepare_d8_bootstrap() { } } } - $configs['module']->call('module_config_sort'); + $configs['module']->setData(module_config_sort($configs['module']->get())); foreach ($configs as $config) { $config->save(); } @@ -415,7 +415,7 @@ function update_module_enable(array $modules) { // Enable the module with a weight of 0. config('system.module') ->set($module, 0) - ->save('module_config_sort'); + ->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); diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 1f2796e..034dff1 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -63,7 +63,6 @@ class Config { * @var Symfony\Component\EventDispatcher\EventDispatcher */ protected $eventDispatcher; - protected $sorted; /** * Constructs a configuration object. @@ -347,35 +346,12 @@ public function load() { * The configuration object. */ public function save() { - // @TODO remove with http://drupal.org/node/1785560 - if (!$this->sorted) { - $this->sortByKey($this->data); - } $this->storage->write($this->name, $this->data); $this->isNew = FALSE; $this->notify('save'); return $this; } - /** - * Calls a PHP callable with the current data. - * - * This allows adding an arbitrary callback to a chain of config method - * calls. - * - * @param callable $callable - * A PHP callable. - * - * @return Drupal\Core\Config\Config - * The configuration object. - */ - public function call($callable) { - $this->data = $callable($this->data); - // @TODO remove with http://drupal.org/node/1785560 - $this->sorted = TRUE; - return $this; - } - /* * Renames the configuration object. * @@ -393,26 +369,6 @@ public function rename($new_name) { } /** - * Sorts all keys in configuration data. - * - * Ensures that re-inserted keys appear in the same location as before, in - * order to ensure an identical order regardless of storage controller. - * A consistent order is important for any storage that allows any kind of - * diff operation. - * - * @param array $data - * An associative array to sort recursively by key name. - */ - public function sortByKey(array &$data) { - ksort($data); - foreach ($data as &$value) { - if (is_array($value)) { - $this->sortByKey($value); - } - } - } - - /** * Deletes the configuration object. * * @return Drupal\Core\Config\Config diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php index 9eea495..2414728 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php @@ -93,7 +93,7 @@ function testCRUD() { } /** - * Tests Drupal\Core\Config\Config::sortByKey(). + * Tests key injection order. */ function testDataKeySort() { $config = config('config_test.keysort'); @@ -112,10 +112,10 @@ function testDataKeySort() { $new_config->set('new', 'Value to be replaced'); $new_config->save(); - // Verify that the data of both objects is in the identical order. + // Verify that the data of the new object is in the reverse order. // assertIdentical() is the required essence of this test; it performs a // strict comparison, which means that keys and values must be identical and - // their order must be identical. - $this->assertIdentical($new_config->get(), $config->get()); + // their order must be as expected. + $this->assertIdentical($new_config->get(), array_reverse($config->get())); } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php index 9316962..2266732 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php @@ -128,10 +128,10 @@ function testNew() { $staging->write($name, $original_name_data); $original_dynamic_data = array( 'id' => 'new', + 'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651', 'label' => 'New', - 'langcode' => 'und', 'style' => '', - 'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651', + 'langcode' => 'und', ); $staging->write($dynamic_name, $original_dynamic_data); $this->assertIdentical($staging->exists($name), TRUE, $name . ' found.'); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 8b194a7..a07a4db 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2862,7 +2862,7 @@ function system_rebuild_module_data($reset = TRUE) { } $modules_cache['data'] = $modules; // Store module filenames so that if can be retrieved during system_list() - // without a rebuild. + // 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. @@ -2950,9 +2950,11 @@ 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 @@ -2993,7 +2995,11 @@ 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) { diff --git a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php index c67dad7..baac1da 100644 --- a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php +++ b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php @@ -211,7 +211,7 @@ function testUpdateShowDisabledThemes() { } } $config - ->call('module_config_sort') + ->setData(module_config_sort($config->get())) ->save(); // Define the initial state for core and the test contrib themes.