summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2017-02-10 10:45:01 +0000
committerAlex Pott2017-02-10 10:45:01 +0000
commit172e9e38cc95a7aa1fabd4a2b7122a7b4b5d6764 (patch)
tree2cc022767e0446fcac4b6eb101c7a5de2688e840
parent7f3c710febfb484431687b5d5919712bf3034834 (diff)
Issue #2815845 by dawehner, Wim Leers, alexpott, tedbow, Berdir, swentel, webflo: Importing (deploying) REST resource config entities should automatically do the necessary route rebuilding
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php4
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php18
-rw-r--r--core/modules/block/src/Tests/BlockTest.php2
-rw-r--r--core/modules/block/src/Tests/Views/DisplayBlockTest.php10
-rw-r--r--core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php3
-rw-r--r--core/modules/node/src/Tests/Views/FrontPageTest.php5
-rw-r--r--core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php2
-rw-r--r--core/modules/page_cache/src/Tests/PageCacheTest.php2
-rw-r--r--core/modules/rest/rest.services.yml7
-rw-r--r--core/modules/rest/src/Entity/RestResourceConfig.php19
-rw-r--r--core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php53
-rw-r--r--core/modules/rest/src/Tests/RESTTestBase.php3
-rw-r--r--core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php4
-rw-r--r--core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php39
-rw-r--r--core/modules/rest/tests/src/Functional/ResourceTestBase.php22
-rw-r--r--core/modules/search/src/Tests/SearchPageCacheTagsTest.php9
-rw-r--r--core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php8
-rw-r--r--core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php4
-rw-r--r--core/modules/system/src/Tests/Routing/RouterTest.php10
-rw-r--r--core/modules/tour/src/Tests/TourCacheTagsTest.php2
-rw-r--r--core/modules/views/src/Tests/GlossaryTest.php1
-rw-r--r--core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php2
22 files changed, 188 insertions, 41 deletions
diff --git a/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php
index 38007f5..c1f5327 100644
--- a/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php
@@ -16,8 +16,8 @@ class CacheRouterRebuildSubscriber implements EventSubscriberInterface {
*/
public function onRouterFinished() {
// Requested URLs that formerly gave a 403/404 may now be valid.
- // Also invalidate all cached routing.
- Cache::invalidateTags(['4xx-response', 'route_match']);
+ // Also invalidate all cached routing as well as every HTTP response.
+ Cache::invalidateTags(['4xx-response', 'route_match', 'http_response']);
}
/**
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 3db181a..5898d17 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -89,6 +89,21 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
}
/**
+ * Sets extra headers on any responses, also subrequest ones.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+ * The event to process.
+ */
+ public function onAllResponds(FilterResponseEvent $event) {
+ $response = $event->getResponse();
+ // Always add the 'http_response' cache tag to be able to invalidate every
+ // response, for example after rebuilding routes.
+ if ($response instanceof CacheableResponseInterface) {
+ $response->getCacheableMetadata()->addCacheTags(['http_response']);
+ }
+ }
+
+ /**
* Sets extra headers on successful responses.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
@@ -284,6 +299,9 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
*/
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = array('onRespond');
+ // There is no specific reason for choosing 16 beside it should be executed
+ // before ::onRespond().
+ $events[KernelEvents::RESPONSE][] = array('onAllResponds', 16);
return $events;
}
diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php
index 9fd869a..57f4647 100644
--- a/core/modules/block/src/Tests/BlockTest.php
+++ b/core/modules/block/src/Tests/BlockTest.php
@@ -385,6 +385,7 @@ class BlockTest extends BlockTestBase {
'block_view',
'config:block.block.powered',
'config:user.role.anonymous',
+ 'http_response',
'rendered',
);
sort($expected_cache_tags);
@@ -426,6 +427,7 @@ class BlockTest extends BlockTestBase {
'config:block.block.powered',
'config:block.block.powered-2',
'config:user.role.anonymous',
+ 'http_response',
'rendered',
);
sort($expected_cache_tags);
diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
index 368af68..d878175 100644
--- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
@@ -262,7 +262,7 @@ class DisplayBlockTest extends ViewTestBase {
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
$this->assertTrue(empty($result), 'The title is not visible.');
- $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' , 'rendered']));
+ $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
}
/**
@@ -288,7 +288,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
// Ensure that the view cachability metadata is propagated even, for an
// empty block.
- $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'rendered']));
+ $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Add a header displayed on empty result.
@@ -306,7 +306,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet($url);
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
- $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'rendered']));
+ $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Hide the header on empty results.
@@ -324,7 +324,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet($url);
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
- $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'rendered']));
+ $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
// Add an empty text.
@@ -341,7 +341,7 @@ class DisplayBlockTest extends ViewTestBase {
$this->drupalGet($url);
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
- $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'rendered']));
+ $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
}
diff --git a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
index 3ad4ad1..bba47d5 100644
--- a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
@@ -46,6 +46,7 @@ class MenuCacheTagsTest extends PageCacheTagsTestBase {
// Verify a cache hit, but also the presence of the correct cache tags.
$expected_tags = array(
+ 'http_response',
'rendered',
'block_view',
'config:block_list',
@@ -107,7 +108,7 @@ class MenuCacheTagsTest extends PageCacheTagsTestBase {
$this->verifyPageCache($url, 'MISS');
// Verify a cache hit.
- $this->verifyPageCache($url, 'HIT', ['config:block_list', 'config:user.role.anonymous', 'rendered']);
+ $this->verifyPageCache($url, 'HIT', ['config:block_list', 'config:user.role.anonymous', 'http_response', 'rendered']);
}
}
diff --git a/core/modules/node/src/Tests/Views/FrontPageTest.php b/core/modules/node/src/Tests/Views/FrontPageTest.php
index b27c416..19cb659 100644
--- a/core/modules/node/src/Tests/Views/FrontPageTest.php
+++ b/core/modules/node/src/Tests/Views/FrontPageTest.php
@@ -265,7 +265,7 @@ class FrontPageTest extends ViewTestBase {
$render_cache_tags
);
$expected_tags = Cache::mergeTags($empty_node_listing_cache_tags, $cache_context_tags);
- $expected_tags = Cache::mergeTags($expected_tags, ['rendered', 'config:user.role.anonymous', 'config:system.site']);
+ $expected_tags = Cache::mergeTags($expected_tags, ['http_response', 'rendered', 'config:user.role.anonymous', 'config:system.site']);
$this->assertPageCacheContextsAndTags(
Url::fromRoute('view.frontpage.page_1'),
$cache_contexts,
@@ -331,7 +331,7 @@ class FrontPageTest extends ViewTestBase {
$this->assertPageCacheContextsAndTags(
Url::fromRoute('view.frontpage.page_1'),
$cache_contexts,
- Cache::mergeTags($first_page_output_cache_tags, ['rendered', 'config:user.role.anonymous'])
+ Cache::mergeTags($first_page_output_cache_tags, ['http_response', 'rendered', 'config:user.role.anonymous'])
);
// Second page.
@@ -350,6 +350,7 @@ class FrontPageTest extends ViewTestBase {
'node_view',
'user_view',
'user:0',
+ 'http_response',
'rendered',
// FinishResponseSubscriber adds this cache tag to responses that have the
// 'user.permissions' cache context for anonymous users.
diff --git a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
index f9fd3de..2c945fd 100644
--- a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
@@ -80,6 +80,7 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
// Full node page 1.
$this->assertPageCacheContextsAndTags($node_1->urlInfo(), $cache_contexts, array(
+ 'http_response',
'rendered',
'block_view',
'config:block_list',
@@ -120,6 +121,7 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
// Full node page 2.
$this->assertPageCacheContextsAndTags($node_2->urlInfo(), $cache_contexts, array(
+ 'http_response',
'rendered',
'block_view',
'config:block_list',
diff --git a/core/modules/page_cache/src/Tests/PageCacheTest.php b/core/modules/page_cache/src/Tests/PageCacheTest.php
index 3a7cd17..d4fae54 100644
--- a/core/modules/page_cache/src/Tests/PageCacheTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTest.php
@@ -63,6 +63,7 @@ class PageCacheTest extends WebTestBase {
sort($cache_entry->tags);
$expected_tags = array(
'config:user.role.anonymous',
+ 'http_response',
'pre_render',
'rendered',
'system_test_cache_tags_page',
@@ -94,6 +95,7 @@ class PageCacheTest extends WebTestBase {
sort($cache_entry->tags);
$expected_tags = array(
'config:user.role.anonymous',
+ 'http_response',
'pre_render',
'rendered',
'system_test_cache_tags_page',
diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml
index 2def91e..7742e1d 100644
--- a/core/modules/rest/rest.services.yml
+++ b/core/modules/rest/rest.services.yml
@@ -35,8 +35,15 @@ services:
logger.channel.rest:
parent: logger.channel_base
arguments: ['rest']
+
+ # Event subscribers.
rest.resource_response.subscriber:
class: Drupal\rest\EventSubscriber\ResourceResponseSubscriber
tags:
- { name: event_subscriber }
arguments: ['@serializer', '@renderer', '@current_route_match']
+ rest.config_subscriber:
+ class: Drupal\rest\EventSubscriber\RestConfigSubscriber
+ arguments: ['@router.builder']
+ tags:
+ - { name: event_subscriber }
diff --git a/core/modules/rest/src/Entity/RestResourceConfig.php b/core/modules/rest/src/Entity/RestResourceConfig.php
index bb83584..12bd846 100644
--- a/core/modules/rest/src/Entity/RestResourceConfig.php
+++ b/core/modules/rest/src/Entity/RestResourceConfig.php
@@ -3,6 +3,7 @@
namespace Drupal\rest\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
use Drupal\rest\RestResourceConfigInterface;
@@ -255,4 +256,22 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
return strtoupper($method);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
+ parent::postSave($storage, $update);
+
+ \Drupal::service('router.builder')->setRebuildNeeded();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function postDelete(EntityStorageInterface $storage, array $entities) {
+ parent::postDelete($storage, $entities);
+
+ \Drupal::service('router.builder')->setRebuildNeeded();
+ }
+
}
diff --git a/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php b/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php
new file mode 100644
index 0000000..abab34a
--- /dev/null
+++ b/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\rest\EventSubscriber;
+
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\Routing\RouteBuilderInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * A subscriber triggering a route rebuild when certain configuration changes.
+ */
+class RestConfigSubscriber implements EventSubscriberInterface {
+
+ /**
+ * The router builder.
+ *
+ * @var \Drupal\Core\Routing\RouteBuilderInterface
+ */
+ protected $routerBuilder;
+
+ /**
+ * Constructs the RestConfigSubscriber.
+ *
+ * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+ * The router builder service.
+ */
+ public function __construct(RouteBuilderInterface $router_builder) {
+ $this->routerBuilder = $router_builder;
+ }
+
+ /**
+ * Informs the router builder a rebuild is needed when necessary.
+ *
+ * @param \Drupal\Core\Config\ConfigCrudEvent $event
+ * The Event to process.
+ */
+ public function onSave(ConfigCrudEvent $event) {
+ $saved_config = $event->getConfig();
+ if ($saved_config->getName() === 'rest.settings' && $event->isChanged('bc_entity_resource_permissions')) {
+ $this->routerBuilder->setRebuildNeeded();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents() {
+ $events[ConfigEvents::SAVE][] = ['onSave'];
+ return $events;
+ }
+
+}
diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php
index 271df51..405493b 100644
--- a/core/modules/rest/src/Tests/RESTTestBase.php
+++ b/core/modules/rest/src/Tests/RESTTestBase.php
@@ -420,8 +420,7 @@ abstract class RESTTestBase extends WebTestBase {
* Rebuilds routing caches.
*/
protected function rebuildCache() {
- // Rebuild routing cache, so that the REST API paths are available.
- $this->container->get('router.builder')->rebuild();
+ $this->container->get('router.builder')->rebuildIfNeeded();
}
/**
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
index d87e423..0be7622 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php
@@ -122,9 +122,9 @@ abstract class BlockResourceTestBase extends EntityResourceTestBase {
protected function getExpectedCacheTags() {
// Because the 'user.permissions' cache context is missing, the cache tag
// for the anonymous user role is never added automatically.
- return array_filter(parent::getExpectedCacheTags(), function ($tag) {
+ return array_values(array_filter(parent::getExpectedCacheTags(), function ($tag) {
return $tag !== 'config:user.role.anonymous';
- });
+ }));
}
/**
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 2c95612..992e3b0 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -147,6 +147,15 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
}
/**
+ * Deprovisions the tested entity resource.
+ */
+ protected function deprovisionEntityResource() {
+ $this->resourceConfigStorage->load('entity.' . static::$entityTypeId)
+ ->delete();
+ $this->refreshTestStateAfterRestConfigChange();
+ }
+
+ /**
* {@inheritdoc}
*/
public function setUp() {
@@ -195,9 +204,6 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
}
$this->entity->save();
}
-
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
}
/**
@@ -291,6 +297,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
if (!static::$auth) {
$expected_cache_tags[] = 'config:user.role.anonymous';
}
+ $expected_cache_tags[] = 'http_response';
return Cache::mergeTags($expected_cache_tags, $this->entity->getCacheTags());
}
@@ -458,8 +465,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
+ $this->refreshTestStateAfterRestConfigChange();
// DX: 403 when unauthorized.
@@ -475,6 +481,20 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
$this->assertResourceResponse(200, FALSE, $response);
+ $this->deprovisionEntityResource();
+
+
+ // DX: upon deprovisioning, immediate 404 if no route, 406 otherwise.
+ $response = $this->request('GET', $url, $request_options);
+ if (!$has_canonical_url) {
+ $this->assertSame(404, $response->getStatusCode());
+ }
+ else {
+ $this->assert406Response($response);
+ }
+
+
+ $this->provisionEntityResource();
$url->setOption('query', ['_format' => 'non_existing_format']);
@@ -673,9 +693,8 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
+ $this->refreshTestStateAfterRestConfigChange();
$request_options[RequestOptions::BODY] = $parseable_valid_request_body_2;
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
// DX: 403 when unauthorized.
@@ -876,9 +895,8 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
+ $this->refreshTestStateAfterRestConfigChange();
$request_options[RequestOptions::BODY] = $parseable_valid_request_body_2;
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
// DX: 403 when unauthorized.
@@ -975,8 +993,7 @@ abstract class EntityResourceTestBase extends ResourceTestBase {
$this->config('rest.settings')->set('bc_entity_resource_permissions', TRUE)->save(TRUE);
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
+ $this->refreshTestStateAfterRestConfigChange();
$this->entity = $this->createEntity();
$url = $this->getUrl()->setOption('query', $url->getOption('query'));
diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
index 2674d70..d0f601b 100644
--- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php
@@ -119,6 +119,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
// Ensure there's a clean slate: delete all REST resource config entities.
$this->resourceConfigStorage->delete($this->resourceConfigStorage->loadMultiple());
+ $this->refreshTestStateAfterRestConfigChange();
}
/**
@@ -141,8 +142,25 @@ abstract class ResourceTestBase extends BrowserTestBase {
'authentication' => $authentication,
]
])->save();
- // @todo Remove this in https://www.drupal.org/node/2815845.
- drupal_flush_all_caches();
+ $this->refreshTestStateAfterRestConfigChange();
+ }
+
+ /**
+ * Refreshes the state of the tester to be in sync with the testee.
+ *
+ * Should be called after every change made to:
+ * - RestResourceConfig entities
+ * - the 'rest.settings' simple configuration
+ */
+ protected function refreshTestStateAfterRestConfigChange() {
+ // Ensure that the cache tags invalidator has its internal values reset.
+ // Otherwise the http_response cache tag invalidation won't work.
+ $this->refreshVariables();
+
+ // Tests using this base class may trigger route rebuilds due to changes to
+ // RestResourceConfig entities or 'rest.settings'. Ensure the test generates
+ // routes using an up-to-date router.
+ \Drupal::service('router.builder')->rebuildIfNeeded();
}
/**
diff --git a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php
index 3a7bc67..667b213 100644
--- a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php
+++ b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php
@@ -70,6 +70,7 @@ class SearchPageCacheTagsTest extends SearchTestBase {
$this->assertCacheTag('node:1');
$this->assertCacheTag('user:2');
$this->assertCacheTag('rendered');
+ $this->assertCacheTag('http_response');
$this->assertCacheTag('node_list');
// Updating a node should invalidate the search plugin's index cache tag.
@@ -83,6 +84,7 @@ class SearchPageCacheTagsTest extends SearchTestBase {
$this->assertCacheTag('node:1');
$this->assertCacheTag('user:2');
$this->assertCacheTag('rendered');
+ $this->assertCacheTag('http_response');
$this->assertCacheTag('node_list');
// Deleting a node should invalidate the search plugin's index cache tag.
@@ -172,6 +174,7 @@ class SearchPageCacheTagsTest extends SearchTestBase {
'config:search.page.node_search',
'search_index',
'search_index:node_search',
+ 'http_response',
'rendered',
'node_list',
];
@@ -192,8 +195,7 @@ class SearchPageCacheTagsTest extends SearchTestBase {
'node_view',
'config:filter.format.plain_text',
]);
- $cache_tags = $this->drupalGetHeader('X-Drupal-Cache-Tags');
- $this->assertEqual(explode(' ', $cache_tags), $expected_cache_tags);
+ $this->assertCacheTags($expected_cache_tags);
// Only get the new node in the search results, should result in node:1,
// node:2 and user:3 as cache tags even though only node:1 is shown. This is
@@ -208,8 +210,7 @@ class SearchPageCacheTagsTest extends SearchTestBase {
'user:3',
'node_view',
]);
- $cache_tags = $this->drupalGetHeader('X-Drupal-Cache-Tags');
- $this->assertEqual(explode(' ', $cache_tags), $expected_cache_tags);
+ $this->assertCacheTags($expected_cache_tags);
}
}
diff --git a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
index 94ea1ac..c216e9b 100644
--- a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
+++ b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php
@@ -122,10 +122,14 @@ trait AssertPageCacheContextsAndTagsTrait {
*/
protected function assertCacheTags(array $expected_tags, $include_default_tags = TRUE) {
// The anonymous role cache tag is only added if the user is anonymous.
- if ($include_default_tags && \Drupal::currentUser()->isAnonymous()) {
- $expected_tags = Cache::mergeTags($expected_tags, ['config:user.role.anonymous']);
+ if ($include_default_tags) {
+ if (\Drupal::currentUser()->isAnonymous()) {
+ $expected_tags = Cache::mergeTags($expected_tags, ['config:user.role.anonymous']);
+ }
+ $expected_tags[] = 'http_response';
}
$actual_tags = $this->getCacheHeaderValues('X-Drupal-Cache-Tags');
+ $expected_tags = array_unique($expected_tags);
sort($expected_tags);
sort($actual_tags);
$this->assertIdentical($actual_tags, $expected_tags);
diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
index 9ecefad..c5e9a95 100644
--- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
+++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
@@ -343,7 +343,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
// '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.
- $page_cache_tags = Cache::mergeTags(['rendered'], ['config:user.role.anonymous']);
+ $page_cache_tags = Cache::mergeTags(['http_response', 'rendered'], ['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.
$page_cache_tags = Cache::mergeTags($page_cache_tags, \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []);
@@ -641,7 +641,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
// Verify cache hits.
$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, ['rendered']);
+ $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($nonempty_entity_listing_cache_tags, $page_cache_tags);
diff --git a/core/modules/system/src/Tests/Routing/RouterTest.php b/core/modules/system/src/Tests/Routing/RouterTest.php
index 1b33baf..c6aa2b8 100644
--- a/core/modules/system/src/Tests/Routing/RouterTest.php
+++ b/core/modules/system/src/Tests/Routing/RouterTest.php
@@ -45,7 +45,7 @@ class RouterTest extends WebTestBase {
// Check expected headers from FinishResponseSubscriber.
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', $expected_cache_contexts));
- $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous rendered');
+ $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous http_response rendered');
// Confirm that the page wrapping is being added, so we're not getting a
// raw body returned.
$this->assertRaw('</html>', 'Page markup was found.');
@@ -60,12 +60,12 @@ class RouterTest extends WebTestBase {
$this->drupalGet('router_test/test18');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url'])));
- $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered');
+ $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo http_response rendered');
// 2. controller result: render array, per-role cacheable route access.
$this->drupalGet('router_test/test19');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url', 'user.roles'])));
- $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered');
+ $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo http_response rendered');
// 3. controller result: Response object, globally cacheable route access.
$this->drupalGet('router_test/test1');
$headers = $this->drupalGetHeaders();
@@ -80,12 +80,12 @@ class RouterTest extends WebTestBase {
$this->drupalGet('router_test/test21');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], '');
- $this->assertEqual($headers['x-drupal-cache-tags'], '');
+ $this->assertEqual($headers['x-drupal-cache-tags'], 'http_response');
// 6. controller result: CacheableResponse object, per-role cacheable route access.
$this->drupalGet('router_test/test22');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], 'user.roles');
- $this->assertEqual($headers['x-drupal-cache-tags'], '');
+ $this->assertEqual($headers['x-drupal-cache-tags'], 'http_response');
// Finally, verify that the X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags
// headers are not sent when their container parameter is set to FALSE.
diff --git a/core/modules/tour/src/Tests/TourCacheTagsTest.php b/core/modules/tour/src/Tests/TourCacheTagsTest.php
index 4f2164e..7a2e87d 100644
--- a/core/modules/tour/src/Tests/TourCacheTagsTest.php
+++ b/core/modules/tour/src/Tests/TourCacheTagsTest.php
@@ -48,6 +48,7 @@ class TourCacheTagsTest extends PageCacheTagsTestBase {
$expected_tags = [
'config:tour.tour.tour-test',
'config:user.role.anonymous',
+ 'http_response',
'rendered',
];
$this->verifyPageCache($url, 'HIT', $expected_tags);
@@ -68,6 +69,7 @@ class TourCacheTagsTest extends PageCacheTagsTestBase {
// Verify a cache hit.
$expected_tags = [
'config:user.role.anonymous',
+ 'http_response',
'rendered',
];
$this->verifyPageCache($url, 'HIT', $expected_tags);
diff --git a/core/modules/views/src/Tests/GlossaryTest.php b/core/modules/views/src/Tests/GlossaryTest.php
index 508a4eb..2a5bc90 100644
--- a/core/modules/views/src/Tests/GlossaryTest.php
+++ b/core/modules/views/src/Tests/GlossaryTest.php
@@ -95,6 +95,7 @@ class GlossaryTest extends ViewTestBase {
'node_list',
'user:0',
'user_list',
+ 'http_response',
'rendered',
// FinishResponseSubscriber adds this cache tag to responses that have the
// 'user.permissions' cache context for anonymous users.
diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
index 199d257..25d1c70 100644
--- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php
@@ -43,7 +43,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
$this->assertNotContains('</html>', $text);
// Response includes cache tags that we can assert.
- $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'rendered');
+ $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'http_response rendered');
// Test that we can read the JS settings.
$js_settings = $this->getDrupalSettings();