core/core.services.yml | 2 +- .../Render/MainContent/SmartCacheHtmlRenderer.php | 11 +- .../src/Tests/BlockContentCacheTagsTest.php | 2 +- .../comment/src/Tests/CommentCacheTagsTest.php | 6 +- core/modules/filter/src/Tests/FilterAPITest.php | 1 + .../menu_ui/src/Tests/MenuCacheTagsTest.php | 3 +- .../modules/node/src/Tests/NodeListBuilderTest.php | 2 +- .../src/Tests/Cache/SmartCacheIntegrationTest.php | 128 +++++++++++++++++++++ .../src/Tests/Entity/EntityCacheTagsTestBase.php | 17 ++- .../src/Tests/Entity/EntityListBuilderTest.php | 2 +- .../src/Tests/Entity/EntityViewBuilderTest.php | 6 +- .../Entity/EntityWithUriCacheTagsTestBase.php | 2 +- .../smart_cache_test/smart_cache_test.info.yml | 6 + .../smart_cache_test/smart_cache_test.routing.yml | 45 ++++++++ .../src/SmartCacheTestController.php | 51 ++++++++ core/modules/tour/src/Tests/TourCacheTagsTest.php | 2 + sites/default/default.services.yml | 4 +- 17 files changed, 269 insertions(+), 21 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index ac85799..c76b1f3 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -2,7 +2,7 @@ parameters: session.storage.options: {} twig.config: {} renderer.config: - required_cache_contexts: ['languages:language_interface', 'theme'] + required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions'] factory.keyvalue: default: keyvalue.database factory.keyvalue.expirable: diff --git a/core/lib/Drupal/Core/Render/MainContent/SmartCacheHtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/SmartCacheHtmlRenderer.php index 79c727a..715461a 100644 --- a/core/lib/Drupal/Core/Render/MainContent/SmartCacheHtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/SmartCacheHtmlRenderer.php @@ -89,8 +89,10 @@ public function __construct(TitleResolverInterface $title_resolver, PluginManage */ protected function finish(array $html) { // If this is a #type => html render array that comes from SmartCache - // already, then there is no point in + // already, then we can return early: no need to redo all the work. if (isset($html['#smartcache'])) { + // Mark the response as a cache hit. + $html['#attached']['http_header'][] = ['X-Drupal-SmartCache', 'HIT']; return parent::finish($html); } @@ -168,6 +170,13 @@ protected function finish(array $html) { $cid = 'smartcache:html_render_array:' . implode(':', $this->cacheContextsManager->convertTokensToKeys($html_cache_contexts)); $expire = ($html_cache_max_age === Cache::PERMANENT) ? Cache::PERMANENT : (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME') + $html_cache_max_age; $this->smartHtmlCache->set($cid, $cacheable_html, $expire, $html_cache_tags); + + // Now that the cacheable HTML is cached, mark the response as a cache miss. + $cacheable_html['#attached']['http_header'][] = ['X-Drupal-SmartCache', 'MISS']; + } + else { + // Now that the cacheable HTML is cached, mark the response as a cache miss. + $cacheable_html['#attached']['http_header'][] = ['X-Drupal-SmartCache', 'UNCACHEABLE']; } return parent::finish($cacheable_html); diff --git a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php index 582d832..c8044dc 100644 --- a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php @@ -90,7 +90,7 @@ public function testBlock() { // Expected keys, contexts, and tags for the block. // @see \Drupal\block\BlockViewBuilder::viewMultiple() $expected_block_cache_keys = ['entity_view', 'block', $block->id()]; - $expected_block_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']; + $expected_block_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; $expected_block_cache_tags = Cache::mergeTags(['block_view', 'rendered'], $block->getCacheTags(), $block->getPlugin()->getCacheTags()); // Expected contexts and tags for the BlockContent entity. diff --git a/core/modules/comment/src/Tests/CommentCacheTagsTest.php b/core/modules/comment/src/Tests/CommentCacheTagsTest.php index 5226434..2393d96 100644 --- a/core/modules/comment/src/Tests/CommentCacheTagsTest.php +++ b/core/modules/comment/src/Tests/CommentCacheTagsTest.php @@ -86,11 +86,7 @@ protected function createEntity() { * {@inheritdoc} */ protected function getAdditionalCacheContextsForEntity(EntityInterface $entity) { - return [ - // Field access for the user picture rendered as part of the node that - // this comment is created on. - 'user.permissions', - ]; + return []; } /** diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php index 483bc22..4923962 100644 --- a/core/modules/filter/src/Tests/FilterAPITest.php +++ b/core/modules/filter/src/Tests/FilterAPITest.php @@ -264,6 +264,7 @@ function testProcessedTextElement() { // The default cache contexts for Renderer. 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', + 'user.permissions', ]; $this->assertEqual($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.'); $expected_markup = '

Hello, world!

This is a dynamic llama.

'; diff --git a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php index 45a9df7..e0c0fc7 100644 --- a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php +++ b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php @@ -54,6 +54,7 @@ public function testMenuBlock() { 'config:block_list', 'config:block.block.' . $block->id(), 'config:system.menu.llama', + 'config:user.role.anonymous', ); $this->verifyPageCache($url, 'HIT', $expected_tags); @@ -107,7 +108,7 @@ public function testMenuBlock() { $this->verifyPageCache($url, 'MISS'); // Verify a cache hit. - $this->verifyPageCache($url, 'HIT', ['config:block_list', 'rendered']); + $this->verifyPageCache($url, 'HIT', ['config:block_list', 'config:user.role.anonymous', 'rendered']); } } diff --git a/core/modules/node/src/Tests/NodeListBuilderTest.php b/core/modules/node/src/Tests/NodeListBuilderTest.php index 798a056..2d23604 100644 --- a/core/modules/node/src/Tests/NodeListBuilderTest.php +++ b/core/modules/node/src/Tests/NodeListBuilderTest.php @@ -39,7 +39,7 @@ public function testCacheContexts() { $build = $list_builder->render(); $this->container->get('renderer')->renderRoot($build); - $this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view'], $build['#cache']['contexts']); + $this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $build['#cache']['contexts']); } } diff --git a/core/modules/system/src/Tests/Cache/SmartCacheIntegrationTest.php b/core/modules/system/src/Tests/Cache/SmartCacheIntegrationTest.php new file mode 100644 index 0000000..5845969 --- /dev/null +++ b/core/modules/system/src/Tests/Cache/SmartCacheIntegrationTest.php @@ -0,0 +1,128 @@ +uninstall(['page_cache']); + } + + /** + * Tests that SmartCache works correctly, and verifies the edge cases. + */ + function testSmartCache() { + // Controllers returning response objects are ignored by SmartCache. + $url = Url::fromUri('route:smart_cache_test.response'); + $this->drupalGet($url); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Response object returned: SmartCache is ignoring.'); + + // Controllers returning render arrays, rendered as HTML responses, are + // handled by SmartCache. + $url = Url::fromUri('route:smart_cache_test.html'); + $this->drupalGet($url); + $this->assertEqual('MISS', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response: SmartCache is active, SmartCache MISS.'); + $this->assertSmartCache($url, [], []); + $this->drupalGet($url); + $this->assertEqual('HIT', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response: SmartCache is active, SmartCache HIT.'); + + // The above is the simple case, where the render array returned by the + // response contains no cache contexts. So let's now test a route/controller + // that *does* vary by a cache context whose value we can easily control: it + // varies by the 'animal' query argument. + foreach (['llama', 'piggy', 'unicorn', 'kitten'] as $animal) { + $url = Url::fromUri('route:smart_cache_test.html.with_cache_contexts', ['query' => ['animal' => $animal]]); + $this->drupalGet($url); + $this->assertEqual('MISS', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response: SmartCache is active, SmartCache MISS.'); + $this->assertSmartCache($url, ['url.query_args:animal'], [$animal]); + $this->drupalGet($url); + $this->assertEqual('HIT', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response: SmartCache is active, SmartCache HIT.'); + + // Finally, let's also verify that the 'smart_cache_test.html' route + // continued to see cache hits if we specify a query argument, because it + // *should* ignore it and continue to provide SmartCache hits. + $url = Url::fromUri('route:smart_cache_test.html', ['query' => ['animal' => 'piglet']]); + $this->drupalGet($url); + $this->assertEqual('HIT', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response: SmartCache is active, SmartCache HIT.'); + } + + // Controllers returning render arrays, rendered as anything except a HTML + // response, are ignored by SmartCache. + $this->drupalGet('smart-cache-test/html', array('query' => array(MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax'))); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as AJAX response: SmartCache is ignoring.'); + $this->drupalGet('smart-cache-test/html', array('query' => array(MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog'))); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as dialog response: SmartCache is ignoring.'); + $this->drupalGet('smart-cache-test/html', array('query' => array(MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal'))); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as modal response: SmartCache is ignoring.'); + + // Admin routes are ignored by SmartCache. + $this->drupalGet('smart-cache-test/html/admin'); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Response returned, rendered as HTML response, admin route: SmartCache is ignoring'); + $this->drupalGet('smart-cache-test/response/admin'); + $this->assertFalse($this->drupalGetHeader('X-Drupal-SmartCache'), 'Response returned, admin route: SmartCache is ignoring'); + + // Max-age = 0 responses are ignored by SmartCache. + $this->drupalGet('smart-cache-test/html/uncacheable'); + $this->assertEqual('UNCACHEABLE', $this->drupalGetHeader('X-Drupal-SmartCache'), 'Render array returned, rendered as HTML response, but uncacheable: SmartCache is running, but not caching.'); + } + + /** + * Asserts SmartCache cache items. + * + * @param \Drupal\Core\Url $url + * The URL to test. + * @param string[] $expected_cache_contexts + * The expected cache contexts for the given URL. + * @param string[] $cid_parts_for_cache_contexts + * The CID parts corresponding to the values in $expected_cache_contexts. + */ + protected function assertSmartCache(Url $url, array $expected_cache_contexts, array $cid_parts_for_cache_contexts) { + // Assert SmartCache contexts item. + $cid_parts = ['smartcache', 'contexts', $url->getRouteName() . hash('sha256', serialize($url->getRouteParameters()))]; + $cid = implode(':', $cid_parts); + $cache_item = \Drupal::cache('smart_cache_contexts')->get($cid); + $this->assertEqual($expected_cache_contexts, array_values(array_diff($cache_item->data, ['route']))); + + // Assert SmartCache html render array item. + $cid_parts = ['smartcache', 'html_render_array', $url->getRouteName() . hash('sha256', serialize($url->getRouteParameters()))]; + $cid_parts = array_merge($cid_parts, $cid_parts_for_cache_contexts); + $cid = implode(':', $cid_parts); + $cache_item = \Drupal::cache('smart_cache_html')->get($cid); + $this->assertTrue($cache_item->data['#type'] === 'html'); + } + +} diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php index 0b365cb..df593d8 100644 --- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php @@ -132,6 +132,8 @@ protected static function generateStandardizedInfo($entity_type_label, $group) { /** * Returns the access cache contexts for the tested entity. * + * Only list cache contexts that aren't part of the required cache contexts. + * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to be tested, as created by createEntity(). * @@ -141,12 +143,14 @@ protected static function generateStandardizedInfo($entity_type_label, $group) { * @see \Drupal\Core\Entity\EntityAccessControlHandlerInterface */ protected function getAccessCacheContextsForEntity(EntityInterface $entity) { - return ['user.permissions']; + return []; } /** * Returns the additional (non-standard) cache contexts for the tested entity. * + * Only list cache contexts that aren't part of the required cache contexts. + * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to be tested, as created by createEntity(). * @@ -331,12 +335,16 @@ public function testReferencedEntity() { $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]); // The default cache contexts for rendered entities. - $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']; + $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; $entity_cache_contexts = $default_cache_contexts; // Cache tags present on every rendered page. $page_cache_tags = Cache::mergeTags( ['rendered'], + // 'user.permissions' is a required cache context, and responses that vary + // by this cache context when requested by anonymous users automatically + // also get this cache tag, to ensure correct invalidation. + ['config:user.role.anonymous'], // 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']: [] @@ -387,9 +395,10 @@ public function testReferencedEntity() { $cache_keys = ['entity_view', 'entity_test', $this->referencingEntity->id(), 'full']; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $access_cache_contexts = $this->getAccessCacheContextsForEntity($this->entity); + $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->referencingEntity); $redirected_cid = NULL; - if (count($access_cache_contexts)) { - $redirected_cid = $this->createCacheId($cache_keys, Cache::mergeContexts($entity_cache_contexts, $this->getAdditionalCacheContextsForEntity($this->referencingEntity), $access_cache_contexts)); + if (count($access_cache_contexts) || count($additional_cache_contexts)) { + $redirected_cid = $this->createCacheId($cache_keys, Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts, $access_cache_contexts)); } $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid); diff --git a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php index 485e72c..e32b689 100644 --- a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php +++ b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php @@ -67,7 +67,7 @@ public function testCacheContexts() { $build = $list_builder->render(); $this->container->get('renderer')->renderRoot($build); - $this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0'], $build['#cache']['contexts']); + $this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']); } } diff --git a/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php b/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php index 333dcda..bf0512d 100644 --- a/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php +++ b/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php @@ -63,7 +63,7 @@ public function testEntityViewBuilderCache() { // Get a fully built entity view render array. $entity_test->save(); $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test, 'full'); - $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'])); + $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'])); $cid = implode(':', $cid_parts); $bin = $build['#cache']['bin']; @@ -113,7 +113,7 @@ public function testEntityViewBuilderCacheWithReferences() { // Get a fully built entity view render array for the referenced entity. $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test_reference, 'full'); - $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'])); + $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'])); $cid_reference = implode(':', $cid_parts); $bin_reference = $build['#cache']['bin']; @@ -132,7 +132,7 @@ public function testEntityViewBuilderCacheWithReferences() { // Get a fully built entity view render array. $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test, 'full'); - $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'])); + $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'])); $cid = implode(':', $cid_parts); $bin = $build['#cache']['bin']; diff --git a/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php index 0b6f430..47b551a 100644 --- a/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php @@ -32,7 +32,7 @@ public function testEntityUri() { $view_mode = $this->selectViewMode($entity_type); // The default cache contexts for rendered entities. - $entity_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']; + $entity_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; // Generate the standardized entity cache tags. $cache_tag = $this->entity->getCacheTags(); diff --git a/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.info.yml b/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.info.yml new file mode 100644 index 0000000..cfa52e2 --- /dev/null +++ b/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.info.yml @@ -0,0 +1,6 @@ +name: 'Test SmartCache' +type: module +description: 'Provides test routes/responses for SmartCache.' +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.routing.yml b/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.routing.yml new file mode 100644 index 0000000..c7164b2 --- /dev/null +++ b/core/modules/system/tests/modules/smart_cache_test/smart_cache_test.routing.yml @@ -0,0 +1,45 @@ +smart_cache_test.response: + path: '/smart-cache-test/response' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::response' + requirements: + _access: 'TRUE' + +smart_cache_test.response.admin: + path: '/smart-cache-test/response/admin' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::response' + requirements: + _access: 'TRUE' + options: + _admin_route: TRUE + +smart_cache_test.html: + path: '/smart-cache-test/html' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::html' + requirements: + _access: 'TRUE' + +smart_cache_test.html.admin: + path: '/smart-cache-test/html/admin' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::html' + requirements: + _access: 'TRUE' + options: + _admin_route: TRUE + +smart_cache_test.html.with_cache_contexts: + path: '/smart-cache-test/html/with-cache-contexts' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::htmlWithCacheContexts' + requirements: + _access: 'TRUE' + +smart_cache_test.html.uncacheable: + path: '/smart-cache-test/html/uncacheable' + defaults: + _controller: '\Drupal\smart_cache_test\SmartCacheTestController::htmlUncacheable' + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/modules/smart_cache_test/src/SmartCacheTestController.php b/core/modules/system/tests/modules/smart_cache_test/src/SmartCacheTestController.php new file mode 100644 index 0000000..28bb937 --- /dev/null +++ b/core/modules/system/tests/modules/smart_cache_test/src/SmartCacheTestController.php @@ -0,0 +1,51 @@ + [ + '#markup' => 'Hello world.', + ], + ]; + } + + public function htmlWithCacheContexts() { + $build = $this->html(); + $build['dynamic_part'] = [ + '#markup' => SafeMarkup::format('Hello there, %animal.', ['%animal' => \Drupal::requestStack()->getCurrentRequest()->query->get('animal')]), + '#cache' => [ + 'contexts' => [ + 'url.query_args:animal', + ], + ], + ]; + return $build; + } + + public function htmlUncacheable() { + $build = $this->html(); + $build['very_dynamic_part'] = [ + '#markup' => 'Drupal cannot handle the awesomeness of llamas.', + '#cache' => [ + 'max-age' => 0, + ], + ]; + return $build; + } + +} diff --git a/core/modules/tour/src/Tests/TourCacheTagsTest.php b/core/modules/tour/src/Tests/TourCacheTagsTest.php index 1c4c323..8d2814f 100644 --- a/core/modules/tour/src/Tests/TourCacheTagsTest.php +++ b/core/modules/tour/src/Tests/TourCacheTagsTest.php @@ -52,6 +52,7 @@ public function testRenderedTour() { // Verify a cache hit, but also the presence of the correct cache tags. $expected_tags = [ 'config:tour.tour.tour-test', + 'config:user.role.anonymous', 'rendered', ]; $this->verifyPageCache($url, 'HIT', $expected_tags); @@ -71,6 +72,7 @@ public function testRenderedTour() { // Verify a cache hit. $expected_tags = [ + 'config:user.role.anonymous', 'rendered', ]; $this->verifyPageCache($url, 'HIT', $expected_tags); diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml index c44c73b..3e813fa 100644 --- a/sites/default/default.services.yml +++ b/sites/default/default.services.yml @@ -82,8 +82,8 @@ parameters: # The Renderer will automatically associate these cache contexts with every # render array, hence varying every render array by these cache contexts. # - # @default ['languages:language_interface', 'theme'] - required_cache_contexts: ['languages:language_interface', 'theme'] + # @default ['languages:language_interface', 'theme', 'user.permissions'] + required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions'] factory.keyvalue: {} # Default key/value storage service to use.