diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 0337d28..5da2a7e 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -275,8 +275,10 @@ protected function replaceData(array $data) { * The configuration object. */ public function setOverride(array $data) { - $this->overrides = NestedArray::mergeDeepArray(array($this->overrides, $data), TRUE); - $this->resetOverriddenData(); + if ($this->context->allowOverrides()) { + $this->overrides = NestedArray::mergeDeepArray(array($this->overrides, $data), TRUE); + $this->resetOverriddenData(); + } return $this; } diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index 4edbead..0cd0382 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -140,7 +140,8 @@ public function rename($old_name, $new_name) { * The config factory object. */ public function enterContext(ContextInterface $context) { - $this->contextStack[] = $context; + // Initialize the context as it is being entered. + $this->contextStack[] = $context->init(); return $this; } diff --git a/core/lib/Drupal/Core/Config/Context/ConfigContext.php b/core/lib/Drupal/Core/Config/Context/ConfigContext.php index 9be0f71..306c049 100644 --- a/core/lib/Drupal/Core/Config/Context/ConfigContext.php +++ b/core/lib/Drupal/Core/Config/Context/ConfigContext.php @@ -15,18 +15,12 @@ /** * Defines the base configuration context object. * - * A configuration context object provides a data array that can be used: - * - as a parameter to get customized configuration objects. - * - as a store of config data used to override values. + * A configuration context object provides a data array that can be used + * as parameters to get customized configuration objects. */ class ConfigContext implements ContextInterface { /** - * Predefined key, values to override specific configuration objects. - */ - const OVERRIDE = 'config.override'; - - /** * The actual storage of key-value pairs. * * @var array @@ -48,6 +42,13 @@ class ConfigContext implements ContextInterface { protected $uuid; /** + * Allow overrides to apply in this context. + * + * @var boolean + */ + protected $allowOverrides = TRUE; + + /** * Constructs the configuration context. * * @param \Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher @@ -60,10 +61,7 @@ public function __construct(EventDispatcher $event_dispatcher) { /** * Implements Drupal\Core\Config\Context\ContextInterface::init(). */ - public function init($context_key, $data) { - if ($data) { - $this->set($context_key, $data); - } + public function init() { $this->setUuid(); // Notify event listeners that a configuration context has been created. $this->notify('context', NULL); @@ -85,20 +83,6 @@ public function set($key, $value) { } /** - * Sets override data. - * - * @param mixed $data - * Override data to store. - * - * @return \Drupal\Core\Config\Context\ConfigContext - * The config context object. - */ - public function setOverride($data) { - $this->init(self::OVERRIDE, $data); - return $this; - } - - /** * Implements Drupal\Core\Config\Context\ContextInterface::setUuid(). */ public function setUuid() { @@ -120,4 +104,11 @@ public function notify($config_event_name, Config $config = NULL) { $this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($this, $config)); } + /** + * Implements Drupal\Core\Config\Context\ContextInterface::allowOverrides(). + */ + public function allowOverrides() { + return $this->allowOverrides; + } + } diff --git a/core/lib/Drupal/Core/Config/Context/ContextInterface.php b/core/lib/Drupal/Core/Config/Context/ContextInterface.php index b3107a7..3d16dcd 100644 --- a/core/lib/Drupal/Core/Config/Context/ContextInterface.php +++ b/core/lib/Drupal/Core/Config/Context/ContextInterface.php @@ -22,21 +22,13 @@ */ interface ContextInterface { - /* + /** * Initialises a config context for use. * - * Creates a unique context identifier, adds data and notifies system about - * the new context. - * - * @param string $context_key - * The key that is used to set context data. - * @param mixed $data - * The context config data. - * * @return \Drupal\Core\Config\Context\ConfigContext * The config context object. */ - public function init($context_key, $data); + public function init(); /** * Returns the stored value for a given key. @@ -85,4 +77,12 @@ public function getUuid(); */ public function notify($config_event_name, Config $config = NULL); + /** + * Whether this context allows overrides. + * + * @return boolean + * TRUE if overrides are allowed, FALSE otherwise. + */ + public function allowOverrides(); + } diff --git a/core/lib/Drupal/Core/Config/Context/FreeConfigContext.php b/core/lib/Drupal/Core/Config/Context/FreeConfigContext.php new file mode 100644 index 0000000..ae8061f --- /dev/null +++ b/core/lib/Drupal/Core/Config/Context/FreeConfigContext.php @@ -0,0 +1,19 @@ +init(self::OVERRIDE, $conf); - return $this; - } -} diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 6f7ff31..8c68ae4 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -58,15 +58,14 @@ public function build(ContainerBuilder $container) { $container->register('config.context', 'Drupal\Core\Config\Context\ContextInterface') ->setFactoryService(new Reference('config.context.factory')) ->setFactoryMethod('get') - ->addArgument('Drupal\Core\Config\Context\GlobalConfigContext') - ->addTag('persist') - ->addMethodCall('setGlobalOverride'); + ->addTag('persist'); // Register a config context with no overrides for use in administration // forms, enabling modules and importing configuration. $container->register('config.context.free', 'Drupal\Core\Config\Context\ContextInterface') ->setFactoryService(new Reference('config.context.factory')) - ->setFactoryMethod('get'); + ->setFactoryMethod('get') + ->addArgument('Drupal\Core\Config\Context\FreeConfigContext'); $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') ->addArgument(new Reference('config.storage')) @@ -278,7 +277,7 @@ public function build(ContainerBuilder $container) { $container->register('request_close_subscriber', 'Drupal\Core\EventSubscriber\RequestCloseSubscriber') ->addArgument(new Reference('module_handler')) ->addTag('event_subscriber'); - $container->register('config_global_override_subscriber', 'Drupal\Core\EventSubscriber\ConfigOverrideSubscriber') + $container->register('config_global_override_subscriber', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber') ->addTag('event_subscriber'); $container->register('language_request_subscriber', 'Drupal\Core\EventSubscriber\LanguageRequestSubscriber') ->addArgument(new Reference('language_manager')) diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php new file mode 100644 index 0000000..b2aa76e --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php @@ -0,0 +1,40 @@ +getConfig(); + if (isset($conf[$config->getName()])) { + $config->setOverride($conf[$config->getName()]); + } + } + + /** + * Implements EventSubscriberInterface::getSubscribedEvents(). + */ + static function getSubscribedEvents() { + $events['config.init'][] = array('configInit', 30); + return $events; + } +} diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php deleted file mode 100644 index 376da10..0000000 --- a/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php +++ /dev/null @@ -1,41 +0,0 @@ -getContext()->get(ConfigContext::OVERRIDE)) { - $config = $event->getConfig(); - if (isset($override[$config->getName()])) { - $config->setOverride($override[$config->getName()]); - } - } - } - - /** - * Implements EventSubscriberInterface::getSubscribedEvents(). - */ - public static function getSubscribedEvents() { - $events['config.init'][] = array('configInit', 30); - return $events; - } -} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php index 78253d3..4377766 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php @@ -75,6 +75,12 @@ function testConfigLocaleUserOverride() { 'langcode' => 'de', ))); + // Ensure reading config without overrides results in expected data. + config_context_enter('config.context.free'); + $config = config('config_test.system'); + $this->assertIdentical($config->get('foo'), 'bar'); + config_context_leave(); + $this->installSchema('user', 'users'); $account = entity_create('user', array( 'name' => 'French user', @@ -83,15 +89,17 @@ function testConfigLocaleUserOverride() { 'status' => 1, 'preferred_langcode' => 'fr', )); - $config_factory = drupal_container()->get('config.factory'); - $user_config_context = config_context_enter("Drupal\\user\\UserConfigContext"); + $user_config_context = config_context_enter('Drupal\user\UserConfigContext'); $user_config_context->setAccount($account); $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), 'fr bar'); // Ensure that we get the expected value when we leave the user context. - $config_factory->leaveContext(); + // The locale overrides contain an English override too, so although we + // are not in a user based language override context, the English + // language override applies due to the negotiated language for the page. + config_context_leave(); $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), 'en bar'); @@ -103,6 +111,7 @@ function testConfigLocaleUserOverride() { 'preferred_langcode' => 'de', )); + $config_factory = drupal_container()->get('config.factory'); $config_factory->enterContext($user_config_context->setAccount($account)); // Should not have to re-initialise config object to get new overrides as // the new context will have a different uuid. @@ -118,7 +127,7 @@ function testConfigLocaleUserOverride() { 'preferred_langcode' => 'en', )); // Create a new user config context to stack on top of the existign one. - $en_user_config_context = config_context_enter("Drupal\\user\\UserConfigContext"); + $en_user_config_context = config_context_enter('Drupal\user\UserConfigContext'); $en_user_config_context->setAccount($account); $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), 'en bar'); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php index 2fdf122..6dfcf4e 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php @@ -51,7 +51,6 @@ function testConfOverride() { $conf['config_test.system']['foo'] = 'overridden'; $conf['config_test.system']['baz'] = 'injected'; $conf['config_test.system']['404'] = 'derp'; - drupal_container()->get('config.context')->setGlobalOverride(); config_install_default_config('module', 'config_test'); @@ -63,31 +62,17 @@ function testConfOverride() { $this->assertFalse(isset($data['baz'])); $this->assertIdentical($data['404'], $expected_original_data['404']); - // Remove the $conf overrides and reset value in config.context service. - unset($conf['config_test.system']); - drupal_container()->get('config.context')->setGlobalOverride(); - - // Verify that the original configuration data exists. + // Enter an override-free context to ensure the original data remains. + config_context_enter('config.context.free'); $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), $expected_original_data['foo']); $this->assertIdentical($config->get('baz'), $expected_original_data['baz']); $this->assertIdentical($config->get('404'), $expected_original_data['404']); + config_context_leave(); - // Apply the overridden data, that needs to be set into the config.context - // service. - $conf['config_test.system']['foo'] = 'overridden'; - $conf['config_test.system']['baz'] = 'injected'; - $conf['config_test.system']['404'] = 'derp'; - drupal_container()->get('config.context')->setGlobalOverride(); - - // Verify that the in-memory configuration object still contains the - // original data. - $this->assertIdentical($config->get('foo'), $expected_original_data['foo']); - $this->assertIdentical($config->get('baz'), $expected_original_data['baz']); - $this->assertIdentical($config->get('404'), $expected_original_data['404']); - - // Reload the configuration object. - $config->init(); + // Get the configuration object in an overriden context (the one set by + // default). + $config = config('config_test.system'); // Verify that it contains the overridden data from $conf. $this->assertIdentical($config->get('foo'), $conf['config_test.system']['foo']); @@ -116,24 +101,15 @@ function testConfOverride() { $this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']); $this->assertIdentical($config->get('404'), $conf['config_test.system']['404']); - // Remove the $conf overrides and reset value in config.context service. - unset($conf['config_test.system']); - drupal_container()->get('config.context')->setGlobalOverride(); - - // Reload it and verify that it still contains the original data. - $config->init(); + // Enter an override-free context to ensure the original data remains saved. + config_context_enter('config.context.free'); + $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), $expected_original_data['foo']); $this->assertIdentical($config->get('baz'), $expected_original_data['baz']); $this->assertIdentical($config->get('404'), $expected_original_data['404']); + config_context_leave(); - // Set globals before importing to prove that the imported file does not - // contain these values. - $conf['config_test.system']['foo'] = 'overridden'; - $conf['config_test.system']['baz'] = 'injected'; - $conf['config_test.system']['404'] = 'derp'; - - // Write file to staging - drupal_container()->get('config.context')->setGlobalOverride(); + // Write file to staging. $staging = $this->container->get('config.storage.staging'); $expected_new_data = array( 'foo' => 'barbar', @@ -152,6 +128,7 @@ function testConfOverride() { $this->assertIdentical($data['404'], $expected_new_data['404']); // Verifiy the overrides are still working. + $config = config('config_test.system'); $this->assertIdentical($config->get('foo'), $conf['config_test.system']['foo']); $this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']); $this->assertIdentical($config->get('404'), $conf['config_test.system']['404']); diff --git a/core/modules/user/lib/Drupal/user/UserConfigContext.php b/core/modules/user/lib/Drupal/user/UserConfigContext.php index d6e4114..917787d 100644 --- a/core/modules/user/lib/Drupal/user/UserConfigContext.php +++ b/core/modules/user/lib/Drupal/user/UserConfigContext.php @@ -26,14 +26,6 @@ class UserConfigContext extends ConfigContext { */ const USER_KEY = 'user.account'; - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::setUuid(). - */ - public function setUuid() { - // Use the user's uuid to identify the config context. - $this->uuid = $this->get(self::USER_KEY)->uuid(); - } - /* * Helper function to create config context for user accounts. * @@ -44,7 +36,9 @@ public function setUuid() { * The user config context object. */ public function setAccount(User $account) { - $this->init(self::USER_KEY, $account); + $this->set(self::USER_KEY, $account); + // Re-initialize since the user change changes the context fundamentally. + $this->init(); return $this; }