diff --git a/core/includes/config.inc b/core/includes/config.inc index 39094f8..0b01073 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -1,6 +1,7 @@ TRUE)); + } + return $config_factory->get($name)->load(); +} + +/** + * Retrieves a configuration factory object for a given context. + * + * @param array $context + * (optional) Array with contextual data to be used for the configuration + * factory. Defaults to an empty array. + * @param Drupal\Core\Config\StorageInterface $storage + * (optional) The storage controller object to use for reading and writing + * configuration data. Defaults to the storage controller object registered + * in the Drupal Container. + * @param Symfony\Component\EventDispatcher\EventDispatcher + * (optional) An event dispatcher instance to use for configuration events. + * Defaults to the event dispatcher instance registered in the Drupal + * Container. + * + * @return Drupal\Core\Config\ConfigFactory + * Configuration factory object. + */ +function config_factory(array $context = array(), StorageInterface $storage = NULL, EventDispatcher $event_dispatcher = NULL) { + $storage = $storage ? $storage : drupal_container()->get('config.storage'); + $event_dispatcher = $event_dispatcher ? $event_dispatcher : drupal_container()->get('dispatcher'); + $factory = new ConfigFactory($storage, $event_dispatcher); + foreach ($context as $key => $value) { + $factory->setContext($key, $value); + } + // Notify other modules and allow them to add other context objects. + module_invoke_all('config_factory', $factory); + return $factory; +} + +/** * Returns a list of differences between configuration storages. * * @param Drupal\Core\Config\StorageInterface $source_storage diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 538ab6d..247af2d 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -9,6 +9,7 @@ namespace Drupal\Core\Config; use Drupal\Component\Utility\NestedArray; use Symfony\Component\EventDispatcher\EventDispatcher; +use Drupal\Core\Config\ConfigFactory; /** * Defines the default configuration object. @@ -51,18 +52,18 @@ class Config { protected $overriddenData; /** - * The storage used to load and save this configuration object. + * The configuration factory that produces this configuration object. * - * @var Drupal\Core\Config\StorageInterface + * @var Drupal\Core\Config\ConfigFactory */ - protected $storage; + protected $factory; /** - * The event dispatcher used to notify subscribers. + * The storage used to load and save this configuration object. * - * @var Symfony\Component\EventDispatcher\EventDispatcher + * @var Drupal\Core\Config\StorageInterface */ - protected $eventDispatcher; + protected $storage; /** * Constructs a configuration object. @@ -72,13 +73,15 @@ class Config { * @param Drupal\Core\Config\StorageInterface $storage * A storage controller object to use for reading and writing the * configuration data. - * @param Symfony\Component\EventDispatcher\EventDispatcher $event_dispatcher - * The event dispatcher used to notify subscribers. + * @param Drupal\Core\Config\ConfigFactory $factory + * (optional) A configuration factory object that produces this config + * object. Defaults to the storage controller object registered in the + * Drupal Container. */ - public function __construct($name, StorageInterface $storage, EventDispatcher $event_dispatcher = NULL) { + public function __construct($name, StorageInterface $storage, ConfigFactory $factory = NULL) { $this->name = $name; $this->storage = $storage; - $this->eventDispatcher = $event_dispatcher ? $event_dispatcher : drupal_container()->get('dispatcher'); + $this->factory = $factory ? $factory : drupal_container()->get('config.factory'); } /** @@ -371,9 +374,22 @@ class Config { } /** - * Dispatch a config event. + * Retrieves the configuration factory that produces this configuration object. + * + * @return Drupal\Core\Config\ConfigFactory + * A configuration factory that produces this configuration object. + */ + public function getFactory() { + return $this->factory; + } + + /** + * Dispatches a config event. + * + * @param $config_event_name + * Event name. */ protected function notify($config_event_name) { - $this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($this)); + $this->factory->notify($config_event_name, $this); } } diff --git a/core/lib/Drupal/Core/Config/ConfigEvent.php b/core/lib/Drupal/Core/Config/ConfigEvent.php index aabd1d8..710f51f 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvent.php +++ b/core/lib/Drupal/Core/Config/ConfigEvent.php @@ -14,10 +14,16 @@ class ConfigEvent extends Event { protected $config; /** - * Constructor. + * Constructs a configuration event object. + * + * @param Drupal\Core\Config\Config + * Configuration object. + * @param Drupal\Core\Config\ConfigFactory + * Configuration factory object. */ - public function __construct(Config $config) { + public function __construct(Config $config, ConfigFactory $factory) { $this->config = $config; + $this->factory = $factory; } /** @@ -26,4 +32,14 @@ class ConfigEvent extends Event { public function getConfig() { return $this->config; } + + /** + * Get configuration factory object. + * + * @return Drupal\Core\Config\ConfigFactory + * Configuration factory object. + */ + public function getFactory() { + return $this->factory; + } } diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index ca36ce7..a2b4b51 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -39,6 +39,13 @@ class ConfigFactory { protected $eventDispatcher; /** + * The data of the configuration context. + * + * @var array + */ + protected $context; + + /** * Constructs the Config factory. * * @param Drupal\Core\Config\StorageInterface $storage @@ -50,6 +57,7 @@ class ConfigFactory { public function __construct(StorageInterface $storage, EventDispatcher $event_dispatcher) { $this->storage = $storage; $this->eventDispatcher = $event_dispatcher; + $this->context = array(); } /** @@ -82,8 +90,64 @@ class ConfigFactory { // @todo The decrease of CPU time is interesting, since that means that // ContainerBuilder involves plenty of function calls (which are known to // be slow in PHP). - $config = new Config($name, $this->storage, $this->eventDispatcher); + $config = new Config($name, $this->storage, $this); return $config->init(); } + /** + * Get storage controller. + * + * @return Drupal\Core\Config\StorageInterface + * A storage controller instance for reading and writing configuration data. + */ + public function getStorage() { + return $this->storage; + } + + /** + * Gets data from this config context. + * + * @param string $key + * (optional) A string that maps to a key within the context data or empty + * to get all data. + * + * @return array + * The data that was requested. + */ + public function getContext($key = '') { + if ($key) { + return isset($this->context[$key]) ? $this->context[$key] : NULL; + } + else { + return $this->context; + } + } + + /** + * Sets data on this config context. + * + * @param $key + * A string that maps to a key within the configuration context. + * @param $value + * Any value to be set for this key. + * + * @return Drupal\Core\Config\ConfigFactory + * This ConfigFactory instance. + */ + public function setContext($key, $value) { + $this->context[$key] = $value; + return $this; + } + + /** + * Dispatches a config event. + * + * @param string $config_event_name + * Event name. + * @param Drupal\Core\Config\Config + * Configuration object. + */ + public function notify($config_event_name, Config $config) { + $this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($config, $this)); + } } diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php index 6ee6a3d..75c508b 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ConfigGlobalOverrideSubscriber.php @@ -23,9 +23,12 @@ class ConfigGlobalOverrideSubscriber implements EventSubscriberInterface { public function configInit(ConfigEvent $event) { global $conf; - $config = $event->getConfig(); - if (isset($conf[$config->getName()])) { - $config->setOverride($conf[$config->getName()]); + // Do not override configuration objects that are intended for administration. + if (!$event->getFactory()->getContext('config.admin')) { + $config = $event->getConfig(); + if (isset($conf[$config->getName()])) { + $config->setOverride($conf[$config->getName()]); + } } } diff --git a/core/modules/config/config.api.php b/core/modules/config/config.api.php index 147412d..558ee08 100644 --- a/core/modules/config/config.api.php +++ b/core/modules/config/config.api.php @@ -124,3 +124,25 @@ function hook_config_import_delete($name, $new_config, $old_config) { return TRUE; } +/** + * Deletes configuration upon synchronizing configuration changes. + * + * This callback is invoked when a new configuration factory is created and + * allows a module to take over the synchronization of configuration data. + * + * Modules should implement this callback if they manage configuration data + * (such as image styles, node types, or fields) which needs to be prepared and + * passed through module API functions to properly handle a configuration + * change. + * + * @param Drupal\Core\Config\ConfigFactory $factory + * A configuration object containing the new configuration data. + */ +function hook_config_factory($factory) { + if (!$factory->getContext('locale.language')) { + // Add user's language when in user's context. + if ($account = $factory->getContext('user.account')) { + $factory->setContext('locale.language', user_preferred_language($account)); + } + } +} diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php index 3d2fd4a..2c0924e 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleConfigSubscriber.php @@ -25,11 +25,12 @@ class LocaleConfigSubscriber implements EventSubscriberInterface { * The Event to process. */ public function configLoad(ConfigEvent $event) { - $config = $event->getConfig(); - $language = language(LANGUAGE_TYPE_INTERFACE); - $locale_name = $this->getLocaleConfigName($config->getName(), $language); - if ($override = $config->getStorage()->read($locale_name)) { - $config->setOverride($override); + if ($language = $event->getFactory()->getContext('locale.language')) { + $config = $event->getConfig(); + $locale_name = $this->getLocaleConfigName($config->getName(), $language); + if ($override = $config->getStorage()->read($locale_name)) { + $config->setOverride($override); + } } } diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index a32d47d..e6f55d7 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -11,6 +11,7 @@ * Gettext portable object files are supported. */ +use Drupal\Core\Config\ConfigFactory; use Drupal\locale\LocaleLookup; use Drupal\locale\LocaleConfigSubscriber; use Drupal\locale\TranslationsStream; @@ -949,6 +950,20 @@ function _locale_rebuild_js($langcode = NULL) { * Implements hook_language_init(). */ function locale_language_init() { + // Add current language to default configuration factory. + drupal_container()->get('config.factory')->setContext('locale.language', language(LANGUAGE_TYPE_INTERFACE)); // Add locale helper to configuration subscribers. drupal_container()->get('dispatcher')->addSubscriber(new LocaleConfigSubscriber()); } + +/** + * Implements hook_config_factory(). + */ +function locale_config_factory(ConfigFactory $factory) { + if (!$factory->getContext('locale.language')) { + // Add user's language for user context. + if ($account = $factory->getContext('user.account')) { + $factory->setContext('locale.language', user_preferred_language($account)); + } + } +} diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 109c54b..844c3ef 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -1377,7 +1377,7 @@ function system_modules_uninstall_submit($form, &$form_state) { * @see system_settings_form() */ function system_site_information_settings($form, &$form_state) { - $site_config = config('system.site'); + $site_config = config_admin('system.site'); $site_mail = $site_config->get('mail'); if (empty($site_mail)) { $site_mail = ini_get('sendmail_from'); @@ -1482,7 +1482,7 @@ function system_site_information_settings_validate($form, &$form_state) { * Form submission handler for system_site_information_settings(). */ function system_site_information_settings_submit($form, &$form_state) { - config('system.site') + config_admin('system.site') ->set('name', $form_state['values']['site_name']) ->set('mail', $form_state['values']['site_mail']) ->set('slogan', $form_state['values']['site_slogan']) @@ -1518,7 +1518,7 @@ function system_cron_settings($form, &$form_state) { $form['cron']['cron_safe_threshold'] = array( '#type' => 'select', '#title' => t('Run cron every'), - '#default_value' => config('system.cron')->get('threshold.autorun'), + '#default_value' => config_admin('system.cron')->get('threshold.autorun'), '#options' => array(0 => t('Never')) + drupal_map_assoc(array(3600, 10800, 21600, 43200, 86400, 604800), 'format_interval'), ); @@ -1531,7 +1531,7 @@ function system_cron_settings($form, &$form_state) { * @ingroup forms */ function system_cron_settings_submit($form, &$form_state) { - config('system.cron') + config_admin('system.cron') ->set('threshold.autorun', $form_state['values']['cron_safe_threshold']) ->save(); } @@ -1563,7 +1563,7 @@ function system_logging_settings($form, &$form_state) { $form['error_level'] = array( '#type' => 'radios', '#title' => t('Error messages to display'), - '#default_value' => config('system.logging')->get('error_level'), + '#default_value' => config_admin('system.logging')->get('error_level'), '#options' => array( ERROR_REPORTING_HIDE => t('None'), ERROR_REPORTING_DISPLAY_SOME => t('Errors and warnings'), @@ -1582,7 +1582,7 @@ function system_logging_settings($form, &$form_state) { * @ingroup forms */ function system_logging_settings_submit($form, &$form_state) { - config('system.logging') + config_admin('system.logging') ->set('error_level', $form_state['values']['error_level']) ->save(); } @@ -1595,7 +1595,7 @@ function system_logging_settings_submit($form, &$form_state) { */ function system_performance_settings($form, &$form_state) { drupal_add_library('system', 'drupal.system'); - $config = config('system.performance'); + $config = config_admin('system.performance'); $form['clear_cache'] = array( '#type' => 'fieldset', @@ -1681,7 +1681,7 @@ function system_performance_settings($form, &$form_state) { * @ingroup forms */ function system_performance_settings_submit($form, &$form_state) { - $config = config('system.performance'); + $config = config_admin('system.performance'); $config->set('cache.page.enabled', $form_state['values']['cache']); $config->set('cache.page.max_age', $form_state['values']['page_cache_maximum_age']); $config->set('response.gzip', $form_state['values']['page_compression']); @@ -1806,7 +1806,7 @@ function system_image_toolkit_settings() { * @ingroup forms */ function system_rss_feeds_settings($form, &$form_state) { - $rss_config = config('system.rss'); + $rss_config = config_admin('system.rss'); $form['feed_description'] = array( '#type' => 'textarea', '#title' => t('Feed description'), @@ -1841,7 +1841,7 @@ function system_rss_feeds_settings($form, &$form_state) { * @ingroup forms */ function system_rss_feeds_settings_submit($form, &$form_state) { - config('system.rss') + config_admin('system.rss') ->set('channel.description', $form_state['values']['feed_description']) ->set('items.limit', $form_state['values']['feed_default_items']) ->set('items.view_mode', $form_state['values']['feed_item_length']) @@ -2147,7 +2147,7 @@ function system_date_time_lookup() { * @see system_site_maintenance_mode_submit() */ function system_site_maintenance_mode($form, &$form_state) { - $config = config('system.maintenance'); + $config = config_admin('system.maintenance'); $form['maintenance_mode'] = array( '#type' => 'checkbox', '#title' => t('Put site into maintenance mode'), @@ -2169,7 +2169,7 @@ function system_site_maintenance_mode($form, &$form_state) { * @ingroup forms */ function system_site_maintenance_mode_submit($form, &$form_state) { - config('system.maintenance') + config_admin('system.maintenance') ->set('enabled', $form_state['values']['maintenance_mode']) ->set('message', $form_state['values']['maintenance_mode_message']) ->save();