diff --git a/core/core.services.yml b/core/core.services.yml index ac24e17..af0daf3 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -81,6 +81,10 @@ services: config.installer: class: Drupal\Core\Config\ConfigInstaller arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher'] + config.cache_prime_subscriber: + class: Drupal\Core\Config\ConfigCachePrimeSubscriber + tags: + - { name: event_subscriber } config.storage.staging: class: Drupal\Core\Config\FileStorage factory_class: Drupal\Core\Config\FileStorageFactory diff --git a/core/lib/Drupal/Core/Config/ConfigCachePrimeEvent.php b/core/lib/Drupal/Core/Config/ConfigCachePrimeEvent.php new file mode 100644 index 0000000..2905a4c --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigCachePrimeEvent.php @@ -0,0 +1,66 @@ +names; + } + + /** + * Adds configuration object names to prime the cache with. + * + * @param array $names + * The configuration object names. + * + * @return $this + * The ConfigCachePrimeEvent object. + */ + public function addNames(array $names) { + $this->names = array_unique(array_merge($this->names, $names)); + return $this; + } + + /** + * Removes configuration object names to preload. + * + * @param array $names_to_remove + * The configuration object names remove preload. + * + * @return $this + * The ConfigCachePrimeEvent object. + */ + public function removeNames(array $names_to_remove) { + $this->names = array_diff($this->names, $names_to_remove); + return $this; + } + +} diff --git a/core/lib/Drupal/Core/Config/ConfigCachePrimeSubscriber.php b/core/lib/Drupal/Core/Config/ConfigCachePrimeSubscriber.php new file mode 100644 index 0000000..4b38d30 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigCachePrimeSubscriber.php @@ -0,0 +1,40 @@ +get('config_cache_prime_names', array()); + if ($settings_config_names) { + $event->addNames($settings_config_names); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[ConfigEvents::PRIME][] = array('onConfigCachePrimeGetSettingsNames'); + return $events; + } + +} diff --git a/core/lib/Drupal/Core/Config/ConfigEvents.php b/core/lib/Drupal/Core/Config/ConfigEvents.php index 0b0bb3a..bcc95bc 100644 --- a/core/lib/Drupal/Core/Config/ConfigEvents.php +++ b/core/lib/Drupal/Core/Config/ConfigEvents.php @@ -57,4 +57,11 @@ */ const IMPORT = 'config.importer.import'; + /** + * Name of event fired when config cache is primed. + * @see \Drupal\Core\Config\ConfigFactory::getCachePrimeNames(). + * @see \Drupal\Core\Config\ConfigCachePrimeSubscriber::getSubscribedEvents(). + */ + const PRIME = 'config.prime.cache'; + } diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index 3d26c78..51d0680 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -9,7 +9,6 @@ use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageDefault; -use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -71,6 +70,13 @@ class ConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface protected $typedConfigManager; /** + * Whether or not the cache has been primed yet. + * + * @var boolean + */ + protected $isCachePrimed; + + /** * Constructs the Config factory. * * @param \Drupal\Core\Config\StorageInterface $storage @@ -84,6 +90,7 @@ public function __construct(StorageInterface $storage, EventDispatcherInterface $this->storage = $storage; $this->eventDispatcher = $event_dispatcher; $this->typedConfigManager = $typed_config; + $this->isCachePrimed = FALSE; } /** @@ -150,6 +157,10 @@ public function get($name) { * {@inheritdoc} */ public function loadMultiple(array $names) { + if (!$this->isCachePrimed) { + $names = array_unique(array_merge($names, $this->getCachePrimeNames())); + } + $list = array(); foreach ($names as $key => $name) { @@ -228,6 +239,23 @@ protected function loadModuleOverrides(array $names) { } /** + * Get a list of configuration object names to prime our cache with. + * + * @return array + * An array of configuration object names. + */ + protected function getCachePrimeNames() { + // It's possible an event subscriber may call back in to the configuration + // system to figure out which configuration objects to prime the cache with. + // This could get us stuck in an infinite loop, so set the flag before + // dispatching the event to avoid unintended recursion. + $this->isCachePrimed = TRUE; + $config_cache_prime_event = new ConfigCachePrimeEvent(); + $this->eventDispatcher->dispatch(ConfigEvents::PRIME, $config_cache_prime_event); + return $config_cache_prime_event->getNames(); + } + + /** * {@inheritdoc} */ public function reset($name = NULL) { diff --git a/core/tests/Drupal/Tests/Core/Config/ConfigFactoryTest.php b/core/tests/Drupal/Tests/Core/Config/ConfigFactoryTest.php new file mode 100644 index 0000000..8f2a1ec --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/ConfigFactoryTest.php @@ -0,0 +1,67 @@ + 'Config factoryt test', + 'description' => 'Tests the Config factory.', + 'group' => 'Configuration', + ); + } + + /** + * Tests loading multiple with prime config names. + */ + public function testLoadMultipleWithCachePrimeNames() { + + $storage = $this->getMock('Drupal\Core\Config\StorageInterface'); + + $config_data = array('test1' => array('config1'), 'prime1' => array('config2')); + $storage->expects($this->once()) + ->method('readMultiple') + ->with(array('test1', 'prime1', 'prime2', 'language1')) + ->will($this->returnValue($config_data)); + + $event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $typed_config_manager = $this->getMockBuilder('\Drupal\Core\Config\TypedConfigManager') + ->disableOriginalConstructor() + ->getMock(); + + $config_factory = new TestConfigFactory($storage, $event_dispatcher, $typed_config_manager); + + $names = ['test1']; + + $configs = $config_factory->loadMultiple($names); + + } + +} + +class TestConfigFactory extends ConfigFactory { + + protected function getCachePrimeNames() { + return array('prime1', 'prime2'); + } + + public function getLanguageConfigNames(array $names) { + return array('language1'); + } +} diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index ad2c404..32ec93f 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -276,6 +276,14 @@ $settings['update_free_access'] = FALSE; /** + * Configuration object names to prime in cache. + * + * The configuration system will prime its cache with the configuration + * objects named in this array. + */ +# $settings['config_cache_prime_names'] = array(); + +/** * Twig debugging: * * When debugging is enabled: