diff --git a/core/lib/Drupal/Core/Config/ConfigEvents.php b/core/lib/Drupal/Core/Config/ConfigEvents.php index 0b0bb3a..8f61193 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvents.php +++ b/core/lib/Drupal/Core/Config/ConfigEvents.php @@ -35,13 +35,6 @@ const RENAME = 'config.rename'; /** - * Name of event fired when collecting overrides for configuration objects. - * - * @see \Drupal\Core\Config\ConfigFactory::loadModuleOverrides(). - */ - const MODULE_OVERRIDES = 'config.module.overrides'; - - /** * Name of event fired when validating in the configuration import process. * * @see \Drupal\Core\Config\ConfigImporter::validate(). diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index 3d26c78..2703646 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -10,6 +10,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageDefault; use Symfony\Component\EventDispatcher\EventDispatcher; +use Drupal\Component\Utility\NestedArray; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -71,6 +72,13 @@ class ConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface protected $typedConfigManager; /** + * An array of config factory override objects ordered by priority. + * + * @var \Drupal\Core\Config\ConfigFactoryOverrideInterface[] + */ + protected $configFactoryOverrides = array(); + + /** * Constructs the Config factory. * * @param \Drupal\Core\Config\StorageInterface $storage @@ -222,9 +230,13 @@ public function loadMultiple(array $names) { * An array of overrides keyed by the configuration object name. */ protected function loadModuleOverrides(array $names) { - $configOverridesEvent = new ConfigModuleOverridesEvent($names, $this->language); - $this->eventDispatcher->dispatch(ConfigEvents::MODULE_OVERRIDES, $configOverridesEvent); - return $configOverridesEvent->getOverrides(); + $overrides = array(); + foreach ($this->configFactoryOverrides as $override) { + // Existing overrides take precedence since these will have been added + // by events with a higher priority. + $overrides = NestedArray::mergeDeepArray(array($override->loadOverrides($names), $overrides), TRUE); + } + return $overrides; } /** @@ -392,4 +404,11 @@ static function getSubscribedEvents() { return $events; } + /** + * {@inheritdoc} + */ + public function addOverride(ConfigFactoryOverrideInterface $config_factory_override) { + $this->configFactoryOverrides[] = $config_factory_override; + } + } diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php index e836a2b..be656ea 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php @@ -191,4 +191,13 @@ public function getLanguageConfigName($langcode, $name); */ public function listAll($prefix = ''); + /** + * Adds config factory override services. + * + * @param \Drupal\Core\Config\ConfigFactoryOverrideInterface $config_factory_override + * The config factory override service to add. It is added at the end of the + * priority list (lower priority relative to existing ones). + */ + public function addOverride(ConfigFactoryOverrideInterface $config_factory_override); + } diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php new file mode 100644 index 0000000..cd66d75 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php @@ -0,0 +1,27 @@ +getDefinition('config.factory'); + $services = array(); + foreach ($container->findTaggedServiceIds('config.factory.override') as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $services[] = array('id' => $id, 'priority' => $priority); + } + usort($services, array($this, 'compareServicePriorities')); + foreach ($services as $service) { + $manager->addMethodCall('addOverride', array(new Reference($service['id']))); + } + } + + /** + * Compares services by priority for ordering. + * + * @param array $a + * Service to compare. + * @param array $b + * Service to compare. + * + * @return int + * Relative order of services to be used with usort. Higher priorities come + * first. + */ + private function compareServicePriorities($a, $b) { + if ($a['priority'] == $b['priority']) { + return 0; + } + return ($a['priority'] > $b['priority']) ? -1 : 1; + } + +} diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php index 847960c..5c3526f 100644 --- a/core/lib/Drupal/Core/CoreServiceProvider.php +++ b/core/lib/Drupal/Core/CoreServiceProvider.php @@ -8,6 +8,7 @@ namespace Drupal\Core; use Drupal\Core\Cache\ListCacheBinsPass; +use Drupal\Core\Config\ConfigFactoryOverridePass; use Drupal\Core\DependencyInjection\ServiceProviderInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass; @@ -78,6 +79,9 @@ public function register(ContainerBuilder $container) { // Add the compiler pass that will process the tagged theme negotiator // service. $container->addCompilerPass(new ThemeNegotiatorPass()); + // Add the compiler pass that will process the tagged config factory + // override services. + $container->addCompilerPass(new ConfigFactoryOverridePass()); // Add the compiler pass that will process tagged authentication services. $container->addCompilerPass(new RegisterAuthenticationPass()); // Register Twig extensions. diff --git a/core/modules/config/tests/config_override/config_override.services.yml b/core/modules/config/tests/config_override/config_override.services.yml index 586ce49..5272a84 100644 --- a/core/modules/config/tests/config_override/config_override.services.yml +++ b/core/modules/config/tests/config_override/config_override.services.yml @@ -1,9 +1,9 @@ services: - config_override_config_subscriber: - class: Drupal\config_override\EventSubscriber\ConfigModuleOverrideSubscriber + config_override.overrider: + class: Drupal\config_override\ConfigOverrider tags: - - { name: event_subscriber } - config_override_low_priority_config_subscriber: - class: Drupal\config_override\EventSubscriber\ConfigModuleLowPriorityOverrideSubscriber + - { name: config.factory.override} + config_override.low_priority_overrider: + class: Drupal\config_override\ConfigOverriderLowPriority tags: - - { name: event_subscriber } + - { name: config.factory.override, priority: -100 } diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php new file mode 100644 index 0000000..2d60d33 --- /dev/null +++ b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php @@ -0,0 +1,37 @@ + array('name' => 'ZOMG overridden site name')); + } + if (in_array('config_override.new', $names)) { + $overrides = $overrides + array('config_override.new' => array('module' => 'override')); + } + } + return $overrides; + } + +} + diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php new file mode 100644 index 0000000..1903888 --- /dev/null +++ b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php @@ -0,0 +1,38 @@ + + 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!', + ) + ); + } + } + return $overrides; + } + +} + diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleLowPriorityOverrideSubscriber.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleLowPriorityOverrideSubscriber.php deleted file mode 100644 index fd7e26c..0000000 --- a/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleLowPriorityOverrideSubscriber.php +++ /dev/null @@ -1,44 +0,0 @@ -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[ConfigEvents::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 deleted file mode 100644 index e168111..0000000 --- a/core/modules/config/tests/config_override/lib/Drupal/config_override/EventSubscriber/ConfigModuleOverrideSubscriber.php +++ /dev/null @@ -1,42 +0,0 @@ -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[ConfigEvents::MODULE_OVERRIDES][] = array('onConfigModuleOverride', 40); - return $events; - } -} -