diff --git a/core/lib/Drupal/Core/Access/AccessResult.php b/core/lib/Drupal/Core/Access/AccessResult.php index f24124e..6ce9173 100644 --- a/core/lib/Drupal/Core/Access/AccessResult.php +++ b/core/lib/Drupal/Core/Access/AccessResult.php @@ -321,7 +321,7 @@ public function cachePerUser() { * @return $this * * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0. Use - * this::addCacheableDependency() instead. + * ::addCacheableDependency() instead. */ public function cacheUntilEntityChanges(EntityInterface $entity) { return $this->addCacheableDependency($entity); @@ -336,7 +336,7 @@ public function cacheUntilEntityChanges(EntityInterface $entity) { * @return $this * * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0. Use - * this::addCacheableDependency() instead. + * ::addCacheableDependency() instead. */ public function cacheUntilConfigurationChanges(ConfigBase $configuration) { return $this->addCacheableDependency($configuration); @@ -354,28 +354,9 @@ public function cacheUntilConfigurationChanges(ConfigBase $configuration) { */ public function addCacheableDependency($other_object) { if ($other_object instanceof CacheableDependencyInterface) { - // This is called many times per request, so avoid merging unless - // absolutely necessary. - if (empty($this->contexts)) { - $this->contexts = $other_object->getCacheContexts(); - } - elseif ($contexts = $other_object->getCacheContexts()) { - $this->contexts = Cache::mergeContexts($this->contexts, $contexts); - } - - if (empty($this->tags)) { - $this->tags = $other_object->getCacheTags(); - } - elseif ($tags = $other_object->getCacheTags()) { - $this->tags = Cache::mergeTags($this->tags, $tags); - } - - if ($this->maxAge === Cache::PERMANENT) { - $this->maxAge = $other_object->getCacheMaxAge(); - } - elseif (($max_age = $other_object->getCacheMaxAge()) && $max_age !== Cache::PERMANENT) { - $this->maxAge = Cache::mergeMaxAges($this->maxAge, $max_age); - } + $this->contexts = Cache::mergeContexts($this->contexts, $other_object->getCacheContexts()); + $this->tags = Cache::mergeTags($this->tags, $other_object->getCacheTags()); + $this->maxAge = Cache::mergeMaxAges($this->maxAge, $other_object->getCacheMaxAge()); } else { $this->maxAge = 0; diff --git a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php index ff9c172..4f9f6bc 100644 --- a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php +++ b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyInterface.php @@ -6,6 +6,8 @@ namespace Drupal\Core\Cache; +use Drupal\Core\Cache\CacheableMetadata; + /** * Allows to add cacheability metadata to an object for the current runtime. * @@ -52,4 +54,14 @@ public function addCacheTags(array $cache_tags); */ public function mergeCacheMaxAge($max_age); + /** + * Adds the passed in cacheability metadata to the object. + * + * @param \Drupal\Core\Cache\CacheableMetadata $metadata + * The cacheability metadata to add. + * + * @return $this + */ + public function addCacheableMetadata(CacheableMetadata $metadata); + } diff --git a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php index 972a829..1728bc9 100644 --- a/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php +++ b/core/lib/Drupal/Core/Cache/RefinableCacheableDependencyTrait.php @@ -36,6 +36,15 @@ /** * {@inheritdoc} */ + public function addCacheableMetadata(CacheableMetadata $metadata) { + $this->addCacheContexts($metadata->getCacheContexts()); + $this->addCacheTags($metadata->getCacheTags()); + $this->mergeCacheMaxAge($metadata->getCacheMaxAge()); + } + + /** + * {@inheritdoc} + */ public function addCacheContexts(array $cache_contexts) { $this->cacheContexts = Cache::mergeContexts($this->cacheContexts, $cache_contexts); return $this; diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index cbc19c7..eba111f 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -127,8 +127,8 @@ protected function doGet($name, $immutable = TRUE) { } } - // Propagate cache contexts to the config object. - $this->propagateCacheableDependencyOverrides($cache_key, $name); + // Propagate cacheable dependencies to the config object. + $this->propagateConfigOverriderCacheability($cache_key, $name); return $this->cache[$cache_key]; } @@ -189,7 +189,7 @@ protected function doLoadMultiple(array $names, $immutable = TRUE) { } // Propagate cacheable dependencies to the config object. - $this->propagateCacheableDependencyOverrides($cache_key, $name); + $this->propagateConfigOverriderCacheability($cache_key, $name); $list[$name] = $this->cache[$cache_key]; } @@ -225,12 +225,9 @@ protected function loadOverrides(array $names) { * @param string $name * The name of the configuration object to construct. */ - protected function propagateCacheableDependencyOverrides($cache_key, $name) { + protected function propagateConfigOverriderCacheability($cache_key, $name) { foreach ($this->configFactoryOverrides as $override) { - $this->cache[$cache_key] - ->addCacheContexts($override->getCacheContexts($name)) - ->addCacheTags($override->getCacheTags($name)) - ->mergeCacheMaxAge($override->getCacheMaxAge($name)); + $this->cache[$cache_key]->addCacheableMetadata($override->getCacheableMetadata($name)); } } diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php index 15723ec..80cc361 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php @@ -59,50 +59,11 @@ public function getCacheSuffix(); public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION); /** - * The cache contexts associated with this config factory override. + * Gets the cacheability metadata associated with the config factory override. * - * These identify a specific variation/representation of the object. - * - * Cache contexts are tokens: placeholders that are converted to cache keys by - * the @cache_contexts_manager service. The replacement value depends on the - * request context (the current URL, language, and so on). They're converted - * before storing or retrieving an object in cache. - * - * @param string $name - * The name of the configuration object that is being constructed. - * - * @return string[] - * An array of cache context tokens, used to generate a cache ID. - * - * @see \Drupal\Core\Cache\Context\CacheContextsManager::convertTokensToKeys() - */ - public function getCacheContexts($name); - - /** - * The cache tags associated with this config factory override. - * - * When this object is modified, these cache tags will be invalidated. - * - * Since a cache tag is already associated with every config object this - * should only be used if multiple config objects are being overridden. - * - * @param string $name - * The name of the configuration object that is being constructed. - * - * @return string[] - * A set of cache tags. - */ - public function getCacheTags($name); - - /** - * The maximum age for which this object may be cached. - * - * @param string $name - * The name of the configuration object that is being constructed. - * - * @return int - * The maximum time in seconds that this object may be cached. + * @return \Drupal\Core\Cache\CacheableMetadata + * A cacheable metadata object. */ - public function getCacheMaxAge($name); + public function getCacheableMetadata($name); } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 6153900..c067ab5 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -196,8 +196,9 @@ protected function doLoadMultiple(array $ids = NULL) { // Add cacheability metadata to the entities. foreach ($entities as $id => $entity) { - $entity->addCacheContexts($configs[$id]->getCacheContexts()); - $entity->mergeCacheMaxAge($configs[$id]->getCacheMaxAge()); + $entity + ->addCacheContexts($configs[$id]->getCacheContexts()) + ->mergeCacheMaxAge($configs[$id]->getCacheMaxAge()); // Remove the self-referring cache tag that is present on Config objects // before setting it. A ConfigEntity doesn't need this since it will be diff --git a/core/modules/config/tests/config_entity_static_cache_test/src/ConfigOverrider.php b/core/modules/config/tests/config_entity_static_cache_test/src/ConfigOverrider.php index 93837cc..3f79379 100644 --- a/core/modules/config/tests/config_entity_static_cache_test/src/ConfigOverrider.php +++ b/core/modules/config/tests/config_entity_static_cache_test/src/ConfigOverrider.php @@ -7,7 +7,7 @@ namespace Drupal\config_entity_static_cache_test; -use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryOverrideInterface; use Drupal\Core\Config\StorageInterface; @@ -44,22 +44,8 @@ public function createConfigObject($name, $collection = StorageInterface::DEFAUL /** * {@inheritdoc} */ - public function getCacheContexts($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - return Cache::PERMANENT; + public function getCacheableMetadata($name) { + return new CacheableMetadata(); } } diff --git a/core/modules/config/tests/config_override_integration_test/src/Cache/ConfigOverrideIntegrationTestCacheContext.php b/core/modules/config/tests/config_override_integration_test/src/Cache/ConfigOverrideIntegrationTestCacheContext.php index 31ec3d3..f2192aa 100644 --- a/core/modules/config/tests/config_override_integration_test/src/Cache/ConfigOverrideIntegrationTestCacheContext.php +++ b/core/modules/config/tests/config_override_integration_test/src/Cache/ConfigOverrideIntegrationTestCacheContext.php @@ -37,7 +37,11 @@ public function getContext() { * {@inheritdoc} */ public function getCacheableMetadata() { - return new CacheableMetadata(); + // Since this depends on State this can change at any time and is not + // cacheable. + $metadata = new CacheableMetadata(); + $metadata->setCacheMaxAge(0); + return $metadata; } } diff --git a/core/modules/config/tests/config_override_integration_test/src/CacheabilityMetadataConfigOverride.php b/core/modules/config/tests/config_override_integration_test/src/CacheabilityMetadataConfigOverride.php index c04089f..fc6a271 100644 --- a/core/modules/config/tests/config_override_integration_test/src/CacheabilityMetadataConfigOverride.php +++ b/core/modules/config/tests/config_override_integration_test/src/CacheabilityMetadataConfigOverride.php @@ -7,7 +7,7 @@ namespace Drupal\config_override_integration_test; -use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryOverrideInterface; use Drupal\Core\Config\StorageInterface; @@ -52,28 +52,14 @@ public function createConfigObject($name, $collection = StorageInterface::DEFAUL /** * {@inheritdoc} */ - public function getCacheContexts($name) { + public function getCacheableMetadata($name) { + $metadata = new CacheableMetadata(); if ($name === 'block.block.config_override_test') { - return ['config_override_integration_test']; + $metadata + ->setCacheContexts(['config_override_integration_test']) + ->setCacheTags(['config_override_integration_test_tag']); } - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - if ($name === 'block.block.config_override_test') { - return ['config_override_integration_test_tag']; - } - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - return Cache::PERMANENT; + return $metadata; } } diff --git a/core/modules/config/tests/config_override_test/src/Cache/PirateDayCacheContext.php b/core/modules/config/tests/config_override_test/src/Cache/PirateDayCacheContext.php index 7ef6f2d..c40cc6a 100644 --- a/core/modules/config/tests/config_override_test/src/Cache/PirateDayCacheContext.php +++ b/core/modules/config/tests/config_override_test/src/Cache/PirateDayCacheContext.php @@ -62,4 +62,5 @@ public static function isPirateDay() { public function getCacheableMetadata() { return new CacheableMetadata(); } + } diff --git a/core/modules/config/tests/config_override_test/src/ConfigOverrider.php b/core/modules/config/tests/config_override_test/src/ConfigOverrider.php index a06cb2e..3c9d84e 100644 --- a/core/modules/config/tests/config_override_test/src/ConfigOverrider.php +++ b/core/modules/config/tests/config_override_test/src/ConfigOverrider.php @@ -8,6 +8,7 @@ namespace Drupal\config_override_test; use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryOverrideInterface; /** @@ -48,23 +49,8 @@ public function createConfigObject($name, $collection = StorageInterface::DEFAUL /** * {@inheritdoc} */ - public function getCacheContexts($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - return Cache::PERMANENT; + public function getCacheableMetadata($name) { + return new CacheableMetadata(); } } - diff --git a/core/modules/config/tests/config_override_test/src/ConfigOverriderLowPriority.php b/core/modules/config/tests/config_override_test/src/ConfigOverriderLowPriority.php index ca4f5bf..ecce742 100644 --- a/core/modules/config/tests/config_override_test/src/ConfigOverriderLowPriority.php +++ b/core/modules/config/tests/config_override_test/src/ConfigOverriderLowPriority.php @@ -7,7 +7,7 @@ namespace Drupal\config_override_test; -use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryOverrideInterface; use Drupal\Core\Config\StorageInterface; @@ -53,22 +53,8 @@ public function createConfigObject($name, $collection = StorageInterface::DEFAUL /** * {@inheritdoc} */ - public function getCacheContexts($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - return Cache::PERMANENT; + public function getCacheableMetadata($name) { + return new CacheableMetadata(); } } diff --git a/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php b/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php index 2cb421d..85e1700 100644 --- a/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php +++ b/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php @@ -8,7 +8,7 @@ namespace Drupal\config_override_test; use Drupal\config_override_test\Cache\PirateDayCacheContext; -use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryOverrideInterface; use Drupal\Core\Config\StorageInterface; @@ -57,31 +57,13 @@ public function createConfigObject($name, $collection = StorageInterface::DEFAUL /** * {@inheritdoc} */ - public function getCacheContexts($name) { - if ($this->isCacheabilityMetadataApplicable($name)) { - return ['pirate_day']; - } - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - if ($this->isCacheabilityMetadataApplicable($name)) { - return ['pirate-day-tag']; - } - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - if ($this->isCacheabilityMetadataApplicable($name)) { - return PirateDayCacheContext::PIRATE_DAY_MAX_AGE; - } - return Cache::PERMANENT; + public function getCacheableMetadata($name) { + $metadata = new CacheableMetadata(); + $metadata + ->setCacheContexts(['pirate_day']) + ->setCacheTags(['pirate-day-tag']) + ->setCacheMaxAge(PirateDayCacheContext::PIRATE_DAY_MAX_AGE); + return $metadata; } /** diff --git a/core/modules/language/src/Config/LanguageConfigFactoryOverride.php b/core/modules/language/src/Config/LanguageConfigFactoryOverride.php index 4015573..e547d1e 100644 --- a/core/modules/language/src/Config/LanguageConfigFactoryOverride.php +++ b/core/modules/language/src/Config/LanguageConfigFactoryOverride.php @@ -7,7 +7,7 @@ namespace Drupal\language\Config; -use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigCollectionInfo; use Drupal\Core\Config\ConfigCrudEvent; use Drupal\Core\Config\ConfigFactoryOverrideBase; @@ -226,25 +226,12 @@ public function onConfigDelete(ConfigCrudEvent $event) { /** * {@inheritdoc} */ - public function getCacheContexts($name) { + public function getCacheableMetadata($name) { + $metadata = new CacheableMetadata(); if ($this->language) { - return ['languages:language_interface']; + $metadata->setCacheContexts(['languages:language_interface']); } - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheTags($name) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getCacheMaxAge($name) { - return Cache::PERMANENT; + return $metadata; } } diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 792898a..2828259 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Timer; use Drupal\Component\Utility\Xss; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\Entity\ThirdPartySettingsInterface; use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; use Drupal\Core\Form\FormStateInterface; @@ -1339,6 +1340,15 @@ public function hasTrustedData() { /** * {@inheritdoc} */ + public function addCacheableMetadata(CacheableMetadata $metadata) { + $this->addCacheContexts($metadata->getCacheContexts()); + $this->addCacheTags($metadata->getCacheTags()); + $this->mergeCacheMaxAge($metadata->getCacheMaxAge()); + } + + /** + * {@inheritdoc} + */ public function addCacheContexts(array $cache_contexts) { return $this->storage->addCacheContexts($cache_contexts); } diff --git a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php index b5f928c..881b096 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php @@ -12,6 +12,7 @@ use Drupal\Core\Access\AccessResultNeutral; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableDependencyInterface; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Tests\UnitTestCase; /** @@ -20,6 +21,28 @@ */ class AccessResultTest extends UnitTestCase { + /** + * The cache contexts manager. + * + * @var \Drupal\Core\Cache\Context\CacheContextsManager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheContextsManager; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->cacheContextsManager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager') + ->disableOriginalConstructor() + ->getMock(); + + $container = new ContainerBuilder(); + $container->set('cache_contexts_manager', $this->cacheContextsManager); + \Drupal::setContainer($container); + } + protected function assertDefaultCacheability(AccessResult $access) { $this->assertSame([], $access->getCacheContexts()); $this->assertSame([], $access->getCacheTags());