From fa326794892593aa7165354ab02e08e6bc2c47a6 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Fri, 1 Nov 2013 11:15:22 +0000 Subject: [PATCH] Issue #2094241 by moshe weitzmann, amateescu, Wim Leers: Cache tag the page cache. --- core/includes/common.inc | 34 ++++++++++++++++++- .../node/lib/Drupal/node/NodeViewBuilder.php | 2 +- .../system/Tests/Bootstrap/PageCacheTest.php | 24 +++++++++++++ core/modules/system/system.module | 1 + .../Controller/SystemTestController.php | 11 ++++++ .../system_test/system_test.routing.yml | 7 ++++ 6 files changed, 77 insertions(+), 2 deletions(-) diff --git a/core/includes/common.inc b/core/includes/common.inc index 5749ffefc5e9..07b5db6610b0 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3182,7 +3182,7 @@ function drupal_page_set_cache(Response $response, Request $request) { // because by the time it is read, the configuration might change. 'page_compressed' => $page_compressed, ), - 'tags' => array('content' => TRUE), + 'tags' => array('content' => TRUE) + drupal_cache_tags_page_get(), 'expire' => CacheBackendInterface::CACHE_PERMANENT, 'created' => REQUEST_TIME, ); @@ -4218,6 +4218,38 @@ function drupal_render_collect_cache_tags($element, $tags = array()) { return $tags; } +/** + * A #post_render callback at the top level of the $page array. Collects the + * tags for use in page cache. + * + * @param string $children + * An HTML string of rendered output. + * @param array $elements + * A render array. + * + * @return string + * The same $children that was passed in - no modifications. + */ +function drupal_post_render_cache_tags_page_set($children, array $elements) { + if (drupal_page_is_cacheable()) { + $tags = &drupal_static('system_cache_tags_page', array()); + $tags = drupal_render_collect_cache_tags($elements); + } + return $children; +} + +/** + * Return the cache tags that were stored during drupal_render_page(). + * + * @return array + * An array of cache tags. + * + * @see drupal_post_render_cache_tags_page_set() + */ +function drupal_cache_tags_page_get() { + return drupal_static('system_cache_tags_page', array()); +} + /** * Prepares an element for caching based on a query. * diff --git a/core/modules/node/lib/Drupal/node/NodeViewBuilder.php b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php index 85511585d368..374ec6eff19e 100644 --- a/core/modules/node/lib/Drupal/node/NodeViewBuilder.php +++ b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php @@ -88,7 +88,7 @@ protected function alterBuild(array &$build, EntityInterface $entity, EntityDisp // The node 'submitted' info is not rendered in a standard way (renderable // array) so we have to add a cache tag manually. - $build['#cache']['tags']['user'][] = $entity->uid; + $build['#cache']['tags']['user'][] = $entity->getAuthorId(); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php index 89d8ff4ae65d..aec3355fca71 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php @@ -9,6 +9,7 @@ use Symfony\Component\Routing\RequestContext; use Drupal\simpletest\WebTestBase; +use Drupal\Core\Cache\Cache; /** * Enables the page cache and tests it with various HTTP requests. @@ -41,6 +42,29 @@ function setUp() { ->save(); } + /** + * Test that cache tags are properly persisted. + * + * Since tag based invalidation works, we know that our tag properly + * persisted. + */ + function testPageCacheTags() { + $config = \Drupal::config('system.performance'); + $config->set('cache.page.use_internal', 1); + $config->set('cache.page.max_age', 300); + $config->save(); + + $path = 'system-test/cache_tags_page'; + $tags = array('system_test_cache_tags_page' => TRUE); + $this->drupalGet($path); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS'); + $this->drupalGet($path); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT'); + Cache::invalidateTags($tags); + $this->drupalGet($path); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS'); + } + /** * Tests support for different cache items with different Accept headers. */ diff --git a/core/modules/system/system.module b/core/modules/system/system.module index cf057b23d376..66e5a6ff18be 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -261,6 +261,7 @@ function system_element_info() { '#theme_wrappers' => array('form'), ); $types['page'] = array( + '#post_render' => array('drupal_post_render_cache_tags_page_set'), '#show_messages' => TRUE, '#theme' => 'page', '#theme_wrappers' => array('html'), diff --git a/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/SystemTestController.php index db4302f15d5a..058aabedb421 100644 --- a/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/SystemTestController.php +++ b/core/modules/system/tests/modules/system_test/lib/Drupal/system_test/Controller/SystemTestController.php @@ -38,6 +38,17 @@ public function lockExit() { return system_test_lock_exit(); } + /** + * Set cache tag on on the returned render array. + */ + function system_test_cache_tags_page() { + $build['main'] = array( + '#markup' => 'Cache tags page example', + '#cache' => array('tags' => array('system_test_cache_tags_page' => TRUE)), + ); + return $build; + } + /** * @todo Remove system_test_authorize_init_page(). */ diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml index 4c6b56546ecf..660cfce92599 100644 --- a/core/modules/system/tests/modules/system_test/system_test.routing.yml +++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml @@ -45,6 +45,13 @@ system_test.lock_exit: requirements: _access: 'TRUE' +system_test.cache_tags_page: + path: '/system-test/cache_tags_page' + defaults: + _controller: '\Drupal\system_test\Controller\SystemTestController::system_test_cache_tags_page' + requirements: + _access: 'TRUE' + system_test.authorize_init: path: '/system-test/authorize-init/{page_title}' defaults: -- GitLab