diff -iu b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php --- b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -514,7 +514,8 @@ * already invalidates it. */ protected function invalidateTagsOnSave($update) { - Cache::invalidateTags($this->getListCacheTags()); + $tags = Cache::mergeTags($this->getEntityType()->getListCacheTags(), $this->getListCacheTags()); + Cache::invalidateTags($tags); } /** @@ -524,7 +525,11 @@ * config system already invalidates them. */ protected static function invalidateTagsOnDelete(EntityTypeInterface $entity_type, array $entities) { - Cache::invalidateTags($entity_type->getListCacheTags()); + $tags = $entity_type->getListCacheTags(); + foreach ($entities as $entity) { + $tags = Cache::mergeTags($entity->getListCacheTags()); + } + Cache::invalidateTags($tags); } /** diff -iu b/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php --- b/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -481,7 +481,9 @@ public function getListCacheTags() { $tags = $this->getEntityType()->getListCacheTags(); if ($this->bundle() != $this->entityTypeId) { - Cache::mergeTags($tags, [$this->entityTypeId . '_list:' . $this->bundle()]); + foreach ($tags as $key => $tag) { + $tags[$key] = $tag . ':' . $this->bundle(); + } } return $tags; } @@ -550,7 +552,7 @@ // updated entity may start to appear in a listing because it now meets that // listing's filtering requirements. A newly created entity may start to // appear in listings because it did not exist before.) - $tags = $this->getListCacheTags(); + $tags = Cache::mergeTags($this->getEntityType()->getListCacheTags(), $this->getListCacheTags()); if ($this->hasLinkTemplate('canonical')) { // Creating or updating an entity may change a cached 403 or 404 response. $tags = Cache::mergeTags($tags, ['4xx-response']); @@ -579,6 +581,7 @@ // cache tag, but subsequent list pages would not be invalidated, hence we // must invalidate its list cache tags as well.) $tags = Cache::mergeTags($tags, $entity->getCacheTagsToInvalidate()); + $tags = Cache::mergeTags($tags, $entity->getListCacheTags()); } Cache::invalidateTags($tags); } diff -iu b/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php --- b/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -256,7 +256,7 @@ * specific list cache tag like most entities, use the cache tag of the theme * this block is placed in instead. */ - public function getBundleListCacheTag() { + public function getListCacheTags() { return ['theme:' . $this->theme]; } diff -iu b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php --- b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php @@ -520,14 +520,14 @@ $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Special case: entity types may choose to use their bundle entity type // cache tags, to avoid having excessively granular invalidation. - $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags(); + $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getListCacheTags() == $this->entity->getListCacheTags(); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Special case: entity types may choose to use their bundle entity type // cache tags, to avoid having excessively granular invalidation. - $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getListCacheTags() == $this->entity->getListCacheTags(); + $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags(); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); @@ -593,7 +593,7 @@ // there is a cache miss for both the empty entity listing and the non-empty // entity listing routes, but not for other routes. $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug'); - Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags()); + Cache::invalidateTags($this->entity->getListCacheTags()); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($referencing_entity_url, 'HIT'); @@ -603,7 +603,7 @@ // there is a cache miss for both the empty entity listing and the non-empty // entity listing routes, but not for other routes. $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug'); - Cache::invalidateTags($this->entity->getListCacheTags()); + Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags()); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($referencing_entity_url, 'HIT'); @@ -635,7 +635,7 @@ $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['http_response', 'rendered']); - $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); + $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); @@ -646,7 +646,7 @@ $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['http_response', 'rendered']); - $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); + $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); only in patch2: --- a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php +++ b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php @@ -225,2 +225,18 @@ + $listTags = []; + $skipListTags = []; + // Sometimes view`s filters are not populated. + if (empty($this->view->filter)) { + $this->view->initHandlers(); + } + // @TODO: maybe there is a better way to add bundle related list cache tags? + foreach ((array) $this->view->filter as $filter) { + if ($filter->getPluginId() == 'bundle') { + foreach (array_keys($filter->value) as $bundle) { + $listTags[] = $filter->getEntityType() . '_list:' . $bundle; + $skipListTags[] = $filter->getEntityType(); + } + } + } + // The list cache tags for the entity types listed in this view. @@ -231,3 +247,6 @@ foreach ($entity_information as $table => $metadata) { - $tags = Cache::mergeTags($tags, \Drupal::entityManager()->getDefinition($metadata['entity_type'])->getListCacheTags()); + // If bundle filter is used then no need to add parent ENTITY_TYPE_list cache tag. + if (!in_array($metadata['entity_type'], $skipListTags)) { + $tags = Cache::mergeTags($tags, \Drupal::entityManager()->getDefinition($metadata['entity_type'])->getListCacheTags()); + } } @@ -236,2 +255,3 @@ $tags = Cache::mergeTags($tags, $this->view->getQuery()->getCacheTags()); + $tags = Cache::mergeTags($tags, $listTags);