diff --git a/core/includes/config.inc b/core/includes/config.inc index f1b3ce2..d871287 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -2,9 +2,7 @@ use Drupal\Core\Config\Config; use Drupal\Core\Config\FileStorage; -use Drupal\Core\Config\Context\AdminContext; -use Drupal\Core\Config\ContextInterface; -use Drupal\Core\Config\NullStorage; +use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Config\StorageInterface; /** @@ -94,26 +92,14 @@ function config_get_storage_names_with_prefix($prefix = '') { * a configuration file. For @code config('book.admin') @endcode, the config * object returned will contain the contents of book.admin configuration file. * + * @param \Drupal\Core\Config\Context\ContextInterface $context + * (Optional) The configuration context to use. + * * @return Drupal\Core\Config\Config * A configuration object. */ -function config($name) { - return drupal_container()->get('config.factory')->get($name); -} - -/** - * Sets the context on the configuration object factory. - * - * @param \Drupal\Core\Config\ContextInterface $context - * The configuration context to set on the factory. - * - * @return Drupal\Core\Config\ContextInterface $context - * The configuration context that was previously set in the config factory. - */ -function config_factory_set_context(ContextInterface $context) { - $current_context = drupal_container()->get('config.factory')->getContext(); - drupal_container()->get('config.factory')->setContext($context); - return $current_context; +function config($name, ContextInterface $context = NULL) { + return drupal_container()->get('config.factory')->get($name, $context); } /** @@ -190,11 +176,11 @@ function config_sync_get_changes(StorageInterface $source_storage, StorageInterf * The storage to synchronize configuration to. */ function config_sync_changes(array $config_changes, StorageInterface $source_storage, StorageInterface $target_storage) { - $target_context = new AdminContext('config.target', $target_storage); + $target_context = drupal_container()->get('config.context.admin'); $factory = drupal_container()->get('config.factory'); foreach (array('delete', 'create', 'change') as $op) { foreach ($config_changes[$op] as $name) { - $config = new Config($name, $target_context); + $config = new Config($name, $target_storage, $target_context); if ($op == 'delete') { $config->delete(); } @@ -261,8 +247,9 @@ function config_import() { * @todo Add support for other extension types; e.g., themes etc. */ function config_import_invoke_owner(array $config_changes, StorageInterface $source_storage, StorageInterface $target_storage) { - $target_context = new AdminContext('config.target', $target_storage); - $source_context = new AdminContext('config.target', $source_storage); + // Use the admin context for config importing so that any global overrides do + // not pollute the import. + $admin_context = drupal_container()->get('config.context.admin'); // Allow modules to take over configuration change operations for // higher-level configuration data. // First pass deleted, then new, and lastly changed configuration, in order to @@ -276,11 +263,11 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou // Validate the configuration object name before importing it. Config::validateName($name); if ($entity_type = config_get_entity_type_by_name($name)) { - $old_config = new Config($name, $target_context); + $old_config = new Config($name, $target_storage, $admin_context); $old_config->load(); $data = $source_storage->read($name); - $new_config = new Config($name, $source_context); + $new_config = new Config($name, $source_storage, $admin_context); if ($data !== FALSE) { $new_config->setData($data); } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 6eb1db8..8b48174 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -337,10 +337,15 @@ function install_begin_request(&$install_state) { $container->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher'); $container->register('config.storage', 'Drupal\Core\Config\InstallStorage'); - $container->register('config.context', 'Drupal\Core\Config\Context\ConfigContext') - ->addArgument(new Reference('config.storage')) + $container->register('config.context.factory', 'Drupal\Core\Config\Context\ConfigContextFactory') ->addArgument(new Reference('event_dispatcher')); + + $container->register('config.context', 'Drupal\Core\Config\Context\ContextInterface') + ->setFactoryService(new Reference('config.context.factory')) + ->setFactoryMethod('get'); + $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') + ->addArgument(new Reference('config.storage')) ->addArgument(new Reference('config.context')); // Register the 'language_manager' service. diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index a65d302..0337d28 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -9,7 +9,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Config\ConfigNameException; -use Drupal\Core\Config\ContextInterface; +use Drupal\Core\Config\Context\ContextInterface; /** * Defines the default configuration object. @@ -73,7 +73,7 @@ class Config { /** * The configuration context used for this configuration object. * - * @var Drupal\Core\Config\ContextInterface + * @var \Drupal\Core\Config\Context\ContextInterface */ protected $context; @@ -89,13 +89,16 @@ class Config { * * @param string $name * The name of the configuration object being constructed. - * @param \Drupal\Core\Config\ContextInterface $context + * @param \Drupal\Core\Config\StorageInterface $storage + * A storage controller object to use for reading and writing the + * configuration data. + * @param \Drupal\Core\Config\Context\ContextInterface $context * The configuration context used for this configuration object. */ - public function __construct($name, ContextInterface $context) { + public function __construct($name, StorageInterface $storage, ContextInterface $context) { $this->name = $name; + $this->storage = $storage; $this->context = $context; - $this->storage = $context->getStorage(); } /** @@ -475,6 +478,16 @@ public function delete() { } /** + * Retrieve the storage used to load and save this configuration object. + * + * @return \Drupal\Core\Config\StorageInterface + * The configuration storage object. + */ + public function getStorage() { + return $this->storage; + } + + /** * Dispatch a config event. */ protected function notify($config_event_name) { diff --git a/core/lib/Drupal/Core/Config/ConfigEvent.php b/core/lib/Drupal/Core/Config/ConfigEvent.php index 7a13e55..c1df902 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvent.php +++ b/core/lib/Drupal/Core/Config/ConfigEvent.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Config; +use Drupal\Core\Config\Context\ContextInterface; use Symfony\Component\EventDispatcher\Event; class ConfigEvent extends Event { @@ -16,14 +17,14 @@ class ConfigEvent extends Event { /** * Configuration context object. * - * @var Drupal\Core\Config\ContextInterface + * @var \Drupal\Core\Config\Context\ContextInterface */ protected $context; /** * Constructs a configuration event object. * - * @param \Drupal\Core\Config\ContextInterface + * @param \Drupal\Core\Config\Context\ContextInterface * Configuration context object. * @param \Drupal\Core\Config\Config * (optional) Configuration object. @@ -43,7 +44,7 @@ public function getConfig() { /** * Get configuration context object. * - * @return Drupal\Core\Config\ContextInterface + * @return \Drupal\Core\Config\Context\ContextInterface * Configuration context. */ public function getContext() { diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index eda9324..2ff8910 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Config; -use Drupal\Core\Config\ContextInterface; +use Drupal\Core\Config\Context\ContextInterface; /** * Defines the configuration object factory. @@ -17,20 +17,32 @@ * * @see Drupal\Core\Config\Config * + * Each configuration object gets a storage controller object injected, which + * is used for reading and writing the configuration data. + * + * @see Drupal\Core\Config\StorageInterface + * * A configuration context is an object containing parameters that will be * available to the configuration plug-ins for them to customize the * configuration data in different ways. * - * @see Drupal\Core\Config\StorageInterface + * @see Drupal\Core\Config\Context\ContextInterface */ class ConfigFactory { /** + * A storage controller instance for reading and writing configuration data. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $storage; + + /** * The default configuration context associated with this factory. * - * @var Drupal\Core\Config\ContextInterface + * @var \Drupal\Core\Config\Context\ContextInterface */ - protected $context; + protected $context; /** * Cached configuration objects. @@ -42,10 +54,13 @@ class ConfigFactory { /** * Constructs the Config factory. * - * @param \Drupal\Core\Config\ContextInterface + * @param \Drupal\Core\Config\StorageInterface + * The configuration storage engine. + * @param \Drupal\Core\Config\Context\ContextInterface * Configuration context object. */ - public function __construct(ContextInterface $context) { + public function __construct(StorageInterface $storage, ContextInterface $context) { + $this->storage = $storage; $this->setContext($context); } @@ -54,14 +69,19 @@ public function __construct(ContextInterface $context) { * * @param string $name * The name of the configuration object to construct. + * @param \Drupal\Core\Config\Context\ContextInterface $context + * (Optional) The configuration context to use. */ - public function get($name) { - $cache_key = get_class($this->getContext()) . ':' . $name; + public function get($name, ContextInterface $context = NULL) { + if ($context) { + $this->setContext($context); + } + $cache_key = $this->getCacheKey($name); if (isset($this->cache[$cache_key])) { return $this->cache[$cache_key]; } - $this->cache[$cache_key] = new Config($name, $this->getContext()); + $this->cache[$cache_key] = new Config($name, $this->storage, $this->getContext()); return $this->cache[$cache_key]->init(); } @@ -74,7 +94,7 @@ public function get($name) { */ public function reset($name = NULL) { if ($name) { - $cache_key = get_class($this->getContext()) . ':' . $name; + $cache_key = $this->getCacheKey($name); if (isset($this->cache[$cache_key])) { $this->cache[$cache_key]->init(); } @@ -97,8 +117,8 @@ public function reset($name = NULL) { * @todo D8: Remove after http://drupal.org/node/1865206. */ public function rename($old_name, $new_name) { - $old_cache_key = get_class($this->getContext()) . ':' . $old_name; - $new_cache_key = get_class($this->getContext()) . ':' . $new_name; + $old_cache_key = $this->getCacheKey($old_name); + $new_cache_key = $this->getCacheKey($new_name); if (isset($this->cache[$old_cache_key])) { $config = $this->cache[$old_cache_key]; // Clone the object into the existing slot. @@ -113,7 +133,7 @@ public function rename($old_name, $new_name) { /** * Gets the default context for this factory. * - * @return Drupal\Core\Config\ContextInterface + * @return Drupal\Core\Config\Context\ContextInterface * A configuration context instance. */ public function getContext() { @@ -123,11 +143,21 @@ public function getContext() { /** * Sets the default context for this factory. * - * @param \Drupal\Core\Config\ContextInterface $context + * @param \Drupal\Core\Config\Context\ContextInterface $context * Context to use to get the configuration. */ public function setContext($context) { $this->context = $context; } + + /* + * Gets the cache key for a given config name in a particular context. + * + * @return string + * The cache key. + */ + public function getCacheKey($name) { + return $this->getContext()->getUuid() . ':' . $name; + } } diff --git a/core/lib/Drupal/Core/Config/Context/AdminContext.php b/core/lib/Drupal/Core/Config/Context/AdminContext.php deleted file mode 100644 index 4424623..0000000 --- a/core/lib/Drupal/Core/Config/Context/AdminContext.php +++ /dev/null @@ -1,40 +0,0 @@ -set(self::ADMIN, $name); - $this->set($name, TRUE); - parent::__construct($storage ?: drupal_container()->get('config.storage'), drupal_container()->get('event_dispatcher')); - } - -} diff --git a/core/lib/Drupal/Core/Config/Context/ConfigContext.php b/core/lib/Drupal/Core/Config/Context/ConfigContext.php index d503beb..2b7ba7f 100644 --- a/core/lib/Drupal/Core/Config/Context/ConfigContext.php +++ b/core/lib/Drupal/Core/Config/Context/ConfigContext.php @@ -2,16 +2,14 @@ /** * @file - * Contains Drupal\Core\Config\Context\ConfigContext. + * Contains \Drupal\Core\Config\Context\ConfigContext. */ namespace Drupal\Core\Config\Context; use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigEvent; -use Drupal\Core\Config\ContextInterface; -use Drupal\Core\Config\StorageInterface; -use Drupal\Core\KeyValueStore\MemoryStorage; +use Drupal\Component\Uuid\Uuid; use Symfony\Component\EventDispatcher\EventDispatcher; /** @@ -20,17 +18,7 @@ * A configuration context object provides a key/value store that can be used * as a parameter to get customized configuration objects. */ -class ConfigContext extends MemoryStorage implements ContextInterface { - - /** - * Predefined key, will be TRUE for administrative contexts. - */ - const ADMIN = 'config.admin'; - - /** - * Predefined key, will contain the object type for object contexts. - */ - const OBJECT = 'config.object'; +class ConfigContext implements ContextInterface { /** * Predefined key, values to override specific configuration objects. @@ -38,44 +26,94 @@ class ConfigContext extends MemoryStorage implements ContextInterface { const OVERRIDE = 'config.override'; /** - * A storage controller instance for reading and writing configuration data. + * The actual storage of key-value pairs. * - * @var Drupal\Core\Config\StorageInterface + * @var array */ - protected $storage; + protected $data = array(); /** * An event dispatcher instance to use for configuration events. * - * @var Symfony\Component\EventDispatcher\EventDispatcher + * @var \Symfony\Component\EventDispatcher\EventDispatcher */ protected $eventDispatcher; /** + * A unique identifier for the context. + * + * @var string + */ + protected $uuid; + + /** * Constructs the configuration context. * - * @param \Drupal\Core\Config\StorageInterface $storage - * The storage controller object to use for reading and writing - * configuration data. - * @param Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher + * @param \Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher * An event dispatcher instance to use for configuration events. */ - public function __construct(StorageInterface $storage, EventDispatcher $event_dispatcher) { - $this->storage = $storage; + public function __construct(EventDispatcher $event_dispatcher) { $this->eventDispatcher = $event_dispatcher; + } + + /** + * Implements Drupal\Core\Config\Context\ContextInterface::init(). + */ + public function init($context_key, $data) { + if ($data) { + $this->set($context_key, $data); + } + $this->setUuid(); // Notify event listeners that a configuration context has been created. $this->notify('context', NULL); + return $this; + } + + /** + * Implements Drupal\Core\Config\Context\ContextInterface::get(). + */ + public function get($key) { + return array_key_exists($key, $this->data) ? $this->data[$key] : NULL; + } + + /** + * Implements Drupal\Core\Config\Context\ContextInterface::set(). + */ + public function set($key, $value) { + $this->data[$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() { + $uuid = new Uuid(); + $this->uuid = $uuid->generate(); } /** - * Implements Drupal\Core\Config\ContextInterface::getStorage(). + * Implements Drupal\Core\Config\Context\ContextInterface::getUuid(). */ - public function getStorage() { - return $this->storage; + public function getUuid() { + return $this->uuid; } /** - * Implements Drupal\Core\Config\ContextInterface::notify(). + * Implements Drupal\Core\Config\Context\ContextInterface::notify(). */ public function notify($config_event_name, Config $config = NULL) { $this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($this, $config)); diff --git a/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php b/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php new file mode 100644 index 0000000..a5100d8 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php @@ -0,0 +1,65 @@ +eventDispatcher = $event_dispatcher; + } + + /** + * Returns a configuration context object. + * + * @param string $class + * (Optional) The name of the configuration class to use. Defaults to + * Drupal\Core\Config\Context\ConfigContext + * @param \Drupal\Core\Config\Context\ContextInterface $context + * (Optional) The configuration context to use. + */ + public function get($class = NULL) { + if (!$class) { + $class = "Drupal\\Core\\Config\\Context\\ConfigContext"; + } + if (class_exists($class)) { + $context = new $class($this->eventDispatcher); + } + else { + throw new \Drupal\Core\Config\ConfigException(sprintf('Unknown config context class: %s', $class)); + } + return $context; + } + + +} diff --git a/core/lib/Drupal/Core/Config/Context/ContextInterface.php b/core/lib/Drupal/Core/Config/Context/ContextInterface.php new file mode 100644 index 0000000..b3107a7 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Context/ContextInterface.php @@ -0,0 +1,88 @@ +data[self::OVERRIDE] = $conf; - parent::__construct($storage, $event_dispatcher); - } - -} diff --git a/core/lib/Drupal/Core/Config/Context/ObjectContext.php b/core/lib/Drupal/Core/Config/Context/ObjectContext.php deleted file mode 100644 index 97a5e2b..0000000 --- a/core/lib/Drupal/Core/Config/Context/ObjectContext.php +++ /dev/null @@ -1,41 +0,0 @@ -set(self::OBJECT, $name); - $this->set($name, $object); - parent::__construct(drupal_container()->get('config.storage'), drupal_container()->get('event_dispatcher')); - } - -} diff --git a/core/lib/Drupal/Core/Config/ContextInterface.php b/core/lib/Drupal/Core/Config/ContextInterface.php deleted file mode 100644 index d928bb0..0000000 --- a/core/lib/Drupal/Core/Config/ContextInterface.php +++ /dev/null @@ -1,43 +0,0 @@ -addArgument(new Reference('config.cachedstorage.storage')) ->addArgument(new Reference('cache.config')); - $container->register('config.context', 'Drupal\Core\Config\Context\GlobalContext') - ->addArgument(new Reference('config.storage')) + $container->register('config.context.factory', 'Drupal\Core\Config\Context\ConfigContextFactory') ->addArgument(new Reference('event_dispatcher')); + $container->register('config.context', 'Drupal\Core\Config\Context\ContextInterface') + ->setFactoryService(new Reference('config.context.factory')) + ->setFactoryMethod('get') + ->addMethodCall('setOverride', array($conf)); + + $container->register('config.context.admin', 'Drupal\Core\Config\Context\ContextInterface') + ->setFactoryService(new Reference('config.context.factory')) + ->setFactoryMethod('get'); + $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') + ->addArgument(new Reference('config.storage')) ->addArgument(new Reference('config.context')) ->addTag('persist'); diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php index 9678102..376da10 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ConfigOverrideSubscriber.php @@ -1,14 +1,13 @@ 'Locale override', + 'description' => 'Confirm that locale overrides work', + 'group' => 'Configuration', + ); + } + + public function setUp() { + parent::setUp(); + config_install_default_config('module', 'config_test'); + } + + /* + * Tests basic locale override. + */ + function testConfigLocaleOverride() { + $name = 'config_test.system'; + // Verify the default configuration values exist. + $config = config($name); + $this->assertIdentical($config->get('foo'), 'en bar'); + } + + /* + * Tests locale override based on user's preferred language. + */ + function testConfigLocaleUserOverride() { + $this->installSchema('system', 'variable'); + $this->installSchema('language', 'language'); + language_save(new Language(array( + 'name' => 'French', + 'langcode' => 'fr', + ))); + language_save(new Language(array( + 'name' => 'English', + 'langcode' => 'en', + ))); + + $this->installSchema('user', 'users'); + $account = entity_create('user', array( + 'name' => 'French user', + 'mail' => 'test@example.com', + 'created' => REQUEST_TIME, + 'status' => 1, + 'preferred_langcode' => 'fr', + )); + + $config_context = drupal_container()->get('config.context.user')->setAccount($account); + $config = config('config_test.system', $config_context); + $this->assertIdentical($config->get('foo'), 'fr bar'); + + $account = entity_create('user', array( + 'name' => 'English user', + 'mail' => 'test@example.com', + 'created' => REQUEST_TIME, + 'status' => 1, + 'preferred_langcode' => 'en', + )); + $config_context = drupal_container()->get('config.context.user')->setAccount($account); + // Should not have to re-initialise config object to get new overrides as + // the new context will have a different uuid. + $config = config('config_test.system', $config_context); + $this->assertIdentical($config->get('foo'), 'en bar'); + + $config = system_config('config_test.system'); + $this->assertIdentical($config->get('foo'), 'bar'); + } + +} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php index f015f82..1dfc9f3 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php @@ -53,11 +53,12 @@ function testConfOverride() { $this->assertIdentical($config->get('baz'), $expected_original_data['baz']); $this->assertIdentical($config->get('404'), $expected_original_data['404']); - // Apply the overridden data, that needs to be set into the GlobalContext object. + // 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')->set(ConfigContext::OVERRIDE, $conf); + drupal_container()->get('config.context')->setOverride($conf); // Verify that the in-memory configuration object still contains the // original data. @@ -95,9 +96,9 @@ 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 GlobalContext object. + // Remove the $conf overrides and reset value in config.context service. unset($conf['config_test.system']); - drupal_container()->get('config.context')->set(ConfigContext::OVERRIDE, $conf); + drupal_container()->get('config.context')->setOverride($conf); // Reload it and verify that it still contains the original data. $config->init(); diff --git a/core/modules/config/lib/Drupal/config/Tests/LocaleConfigOverride.php b/core/modules/config/lib/Drupal/config/Tests/LocaleConfigOverride.php deleted file mode 100644 index 20f835d..0000000 --- a/core/modules/config/lib/Drupal/config/Tests/LocaleConfigOverride.php +++ /dev/null @@ -1,38 +0,0 @@ - 'Locale override', - 'description' => 'Confirm that locale overrides work', - 'group' => 'Configuration', - ); - } - - function testLocaleConfigOverride() { - $name = 'config_test.system'; - // Verify the default configuration values exist. - $config = config($name); - $this->assertIdentical($config->get('foo'), 'en bar'); - } -} diff --git a/core/modules/config/tests/config_test/config/locale.config.fr.config_test.system.yml b/core/modules/config/tests/config_test/config/locale.config.fr.config_test.system.yml new file mode 100644 index 0000000..c36dbf7 --- /dev/null +++ b/core/modules/config/tests/config_test/config/locale.config.fr.config_test.system.yml @@ -0,0 +1 @@ +foo: fr bar diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php index 955641d..79ebbd3 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php @@ -1,14 +1,16 @@ languageManager = $language_manager; + } /** * Initialize configuration context with language. @@ -28,18 +48,20 @@ class LocaleConfigSubscriber implements EventSubscriberInterface { */ public function configContext(ConfigEvent $event) { $context = $event->getContext(); - if (!$context->get('locale.language')) { - // Add user's language for user context. - if ($account = $context->get('user.account')) { - $context->set('locale.language', language_load(user_preferred_langcode($account))); - } + + // Add user's language for user context. + if ($account = $context->get('user.account')) { + $context->set('locale.language', language_load(user_preferred_langcode($account))); + } + elseif ($language = $this->languageManager->getLanguage(LANGUAGE_TYPE_INTERFACE)) { + $context->set('locale.language', $language); } } /** * Override configuration values with localized data. * - * @param Drupal\Core\Config\ConfigEvent $event + * @param \Drupal\Core\Config\ConfigEvent $event * The Event to process. */ public function configLoad(ConfigEvent $event) { @@ -47,7 +69,9 @@ public function configLoad(ConfigEvent $event) { if ($language = $context->get('locale.language')) { $config = $event->getConfig(); $locale_name = $this->getLocaleConfigName($config->getName(), $language); - if ($override = $context->getStorage()->read($locale_name)) { + // Check to see if the config storage has an appropriately named file + // containing override data. + if ($override = $event->getConfig()->getStorage()->read($locale_name)) { $config->setOverride($override); } } @@ -58,8 +82,16 @@ public function configLoad(ConfigEvent $event) { * * It will be the same name with a prefix depending on language code: * locale.config.LANGCODE.NAME + * + * @param string $name + * The name of the config object. + * @param \Drupal\Core\Language\Language $language + * The language object. + * + * @return string + * The localised config name. */ - public function getLocaleConfigName($name, $language) { + public function getLocaleConfigName($name, Language $language) { return 'locale.config.' . $language->langcode . '.' . $name; } diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index c0d55d4..b54d76a 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -16,7 +16,6 @@ use Drupal\locale\StringDatabaseStorage; use Drupal\locale\TranslationsStream; use Drupal\Core\Database\Database; -use Drupal\Core\Config\ConfigFactory; /** * Regular expression pattern used to localize JavaScript strings. @@ -1308,13 +1307,3 @@ function _locale_rebuild_js($langcode = NULL) { return TRUE; } } - -/** - * Implements hook_language_init(). - */ -function locale_language_init() { - // Add current language to default configuration context. - drupal_container()->get('config.context')->set('locale.language', language(LANGUAGE_TYPE_INTERFACE)); - // Add locale helper to configuration subscribers. - drupal_container()->get('event_dispatcher')->addSubscriber(new LocaleConfigSubscriber()); -} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 41750be..543af6f 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -7,7 +7,6 @@ use Drupal\Core\Utility\ModuleInfo; use Drupal\Core\TypedData\Primitive; -use Drupal\Core\Config\Context\AdminContext; use Drupal\system\Plugin\block\block\SystemMenuBlock; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; @@ -3463,11 +3462,7 @@ function system_admin_compact_page($mode = 'off') { * @see config() */ function system_config($name) { - static $context; - if (!isset($context)) { - $context = new AdminContext('system.config', drupal_container()->get('config.storage')); - } - return config($name, $context); + return config($name, drupal_container()->get('config.context.admin')); } /** diff --git a/core/modules/user/lib/Drupal/user/UserBundle.php b/core/modules/user/lib/Drupal/user/UserBundle.php index a4e7d8d..c963bc6 100644 --- a/core/modules/user/lib/Drupal/user/UserBundle.php +++ b/core/modules/user/lib/Drupal/user/UserBundle.php @@ -25,5 +25,9 @@ public function build(ContainerBuilder $container) { $container ->register('user.data', 'Drupal\user\UserData') ->addArgument(new Reference('database')); + $container->register('config.context.user', 'Drupal\Core\Config\Context\ContextInterface') + ->setFactoryService(new Reference('config.context.factory')) + ->setFactoryMethod('get') + ->addArgument('Drupal\user\UserConfigContext'); } } diff --git a/core/modules/user/lib/Drupal/user/UserConfigContext.php b/core/modules/user/lib/Drupal/user/UserConfigContext.php index 2206df7..ed0b957 100644 --- a/core/modules/user/lib/Drupal/user/UserConfigContext.php +++ b/core/modules/user/lib/Drupal/user/UserConfigContext.php @@ -2,27 +2,45 @@ /** * @file - * Contains Drupal\user\UserConfigContext + * Contains \Drupal\user\UserConfigContext */ namespace Drupal\user; -use Drupal\Core\Config\Context\ObjectContext; +use Drupal\Core\Config\Context\ConfigContext; use Drupal\user\Plugin\Core\Entity\User; + /** * Defines a configuration context object for a user account. */ -class UserConfigContext extends ObjectContext { +class UserConfigContext extends ConfigContext { + + /** + * Predefined key for account object. + */ + const USER_KEY = 'user.account'; /** - * Overrides \Drupal\Core\Config\ConfigContext::__construct(). + * 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. + * + * @param \Drupal\user\Plugin\Core\Entity\User $account + * The account to add to the config context. * - * @param \Drupal\user\Plugin\Core\Entity\User $user - * The user object to use in this context. + * @return \Drupal\user\UserConfigContext + * The user config context object. */ - public function __construct($user) { - parent::__construct('user.account', $user); + public function setAccount(User $account) { + $this->init(self::USER_KEY, $account); + return $this; } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 3fa64f2..c5f360c 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -702,18 +702,6 @@ function user_format_name($account) { } /** - * Implements hook_config_context_info(). - */ -function user_config_context_info() { - return array( - 'user.account' => array( - 'title' => t('User account'), - 'class' => '\Drupal\user\UserConfigContext', - ), - ); -} - -/** * Implements hook_template_preprocess_default_variables_alter(). * * @see user_user_login() @@ -1766,17 +1754,14 @@ function user_mail($key, &$message, $params) { // Get configuration objects customized for this user, that may be localized // for the user's language if the locale module is enabled. - $config_context = config_factory_set_context(new UserConfigContext($params['account'])); - $mail_config = config('user.mail'); + $config_context = drupal_container()->get('config.context.user')->setAccount($params['account']); + $mail_config = config('user.mail', $config_context); // We do not sanitize the token replacement, since the output of this // replacement is intended for an e-mail message, not a web browser. $token_options = array('langcode' => $langcode, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE); $message['subject'] .= token_replace($mail_config->get($key . '.subject'), $variables, $token_options); $message['body'][] = token_replace($mail_config->get($key . '.body'), $variables, $token_options); - - // Set the configuration context back to the original. - config_factory_set_context($config_context); } /**