From 73069e05e8a32f421e0f9a3132ae76d94f3bdcde Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Fri, 16 Jan 2015 10:43:35 +0000 Subject: [PATCH] Issue #2392319 by alexpott, effulgentsia: Config objects (but not config entities) should by default be immutable --- core/includes/file.inc | 5 +- core/includes/install.core.inc | 2 +- core/includes/install.inc | 2 +- core/includes/module.inc | 3 +- core/lib/Drupal.php | 4 +- core/lib/Drupal/Core/Config/Config.php | 3 +- core/lib/Drupal/Core/Config/ConfigFactory.php | 85 ++++++++++++++++--- .../Core/Config/ConfigFactoryInterface.php | 37 ++++++-- core/lib/Drupal/Core/Config/ConfigManager.php | 2 +- .../Config/Entity/ConfigEntityStorage.php | 10 +-- .../Drupal/Core/Config/ImmutableConfig.php | 61 +++++++++++++ .../Core/Config/ImmutableConfigException.php | 16 ++++ .../Drupal/Core/Extension/ModuleInstaller.php | 8 +- .../Drupal/Core/Extension/ThemeHandler.php | 8 +- core/lib/Drupal/Core/Form/ConfigFormBase.php | 17 +--- .../Drupal/Core/Form/ConfigFormBaseTrait.php | 77 +++++++++++++++++ core/lib/Drupal/Core/Form/FormBase.php | 2 +- .../Core/Installer/Form/SiteConfigureForm.php | 11 +++ .../Core/Menu/StaticMenuLinkOverrides.php | 7 +- .../aggregator/src/Form/SettingsForm.php | 7 ++ .../aggregator/processor/DefaultProcessor.php | 21 +++-- .../aggregator/processor/TestProcessor.php | 13 ++- core/modules/book/book.module | 2 +- .../book/src/Form/BookSettingsForm.php | 7 ++ .../ckeditor/src/Tests/CKEditorTest.php | 2 +- core/modules/color/color.module | 22 +++-- .../src/Form/ConfigSingleImportForm.php | 2 +- .../config/src/Tests/ConfigCRUDTest.php | 4 +- .../config/src/Tests/ConfigEventsTest.php | 7 +- .../src/Tests/ConfigLanguageOverrideTest.php | 7 +- .../src/Tests/ConfigModuleOverridesTest.php | 2 +- .../config/src/Tests/ConfigOverrideTest.php | 24 ++++-- .../src/Tests/ConfigOverridesPriorityTest.php | 2 +- .../src/SchemaListenerController.php | 23 ++++- .../src/Tests/ConfigTranslationUiTest.php | 2 +- core/modules/contact/contact.module | 6 +- .../contact/src/ContactFormEditForm.php | 11 +++ core/modules/dblog/dblog.module | 4 +- core/modules/forum/src/ForumSettingsForm.php | 7 ++ core/modules/language/language.module | 10 ++- .../src/ConfigurableLanguageInterface.php | 11 +++ .../src/ConfigurableLanguageManager.php | 30 +++---- .../src/Entity/ConfigurableLanguage.php | 10 ++- .../src/Form/NegotiationBrowserDeleteForm.php | 10 +++ .../src/Form/NegotiationBrowserForm.php | 7 ++ .../src/Form/NegotiationConfigureForm.php | 7 ++ .../src/Form/NegotiationSelectedForm.php | 7 ++ .../src/Form/NegotiationSessionForm.php | 7 ++ .../language/src/Form/NegotiationUrlForm.php | 7 ++ .../language/src/LanguageNegotiator.php | 2 +- .../tests/language_test/language_test.module | 5 +- core/modules/locale/locale.install | 2 +- core/modules/locale/locale.module | 4 +- .../locale/src/Form/LocaleSettingsForm.php | 7 ++ .../locale/src/Tests/LocaleUpdateBase.php | 8 +- .../src/Plugin/migrate/destination/Config.php | 11 +-- .../tests/src/Unit/destination/ConfigTest.php | 7 +- core/modules/node/node.module | 4 +- .../search/src/SearchPageListBuilder.php | 2 +- .../search/src/SearchPageRepository.php | 4 +- .../src/Unit/SearchPageRepositoryTest.php | 4 +- core/modules/shortcut/shortcut.install | 4 +- core/modules/shortcut/shortcut.module | 2 +- .../src/Form/SimpletestSettingsForm.php | 7 ++ .../simpletest/src/InstallerTestBase.php | 2 +- .../modules/simpletest/src/KernelTestBase.php | 7 +- core/modules/simpletest/src/TestBase.php | 2 +- core/modules/simpletest/src/WebTestBase.php | 8 +- .../statistics/src/StatisticsSettingsForm.php | 7 ++ core/modules/syslog/syslog.install | 2 +- core/modules/syslog/syslog.module | 4 +- .../system/src/Controller/ThemeController.php | 11 ++- core/modules/system/src/Form/CronForm.php | 7 ++ .../system/src/Form/FileSystemForm.php | 7 ++ .../system/src/Form/ImageToolkitForm.php | 7 ++ core/modules/system/src/Form/LoggingForm.php | 7 ++ .../system/src/Form/PerformanceForm.php | 7 ++ core/modules/system/src/Form/RegionalForm.php | 7 ++ core/modules/system/src/Form/RssFeedsForm.php | 7 ++ .../system/src/Form/SiteInformationForm.php | 7 ++ .../src/Form/SiteMaintenanceModeForm.php | 7 ++ .../system/src/Form/ThemeAdminForm.php | 7 ++ .../system/src/Form/ThemeSettingsForm.php | 22 ++++- .../src/Plugin/ImageToolkit/GDToolkit.php | 4 +- .../system/src/Tests/Form/FormObjectTest.php | 2 +- core/modules/system/system.install | 2 +- .../modules/form_test/form_test.services.yml | 1 + .../form_test/src/FormTestArgumentsObject.php | 11 ++- .../src/FormTestControllerObject.php | 15 +++- .../modules/form_test/src/FormTestObject.php | 11 ++- .../form_test/src/FormTestServiceObject.php | 13 ++- .../src/SystemConfigFormTestForm.php | 7 ++ .../src/Plugin/ImageToolkit/TestToolkit.php | 4 +- .../modules/update/src/UpdateSettingsForm.php | 7 ++ core/modules/user/src/AccountSettingsForm.php | 11 +++ core/modules/user/user.module | 2 +- .../views_test_data/views_test_data.install | 2 +- .../src/Form/AdvancedSettingsForm.php | 7 ++ .../views_ui/src/Form/BasicSettingsForm.php | 7 ++ core/profiles/minimal/minimal.install | 4 +- core/profiles/standard/standard.install | 6 +- .../Config/Entity/ConfigEntityStorageTest.php | 24 +++++- .../Tests/Core/Config/ImmutableConfigTest.php | 70 +++++++++++++++ .../Core/Form/ConfigFormBaseTraitTest.php | 76 +++++++++++++++++ .../Core/Menu/StaticMenuLinkOverridesTest.php | 4 +- core/tests/Drupal/Tests/UnitTestCase.php | 25 ++++-- sites/default/default.settings.php | 13 ++- 107 files changed, 976 insertions(+), 201 deletions(-) create mode 100644 core/lib/Drupal/Core/Config/ImmutableConfig.php create mode 100644 core/lib/Drupal/Core/Config/ImmutableConfigException.php create mode 100644 core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php create mode 100644 core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php create mode 100644 core/tests/Drupal/Tests/Core/Form/ConfigFormBaseTraitTest.php diff --git a/core/includes/file.inc b/core/includes/file.inc index effb71c03d06..d47fbc44f054 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -1520,9 +1520,10 @@ function drupal_tempnam($directory, $prefix) { * A string containing the path to the temporary directory. */ function file_directory_temp() { - $config = \Drupal::config('system.file'); - $temporary_directory = $config->get('path.temporary'); + $temporary_directory = \Drupal::config('system.file')->get('path.temporary'); if (empty($temporary_directory)) { + // Needs set up. + $config = \Drupal::configFactory()->getEditable('system.file'); $temporary_directory = file_directory_os_temp(); if (empty($temporary_directory)) { diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 1ec434db09e6..d3d7a04cf4de 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1647,7 +1647,7 @@ function install_download_additional_translations_operations(&$install_state) { // If a non-English language was selected, change the default language and // remove English. if ($langcode != 'en') { - \Drupal::config('system.site')->set('langcode', $langcode)->save(); + \Drupal::configFactory()->getEditable('system.site')->set('langcode', $langcode)->save(); \Drupal::service('language.default')->set($language); if (empty($install_state['profile_info']['keep_english'])) { entity_delete_multiple('configurable_language', array('en')); diff --git a/core/includes/install.inc b/core/includes/install.inc index ad911db7ef72..e247378750d1 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -618,7 +618,7 @@ function drupal_install_system($install_state) { // Ensure default language is saved. if (isset($install_state['parameters']['langcode'])) { - \Drupal::config('system.site') + \Drupal::configFactory()->getEditable('system.site') ->set('langcode', $install_state['parameters']['langcode']) ->save(); } diff --git a/core/includes/module.inc b/core/includes/module.inc index 1ac014a1e2a5..f4fac6e85b2a 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -211,8 +211,7 @@ function drupal_required_modules() { * An integer representing the weight of the module. */ function module_set_weight($module, $weight) { - // Update the module weight in the config file that contains it. - $extension_config = \Drupal::config('core.extension'); + $extension_config = \Drupal::configFactory()->getEditable('core.extension'); if ($extension_config->get("module.$module") !== NULL) { $extension_config ->set("module.$module", $weight) diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 8e31869b5227..7b52d13181d3 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -298,8 +298,8 @@ public static function lock() { * a configuration file. For @code \Drupal::config('book.admin') @endcode, the config * object returned will contain the contents of book.admin configuration file. * - * @return \Drupal\Core\Config\Config - * A configuration object. + * @return \Drupal\Core\Config\ImmutableConfig + * An immutable configuration object. */ public static function config($name) { return static::$container->get('config.factory')->get($name); diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index ed9c28efb376..51ade6ce736f 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -79,8 +79,7 @@ public function __construct($name, StorageInterface $storage, EventDispatcherInt */ public function initWithData(array $data) { parent::initWithData($data); - $this->settingsOverrides = array(); - $this->moduleOverrides = array(); + $this->resetOverriddenData(); return $this; } diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index ce092d374ad3..46aaeada3218 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -102,18 +102,44 @@ public function getOverrideState() { return $this->useOverrides; } + /** + * {@inheritdoc} + */ + public function getEditable($name) { + $old_state = $this->getOverrideState(); + $this->setOverrideState(FALSE); + $config = $this->doGet($name, FALSE); + $this->setOverrideState($old_state); + return $config; + } + /** * {@inheritdoc} */ public function get($name) { - if ($config = $this->loadMultiple(array($name))) { + return $this->doGet($name); + } + + /** + * Returns a configuration object for a given name. + * + * @param string $name + * The name of the configuration object to construct. + * @param bool $immutable + * (optional) Create an immutable configuration object. Defaults to TRUE. + * + * @return \Drupal\Core\Config\Config|\Drupal\Core\Config\ImmutableConfig + * A configuration object. + */ + protected function doGet($name, $immutable = TRUE) { + if ($config = $this->doLoadMultiple(array($name), $immutable)) { return $config[$name]; } else { // If the configuration object does not exist in the configuration // storage, create a new object and add it to the static cache. - $cache_key = $this->getConfigCacheKey($name); - $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager); + $cache_key = $this->getConfigCacheKey($name, $immutable); + $this->cache[$cache_key] = $this->createConfigObject($name, $immutable); if ($this->useOverrides) { // Get and apply any overrides. @@ -134,10 +160,25 @@ public function get($name) { * {@inheritdoc} */ public function loadMultiple(array $names) { + return $this->doLoadMultiple($names); + } + + /** + * Returns a list of configuration objects for the given names. + * + * @param array $names + * List of names of configuration objects. + * @param bool $immutable + * (optional) Create an immutable configuration objects. Defaults to TRUE. + * + * @return \Drupal\Core\Config\Config[]|\Drupal\Core\Config\ImmutableConfig[] + * List of successfully loaded configuration objects, keyed by name. + */ + protected function doLoadMultiple(array $names, $immutable = TRUE) { $list = array(); foreach ($names as $key => $name) { - $cache_key = $this->getConfigCacheKey($name); + $cache_key = $this->getConfigCacheKey($name, $immutable); if (isset($this->cache[$cache_key])) { $list[$name] = $this->cache[$cache_key]; unset($names[$key]); @@ -156,9 +197,9 @@ public function loadMultiple(array $names) { } foreach ($storage_data as $name => $data) { - $cache_key = $this->getConfigCacheKey($name); + $cache_key = $this->getConfigCacheKey($name, $immutable); - $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager); + $this->cache[$cache_key] = $this->createConfigObject($name, $immutable); $this->cache[$cache_key]->initWithData($data); if ($this->useOverrides) { if (isset($module_overrides[$name])) { @@ -230,7 +271,7 @@ public function rename($old_name, $new_name) { // Prime the cache and load the configuration with the correct overrides. $config = $this->get($new_name); $this->eventDispatcher->dispatch(ConfigEvents::RENAME, new ConfigRenameEvent($config, $old_name)); - return $config; + return $this; } /** @@ -254,12 +295,14 @@ public function getCacheKeys() { * * @param string $name * The name of the configuration object. + * @param bool $immutable + * Whether or not the object is mutable. * * @return string * The cache key. */ - protected function getConfigCacheKey($name) { - return $name . ':' . implode(':', $this->getCacheKeys()); + protected function getConfigCacheKey($name, $immutable) { + return $name . ':' . implode(':', $this->getCacheKeys()) . ':' . ($immutable ? static::IMMUTABLE: static::MUTABLE); } /** @@ -294,7 +337,7 @@ public function listAll($prefix = '') { } /** - * Removes stale static cache entries when configuration is saved. + * Updates stale static cache entries when configuration is saved. * * @param ConfigCrudEvent $event * The configuration event. @@ -307,7 +350,9 @@ public function onConfigSave(ConfigCrudEvent $event) { foreach ($this->getConfigCacheKeys($saved_config->getName()) as $cache_key) { $cached_config = $this->cache[$cache_key]; if ($cached_config !== $saved_config) { - $this->cache[$cache_key]->setData($saved_config->getRawData()); + // We can not just update the data since other things about the object + // might have changed. For example, whether or not it is new. + $this->cache[$cache_key]->initWithData($saved_config->getRawData()); } } } @@ -341,4 +386,22 @@ public function addOverride(ConfigFactoryOverrideInterface $config_factory_overr $this->configFactoryOverrides[] = $config_factory_override; } + /** + * Creates a configuration object. + * + * @param string $name + * Configuration object name. + * @param bool $immutable + * Determines whether a mutable or immutable config object is returned. + * + * @return \Drupal\Core\Config\Config|\Drupal\Core\Config\ImmutableConfig + * The configuration object. + */ + protected function createConfigObject($name, $immutable) { + if ($immutable) { + return new ImmutableConfig($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager); + } + return new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager); + } + } diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php index d51e02346864..f74be94117c0 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php @@ -14,6 +14,16 @@ */ interface ConfigFactoryInterface { + /** + * Constant used in static cache keys for mutable config objects. + */ + const MUTABLE = 'mutable'; + + /** + * Constant used in static cache keys for immutable config objects. + */ + const IMMUTABLE = 'immutable'; + /** * Sets the override state. * @@ -33,26 +43,42 @@ public function setOverrideState($state); public function getOverrideState(); /** - * Returns a configuration object for a given name. + * Returns an immutable configuration object for a given name. * * @param string $name * The name of the configuration object to construct. * - * @return \Drupal\Core\Config\Config + * @return \Drupal\Core\Config\ImmutableConfig * A configuration object. */ public function get($name); + /** + * Returns an mutable configuration object for a given name. + * + * Should not be used for config that will have runtime effects. Therefore it + * is always loaded override free. + * + * @param string $name + * The name of the configuration object to construct. + * + * @return \Drupal\Core\Config\Config + * A configuration object. + */ + public function getEditable($name); + /** * Returns a list of configuration objects for the given names. * * This will pre-load all requested configuration objects does not create - * new configuration objects. + * new configuration objects. This method always return immutable objects. + * ConfigFactoryInterface::getEditable() should be used to retrieve mutable + * configuration objects, one by one. * * @param array $names * List of names of configuration objects. * - * @return \Drupal\Core\Config\Config[] + * @return \Drupal\Core\Config\ImmutableConfig[] * List of successfully loaded configuration objects, keyed by name. */ public function loadMultiple(array $names); @@ -76,8 +102,7 @@ public function reset($name = NULL); * @param string $new_name * The new name of the configuration object. * - * @return \Drupal\Core\Config\Config - * The renamed config object. + * @return $this */ public function rename($old_name, $new_name); diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php index a97cf7288dd1..da0fa989289c 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -224,7 +224,7 @@ public function uninstall($type, $name) { $config_names = $this->configFactory->listAll($name . '.'); foreach ($config_names as $config_name) { - $this->configFactory->get($config_name)->delete(); + $this->configFactory->getEditable($config_name)->delete(); } // Remove any matching configuration from collections. diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 7057491b7191..6626578a76a1 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -200,8 +200,7 @@ protected function doCreate(array $values) { */ protected function doDelete($entities) { foreach ($entities as $entity) { - $config = $this->configFactory->get($this->getPrefix() . $entity->id()); - $config->delete(); + $this->configFactory->getEditable($this->getPrefix() . $entity->id())->delete(); } } @@ -238,16 +237,15 @@ public function save(EntityInterface $entity) { protected function doSave($id, EntityInterface $entity) { $is_new = $entity->isNew(); $prefix = $this->getPrefix(); + $config_name = $prefix . $entity->id(); if ($id !== $entity->id()) { // Renaming a config object needs to cater for: // - Storage needs to access the original object. // - The object needs to be renamed/copied in ConfigFactory and reloaded. // - All instances of the object need to be renamed. - $config = $this->configFactory->rename($prefix . $id, $prefix . $entity->id()); - } - else { - $config = $this->configFactory->get($prefix . $id); + $this->configFactory->rename($prefix . $id, $config_name); } + $config = $this->configFactory->getEditable($config_name); // Retrieve the desired properties and set them in config. $config->setData($this->mapToStorageRecord($entity)); diff --git a/core/lib/Drupal/Core/Config/ImmutableConfig.php b/core/lib/Drupal/Core/Config/ImmutableConfig.php new file mode 100644 index 000000000000..61e7fdd099b9 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ImmutableConfig.php @@ -0,0 +1,61 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Config\ImmutableConfig. + */ + +namespace Drupal\Core\Config; + +use Drupal\Component\Utility\String; + +/** + * Defines the immutable configuration object. + * + * Encapsulates all capabilities needed for runtime configuration handling + * except being able to change the configuration. + * + * If you need to be able to change configuration use + * \Drupal\Core\Form\ConfigFormBaseTrait or + * \Drupal\Core\Config\ConfigFactoryInterface::getEditable(). + * + * @see \Drupal\Core\Form\ConfigFormBaseTrait + * @see \Drupal\Core\Config\ConfigFactoryInterface::getEditable() + * @see \Drupal\Core\Config\ConfigFactoryInterface::get() + * + * @ingroup config_api + */ +class ImmutableConfig extends Config { + + /** + * {@inheritdoc} + */ + public function set($key, $value) { + throw new ImmutableConfigException(String::format('Can not set values on immutable configuration !name:!key. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object', ['!name' => $this->getName(), '!key' => $key])); + } + + /** + * {@inheritdoc} + */ + public function clear($key) { + throw new ImmutableConfigException(String::format('Can not clear !key key in immutable configuration !name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object', ['!name' => $this->getName(), '!key' => $key])); + } + + /** + * {@inheritdoc} + */ + public function save() { + throw new ImmutableConfigException(String::format('Can not save immutable configuration !name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object', ['!name' => $this->getName()])); + } + + /** + * Deletes the configuration object. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ + public function delete() { + throw new ImmutableConfigException(String::format('Can not delete immutable configuration !name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object', ['!name' => $this->getName()])); + } + +} diff --git a/core/lib/Drupal/Core/Config/ImmutableConfigException.php b/core/lib/Drupal/Core/Config/ImmutableConfigException.php new file mode 100644 index 000000000000..4df074a55563 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ImmutableConfigException.php @@ -0,0 +1,16 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Config\ImmutableConfigException. + */ + +namespace Drupal\Core\Config; + +/** + * Exception throw when an immutable config object is altered. + * + * @see \Drupal\Core\Config\ImmutableConfig + */ +class ImmutableConfigException extends \LogicException { +} diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index 73278d32bf37..6cb8363e6d48 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -79,7 +79,7 @@ public function addUninstallValidator(ModuleUninstallValidatorInterface $uninsta * {@inheritdoc} */ public function install(array $module_list, $enable_dependencies = TRUE) { - $extension_config = \Drupal::config('core.extension'); + $extension_config = \Drupal::configFactory()->getEditable('core.extension'); if ($enable_dependencies) { // Get all module data so we can find dependencies and sort. $module_data = system_rebuild_module_data(); @@ -300,8 +300,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { return FALSE; } - // Only process currently installed modules. - $extension_config = \Drupal::config('core.extension'); + $extension_config = \Drupal::configFactory()->getEditable('core.extension'); $installed_modules = $extension_config->get('module') ?: array(); if (!$module_list = array_intersect_key($module_list, $installed_modules)) { // Nothing to do. All modules already uninstalled. @@ -387,8 +386,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { drupal_uninstall_schema($module); // Remove the module's entry from the config. - $extension_config = \Drupal::config('core.extension'); - $extension_config->clear("module.$module")->save(); + \Drupal::configFactory()->getEditable('core.extension')->clear("module.$module")->save(); // Update the module handler to remove the module. // The current ModuleHandler instance is obsolete with the kernel rebuild diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index 89ad50319ebd..2f0fd9498ab6 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -179,7 +179,7 @@ public function setDefault($name) { if (!isset($list[$name])) { throw new \InvalidArgumentException("$name theme is not installed."); } - $this->configFactory->get('system.theme') + $this->configFactory->getEditable('system.theme') ->set('default', $name) ->save(); return $this; @@ -189,7 +189,7 @@ public function setDefault($name) { * {@inheritdoc} */ public function install(array $theme_list, $install_dependencies = TRUE) { - $extension_config = $this->configFactory->get('core.extension'); + $extension_config = $this->configFactory->getEditable('core.extension'); $theme_data = $this->rebuildThemeData(); @@ -313,8 +313,8 @@ public function install(array $theme_list, $install_dependencies = TRUE) { * {@inheritdoc} */ public function uninstall(array $theme_list) { - $extension_config = $this->configFactory->get('core.extension'); - $theme_config = $this->configFactory->get('system.theme'); + $extension_config = $this->configFactory->getEditable('core.extension'); + $theme_config = $this->configFactory->getEditable('system.theme'); $list = $this->listInfo(); foreach ($theme_list as $key) { if (!isset($list[$key])) { diff --git a/core/lib/Drupal/Core/Form/ConfigFormBase.php b/core/lib/Drupal/Core/Form/ConfigFormBase.php index f58bc11b6e44..5ed650a613ca 100644 --- a/core/lib/Drupal/Core/Form/ConfigFormBase.php +++ b/core/lib/Drupal/Core/Form/ConfigFormBase.php @@ -15,6 +15,7 @@ * Base class for implementing system configuration forms. */ abstract class ConfigFormBase extends FormBase { + use ConfigFormBaseTrait; /** * Constructs a \Drupal\system\ConfigFormBase object. @@ -59,20 +60,4 @@ public function submitForm(array &$form, FormStateInterface $form_state) { drupal_set_message($this->t('The configuration options have been saved.')); } - /** - * {@inheritdoc} - * - * Overrides \Drupal\Core\Form\FormBase::config() so that configuration is - * returned override free. This ensures that overrides do not pollute saved - * configuration. - */ - protected function config($name) { - $config_factory = $this->configFactory(); - $old_state = $config_factory->getOverrideState(); - $config_factory->setOverrideState(FALSE); - $config = $config_factory->get($name); - $config_factory->setOverrideState($old_state); - return $config; - } - } diff --git a/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php b/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php new file mode 100644 index 000000000000..1cbac3c27c05 --- /dev/null +++ b/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php @@ -0,0 +1,77 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Form\ConfigFormBaseTrait. + */ + +namespace Drupal\Core\Form; + +use Drupal\Core\Config\ConfigFactoryInterface; + +/** + * Provides access to configuration for forms. + * + * This trait provides a config() method that returns override free and mutable + * config objects if the configuration name is in the array returned by the + * getEditableConfigNames() implementation. + * + * Forms that present configuration to the user have to take care not to save + * configuration overrides to the stored configuration since overrides are often + * environment specific. Default values of form elements should be obtained from + * override free configuration objects. However, if a form reacts to + * configuration in any way, for example sends an email to the system.site:mail + * address, then it is important that the value comes from a configuration + * object with overrides. Therefore, override free and editable configuration + * objects are limited to those listed by the getEditableConfigNames() method. + */ +trait ConfigFormBaseTrait { + + /** + * Retrieves a configuration object. + * + * Objects that use the trait need to implement the + * \Drupal\Core\Form\ConfigFormBaseTrait::getEditableConfigNames() to declare + * which configuration objects this method returns override free and mutable. + * This ensures that overrides do not pollute saved configuration. + * + * @param string $name + * The name of the configuration object to retrieve. The name corresponds to + * a configuration file. For @code \Drupal::config('book.admin') @endcode, + * the config object returned will contain the contents of book.admin + * configuration file. + * + * @return \Drupal\Core\Config\Config|\Drupal\Core\Config\ImmutableConfig + * A configuration object. + */ + protected function config($name) { + /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ + if (method_exists($this, 'configFactory')) { + $config_factory = $this->configFactory(); + } + elseif (property_exists($this, 'configFactory')) { + $config_factory = $this->configFactory; + } + if (!isset($config_factory) || !($config_factory instanceof ConfigFactoryInterface)) { + throw new \LogicException('No config factory available for ConfigFormBaseTrait'); + } + if (in_array($name, $this->getEditableConfigNames())) { + // Get a mutable object from the factory. + $config = $config_factory->getEditable($name); + } + else { + $config = $config_factory->get($name); + } + return $config; + } + + /** + * Gets the configuration names that will be editable. + * + * @return array + * An array of configuration object names that are editable if called in + * conjunction with the trait's config() method. + */ + abstract protected function getEditableConfigNames(); + +} diff --git a/core/lib/Drupal/Core/Form/FormBase.php b/core/lib/Drupal/Core/Form/FormBase.php index b60e9ed32cc6..d7c2bfde84ae 100644 --- a/core/lib/Drupal/Core/Form/FormBase.php +++ b/core/lib/Drupal/Core/Form/FormBase.php @@ -87,7 +87,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { * the config object returned will contain the contents of book.admin * configuration file. * - * @return \Drupal\Core\Config\Config + * @return \Drupal\Core\Config\ImmutableConfig * A configuration object. */ protected function config($name) { diff --git a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php index ba55764d4cfa..0354e25491fc 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php @@ -97,6 +97,17 @@ public function getFormId() { return 'install_configure_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return [ + 'system.date', + 'system.site', + 'update.settings', + ]; + } + /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php index 789e25845deb..a52601cdd79d 100644 --- a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php +++ b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php @@ -17,6 +17,10 @@ class StaticMenuLinkOverrides implements StaticMenuLinkOverridesInterface { /** * The config name used to store the overrides. * + * This configuration can not be overridden by configuration overrides because + * menu links and these overrides are cached in a way that is not override + * aware. + * * @var string */ protected $configName = 'core.menu.static_menu_link_overrides'; @@ -54,7 +58,8 @@ public function __construct(ConfigFactoryInterface $config_factory) { */ protected function getConfig() { if (empty($this->config)) { - $this->config = $this->configFactory->get($this->configName); + // Get an override free and editable configuration object. + $this->config = $this->configFactory->getEditable($this->configName); } return $this->config; } diff --git a/core/modules/aggregator/src/Form/SettingsForm.php b/core/modules/aggregator/src/Form/SettingsForm.php index ff6fd624f2dc..69c5ed67ad60 100644 --- a/core/modules/aggregator/src/Form/SettingsForm.php +++ b/core/modules/aggregator/src/Form/SettingsForm.php @@ -96,6 +96,13 @@ public function getFormId() { return 'aggregator_admin_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['aggregator.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php b/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php index c31b4ff46eba..cadd84b721d6 100644 --- a/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php +++ b/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php @@ -16,6 +16,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Datetime\DateFormatter; use Drupal\Core\Entity\Query\QueryInterface; +use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Routing\UrlGeneratorTrait; @@ -33,7 +34,7 @@ * ) */ class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface { - + use ConfigFormBaseTrait; use UrlGeneratorTrait; /** @@ -107,11 +108,19 @@ public static function create(ContainerInterface $container, array $configuratio ); } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['aggregator.settings']; + } + /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $processors = $this->configuration['processors']; + $config = $this->config('aggregator.settings'); + $processors = $config->get('processors'); $info = $this->getPluginDefinition(); $counts = array(3, 5, 10, 15, 20, 25); $items = array_map(function ($count) { @@ -135,7 +144,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $form['processors'][$info['id']]['aggregator_summary_items'] = array( '#type' => 'select', '#title' => t('Number of items shown in listing pages'), - '#default_value' => $this->configuration['source']['list_max'], + '#default_value' => $config->get('source.list_max'), '#empty_value' => 0, '#options' => $items, ); @@ -143,7 +152,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $form['processors'][$info['id']]['aggregator_clear'] = array( '#type' => 'select', '#title' => t('Discard items older than'), - '#default_value' => $this->configuration['items']['expire'], + '#default_value' => $config->get('items.expire'), '#options' => $period, '#description' => t('Requires a correctly configured <a href="@cron">cron maintenance task</a>.', array('@cron' => $this->url('system.status'))), ); @@ -156,7 +165,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $form['processors'][$info['id']]['aggregator_teaser_length'] = array( '#type' => 'select', '#title' => t('Length of trimmed description'), - '#default_value' => $this->configuration['items']['teaser_length'], + '#default_value' => $config->get('items.teaser_length'), '#options' => $options, '#description' => t('The maximum number of characters used in the trimmed version of content.'), ); @@ -275,7 +284,7 @@ public function getConfiguration() { * {@inheritdoc} */ public function setConfiguration(array $configuration) { - $config = $this->configFactory->get('aggregator.settings'); + $config = $this->config('aggregator.settings'); foreach ($configuration as $key => $value) { $config->set($key, $value); } diff --git a/core/modules/aggregator/tests/modules/aggregator_test/src/Plugin/aggregator/processor/TestProcessor.php b/core/modules/aggregator/tests/modules/aggregator_test/src/Plugin/aggregator/processor/TestProcessor.php index c9307015f3b4..1a6ee19b4f32 100644 --- a/core/modules/aggregator/tests/modules/aggregator_test/src/Plugin/aggregator/processor/TestProcessor.php +++ b/core/modules/aggregator/tests/modules/aggregator_test/src/Plugin/aggregator/processor/TestProcessor.php @@ -11,6 +11,7 @@ use Drupal\aggregator\Plugin\ProcessorInterface; use Drupal\aggregator\FeedInterface; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -27,6 +28,7 @@ * ) */ class TestProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface { + use ConfigFormBaseTrait; /** * Contains the configuration object factory. @@ -64,11 +66,18 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition); } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['aggregator_test.settings']; + } + /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $processors = $this->configFactory->get('aggregator.settings')->get('processors'); + $processors = $this->config('aggregator.settings')->get('processors'); $info = $this->getPluginDefinition(); $form['processors'][$info['id']] = array( @@ -134,7 +143,7 @@ public function getConfiguration() { * {@inheritdoc} */ public function setConfiguration(array $configuration) { - $config = $this->configFactory->get('aggregator_test.settings'); + $config = $this->config('aggregator_test.settings'); foreach ($configuration as $key => $value) { $config->set($key, $value); } diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 9c7ab5503f49..a11f74d4928d 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -559,7 +559,7 @@ function book_type_is_allowed($type) { */ function book_node_type_update(NodeTypeInterface $type) { if ($type->getOriginalId() != $type->id()) { - $config = \Drupal::config('book.settings'); + $config = \Drupal::configFactory()->getEditable('book.settings'); // Update the list of node types that are allowed to be added to books. $allowed_types = $config->get('allowed_types'); $old_key = array_search($type->getOriginalId(), $allowed_types); diff --git a/core/modules/book/src/Form/BookSettingsForm.php b/core/modules/book/src/Form/BookSettingsForm.php index fe1db372b7d4..0db0dc5ca950 100644 --- a/core/modules/book/src/Form/BookSettingsForm.php +++ b/core/modules/book/src/Form/BookSettingsForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'book_admin_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['book.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/ckeditor/src/Tests/CKEditorTest.php b/core/modules/ckeditor/src/Tests/CKEditorTest.php index dc5f2350edfc..572e8abf242f 100644 --- a/core/modules/ckeditor/src/Tests/CKEditorTest.php +++ b/core/modules/ckeditor/src/Tests/CKEditorTest.php @@ -402,7 +402,7 @@ function testJSTranslation() { protected function assertCKEditorLanguage($langcode = 'fr') { // Set French as the site default language. ConfigurableLanguage::createFromLangcode('fr')->save(); - \Drupal::config('system.site')->set('langcode', 'fr')->save(); + $this->config('system.site')->set('langcode', 'fr')->save(); // Reset the language manager so new negotiations attempts will fall back on // French. Reinject the language manager CKEditor to use the current one. diff --git a/core/modules/color/color.module b/core/modules/color/color.module index 5ad67f2084f1..8bbb03551a2b 100644 --- a/core/modules/color/color.module +++ b/core/modules/color/color.module @@ -169,7 +169,10 @@ function color_get_palette($theme, $default = FALSE) { // Load variable. // @todo Default color config should be moved to yaml in the theme. - return \Drupal::config('color.theme.' . $theme)->get('palette') ?: $palette; + // Getting a mutable override-free object because this function is only used + // in forms. Color configuration is used to write CSS to the file system + // making configuration overrides pointless. + return \Drupal::configFactory()->getEditable('color.theme.' . $theme)->get('palette') ?: $palette; } /** @@ -196,7 +199,11 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them // See if we're using a predefined scheme. // Note: we use the original theme when the default scheme is chosen. - $current_scheme = \Drupal::config('color.theme.' . $theme)->get('palette'); + // Note: we use configuration without overrides since this information is used + // in a form and therefore without doing this would bleed overrides into + // active configuration. Furthermore, color configuration is used to write + // CSS to the file system making configuration overrides pointless. + $current_scheme = \Drupal::configFactory()->getEditable('color.theme.' . $theme)->get('palette'); foreach ($schemes as $key => $scheme) { if ($current_scheme == $scheme) { $scheme_name = $key; @@ -213,6 +220,7 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them } // Add scheme selector. + $default_palette = color_get_palette($theme, TRUE); $form['scheme'] = array( '#type' => 'select', '#title' => t('Color set'), @@ -226,7 +234,7 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them // Add custom JavaScript. 'drupalSettings' => [ 'color' => [ - 'reference' => color_get_palette($theme, TRUE), + 'reference' => $default_palette, 'schemes' => $schemes, ], 'gradients' => $info['gradients'], @@ -234,8 +242,8 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them ), ); - // Add palette fields. - $palette = color_get_palette($theme); + // Add palette fields. Use the configuration if available. + $palette = $current_scheme ?: $default_palette; $names = $info['fields']; $form['palette']['#tree'] = TRUE; foreach ($palette as $name => $value) { @@ -361,7 +369,7 @@ function color_scheme_form_submit($form, FormStateInterface $form_state) { return; } - $config = \Drupal::config('color.theme.' . $theme); + $config = \Drupal::configFactory()->getEditable('color.theme.' . $theme); // Resolve palette. if ($scheme != '') { @@ -620,7 +628,7 @@ function _color_render_images($theme, &$info, &$paths, $palette) { if ($file == 'screenshot.png') { $slice = imagecreatetruecolor(150, 90); imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height); - \Drupal::config('color.theme.' . $theme) + \Drupal::configFactory()->getEditable('color.theme.' . $theme) ->set('screenshot', $image) ->save(); } diff --git a/core/modules/config/src/Form/ConfigSingleImportForm.php b/core/modules/config/src/Form/ConfigSingleImportForm.php index 58156b094bce..ee1dfde1603f 100644 --- a/core/modules/config/src/Form/ConfigSingleImportForm.php +++ b/core/modules/config/src/Form/ConfigSingleImportForm.php @@ -243,7 +243,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // If a simple configuration file was added, set the data and save. if ($this->data['config_type'] === 'system.simple') { - $this->config($this->data['config_name'])->setData($this->data['import'])->save(); + $this->configFactory()->getEditable($this->data['config_name'])->setData($this->data['import'])->save(); drupal_set_message($this->t('The %name configuration was imported.', array('%name' => $this->data['config_name']))); } // For a config entity, create an entity and save it. diff --git a/core/modules/config/src/Tests/ConfigCRUDTest.php b/core/modules/config/src/Tests/ConfigCRUDTest.php index 25391fef7cf3..f54caed17183 100644 --- a/core/modules/config/src/Tests/ConfigCRUDTest.php +++ b/core/modules/config/src/Tests/ConfigCRUDTest.php @@ -249,7 +249,7 @@ public function testDataTypes() { \Drupal::service('module_installer')->install(array('config_test')); $storage = new DatabaseStorage($this->container->get('database'), 'config'); $name = 'config_test.types'; - $config = $this->container->get('config.factory')->get($name); + $config = $this->config($name); $original_content = file_get_contents(drupal_get_path('module', 'config_test') . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY . "/$name.yml"); $this->verbose('<pre>' . $original_content . "\n" . var_export($storage->read($name), TRUE)); @@ -299,7 +299,7 @@ public function testDataTypes() { // also fails. $typed_config_manager = $this->container->get('config.typed'); $config_name = 'config_test.no_schema'; - $config = $this->container->get('config.factory')->get($config_name); + $config = $this->config($config_name); $this->assertFalse($typed_config_manager->hasConfigSchema($config_name)); try { diff --git a/core/modules/config/src/Tests/ConfigEventsTest.php b/core/modules/config/src/Tests/ConfigEventsTest.php index b4f72794ad1a..fb6eca61eaf7 100644 --- a/core/modules/config/src/Tests/ConfigEventsTest.php +++ b/core/modules/config/src/Tests/ConfigEventsTest.php @@ -67,11 +67,14 @@ function testConfigRenameEvent() { $GLOBALS['config'][$name] = array('key' => 'overridden'); $GLOBALS['config'][$new_name] = array('key' => 'new overridden'); - $config = \Drupal::config($name); + $config = $this->config($name); $config->set('key', 'initial')->save(); $event = \Drupal::state()->get('config_events_test.event', array()); $this->assertIdentical($event['event_name'], ConfigEvents::SAVE); - $this->assertIdentical($event['current_config_data'], array('key' => 'overridden')); + $this->assertIdentical($event['current_config_data'], array('key' => 'initial')); + + // Override applies when getting runtime config. + $this->assertEqual($GLOBALS['config'][$name], \Drupal::config($name)->get()); \Drupal::configFactory()->rename($name, $new_name); $event = \Drupal::state()->get('config_events_test.event', array()); diff --git a/core/modules/config/src/Tests/ConfigLanguageOverrideTest.php b/core/modules/config/src/Tests/ConfigLanguageOverrideTest.php index 9de963cc77f6..cc754d4b3c9d 100644 --- a/core/modules/config/src/Tests/ConfigLanguageOverrideTest.php +++ b/core/modules/config/src/Tests/ConfigLanguageOverrideTest.php @@ -76,7 +76,7 @@ function testConfigLanguageOverride() { // Test how overrides react to base configuration changes. Set up some base // values. - \Drupal::config('config_test.foo') + \Drupal::configFactory()->getEditable('config_test.foo') ->set('value', array('key' => 'original')) ->set('label', 'Original') ->save(); @@ -94,6 +94,7 @@ function testConfigLanguageOverride() { $this->assertIdentical($config->get('value'), array('key' => 'override')); // Ensure renaming the config will rename the override. + \Drupal::languageManager()->setConfigOverrideLanguage(language_load('en')); \Drupal::configFactory()->rename('config_test.foo', 'config_test.bar'); $config = \Drupal::config('config_test.bar'); $this->assertEqual($config->get('value'), array('key' => 'original')); @@ -108,7 +109,7 @@ function testConfigLanguageOverride() { $this->assertEqual($override->get('value'), array('key' => 'override')); // Ensure changing data in the config will update the overrides. - $config = \Drupal::config('config_test.bar')->clear('value.key')->save(); + $config = \Drupal::configFactory()->getEditable('config_test.bar')->clear('value.key')->save(); $this->assertEqual($config->get('value'), array()); $override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.bar'); $this->assertFalse($override->isNew()); @@ -119,7 +120,7 @@ function testConfigLanguageOverride() { $this->assertEqual($override->get('value'), NULL); // Ensure deleting the config will delete the override. - \Drupal::configFactory()->get('config_test.bar')->delete(); + \Drupal::configFactory()->getEditable('config_test.bar')->delete(); $override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.bar'); $this->assertTrue($override->isNew()); $this->assertEqual($override->get('value'), NULL); diff --git a/core/modules/config/src/Tests/ConfigModuleOverridesTest.php b/core/modules/config/src/Tests/ConfigModuleOverridesTest.php index 41f144c32b03..923b2f0deeee 100644 --- a/core/modules/config/src/Tests/ConfigModuleOverridesTest.php +++ b/core/modules/config/src/Tests/ConfigModuleOverridesTest.php @@ -32,7 +32,7 @@ public function testSimpleModuleOverrides() { $non_overridden_slogan = 'Yay for defaults!'; $config_factory = $this->container->get('config.factory'); $config_factory - ->get($name) + ->getEditable($name) ->set('name', $non_overridden_name) ->set('slogan', $non_overridden_slogan) ->save(); diff --git a/core/modules/config/src/Tests/ConfigOverrideTest.php b/core/modules/config/src/Tests/ConfigOverrideTest.php index 38ba0a1e581f..75088962ddca 100644 --- a/core/modules/config/src/Tests/ConfigOverrideTest.php +++ b/core/modules/config/src/Tests/ConfigOverrideTest.php @@ -55,14 +55,22 @@ function testConfOverride() { $this->assertFalse(isset($data['baz'])); $this->assertIdentical($data['404'], $expected_original_data['404']); - // Get the configuration object in with overrides. - $config = \Drupal::config('config_test.system'); + // Get the configuration object with overrides. + $config = \Drupal::configFactory()->get('config_test.system'); // Verify that it contains the overridden data from $config. $this->assertIdentical($config->get('foo'), $overrides['config_test.system']['foo']); $this->assertIdentical($config->get('baz'), $overrides['config_test.system']['baz']); $this->assertIdentical($config->get('404'), $overrides['config_test.system']['404']); + // Get the configuration object which does not have overrides. + $config = \Drupal::configFactory()->getEditable('config_test.system'); + + // Verify that it does not contains the overridden data from $config. + $this->assertIdentical($config->get('foo'), $expected_original_data['foo']); + $this->assertIdentical($config->get('baz'), NULL); + $this->assertIdentical($config->get('404'), $expected_original_data['404']); + // Set the value for 'baz' (on the original data). $expected_original_data['baz'] = 'original baz'; $config->set('baz', $expected_original_data['baz']); @@ -71,11 +79,6 @@ function testConfOverride() { $expected_original_data['404'] = 'original 404'; $config->set('404', $expected_original_data['404']); - // Verify that it still contains the overridden data from $config. - $this->assertIdentical($config->get('foo'), $overrides['config_test.system']['foo']); - $this->assertIdentical($config->get('baz'), $overrides['config_test.system']['baz']); - $this->assertIdentical($config->get('404'), $overrides['config_test.system']['404']); - // Save the configuration object (having overrides applied). $config->save(); @@ -85,6 +88,11 @@ function testConfOverride() { $this->assertIdentical($config->get('baz'), $overrides['config_test.system']['baz']); $this->assertIdentical($config->get('404'), $overrides['config_test.system']['404']); + // Verify that raw config data has changed. + $this->assertIdentical($config->getOriginal('foo', FALSE), $expected_original_data['foo']); + $this->assertIdentical($config->getOriginal('baz', FALSE), $expected_original_data['baz']); + $this->assertIdentical($config->getOriginal('404', FALSE), $expected_original_data['404']); + // Write file to staging. $staging = $this->container->get('config.storage.staging'); $expected_new_data = array( @@ -118,7 +126,7 @@ function testConfOverride() { $this->assertIdentical($config->get('key'), 'override'); $old_state = \Drupal::configFactory()->getOverrideState(); \Drupal::configFactory()->setOverrideState(FALSE); - $config_raw = \Drupal::config('config_test.new'); + $config_raw = \Drupal::configFactory()->getEditable('config_test.new'); $this->assertIdentical($config_raw->get('key'), NULL); $config_raw ->set('key', 'raw') diff --git a/core/modules/config/src/Tests/ConfigOverridesPriorityTest.php b/core/modules/config/src/Tests/ConfigOverridesPriorityTest.php index 1fd05fa4dc2c..0cf8f0bcb487 100644 --- a/core/modules/config/src/Tests/ConfigOverridesPriorityTest.php +++ b/core/modules/config/src/Tests/ConfigOverridesPriorityTest.php @@ -41,7 +41,7 @@ public function testOverridePriorities() { /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */ $config_factory = $this->container->get('config.factory'); $config_factory - ->get('system.site') + ->getEditable('system.site') ->set('name', $non_overridden_name) ->set('slogan', $non_overridden_slogan) ->set('mail', $non_overridden_mail) diff --git a/core/modules/config/tests/config_test/src/SchemaListenerController.php b/core/modules/config/tests/config_test/src/SchemaListenerController.php index baf297039777..1a6b28c3f827 100644 --- a/core/modules/config/tests/config_test/src/SchemaListenerController.php +++ b/core/modules/config/tests/config_test/src/SchemaListenerController.php @@ -7,20 +7,41 @@ namespace Drupal\config_test; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Schema\SchemaIncompleteException; use Drupal\Core\Controller\ControllerBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Controller for testing \Drupal\Core\Config\Testing\ConfigSchemaChecker. */ class SchemaListenerController extends ControllerBase { + /** + * Constructs the SchemaListenerController object. + * + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The config factory. + */ + public function __construct(ConfigFactoryInterface $config_factory) { + $this->configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory') + ); + } + /** * Tests the WebTestBase tests can use strict schema checking. */ public function test() { try { - $this->config('config_schema_test.schemaless')->set('foo', 'bar')->save(); + $this->configFactory->getEditable('config_schema_test.schemaless')->set('foo', 'bar')->save(); } catch (SchemaIncompleteException $e) { return [ diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php index 5a5f896eb676..e1ce0f632e92 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php @@ -759,7 +759,7 @@ public function testTextFormatTranslation() { // security vulnerabilities. $config_factory ->setOverrideState(FALSE) - ->get('config_translation_test.content') + ->getEditable('config_translation_test.content') ->set('content.format', 'full_html') ->save(); diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index c56633f860da..7444b6ef0e53 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -181,7 +181,7 @@ function contact_user_profile_form_submit($form, FormStateInterface $form_state) * * Add the default personal contact setting on the user settings page. * - * @see user_admin_settings() + * @see \Drupal\user\AccountSettingsForm */ function contact_form_user_admin_settings_alter(&$form, FormStateInterface $form_state) { $form['contact'] = array( @@ -194,7 +194,7 @@ function contact_form_user_admin_settings_alter(&$form, FormStateInterface $form '#type' => 'checkbox', '#title' => t('Enable the personal contact form by default for new users'), '#description' => t('Changing this setting will not affect existing users.'), - '#default_value' => \Drupal::config('contact.settings')->get('user_default_enabled'), + '#default_value' => \Drupal::configFactory()->getEditable('contact.settings')->get('user_default_enabled'), ); // Add submit handler to save contact configuration. $form['#submit'][] = 'contact_form_user_admin_settings_submit'; @@ -206,7 +206,7 @@ function contact_form_user_admin_settings_alter(&$form, FormStateInterface $form * @see contact_form_user_admin_settings_alter() */ function contact_form_user_admin_settings_submit($form, FormStateInterface $form_state) { - \Drupal::config('contact.settings') + \Drupal::configFactory()->getEditable('contact.settings') ->set('user_default_enabled', $form_state->getValue('contact_default_status')) ->save(); } diff --git a/core/modules/contact/src/ContactFormEditForm.php b/core/modules/contact/src/ContactFormEditForm.php index 123ba38cc314..420be7da1f8f 100644 --- a/core/modules/contact/src/ContactFormEditForm.php +++ b/core/modules/contact/src/ContactFormEditForm.php @@ -7,14 +7,25 @@ namespace Drupal\contact; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\FormStateInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base form for contact form edit forms. */ class ContactFormEditForm extends EntityForm { + use ConfigFormBaseTrait; + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['contact.settings']; + } /** * {@inheritdoc} diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module index e8568d4c5d43..570aaa401671 100644 --- a/core/modules/dblog/dblog.module +++ b/core/modules/dblog/dblog.module @@ -98,7 +98,7 @@ function dblog_form_system_logging_settings_alter(&$form, FormStateInterface $fo $form['dblog_row_limit'] = array( '#type' => 'select', '#title' => t('Database log messages to keep'), - '#default_value' => \Drupal::config('dblog.settings')->get('row_limit'), + '#default_value' => \Drupal::configFactory()->getEditable('dblog.settings')->get('row_limit'), '#options' => array(0 => t('All')) + array_combine($row_limits, $row_limits), '#description' => t('The maximum number of messages to keep in the database log. Requires a <a href="@cron">cron maintenance task</a>.', array('@cron' => \Drupal::url('system.status'))) ); @@ -112,5 +112,5 @@ function dblog_form_system_logging_settings_alter(&$form, FormStateInterface $fo * @see dblog_form_system_logging_settings_alter() */ function dblog_logging_settings_submit($form, FormStateInterface $form_state) { - \Drupal::config('dblog.settings')->set('row_limit', $form_state->getValue('dblog_row_limit'))->save(); + \Drupal::configFactory()->getEditable('dblog.settings')->set('row_limit', $form_state->getValue('dblog_row_limit'))->save(); } diff --git a/core/modules/forum/src/ForumSettingsForm.php b/core/modules/forum/src/ForumSettingsForm.php index 77f176ddd3e6..f2b43c4a9334 100644 --- a/core/modules/forum/src/ForumSettingsForm.php +++ b/core/modules/forum/src/ForumSettingsForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'forum_admin_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['forum.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/language.module b/core/modules/language/language.module index ddf580403110..d0b9aabc4b1c 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -339,7 +339,9 @@ function language_negotiation_url_prefixes_update() { * Saves language prefix settings. */ function language_negotiation_url_prefixes_save(array $prefixes) { - \Drupal::config('language.negotiation') + // @todo https://www.drupal.org/node/2403229 $prefixes can contain + // configuration overrides. + \Drupal::configFactory()->getEditable('language.negotiation') ->set('url.prefixes', $prefixes) ->save(); } @@ -355,7 +357,9 @@ function language_negotiation_url_domains() { * Saves the language domain settings. */ function language_negotiation_url_domains_save(array $domains) { - \Drupal::config('language.negotiation') + // @todo https://www.drupal.org/node/2403229 $domains can contain + // configuration overrides. + \Drupal::configFactory()->getEditable('language.negotiation') ->set('url.domains', $domains) ->save(); } @@ -492,7 +496,7 @@ function language_form_alter(&$form, FormStateInterface $form_state) { * @see language_form_system_regional_settings_alter() */ function language_system_regional_settings_form_submit($form, FormStateInterface $form_state) { - \Drupal::config('system.site')->set('langcode', $form_state->getValue('site_default_language'))->save(); + \Drupal::configFactory()->getEditable('system.site')->set('langcode', $form_state->getValue('site_default_language'))->save(); } /** diff --git a/core/modules/language/src/ConfigurableLanguageInterface.php b/core/modules/language/src/ConfigurableLanguageInterface.php index a4b794e1aa0a..994f6c1fa651 100644 --- a/core/modules/language/src/ConfigurableLanguageInterface.php +++ b/core/modules/language/src/ConfigurableLanguageInterface.php @@ -16,4 +16,15 @@ */ interface ConfigurableLanguageInterface extends ConfigEntityInterface, LanguageInterface { + /** + * Sets the weight of the language. + * + * @param int $weight + * The weight, used to order languages with larger positive weights sinking + * items toward the bottom of lists. + * + * @return $this + */ + public function setWeight($weight); + } diff --git a/core/modules/language/src/ConfigurableLanguageManager.php b/core/modules/language/src/ConfigurableLanguageManager.php index e17b3d2eda9b..a4ca11b6a761 100644 --- a/core/modules/language/src/ConfigurableLanguageManager.php +++ b/core/modules/language/src/ConfigurableLanguageManager.php @@ -195,7 +195,7 @@ public function getDefinedLanguageTypesInfo() { * {@inheritdoc} */ public function saveLanguageTypesConfiguration(array $values) { - $config = $this->configFactory->get('language.types'); + $config = $this->configFactory->getEditable('language.types'); if (isset($values['configurable'])) { $config->set('configurable', $values['configurable']); } @@ -343,23 +343,21 @@ public function getNativeLanguages() { * {@inheritdoc} */ public function updateLockedLanguageWeights() { - $max_weight = 0; + // Get the weight of the last configurable language. + $configurable_languages = $this->getLanguages(LanguageInterface::STATE_CONFIGURABLE); + $max_weight = end($configurable_languages)->getWeight(); - // Get maximum weight to update the system languages to keep them on bottom. - foreach ($this->getLanguages(LanguageInterface::STATE_CONFIGURABLE) as $language) { - if (!$language->isLocked()) { - $max_weight = max($max_weight, $language->getWeight()); - } - } - - // Loop locked languages to maintain the existing order. $locked_languages = $this->getLanguages(LanguageInterface::STATE_LOCKED); - $config_ids = array_map(function($language) { return 'language.entity.' . $language->getId(); }, $locked_languages); - foreach ($this->configFactory->loadMultiple($config_ids) as $config) { - // Update system languages weight. - $max_weight++; - $config->set('weight', $max_weight); - $config->save(); + // Update locked language weights to maintain the existing order, if + // necessary. + if (reset($locked_languages)->getWeight() <= $max_weight) { + foreach ($locked_languages as $language) { + // Update system languages weight. + $max_weight++; + ConfigurableLanguage::load($language->getId()) + ->setWeight($max_weight) + ->save(); + } } } diff --git a/core/modules/language/src/Entity/ConfigurableLanguage.php b/core/modules/language/src/Entity/ConfigurableLanguage.php index f2e128ba3455..e52f763946c4 100644 --- a/core/modules/language/src/Entity/ConfigurableLanguage.php +++ b/core/modules/language/src/Entity/ConfigurableLanguage.php @@ -130,7 +130,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { $language_manager = \Drupal::languageManager(); $language_manager->reset(); - if ($language_manager instanceof ConfigurableLanguageManagerInterface) { + if (!$this->isLocked() && $language_manager instanceof ConfigurableLanguageManagerInterface) { $language_manager->updateLockedLanguageWeights(); } @@ -230,6 +230,14 @@ public function getWeight() { return $this->weight; } + /** + * {@inheritdoc} + */ + public function setWeight($weight) { + $this->weight = $weight; + return $this; + } + /** * Creates a configurable language object from a langcode. * diff --git a/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php b/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php index 64f199306a86..1dc1447522de 100644 --- a/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php +++ b/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php @@ -7,6 +7,7 @@ namespace Drupal\language\Form; +use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; @@ -16,6 +17,7 @@ * Defines a confirmation form for deleting a browser language negotiation mapping. */ class NegotiationBrowserDeleteForm extends ConfirmFormBase { + use ConfigFormBaseTrait; /** * The browser language code to be deleted. @@ -24,6 +26,14 @@ class NegotiationBrowserDeleteForm extends ConfirmFormBase { */ protected $browserLangcode; + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.mappings']; + } + + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/Form/NegotiationBrowserForm.php b/core/modules/language/src/Form/NegotiationBrowserForm.php index d7722141f317..14ebb625985f 100644 --- a/core/modules/language/src/Form/NegotiationBrowserForm.php +++ b/core/modules/language/src/Form/NegotiationBrowserForm.php @@ -53,6 +53,13 @@ public function getFormId() { return 'language_negotiation_configure_browser_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.mappings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/Form/NegotiationConfigureForm.php b/core/modules/language/src/Form/NegotiationConfigureForm.php index ca208018fd5d..d9cf42051aa6 100644 --- a/core/modules/language/src/Form/NegotiationConfigureForm.php +++ b/core/modules/language/src/Form/NegotiationConfigureForm.php @@ -118,6 +118,13 @@ public function getFormID() { return 'language_negotiation_configure_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.types']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/Form/NegotiationSelectedForm.php b/core/modules/language/src/Form/NegotiationSelectedForm.php index 5b5d5a978371..57194f96fd08 100644 --- a/core/modules/language/src/Form/NegotiationSelectedForm.php +++ b/core/modules/language/src/Form/NegotiationSelectedForm.php @@ -23,6 +23,13 @@ public function getFormId() { return 'language_negotiation_configure_selected_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.negotiation']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/Form/NegotiationSessionForm.php b/core/modules/language/src/Form/NegotiationSessionForm.php index a0bd7779c9f2..fff1dd59902c 100644 --- a/core/modules/language/src/Form/NegotiationSessionForm.php +++ b/core/modules/language/src/Form/NegotiationSessionForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'language_negotiation_configure_session_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.negotiation']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/Form/NegotiationUrlForm.php b/core/modules/language/src/Form/NegotiationUrlForm.php index 979cca9038f4..fa1cd3eada7f 100644 --- a/core/modules/language/src/Form/NegotiationUrlForm.php +++ b/core/modules/language/src/Form/NegotiationUrlForm.php @@ -56,6 +56,13 @@ public function getFormId() { return 'language_negotiation_configure_url_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['language.negotiation']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/language/src/LanguageNegotiator.php b/core/modules/language/src/LanguageNegotiator.php index af2d9529c4e7..bc924fbf2a50 100644 --- a/core/modules/language/src/LanguageNegotiator.php +++ b/core/modules/language/src/LanguageNegotiator.php @@ -286,7 +286,7 @@ function saveConfiguration($type, $enabled_methods) { unset($enabled_methods[$method_id]); } } - $this->configFactory->get('language.types')->set('negotiation.' . $type . '.enabled', $enabled_methods)->save(); + $this->configFactory->getEditable('language.types')->set('negotiation.' . $type . '.enabled', $enabled_methods)->save(); } /** diff --git a/core/modules/language/tests/language_test/language_test.module b/core/modules/language/tests/language_test/language_test.module index 0a891982ada1..2ca1ff5eafac 100644 --- a/core/modules/language/tests/language_test/language_test.module +++ b/core/modules/language/tests/language_test/language_test.module @@ -45,10 +45,11 @@ function language_test_language_types_info_alter(array &$language_types) { unset($language_types[LanguageInterface::TYPE_CONTENT]['fixed']); // By default languages are not configurable. Make // LanguageInterface::TYPE_CONTENT configurable. - $configurable = \Drupal::config('language.types')->get('configurable'); + $config = \Drupal::configFactory()->getEditable('language.types'); + $configurable = $config->get('configurable'); if (!in_array(LanguageInterface::TYPE_CONTENT, $configurable)) { $configurable[] = LanguageInterface::TYPE_CONTENT; - \Drupal::config('language.types')->set('configurable', $configurable)->save(); + $config->set('configurable', $configurable)->save(); } } } diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 8aa8d82370f4..81aadf534b4e 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -16,7 +16,7 @@ function locale_install() { // Create the interface translations directory and ensure it's writable. if (!$directory = \Drupal::config('locale.settings')->get('translation.path')) { $directory = conf_path() . '/files/translations'; - \Drupal::config('locale.settings')->set('translation.path', $directory)->save(); + \Drupal::configFactory()->getEditable('locale.settings')->set('translation.path', $directory)->save(); } file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); } diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 9e09a4636fea..52a5eb9e2dca 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -647,7 +647,7 @@ function locale_form_language_admin_edit_form_alter(&$form, FormStateInterface $ $form['locale_translate_english'] = array( '#title' => t('Enable interface translation to English'), '#type' => 'checkbox', - '#default_value' => locale_translate_english(), + '#default_value' => \Drupal::configFactory()->getEditable('locale.settings')->get('translate_english'), ); $form['actions']['submit']['#submit'][] = 'locale_form_language_admin_edit_form_alter_submit'; } @@ -657,7 +657,7 @@ function locale_form_language_admin_edit_form_alter(&$form, FormStateInterface $ * Form submission handler for language_admin_edit_form(). */ function locale_form_language_admin_edit_form_alter_submit($form, FormStateInterface $form_state) { - \Drupal::config('locale.settings')->set('translate_english', intval($form_state->getValue('locale_translate_english')))->save(); + \Drupal::configFactory()->getEditable('locale.settings')->set('translate_english', intval($form_state->getValue('locale_translate_english')))->save(); } /** diff --git a/core/modules/locale/src/Form/LocaleSettingsForm.php b/core/modules/locale/src/Form/LocaleSettingsForm.php index 16c2087c27ee..4ff2c3332453 100644 --- a/core/modules/locale/src/Form/LocaleSettingsForm.php +++ b/core/modules/locale/src/Form/LocaleSettingsForm.php @@ -21,6 +21,13 @@ public function getFormId() { return 'locale_translate_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['locale.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/locale/src/Tests/LocaleUpdateBase.php b/core/modules/locale/src/Tests/LocaleUpdateBase.php index 4a92a3051752..7e17c892e152 100644 --- a/core/modules/locale/src/Tests/LocaleUpdateBase.php +++ b/core/modules/locale/src/Tests/LocaleUpdateBase.php @@ -60,7 +60,7 @@ protected function setUp() { // Update module should not go out to d.o to check for updates. We override // the url to the default update_test xml path. But without providing // a mock xml file, no update data will be found. - \Drupal::config('update.settings')->set('fetch.url', _url('update-test', array('absolute' => TRUE)))->save(); + $this->config('update.settings')->set('fetch.url', _url('update-test', array('absolute' => TRUE)))->save(); // Setup timestamps to identify old and new translation sources. $this->timestampOld = REQUEST_TIME - 300; @@ -70,7 +70,7 @@ protected function setUp() { // Enable import of translations. By default this is disabled for automated // tests. - \Drupal::config('locale.settings') + $this->config('locale.settings') ->set('translation.import_enabled', TRUE) ->save(); } @@ -84,7 +84,7 @@ protected function setUp() { */ protected function setTranslationsDirectory($path) { file_prepare_directory($path, FILE_CREATE_DIRECTORY); - \Drupal::config('locale.settings')->set('translation.path', $path)->save(); + $this->config('locale.settings')->set('translation.path', $path)->save(); } /** @@ -180,7 +180,7 @@ protected function makePoFile($path, $filename, $timestamp = NULL, array $transl * imported. */ protected function setTranslationFiles() { - $config = \Drupal::config('locale.settings'); + $config = $this->config('locale.settings'); // A flag is set to let the locale_test module replace the project data with // a set of test projects which match the below project files. diff --git a/core/modules/migrate/src/Plugin/migrate/destination/Config.php b/core/modules/migrate/src/Plugin/migrate/destination/Config.php index a7b5de29d3e6..7d84813a6c1d 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/Config.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/Config.php @@ -6,6 +6,7 @@ namespace Drupal\migrate\Plugin\migrate\destination; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\migrate\Entity\MigrationInterface; use Drupal\migrate\MigrateException; @@ -43,12 +44,12 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface * The plugin implementation definition. * @param \Drupal\migrate\Entity\MigrationInterface $migration * The migration entity. - * @param \Drupal\Core\Config\Config $config - * The configuration object. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The configuration factory. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigObject $config) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, ConfigFactoryInterface $config_factory) { parent::__construct($configuration, $plugin_id, $plugin_definition, $migration); - $this->config = $config; + $this->config = $config_factory->getEditable($configuration['config_name']); } /** @@ -60,7 +61,7 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $migration, - $container->get('config.factory')->get($configuration['config_name']) + $container->get('config.factory') ); } diff --git a/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php b/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php index 8ed3f6d846ea..6b7dcd7cbeb5 100644 --- a/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php +++ b/core/modules/migrate/tests/src/Unit/destination/ConfigTest.php @@ -37,13 +37,18 @@ public function testImport() { } $config->expects($this->once()) ->method('save'); + $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); + $config_factory->expects($this->once()) + ->method('getEditable') + ->with('d8_config') + ->will($this->returnValue($config)); $row = $this->getMockBuilder('Drupal\migrate\Row') ->disableOriginalConstructor() ->getMock(); $row->expects($this->once()) ->method('getRawDestination') ->will($this->returnValue($source)); - $destination = new Config(array(), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config); + $destination = new Config(array('config_name' => 'd8_config'), 'd8_config', array('pluginId' => 'd8_config'), $migration, $config_factory); $destination->import($row); } diff --git a/core/modules/node/node.module b/core/modules/node/node.module index a82ba2e65b7b..a1f2c3b4e685 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -843,7 +843,7 @@ function node_form_system_themes_admin_form_alter(&$form, FormStateInterface $fo $form['admin_theme']['use_admin_theme'] = array( '#type' => 'checkbox', '#title' => t('Use the administration theme when editing or creating content'), - '#default_value' => \Drupal::config('node.settings')->get('use_admin_theme'), + '#default_value' => \Drupal::configFactory()->getEditable('node.settings')->get('use_admin_theme'), ); $form['#submit'][] = 'node_form_system_themes_admin_form_submit'; } @@ -854,7 +854,7 @@ function node_form_system_themes_admin_form_alter(&$form, FormStateInterface $fo * @see node_form_system_themes_admin_form_alter() */ function node_form_system_themes_admin_form_submit($form, FormStateInterface $form_state) { - \Drupal::config('node.settings') + \Drupal::configFactory()->getEditable('node.settings') ->set('use_admin_theme', $form_state->getValue('use_admin_theme')) ->save(); \Drupal::service('router.builder_indicator')->setRebuildNeeded(); diff --git a/core/modules/search/src/SearchPageListBuilder.php b/core/modules/search/src/SearchPageListBuilder.php index 9efd4cce5063..62aa99ea00f6 100644 --- a/core/modules/search/src/SearchPageListBuilder.php +++ b/core/modules/search/src/SearchPageListBuilder.php @@ -328,7 +328,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); - $search_settings = $this->configFactory->get('search.settings'); + $search_settings = $this->configFactory->getEditable('search.settings'); // If these settings change, the default index needs to be rebuilt. if (($search_settings->get('index.minimum_word_size') != $form_state->getValue('minimum_word_size')) || ($search_settings->get('index.overlap_cjk') != $form_state->getValue('overlap_cjk'))) { $search_settings->set('index.minimum_word_size', $form_state->getValue('minimum_word_size')); diff --git a/core/modules/search/src/SearchPageRepository.php b/core/modules/search/src/SearchPageRepository.php index 3dfdfb237b2b..66f7bdadaf40 100644 --- a/core/modules/search/src/SearchPageRepository.php +++ b/core/modules/search/src/SearchPageRepository.php @@ -94,14 +94,14 @@ public function getDefaultSearchPage() { * {@inheritdoc} */ public function clearDefaultSearchPage() { - $this->configFactory->get('search.settings')->clear('default_page')->save(); + $this->configFactory->getEditable('search.settings')->clear('default_page')->save(); } /** * {@inheritdoc} */ public function setDefaultSearchPage(SearchPageInterface $search_page) { - $this->configFactory->get('search.settings')->set('default_page', $search_page->id())->save(); + $this->configFactory->getEditable('search.settings')->set('default_page', $search_page->id())->save(); $search_page->enable()->save(); } diff --git a/core/modules/search/tests/src/Unit/SearchPageRepositoryTest.php b/core/modules/search/tests/src/Unit/SearchPageRepositoryTest.php index 3ff112e04bc2..767a81b59a3c 100644 --- a/core/modules/search/tests/src/Unit/SearchPageRepositoryTest.php +++ b/core/modules/search/tests/src/Unit/SearchPageRepositoryTest.php @@ -151,7 +151,7 @@ public function testClearDefaultSearchPage() { ->with('default_page') ->will($this->returnValue($config)); $this->configFactory->expects($this->once()) - ->method('get') + ->method('getEditable') ->with('search.settings') ->will($this->returnValue($config)); $this->searchPageRepository->clearDefaultSearchPage(); @@ -227,7 +227,7 @@ public function testSetDefaultSearchPage() { ->method('save') ->will($this->returnValue($config)); $this->configFactory->expects($this->once()) - ->method('get') + ->method('getEditable') ->with('search.settings') ->will($this->returnValue($config)); diff --git a/core/modules/shortcut/shortcut.install b/core/modules/shortcut/shortcut.install index d716a0395ae0..41a78a2afdf0 100644 --- a/core/modules/shortcut/shortcut.install +++ b/core/modules/shortcut/shortcut.install @@ -56,7 +56,7 @@ function shortcut_install() { // Theme settings are not configuration entities and cannot depend on modules // so to set a module-specific setting, we need to set it with logic. if (\Drupal::service('theme_handler')->themeExists('seven')) { - \Drupal::config('seven.settings')->set('third_party_settings.shortcut.module_link', TRUE)->save(); + \Drupal::configFactory()->getEditable('seven.settings')->set('third_party_settings.shortcut.module_link', TRUE)->save(); } } @@ -67,6 +67,6 @@ function shortcut_uninstall() { // Theme settings are not configuration entities and cannot depend on modules // so to unset a module-specific setting, we need to unset it with logic. if (\Drupal::service('theme_handler')->themeExists('seven')) { - \Drupal::config('seven.settings')->clear('third_party_settings.shortcut.module_link')->save(); + \Drupal::configFactory()->getEditable('seven.settings')->clear('third_party_settings.shortcut.module_link')->save(); } } diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index ba9c43db0055..88c64dd0af9d 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -405,7 +405,7 @@ function shortcut_themes_installed($theme_list) { // Theme settings are not configuration entities and cannot depend on modules // so to set a module-specific setting, we need to set it with logic. if (\Drupal::moduleHandler()->moduleExists('shortcut')) { - \Drupal::config('seven.settings')->set('third_party_settings.shortcut.module_link', TRUE)->save(); + \Drupal::configFactory()->getEditable('seven.settings')->set('third_party_settings.shortcut.module_link', TRUE)->save(); } } } diff --git a/core/modules/simpletest/src/Form/SimpletestSettingsForm.php b/core/modules/simpletest/src/Form/SimpletestSettingsForm.php index d4e719773b69..e6d4d4df1e11 100644 --- a/core/modules/simpletest/src/Form/SimpletestSettingsForm.php +++ b/core/modules/simpletest/src/Form/SimpletestSettingsForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'simpletest_settings_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['simpletest.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php index d87718e303df..11e9076cb5dc 100644 --- a/core/modules/simpletest/src/InstallerTestBase.php +++ b/core/modules/simpletest/src/InstallerTestBase.php @@ -160,7 +160,7 @@ protected function setUp() { // Manually configure the test mail collector implementation to prevent // tests from sending out e-mails and collect them in state instead. - $config->get('system.mail') + $config->getEditable('system.mail') ->set('interface.default', 'test_mail_collector') ->save(); diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 50e96b4f4861..e5d076aca4db 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -208,7 +208,10 @@ protected function setUp() { if ($modules) { $this->enableModules($modules); } - // In order to use theme functions default theme config needs to exist. + // In order to use theme functions default theme config needs to exist. This + // configuration is not saved because it would fatal due to system module's + // configuration schema not existing. However since the configuration is + // cached in the configuration factory everything works. $this->config('system.theme')->set('default', 'classy'); // Tests based on this class are entitled to use Drupal's File and @@ -483,7 +486,7 @@ protected function disableModules(array $modules) { // Unset the list of modules in the extension handler. $module_handler = $this->container->get('module_handler'); $module_filenames = $module_handler->getModuleList(); - $extension_config = $this->container->get('config.factory')->get('core.extension'); + $extension_config = $this->config('core.extension'); foreach ($modules as $module) { unset($module_filenames[$module]); $extension_config->clear('module.' . $module); diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php index 7eaf71bbd605..cfcfdbc56801 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -1629,7 +1629,7 @@ protected function config($name) { $config_factory = \Drupal::configFactory(); $old_state = $config_factory->getOverrideState(); $config_factory->setOverrideState(FALSE); - $config = $config_factory->get($name); + $config = $config_factory->getEditable($name); $config_factory->setOverrideState($old_state); return $config; } diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index bb6401fed51d..8b042afd78c3 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -888,7 +888,7 @@ protected function setUp() { // UI. If declared in settings.php, they would no longer be configurable. file_prepare_directory($this->privateFilesDirectory, FILE_CREATE_DIRECTORY); file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY); - $config->get('system.file') + $config->getEditable('system.file') ->set('path.temporary', $this->tempFilesDirectory) ->save(); @@ -896,7 +896,7 @@ protected function setUp() { // tests from sending out emails and collect them in state instead. // While this should be enforced via settings.php prior to installation, // some tests expect to be able to test mail system implementations. - $config->get('system.mail') + $config->getEditable('system.mail') ->set('interface.default', 'test_mail_collector') ->save(); @@ -904,10 +904,10 @@ protected function setUp() { // environment optimizations for all tests to avoid needless overhead and // ensure a sane default experience for test authors. // @see https://drupal.org/node/2259167 - $config->get('system.logging') + $config->getEditable('system.logging') ->set('error_level', 'verbose') ->save(); - $config->get('system.performance') + $config->getEditable('system.performance') ->set('css.preprocess', FALSE) ->set('js.preprocess', FALSE) ->save(); diff --git a/core/modules/statistics/src/StatisticsSettingsForm.php b/core/modules/statistics/src/StatisticsSettingsForm.php index 47411d7b38f1..2213befda3c5 100644 --- a/core/modules/statistics/src/StatisticsSettingsForm.php +++ b/core/modules/statistics/src/StatisticsSettingsForm.php @@ -55,6 +55,13 @@ public function getFormId() { return 'statistics_settings_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['statistics.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/syslog/syslog.install b/core/modules/syslog/syslog.install index 8a2350a78fc1..e3377c8aeb74 100644 --- a/core/modules/syslog/syslog.install +++ b/core/modules/syslog/syslog.install @@ -11,5 +11,5 @@ function syslog_install() { // The default facility setting depends on the operating system, so it needs // to be set dynamically during installation. - \Drupal::config('syslog.settings')->set('facility', defined('LOG_LOCAL0') ? LOG_LOCAL0 : LOG_USER)->save(); + \Drupal::configFactory()->getEditable('syslog.settings')->set('facility', defined('LOG_LOCAL0') ? LOG_LOCAL0 : LOG_USER)->save(); } diff --git a/core/modules/syslog/syslog.module b/core/modules/syslog/syslog.module index aad40609a84f..61873f981171 100644 --- a/core/modules/syslog/syslog.module +++ b/core/modules/syslog/syslog.module @@ -33,7 +33,7 @@ function syslog_help($route_name, RouteMatchInterface $route_match) { * Implements hook_form_FORM_ID_alter(). */ function syslog_form_system_logging_settings_alter(&$form, FormStateInterface $form_state) { - $config = \Drupal::config('syslog.settings'); + $config = \Drupal::configFactory()->getEditable('syslog.settings'); $help = \Drupal::moduleHandler()->moduleExists('help') ? ' ' . \Drupal::l(t('More information'), new Url('help.page', ['name' => 'syslog'])) . '.' : NULL; $form['syslog_identity'] = array( '#type' => 'textfield', @@ -66,7 +66,7 @@ function syslog_form_system_logging_settings_alter(&$form, FormStateInterface $f * @see syslog_form_system_logging_settings_alter() */ function syslog_logging_settings_submit($form, FormStateInterface $form_state) { - \Drupal::config('syslog.settings') + \Drupal::configFactory()->getEditable('syslog.settings') ->set('identity', $form_state->getValue('syslog_identity')) ->set('facility', $form_state->getValue('syslog_facility')) ->set('format', $form_state->getValue('syslog_format')) diff --git a/core/modules/system/src/Controller/ThemeController.php b/core/modules/system/src/Controller/ThemeController.php index 3bb6d316895b..26083cbf4657 100644 --- a/core/modules/system/src/Controller/ThemeController.php +++ b/core/modules/system/src/Controller/ThemeController.php @@ -7,6 +7,7 @@ namespace Drupal\system\Controller; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\Routing\RouteBuilderIndicatorInterface; @@ -40,10 +41,13 @@ class ThemeController extends ControllerBase { * The theme handler. * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder_indicator * The route builder. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The config factory. */ - public function __construct(ThemeHandlerInterface $theme_handler, RouteBuilderIndicatorInterface $route_builder_indicator) { + public function __construct(ThemeHandlerInterface $theme_handler, RouteBuilderIndicatorInterface $route_builder_indicator, ConfigFactoryInterface $config_factory) { $this->themeHandler = $theme_handler; $this->routeBuilderIndicator = $route_builder_indicator; + $this->configFactory = $config_factory; } /** @@ -52,7 +56,8 @@ public function __construct(ThemeHandlerInterface $theme_handler, RouteBuilderIn public static function create(ContainerInterface $container) { return new static( $container->get('theme_handler'), - $container->get('router.builder_indicator') + $container->get('router.builder_indicator'), + $container->get('config.factory') ); } @@ -142,7 +147,7 @@ public function install(Request $request) { * Throws access denied when no theme is set in the request. */ public function setDefaultTheme(Request $request) { - $config = $this->config('system.theme'); + $config = $this->configFactory->getEditable('system.theme'); $theme = $request->query->get('theme'); if (isset($theme)) { diff --git a/core/modules/system/src/Form/CronForm.php b/core/modules/system/src/Form/CronForm.php index cfb82fd8857e..f906c7022358 100644 --- a/core/modules/system/src/Form/CronForm.php +++ b/core/modules/system/src/Form/CronForm.php @@ -80,6 +80,13 @@ public function getFormId() { return 'system_cron_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.cron']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/FileSystemForm.php b/core/modules/system/src/Form/FileSystemForm.php index 8cf5eb38fdec..368f318d08b4 100644 --- a/core/modules/system/src/Form/FileSystemForm.php +++ b/core/modules/system/src/Form/FileSystemForm.php @@ -71,6 +71,13 @@ public function getFormId() { return 'system_file_system_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.file']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/ImageToolkitForm.php b/core/modules/system/src/Form/ImageToolkitForm.php index 6eeaa4ef942c..0d9bec9446ea 100644 --- a/core/modules/system/src/Form/ImageToolkitForm.php +++ b/core/modules/system/src/Form/ImageToolkitForm.php @@ -58,6 +58,13 @@ public function getFormId() { return 'system_image_toolkit_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.image']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/LoggingForm.php b/core/modules/system/src/Form/LoggingForm.php index 500fed033ab3..cfbbddc46a78 100644 --- a/core/modules/system/src/Form/LoggingForm.php +++ b/core/modules/system/src/Form/LoggingForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'system_logging_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.logging']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/PerformanceForm.php b/core/modules/system/src/Form/PerformanceForm.php index 372b319e321b..9049c7825bb2 100644 --- a/core/modules/system/src/Form/PerformanceForm.php +++ b/core/modules/system/src/Form/PerformanceForm.php @@ -90,6 +90,13 @@ public function getFormId() { return 'system_performance_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.performance']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/RegionalForm.php b/core/modules/system/src/Form/RegionalForm.php index 2d3934f27813..827f74f7fa34 100644 --- a/core/modules/system/src/Form/RegionalForm.php +++ b/core/modules/system/src/Form/RegionalForm.php @@ -55,6 +55,13 @@ public function getFormId() { return 'system_regional_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.date']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/RssFeedsForm.php b/core/modules/system/src/Form/RssFeedsForm.php index 84f18fa7929c..cde99641440e 100644 --- a/core/modules/system/src/Form/RssFeedsForm.php +++ b/core/modules/system/src/Form/RssFeedsForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'system_rss_feeds_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.rss']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/SiteInformationForm.php b/core/modules/system/src/Form/SiteInformationForm.php index f2efcd513315..71a0fbd2d9de 100644 --- a/core/modules/system/src/Form/SiteInformationForm.php +++ b/core/modules/system/src/Form/SiteInformationForm.php @@ -68,6 +68,13 @@ public function getFormId() { return 'system_site_information_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.site']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/SiteMaintenanceModeForm.php b/core/modules/system/src/Form/SiteMaintenanceModeForm.php index b87533e2ec76..cde1f57fd4f8 100644 --- a/core/modules/system/src/Form/SiteMaintenanceModeForm.php +++ b/core/modules/system/src/Form/SiteMaintenanceModeForm.php @@ -54,6 +54,13 @@ public function getFormId() { return 'system_site_maintenance_mode'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.maintenance']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/ThemeAdminForm.php b/core/modules/system/src/Form/ThemeAdminForm.php index 93cace87f425..9aa712379cb8 100644 --- a/core/modules/system/src/Form/ThemeAdminForm.php +++ b/core/modules/system/src/Form/ThemeAdminForm.php @@ -21,6 +21,13 @@ public function getFormID() { return 'system_themes_admin_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.theme']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Form/ThemeSettingsForm.php b/core/modules/system/src/Form/ThemeSettingsForm.php index 959fd565be13..75983f07c3e7 100644 --- a/core/modules/system/src/Form/ThemeSettingsForm.php +++ b/core/modules/system/src/Form/ThemeSettingsForm.php @@ -37,6 +37,13 @@ class ThemeSettingsForm extends ConfigFormBase { */ protected $themeHandler; + /** + * An array of configuration names that should be editable. + * + * @var array + */ + protected $editableConfig = []; + /** * Constructs a ThemeSettingsForm object. * @@ -72,6 +79,13 @@ public function getFormId() { return 'system_theme_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return $this->editableConfig; + } + /** * {@inheritdoc} * @@ -99,6 +113,10 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme = $var = 'theme_settings'; $config_key = 'system.theme.global'; } + // @todo this is pretty meaningless since we're using theme_get_settings + // which means overrides can bleed into active config here. Will be fixed + // by https://www.drupal.org/node/2402467. + $this->editableConfig = [$config_key]; $form['var'] = array( '#type' => 'hidden', @@ -389,7 +407,9 @@ public function validateForm(array &$form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); - $config = $this->config($form_state->getValue('config_key')); + $config_key = $form_state->getValue('config_key'); + $this->editableConfig = [$config_key]; + $config = $this->config($config_key); // Exclude unnecessary elements before saving. $form_state->cleanValues(); diff --git a/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php b/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php index 7aa56d03eafe..d16330f62a53 100644 --- a/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php +++ b/core/modules/system/src/Plugin/ImageToolkit/GDToolkit.php @@ -104,7 +104,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality but bigger files.'), '#min' => 0, '#max' => 100, - '#default_value' => $this->configFactory->get('system.image.gd')->get('jpeg_quality'), + '#default_value' => $this->configFactory->getEditable('system.image.gd')->get('jpeg_quality', FALSE), '#field_suffix' => t('%'), ); return $form; @@ -114,7 +114,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configFactory->get('system.image.gd') + $this->configFactory->getEditable('system.image.gd') ->set('jpeg_quality', $form_state->getValue(array('gd', 'image_jpeg_quality'))) ->save(); } diff --git a/core/modules/system/src/Tests/Form/FormObjectTest.php b/core/modules/system/src/Tests/Form/FormObjectTest.php index 237d9e74a4af..a732e9678da4 100644 --- a/core/modules/system/src/Tests/Form/FormObjectTest.php +++ b/core/modules/system/src/Tests/Form/FormObjectTest.php @@ -27,7 +27,7 @@ class FormObjectTest extends SystemConfigFormTestBase { protected function setUp() { parent::setUp(); - $this->form = new FormTestObject(); + $this->form = new FormTestObject($this->container->get('config.factory')); $this->values = array( 'bananas' => array( '#value' => $this->randomString(10), diff --git a/core/modules/system/system.install b/core/modules/system/system.install index cc2079fa6961..08e7865983fd 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -623,7 +623,7 @@ function system_install() { \Drupal::state()->set('system.cron_key', $cron_key); // Populate the site UUID. - \Drupal::config('system.site') + \Drupal::configFactory()->getEditable('system.site') ->set('uuid', \Drupal::service('uuid')->generate()) ->save(); } diff --git a/core/modules/system/tests/modules/form_test/form_test.services.yml b/core/modules/system/tests/modules/form_test/form_test.services.yml index 472e0bc03877..24513a66e0e6 100644 --- a/core/modules/system/tests/modules/form_test/form_test.services.yml +++ b/core/modules/system/tests/modules/form_test/form_test.services.yml @@ -1,6 +1,7 @@ services: form_test.form.serviceform: class: Drupal\form_test\FormTestServiceObject + arguments: ['@config.factory'] form_test.event_subscriber: class: Drupal\form_test\EventSubscriber\FormTestEventSubscriber tags: diff --git a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php index da7b4d58330c..9dc522ce762d 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php @@ -8,13 +8,13 @@ namespace Drupal\form_test; use Drupal\Component\Utility\String; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; /** * Provides a test form object that needs arguments. */ -class FormTestArgumentsObject extends FormBase { +class FormTestArgumentsObject extends ConfigFormBase { /** * {@inheritdoc} @@ -23,6 +23,13 @@ public function getFormId() { return 'form_test_form_test_arguments_object'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['form_test.object']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php b/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php index 1b96b3da093d..40a79af1fb4a 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestControllerObject.php @@ -7,7 +7,7 @@ namespace Drupal\form_test; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -15,7 +15,7 @@ /** * Provides a test form object. */ -class FormTestControllerObject extends FormBase { +class FormTestControllerObject extends ConfigFormBase { /** * {@inheritdoc} @@ -24,12 +24,21 @@ public function getFormId() { return 'form_test_form_test_controller_object'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['form_test.object']; + } + /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { drupal_set_message(t('The FormTestControllerObject::create() method was used for this form.')); - return new static(); + return new static( + $container->get('config.factory') + ); } /** diff --git a/core/modules/system/tests/modules/form_test/src/FormTestObject.php b/core/modules/system/tests/modules/form_test/src/FormTestObject.php index 4669bfec6519..73f273e6fb09 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestObject.php @@ -7,13 +7,13 @@ namespace Drupal\form_test; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; /** * Provides a test form object. */ -class FormTestObject extends FormBase { +class FormTestObject extends ConfigFormBase { /** * {@inheritdoc} @@ -22,6 +22,13 @@ public function getFormId() { return 'form_test_form_test_object'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['form_test.object']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/tests/modules/form_test/src/FormTestServiceObject.php b/core/modules/system/tests/modules/form_test/src/FormTestServiceObject.php index de4e6c0fdcdb..c60b6d158d62 100644 --- a/core/modules/system/tests/modules/form_test/src/FormTestServiceObject.php +++ b/core/modules/system/tests/modules/form_test/src/FormTestServiceObject.php @@ -7,13 +7,13 @@ namespace Drupal\form_test; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; /** * Provides a test form object. */ -class FormTestServiceObject extends FormBase { +class FormTestServiceObject extends ConfigFormBase { /** * {@inheritdoc} @@ -22,6 +22,13 @@ public function getFormId() { return 'form_test_form_test_service_object'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['form_test.object']; + } + /** * {@inheritdoc} */ @@ -54,7 +61,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) { */ public function submitForm(array &$form, FormStateInterface $form_state) { drupal_set_message($this->t('The FormTestServiceObject::submitForm() method was used for this form.')); - $this->config('form_test.object') + $this->config('form_test.object', FALSE) ->set('bananas', $form_state->getValue('bananas')) ->save(); } diff --git a/core/modules/system/tests/modules/form_test/src/SystemConfigFormTestForm.php b/core/modules/system/tests/modules/form_test/src/SystemConfigFormTestForm.php index 45efda74babd..243a81b10390 100644 --- a/core/modules/system/tests/modules/form_test/src/SystemConfigFormTestForm.php +++ b/core/modules/system/tests/modules/form_test/src/SystemConfigFormTestForm.php @@ -21,4 +21,11 @@ public function getFormId() { return 'form_test_system_config_test_form'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return []; + } + } diff --git a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php index f72eaaaddd10..7513ac26f9c4 100644 --- a/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php +++ b/core/modules/system/tests/modules/image_test/src/Plugin/ImageToolkit/TestToolkit.php @@ -103,7 +103,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#description' => $this->t('A toolkit parameter for testing purposes.'), '#min' => 0, '#max' => 100, - '#default_value' => $this->configFactory->get('system.image.test_toolkit')->get('test_parameter'), + '#default_value' => $this->configFactory->getEditable('system.image.test_toolkit')->get('test_parameter', FALSE), ); return $form; } @@ -121,7 +121,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configFactory->get('system.image.test_toolkit') + $this->configFactory->getEditable('system.image.test_toolkit') ->set('test_parameter', $form_state->getValue(array('test', 'test_parameter'))) ->save(); } diff --git a/core/modules/update/src/UpdateSettingsForm.php b/core/modules/update/src/UpdateSettingsForm.php index 81ef7e00930b..7e4664de9d2d 100644 --- a/core/modules/update/src/UpdateSettingsForm.php +++ b/core/modules/update/src/UpdateSettingsForm.php @@ -22,6 +22,13 @@ public function getFormId() { return 'update_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['update.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/user/src/AccountSettingsForm.php b/core/modules/user/src/AccountSettingsForm.php index bce6a6064f7e..2b91877d9b03 100644 --- a/core/modules/user/src/AccountSettingsForm.php +++ b/core/modules/user/src/AccountSettingsForm.php @@ -56,6 +56,17 @@ public function getFormId() { return 'user_admin_settings'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return [ + 'system.site', + 'user.mail', + 'user.settings', + ]; + } + /** * {@inheritdoc} */ diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 38f0ba06ba75..ed18d47b77b0 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1369,7 +1369,7 @@ function user_modules_uninstalled($modules) { \Drupal::service('user.data')->delete($modules); // User signatures require Filter module. if (in_array('filter', $modules)) { - \Drupal::config('user.settings')->set('signatures', FALSE)->save(); + \Drupal::configFactory()->getEditable('user.settings')->set('signatures', FALSE)->save(); } } diff --git a/core/modules/views/tests/modules/views_test_data/views_test_data.install b/core/modules/views/tests/modules/views_test_data/views_test_data.install index 8cd7f38a3c33..eeb5faa845cc 100644 --- a/core/modules/views/tests/modules/views_test_data/views_test_data.install +++ b/core/modules/views/tests/modules/views_test_data/views_test_data.install @@ -31,5 +31,5 @@ function views_test_data_install() { 'em' => 'EM', 'marquee' => 'MARQUEE' ); - \Drupal::config('views.settings')->set('field_rewrite_elements', $values)->save(); + \Drupal::configFactory()->getEditable('views.settings')->set('field_rewrite_elements', $values)->save(); } diff --git a/core/modules/views_ui/src/Form/AdvancedSettingsForm.php b/core/modules/views_ui/src/Form/AdvancedSettingsForm.php index a9ffd6f0081d..d8cd1e21d42a 100644 --- a/core/modules/views_ui/src/Form/AdvancedSettingsForm.php +++ b/core/modules/views_ui/src/Form/AdvancedSettingsForm.php @@ -23,6 +23,13 @@ public function getFormId() { return 'views_ui_admin_settings_advanced'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['views.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/modules/views_ui/src/Form/BasicSettingsForm.php b/core/modules/views_ui/src/Form/BasicSettingsForm.php index 557745b50302..1732c9ac0fd9 100644 --- a/core/modules/views_ui/src/Form/BasicSettingsForm.php +++ b/core/modules/views_ui/src/Form/BasicSettingsForm.php @@ -56,6 +56,13 @@ public function getFormId() { return 'views_ui_admin_settings_basic'; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['views.settings']; + } + /** * {@inheritdoc} */ diff --git a/core/profiles/minimal/minimal.install b/core/profiles/minimal/minimal.install index 52bea389a499..a8baf07906b3 100644 --- a/core/profiles/minimal/minimal.install +++ b/core/profiles/minimal/minimal.install @@ -13,8 +13,8 @@ */ function minimal_install() { // Disable the user pictures on nodes. - \Drupal::config('system.theme.global')->set('features.node_user_picture', FALSE)->save(); + \Drupal::configFactory()->getEditable('system.theme.global')->set('features.node_user_picture', FALSE)->save(); // Allow visitor account creation, but with administrative approval. - \Drupal::config('user.settings')->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)->save(); + \Drupal::configFactory()->getEditable('user.settings')->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)->save(); } diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install index 645587b3babd..f57166793f5b 100644 --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -22,10 +22,10 @@ function standard_install() { \Drupal::service('entity.definition_update_manager')->applyUpdates(); // Set front page to "node". - \Drupal::config('system.site')->set('page.front', 'node')->save(); + \Drupal::configFactory()->getEditable('system.site')->set('page.front', 'node')->save(); // Allow visitor account creation with administrative approval. - $user_settings = \Drupal::config('user.settings'); + $user_settings = \Drupal::configFactory()->getEditable('user.settings'); $user_settings->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)->save(); // Enable default permissions for system roles. @@ -71,5 +71,5 @@ function standard_install() { $shortcut->save(); // Enable the admin theme. - \Drupal::config('node.settings')->set('use_admin_theme', '1')->save(); + \Drupal::configFactory()->getEditable('node.settings')->set('use_admin_theme', '1')->save(); } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php index f7eef52f0a35..4ed1c20b670f 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php @@ -246,11 +246,16 @@ public function testSaveInsert(EntityInterface $entity) { $this->entityTypeId . '_list', // List cache tag. )); - $this->configFactory->expects($this->exactly(2)) + $this->configFactory->expects($this->exactly(1)) ->method('get') ->with('the_config_prefix.foo') ->will($this->returnValue($config_object)); + $this->configFactory->expects($this->exactly(1)) + ->method('getEditable') + ->with('the_config_prefix.foo') + ->will($this->returnValue($config_object)); + $this->moduleHandler->expects($this->at(0)) ->method('invokeAll') ->with('test_entity_type_presave'); @@ -311,10 +316,14 @@ public function testSaveUpdate(EntityInterface $entity) { ->method('loadMultiple') ->with(array('the_config_prefix.foo')) ->will($this->returnValue(array())); - $this->configFactory->expects($this->exactly(2)) + $this->configFactory->expects($this->exactly(1)) ->method('get') ->with('the_config_prefix.foo') ->will($this->returnValue($config_object)); + $this->configFactory->expects($this->exactly(1)) + ->method('getEditable') + ->with('the_config_prefix.foo') + ->will($this->returnValue($config_object)); $this->moduleHandler->expects($this->at(0)) ->method('invokeAll') @@ -370,6 +379,10 @@ public function testSaveRename(ConfigEntityInterface $entity) { $this->configFactory->expects($this->once()) ->method('rename') + ->willReturn($this->configFactory); + $this->configFactory->expects($this->exactly(1)) + ->method('getEditable') + ->with('the_config_prefix.bar') ->will($this->returnValue($config_object)); $this->configFactory->expects($this->exactly(2)) ->method('loadMultiple') @@ -506,8 +519,11 @@ public function testSaveNoMismatch() { ->will($this->returnValue($config_object)); $this->configFactory->expects($this->once()) ->method('rename') + ->willReturn($this->configFactory); + $this->configFactory->expects($this->exactly(1)) + ->method('getEditable') + ->with('the_config_prefix.foo') ->will($this->returnValue($config_object)); - $this->entityQuery->expects($this->once()) ->method('condition') ->will($this->returnSelf()); @@ -736,7 +752,7 @@ public function testDelete() { )); $this->configFactory->expects($this->exactly(2)) - ->method('get') + ->method('getEditable') ->will($this->returnValueMap($config_map)); $this->moduleHandler->expects($this->at(0)) diff --git a/core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php b/core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php new file mode 100644 index 000000000000..8b0bbf8f49cf --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/ImmutableConfigTest.php @@ -0,0 +1,70 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Config\ImmutableConfigTest. + */ + +namespace Drupal\Tests\Core\Config; + +use Drupal\Core\Config\ImmutableConfig; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\Core\Config\ImmutableConfig + * @group Config + */ +class ImmutableConfigTest extends UnitTestCase { + + /** + * The immutable config object under test. + * + * @var \Drupal\Core\Config\ImmutableConfig + */ + protected $config; + + protected function setUp() { + parent::setUp(); + $storage = $this->getMock('Drupal\Core\Config\StorageInterface'); + $event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $typed_config = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface'); + $this->config = new ImmutableConfig('test', $storage, $event_dispatcher, $typed_config); + } + + /** + * @covers ::set + * @expectedException \Drupal\Core\Config\ImmutableConfigException + * @expectedExceptionMessage Can not set values on immutable configuration test:name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object + */ + public function testSet() { + $this->config->set('name', 'value'); + } + + /** + * @covers ::clear + * @expectedException \Drupal\Core\Config\ImmutableConfigException + * @expectedExceptionMessage Can not clear name key in immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object + */ + public function testClear() { + $this->config->clear('name'); + } + + /** + * @covers ::save + * @expectedException \Drupal\Core\Config\ImmutableConfigException + * @expectedExceptionMessage Can not save immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object + */ + public function testSave() { + $this->config->save(); + } + + /** + * @covers ::delete + * @expectedException \Drupal\Core\Config\ImmutableConfigException + * @expectedExceptionMessage Can not delete immutable configuration test. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object + */ + public function testDelete() { + $this->config->delete(); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Form/ConfigFormBaseTraitTest.php b/core/tests/Drupal/Tests/Core/Form/ConfigFormBaseTraitTest.php new file mode 100644 index 000000000000..443646bfd220 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Form/ConfigFormBaseTraitTest.php @@ -0,0 +1,76 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Form\ConfigFormBaseTraitTest. + */ + +namespace Drupal\Tests\Core\Form; + +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\Core\Form\ConfigFormBaseTrait + * @group Form + */ +class ConfigFormBaseTraitTest extends UnitTestCase { + + /** + * @covers ::config + */ + public function testConfig() { + + $trait = $this->getMockForTrait('Drupal\Core\Form\ConfigFormBaseTrait'); + // Set up some configuration in a mocked config factory. + $trait->configFactory = $this->getConfigFactoryStub([ + 'editable.config' => [], + 'immutable.config' => [] + ]); + + $trait->expects($this->any()) + ->method('getEditableConfigNames') + ->willReturn(['editable.config']); + + $config_method = new \ReflectionMethod($trait, 'config'); + $config_method->setAccessible(TRUE); + + // Ensure that configuration that is expected to be mutable is. + $result = $config_method->invoke($trait, 'editable.config'); + $this->assertInstanceOf('\Drupal\Core\Config\Config', $result); + $this->assertNotInstanceOf('\Drupal\Core\Config\ImmutableConfig', $result); + + // Ensure that configuration that is expected to be immutable is. + $result = $config_method->invoke($trait, 'immutable.config'); + $this->assertInstanceOf('\Drupal\Core\Config\ImmutableConfig', $result); + } + + /** + * @covers ::config + * @expectedException \LogicException + * @expectedExceptionMessage No config factory available for ConfigFormBaseTrait + */ + public function testConfigFactoryException() { + $trait = $this->getMockForTrait('Drupal\Core\Form\ConfigFormBaseTrait'); + $config_method = new \ReflectionMethod($trait, 'config'); + $config_method->setAccessible(TRUE); + + // There is no config factory available this should result in an exception. + $config_method->invoke($trait, 'editable.config'); + } + + /** + * @covers ::config + * @expectedException \LogicException + * @expectedExceptionMessage No config factory available for ConfigFormBaseTrait + */ + public function testConfigFactoryExceptionInvalidProperty() { + $trait = $this->getMockForTrait('Drupal\Core\Form\ConfigFormBaseTrait'); + $trait->configFactory = TRUE; + $config_method = new \ReflectionMethod($trait, 'config'); + $config_method->setAccessible(TRUE); + + // There is no config factory available this should result in an exception. + $config_method->invoke($trait, 'editable.config'); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php index ea37f39b77c0..3f6093317e8b 100644 --- a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php @@ -144,7 +144,7 @@ public function testSaveOverride() { $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); $config_factory->expects($this->once()) - ->method('get') + ->method('getEditable') ->will($this->returnValue($config)); $static_override = new StaticMenuLinkOverrides($config_factory); @@ -186,7 +186,7 @@ public function testDeleteOverrides($ids, array $old_definitions, array $new_def $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); $config_factory->expects($this->once()) - ->method('get') + ->method('getEditable') ->will($this->returnValue($config)); $static_override = new StaticMenuLinkOverrides($config_factory); diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index 1a0ac77d0b16..d6deb9eafae2 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -100,13 +100,11 @@ protected function assertArrayEquals(array $expected, array $actual, $message = * A MockBuilder object for the ConfigFactory with the desired return values. */ public function getConfigFactoryStub(array $configs = array()) { - $config_map = array(); + $config_get_map = array(); + $config_editable_map = array(); // Construct the desired configuration object stubs, each with its own // desired return map. foreach ($configs as $config_name => $config_values) { - $config_object = $this->getMockBuilder('Drupal\Core\Config\Config') - ->disableOriginalConstructor() - ->getMock(); $map = array(); foreach ($config_values as $key => $value) { $map[] = array($key, $value); @@ -114,18 +112,31 @@ public function getConfigFactoryStub(array $configs = array()) { // Also allow to pass in no argument. $map[] = array('', $config_values); - $config_object->expects($this->any()) + $immutable_config_object = $this->getMockBuilder('Drupal\Core\Config\ImmutableConfig') + ->disableOriginalConstructor() + ->getMock(); + $immutable_config_object->expects($this->any()) ->method('get') ->will($this->returnValueMap($map)); + $config_get_map[] = array($config_name, $immutable_config_object); - $config_map[] = array($config_name, $config_object); + $mutable_config_object = $this->getMockBuilder('Drupal\Core\Config\Config') + ->disableOriginalConstructor() + ->getMock(); + $mutable_config_object->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($map)); + $config_editable_map[] = array($config_name, $mutable_config_object); } // Construct a config factory with the array of configuration object stubs // as its return map. $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); $config_factory->expects($this->any()) ->method('get') - ->will($this->returnValueMap($config_map)); + ->will($this->returnValueMap($config_get_map)); + $config_factory->expects($this->any()) + ->method('getEditable') + ->will($this->returnValueMap($config_editable_map)); return $config_factory; } diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index a43575445adf..76d26fcfdf3c 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -551,7 +551,18 @@ * the default settings.php. * * Note that any values you provide in these variable overrides will not be - * modifiable from the Drupal administration interface. + * viewable from the Drupal administration interface. The administration + * interface displays the values stored in configuration so that you can stage + * changes to other environments that don't have the overrides. + * + * There are particular configuration values that are risky to override. For + * example, overriding the list of installed modules in 'core.extension' is not + * supported as module install or uninstall has not occurred. Other examples + * include field storage configuration, because it has effects on database + * structure, and 'core.menu.static_menu_link_overrides' since this is cached in + * a way that is not config override aware. Also, note that changing + * configuration values in settings.php will not fire any of the configuration + * change events. */ # $config['system.site']['name'] = 'My Drupal site'; # $config['system.theme']['default'] = 'stark'; -- GitLab