diff --git a/core/includes/config.inc b/core/includes/config.inc index 347bf85..8f357d7 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 + * Array with contextual data to be used for the configuration factory. + * @param Drupal\Core\Config\StorageInterface $storage + * The storage controller object to use for reading and writing + * configuration data. + * @param Symfony\Component\EventDispatcher\EventDispatcher + * An event dispatcher instance to use for configuration events. + */ +function config_factory($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..c594c4b 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,13 @@ 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 + * A configuration factory object that produces this config object. */ - 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 +372,16 @@ class Config { } /** + * Retrieve the configuration factory used to create this configuration object. + */ + public function getFactory() { + return $this->factory; + } + + /** * Dispatch a config event. */ 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..9449404 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvent.php +++ b/core/lib/Drupal/Core/Config/ConfigEvent.php @@ -16,8 +16,9 @@ class ConfigEvent extends Event { /** * Constructor. */ - public function __construct(Config $config) { + public function __construct(Config $config, ConfigFactory $factory) { $this->config = $config; + $this->factory = $factory; } /** @@ -26,4 +27,11 @@ class ConfigEvent extends Event { public function getConfig() { return $this->config; } + + /** + * Get 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..b56ce1d 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,58 @@ 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. + */ + public function getStorage() { + return $this->storage; + } + + /** + * Gets data from this config context. + * + * @param $key + * A string that maps to a key within the context data or empty to get all data. + * + * @return + * 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. + */ + public function setContext($key, $value) { + $this->data[$key] = $value; + return $this; + } + + /** + * Dispatch a config event. + * + * @param $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 d83684c..1673777 100644 --- a/core/modules/config/config.api.php +++ b/core/modules/config/config.api.php @@ -121,3 +121,25 @@ function hook_config_import_delete($name, $new_config, $old_config) { return TRUE; } +/** + * Delete 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)); + } + } +} \ No newline at end of file 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 aec8978..7d85996 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -13,6 +13,7 @@ use Drupal\locale\LocaleLookup; use Drupal\locale\LocaleConfigSubscriber; +use Drupal\Core\Config\ConfigFactory; /** * Regular expression pattern used to localize JavaScript strings. @@ -885,6 +886,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)); + } + } +} \ No newline at end of file diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 72c50d4..d5bc3d6 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -1479,7 +1479,7 @@ function system_ip_blocking_delete_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'); @@ -1584,7 +1584,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']) @@ -1620,7 +1620,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'), ); @@ -1633,7 +1633,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(); } @@ -1665,7 +1665,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'), @@ -1684,7 +1684,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(); } @@ -1697,7 +1697,7 @@ function system_logging_settings_submit($form, &$form_state) { */ function system_performance_settings($form, &$form_state) { drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); - $config = config('system.performance'); + $config = config_admin('system.performance'); $form['clear_cache'] = array( '#type' => 'fieldset', @@ -1783,7 +1783,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']); @@ -1908,7 +1908,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'), @@ -1943,7 +1943,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']) @@ -2249,7 +2249,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'), @@ -2271,7 +2271,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();