diff --git a/core/core.services.yml b/core/core.services.yml index 1449b3b..8e9ca23 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -75,25 +75,12 @@ services: arguments: ['@config.cachedstorage.storage', '@cache.config'] tags: - { name: persist } - config.context.factory: - class: Drupal\Core\Config\Context\ConfigContextFactory - arguments: ['@event_dispatcher', '@uuid'] - config.context: - class: Drupal\Core\Config\Context\ContextInterface - tags: - - { name: persist } - factory_method: get - factory_service: config.context.factory - config.context.free: - class: Drupal\Core\Config\Context\ContextInterface - factory_method: get - factory_service: config.context.factory - arguments: [Drupal\Core\Config\Context\FreeConfigContext] config.factory: class: Drupal\Core\Config\ConfigFactory tags: - { name: persist } - arguments: ['@config.storage', '@config.context', '@config.typed'] + - { name: event_subscriber } + arguments: ['@config.storage', '@event_dispatcher', '@config.typed'] config.storage.staging: class: Drupal\Core\Config\FileStorage factory_class: Drupal\Core\Config\FileStorageFactory @@ -617,7 +604,7 @@ services: arguments: ['@module_handler'] date: class: Drupal\Core\Datetime\Date - arguments: ['@entity.manager', '@language_manager', '@string_translation'] + arguments: ['@entity.manager', '@language_manager', '@string_translation', '@config.factory'] feed.bridge.reader: class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer calls: diff --git a/core/includes/config.inc b/core/includes/config.inc index c7fca03..e4fb08f 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -3,12 +3,14 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigException; +use Drupal\Core\Language\Language; use Drupal\Core\Config\ExtensionInstallStorage; use Drupal\Core\Config\Context\FreeConfigContext; use Drupal\Core\Config\FileStorage; use Drupal\Core\Config\StorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Symfony\Component\Yaml\Dumper; +use Symfony\Component\EventDispatcher\EventDispatcher; /** * @file @@ -66,17 +68,18 @@ function ($value) use ($name) { if (!empty($config_to_install)) { $entity_manager = Drupal::service('entity.manager'); $config_factory = Drupal::service('config.factory'); - $context = new FreeConfigContext(Drupal::service('event_dispatcher'), Drupal::service('uuid')); $target_storage = Drupal::service('config.storage'); $typed_config = Drupal::service('config.typed'); - $config_factory->enterContext($context); + $event_dispatcher = Drupal::service('event_dispatcher'); + + $config_factory->disableOverrides(); foreach ($config_to_install as $name) { // Only import new config. if ($target_storage->exists($name)) { continue; } - $new_config = new Config($name, $target_storage, $context, $typed_config); + $new_config = new Config($name, $target_storage, $event_dispatcher, $typed_config); $data = $source_storage->read($name); if ($data !== FALSE) { $new_config->setData($data); @@ -90,11 +93,8 @@ function ($value) use ($name) { else { $new_config->save(); } - - // Reset static cache on the config factory. - $config_factory->reset($name); + $config_factory->enableOverrides(); } - $config_factory->leaveContext(); } } @@ -146,54 +146,6 @@ function config($name) { } /** - * Sets the config context on the config factory. - * - * This allows configuration objects to be created using special configuration - * contexts eg. global override free or locale using a user preferred language. - * Calling this function affects all subsequent calls to \Drupal::config() until - * config_context_leave() is called. - * - * @see config_context_leave() - * @see \Drupal\Core\Config\ConfigFactory - * - * @param string $context_name - * The name of the config context service on the container or a fully - * qualified class implementing \Drupal\Core\Config\Context\ContextInterface. - * - * @return \Drupal\Core\Config\Context\ContextInterface - * The configuration context object. - */ -function config_context_enter($context_name) { - $container = \Drupal::getContainer(); - if ($container->has($context_name)) { - $context = $container->get($context_name); - } - elseif (class_exists($context_name) && in_array('Drupal\Core\Config\Context\ContextInterface', class_implements($context_name))) { - $context = $container - ->get('config.context.factory') - ->get($context_name); - } - else { - throw new ConfigException(sprintf('Unknown config context service or class: %s', $context_name)); - } - $container - ->get('config.factory') - ->enterContext($context); - return $context; -} - -/** - * Leaves the current config context returning to the previous context. - * - * @see config_context_enter() - * @see \Drupal\Core\Config\ConfigFactory - */ -function config_context_leave() { - \Drupal::service('config.factory') - ->leaveContext(); -} - -/** * Returns the entity type of a configuration object. * * @param string $name diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index e6a5338..46fbcbc 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -378,13 +378,6 @@ 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.factory', 'Drupal\Core\Config\Context\ConfigContextFactory') - ->addArgument(new Reference('event_dispatcher')) - ->addArgument(new Reference('uuid')); - - $container->register('config.context', 'Drupal\Core\Config\Context\ContextInterface') - ->setFactoryService(new Reference('config.context.factory')) - ->setFactoryMethod('get'); $container->register('config.storage.schema', 'Drupal\Core\Config\Schema\SchemaStorage'); @@ -395,7 +388,7 @@ function install_begin_request(&$install_state) { $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') ->addArgument(new Reference('config.storage')) - ->addArgument(new Reference('config.context')) + ->addArgument(new Reference('event_dispatcher')) ->addArgument(new Reference('config.typed')); // Register the 'language_manager' service. diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 856c424..b0a14cb 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -2563,7 +2563,7 @@ function menu_router_rebuild() { function menu_router_build($save = FALSE) { // Ensure that all configuration used to build the menu items are loaded // without overrides. - config_context_enter('config.context.free'); + \Drupal::configFactory()->disableOverrides(); // We need to manually call each module so that we can know which module // a given item came from. $callbacks = array(); @@ -2578,8 +2578,8 @@ function menu_router_build($save = FALSE) { } // Alter the menu as defined in modules, keys are like user/%user. drupal_alter('menu', $callbacks); - // Return to the original context before menu building. - config_context_leave(); + // Re-enable configuration overrides. + \Drupal::configFactory()->enableOverrides(); foreach ($callbacks as $path => $router_item) { // If the menu item is a default local task and incorrectly references a // route, remove it. diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 9c14801..6af2411 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -242,6 +242,19 @@ public static function config($name) { } /** + * Retrieves the configuration factory. + * + * This is mostly used to change the override settings on the configuration + * factory. For example, changing the language, or turning all overrides on + * or off. + * + * @return \Drupal\Core\Config\ConfigFactory + */ + public static function configFactory() { + return static::$container->get('config.factory'); + } + + /** * Returns a queue for the given queue name. * * The following values can be set in your settings.php file's $settings diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index e026717..38761ac 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -10,11 +10,12 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Core\Config\ConfigNameException; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Config\Schema\SchemaIncompleteException; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\IntegerInterface; +use Drupal\Core\Language\Language; +use Symfony\Component\EventDispatcher\EventDispatcher; /** * Defines the default configuration object. @@ -34,6 +35,20 @@ class Config { const MAX_NAME_LENGTH = 250; /** + * An event dispatcher instance to use for configuration events. + * + * @var \Symfony\Component\EventDispatcher\EventDispatcher + */ + protected $eventDispatcher; + + /** + * The language object used to override configuration data. + * + * @var Drupal\Core\Language\Language + */ + protected $language; + + /** * The name of the configuration object. * * @var string @@ -55,25 +70,35 @@ class Config { protected $data; /** - * The current runtime data ($data + $overrides from Config Context). + * The current runtime data. + * + * The configuration data from storage merged with language, module and + * settings overrides. * * @var array */ protected $overriddenData; /** - * The storage used to load and save this configuration object. + * The current language overrides. * - * @var \Drupal\Core\Config\StorageInterface + * @var array */ - protected $storage; + protected $languageOverrides; /** - * The configuration context used for this configuration object. + * The current module overrides. * - * @var \Drupal\Core\Config\Context\ContextInterface + * @var array */ - protected $context; + protected $moduleOverrides; + + /** + * The storage used to load and save this configuration object. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $storage; /** * Whether the configuration object has already been loaded. @@ -104,28 +129,19 @@ class Config { * @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. + * @param \Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher + * An event dispatcher instance to use for configuration events. * @param \Drupal\Core\Config\TypedConfigManager $typed_config * The typed configuration manager service. + * @param \Drupal\Core\Language\Language $language + * The language object used to override configuration data. */ - public function __construct($name, StorageInterface $storage, ContextInterface $context, TypedConfigManager $typed_config) { + public function __construct($name, StorageInterface $storage, EventDispatcher $event_dispatcher, TypedConfigManager $typed_config, Language $language = NULL) { $this->name = $name; $this->storage = $storage; - $this->context = $context; + $this->eventDispatcher = $event_dispatcher; $this->typedConfigManager = $typed_config; - } - - /** - * Initializes a configuration object. - * - * @return \Drupal\Core\Config\Config - * The configuration object. - */ - public function init() { - $this->isLoaded = FALSE; - $this->notify('init'); - return $this; + $this->language = $language; } /** @@ -139,10 +155,11 @@ public function init() { */ public function initWithData(array $data) { $this->isLoaded = TRUE; + $this->settingsOverrides = array(); + $this->languageOverrides = array(); + $this->moduleOverrides = array(); $this->isNew = FALSE; - $this->notify('init'); $this->replaceData($data); - $this->notify('load'); return $this; } @@ -295,7 +312,7 @@ protected function replaceData(array $data) { } /** - * Sets overridden data for this configuration object. + * Sets settings.php overrides for this configuration object. * * The overridden data only applies to this configuration object. * @@ -305,8 +322,38 @@ protected function replaceData(array $data) { * @return \Drupal\Core\Config\Config * The configuration object. */ - public function setOverride(array $data) { - $this->context->setOverrides($this->getName(), $data); + public function setSettingsOverride(array $data) { + $this->settingsOverrides = $data; + $this->resetOverriddenData(); + return $this; + } + + /** + * Sets module overrides for this configuration object. + * + * @param array $data + * The overridden values of the configuration data. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ + public function setModuleOverride(array $data) { + $this->moduleOverrides = $data; + $this->resetOverriddenData(); + return $this; + } + + /** + * Sets language overrides for this configuration object. + * + * @param array $data + * The overridden values of the configuration data. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ + public function setLanguageOverride(array $data) { + $this->languageOverrides = $data; $this->resetOverriddenData(); return $this; } @@ -314,16 +361,24 @@ public function setOverride(array $data) { /** * Sets the current data for this configuration object. * - * Merges overridden configuration data into the original data. + * Configuration overrides operate at three distinct layers: language, modules + * and settings.php, with the last of these taking precedence. Overrides in + * settings.php take precedence over values provided by modules. Overrides + * provided by modules take precedence over language. * * @return \Drupal\Core\Config\Config * The configuration object. */ protected function setOverriddenData() { $this->overriddenData = $this->data; - $overrides = $this->context->getOverrides($this->getName()); - if (is_array($overrides)) { - $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $overrides), TRUE); + if (isset($this->languageOverrides) && is_array($this->languageOverrides)) { + $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->languageOverrides), TRUE); + } + if (isset($this->moduleOverrides) && is_array($this->moduleOverrides)) { + $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->moduleOverrides), TRUE); + } + if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) { + $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->settingsOverrides), TRUE); } return $this; } @@ -412,7 +467,6 @@ public function load() { $this->isNew = FALSE; $this->replaceData($data); } - $this->notify('load'); $this->isLoaded = TRUE; return $this; } @@ -479,7 +533,7 @@ public function getStorage() { * The configuration event name. */ protected function notify($config_event_name) { - $this->context->notify($config_event_name, $this); + $this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($this)); } /** @@ -574,4 +628,14 @@ protected function castValue($key, $value) { return $value; } + /** + * Returns the language object for this Config object. + * + * @return \Drupal\Core\Language\Language + */ + public function getLanguage() { + return $this->language; + } + } + diff --git a/core/lib/Drupal/Core/Config/ConfigEvent.php b/core/lib/Drupal/Core/Config/ConfigEvent.php index 4cfac2e..5b07098 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvent.php +++ b/core/lib/Drupal/Core/Config/ConfigEvent.php @@ -2,7 +2,6 @@ namespace Drupal\Core\Config; -use Drupal\Core\Config\Context\ContextInterface; use Symfony\Component\EventDispatcher\Event; class ConfigEvent extends Event { @@ -15,23 +14,13 @@ class ConfigEvent extends Event { protected $config; /** - * Configuration context object. - * - * @var \Drupal\Core\Config\Context\ContextInterface - */ - protected $context; - - /** * Constructs a configuration event object. * - * @param \Drupal\Core\Config\Context\ContextInterface - * Configuration context object. * @param \Drupal\Core\Config\Config - * (optional) Configuration object. + * Configuration object. */ - public function __construct(ContextInterface $context, Config $config = NULL) { + public function __construct(Config $config) { $this->config = $config; - $this->context = $context; } /** @@ -40,14 +29,5 @@ public function __construct(ContextInterface $context, Config $config = NULL) { public function getConfig() { return $this->config; } - - /** - * Gets configuration context object. - * - * @return \Drupal\Core\Config\Context\ContextInterface - * Configuration context. - */ - public function getContext() { - return $this->context; - } } + diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index 7b1e97c..8a447fe 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -7,8 +7,9 @@ namespace Drupal\Core\Config; -use Drupal\Core\Config\Context\ContextInterface; -use Drupal\Core\Config\TypedConfigManager; +use Drupal\Core\Language\Language; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Defines the configuration object factory. @@ -22,14 +23,13 @@ * 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\Context\ContextInterface */ -class ConfigFactory { +class ConfigFactory implements EventSubscriberInterface { + + /** + * Prefix for all language configuration files. + */ + const LANGUAGE_CONFIG_PREFIX = 'language.config'; /** * A storage controller instance for reading and writing configuration data. @@ -39,16 +39,30 @@ class ConfigFactory { protected $storage; /** - * A stack of configuration contexts the last being the context in use. + * An event dispatcher instance to use for configuration events. * - * @var array + * @var \Symfony\Component\EventDispatcher\EventDispatcher */ - protected $contextStack = array(); + protected $eventDispatcher; + + /** + * A flag indicating if we should use overrides. + * + * @var boolean + */ + protected $useOverrides = TRUE; + + /** + * The language object used to override configuration data. + * + * @var \Drupal\Core\Language\Language + */ + protected $language; /** * Cached configuration objects. * - * @var array + * @var \Drupal\Core\Config\Config[] */ protected $cache = array(); @@ -64,19 +78,38 @@ class ConfigFactory { * * @param \Drupal\Core\Config\StorageInterface $storage * The configuration storage engine. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * Configuration context object. + * @param \Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher + * An event dispatcher instance to use for configuration events. * @param \Drupal\Core\Config\TypedConfigManager $typed_config * The typed configuration manager. + * @param \Drupal\Core\Language\Language + * (optional) The language for this configuration. The config factory will + * use it to override configuration data if language overrides are + * available. */ - public function __construct(StorageInterface $storage, ContextInterface $context, TypedConfigManager $typed_config) { + public function __construct(StorageInterface $storage, EventDispatcher $event_dispatcher, TypedConfigManager $typed_config, Language $language = NULL) { $this->storage = $storage; + $this->eventDispatcher = $event_dispatcher; $this->typedConfigManager = $typed_config; - $this->enterContext($context); + $this->language = $language; } /** - * Returns a configuration object for a given name and context. + * Disable overrides when loading configuration objects. + */ + public function disableOverrides() { + $this->useOverrides = FALSE; + } + + /** + * Enable overrides when loading configuration objects. + */ + public function enableOverrides() { + $this->useOverrides = TRUE; + } + + /** + * Returns a configuration object for a given name. * * @param string $name * The name of the configuration object to construct. @@ -85,18 +118,51 @@ public function __construct(StorageInterface $storage, ContextInterface $context * A configuration object. */ public function get($name) { - $context = $this->getContext(); - $cache_key = $this->getCacheKey($name, $context); - if (isset($this->cache[$cache_key])) { - return $this->cache[$cache_key]; + global $conf; + + if ($config = $this->loadMultiple(array($name))) { + return $config[$name]; } + else { + $cache_key = $this->getCacheKey($name); + // If the config object has been deleted it will already exist in the + // cache but self::loadMultiple does not return such objects. + // @todo Explore making ConfigFactory a listener to the config.delete + // event to reset the static cache when this occurs. + if (!isset($this->cache[$cache_key])) { + // If the configuration object does not exist in the configuration + // storage or static cache create a new object and add it to the static + // cache. + $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language); - $this->cache[$cache_key] = new Config($name, $this->storage, $context, $this->typedConfigManager); - return $this->cache[$cache_key]->init(); + if ($this->canOverride($name)) { + // Get and apply any language overrides. + if ($this->language) { + $language_overrides = $this->storage->read($this->getLanguageConfigName($this->language->id, $name)); + } + else { + $language_overrides = FALSE; + } + if (is_array($language_overrides)) { + $this->cache[$cache_key]->setLanguageOverride($language_overrides); + } + // Get and apply any module overrides. + $module_overrides = $this->loadModuleOverrides(array($name)); + if (isset($module_overrides[$name])) { + $this->cache[$cache_key]->setModuleOverride($module_overrides[$name]); + } + // Apply any settings.php overrides. + if (isset($conf[$name])) { + $this->cache[$cache_key]->setSettingsOverride($conf[$name]); + } + } + } + return $this->cache[$cache_key]; + } } /** - * Returns a list of configuration objects for a given names and context. + * Returns a list of configuration objects for the given names. * * This will pre-load all requested configuration objects does not create * new configuration objects. @@ -108,13 +174,14 @@ public function get($name) { * List of successfully loaded configuration objects, keyed by name. */ public function loadMultiple(array $names) { - $context = $this->getContext(); + global $conf; $list = array(); + foreach ($names as $key => $name) { - $cache_key = $this->getCacheKey($name, $context); // @todo: Deleted configuration stays in $this->cache, only return - // config entities that are not new. + // configuration objects that are not new. + $cache_key = $this->getCacheKey($name); if (isset($this->cache[$cache_key]) && !$this->cache[$cache_key]->isNew()) { $list[$name] = $this->cache[$cache_key]; unset($names[$key]); @@ -123,18 +190,70 @@ public function loadMultiple(array $names) { // Pre-load remaining configuration files. if (!empty($names)) { - $storage_data = $this->storage->readMultiple($names); + // Initialise override information. + $module_overrides = array(); + $language_names = array(); + + if ($this->useOverrides) { + // In order to make just one call to storage, add in language names. + // Keep track of them separately, so we can get language override data + // returned from storage and set it on new Config objects. + $language_names = $this->getLanguageConfigNames($names); + } + + $storage_data = $this->storage->readMultiple(array_merge($names, array_values($language_names))); + + if ($this->useOverrides && !empty($storage_data)) { + // Only fire module override event if we have configuration to override. + $module_overrides = $this->loadModuleOverrides($names); + } + foreach ($storage_data as $name => $data) { - $cache_key = $this->getCacheKey($name, $context); - $this->cache[$cache_key] = new Config($name, $this->storage, $context, $this->typedConfigManager); + if (in_array($name, $language_names)) { + // Language override configuration is used to override other + // configuration. Therefore, when it has been added to the + // $storage_data it is not statically cached in the config factory or + // overridden in any way. + continue; + } + $cache_key = $this->getCacheKey($name); + + $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language); $this->cache[$cache_key]->initWithData($data); + if ($this->canOverride($name)) { + if (isset($language_names[$name]) && isset($storage_data[$language_names[$name]])) { + $this->cache[$cache_key]->setLanguageOverride($storage_data[$language_names[$name]]); + } + if (isset($module_overrides[$name])) { + $this->cache[$cache_key]->setModuleOverride($module_overrides[$name]); + } + if (isset($conf[$name])) { + $this->cache[$cache_key]->setSettingsOverride($conf[$name]); + } + } $list[$name] = $this->cache[$cache_key]; } } + return $list; } /** + * Get arbitrary overrides for the named configuration objects from modules. + * + * @param array $names + * The names of the configuration objects to get overrides for. + * + * @return array + * An array of overrides keyed by the configuration object name. + */ + protected function loadModuleOverrides(array $names) { + $configOverridesEvent = new ConfigModuleOverridesEvent($names, $this->language); + $this->eventDispatcher->dispatch('config.module.overrides', $configOverridesEvent); + return $configOverridesEvent->getOverrides(); + } + + /** * Resets and re-initializes configuration objects. Internal use only. * * @param string $name @@ -146,7 +265,7 @@ public function loadMultiple(array $names) { */ public function reset($name = NULL) { if ($name) { - // Clear the cached configuration object in all contexts. + // Clear all cached configuration for this name. foreach ($this->getCacheKeys($name) as $cache_key) { unset($this->cache[$cache_key]); } @@ -174,103 +293,171 @@ public function reset($name = NULL) { * The renamed config object. */ public function rename($old_name, $new_name) { - $context = $this->getContext(); - $old_cache_key = $this->getCacheKey($old_name, $context); - $new_cache_key = $this->getCacheKey($new_name, $context); + $this->storage->rename($old_name, $new_name); + $old_cache_key = $this->getCacheKey($old_name); if (isset($this->cache[$old_cache_key])) { - $config = $this->cache[$old_cache_key]; unset($this->cache[$old_cache_key]); } - else { - // Create the config object if it's not yet loaded into the static cache. - $config = new Config($old_name, $this->storage, $context, $this->typedConfigManager); + + $new_cache_key = $this->getCacheKey($new_name); + $this->cache[$new_cache_key] = new Config($new_name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language); + $this->cache[$new_cache_key]->load(); + return $this->cache[$new_cache_key]; + } + + /** + * Gets the cache key for a given config name. + * + * @param string $name + * The name of the configuration object. + * + * @return string + * The cache key. + */ + public function getCacheKey($name) { + $can_override = $this->canOverride($name); + $cache_key = $name . ':' . ($can_override ? 'overrides' : 'raw'); + + if ($can_override && isset($this->language)) { + $cache_key = $cache_key . ':' . $this->language->id; } + return $cache_key; + } - $this->cache[$new_cache_key] = $config; - $this->storage->rename($old_name, $new_name); - return $this->cache[$new_cache_key]->setName($new_name)->init(); + /** + * Gets all the cache keys that match the provided config name. + * + * @param string $name + * The name of the configuration object. + * + * @return array + * An array of cache keys that match the provided config name. + */ + public function getCacheKeys($name) { + return array_filter(array_keys($this->cache), function($key) use ($name) { + // Return TRUE if the key starts with the configuration name. + return strpos($key, $name) === 0; + }); } /** - * Sets the config context by adding it to the context stack. + * Clears the config factory static cache. * - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to add. + * @return \Drupal\Core\Config\ConfigFactory + * The config factory object. + */ + public function clearStaticCache() { + $this->cache = array(); + return $this; + } + + /** + * Set the language to be used in configuration overrides. + * + * @param \Drupal\Core\Language\Language $language + * The language object to be set on the config factory. Used to override + * configuration by language. * * @return \Drupal\Core\Config\ConfigFactory * The config factory object. */ - public function enterContext(ContextInterface $context) { - // Initialize the context as it is being entered. - $this->contextStack[] = $context->init(); + public function setLanguage(Language $language = NULL) { + $this->language = $language; return $this; } /** - * Gets the current config context. + * Gets the language Used to override configuration. * - * @return \Drupal\Core\Config\Context\ContextInterface $context - * The current configuration context. + * @return \Drupal\Core\Language\Language */ - public function getContext() { - return end($this->contextStack); + public function getLanguage() { + return $this->language; } /** - * Leaves the current context by removing it from the context stack. + * Gets configuration names for this language. * - * @return \Drupal\Core\Config\ConfigFactory - * The config factory object. + * It will be the same name with a prefix depending on language code: + * language.config.LANGCODE.NAME + * + * @param array $names + * A list of configuration object names. + * + * @return array + * The localized config names, keyed by configuration object name. */ - public function leaveContext() { - // Ensure at least one context is left on the stack. We already ensured - // there is at least one context set by taking the initial one in the - // constructor. - if (count($this->contextStack) > 1) { - array_pop($this->contextStack); + public function getLanguageConfigNames(array $names) { + $language_names = array(); + if (isset($this->language)) { + foreach ($names as $name) { + if ($language_name = $this->getLanguageConfigName($this->language->id, $name)) { + $language_names[$name] = $language_name; + } + } } - return $this; + return $language_names; } /** - * Gets the cache key for a given config name in a particular context. + * Gets configuration name for the provided language. * + * The name will be the same name with a prefix depending on language code: + * language.config.LANGCODE.NAME + * + * @param string $langcode + * The language code. * @param string $name * The name of the configuration object. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context. * - * @return string - * The cache key. + * @return bool|string + * The configuration name for configuration object providing overrides. + * Returns false if the name already starts with the language config prefix. */ - public function getCacheKey($name, ContextInterface $context) { - return $name . ':' . $context->getUuid(); + public function getLanguageConfigName($langcode, $name) { + if (strpos($name, static::LANGUAGE_CONFIG_PREFIX) === 0) { + return FALSE; + } + return static::LANGUAGE_CONFIG_PREFIX . '.' . $langcode . '.' . $name; } /** - * Gets all the cache keys that match the provided config name. + * Determines if a particular configuration object can be overridden. + * + * Language override configuration should not be overridden. * * @param string $name * The name of the configuration object. * - * @return array - * An array of cache keys that match the provided config name. + * @return bool + * TRUE if the configuration object can be overridden. */ - public function getCacheKeys($name) { - $cache_keys = array_keys($this->cache); - return array_filter($cache_keys, function($key) use ($name) { - return ( strpos($key, $name) !== false ); - }); + protected function canOverride($name) { + return $this->useOverrides && !(strpos($name, static::LANGUAGE_CONFIG_PREFIX) === 0); } /** - * Clears the config factory static cache. + * Removes stale static cache entries when configuration is saved. * - * @return \Drupal\Core\Config\ConfigFactory - * The config factory object. + * @param ConfigEvent $event + * The configuration event. */ - public function clearStaticCache() { - $this->cache = array(); - return $this; + public function onConfigSave(ConfigEvent $event) { + // Clear out any other cache keys apart from the config object being saved. + $saved_config = $event->getConfig(); + foreach ($this->getCacheKeys($saved_config->getName()) as $cache_key) { + if ($this->cache[$cache_key] != $saved_config) { + unset($this->cache[$cache_key]); + } + } } + + /** + * {@inheritdoc} + */ + static function getSubscribedEvents() { + $events['config.save'][] = array('onConfigSave', 255); + return $events; + } + } diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php index dd5b9bb..0feabdf 100644 --- a/core/lib/Drupal/Core/Config/ConfigImporter.php +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php @@ -7,7 +7,6 @@ namespace Drupal\Core\Config; -use Drupal\Core\Config\Context\FreeConfigContext; use Drupal\Core\Config\TypedConfigManager; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Lock\LockBackendInterface; @@ -55,13 +54,6 @@ class ConfigImporter { protected $eventDispatcher; /** - * The configuration context. - * - * @var \Drupal\Core\Config\Context\ContextInterface - */ - protected $context; - - /** * The configuration factory. * * @var \Drupal\Core\Config\ConfigFactory @@ -138,10 +130,6 @@ public function __construct(StorageComparerInterface $storage_comparer, EventDis $this->uuidService = $uuid_service; $this->typedConfigManager = $typed_config; $this->processed = $this->storageComparer->getEmptyChangelist(); - // Use an override free context for importing so that overrides to do not - // pollute the imported data. The context is hard coded to ensure this is - // the case. - $this->context = new FreeConfigContext($this->eventDispatcher, $this->uuidService); } /** @@ -235,7 +223,6 @@ public function import() { // Ensure that the changes have been validated. $this->validate(); - $this->configFactory->enterContext($this->context); if (!$this->lock->acquire(static::ID)) { // Another process is synchronizing configuration. throw new ConfigImporterException(sprintf('%s is already importing', static::ID)); @@ -248,9 +235,6 @@ public function import() { // The import is now complete. $this->lock->release(static::ID); $this->reset(); - // Leave the context used during import and clear the ConfigFactory's - // static cache. - $this->configFactory->leaveContext()->reset(); } return $this; } @@ -278,7 +262,7 @@ public function validate() { protected function importConfig() { foreach (array('delete', 'create', 'update') as $op) { foreach ($this->getUnprocessed($op) as $name) { - $config = new Config($name, $this->storageComparer->getTargetStorage(), $this->context, $this->typedConfigManager); + $config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager); if ($op == 'delete') { $config->delete(); } @@ -311,11 +295,11 @@ protected function importInvokeOwner() { // 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, $this->storageComparer->getTargetStorage(), $this->context, $this->typedConfigManager); + $old_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager); $old_config->load(); $data = $this->storageComparer->getSourceStorage()->read($name); - $new_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->context, $this->typedConfigManager); + $new_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager); if ($data !== FALSE) { $new_config->setData($data); } diff --git a/core/lib/Drupal/Core/Config/ConfigModuleOverridesEvent.php b/core/lib/Drupal/Core/Config/ConfigModuleOverridesEvent.php new file mode 100644 index 0000000..26692ea --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigModuleOverridesEvent.php @@ -0,0 +1,109 @@ +names = $names; + $this->language = $language; + $this->overrides = array(); + } + + /** + * Gets configuration names. + * + * @return array + * The list of configuration names that can be overridden. + */ + public function getNames() { + return $this->names; + } + + /** + * Gets configuration language. + * + * @return \Drupal\Core\Language\Language + * The configuration language object. + */ + public function getLanguage() { + return $this->language; + } + + /** + * Get configuration overrides. + * + * @return array. + * The array of configuration overrides. + */ + public function getOverrides() { + return $this->overrides; + } + + /** + * Sets a configuration override for the given name. + * + * @param string $name + * The configuration object name to override. + * @param array $values + * The values in the configuration object to override. + * + * @return self + * The ConfigModuleOverridesEvent object. + */ + public function setOverride($name, array $values) { + if (in_array($name, $this->names)) { + if (isset($this->overrides[$name])) { + // Existing overrides take precedence since these will have been added + // by events with a higher priority. + $this->overrides[$name] = NestedArray::mergeDeepArray(array($values, $this->overrides[$name]), TRUE); + } + else { + $this->overrides[$name] = $values; + } + } + return $this; + } +} + diff --git a/core/lib/Drupal/Core/Config/Context/ConfigContext.php b/core/lib/Drupal/Core/Config/Context/ConfigContext.php deleted file mode 100644 index 128165b..0000000 --- a/core/lib/Drupal/Core/Config/Context/ConfigContext.php +++ /dev/null @@ -1,141 +0,0 @@ -eventDispatcher = $event_dispatcher; - $this->uuidService = $uuid; - } - - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::init(). - */ - public function init() { - // Reset existing overrides and get a UUID for this context. - $this->overrides = array(); - $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; - } - - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::setUuid(). - */ - public function setUuid() { - $this->uuid = $this->uuidService->generate(); - } - - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::getUuid(). - */ - public function getUuid() { - return $this->uuid; - } - - /** - * 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)); - } - - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::setOverride(). - */ - public function setOverrides($config_name, $data) { - if (!isset($this->overrides[$config_name])) { - $this->overrides[$config_name] = $data; - } - else { - $this->overrides[$config_name] = NestedArray::mergeDeepArray(array($this->overrides[$config_name], $data), TRUE); - } - } - - /** - * Implements \Drupal\Core\Config\Context\ContextInterface::getOverrides(). - */ - public function getOverrides($config_name) { - if (isset($this->overrides[$config_name])) { - return $this->overrides[$config_name]; - } - return FALSE; - } - -} diff --git a/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php b/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php deleted file mode 100644 index de3fd7b..0000000 --- a/core/lib/Drupal/Core/Config/Context/ConfigContextFactory.php +++ /dev/null @@ -1,74 +0,0 @@ -eventDispatcher = $event_dispatcher; - $this->uuidService = $uuid; - } - - /** - * Returns a configuration context object. - * - * @param string $class - * (Optional) The name of the configuration class to use. Defaults to - * Drupal\Core\Config\Context\ConfigContext - * - * @return \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, $this->uuidService); - } - else { - throw new 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 deleted file mode 100644 index e37d2d0..0000000 --- a/core/lib/Drupal/Core/Config/Context/ContextInterface.php +++ /dev/null @@ -1,101 +0,0 @@ -set(self::LANGUAGE_KEY, $language); - // Re-initialize since the language change changes the context - // fundamentally. - $this->init(); - return $this; - } - -} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index 5570aef..809f186 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -362,7 +362,7 @@ public function save(EntityInterface $entity) { // - Storage controller 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. - $this->configFactory->rename($prefix . $id, $prefix . $entity->id()); + $config = $this->configFactory->rename($prefix . $id, $prefix . $entity->id()); } // Build an ID if none is set. diff --git a/core/lib/Drupal/Core/Datetime/Date.php b/core/lib/Drupal/Core/Datetime/Date.php index 0510fa4..34b8632 100644 --- a/core/lib/Drupal/Core/Datetime/Date.php +++ b/core/lib/Drupal/Core/Datetime/Date.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Datetime; use Drupal\Component\Utility\Xss; +use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\Language; @@ -40,6 +41,13 @@ class Date { */ protected $languageManager; + /** + * The configuration factory. + * + * @var \Drupal\Core\Config\ConfigFactory + */ + protected $configFactory; + protected $country = NULL; protected $dateFormats = array(); @@ -72,10 +80,11 @@ class Date { * @param \Drupal\Core\StringTranslation\TranslationInterface $translation * The string translation. */ - public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager, TranslationInterface $translation) { + public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager, TranslationInterface $translation, ConfigFactory $config_factory) { $this->dateFormatStorage = $entity_manager->getStorageController('date_format'); $this->languageManager = $language_manager; $this->stringTranslation = $translation; + $this->configFactory = $config_factory; } /** @@ -205,11 +214,10 @@ protected function t($string, array $args = array(), array $options = array()) { protected function dateFormat($format, $langcode) { if (!isset($this->dateFormats[$format][$langcode])) { // Enter a language specific context so the right date format is loaded. - $language_context = config_context_enter('Drupal\Core\Config\Context\LanguageConfigContext'); - $language_context->setLanguage(new Language(array('id' => $langcode))); - + $original_language = $this->configFactory->getLanguage(); + $this->configFactory->setLanguage(new Language(array('id' => $langcode))); $this->dateFormats[$format][$langcode] = $this->dateFormatStorage->load($format); - config_context_leave(); + $this->configFactory->setLanguage($original_language); } return $this->dateFormats[$format][$langcode]; } diff --git a/core/lib/Drupal/Core/Form/ConfigFormBase.php b/core/lib/Drupal/Core/Form/ConfigFormBase.php index 5c69835..91a91d5 100644 --- a/core/lib/Drupal/Core/Form/ConfigFormBase.php +++ b/core/lib/Drupal/Core/Form/ConfigFormBase.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Form\FormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -29,12 +28,9 @@ * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context) { + public function __construct(ConfigFactory $config_factory) { $this->configFactory = $config_factory; - $this->configFactory->enterContext($context); } /** @@ -42,8 +38,7 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con */ public static function create(ContainerInterface $container) { return new static( - $container->get('config.factory'), - $container->get('config.context.free') + $container->get('config.factory') ); } @@ -73,13 +68,15 @@ public function submitForm(array &$form, array &$form_state) { /** * {@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) { - if (!$this->configFactory) { - $container = $this->container(); - $this->configFactory = $container->get('config.factory'); - $this->configFactory->enterContext($container->get('config.context.free')); - } - return $this->configFactory->get($name); + $this->configFactory->disableOverrides(); + $config = $this->configFactory->get($name); + $this->configFactory->enableOverrides(); + return $config; } } diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index e6526f2..a7dfbc0 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -236,7 +236,7 @@ protected function getLanguageTypes() { * @return \Drupal\Core\Language\Language * A language object. */ - protected function getLanguageDefault() { + public function getLanguageDefault() { $default_info = variable_get('language_default', array( 'id' => 'en', 'name' => 'English', diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php index 1c59201..5fc015b 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php @@ -9,7 +9,6 @@ use Drupal\aggregator\Plugin\AggregatorPluginManager; use Drupal\Component\Utility\String; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Plugin\PluginFormInterface; use Drupal\Core\StringTranslation\TranslationInterface; @@ -51,8 +50,6 @@ class SettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. * @param \Drupal\aggregator\Plugin\AggregatorPluginManager $fetcher_manager * The aggregator fetcher plugin manager. * @param \Drupal\aggregator\Plugin\AggregatorPluginManager $parser_manager @@ -62,8 +59,8 @@ class SettingsForm extends ConfigFormBase { * @param \Drupal\Core\StringTranslation\TranslationInterface $translation_manager * The string translation manager. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, AggregatorPluginManager $fetcher_manager, AggregatorPluginManager $parser_manager, AggregatorPluginManager $processor_manager, TranslationInterface $translation_manager) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, AggregatorPluginManager $fetcher_manager, AggregatorPluginManager $parser_manager, AggregatorPluginManager $processor_manager, TranslationInterface $translation_manager) { + parent::__construct($config_factory); $this->translationManager = $translation_manager; $this->managers = array( 'fetcher' => $fetcher_manager, @@ -84,7 +81,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('plugin.manager.aggregator.fetcher'), $container->get('plugin.manager.aggregator.parser'), $container->get('plugin.manager.aggregator.processor'), diff --git a/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php index 9c120c3..139a5ba 100644 --- a/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php +++ b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php @@ -67,7 +67,6 @@ public function setUp() { $this->settingsForm = new SettingsForm( $this->configFactory, - $this->getMock('Drupal\Core\Config\Context\ContextInterface'), $this->managers['fetcher'], $this->managers['parser'], $this->managers['processor'], diff --git a/core/modules/book/lib/Drupal/book/Tests/BookTest.php b/core/modules/book/lib/Drupal/book/Tests/BookTest.php index 93c5c78..21fc988 100644 --- a/core/modules/book/lib/Drupal/book/Tests/BookTest.php +++ b/core/modules/book/lib/Drupal/book/Tests/BookTest.php @@ -434,9 +434,9 @@ function testBookNodeTypeChange() { // 'page', // ); // @endcode - $current_config = \Drupal::config('book.settings')->init()->get(); + $current_config = \Drupal::config('book.settings')->get(); $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, \Drupal::config('book.settings')->init()->get()); + $this->assertIdentical($current_config, \Drupal::config('book.settings')->get()); // Change the name, machine name and description. $edit = array( @@ -455,9 +455,9 @@ function testBookNodeTypeChange() { // 'zebra', // ); // @endcode - $current_config = \Drupal::config('book.settings')->init()->get(); + $current_config = \Drupal::config('book.settings')->get(); $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, \Drupal::config('book.settings')->init()->get()); + $this->assertIdentical($current_config, \Drupal::config('book.settings')->get()); $edit = array( 'name' => 'Animal book', @@ -473,9 +473,9 @@ function testBookNodeTypeChange() { // 'zebra', // ); // @endcode - $current_config = \Drupal::config('book.settings')->init()->get(); + $current_config = \Drupal::config('book.settings')->get(); $this->drupalPostForm('admin/structure/book/settings', array(), t('Save configuration')); - $this->assertIdentical($current_config, \Drupal::config('book.settings')->init()->get()); + $this->assertIdentical($current_config, \Drupal::config('book.settings')->get()); // Ensure that after all the node type changes book.settings:child_type has // the expected value. diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php index a214b63..9095b7d 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php @@ -48,11 +48,6 @@ class ConfigExportImportUITest extends WebTestBase { */ protected $admin_role; - /** - * Sort methods alphabetically in order to allow for a predictable sequence. - */ - const SORT_METHODS = TRUE; - public static $modules = array('config'); public static function getInfo() { @@ -73,52 +68,31 @@ protected function setUp() { } /** - * Tests a simple site configuration export case: site slogan. + * Tests a simple site export import case. */ - function testExport() { - $this->siteUuid = \Drupal::config('system.site')->get('uuid'); - - // Create a role for second round. - $this->admin_role = $this->drupalCreateRole(array('synchronize configuration', 'import configuration')); - $this->slogan = $this->randomString(16); + public function testExportImport() { + $this->originalSlogan = \Drupal::config('system.site')->get('slogan'); + $this->newSlogan = $this->randomString(16); + $this->assertNotEqual($this->newSlogan, $this->originalSlogan); \Drupal::config('system.site') - ->set('slogan', $this->slogan) + ->set('slogan', $this->newSlogan) ->save(); + $this->assertEqual(\Drupal::config('system.site')->get('slogan'), $this->newSlogan); + $this->drupalPostForm('admin/config/development/configuration/full/export', array(), 'Export'); $this->tarball = $this->drupalGetContent(); - } - /** - * Tests importing the tarball to ensure changes made it over. - */ - function testImport() { - $filename = 'temporary://' . $this->randomName(); - file_put_contents($filename, $this->tarball); - $this->doImport($filename); - // Now that the role is imported, change the slogan and re-import with a non-root user. - $web_user = $this->drupalCreateUser(); - $web_user->addRole($this->admin_role); - $web_user->save(); - $this->drupalLogin($web_user); \Drupal::config('system.site') - ->set('slogan', $this->randomString(16)) + ->set('slogan', $this->originalSlogan) ->save(); - $this->doImport($filename); - } - - /** - * Import a tarball and assert the data is correct. - * - * @param string $filename - * The name of the tarball containing the configuration to be imported. - */ - protected function doImport($filename) { - // The site UUIDs must match for the import to work. - \Drupal::config('system.site')->set('uuid', $this->siteUuid)->save(); + $this->assertEqual(\Drupal::config('system.site')->get('slogan'), $this->originalSlogan); - $this->assertNotEqual($this->slogan, \Drupal::config('system.site')->get('slogan')); + $filename = 'temporary://' . $this->randomName(); + file_put_contents($filename, $this->tarball); $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload'); $this->drupalPostForm(NULL, array(), 'Import all'); - $this->assertEqual($this->slogan, \Drupal::config('system.site')->get('slogan')); + + $this->assertEqual(\Drupal::config('system.site')->get('slogan'), $this->newSlogan); } } + diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php index 6af6295..de7fc7f 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php @@ -62,7 +62,8 @@ function setUp() { $this->container->get('entity.manager'), $this->container->get('lock'), $this->container->get('uuid'), - $this->container->get('config.typed') + $this->container->get('config.typed'), + $this->container->get('module_handler') ); $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging')); } @@ -229,6 +230,7 @@ function testUpdated() { $this->configImporter->reset()->import(); // Verify the values were updated. + \Drupal::configFactory()->reset($name); $config = \Drupal::config($name); $this->assertIdentical($config->get('foo'), 'beer'); $config = \Drupal::config($dynamic_name); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php index 1062ea5..992c1bd 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallTest.php @@ -47,6 +47,8 @@ function testModuleInstallation() { $this->installConfig(array('config_test')); // Verify that default module config exists. + \Drupal::configFactory()->reset($default_config); + \Drupal::configFactory()->reset($default_configuration_entity); $config = \Drupal::config($default_config); $this->assertIdentical($config->isNew(), FALSE); $config = \Drupal::config($default_configuration_entity); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php index 3bb7839..0fd3f5e 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php @@ -49,6 +49,8 @@ function testIntegrationModuleReinstallation() { \Drupal::moduleHandler()->install(array('config_integration_test')); // Verify that default module config exists. + \Drupal::configFactory()->reset($default_config); + \Drupal::configFactory()->reset($default_configuration_entity); $config_static = \Drupal::config($default_config); $this->assertIdentical($config_static->isNew(), FALSE); $this->assertIdentical($config_static->get('foo'), 'default setting'); @@ -82,6 +84,8 @@ function testIntegrationModuleReinstallation() { \Drupal::moduleHandler()->install(array('config_integration_test')); // Verify the integration module's config was re-installed. + \Drupal::configFactory()->reset($default_config); + \Drupal::configFactory()->reset($default_configuration_entity); $config_static = \Drupal::config($default_config); $this->assertIdentical($config_static->isNew(), FALSE); $this->assertIdentical($config_static->get('foo'), 'default setting'); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php new file mode 100644 index 0000000..e0cec21 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php @@ -0,0 +1,84 @@ + 'Language override', + 'description' => 'Confirm that language overrides work', + 'group' => 'Configuration', + ); + } + + public function setUp() { + parent::setUp(); + config_install_default_config('module', 'config_test'); + config_install_default_config('module', 'locale'); + \Drupal::configFactory()->setLanguage(language_default()); + } + + /** + * Tests locale override based on language. + */ + function testConfigLanguageOverride() { + $config = \Drupal::config('config_test.system'); + $this->assertIdentical($config->get('foo'), 'en bar'); + + language_save(new Language(array( + 'name' => 'French', + 'id' => 'fr', + ))); + language_save(new Language(array( + 'name' => 'German', + 'id' => 'de', + ))); + + \Drupal::configFactory()->setLanguage(language_load('fr')); + $config = \Drupal::config('config_test.system'); + $this->assertIdentical($config->get('foo'), 'fr bar'); + + \Drupal::configFactory()->setLanguage(language_load('de')); + $config = \Drupal::config('config_test.system'); + $this->assertIdentical($config->get('foo'), 'de bar'); + + // Test overrides of completely new configuration objects. In normal runtime + // this should only happen for configuration entities as we should not be + // creating simple configuration objects on the fly. + $language_config_name = \Drupal::configFactory()->getLanguageConfigName('de', 'config_test.new'); + \Drupal::config($language_config_name)->set('language', 'override')->save(); + \Drupal::config('config_test.new'); + $config = \Drupal::config('config_test.new'); + $this->assertTrue($config->isNew(), 'The configuration object config_test.new is new'); + $this->assertIdentical($config->get('language'), 'override'); + \Drupal::configFactory()->disableOverrides(); + $config = \Drupal::config('config_test.new'); + $this->assertIdentical($config->get('language'), NULL); + \Drupal::configFactory()->enableOverrides(); + + // Ensure that language configuration overrides can not be overridden. + global $conf; + $conf[$language_config_name]['language'] = 'conf cannot override'; + $this->assertIdentical(\Drupal::config($language_config_name)->get('language'), 'override'); + } +} + diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverrideWebTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php similarity index 77% rename from core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverrideWebTest.php rename to core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php index f98a1e0..d8412b4 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverrideWebTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\config\Tests\ConfigLocaleOverrideWebTest. + * Contains \Drupal\config\Tests\ConfigLanguageOverrideWebTest. */ namespace Drupal\config\Tests; @@ -12,14 +12,14 @@ /** * Tests language overrides in configuration through the request. */ -class ConfigLocaleOverrideWebTest extends WebTestBase { +class ConfigLanguageOverrideWebTest extends WebTestBase { - public static $modules = array('locale', 'language', 'system'); + public static $modules = array('language', 'system'); public static function getInfo() { return array( - 'name' => 'Locale overrides through the request', - 'description' => 'Tests locale overrides applied through the website.', + 'name' => 'Language overrides through the request', + 'description' => 'Tests language overrides applied through the website.', 'group' => 'Configuration', ); } @@ -47,7 +47,8 @@ function testSiteNameTranslation() { $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); // Save an override for the XX language. - \Drupal::config('locale.config.xx.system.site')->set('name', 'XX site name')->save(); + $config_name = \Drupal::configFactory()->getLanguageConfigName('xx', 'system.site'); + \Drupal::config($config_name)->set('name', 'XX site name')->save(); $this->drupalLogout(); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php deleted file mode 100644 index 24edb76..0000000 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php +++ /dev/null @@ -1,297 +0,0 @@ - 'Locale override', - 'description' => 'Confirm that locale overrides work', - 'group' => 'Configuration', - ); - } - - public function setUp() { - parent::setUp(); - config_install_default_config('module', 'config_test'); - config_install_default_config('module', 'locale'); - } - - /** - * Tests basic locale override. - */ - function testConfigLocaleOverride() { - $name = 'config_test.system'; - // The default language is en so the config key should be localised. - $config = \Drupal::config($name); - $this->assertIdentical($config->get('foo'), 'en bar'); - $this->assertIdentical($config->get('404'), 'herp'); - - // Ensure that we get the expected value when we avoid overrides. - config_context_enter('config.context.free'); - $config_admin = \Drupal::config($name); - $this->assertIdentical($config_admin->get('foo'), 'bar'); - $this->assertIdentical($config_admin->get('404'), 'herp'); - - // Leave the non override context. - config_context_leave(); - $config = \Drupal::config($name); - $this->assertIdentical($config->get('foo'), 'en bar'); - $this->assertIdentical($config->get('404'), 'herp'); - } - - /** - * Tests locale override based on user's preferred language. - */ - function testConfigLocaleUserOverride() { - $this->installSchema('system', 'variable'); - $this->installConfig(array('language')); - language_save(new Language(array( - 'name' => 'French', - 'id' => 'fr', - ))); - language_save(new Language(array( - 'name' => 'English', - 'id' => 'en', - ))); - language_save(new Language(array( - 'name' => 'German', - 'id' => 'de', - ))); - - $this->installSchema('user', 'users'); - $account = entity_create('user', array( - 'name' => 'French user', - 'mail' => 'test@example.com', - 'created' => REQUEST_TIME, - 'status' => 1, - 'preferred_langcode' => 'fr', - )); - - $user_config_context = config_context_enter('Drupal\user\UserConfigContext'); - $user_config_context->setAccount($account); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'fr bar'); - // Ensure the non-overriden value is still the same. - $this->assertIdentical($config->get('404'), 'herp'); - - // Ensure that we get the expected value when we leave the user context. 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 = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - $account = entity_create('user', array( - 'name' => 'German user', - 'mail' => 'test@example.com', - 'created' => REQUEST_TIME, - 'status' => 1, - 'preferred_langcode' => 'de', - )); - - $config_factory = \Drupal::service('config.factory'); - $config_factory->enterContext($user_config_context->setAccount($account)); - // Should not have to re-initialize the configuration object to get new - // overrides as the new context will have a different uuid. - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'de bar'); - - // Enter an english context on top of the german context. - $account = entity_create('user', array( - 'name' => 'English user', - 'mail' => 'test@example.com', - 'created' => REQUEST_TIME, - 'status' => 1, - '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->setAccount($account); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - // Ensure that we get the expected value when we leave the english user - // context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'de bar'); - - // Ensure that we get the expected value when we leave the german user - // context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - // Ensure that we cannot leave the default context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - } - - /** - * Tests locale override based on language. - */ - function testConfigLocaleLanguageOverride() { - $this->installSchema('system', 'variable'); - $this->installConfig(array('language')); - language_save(new Language(array( - 'name' => 'French', - 'id' => 'fr', - ))); - language_save(new Language(array( - 'name' => 'English', - 'id' => 'en', - ))); - language_save(new Language(array( - 'name' => 'German', - 'id' => 'de', - ))); - - $language = language_load('fr'); - $language_config_context = config_context_enter('Drupal\Core\Config\Context\LanguageConfigContext'); - $language_config_context->setLanguage($language); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'fr bar'); - // Ensure the non-overridden value is still the same. - $this->assertIdentical($config->get('404'), 'herp'); - - // Ensure that we get the expected value when we leave the language context. The - // locale overrides contain an English override too, so although we are not - // in a language override context, the English language override - // applies due to the negotiated language for the page. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - $config_factory = \Drupal::service('config.factory'); - $language = language_load('de'); - $config_factory->enterContext($language_config_context->setLanguage($language)); - // Should not have to re-initialize the configuration object to get new - // overrides as the new context will have a different uuid. - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'de bar'); - - // Enter an english context on top of the german context. - $language = language_load('en'); - // Create a new language config context to stack on top of the existing one. - $en_language_config_context = config_context_enter('Drupal\Core\Config\Context\LanguageConfigContext'); - $en_language_config_context->setLanguage($language); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - // Ensure that we get the expected value when we leave the english - // language context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'de bar'); - - // Ensure that we get the expected value when we leave the german - // language context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - - // Ensure that we cannot leave the default context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - } - - /** - * Tests locale override in combination with global overrides. - */ - function testConfigLocaleUserAndGlobalOverride() { - global $conf; - - // Globally override value for the keys in config_test.system. Although we - // override the foo key, there are also language overrides, which trump - // global overrides so the 'foo' key override will never surface. - $conf['config_test.system']['foo'] = 'global bar'; - $conf['config_test.system']['404'] = 'global herp'; - - $this->installSchema('system', 'variable'); - $this->installConfig(array('language')); - language_save(new Language(array( - 'name' => 'French', - 'id' => 'fr', - ))); - - $this->installSchema('user', 'users'); - $account = entity_create('user', array( - 'name' => 'French user', - 'mail' => 'test@example.com', - 'created' => REQUEST_TIME, - 'status' => 1, - 'preferred_langcode' => 'fr', - )); - - $user_config_context = config_context_enter('Drupal\user\UserConfigContext'); - $user_config_context->setAccount($account); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'fr bar'); - // Ensure the value overriden from global $conf works. - $this->assertIdentical($config->get('404'), 'global herp'); - - // Ensure that we get the expected value when we leave the user context. 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 = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - // Global override should still apply. - $this->assertIdentical($config->get('404'), 'global herp'); - - // Ensure that we cannot leave the default context. - config_context_leave(); - $config = \Drupal::config('config_test.system'); - $this->assertIdentical($config->get('foo'), 'en bar'); - // Global override should still apply. - $this->assertIdentical($config->get('404'), 'global herp'); - - // Ensure that we get the expected value when we avoid overrides. - config_context_enter('config.context.free'); - $config_admin = \Drupal::config('config_test.system'); - // Language override should not apply anymore. - $this->assertIdentical($config_admin->get('foo'), 'bar'); - // Global override should not apply. - $this->assertIdentical($config_admin->get('404'), 'herp'); - config_context_leave(); - } - - /** - * Tests config_context_enter() invalid context name handling. - */ - function testInvalidContextName() { - $message = 'Expected ConfigException was thrown for an invalid context_name argument.'; - try { - config_context_enter('invalid.config.context'); - $this->fail($message); - } - catch (ConfigException $e) { - $this->pass($message); - } - } -} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigModuleOverridesTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigModuleOverridesTest.php new file mode 100644 index 0000000..0d45693 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigModuleOverridesTest.php @@ -0,0 +1,62 @@ + 'Module overrides', + 'description' => 'Tests that modules can override configuration with event subscribers.', + 'group' => 'Configuration', + ); + } + + public function testSimpleModuleOverrides() { + $GLOBALS['config_test_run_module_overrides'] = TRUE; + $name = 'system.site'; + $overridden_name = 'ZOMG overridden site name'; + $non_overridden_name = 'ZOMG this name is on disk mkay'; + $overridden_slogan = 'Yay for overrides!'; + $non_overridden_slogan = 'Yay for defaults!'; + $config_factory = $this->container->get('config.factory'); + $config_factory + ->get($name) + ->set('name', $non_overridden_name) + ->set('slogan', $non_overridden_slogan) + ->save(); + + $config_factory->disableOverrides(); + $this->assertEqual($non_overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($non_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + + $config_factory->enableOverrides(); + $this->assertEqual($overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($overridden_slogan, $config_factory->get('system.site')->get('slogan')); + + // Test overrides of completely new configuration objects. In normal runtime + // this should only happen for configuration entities as we should not be + // creating simple configuration objects on the fly. + $config = \Drupal::config('config_override.new'); + $this->assertTrue($config->isNew(), 'The configuration object config_override.new is new'); + $this->assertIdentical($config->get('module'), 'override'); + \Drupal::configFactory()->disableOverrides(); + $config = \Drupal::config('config_override.new'); + $this->assertIdentical($config->get('module'), NULL); + \Drupal::configFactory()->enableOverrides(); + + unset($GLOBALS['config_test_run_module_overrides']); + } +} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php index a6016c3..9353b02 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php @@ -61,14 +61,6 @@ function testConfOverride() { $this->assertFalse(isset($data['baz'])); $this->assertIdentical($data['404'], $expected_original_data['404']); - // Enter an override-free context to ensure the original data remains. - config_context_enter('config.context.free'); - $config = \Drupal::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(); - // Get the configuration object in an overriden context (the one set by // default). $config = \Drupal::config('config_test.system'); @@ -100,14 +92,6 @@ function testConfOverride() { $this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']); $this->assertIdentical($config->get('404'), $conf['config_test.system']['404']); - // Enter an override-free context to ensure the original data remains saved. - config_context_enter('config.context.free'); - $config = \Drupal::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(); - // Write file to staging. $staging = $this->container->get('config.storage.staging'); $expected_new_data = array( @@ -131,6 +115,18 @@ function testConfOverride() { $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']); + + // Test overrides of completely new configuration objects. In normal runtime + // this should only happen for configuration entities as we should not be + // creating simple configuration objects on the fly. + $conf['config_test.new']['key'] = 'override'; + $config = \Drupal::config('config_test.new'); + $this->assertTrue($config->isNew(), 'The configuration object config_test.new is new'); + $this->assertIdentical($config->get('key'), 'override'); + \Drupal::configFactory()->disableOverrides(); + $config = \Drupal::config('config_test.new'); + $this->assertIdentical($config->get('key'), NULL); + \Drupal::configFactory()->enableOverrides(); } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php new file mode 100644 index 0000000..7657376 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php @@ -0,0 +1,103 @@ + 'Override priority', + 'description' => 'Tests that language, module and settings.php are applied in the correct order.', + 'group' => 'Configuration', + ); + } + + public function testOverridePriorities() { + global $conf; + $GLOBALS['config_test_run_module_overrides'] = FALSE; + + $non_overridden_mail = 'site@example.com'; + $language_overridden_mail = 'french@example.com'; + + $language_overridden_name = 'French site name'; + $module_overridden_name = 'ZOMG overridden site name'; + $non_overridden_name = 'ZOMG this name is on disk mkay'; + + $module_overridden_slogan = 'Yay for overrides!'; + $non_overridden_slogan = 'Yay for defaults!'; + + /** @var \Drupal\Core\Config\ConfigFactory $config_factory */ + $config_factory = $this->container->get('config.factory'); + $config_factory + ->get('system.site') + ->set('name', $non_overridden_name) + ->set('slogan', $non_overridden_slogan) + ->set('mail', $non_overridden_mail) + ->set('weight_select_max', 50) + ->save(); + + // Ensure that no overrides are applying. + $this->assertEqual($non_overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($non_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + $this->assertEqual($non_overridden_mail, $config_factory->get('system.site')->get('mail')); + $this->assertEqual(50, $config_factory->get('system.site')->get('weight_select_max')); + + // Override using language. + $language = new Language(array( + 'name' => 'French', + 'id' => 'fr', + )); + $config_factory->setLanguage($language); + $language_config_name = $config_factory->getLanguageConfigName($language->id, 'system.site'); + $config_factory + ->get($language_config_name) + ->set('name', $language_overridden_name) + ->set('mail', $language_overridden_mail) + ->save(); + + $this->assertEqual($language_overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($non_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + $this->assertEqual($language_overridden_mail, $config_factory->get('system.site')->get('mail')); + $this->assertEqual(50, $config_factory->get('system.site')->get('weight_select_max')); + + // Enable module overrides. Do not override system.site:mail to prove that + // the language override still applies. + $GLOBALS['config_test_run_module_overrides'] = TRUE; + $config_factory->reset('system.site'); + $this->assertEqual($module_overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($module_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + $this->assertEqual($language_overridden_mail, $config_factory->get('system.site')->get('mail')); + $this->assertEqual(50, $config_factory->get('system.site')->get('weight_select_max')); + + // Configure a global override to simulate overriding using settings.php. Do + // not override system.site:mail or system.site:slogan to prove that the + // language and module overrides still apply. + $conf['system.site']['name'] = 'Site name global conf override'; + $config_factory->reset('system.site'); + $this->assertEqual('Site name global conf override', $config_factory->get('system.site')->get('name')); + $this->assertEqual($module_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + $this->assertEqual($language_overridden_mail, $config_factory->get('system.site')->get('mail')); + $this->assertEqual(50, $config_factory->get('system.site')->get('weight_select_max')); + + $config_factory->disableOverrides(); + $this->assertEqual($non_overridden_name, $config_factory->get('system.site')->get('name')); + $this->assertEqual($non_overridden_slogan, $config_factory->get('system.site')->get('slogan')); + $this->assertEqual($non_overridden_mail, $config_factory->get('system.site')->get('mail')); + $this->assertEqual(50, $config_factory->get('system.site')->get('weight_select_max')); + + unset($GLOBALS['config_test_run_module_overrides']); + } +} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php index d9504b2..34743d5 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php @@ -79,6 +79,7 @@ function testSnapshot() { $this->configImporter()->import(); // Verify changed config was properly imported. + \Drupal::configFactory()->reset($config_name); $this->assertIdentical(\Drupal::config($config_name)->get($config_key), $new_data); // Verify that a new snapshot was created which and that it matches diff --git a/core/modules/config/tests/config_override/config_override.info.yml b/core/modules/config/tests/config_override/config_override.info.yml new file mode 100644 index 0000000..1ccb50b --- /dev/null +++ b/core/modules/config/tests/config_override/config_override.info.yml @@ -0,0 +1,6 @@ +name: 'Configuration override test' +type: module +package: Testing +version: VERSION +core: 8.x +hidden: true diff --git a/core/modules/config/tests/config_override/config_override.module b/core/modules/config/tests/config_override/config_override.module new file mode 100644 index 0000000..0261055 --- /dev/null +++ b/core/modules/config/tests/config_override/config_override.module @@ -0,0 +1,6 @@ +getNames(); + if (in_array('system.site', $names)) { + $event->setOverride('system.site', array( + 'name' => 'Should not apply because of higher priority listener', + // This override should apply because it is not overridden by the + // higher priority listener. + 'slogan' => 'Yay for overrides!', + )); + } + } + } + + /** + * Registers the methods in this class that should be listeners. + * + * @return array + * An array of event listener definitions. + */ + static function getSubscribedEvents() { + $events['config.module.overrides'][] = array('onConfigModuleOverride', 35); + return $events; + } +} + diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleOverrideSubscriber.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleOverrideSubscriber.php new file mode 100644 index 0000000..54f0f64 --- /dev/null +++ b/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleOverrideSubscriber.php @@ -0,0 +1,41 @@ +getNames(); + if (in_array('system.site', $names)) { + $event->setOverride('system.site', array('name' => 'ZOMG overridden site name')); + } + if (in_array('config_override.new', $names)) { + $event->setOverride('config_override.new', array('module' => 'override')); + } + } + } + + /** + * Registers the methods in this class that should be listeners. + * + * @return array + * An array of event listener definitions. + */ + static function getSubscribedEvents() { + $events['config.module.overrides'][] = array('onConfigModuleOverride', 40); + return $events; + } +} + diff --git a/core/modules/config/tests/config_test/config/locale.config.de.config_test.system.yml b/core/modules/config/tests/config_test/config/language.config.de.config_test.system.yml similarity index 100% rename from core/modules/config/tests/config_test/config/locale.config.de.config_test.system.yml rename to core/modules/config/tests/config_test/config/language.config.de.config_test.system.yml diff --git a/core/modules/config/tests/config_test/config/locale.config.en.config_test.system.yml b/core/modules/config/tests/config_test/config/language.config.en.config_test.system.yml similarity index 100% rename from core/modules/config/tests/config_test/config/locale.config.en.config_test.system.yml rename to core/modules/config/tests/config_test/config/language.config.en.config_test.system.yml 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/language.config.fr.config_test.system.yml similarity index 100% rename from core/modules/config/tests/config_test/config/locale.config.fr.config_test.system.yml rename to core/modules/config/tests/config_test/config/language.config.fr.config_test.system.yml diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationDeleteForm.php b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationDeleteForm.php index 01304ae..3950667 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationDeleteForm.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationDeleteForm.php @@ -10,6 +10,7 @@ use Drupal\config_translation\ConfigMapperManagerInterface; use Drupal\Core\Cache\Cache; use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfirmFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -65,11 +66,14 @@ class ConfigTranslationDeleteForm extends ConfirmFormBase { * The configuration mapper manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The configuration factory. */ - public function __construct(StorageInterface $config_storage, ConfigMapperManagerInterface $config_mapper_manager, ModuleHandlerInterface $module_handler) { + public function __construct(StorageInterface $config_storage, ConfigMapperManagerInterface $config_mapper_manager, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) { $this->configStorage = $config_storage; $this->configMapperManager = $config_mapper_manager; $this->moduleHandler = $module_handler; + $this->configFactory = $config_factory; } /** @@ -79,7 +83,8 @@ public static function create(ContainerInterface $container) { return new static( $container->get('config.storage'), $container->get('plugin.manager.config_translation.mapper'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('config.factory') ); } @@ -137,7 +142,8 @@ public function buildForm(array $form, array &$form_state, Request $request = NU */ public function submitForm(array &$form, array &$form_state) { foreach ($this->mapper->getConfigNames() as $name) { - $this->configStorage->delete('locale.config.' . $this->language->id . '.' . $name); + $config_name = $this->configFactory->getLanguageConfigName($this->language->id, $name); + $this->configStorage->delete($config_name); } // Flush all persistent caches. diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php index e559ea1..9295b81 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php @@ -9,6 +9,7 @@ use Drupal\config_translation\ConfigMapperManagerInterface; use Drupal\Core\Config\Config; +use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Config\Schema\Element; use Drupal\Core\Config\TypedConfigManager; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -92,12 +93,15 @@ * The translation storage object. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook. + * @param \Drupal\Core\Config\ConfigFactory + * The config factory. */ - public function __construct(TypedConfigManager $typed_config_manager, ConfigMapperManagerInterface $config_mapper_manager, StringStorageInterface $locale_storage, ModuleHandlerInterface $module_handler) { + public function __construct(TypedConfigManager $typed_config_manager, ConfigMapperManagerInterface $config_mapper_manager, StringStorageInterface $locale_storage, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) { $this->typedConfigManager = $typed_config_manager; $this->configMapperManager = $config_mapper_manager; $this->localeStorage = $locale_storage; $this->moduleHandler = $module_handler; + $this->configFactory = $config_factory; } /** @@ -108,7 +112,8 @@ public static function create(ContainerInterface $container) { $container->get('config.typed'), $container->get('plugin.manager.config_translation.mapper'), $container->get('locale.storage'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('config.factory') ); } @@ -158,20 +163,16 @@ public function buildForm(array $form, array &$form_state, Request $request = NU $this->language = $language; $this->sourceLanguage = $this->mapper->getLanguageWithFallback(); - // Make sure we are in the override free configuration context. For example, - // visiting the configuration page in another language would make those - // language overrides active by default. But we need the original values. - config_context_enter('config.context.free'); // Get base language configuration to display in the form before entering // into the language context for the form. This avoids repetitively going // in and out of the language context to get original values later. + $this->configFactory->disableOverrides(); $this->baseConfigData = $this->mapper->getConfigData(); - // Leave override free context. - config_context_leave(); + $this->configFactory->enableOverrides(); - // Enter context for the translation target language requested and generate - // form with translation data in that language. - config_context_enter('Drupal\Core\Config\Context\LanguageConfigContext')->setLanguage($this->language); + // Set the translation target language on the configuration factory. + $original_language = $this->configFactory->getLanguage(); + $this->configFactory->setLanguage($this->language); // Add some information to the form state for easier form altering. $form_state['config_translation_mapper'] = $this->mapper; @@ -196,9 +197,8 @@ public function buildForm(array $form, array &$form_state, Request $request = NU '#button_type' => 'primary', ); - // Leave the language context so that configuration accessed later in the - // request is displayed in the correct language. - config_context_leave(); + // Set the configuration language back. + $this->configFactory->setLanguage($original_language); return $form; } @@ -209,13 +209,13 @@ public function buildForm(array $form, array &$form_state, Request $request = NU public function submitForm(array &$form, array &$form_state) { $form_values = $form_state['values']['config_names']; - // For the form submission handling, use the override free context. - config_context_enter('config.context.free'); - + // For the form submission handling, use the raw data. + $this->configFactory->disableOverrides(); foreach ($this->mapper->getConfigNames() as $name) { // Set configuration values based on form submission and source values. $base_config = $this->config($name); - $translation_config = $this->config('locale.config.' . $this->language->id . '.' . $name); + $translation_config_name = $this->configFactory->getLanguageConfigName($this->language->id, $name); + $translation_config = $this->config($translation_config_name); $locations = $this->localeStorage->getLocations(array('type' => 'configuration', 'name' => $name)); $this->setConfig($this->language, $base_config, $translation_config, $form_values[$name], !empty($locations)); @@ -229,8 +229,7 @@ public function submitForm(array &$form, array &$form_state) { $translation_config->save(); } } - - config_context_leave(); + $this->configFactory->enableOverrides(); $form_state['redirect_route'] = array( 'route_name' => $this->mapper->getOverviewRoute(), diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php index 83f4a14..c6e4094 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Tests/ConfigTranslationUiTest.php @@ -178,7 +178,8 @@ public function testSourceValueDuplicateSave() { // Read overridden file from active config. $file_storage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]); - $config_parsed = $file_storage->read('locale.config.fr.system.site'); + $language_config_name = \Drupal::configFactory()->getLanguageConfigName('fr', 'system.site'); + $config_parsed = $file_storage->read($language_config_name); // Expect both name and slogan in language specific file. $expected = array( @@ -199,7 +200,7 @@ public function testSourceValueDuplicateSave() { ); $this->drupalPostForm(NULL, $edit, t('Save translation')); $this->assertRaw(t('Successfully updated @language translation.', array('@language' => 'French'))); - $config_parsed = $file_storage->read('locale.config.fr.system.site'); + $config_parsed = $file_storage->read($language_config_name); // Expect only slogan in language specific file. $expected = array('slogan' => 'FR ' . $site_slogan); @@ -213,7 +214,7 @@ public function testSourceValueDuplicateSave() { 'config_names[system.site][slogan][translation]' => $site_slogan, ); $this->drupalPostForm(NULL, $edit, t('Save translation')); - $config_parsed = $file_storage->read('locale.config.fr.system.site'); + $config_parsed = $file_storage->read($language_config_name); // Expect no language specific file. $this->assertFalse($config_parsed); @@ -284,7 +285,8 @@ public function testContactConfigEntityTranslation() { $this->drupalPostForm($translation_page_url, $edit, t('Save translation')); // Expect translated values in language specific file. - $config_parsed = $file_storage->read('locale.config.'. $langcode . '.contact.category.feedback'); + $language_config_name = \Drupal::configFactory()->getLanguageConfigName($langcode, 'contact.category.feedback'); + $config_parsed = $file_storage->read($language_config_name); $expected = array( 'label' => 'Website feedback - ' . $langcode, 'reply' => 'Thank you for your mail - ' . $langcode, @@ -347,7 +349,8 @@ public function testContactConfigEntityTranslation() { $this->assertNoLinkByHref("$translation_base_url/$langcode/delete"); // Expect no language specific file present anymore. - $config_parsed = $file_storage->read('locale.config.'. $langcode . '.config.category.feedback'); + $language_config_name = \Drupal::configFactory()->getLanguageConfigName($langcode, 'contact.category.feedback'); + $config_parsed = $file_storage->read($language_config_name); $this->assertFalse($config_parsed); } @@ -414,7 +417,8 @@ public function testDateFormatTranslation() { $this->drupalPostForm($translation_page_url, $edit, t('Save translation')); // Get translation and check we've got the right value. - $config_parsed = $file_storage->read('locale.config.fr.system.date_format.' . $id); + $language_config_name = \Drupal::configFactory()->getLanguageConfigName('fr', 'system.date_format.' . $id); + $config_parsed = $file_storage->read($language_config_name); $expected = array( 'label' => $id . ' - FR', 'pattern' => array('php' => 'D'), diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml index d6599b3..05b4798 100644 --- a/core/modules/language/language.services.yml +++ b/core/modules/language/language.services.yml @@ -5,3 +5,8 @@ services: tags: - { name: path_processor_inbound, priority: 300 } - { name: path_processor_outbound, priority: 100 } + language_config_subscriber: + class: Drupal\language\LanguageConfigSubscriber + tags: + - { name: event_subscriber } + arguments: ['@language_manager', '@config.factory'] diff --git a/core/modules/language/lib/Drupal/language/Form/ContentLanguageSettingsForm.php b/core/modules/language/lib/Drupal/language/Form/ContentLanguageSettingsForm.php index 6cd8514..7162eea 100644 --- a/core/modules/language/lib/Drupal/language/Form/ContentLanguageSettingsForm.php +++ b/core/modules/language/lib/Drupal/language/Form/ContentLanguageSettingsForm.php @@ -8,7 +8,6 @@ namespace Drupal\language\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class ContentLanguageSettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, EntityManagerInterface $entity_manager) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, EntityManagerInterface $entity_manager) { + parent::__construct($config_factory); $this->entityManager = $entity_manager; } @@ -47,7 +44,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('entity.manager') ); } diff --git a/core/modules/language/lib/Drupal/language/Form/NegotiationBrowserForm.php b/core/modules/language/lib/Drupal/language/Form/NegotiationBrowserForm.php index 2271b14..0537a6a 100644 --- a/core/modules/language/lib/Drupal/language/Form/NegotiationBrowserForm.php +++ b/core/modules/language/lib/Drupal/language/Form/NegotiationBrowserForm.php @@ -8,7 +8,6 @@ namespace Drupal\language\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -31,8 +30,8 @@ class NegotiationBrowserForm extends ConfigFormBase { * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, ModuleHandlerInterface $module_handler) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, ModuleHandlerInterface $module_handler) { + parent::__construct($config_factory); $this->moduleHandler = $module_handler; } @@ -42,7 +41,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('module_handler') ); } @@ -196,5 +194,5 @@ protected function language_get_browser_drupal_langcode_mappings() { } return $config->get(); } - } + diff --git a/core/modules/language/lib/Drupal/language/LanguageConfigSubscriber.php b/core/modules/language/lib/Drupal/language/LanguageConfigSubscriber.php new file mode 100644 index 0000000..702b857 --- /dev/null +++ b/core/modules/language/lib/Drupal/language/LanguageConfigSubscriber.php @@ -0,0 +1,68 @@ +languageManager = $language_manager; + $this->configFactory = $config_factory; + } + + /** + * Sets the negotiated interface language on the configuration factory. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event + * Kernel event to respond to. + */ + public function onKernelRequestSetDefaultConfigLanguage(GetResponseEvent $event) { + if ($this->languageManager->isMultiLingual()) { + $this->configFactory->setLanguage($this->languageManager->getLanguage()); + } + } + + /** + * Implements EventSubscriberInterface::getSubscribedEvents(). + */ + static function getSubscribedEvents() { + $events[KernelEvents::REQUEST][] = array('onKernelRequestSetDefaultConfigLanguage', 48); + return $events; + } +} + diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php index 9284444..bd06d76 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php @@ -11,6 +11,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\Config\TypedConfigManager; use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Config\ConfigFactory; /** * Manages localized configuration type plugins. @@ -37,6 +38,13 @@ class LocaleConfigManager extends TypedConfigManager { protected $translations; /** + * The configuration factory. + * + * @var \Drupal\Core\Config\ConfigFactory + */ + protected $configFactory; + + /** * Creates a new typed configuration manager. * * @param \Drupal\Core\Config\StorageInterface $configStorage @@ -50,12 +58,15 @@ class LocaleConfigManager extends TypedConfigManager { * The locale storage to use for reading string translations. * @param \Drupal\Core\Cache\CacheBackendInterface $cache * The cache backend to use for caching the definitions. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The configuration factory */ - public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, StorageInterface $installStorage, StringStorageInterface $localeStorage, CacheBackendInterface $cache) { + public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, StorageInterface $installStorage, StringStorageInterface $localeStorage, CacheBackendInterface $cache, ConfigFactory $config_factory) { // Note we use the install storage for the parent constructor. parent::__construct($configStorage, $schemaStorage, $cache); $this->installStorage = $installStorage; $this->localeStorage = $localeStorage; + $this->configFactory = $config_factory; } /** @@ -122,7 +133,7 @@ protected function compareConfigData(array $default, $updated) { * Configuration data to be saved, that will be only the translated values. */ public function saveTranslationData($name, $langcode, array $data) { - $locale_name = self::localeConfigName($langcode, $name); + $locale_name = $this->configFactory->getLanguageConfigName($langcode, $name); $this->configStorage->write($locale_name, $data); } @@ -135,7 +146,7 @@ public function saveTranslationData($name, $langcode, array $data) { * Language code. */ public function deleteTranslationData($name, $langcode) { - $locale_name = self::localeConfigName($langcode, $name); + $locale_name = $this->configFactory->getLanguageConfigName($langcode, $name); $this->configStorage->delete($locale_name); } @@ -209,7 +220,7 @@ public function getStringNames(array $lids) { * Language code to delete. */ public function deleteLanguageTranslations($langcode) { - $locale_name = self::localeConfigName($langcode); + $locale_name = ConfigFactory::LANGUAGE_CONFIG_PREFIX . '.' . $langcode . '.'; foreach ($this->configStorage->listAll($locale_name) as $name) { $this->configStorage->delete($name); } @@ -294,24 +305,9 @@ public function translateString($name, $langcode, $source, $context) { * A boolean indicating if a language has configuration translations. */ public function hasTranslation($name, Language $language) { - $locale_name = static::localeConfigName($language->id, $name); + $locale_name = $this->configFactory->getLanguageConfigName($language->id, $name); $translation = $this->configStorage->read($locale_name); return !empty($translation); } - /** - * Provides configuration data location for given langcode and name. - * - * @param string $langcode - * The language code. - * @param string|null $name - * Name of the original configuration. Set to NULL to get the name prefix - * for all $langcode overrides. - * - * @return string - */ - public static function localeConfigName($langcode, $name = NULL) { - return rtrim('locale.config.' . $langcode . '.' . $name, '.'); - } - } diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php deleted file mode 100644 index 11fa899..0000000 --- a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php +++ /dev/null @@ -1,142 +0,0 @@ -languageManager = $language_manager; - $this->defaultConfigContext = $config_context; - } - - /** - * Initializes configuration context with language. - * - * @param \Drupal\Core\Config\ConfigEvent $event - * The Event to process. - */ - public function configContext(ConfigEvent $event) { - $context = $event->getContext(); - - // If there is a language set explicitly in the current context, use it. - // Otherwise check if there is a user set in the current context, - // to set the language based on the preferred language of the user. - // Otherwise set it based on the negotiated interface language. - if ($language = $context->get('language')) { - $context->set('locale.language', $language); - } - elseif ($account = $context->get('user.account')) { - $context->set('locale.language', language_load($account->getPreferredLangcode())); - } - 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 - * The Event to process. - */ - public function configLoad(ConfigEvent $event) { - $context = $event->getContext(); - if ($language = $context->get('locale.language')) { - $config = $event->getConfig(); - $locale_name = $this->getLocaleConfigName($config->getName(), $language); - // 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); - } - } - } - - /** - * Sets the negotiated interface language on the default configuration context. - * - * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event - * Kernel event to respond to. - */ - public function onKernelRequestSetDefaultConfigContextLocale(GetResponseEvent $event) { - // Re-initialize the default configuration context to ensure any cached - // configuration object are reset and can be translated. This will invoke - // the config context event which will retrieve the negotiated language - // from the language manager in configContext(). - $this->defaultConfigContext->init(); - } - - /** - * Get configuration name for this language. - * - * 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 localized config name. - */ - public function getLocaleConfigName($name, Language $language) { - return 'locale.config.' . $language->id . '.' . $name; - } - - /** - * Implements EventSubscriberInterface::getSubscribedEvents(). - */ - static function getSubscribedEvents() { - $events['config.context'][] = array('configContext', 20); - $events['config.load'][] = array('configLoad', 20); - // Set the priority above the one from the RouteListener (priority 32) - // so ensure that the context is cleared before the routing system steps in. - $events[KernelEvents::REQUEST][] = array('onKernelRequestSetDefaultConfigContextLocale', 48); - return $events; - } -} diff --git a/core/modules/locale/lib/Drupal/locale/ParamConverter/LocaleAdminPathConfigEntityConverter.php b/core/modules/locale/lib/Drupal/locale/ParamConverter/LocaleAdminPathConfigEntityConverter.php index 1be24be..6488eb4 100644 --- a/core/modules/locale/lib/Drupal/locale/ParamConverter/LocaleAdminPathConfigEntityConverter.php +++ b/core/modules/locale/lib/Drupal/locale/ParamConverter/LocaleAdminPathConfigEntityConverter.php @@ -9,6 +9,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Route; +use Drupal\Core\Config\ConfigFactory; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\ParamConverter\EntityConverter; use Drupal\Core\ParamConverter\ParamConverterInterface; @@ -29,17 +31,33 @@ class LocaleAdminPathConfigEntityConverter extends EntityConverter { /** + * The config factory. + * + * @var \Drupal\Core\Config\ConfigFactory + */ + protected $configFactory; + + /** + * Constructs a new EntityConverter. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entityManager + * The entity manager. + */ + public function __construct(EntityManagerInterface $entity_manager, ConfigFactory $config_factory) { + $this->configFactory = $config_factory; + parent::__construct($entity_manager); + } + + /** * {@inheritdoc} */ public function convert($value, $definition, $name, array $defaults, Request $request) { $entity_type = substr($definition['type'], strlen('entity:')); if ($storage = $this->entityManager->getStorageController($entity_type)) { - // Enter the override-free context, so we can ensure no overrides are - // applied. - config_context_enter('config.context.free'); + // Make sure no overrides are loaded. + $this->configFactory->disableOverrides(); $entity = $storage->load($value); - // Leave the override-free context. - config_context_leave(); + $this->configFactory->enableOverrides(); return $entity; } } diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php index af87dc9..16fc30b 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php @@ -47,7 +47,8 @@ public function testHasTranslation() { $this->container->get('config.storage.schema'), $this->container->get('config.storage.installer'), $this->container->get('locale.storage'), - $this->container->get('cache.config') + $this->container->get('cache.config'), + $this->container->get('config.factory') ); $language = new Language(array('id' => 'de')); diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php index 0970b9c..f7c64bf 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php @@ -89,7 +89,6 @@ function testConfigTranslation() { $translation = $wrapper->getTranslation($langcode); $properties = $translation->getProperties(); $this->assertEqual(count($properties), 1, 'Got the right number of properties after translation'); -// $this->assertEqual($properties['name']->getValue(), $site_name, 'Got the right translation for site name after translation'); // Check the translated site name is displayed. $this->drupalGet($langcode); @@ -172,14 +171,15 @@ function testConfigTranslation() { $this->assertEqual($property->getValue(), $image_style_label, 'Got the right translation for image style name after translation'); // Quick test to ensure translation file exists. - $this->assertEqual(\Drupal::config('locale.config.xx.image.style.medium')->get('label'), $image_style_label); + $language_config_name = \Drupal::configFactory()->getLanguageConfigName('xx', 'image.style.medium'); + $this->assertEqual(\Drupal::config($language_config_name)->get('label'), $image_style_label); // Uninstall the module. $this->drupalPostForm('admin/modules/uninstall', array('uninstall[image]' => "image"), t('Uninstall')); $this->drupalPostForm(NULL, array(), t('Uninstall')); // Ensure that the translated configuration has been removed. - $this->assertFalse(\Drupal::config('locale.config.xx.image.style.medium')->get('label'), 'Translated configuration for image module removed.'); + $this->assertFalse(\Drupal::config($language_config_name)->get('label'), 'Translated configuration for image module removed.'); // Translate default category using the UI so configuration is refreshed. $category_label = $this->randomName(20); diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationUiTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationUiTest.php index d02f763..5c67d4e 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationUiTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationUiTest.php @@ -109,7 +109,8 @@ function testStringTranslation() { ); $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); $this->assertText(t('The strings have been saved.'), 'The strings have been saved.'); - $this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), 'Correct page redirection.'); + $url_bits = explode('?', $this->getUrl()); + $this->assertEqual($url_bits[0], url('admin/config/regional/translate', array('absolute' => TRUE)), 'Correct page redirection.'); $search = array( 'string' => $name, 'langcode' => $langcode, diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 5c98791..960381c 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -947,9 +947,9 @@ function locale_update_8016() { // Fetch all date types from {date_format_type}. $result = db_query('SELECT * FROM {date_format_locale}'); foreach ($result as $format) { - $language = $format->language; // Create config objects for the language if not yet done. - \Drupal::config("locale.config.$language.system.date_format." . $format->type) + $config_name = \Drupal::configFactory()->getLanguageConfigName($format->language, 'system.date_format.' . $format->type); + \Drupal::config($config_name) ->set('pattern.php', $format->format) ->save(); } diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml index 568f21d..b5f4cf4 100644 --- a/core/modules/locale/locale.services.yml +++ b/core/modules/locale/locale.services.yml @@ -1,17 +1,12 @@ services: - locale_config_subscriber: - class: Drupal\locale\LocaleConfigSubscriber - tags: - - { name: event_subscriber } - arguments: ['@language_manager', '@config.context'] paramconverter.configentity_admin: class: Drupal\locale\ParamConverter\LocaleAdminPathConfigEntityConverter tags: - { name: paramconverter, priority: 5 } - arguments: ['@entity.manager'] + arguments: ['@entity.manager', '@config.factory'] locale.config.typed: class: Drupal\locale\LocaleConfigManager - arguments: ['@config.storage', '@config.storage.schema', '@config.storage.installer', '@locale.storage', '@cache.config'] + arguments: ['@config.storage', '@config.storage.schema', '@config.storage.installer', '@locale.storage', '@cache.config', '@config.factory'] locale.storage: class: Drupal\locale\StringDatabaseStorage arguments: ['@database'] diff --git a/core/modules/locale/tests/modules/locale_test/config/locale.config.de.locale_test.translation.yml b/core/modules/locale/tests/modules/locale_test/config/language.config.de.locale_test.translation.yml similarity index 100% rename from core/modules/locale/tests/modules/locale_test/config/locale.config.de.locale_test.translation.yml rename to core/modules/locale/tests/modules/locale_test/config/language.config.de.locale_test.translation.yml diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php index 0367775..36b0fa6 100644 --- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php +++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateSystemConfigsTest.php @@ -181,11 +181,11 @@ public function testSystemFile() { $this->prepare($migration, $dumps); $executable = new MigrateExecutable($migration, new MigrateMessage()); $executable->import(); - config_context_enter('config.context.free'); + \Drupal::configFactory()->disableOverrides(); $config = \Drupal::config('system.file'); $this->assertIdentical($config->get('path.private'), 'files/test'); $this->assertIdentical($config->get('path.temporary'), 'files/temp'); - config_context_leave(); + \Drupal::configFactory()->enableOverrides(); } } diff --git a/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php b/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php index 0d3e115..d0acb03 100644 --- a/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php +++ b/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php @@ -8,7 +8,6 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\KeyValueStore\StateInterface; use Drupal\Core\Plugin\PluginFormInterface; @@ -54,8 +53,6 @@ class SearchSettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The configuration factory object that manages search settings. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The context interface * @param \Drupal\search\SearchPluginManager $manager * The manager for search plugins. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler @@ -63,8 +60,8 @@ class SearchSettingsForm extends ConfigFormBase { * @param \Drupal\Core\KeyValueStore\StateInterface $state * The state key/value store interface, gives access to state based config settings. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, SearchPluginManager $manager, ModuleHandlerInterface $module_handler, StateInterface $state) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, SearchPluginManager $manager, ModuleHandlerInterface $module_handler, StateInterface $state) { + parent::__construct($config_factory); $this->searchSettings = $config_factory->get('search.settings'); $this->searchPluginManager = $manager; $this->moduleHandler = $module_handler; @@ -77,7 +74,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('plugin.manager.search'), $container->get('module_handler'), $container->get('state') diff --git a/core/modules/statistics/lib/Drupal/statistics/StatisticsSettingsForm.php b/core/modules/statistics/lib/Drupal/statistics/StatisticsSettingsForm.php index e8646cd..2f4d9f7 100644 --- a/core/modules/statistics/lib/Drupal/statistics/StatisticsSettingsForm.php +++ b/core/modules/statistics/lib/Drupal/statistics/StatisticsSettingsForm.php @@ -6,7 +6,6 @@ namespace Drupal\statistics; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Config\ConfigFactory; @@ -29,13 +28,11 @@ class StatisticsSettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, ModuleHandlerInterface $module_handler) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, ModuleHandlerInterface $module_handler) { + parent::__construct($config_factory); $this->moduleHandler = $module_handler; } @@ -46,7 +43,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('module_handler') ); } @@ -95,5 +91,5 @@ public function submitForm(array &$form, array &$form_state) { parent::submitForm($form, $form_state); } - } + diff --git a/core/modules/system/lib/Drupal/system/Form/CronForm.php b/core/modules/system/lib/Drupal/system/Form/CronForm.php index 5d94762..6a070e0 100644 --- a/core/modules/system/lib/Drupal/system/Form/CronForm.php +++ b/core/modules/system/lib/Drupal/system/Form/CronForm.php @@ -8,7 +8,6 @@ namespace Drupal\system\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\KeyValueStore\StateInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -31,13 +30,11 @@ class CronForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context used for this configuration object. * @param \Drupal\Core\KeyValueStore\StateInterface $state - * The state key value store. + * The state keyvalue collection to use. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, StateInterface $state) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, StateInterface $state) { + parent::__construct($config_factory); $this->state = $state; } @@ -47,7 +44,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('state') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/ImageToolkitForm.php b/core/modules/system/lib/Drupal/system/Form/ImageToolkitForm.php index 1600b58..1ab3a26 100644 --- a/core/modules/system/lib/Drupal/system/Form/ImageToolkitForm.php +++ b/core/modules/system/lib/Drupal/system/Form/ImageToolkitForm.php @@ -8,7 +8,6 @@ namespace Drupal\system\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\ImageToolkit\ImageToolkitManager; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class ImageToolkitForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context used for this configuration object. * @param \Drupal\Core\ImageToolkit\ImageToolkitManager $manager * The image toolkit plugin manager. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, ImageToolkitManager $manager) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, ImageToolkitManager $manager) { + parent::__construct($config_factory); foreach ($manager->getAvailableToolkits() as $id => $definition) { $this->availableToolkits[$id] = $manager->createInstance($id); @@ -49,7 +46,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('image.toolkit.manager') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php b/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php index f596078..cc114bf 100644 --- a/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php +++ b/core/modules/system/lib/Drupal/system/Form/PerformanceForm.php @@ -9,7 +9,6 @@ use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Cache\CacheBackendInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,12 +29,10 @@ class PerformanceForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context used for this configuration object. * @param \Drupal\Core\Cache\CacheBackendInterface $page_cache */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, CacheBackendInterface $page_cache) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, CacheBackendInterface $page_cache) { + parent::__construct($config_factory); $this->pageCache = $page_cache; } @@ -46,7 +43,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('cache.page') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/RegionalForm.php b/core/modules/system/lib/Drupal/system/Form/RegionalForm.php index a75ff7f..2ca6acf 100644 --- a/core/modules/system/lib/Drupal/system/Form/RegionalForm.php +++ b/core/modules/system/lib/Drupal/system/Form/RegionalForm.php @@ -8,7 +8,6 @@ namespace Drupal\system\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Locale\CountryManagerInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class RegionalForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context used for this configuration object. * @param \Drupal\Core\Locale\CountryManagerInterface $country_manager * The country manager. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, CountryManagerInterface $country_manager) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, CountryManagerInterface $country_manager) { + parent::__construct($config_factory); $this->countryManager = $country_manager; } @@ -46,7 +43,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('country_manager') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/SiteInformationForm.php b/core/modules/system/lib/Drupal/system/Form/SiteInformationForm.php index 34e3584..aca83c3 100644 --- a/core/modules/system/lib/Drupal/system/Form/SiteInformationForm.php +++ b/core/modules/system/lib/Drupal/system/Form/SiteInformationForm.php @@ -8,7 +8,6 @@ namespace Drupal\system\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Path\AliasManagerInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class SiteInformationForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context used for this configuration object. * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager * The path alias manager. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, AliasManagerInterface $alias_manager) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, AliasManagerInterface $alias_manager) { + parent::__construct($config_factory); $this->aliasManager = $alias_manager; } @@ -47,7 +44,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('path.alias_manager') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/SiteMaintenanceModeForm.php b/core/modules/system/lib/Drupal/system/Form/SiteMaintenanceModeForm.php index 693dc28..535ecfd 100644 --- a/core/modules/system/lib/Drupal/system/Form/SiteMaintenanceModeForm.php +++ b/core/modules/system/lib/Drupal/system/Form/SiteMaintenanceModeForm.php @@ -8,7 +8,6 @@ namespace Drupal\system\Form; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\KeyValueStore\StateInterface; use Drupal\Core\Form\ConfigFormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class SiteMaintenanceModeForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. * @param \Drupal\Core\KeyValueStore\StateInterface $state * The state keyvalue collection to use. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, StateInterface $state) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, StateInterface $state) { + parent::__construct($config_factory); $this->state = $state; } @@ -46,7 +43,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('state') ); } diff --git a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php index ec76227..dc1490a 100644 --- a/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php +++ b/core/modules/system/lib/Drupal/system/Form/ThemeSettingsForm.php @@ -12,7 +12,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Drupal\Core\Cache\Cache; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; @@ -33,13 +32,11 @@ class ThemeSettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface * The module handler instance to use. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, ModuleHandlerInterface $module_handler) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, ModuleHandlerInterface $module_handler) { + parent::__construct($config_factory); $this->moduleHandler = $module_handler; } @@ -50,7 +47,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('module_handler') ); } diff --git a/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php b/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php index f9965f9..237473a 100644 --- a/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php +++ b/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php @@ -9,8 +9,6 @@ use Drupal\Core\Config\Config; use Drupal\Core\Config\ConfigImporterEvent; use Drupal\Core\Config\ConfigImporterException; -use Drupal\Core\Config\Context\ConfigContext; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Config\ConfigEvent; use Drupal\Core\Config\StorageDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php index 849c1ef..7cb4df5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php @@ -48,8 +48,7 @@ function setUp() { */ public function testMenuRouterRebuildContext() { // Enter a language context before rebuilding the menu router tables. - $language_context = config_context_enter('Drupal\Core\Config\Context\LanguageConfigContext'); - $language_context->setLanguage(language_load('nl')); + \Drupal::configFactory()->setLanguage(language_load('nl')); menu_router_rebuild(); // Check that the language context was not used for building the menu item. diff --git a/core/modules/system/tests/modules/menu_test/config/locale.config.nl.menu_test.menu_item.yml b/core/modules/system/tests/modules/menu_test/config/language.config.nl.menu_test.menu_item.yml similarity index 100% rename from core/modules/system/tests/modules/menu_test/config/locale.config.nl.menu_test.menu_item.yml rename to core/modules/system/tests/modules/menu_test/config/language.config.nl.menu_test.menu_item.yml diff --git a/core/modules/tour/tests/tour_test/config/locale.config.it.tour.tour.tour-test.yml b/core/modules/tour/tests/tour_test/config/language.config.it.tour.tour.tour-test.yml similarity index 100% rename from core/modules/tour/tests/tour_test/config/locale.config.it.tour.tour.tour-test.yml rename to core/modules/tour/tests/tour_test/config/language.config.it.tour.tour.tour-test.yml diff --git a/core/modules/user/lib/Drupal/user/AccountSettingsForm.php b/core/modules/user/lib/Drupal/user/AccountSettingsForm.php index ace1834..20ae102 100644 --- a/core/modules/user/lib/Drupal/user/AccountSettingsForm.php +++ b/core/modules/user/lib/Drupal/user/AccountSettingsForm.php @@ -9,7 +9,6 @@ use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Config\Context\ContextInterface; use Drupal\Core\Extension\ModuleHandler; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -30,13 +29,11 @@ class AccountSettingsForm extends ConfigFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The factory for configuration objects. - * @param \Drupal\Core\Config\Context\ContextInterface $context - * The configuration context. * @param \Drupal\Core\Extension\ModuleHandler $module_handler * The module handler. */ - public function __construct(ConfigFactory $config_factory, ContextInterface $context, ModuleHandler $module_handler) { - parent::__construct($config_factory, $context); + public function __construct(ConfigFactory $config_factory, ModuleHandler $module_handler) { + parent::__construct($config_factory); $this->moduleHandler = $module_handler; } @@ -46,7 +43,6 @@ public function __construct(ConfigFactory $config_factory, ContextInterface $con public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('config.context.free'), $container->get('module_handler') ); } diff --git a/core/modules/user/lib/Drupal/user/UserConfigContext.php b/core/modules/user/lib/Drupal/user/UserConfigContext.php deleted file mode 100644 index 1d5f497..0000000 --- a/core/modules/user/lib/Drupal/user/UserConfigContext.php +++ /dev/null @@ -1,45 +0,0 @@ -set(self::USER_KEY, $account); - // Re-initialize since the user change changes the context fundamentally. - $this->init(); - return $this; - } - -} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index f6a30cb..28e1872 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1339,12 +1339,10 @@ function user_mail($key, &$message, $params) { $langcode = $message['langcode']; $variables = array('user' => $params['account']); - // Get configuration objects customized for the user specified in $params as - // this user is not necessarily the same as the one triggering the mail. This - // allows the configuration objects to be localized for the user's language if - // the locale module is enabled. - $user_config_context = config_context_enter('Drupal\user\UserConfigContext'); - $user_config_context->setAccount($params['account']); + $original_language = \Drupal::configFactory()->getLanguage(); + + $language = language_load($params['account']->getPreferredLangcode()); + \Drupal::configFactory()->setLanguage($language); $mail_config = \Drupal::config('user.mail'); // We do not sanitize the token replacement, since the output of this @@ -1353,8 +1351,7 @@ function user_mail($key, &$message, $params) { $message['subject'] .= $token_service->replace($mail_config->get($key . '.subject'), $variables, $token_options); $message['body'][] = $token_service->replace($mail_config->get($key . '.body'), $variables, $token_options); - // Return the previous config context. - config_context_leave(); + \Drupal::configFactory()->setLanguage($original_language); } /** diff --git a/core/tests/Drupal/Tests/Core/Datetime/DateTest.php b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php index 32d2103..55f2471 100644 --- a/core/tests/Drupal/Tests/Core/Datetime/DateTest.php +++ b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php @@ -65,7 +65,7 @@ protected function setUp() { ->getMock(); $this->stringTranslation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface'); - $this->date = new Date($this->entityManager, $this->languageManager, $this->stringTranslation); + $this->date = new Date($this->entityManager, $this->languageManager, $this->stringTranslation, $this->getConfigFactoryStub()); } /**