diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index ef4423857e..d401453ff5 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -487,7 +487,7 @@ public function onDependencyRemoval(array $dependencies) { * already invalidates it. */ protected function invalidateTagsOnSave($update) { - Cache::invalidateTags($this->getEntityType()->getListCacheTags()); + Cache::invalidateTags($this->getListCacheTagsToInvalidate()); } /** @@ -497,7 +497,11 @@ protected function invalidateTagsOnSave($update) { * 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($tags, $entity->getListCacheTagsToInvalidate()); + } + Cache::invalidateTags($tags); } /** diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 84991bc609..94b584c3aa 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -488,12 +488,23 @@ public function getCacheContexts() { return $this->cacheContexts; } + /** + * {@inheritdoc} + */ + public function getListCacheTagsToInvalidate() { + $tags = $this->getEntityType()->getListCacheTags(); + if ($this->bundle() != $this->entityTypeId) { + foreach ($tags as $key => $tag) { + $tags[$key] = $tag . ':' . $this->bundle(); + } + } + return $tags; + } + /** * {@inheritdoc} */ public function getCacheTagsToInvalidate() { - // @todo Add bundle-specific listing cache tag? - // https://www.drupal.org/node/2145751 if ($this->isNew()) { return []; } @@ -558,7 +569,7 @@ protected function invalidateTagsOnSave($update) { // 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->getEntityType()->getListCacheTags(); + $tags = $this->getListCacheTagsToInvalidate(); if ($this->hasLinkTemplate('canonical')) { // Creating or updating an entity may change a cached 403 or 404 response. $tags = Cache::mergeTags($tags, ['4xx-response']); @@ -587,6 +598,7 @@ protected static function invalidateTagsOnDelete(EntityTypeInterface $entity_typ // 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->getListCacheTagsToInvalidate()); } Cache::invalidateTags($tags); } diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 9cdb435f29..18988a8eaf 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -424,6 +424,13 @@ public function referencedEntities(); */ public function getOriginalId(); + /** + * The list cache tags to invalidate for this entity. + * + * @return string[] + */ + public function getListCacheTags(); + /** * Returns the cache tags that should be used to invalidate caches. * diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php index ece8de38ab..5ee1fea176 100644 --- a/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -354,4 +354,16 @@ public function preSave(EntityStorageInterface $storage) { } } + /** + * {@inheritdoc} + * + * Block configuration entities are a special case: one block entity stores + * the placement of one block in one theme. Instead of using an entity type- + * specific list cache tag like most entities, use the cache tag of the theme + * this block is placed in instead. + */ + public function getListCacheTagsToInvalidate() { + return ['theme:' . $this->theme]; + } + }