diff --git a/core/includes/module.inc b/core/includes/module.inc index ff11244..66f500d 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -69,7 +69,7 @@ function system_list_reset() { // @todo Trigger an event upon module install/uninstall and theme // enable/disable, and move this into an event subscriber. // @see https://drupal.org/node/2206347 - Cache::invalidateTags(array('extension')); + Cache::invalidateTags(['config:core.extension']); } /** diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php index 576ffb7..a59f697 100644 --- a/core/lib/Drupal/Core/Access/AccessManager.php +++ b/core/lib/Drupal/Core/Access/AccessManager.php @@ -97,7 +97,7 @@ public function checkNamedRoute($route_name, array $parameters = array(), Accoun } catch (RouteNotFoundException $e) { // Cacheable until extensions change. - $result = AccessResult::forbidden()->addCacheTags(array('extension')); + $result = AccessResult::forbidden()->addCacheTags(['config:core.extension']); return $return_as_object ? $result : $result->isAllowed(); } catch (ParamNotConvertedException $e) { diff --git a/core/lib/Drupal/Core/Access/AccessResult.php b/core/lib/Drupal/Core/Access/AccessResult.php index 329d50d..76f0212 100644 --- a/core/lib/Drupal/Core/Access/AccessResult.php +++ b/core/lib/Drupal/Core/Access/AccessResult.php @@ -8,6 +8,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableInterface; +use Drupal\Core\Config\ConfigBase; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; @@ -361,6 +362,19 @@ public function cacheUntilEntityChanges(EntityInterface $entity) { } /** + * Convenience method, adds the configuration object's cache tag. + * + * @param \Drupal\Core\Config\ConfigBase $configuration + * The configuration object whose cache tag to set on the access result. + * + * @return $this + */ + public function cacheUntilConfigurationChanges(ConfigBase $configuration) { + $this->addCacheTags($configuration->getCacheTags()); + return $this; + } + + /** * {@inheritdoc} */ public function orIf(AccessResultInterface $other) { diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php index ddf444e..1521d4b 100644 --- a/core/lib/Drupal/Core/Cache/Cache.php +++ b/core/lib/Drupal/Core/Cache/Cache.php @@ -81,14 +81,16 @@ public static function validateTags(array $tags) { * A prefix string. * @param array $suffixes * An array of suffixes. Will be cast to strings. + * @param string $glue + * A string to be used as glue for concatenation. Defaults to a colon. * * @return string[] * An array of cache tags. */ - public static function buildTags($prefix, array $suffixes) { + public static function buildTags($prefix, array $suffixes, $glue = ':') { $tags = []; foreach ($suffixes as $suffix) { - $tags[] = $prefix . ':' . $suffix; + $tags[] = $prefix . $glue . $suffix; } return $tags; } diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index d354799..bc6ba29 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Cache\Cache; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** @@ -223,6 +224,7 @@ public function save() { } $this->storage->write($this->name, $this->data); + Cache::invalidateTags($this->getCacheTags()); $this->isNew = FALSE; $this->eventDispatcher->dispatch(ConfigEvents::SAVE, new ConfigCrudEvent($this)); $this->originalData = $this->data; @@ -238,6 +240,7 @@ public function save() { public function delete() { $this->data = array(); $this->storage->delete($this->name); + Cache::invalidateTags($this->getCacheTags()); $this->isNew = TRUE; $this->resetOverriddenData(); $this->eventDispatcher->dispatch(ConfigEvents::DELETE, new ConfigCrudEvent($this)); diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php index f259dc7..e94db9b 100644 --- a/core/lib/Drupal/Core/Config/ConfigBase.php +++ b/core/lib/Drupal/Core/Config/ConfigBase.php @@ -262,4 +262,15 @@ public function merge(array $data_to_merge) { $this->setData(NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE)); return $this; } + + /** + * The unique cache tag associated with this configuration object. + * + * @return string[] + * An array of cache tags. + */ + public function getCacheTags() { + return ['config:' . $this->name]; + } + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index ad5f0d1..8cca5bd 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -372,6 +372,15 @@ public function link($text = NULL, $rel = 'edit-form', array $options = []) { } /** + * {@inheritdoc} + */ + public function getCacheTags() { + // Use cache tags that match the underlying config object's name. + // @see \Drupal\Core\Config\ConfigBase::getCacheTags() + return ['config:' . $this->getConfigDependencyName()]; + } + + /** * Overrides \Drupal\Core\Entity\DependencyTrait:addDependency(). * * Note that this function should only be called from implementations of diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php index 3fe34f1..23b0f4a 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php @@ -64,6 +64,12 @@ class ConfigEntityType extends EntityType { * {@inheritdoc} */ public function __construct($definition) { + // Ensure a default list cache tag is set; do this before calling the parent + // constructor, because we want "Configuration System style" cache tags. + if (empty($this->list_cache_tags)) { + $this->list_cache_tags = ['config:' . $definition['id'] . '_list']; + } + parent::__construct($definition); // Always add a default 'uuid' key. $this->entity_keys['uuid'] = 'uuid'; diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index d8e8e3e..199282d 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -399,7 +399,7 @@ public function getTypedData(); /** * The unique cache tag associated with this entity. * - * @return array + * @return string[] * An array of cache tags. */ public function getCacheTags(); diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php index 61c60c2..8851b27 100644 --- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php +++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php @@ -125,7 +125,7 @@ public function getCurrentRouteMenuTreeParameters($menu_name) { // expanded. ->addExpandedParents($this->treeStorage->getExpanded($menu_name, $active_trail)); - $this->cache->set($cid, $parameters, CacheBackendInterface::CACHE_PERMANENT, array('menu:' . $menu_name)); + $this->cache->set($cid, $parameters, CacheBackendInterface::CACHE_PERMANENT, array('config:system.menu.' . $menu_name)); } $this->cachedCurrentRouteParameters[$menu_name] = $parameters; } @@ -255,7 +255,7 @@ public function build(array $tree, $level = 0) { $build['#theme'] = 'menu__' . strtr($menu_name, '-', '_'); $build['#items'] = $items; // Set cache tag. - $build['#cache']['tags'][] = 'menu:' . $menu_name; + $build['#cache']['tags'][] = 'config:system.menu.' . $menu_name; return $build; } else { diff --git a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php index 0898091..941ac41 100644 --- a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php +++ b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php @@ -180,7 +180,7 @@ public function rebuild(array $definitions) { $this->resetDefinitions(); $affected_menus = $this->getMenuNames() + $before_menus; // Invalidate any cache tagged with any menu name. - $cache_tags = Cache::buildTags('menu', $affected_menus); + $cache_tags = Cache::buildTags('config:system.menu.', $affected_menus, ''); Cache::invalidateTags($cache_tags); $this->resetDefinitions(); // Every item in the cache bin should have one of the menu cache tags but it @@ -241,7 +241,7 @@ protected function safeExecuteSelect(SelectInterface $query) { public function save(array $link) { $affected_menus = $this->doSave($link); $this->resetDefinitions(); - $cache_tags = Cache::buildTags('menu', $affected_menus); + $cache_tags = Cache::buildTags('config:system.menu.', $affected_menus, ''); Cache::invalidateTags($cache_tags); return $affected_menus; } @@ -421,7 +421,7 @@ public function delete($id) { $this->updateParentalStatus($item); // Many children may have moved. $this->resetDefinitions(); - Cache::invalidateTags(array('menu:' . $item['menu_name'])); + Cache::invalidateTags(array('config:system.menu.' . $item['menu_name'])); } } @@ -822,7 +822,7 @@ public function loadTreeData($menu_name, MenuTreeParameters $parameters) { $data['tree'] = $this->doBuildTreeData($links, $parameters->activeTrail, $parameters->minDepth); $data['definitions'] = array(); $data['route_names'] = $this->collectRoutesAndDefinitions($data['tree'], $data['definitions']); - $this->menuCacheBackend->set($tree_cid, $data, Cache::PERMANENT, array('menu:' . $menu_name)); + $this->menuCacheBackend->set($tree_cid, $data, Cache::PERMANENT, ['config:system.menu.' . $menu_name]); // The definitions were already added to $this->definitions in // $this->doBuildTreeData() unset($data['definitions']); diff --git a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php index ebde906..3f30dfc 100644 --- a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php +++ b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverrides.php @@ -144,6 +144,13 @@ public function saveOverride($id, array $definition) { } /** + * {@inheritdoc} + */ + public function getCacheTags() { + return $this->getConfig()->getCacheTags(); + } + + /** * Encodes the ID by replacing dots with double underscores. * * This is done because config schema uses dots for its internal type diff --git a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverridesInterface.php b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverridesInterface.php index 43c4416..f3f429a 100644 --- a/core/lib/Drupal/Core/Menu/StaticMenuLinkOverridesInterface.php +++ b/core/lib/Drupal/Core/Menu/StaticMenuLinkOverridesInterface.php @@ -84,4 +84,12 @@ public function loadMultipleOverrides(array $ids); */ public function saveOverride($id, array $definition); + /** + * The unique cache tag associated with this menu link override. + * + * @return string[] + * An array of cache tags. + */ + public function getCacheTags(); + } diff --git a/core/lib/Drupal/Core/Render/Element/Page.php b/core/lib/Drupal/Core/Render/Element/Page.php index 0d8b777..b65446a 100644 --- a/core/lib/Drupal/Core/Render/Element/Page.php +++ b/core/lib/Drupal/Core/Render/Element/Page.php @@ -20,29 +20,11 @@ class Page extends RenderElement { * {@inheritdoc} */ public function getInfo() { - $class = get_class($this); return array( '#show_messages' => TRUE, - '#pre_render' => array( - array($class, 'preRenderPage'), - ), '#theme' => 'page', '#title' => '', ); } - /** - * #pre_render callback for the page element type. - * - * @param array $element - * A structured array containing the page element type build properties. - * - * @return array - */ - public static function preRenderPage($element) { - $element['#cache']['tags'][] = 'theme:' . \Drupal::theme()->getActiveTheme()->getName(); - $element['#cache']['tags'][] = 'theme_global_settings'; - return $element; - } - } diff --git a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php index 78ffd26..38c2e31 100644 --- a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php +++ b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php @@ -25,8 +25,8 @@ class ThemeAccessCheck implements AccessInterface { * The access result. */ public function access($theme) { - // Cacheable until the theme is modified. - return AccessResult::allowedIf($this->checkAccess($theme))->addCacheTags(array('theme:' . $theme)); + // Cacheable until the theme settings are modified. + return AccessResult::allowedIf($this->checkAccess($theme))->addCacheTags(['config:' . $theme . '.settings']); } /** diff --git a/core/lib/Drupal/Core/Theme/ThemeSettings.php b/core/lib/Drupal/Core/Theme/ThemeSettings.php index f1ad829..ab0d081 100644 --- a/core/lib/Drupal/Core/Theme/ThemeSettings.php +++ b/core/lib/Drupal/Core/Theme/ThemeSettings.php @@ -46,4 +46,12 @@ public function __construct($theme) { public function getTheme() { return $this->theme; } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + return ['rendered']; + } + } diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php index 0edc961..723bf68 100644 --- a/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -204,19 +204,6 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { /** * {@inheritdoc} - * - * Block configuration entities are a special case: one block entity stores - * the placement of one block in one theme. Changing these entities may affect - * any page that is rendered in a certain theme, even if the block doesn't - * appear there currently. Hence a block configuration entity must also return - * the associated theme's cache tag. - */ - public function getCacheTags() { - return Cache::mergeTags(parent::getCacheTags(), ['theme:' . $this->theme]); - } - - /** - * {@inheritdoc} */ public function setContexts(array $contexts) { $this->contexts = $contexts; diff --git a/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php b/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php index 895e2c6..bf91a04 100644 --- a/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php +++ b/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php @@ -12,6 +12,7 @@ use Drupal\block\Event\BlockEvents; use Drupal\Core\Block\MainContentBlockPluginInterface; use Drupal\Core\Display\PageVariantInterface; +use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityViewBuilderInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Display\VariantBase; @@ -43,11 +44,11 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont protected $blockViewBuilder; /** - * The current theme. + * The Block entity type list cache tags. * - * @var string + * @var string[] */ - protected $theme; + protected $blockListCacheTags; /** * The render array representing the main page content. @@ -71,12 +72,15 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont * The block view builder. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher * The event dispatcher. + * @param string[] $block_list_cache_tags + * The Block entity type list cache tags. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockRepositoryInterface $block_repository, EntityViewBuilderInterface $block_view_builder, EventDispatcherInterface $dispatcher) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockRepositoryInterface $block_repository, EntityViewBuilderInterface $block_view_builder, EventDispatcherInterface $dispatcher, array $block_list_cache_tags) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->blockRepository = $block_repository; $this->blockViewBuilder = $block_view_builder; $this->dispatcher = $dispatcher; + $this->blockListCacheTags = $block_list_cache_tags; } /** @@ -89,7 +93,8 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_definition, $container->get('block.repository'), $container->get('entity.manager')->getViewBuilder('block'), - $container->get('event_dispatcher') + $container->get('event_dispatcher'), + $container->get('entity.manager')->getDefinition('block')->getListCacheTags() ); } @@ -108,7 +113,11 @@ public function build() { // Track whether a block that shows the main content is displayed or not. $main_content_block_displayed = FALSE; - $build = array(); + $build = [ + '#cache' => [ + 'tags' => $this->blockListCacheTags, + ], + ]; $contexts = $this->getActiveBlockContexts(); // Load all region content assigned via blocks. foreach ($this->blockRepository->getVisibleBlocksPerRegion($contexts) as $region => $blocks) { diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php index 9c30e10..587ef33 100644 --- a/core/modules/block/src/Tests/BlockTest.php +++ b/core/modules/block/src/Tests/BlockTest.php @@ -327,10 +327,9 @@ public function testBlockCacheTags() { $cid = implode(':', $cid_parts); $cache_entry = \Drupal::cache('render')->get($cid); $expected_cache_tags = array( - 'theme:classy', - 'theme_global_settings', + 'config:block_list', 'block_view', - 'block:powered', + 'config:block.block.powered', 'block_plugin:system_powered_by_block', 'rendered', ); @@ -339,8 +338,7 @@ public function testBlockCacheTags() { $cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:en:classy'); $expected_cache_tags = array( 'block_view', - 'block:powered', - 'theme:classy', + 'config:block.block.powered', 'block_plugin:system_powered_by_block', 'rendered', ); @@ -369,11 +367,10 @@ public function testBlockCacheTags() { $cid = implode(':', $cid_parts); $cache_entry = \Drupal::cache('render')->get($cid); $expected_cache_tags = array( - 'theme:classy', - 'theme_global_settings', + 'config:block_list', 'block_view', - 'block:powered-2', - 'block:powered', + 'config:block.block.powered', + 'config:block.block.powered-2', 'block_plugin:system_powered_by_block', 'rendered', ); @@ -381,8 +378,7 @@ public function testBlockCacheTags() { $this->assertEqual($cache_entry->tags, $expected_cache_tags); $expected_cache_tags = array( 'block_view', - 'block:powered', - 'theme:classy', + 'config:block.block.powered', 'block_plugin:system_powered_by_block', 'rendered', ); @@ -391,8 +387,7 @@ public function testBlockCacheTags() { $this->assertIdentical($cache_entry->tags, $expected_cache_tags); $expected_cache_tags = array( 'block_view', - 'block:powered-2', - 'theme:classy', + 'config:block.block.powered-2', 'block_plugin:system_powered_by_block', 'rendered', ); diff --git a/core/modules/block/src/Tests/BlockViewBuilderTest.php b/core/modules/block/src/Tests/BlockViewBuilderTest.php index 2ddbcab..bfd37d4 100644 --- a/core/modules/block/src/Tests/BlockViewBuilderTest.php +++ b/core/modules/block/src/Tests/BlockViewBuilderTest.php @@ -215,7 +215,7 @@ public function testBlockViewBuilderAlter() { $request->setMethod('GET'); $default_keys = array('entity_view', 'block', 'test_block', 'en', 'cache_context.theme'); - $default_tags = array('block_view', 'block:test_block', 'theme:stark', 'block_plugin:test_cache'); + $default_tags = array('block_view', 'config:block.block.test_block', 'block_plugin:test_cache'); // Advanced: cached block, but an alter hook adds an additional cache key. $this->setBlockCacheConfig(array( @@ -230,7 +230,7 @@ public function testBlockViewBuilderAlter() { $this->assertIdentical(drupal_render($build), ''); $cache_entry = $this->container->get('cache.render')->get($cid); $this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.'); - $expected_tags = array('block_view', 'block:test_block', 'theme:stark', 'block_plugin:test_cache', 'rendered'); + $expected_tags = array_merge($default_tags, ['rendered']); sort($expected_tags); $this->assertIdentical($cache_entry->tags, $expected_tags, 'The block render element has been cached with the expected cache tags.'); $this->container->get('cache.render')->delete($cid); @@ -246,7 +246,7 @@ public function testBlockViewBuilderAlter() { $this->assertIdentical(drupal_render($build), ''); $cache_entry = $this->container->get('cache.render')->get($cid); $this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.'); - $expected_tags = array('block_view', 'block:test_block', 'theme:stark', 'block_plugin:test_cache', $alter_add_tag, 'rendered'); + $expected_tags = array_merge($default_tags, [$alter_add_tag, 'rendered']); sort($expected_tags); $this->assertIdentical($cache_entry->tags, $expected_tags, 'The block render element has been cached with the expected cache tags.'); $this->container->get('cache.render')->delete($cid); diff --git a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php index 0ae38d4..c39d744 100644 --- a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php +++ b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php @@ -61,9 +61,8 @@ public function setUpDisplayVariant($configuration = array(), $definition = arra $this->dispatcher->expects($this->any()) ->method('dispatch') ->willReturnArgument(1); - $this->contextHandler = $this->getMock('Drupal\Core\Plugin\Context\ContextHandlerInterface'); return $this->getMockBuilder('Drupal\block\Plugin\DisplayVariant\BlockPageVariant') - ->setConstructorArgs(array($configuration, 'test', $definition, $this->blockRepository, $this->blockViewBuilder, $this->dispatcher, $this->contextHandler)) + ->setConstructorArgs(array($configuration, 'test', $definition, $this->blockRepository, $this->blockViewBuilder, $this->dispatcher, ['config:block_list'])) ->setMethods(array('getRegionNames')) ->getMock(); } @@ -89,6 +88,11 @@ public function providerBuild() { $test_cases = []; $test_cases[] = [$blocks_config, 4, [ + '#cache' => [ + 'tags' => [ + 'config:block_list', + ], + ], 'top' => [ 'block1' => [], '#sorted' => TRUE, @@ -108,6 +112,11 @@ public function providerBuild() { unset($blocks_config['block4']); $test_cases[] = [$blocks_config, 3, [ + '#cache' => [ + 'tags' => [ + 'config:block_list', + ], + ], 'top' => [ 'block1' => [], '#sorted' => TRUE, @@ -170,7 +179,16 @@ public function testBuildWithoutMainContent() { ->method('getVisibleBlocksPerRegion') ->willReturn([]); - $expected = ['content' => ['system_main' => []]]; + $expected = [ + '#cache' => [ + 'tags' => [ + 'config:block_list', + ], + ], + 'content' => [ + 'system_main' => [], + ], + ]; $this->assertSame($expected, $display_variant->build()); } diff --git a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php index 1ea2156..b02086d 100644 --- a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php @@ -55,7 +55,7 @@ protected function createEntity() { * Each comment must have a comment body, which always has a text format. */ protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) { - return array('filter_format:plain_text'); + return ['config:filter.format.plain_text']; } } diff --git a/core/modules/comment/src/Tests/CommentCacheTagsTest.php b/core/modules/comment/src/Tests/CommentCacheTagsTest.php index 5da5555..6f83dbf 100644 --- a/core/modules/comment/src/Tests/CommentCacheTagsTest.php +++ b/core/modules/comment/src/Tests/CommentCacheTagsTest.php @@ -86,7 +86,7 @@ protected function createEntity() { protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) { /** @var \Drupal\comment\CommentInterface $entity */ return array( - 'filter_format:plain_text', + 'config:filter.format.plain_text', 'user:' . $entity->getOwnerId(), 'user_view', ); diff --git a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php index 5e4359d..1a97e1b 100644 --- a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php +++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php @@ -107,7 +107,7 @@ public function testCacheTags() { 'comment_list', 'comment_view', 'comment:' . $comment->id(), - 'filter_format:plain_text', + 'config:filter.format.plain_text', 'user_view', 'user:2', ); diff --git a/core/modules/contact/src/Access/ContactPageAccess.php b/core/modules/contact/src/Access/ContactPageAccess.php index e1a5294..97d6b06 100644 --- a/core/modules/contact/src/Access/ContactPageAccess.php +++ b/core/modules/contact/src/Access/ContactPageAccess.php @@ -93,7 +93,9 @@ public function access(UserInterface $user, AccountInterface $account) { } // If the requested user did not save a preference yet, deny access if the // configured default is disabled. - else if (!$this->configFactory->get('contact.settings')->get('user_default_enabled')) { + $contact_settings = $this->configFactory->get('contact.settings'); + $access->cacheUntilConfigurationChanges($contact_settings); + if (!isset($account_data) && !$contact_settings->get('user_default_enabled')) { return $access; } diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php index d4c47bf..50210b5 100644 --- a/core/modules/filter/src/Tests/FilterAPITest.php +++ b/core/modules/filter/src/Tests/FilterAPITest.php @@ -247,7 +247,7 @@ function testProcessedTextElement() { $this->assertEqual($expected_assets, $build['#attached'], 'Expected assets present'); $expected_cache_tags = array( // The cache tag set by the processed_text element itself. - 'filter_format:element_test', + 'config:filter.format.element_test', // The cache tags set by the filter_test_cache_tags filter. 'foo:bar', 'foo:baz', diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php index b73c06f..f8820fe 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php @@ -173,7 +173,7 @@ function _testImageFieldFormatters($scheme) { $default_output = drupal_render($image_style); $this->drupalGet('node/' . $nid); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('image_style:thumbnail', $cache_tags)); + $this->assertTrue(in_array('config:image.style.thumbnail', $cache_tags)); $this->assertRaw($default_output, 'Image style thumbnail formatter displaying correctly on full node view.'); if ($scheme == 'private') { diff --git a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php index ba19651..96432d4 100644 --- a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php +++ b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php @@ -48,13 +48,12 @@ public function testMenuBlock() { // Verify a cache hit, but also the presence of the correct cache tags. $expected_tags = array( - 'theme:classy', - 'theme_global_settings', 'rendered', 'block_view', - 'block:' . $block->id(), + 'config:block_list', + 'config:block.block.' . $block->id(), 'block_plugin:system_menu_block__llama', - 'menu:llama', + 'config:system.menu.llama', ); $this->verifyPageCache($path, 'HIT', $expected_tags); @@ -106,7 +105,7 @@ public function testMenuBlock() { $this->verifyPageCache($path, 'MISS'); // Verify a cache hit. - $this->verifyPageCache($path, 'HIT', array('rendered', 'theme:classy', 'theme_global_settings')); + $this->verifyPageCache($path, 'HIT', ['config:block_list', 'rendered']); } } diff --git a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php index 41e4f1c..09efc57 100644 --- a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php +++ b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php @@ -202,12 +202,12 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles = $this->assertRaw('media="(min-width: 560px)"'); $this->assertRaw('media="(min-width: 851px)"'); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('responsive_image_mapping:mapping_one', $cache_tags)); + $this->assertTrue(in_array('config:responsive_image.mappings.mapping_one', $cache_tags)); if (!$empty_styles) { - $this->assertTrue(in_array('image_style:thumbnail', $cache_tags)); - $this->assertTrue(in_array('image_style:medium', $cache_tags)); + $this->assertTrue(in_array('config:image.style.thumbnail', $cache_tags)); + $this->assertTrue(in_array('config:image.style.medium', $cache_tags)); } - $this->assertTrue(in_array('image_style:large', $cache_tags)); + $this->assertTrue(in_array('config:image.style.large', $cache_tags)); // Test the fallback image style. $large_style = entity_load('image_style', 'large'); diff --git a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php index da975f6..e52c214 100644 --- a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php +++ b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php @@ -41,25 +41,25 @@ function testSearchText() { // Initial page for searching nodes. $this->drupalGet('search/node'); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('search_page:node_search', $cache_tags)); + $this->assertTrue(in_array('config:search.page.node_search', $cache_tags)); // Node search results. $edit = array(); $edit['keys'] = 'bike shed'; $this->drupalPostForm('search/node', $edit, t('Search')); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('search_page:node_search', $cache_tags)); + $this->assertTrue(in_array('config:search.page.node_search', $cache_tags)); // Initial page for searching users. $this->drupalGet('search/user'); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('search_page:user_search', $cache_tags)); + $this->assertTrue(in_array('config:search.page.user_search', $cache_tags)); // User search results. $edit['keys'] = $this->searchingUser->getUsername(); $this->drupalPostForm('search/user', $edit, t('Search')); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); - $this->assertTrue(in_array('search_page:user_search', $cache_tags)); + $this->assertTrue(in_array('config:search.page.user_search', $cache_tags)); } } diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php index ad43339..86b4749 100644 --- a/core/modules/shortcut/src/Entity/Shortcut.php +++ b/core/modules/shortcut/src/Entity/Shortcut.php @@ -47,7 +47,7 @@ * "delete-form" = "entity.shortcut.delete_form", * "edit-form" = "entity.shortcut.canonical", * }, - * list_cache_tags = { "shortcut_set_list" }, + * list_cache_tags = { "config:shortcut_set_list" }, * bundle_entity_type = "shortcut_set" * ) */ diff --git a/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php b/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php index 98b0904..2fd7385 100644 --- a/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php +++ b/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php @@ -58,11 +58,11 @@ protected function createEntity() { */ public function testEntityCreation() { // Create a cache entry that is tagged with a shortcut set cache tag. - $cache_tags = array('shortcut_set:default'); + $cache_tags = ['config:shortcut.set.default']; \Drupal::cache('render')->set('foo', 'bar', \Drupal\Core\Cache\CacheBackendInterface::CACHE_PERMANENT, $cache_tags); // Verify a cache hit. - $this->verifyRenderCache('foo', array('shortcut_set:default')); + $this->verifyRenderCache('foo', $cache_tags); // Now create a shortcut entity in that shortcut set. $this->createEntity(); diff --git a/core/modules/system/src/EventSubscriber/ThemeSettingsCacheTag.php b/core/modules/system/src/EventSubscriber/ThemeSettingsCacheTag.php new file mode 100644 index 0000000..a6a6b7c --- /dev/null +++ b/core/modules/system/src/EventSubscriber/ThemeSettingsCacheTag.php @@ -0,0 +1,68 @@ +themeHandler = $theme_handler; + } + + /** + * Invalidate the 'rendered' cache tag whenever a theme setting is modified. + * + * @param \Drupal\Core\Config\ConfigCrudEvent $event + * The Event to process. + */ + public function onSave(ConfigCrudEvent $event) { + // Global theme settings. + if ($event->getConfig()->getName() === 'system.theme.global') { + Cache::invalidateTags(['rendered']); + } + + // Theme-specific settings, check if this matches a theme settings + // configuration object, in that case, clear the rendered cache tag. + foreach (array_keys($this->themeHandler->listInfo()) as $theme_name) { + if ($theme_name == $event->getConfig()->getName()) { + Cache::invalidateTags(['rendered']); + break; + } + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[ConfigEvents::SAVE][] = ['onSave']; + return $events; + } + +} diff --git a/core/modules/system/src/Form/ThemeSettingsForm.php b/core/modules/system/src/Form/ThemeSettingsForm.php index 8e72246..8bb150a 100644 --- a/core/modules/system/src/Form/ThemeSettingsForm.php +++ b/core/modules/system/src/Form/ThemeSettingsForm.php @@ -419,15 +419,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } theme_settings_convert_to_config($values, $config)->save(); - - // Invalidate either the theme-specific cache tag or the global theme - // settings cache tag, depending on whose settings were actually changed. - if (isset($values['theme'])) { - Cache::invalidateTags(array('theme:' . $values['theme'])); - } - else { - Cache::invalidateTags(array('theme_global_settings')); - } } /** diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php index 16af329..57aceef 100644 --- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -190,7 +190,7 @@ public function getCacheTags() { // menu block must also be re-rendered for that user, because maybe a menu // link that is accessible for that user has been added. $cache_tags = parent::getCacheTags(); - $cache_tags[] = 'menu:' . $this->getDerivativeId(); + $cache_tags[] = 'config:system.menu.' . $this->getDerivativeId(); return $cache_tags; } diff --git a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php index a016161..c3538f2 100644 --- a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php +++ b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php @@ -65,8 +65,6 @@ function testPageCacheTags() { 'pre_render', 'rendered', 'system_test_cache_tags_page', - 'theme:classy', - 'theme_global_settings', ); $this->assertIdentical($cache_entry->tags, $expected_tags); diff --git a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php index 1991a31..3fc3e34 100644 --- a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php @@ -69,16 +69,15 @@ function testPageCacheTags() { // Full node page 1. $this->verifyPageCacheTags('node/' . $node_1->id(), array( 'rendered', - 'theme:bartik', - 'theme_global_settings', 'block_view', - 'block:bartik_content', - 'block:bartik_tools', - 'block:bartik_login', - 'block:bartik_footer', - 'block:bartik_powered', - 'block:bartik_main_menu', - 'block:bartik_account_menu', + 'config:block_list', + 'config:block.block.bartik_content', + 'config:block.block.bartik_tools', + 'config:block.block.bartik_login', + 'config:block.block.bartik_footer', + 'config:block.block.bartik_powered', + 'config:block.block.bartik_main_menu', + 'config:block.block.bartik_account_menu', 'block_plugin:system_main_block', 'block_plugin:system_menu_block__account', 'block_plugin:system_menu_block__main', @@ -89,27 +88,26 @@ function testPageCacheTags() { 'node_view', 'node:' . $node_1->id(), 'user:' . $author_1->id(), - 'filter_format:basic_html', - 'menu:account', - 'menu:tools', - 'menu:footer', - 'menu:main', + 'config:filter.format.basic_html', + 'config:system.menu.account', + 'config:system.menu.tools', + 'config:system.menu.footer', + 'config:system.menu.main', )); // Full node page 2. $this->verifyPageCacheTags('node/' . $node_2->id(), array( 'rendered', - 'theme:bartik', - 'theme_global_settings', 'block_view', - 'block:bartik_content', - 'block:bartik_tools', - 'block:bartik_login', - 'block:' . $block->id(), - 'block:bartik_footer', - 'block:bartik_powered', - 'block:bartik_main_menu', - 'block:bartik_account_menu', + 'config:block_list', + 'config:block.block.bartik_content', + 'config:block.block.bartik_tools', + 'config:block.block.bartik_login', + 'config:block.block.' . $block->id(), + 'config:block.block.bartik_footer', + 'config:block.block.bartik_powered', + 'config:block.block.bartik_main_menu', + 'config:block.block.bartik_account_menu', 'block_plugin:system_main_block', 'block_plugin:system_menu_block__account', 'block_plugin:system_menu_block__main', @@ -121,11 +119,11 @@ function testPageCacheTags() { 'node_view', 'node:' . $node_2->id(), 'user:' . $author_2->id(), - 'filter_format:full_html', - 'menu:account', - 'menu:tools', - 'menu:footer', - 'menu:main', + 'config:filter.format.full_html', + 'config:system.menu.account', + 'config:system.menu.tools', + 'config:system.menu.footer', + 'config:system.menu.main', )); } diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php index 2bd830b..2ddfdb8 100644 --- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php @@ -282,8 +282,13 @@ public function testReferencedEntity() { $empty_entity_listing_path = 'entity_test/list_empty/' . $entity_type; $nonempty_entity_listing_path = 'entity_test/list_labels_alphabetically/' . $entity_type; - $render_cache_tags = array('rendered'); - $theme_cache_tags = array('theme:classy', 'theme_global_settings'); + // Cache tags present on every rendered page. + $page_cache_tags = Cache::mergeTags( + ['rendered'], + // If the block module is used, the Block page display variant is used, + // which adds the block config entity type's list cache tags. + \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list']: [] + ); $view_cache_tag = array(); if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { @@ -298,11 +303,13 @@ public function testReferencedEntity() { // Includes the main entity's cache tags, since this entity references it. $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntity($this->entity), - $view_cache_tag + $view_cache_tag, + ['rendered'] ); $non_referencing_entity_cache_tags = Cache::mergeTags( $this->non_referencing_entity->getCacheTags(), - \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags() + \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), + ['rendered'] ); // Generate the cache tags for all two possible entity listing paths. @@ -310,44 +317,37 @@ public function testReferencedEntity() { // 2. list cache tag plus entity cache tag (listing query has a match) $empty_entity_listing_cache_tags = Cache::mergeTags( $this->entity->getEntityType()->getListCacheTags(), - $theme_cache_tags, - $render_cache_tags + $page_cache_tags ); $nonempty_entity_listing_cache_tags = Cache::mergeTags( $this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntityListing($this->entity), - $theme_cache_tags, - $render_cache_tags + $page_cache_tags ); $this->pass("Test referencing entity.", 'Debug'); $this->verifyPageCache($referencing_entity_path, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags); - $this->verifyPageCache($referencing_entity_path, 'HIT', $tags); + $this->verifyPageCache($referencing_entity_path, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); // Also verify the existence of an entity render cache entry. $cid = 'entity_view:entity_test:' . $this->referencing_entity->id() . ':full:classy:r.anonymous:' . date_default_timezone_get(); - $tags = Cache::mergeTags($render_cache_tags, $referencing_entity_cache_tags); - $this->verifyRenderCache($cid, $tags); + $this->verifyRenderCache($cid, $referencing_entity_cache_tags); $this->pass("Test non-referencing entity.", 'Debug'); $this->verifyPageCache($non_referencing_entity_path, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $non_referencing_entity_cache_tags); - $this->verifyPageCache($non_referencing_entity_path, 'HIT', $tags); + $this->verifyPageCache($non_referencing_entity_path, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags)); // Also verify the existence of an entity render cache entry. $cid = 'entity_view:entity_test:' . $this->non_referencing_entity->id() . ':full:classy:r.anonymous:' . date_default_timezone_get(); - $tags = Cache::mergeTags($render_cache_tags, $non_referencing_entity_cache_tags); - $this->verifyRenderCache($cid, $tags); + $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags); $this->pass("Test listing of referencing entities.", 'Debug'); // Prime the page cache for the listing of referencing entities. $this->verifyPageCache($listing_path, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags); - $this->verifyPageCache($listing_path, 'HIT', $tags); + $this->verifyPageCache($listing_path, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); $this->pass("Test empty listing.", 'Debug'); @@ -563,16 +563,13 @@ public function testReferencedEntity() { // Verify cache hits. $referencing_entity_cache_tags = Cache::mergeTags( $this->referencing_entity->getCacheTags(), - \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags() + \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), + ['rendered'] ); - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags); - $this->verifyPageCache($referencing_entity_path, 'HIT', $tags); - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags); - $this->verifyPageCache($listing_path, 'HIT', $tags); - $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $this->entity->getEntityType()->getListCacheTags()); - $this->verifyPageCache($empty_entity_listing_path, 'HIT', $tags); - $tags = Cache::mergeTags($tags, $this->getAdditionalCacheTagsForEntityListing()); - $this->verifyPageCache($nonempty_entity_listing_path, 'HIT', $tags); + $this->verifyPageCache($referencing_entity_path, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); + $this->verifyPageCache($listing_path, 'HIT', $page_cache_tags); + $this->verifyPageCache($empty_entity_listing_path, 'HIT', $empty_entity_listing_cache_tags); + $this->verifyPageCache($nonempty_entity_listing_path, 'HIT', Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing(), $page_cache_tags)); } /** diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml index e95c91d..97cd4b9 100644 --- a/core/modules/system/system.services.yml +++ b/core/modules/system/system.services.yml @@ -42,3 +42,8 @@ services: arguments: ['@cron', '@config.factory', '@state'] tags: - { name: event_subscriber } + system.theme_settings_cache_tag: + class: Drupal\system\EventSubscriber\ThemeSettingsCacheTag + arguments: ['@theme_handler'] + tags: + - { name: event_subscriber } diff --git a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php index e2adde7..6fad815 100644 --- a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php +++ b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php @@ -222,7 +222,7 @@ function testCacheClearByCacheTag() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser against the language "en". $cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . 'en'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "en".'); + $this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "en".'); // Assert that no toolbar cache exists for adminUser against the // language "fr". @@ -242,7 +242,7 @@ function testCacheClearByCacheTag() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser against the language "fr". $cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . 'fr'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "fr".'); + $this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "fr".'); // Log in the adminUser2 user. We will use this user as a control to // verify that clearing a cache tag for adminUser does not clear the cache @@ -255,7 +255,7 @@ function testCacheClearByCacheTag() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser2 against the language "en". $cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'en'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); + $this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); // Request a page in 'fr' to create the cache. $this->drupalGet('fr/test-page'); @@ -263,11 +263,11 @@ function testCacheClearByCacheTag() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser against the language "fr". $cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'fr'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); + $this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); - // Log in adminUser and clear the caches for this user using a tag. + // Log in the admin user and clear the caches for this user using a tag. $this->drupalLogin($this->adminUser); - Cache::deleteTags(array('user:' . $admin_user_id)); + Cache::invalidateTags(array('user:' . $admin_user_id)); // Assert that no toolbar cache exists for adminUser against the // language "en". @@ -285,12 +285,12 @@ function testCacheClearByCacheTag() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser2 against the language "en". $cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'en'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); + $this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser2 against the language "fr". $cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'fr'); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); + $this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); } /** @@ -374,7 +374,7 @@ function testLocaleTranslationSubtreesHashCacheClear() { // Assert that a cache tag in the toolbar cache under the key "user" exists // for adminUser against the language "xx". $cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . $langcode); - $this->assertEqual($cache->tags[2], 'user:' . $admin_user_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "xx".'); + $this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "xx".'); // Get a baseline hash for the admin menu subtrees before translating one // of the menu link items. diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 7b75e89..50704d0 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -314,7 +314,7 @@ function _toolbar_get_subtrees_hash($langcode) { // Clear the cache when the 'locale' tag is deleted. This ensures a fresh // subtrees rendering when string translations are made. $role_list_cache_tags = \Drupal::entityManager()->getDefinition('user_role')->getListCacheTags(); - \Drupal::cache('toolbar')->set($cid, $hash, Cache::PERMANENT, Cache::mergeTags(array('user:' . $uid, 'locale', 'menu:admin'), $role_list_cache_tags)); + \Drupal::cache('toolbar')->set($cid, $hash, Cache::PERMANENT, Cache::mergeTags(array('user:' . $uid, 'locale', 'config:system.menu.admin'), $role_list_cache_tags)); } return $hash; } diff --git a/core/modules/tour/src/Tests/TourCacheTagsTest.php b/core/modules/tour/src/Tests/TourCacheTagsTest.php index 085477a..d6a537f 100644 --- a/core/modules/tour/src/Tests/TourCacheTagsTest.php +++ b/core/modules/tour/src/Tests/TourCacheTagsTest.php @@ -48,12 +48,10 @@ public function testRenderedTour() { $this->verifyPageCache($path, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. - $expected_tags = array( - 'theme:classy', - 'theme_global_settings', - 'tour:tour-test', + $expected_tags = [ + 'config:tour.tour.tour-test', 'rendered', - ); + ]; $this->verifyPageCache($path, 'HIT', $expected_tags); // Verify that after modifying the tour, there is a cache miss. @@ -70,7 +68,10 @@ public function testRenderedTour() { $this->verifyPageCache($path, 'MISS'); // Verify a cache hit. - $this->verifyPageCache($path, 'HIT', array('rendered', 'theme:classy', 'theme_global_settings')); + $expected_tags = [ + 'rendered', + ]; + $this->verifyPageCache($path, 'HIT', $expected_tags); } } diff --git a/core/modules/user/src/Access/RegisterAccessCheck.php b/core/modules/user/src/Access/RegisterAccessCheck.php index 0f0a3f5..ee0e5be 100644 --- a/core/modules/user/src/Access/RegisterAccessCheck.php +++ b/core/modules/user/src/Access/RegisterAccessCheck.php @@ -26,7 +26,7 @@ class RegisterAccessCheck implements AccessInterface { * The access result. */ public function access(AccountInterface $account) { - // @todo cacheable per role once https://www.drupal.org/node/2040135 lands. - return AccessResult::allowedIf($account->isAnonymous() && \Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY)->setCacheable(FALSE); + $user_settings = \Drupal::config('user.settings'); + return AccessResult::allowedIf($account->isAnonymous() && $user_settings->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY)->cacheUntilConfigurationChanges($user_settings); } } diff --git a/core/modules/user/src/PermissionsHash.php b/core/modules/user/src/PermissionsHash.php index 3f72645..57f0646 100644 --- a/core/modules/user/src/PermissionsHash.php +++ b/core/modules/user/src/PermissionsHash.php @@ -59,7 +59,7 @@ public function generate(AccountInterface $account) { } else { $permissions_hash = $this->doGenerate($sorted_roles); - $tags = Cache::buildTags('user_role', $sorted_roles); + $tags = Cache::buildTags('config:user.role.', $sorted_roles, ''); $this->cache->set("user_permissions_hash:$role_list", $permissions_hash, Cache::PERMANENT, $tags); } diff --git a/core/modules/user/src/Tests/UserPictureTest.php b/core/modules/user/src/Tests/UserPictureTest.php index 13feb0f..94c4a2f 100644 --- a/core/modules/user/src/Tests/UserPictureTest.php +++ b/core/modules/user/src/Tests/UserPictureTest.php @@ -103,9 +103,6 @@ function testPictureOnNodeComment() { ->set('features.comment_user_picture', TRUE) ->save(); - // @todo Remove when https://www.drupal.org/node/2040135 lands. - Cache::invalidateTags(['rendered']); - $edit = array( 'comment_body[0][value]' => $this->randomString(), ); @@ -118,9 +115,6 @@ function testPictureOnNodeComment() { ->set('features.comment_user_picture', FALSE) ->save(); - // @todo Remove when https://www.drupal.org/node/2040135 lands. - Cache::invalidateTags(['rendered']); - $this->drupalGet('node/' . $node->id()); $this->assertNoRaw(file_uri_target($file->getFileUri()), 'User picture not found on node and comment.'); } diff --git a/core/modules/user/src/Tests/UserSignatureTest.php b/core/modules/user/src/Tests/UserSignatureTest.php index 4fa92d8..b70c91d 100644 --- a/core/modules/user/src/Tests/UserSignatureTest.php +++ b/core/modules/user/src/Tests/UserSignatureTest.php @@ -128,7 +128,7 @@ function testUserSignature() { $this->assertRaw(check_markup($signature_text, $this->filtered_html_format->id()), 'Filtered signature text found.'); // Verify that the user signature's text format's cache tag is present. $this->drupalGet('node/' . $node->id()); - $this->assertTrue(in_array('filter_format:filtered_html_format', explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')))); + $this->assertTrue(in_array('config:filter.format.filtered_html_format', explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')))); // Verify the signature field is available on Manage form display page. $this->config('user.settings')->set('signatures', 0)->save(); diff --git a/core/modules/views/src/Plugin/ViewsHandlerManager.php b/core/modules/views/src/Plugin/ViewsHandlerManager.php index ac7abda..9d3fda4 100644 --- a/core/modules/views/src/Plugin/ViewsHandlerManager.php +++ b/core/modules/views/src/Plugin/ViewsHandlerManager.php @@ -59,7 +59,7 @@ public function __construct($handler_type, \Traversable $namespaces, ViewsData $ } parent::__construct("Plugin/views/$handler_type", $namespaces, $module_handler, $plugin_interface, $plugin_definition_annotation_name); - $this->setCacheBackend($cache_backend, "views:$handler_type", array('extension', 'extension:views')); + $this->setCacheBackend($cache_backend, "views:$handler_type", array('config:core.extension', 'extension:views')); $this->alterInfo('views_plugins_' . $handler_type); $this->viewsData = $views_data; diff --git a/core/modules/views/src/Plugin/ViewsPluginManager.php b/core/modules/views/src/Plugin/ViewsPluginManager.php index c340ca2..8e83d42 100644 --- a/core/modules/views/src/Plugin/ViewsPluginManager.php +++ b/core/modules/views/src/Plugin/ViewsPluginManager.php @@ -43,7 +43,7 @@ public function __construct($type, \Traversable $namespaces, CacheBackendInterfa ); $this->alterInfo('views_plugins_' . $type); - $this->setCacheBackend($cache_backend, "views:{$type}_plugins", array('extension', 'extension:views')); + $this->setCacheBackend($cache_backend, "views:{$type}_plugins", array('config:core.extension', 'extension:views')); } } diff --git a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php index 163dc44..bce200d 100644 --- a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php +++ b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php @@ -205,8 +205,7 @@ public function cacheGet($type) { * to be sure that we catch everything. Maybe that's a bad idea. */ public function cacheFlush() { - $id = $this->view->storage->id(); - Cache::invalidateTags(array('view:' . $id)); + Cache::invalidateTags($this->view->storage->getCacheTags()); } /** @@ -323,12 +322,11 @@ public function generateOutputKey() { /** * Gets an array of cache tags for the current view. * - * @return array - * An array fo cache tags based on the current view. + * @return string[] + * An array of cache tags based on the current view. */ protected function getCacheTags() { - $id = $this->view->storage->id(); - $tags = array('view:' . $id); + $tags = $this->view->storage->getCacheTags(); $entity_information = $this->view->query->getEntityTableInfo(); diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index a49740d..6d95134 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -202,8 +202,7 @@ public function initDisplay(ViewExecutable $view, array &$display, array &$optio } else { $this->unpackOptions($this->options, $options); - $id = $this->view->storage->id(); - \Drupal::cache('data')->set($cid, $this->options, Cache::PERMANENT, array('extension', 'extension:views', 'view:' . $id)); + \Drupal::cache('data')->set($cid, $this->options, Cache::PERMANENT, Cache::mergeTags(array('config:core.extension', 'extension:views'), $this->view->storage->getCacheTags())); } static::$unpackOptions[$cid] = $this->options; } diff --git a/core/modules/views/src/ViewsData.php b/core/modules/views/src/ViewsData.php index 796e94b..9ac3896 100644 --- a/core/modules/views/src/ViewsData.php +++ b/core/modules/views/src/ViewsData.php @@ -200,7 +200,7 @@ protected function cacheGet($cid) { * The data that will be cached. */ protected function cacheSet($cid, $data) { - return $this->cacheBackend->set($this->prepareCid($cid), $data, Cache::PERMANENT, array('views_data', 'extension', 'extension:views')); + return $this->cacheBackend->set($this->prepareCid($cid), $data, Cache::PERMANENT, array('views_data', 'config:core.extension', 'extension:views')); } /** diff --git a/core/modules/views/views.module b/core/modules/views/views.module index b84d983..3b11957 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -470,7 +470,7 @@ function views_field_config_create(FieldConfigInterface $field) { * Implements hook_ENTITY_TYPE_update() for 'field_config'. */ function views_field_config_update(FieldConfigInterface $field) { - Cache::deleteTags(array('extension' => 'views')); + Cache::deleteTags(['extension:views']); \Drupal::cache('render')->deleteAll(); } @@ -478,7 +478,7 @@ function views_field_config_update(FieldConfigInterface $field) { * Implements hook_ENTITY_TYPE_delete() for 'field_config'. */ function views_field_config_delete(FieldConfigInterface $field) { - Cache::deleteTags(array('extension' => 'views')); + Cache::deleteTags(['extension:views']); \Drupal::cache('render')->deleteAll(); } @@ -487,7 +487,7 @@ function views_field_config_delete(FieldConfigInterface $field) { */ function views_invalidate_cache() { // Clear Views' info cache entries. - Cache::deleteTags(array('extension' => 'views')); + Cache::deleteTags(['extension:views']); // Set the menu as needed to be rebuilt. \Drupal::service('router.builder_indicator')->setRebuildNeeded(); diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 58a1734..311a15e 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -1158,7 +1158,7 @@ public function getDependencies() { * {@inheritdoc} */ public function getCacheTags() { - $this->storage->getCacheTags(); + return $this->storage->getCacheTags(); } /** diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php index 98cffaf..ec1cdd6 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php @@ -555,7 +555,7 @@ public function testCheckNamedRouteWithNonExistingRoute() { $this->setupAccessChecker(); $this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account), 'A non existing route lead to access.'); - $this->assertEquals(AccessResult::forbidden()->addCacheTags(array('extension')), $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account, TRUE), 'A non existing route lead to access.'); + $this->assertEquals(AccessResult::forbidden()->addCacheTags(['config:core.extension']), $this->accessManager->checkNamedRoute('test_route_1', array(), $this->account, TRUE), 'A non existing route lead to access.'); } /** diff --git a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php index 1213614..da5651c 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php @@ -400,6 +400,7 @@ public function testCacheContexts() { * @covers ::resetCacheTags * @covers ::getCacheTags * @covers ::cacheUntilEntityChanges + * @covers ::cacheUntilConfigurationChanges */ public function testCacheTags() { $verify = function (AccessResult $access, array $tags) { @@ -447,6 +448,18 @@ public function testCacheTags() { $b = AccessResult::neutral()->cacheUntilEntityChanges($node); $verify($b, $tags); $this->assertEquals($a, $b); + + // ::cacheUntilConfigurationChanges() convenience method. + $configuration = $this->getMock('\Drupal\Core\Config\ConfigBase'); + $configuration->expects($this->any()) + ->method('getCacheTags') + ->will($this->returnValue(array('config:foo.bar.baz'))); + $tags = array('config:foo.bar.baz'); + $a = AccessResult::neutral()->addCacheTags($tags); + $verify($a, $tags); + $b = AccessResult::neutral()->cacheUntilConfigurationChanges($configuration); + $verify($b, $tags); + $this->assertEquals($a, $b); } /** diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php index a425572..1ef83a0 100644 --- a/core/tests/Drupal/Tests/Core/Cache/CacheTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/CacheTest.php @@ -105,6 +105,8 @@ public function buildTagsProvider() { ['node', [5 => NULL], ['node:']], ['node', ['a' => NULL], ['node:']], ['node', ['a' => TRUE], ['node:1']], + // Test the $glue parameter. + ['config:system.menu', ['menu_name'], ['config:system.menu.menu_name'], '.'], ]; } @@ -113,8 +115,8 @@ public function buildTagsProvider() { * * @dataProvider buildTagsProvider */ - public function testBuildTags($prefix, array $suffixes, array $expected) { - $this->assertEquals($expected, Cache::buildTags($prefix, $suffixes)); + public function testBuildTags($prefix, array $suffixes, array $expected, $glue = ':') { + $this->assertEquals($expected, Cache::buildTags($prefix, $suffixes, $glue)); } /** diff --git a/core/tests/Drupal/Tests/Core/Config/ConfigTest.php b/core/tests/Drupal/Tests/Core/Config/ConfigTest.php index 4111e08..15d300b 100644 --- a/core/tests/Drupal/Tests/Core/Config/ConfigTest.php +++ b/core/tests/Drupal/Tests/Core/Config/ConfigTest.php @@ -7,6 +7,7 @@ namespace Drupal\Tests\Core\Config; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Tests\UnitTestCase; use Drupal\Core\Config\Config; use Drupal\Component\Utility\String; @@ -55,6 +56,10 @@ public function setUp() { $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->typedConfig = $this->getMock('\Drupal\Core\Config\TypedConfigManagerInterface'); $this->config = new Config('config.test', $this->storage, $this->eventDispatcher, $this->typedConfig); + + $container = new ContainerBuilder(); + $container->setParameter('cache_bins', []); + \Drupal::setContainer($container); } /** @@ -118,6 +123,15 @@ public function testSetData($data) { * @dataProvider nestedDataProvider */ public function testSave($data) { + // Mock the cache backend, verifying that invalidateTags() is invoked on it. + $cache_backend = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface'); + $cache_backend->expects($this->once()) + ->method('invalidateTags') + ->with(['config:config.test']); + $container = \Drupal::getContainer(); + $container->set('cache.mocked', $cache_backend); + $container->setParameter('cache_bins', ['cache.mocked' => 'mocked']); + // Set initial data. $this->config->setData($data); @@ -276,6 +290,16 @@ public function testNestedClear($data) { * @dataProvider overrideDataProvider */ public function testDelete($data, $module_data) { + // Mock the cache backend, verifying that invalidateTags() is invoked on it, + // *twice*: once for saving, once for deleting. + $cache_backend = $this->getMock('\Drupal\Core\Cache\CacheBackendInterface'); + $cache_backend->expects($this->exactly(2)) + ->method('invalidateTags') + ->with(['config:config.test']); + $container = \Drupal::getContainer(); + $container->set('cache.mocked', $cache_backend); + $container->setParameter('cache_bins', ['cache.mocked' => 'mocked']); + // Set initial data. foreach ($data as $key => $value) { $this->config->set($key, $value); @@ -356,6 +380,13 @@ public function testValidateNameException($name, $exception_message) { } /** + * @covers ::getCacheTags + */ + public function testGetCacheTags() { + $this->assertSame(['config:' . $this->config->getName()], $this->config->getCacheTags()); + } + + /** * Provides data to test name validation. * * @see \Drupal\Tests\Core\Config\ConfigTest::testValidateNameException() diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index 2da84fe..e5f6844 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -106,6 +106,9 @@ protected function setUp() { $this->entityType->expects($this->any()) ->method('getProvider') ->will($this->returnValue($this->provider)); + $this->entityType->expects($this->any()) + ->method('getConfigPrefix') + ->willReturn('test_provider.' . $this->entityTypeId); $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); $this->entityManager->expects($this->any()) @@ -363,7 +366,7 @@ public function testEnable() { public function testDisable() { $this->cacheBackend->expects($this->once()) ->method('invalidateTags') - ->with(array($this->entityTypeId . ':' . $this->id)); + ->with(array('config:test_provider.' . $this->entityTypeId . '.' . $this->id)); $this->entity->setStatus(TRUE); $this->assertSame($this->entity, $this->entity->disable()); diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php index 3f95ed9..d94304e 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php @@ -303,7 +303,7 @@ public function testSaveUpdate(EntityInterface $entity) { $this->cacheBackend->expects($this->once()) ->method('invalidateTags') ->with(array( - $this->entityTypeId . ':foo', // Own cache tag. + 'config:the_config_prefix.foo', // Own cache tag. $this->entityTypeId . '_list', // List cache tag. )); @@ -363,7 +363,7 @@ public function testSaveRename(ConfigEntityInterface $entity) { $this->cacheBackend->expects($this->once()) ->method('invalidateTags') ->with(array( - $this->entityTypeId .':bar', // Own cache tag. + 'config:the_config_prefix.bar', // Own cache tag. $this->entityTypeId . '_list', // List cache tag. )); @@ -729,8 +729,8 @@ public function testDelete() { $this->cacheBackend->expects($this->once()) ->method('invalidateTags') ->with(array( - $this->entityTypeId . ':bar', // Own cache tag. - $this->entityTypeId . ':foo', // Own cache tag. + 'config:the_config_prefix.bar', // Own cache tag. + 'config:the_config_prefix.foo', // Own cache tag. $this->entityTypeId . '_list', // List cache tag. ));