core/includes/common.inc | 4 ++-- core/lib/Drupal/Core/Cache/ApcuBackend.php | 2 +- core/lib/Drupal/Core/Cache/Cache.php | 2 +- core/lib/Drupal/Core/Cache/DatabaseBackend.php | 4 ++-- core/lib/Drupal/Core/Cache/MemoryBackend.php | 3 +-- core/lib/Drupal/Core/Cache/PhpBackend.php | 3 +-- core/lib/Drupal/Core/Entity/Entity.php | 3 +-- core/lib/Drupal/Core/Entity/EntityViewBuilder.php | 1 - core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php | 7 ++++++- core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php | 5 ++--- core/modules/block/src/BlockViewBuilder.php | 1 - core/modules/block/src/Tests/BlockViewBuilderTest.php | 1 - core/modules/block/tests/modules/block_test/block_test.module | 2 +- core/modules/system/src/Plugin/Block/SystemBrandingBlock.php | 6 +++--- core/modules/system/src/Plugin/Block/SystemMenuBlock.php | 5 +++-- core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php | 4 +--- 16 files changed, 25 insertions(+), 28 deletions(-) diff --git a/core/includes/common.inc b/core/includes/common.inc index 24ac99a..9bd3038 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -29,7 +29,6 @@ use Drupal\Core\PhpStorage\PhpStorageFactory; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Datetime\DrupalDateTime; -use Drupal\Core\EventSubscriber\HtmlViewSubscriber; use Drupal\Core\Routing\GeneratorNotInitializedException; use Drupal\Core\Template\Attribute; use Drupal\Core\Render\Element; @@ -3118,7 +3117,8 @@ function drupal_render_cache_set(&$markup, array $elements) { // Persist cache tags associated with this element. Also associate the // "rendered" cache tag. This allows us to invalidate the entire render cache, // regardless of the cache bin. - $data['#cache']['tags'] = Cache::mergeTags($elements['#cache']['tags'], ['rendered']); + $data['#cache']['tags'] = $elements['#cache']['tags']; + $data['#cache']['tags'][] = 'rendered'; $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'render'; $expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : Cache::PERMANENT; diff --git a/core/lib/Drupal/Core/Cache/ApcuBackend.php b/core/lib/Drupal/Core/Cache/ApcuBackend.php index f787401..199a134 100644 --- a/core/lib/Drupal/Core/Cache/ApcuBackend.php +++ b/core/lib/Drupal/Core/Cache/ApcuBackend.php @@ -189,7 +189,7 @@ protected function prepareItem($cache, $allow_invalid) { * {@inheritdoc} */ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) { - Cache::validateTags($tags); + $tags = Cache::mergeTags($tags, []); $cache = new \stdClass(); $cache->cid = $cid; $cache->created = round(microtime(TRUE), 3); diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php index 68d316c..a29ae57 100644 --- a/core/lib/Drupal/Core/Cache/Cache.php +++ b/core/lib/Drupal/Core/Cache/Cache.php @@ -22,7 +22,7 @@ class Cache { const PERMANENT = CacheBackendInterface::CACHE_PERMANENT; /** - * Merges arrays of cache tags. + * Merges arrays of cache tags and removes duplicates. * * The cache tags array is returned in a format that is valid for * \Drupal\Core\Cache\CacheBackendInterface::set(). diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index b243967..480c840 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -147,7 +147,7 @@ protected function prepareItem($cache, $allow_invalid) { * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) { - Cache::validateTags($tags); + $tags = Cache::mergeTags($tags, []); $try_again = FALSE; try { // The bin might not yet exist. @@ -234,7 +234,7 @@ public function setMultiple(array $items) { 'tags' => array(), ); - Cache::validateTags($item['tags']); + $item['tags'] = Cache::mergeTags($item['tags'], []); // Remove tags that were already deleted or invalidated during this // request from the static caches so that another deletion or diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php index a8814ac..ce74ff4 100644 --- a/core/lib/Drupal/Core/Cache/MemoryBackend.php +++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php @@ -107,13 +107,12 @@ protected function prepareItem($cache, $allow_invalid) { * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) { - Cache::validateTags($tags); $this->cache[$cid] = (object) array( 'cid' => $cid, 'data' => serialize($data), 'created' => REQUEST_TIME, 'expire' => $expire, - 'tags' => $tags, + 'tags' => Cache::mergeTags($tags, []), ); } diff --git a/core/lib/Drupal/Core/Cache/PhpBackend.php b/core/lib/Drupal/Core/Cache/PhpBackend.php index 26eaf7e..e7de3b6 100644 --- a/core/lib/Drupal/Core/Cache/PhpBackend.php +++ b/core/lib/Drupal/Core/Cache/PhpBackend.php @@ -138,9 +138,8 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array 'data' => $data, 'created' => round(microtime(TRUE), 3), 'expire' => $expire, - 'tags' => $tags, + 'tags' => Cache::mergeTags($tags, []), ); - Cache::validateTags($item->tags); $this->writeItem($this->normalizeCid($cid), $item); } diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index a2cf4fa..fc289d2 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -9,7 +9,6 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\DependencyInjection\DependencySerializationTrait; -use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Component\Utility\Unicode; use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException; @@ -473,7 +472,7 @@ protected function invalidateTagsOnSave($update) { $tags = $this->getListCacheTags(); if ($update) { // An existing entity was updated, also invalidate its unique cache tag. - $tags = NestedArray::mergeDeep($tags, $this->getCacheTag()); + $tags = Cache::mergeTags($tags, $this->getCacheTag()); $this->onUpdateBundleEntity(); } Cache::invalidateTags($tags); diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php index e989182..e24735a 100644 --- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php @@ -7,7 +7,6 @@ namespace Drupal\Core\Entity; -use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Field\FieldItemInterface; diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php index 77bfc3c..164f7f5 100644 --- a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php +++ b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php @@ -72,7 +72,12 @@ public function render(HtmlFragmentInterface $fragment, $status_code = 200) { // Persist cache tags associated with this page. Also associate the // "rendered" cache tag. This allows us to invalidate the entire render // cache, regardless of the cache bin. - $page->setCacheTags(Cache::mergeTags($page_array['#cache']['tags'], ['rendered'])); + $cache_tags = $page_array['#cache']['tags']; + $cache_tags[] = 'rendered'; + // Only keep unique cache tags. We need to prevent duplicates here already + // rather than only in the cache layer, because they are also used by + // reverse proxies (like Varnish), not only by Drupal's page cache. + $page->setCacheTags(array_unique($cache_tags)); } return $page; diff --git a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php index 65f95f1..f28ff0d 100644 --- a/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php +++ b/core/modules/aggregator/src/Plugin/Block/AggregatorFeedBlock.php @@ -7,10 +7,10 @@ namespace Drupal\aggregator\Plugin\Block; -use Drupal\Component\Utility\NestedArray; use Drupal\aggregator\FeedStorageInterface; use Drupal\aggregator\ItemStorageInterface; use Drupal\Core\Block\BlockBase; +use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; @@ -195,8 +195,7 @@ public function build() { public function getCacheTags() { $cache_tags = parent::getCacheTags(); $feed = $this->feedStorage->load($this->configuration['feed']); - $cache_tags = NestedArray::mergeDeep($cache_tags, $feed->getCacheTag()); - return $cache_tags; + return Cache::mergeTags($cache_tags, $feed->getCacheTag()); } } diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php index c3d6147..25a2a2c 100644 --- a/core/modules/block/src/BlockViewBuilder.php +++ b/core/modules/block/src/BlockViewBuilder.php @@ -7,7 +7,6 @@ namespace Drupal\block; -use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityViewBuilder; diff --git a/core/modules/block/src/Tests/BlockViewBuilderTest.php b/core/modules/block/src/Tests/BlockViewBuilderTest.php index a115c6d..b2dde86 100644 --- a/core/modules/block/src/Tests/BlockViewBuilderTest.php +++ b/core/modules/block/src/Tests/BlockViewBuilderTest.php @@ -8,7 +8,6 @@ namespace Drupal\block\Tests; use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\UrlCacheContext; use Drupal\simpletest\DrupalUnitTestBase; diff --git a/core/modules/block/tests/modules/block_test/block_test.module b/core/modules/block/tests/modules/block_test/block_test.module index 19e65ad..cec0b24 100644 --- a/core/modules/block/tests/modules/block_test/block_test.module +++ b/core/modules/block/tests/modules/block_test/block_test.module @@ -28,7 +28,7 @@ function block_test_block_view_test_cache_alter(array &$build, BlockPluginInterf $build['#cache']['keys'][] = \Drupal::state()->get('block_test_view_alter_cache_key'); } if (\Drupal::state()->get('block_test_view_alter_cache_tag') !== NULL) { - $build['#cache']['tags'] = Cache::mergeTags($build['#cache']['tags'], [\Drupal::state()->get('block_test_view_alter_cache_tag')]); + $build['#cache']['tags'][] = \Drupal::state()->get('block_test_view_alter_cache_tag'); } if (\Drupal::state()->get('block_test_view_alter_append_pre_render_prefix') !== NULL) { $build['#pre_render'][] = 'block_test_pre_render_alter_content'; diff --git a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php index e65109e..6d10aff 100644 --- a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php @@ -7,9 +7,7 @@ namespace Drupal\system\Plugin\Block; -use Drupal\Component\Utility\NestedArray; use Drupal\Core\Block\BlockBase; -use Drupal\Core\Cache\Cache; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; @@ -193,7 +191,9 @@ public function build() { public function getCacheTags() { // The theme-specific cache tag is set automatically for each block, but the // output of this block also depends on the global theme settings. - return Cache::mergeTags(parent::getCacheTags(), ['theme_global_setting']); + $cache_tags = parent::getCacheTags(); + $cache_tags[] = 'theme_global_setting'; + return $cache_tags; } /** diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php index fc57930..16af329 100644 --- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -7,7 +7,6 @@ namespace Drupal\system\Plugin\Block; -use Drupal\Component\Utility\NestedArray; use Drupal\Core\Block\BlockBase; use Drupal\Core\Cache\Cache; use Drupal\Core\Form\FormStateInterface; @@ -190,7 +189,9 @@ public function getCacheTags() { // the cache tag for this menu to be set: whenever the menu is changed, this // menu block must also be re-rendered for that user, because maybe a menu // link that is accessible for that user has been added. - return Cache::mergeTags(parent::getCacheTags(), ['menu:' . $this->getDerivativeId()]); + $cache_tags = parent::getCacheTags(); + $cache_tags[] = 'menu:' . $this->getDerivativeId(); + return $cache_tags; } /** diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php index c2db659..1fa0d93 100644 --- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php @@ -7,10 +7,8 @@ namespace Drupal\system\Tests\Entity; -use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\EventSubscriber\HtmlViewSubscriber; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\system\Tests\Cache\PageCacheTagsTestBase; @@ -467,7 +465,7 @@ public function testReferencedEntity() { $this->verifyPageCache($non_referencing_entity_path, 'HIT'); // Verify cache hits. - $referencing_entity_cache_tags = NestedArray::mergeDeep( + $referencing_entity_cache_tags = Cache::mergeTags( $this->referencing_entity->getCacheTag(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTag() );