diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index cf3688d..0c4322c 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -75,7 +75,13 @@ class ConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface * * @var array */ - protected $cannotOverridable = ['core.extension']; + protected $cannotOverride = [ + // Due to side effects of doing a module install or uninstall. + 'core.extension', + // Due to the fact that this information is cached in a way that is not + // config override aware. + 'menu_link.static.overrides' + ]; /** * Constructs the Config factory. @@ -404,6 +410,6 @@ protected function createConfigObject($name, $immutable) { * Returns TRUE if the configuration object can be overridden. */ protected function canOverride($name) { - return !in_array($name, $this->cannotOverridable); + return !in_array($name, $this->cannotOverride); } } diff --git a/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php b/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php index 0204a1f..c3024b0 100644 --- a/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php +++ b/core/lib/Drupal/Core/Form/ConfigFormBaseTrait.php @@ -12,11 +12,18 @@ /** * 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. 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. + * environment specific. Default values of form elements should be obtained from + * override free configuration objects. However, if a form reacts to + * configuration in anyway, 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 { diff --git a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php index 01fbb65..659ff90 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 = 'menu_link.static.overrides'; @@ -54,6 +58,7 @@ public function __construct(ConfigFactoryInterface $config_factory) { */ protected function getConfig() { if (empty($this->config)) { + // Get an override free and editable configuration object. $this->config = $this->configFactory->getEditable($this->configName); } return $this->config; @@ -80,7 +85,7 @@ public function loadOverride($id) { * {@inheritdoc} */ public function deleteMultipleOverrides(array $ids) { - $all_overrides = $this->getConfig()->getOriginal('definitions', FALSE); + $all_overrides = $this->getConfig()->get('definitions'); $save = FALSE; foreach ($ids as $id) { $id = static::encodeId($id); @@ -135,7 +140,7 @@ public function saveOverride($id, array $definition) { $definition = array_intersect_key($definition, $expected); if ($definition) { $id = static::encodeId($id); - $all_overrides = $this->getConfig()->getOriginal('definitions', FALSE); + $all_overrides = $this->getConfig()->get('definitions', FALSE); // Combine with any existing data. $all_overrides[$id] = $definition + $this->loadOverride($id); $this->getConfig()->set('definitions', $all_overrides)->save(); diff --git a/core/modules/aggregator/src/Plugin/AggregatorPluginSettingsBase.php b/core/modules/aggregator/src/Plugin/AggregatorPluginSettingsBase.php index 15e3c3d..eb6ad36 100644 --- a/core/modules/aggregator/src/Plugin/AggregatorPluginSettingsBase.php +++ b/core/modules/aggregator/src/Plugin/AggregatorPluginSettingsBase.php @@ -8,8 +8,6 @@ namespace Drupal\aggregator\Plugin; use Drupal\Component\Plugin\ConfigurablePluginInterface; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Form\ConfigFormBaseTrait; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Plugin\PluginFormInterface; @@ -27,29 +25,6 @@ * @see plugin_api */ abstract class AggregatorPluginSettingsBase extends PluginBase implements PluginFormInterface, ConfigurablePluginInterface { - use ConfigFormBaseTrait; - - /** - * Contains the configuration object factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - - /** - * Constructs a Drupal\Component\Plugin\PluginBase object. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->configFactory = $config_factory; - } /** * {@inheritdoc} diff --git a/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php b/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php index 8290527..f51a403 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; /** @@ -83,13 +84,13 @@ class DefaultProcessor extends AggregatorPluginSettingsBase implements Processor * The date formatter service. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, QueryInterface $item_query, ItemStorageInterface $item_storage, DateFormatter $date_formatter) { + $this->configFactory = $config; $this->itemStorage = $item_storage; $this->itemQuery = $item_query; $this->dateFormatter = $date_formatter; - $this->configFactory = $config; // @todo Refactor aggregator plugins to ConfigEntity so merging // the configuration here is not needed. - parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition, $config); + parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition); } /** 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 6e08844..1a6ee19 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,14 @@ * ) */ class TestProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface { + use ConfigFormBaseTrait; + + /** + * Contains the configuration object factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; /** * {@inheritdoc} @@ -54,7 +63,7 @@ public static function create(ContainerInterface $container, array $configuratio */ public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config) { $this->configFactory = $config; - parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition, $config); + parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition); } /** diff --git a/core/modules/book/book.module b/core/modules/book/book.module index f55c472..57ee1ab 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -561,7 +561,7 @@ function book_node_type_update(NodeTypeInterface $type) { if ($type->getOriginalId() != $type->id()) { $config = \Drupal::configFactory()->getEditable('book.settings'); // Update the list of node types that are allowed to be added to books. - $allowed_types = $config->getOriginal('allowed_types', FALSE); + $allowed_types = $config->get('allowed_types'); $old_key = array_search($type->getOriginalId(), $allowed_types); if ($old_key !== FALSE) { @@ -573,7 +573,7 @@ function book_node_type_update(NodeTypeInterface $type) { } // Update the setting for the "Add child page" link. - if ($config->getOriginal('child_type', FALSE) == $type->getOriginalId()) { + if ($config->get('child_type') == $type->getOriginalId()) { $config->set('child_type', $type->id()); } $config->save(); diff --git a/core/modules/color/color.module b/core/modules/color/color.module index 71f5d82..7d8473c 100644 --- a/core/modules/color/color.module +++ b/core/modules/color/color.module @@ -169,7 +169,9 @@ 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 overriding color + // configuration makes no sense. + return \Drupal::configFactory()->getEditable('color.theme.' . $theme)->get('palette') ?: $palette; } /** @@ -199,7 +201,9 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them // 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. - $current_scheme = \Drupal::config('color.theme.' . $theme)->getOriginal('palette', FALSE); + // Getting a mutable override-free object because overriding color + // configuration makes no sense. + $current_scheme = \Drupal::configFactory()->getEditable('color.theme.' . $theme)->get('palette'); foreach ($schemes as $key => $scheme) { if ($current_scheme == $scheme) { $scheme_name = $key; @@ -624,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 3ef3d33..ee1dfde 100644 --- a/core/modules/config/src/Form/ConfigSingleImportForm.php +++ b/core/modules/config/src/Form/ConfigSingleImportForm.php @@ -8,7 +8,6 @@ namespace Drupal\config\Form; use Drupal\Component\Serialization\Yaml; -use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\StorageInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\ConfirmFormBase; @@ -56,13 +55,10 @@ class ConfigSingleImportForm extends ConfirmFormBase { * The entity manager. * @param \Drupal\Core\Config\StorageInterface $config_storage * The config storage. - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The config factory. */ - public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage, ConfigFactoryInterface $config_factory) { + public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage) { $this->entityManager = $entity_manager; $this->configStorage = $config_storage; - $this->configFactory = $config_factory; } /** @@ -71,8 +67,7 @@ public function __construct(EntityManagerInterface $entity_manager, StorageInter public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), - $container->get('config.storage'), - $container->get('config.factory') + $container->get('config.storage') ); } @@ -248,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->configFactory->getEditable($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/contact/contact.module b/core/modules/contact/contact.module index 33eb25a..6764e81 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -194,7 +194,6 @@ 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.'), - // @see \Drupal\Core\Form\ConfigFormBase::config() '#default_value' => \Drupal::configFactory()->getEditable('contact.settings')->get('user_default_enabled'), ); // Add submit handler to save contact configuration. diff --git a/core/modules/contact/src/ContactFormEditForm.php b/core/modules/contact/src/ContactFormEditForm.php index 520f5b0..420be7d 100644 --- a/core/modules/contact/src/ContactFormEditForm.php +++ b/core/modules/contact/src/ContactFormEditForm.php @@ -21,24 +21,6 @@ class ContactFormEditForm extends EntityForm { use ConfigFormBaseTrait; /** - * Constructs the ContactFormEditForm. - * - * @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') - ); - } - - /** * {@inheritdoc} */ protected function getEditableConfigNames() { diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 69f1ba4..358dd4a 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -339,7 +339,8 @@ function language_negotiation_url_prefixes_update() { * Saves language prefix settings. */ function language_negotiation_url_prefixes_save(array $prefixes) { - // @fixme this is super dodgy - overrides can bleed. + // @todo https://www.drupal.org/node/2403229 $prefixes can contain + // configuration overrides. \Drupal::configFactory()->getEditable('language.negotiation') ->set('url.prefixes', $prefixes) ->save(); @@ -356,7 +357,8 @@ function language_negotiation_url_domains() { * Saves the language domain settings. */ function language_negotiation_url_domains_save(array $domains) { - // @fixme this is super dodgy - overrides can bleed. + // @todo https://www.drupal.org/node/2403229 $domains can contain + // configuration overrides. \Drupal::configFactory()->getEditable('language.negotiation') ->set('url.domains', $domains) ->save(); @@ -494,8 +496,6 @@ 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) { - // @fixme can config overrides bleed here? Default language is injected into - // the container. \Drupal::configFactory()->getEditable('system.site')->set('langcode', $form_state->getValue('site_default_language'))->save(); } diff --git a/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php b/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php index 8276d95..5e511b6 100644 --- a/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php +++ b/core/modules/language/src/Form/NegotiationBrowserDeleteForm.php @@ -27,25 +27,6 @@ class NegotiationBrowserDeleteForm extends ConfirmFormBase { protected $browserLangcode; /** - * Constructs the NegotiationBrowserDeleteForm 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') - ); - } - - /** * {@inheritdoc} */ public function getQuestion() { @@ -85,7 +66,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { if (array_key_exists($this->browserLangcode, $mappings)) { unset($mappings[$this->browserLangcode]); - $this->configFactory->getEditable('language.mappings') + $this->configFactory()->getEditable('language.mappings') ->clear($this->browserLangcode) ->save(); diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 8665e48..79b2a50 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' => \Drupal::config('locale.settings')->getOriginal('translate_english', FALSE), + '#default_value' => \Drupal::configFactory()->getEditable('locale.settings')->get('translate_english'), ); $form['actions']['submit']['#submit'][] = 'locale_form_language_admin_edit_form_alter_submit'; } diff --git a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php index 590bd21..6c55354 100644 --- a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php @@ -15,11 +15,6 @@ * @group Menu */ class StaticMenuLinkOverridesTest extends UnitTestCase { - protected function setUp() { - $this->markTestSkipped('Crazy test'); - parent::setUp(); // TODO: Change the autogenerated stub - } - /** * Tests the constructor. @@ -107,7 +102,6 @@ public function testLoadMultipleOverrides() { * @covers ::getConfig */ public function testSaveOverride() { - $this->markTestSkipped('Crazy test'); $config = $this->getMockBuilder('Drupal\Core\Config\Config') ->disableOriginalConstructor() ->getMock(); @@ -150,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); @@ -172,7 +166,6 @@ public function testSaveOverride() { * @dataProvider providerTestDeleteOverrides */ public function testDeleteOverrides($ids, array $old_definitions, array $new_definitions) { - $this->markTestSkipped('Crazy test'); $config = $this->getMockBuilder('Drupal\Core\Config\Config') ->disableOriginalConstructor() ->getMock(); @@ -193,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);