Commit 2ca54697 authored by catch's avatar catch

Issue #2215719 by Wim Leers: Cache tags set by #pre_render callbacks are lost in page cache.

parent 2cfe1894
......@@ -3990,6 +3990,12 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) {
$suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
$elements['#markup'] = $prefix . $elements['#children'] . $suffix;
// Collect all cache tags. This allows the caller of drupal_render() to also
// access the complete list of cache tags.
if (!$is_recursive_call || isset($elements['#cache'])) {
$elements['#cache']['tags'] = drupal_render_collect_cache_tags($elements);
}
// Cache the processed element if #cache is set.
if (isset($elements['#cache'])) {
drupal_render_cache_set($elements['#markup'], $elements);
......@@ -4196,10 +4202,14 @@ function drupal_render_cache_set(&$markup, array $elements) {
$data['#post_render_cache'] = $elements['#post_render_cache'];
}
// Persist cache tags associated with this element.
if (isset($elements['#cache']['tags'])) {
$data['#cache']['tags'] = $elements['#cache']['tags'];
}
$bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
$expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : Cache::PERMANENT;
$tags = drupal_render_collect_cache_tags($elements);
\Drupal::cache($bin)->set($cid, $data, $expire, $tags);
\Drupal::cache($bin)->set($cid, $data, $expire, $elements['#cache']['tags']);
}
/**
......
......@@ -1967,14 +1967,6 @@ function template_preprocess_html(&$variables) {
}
}
// Initializes attributes which are specific to the html and body elements.
$variables['html_attributes'] = new Attribute;
// HTML element attributes.
$language_interface = \Drupal::service('language_manager')->getCurrentLanguage();
$variables['html_attributes']['lang'] = $language_interface->id;
$variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
$site_config = \Drupal::config('system.site');
// Construct page title.
if ($page->hasTitle()) {
......
......@@ -71,9 +71,9 @@ protected function createHtmlFragment($page_content, Request $request) {
);
}
$cache_tags = $this->drupalRenderCollectCacheTags($page_content);
$cache = !empty($cache_tags) ? array('tags' => $cache_tags) : array();
$fragment = new HtmlFragment($this->drupalRender($page_content), $cache);
$content = $this->drupalRender($page_content);
$cache = !empty($page_content['#cache']['tags']) ? array('tags' => $page_content['#cache']['tags']) : array();
$fragment = new HtmlFragment($content, $cache);
// A title defined in the return always wins.
if (isset($page_content['#title'])) {
......@@ -95,13 +95,4 @@ protected function drupalRender(&$elements, $is_recursive_call = FALSE) {
return drupal_render($elements, $is_recursive_call);
}
/**
* Wraps drupal_render_collect_cache_tags()
*
* @todo: Remove as part of https://drupal.org/node/2182149
*/
protected function drupalRenderCollectCacheTags($element, $tags = array()) {
return drupal_render_collect_cache_tags($element, $tags);
}
}
......@@ -48,15 +48,14 @@ public function render(HtmlFragment $fragment, $status_code = 200) {
// hook_page_build(). This adds the other regions to the page.
$page_array = drupal_prepare_page($page_content);
// Collect cache tags for all the content in all the regions on the page.
$tags = drupal_render_collect_cache_tags($page_array);
// Build the HtmlPage object.
$page = new HtmlPage('', array('tags' => $tags), $fragment->getTitle());
$page = new HtmlPage('', array(), $fragment->getTitle());
$page = $this->preparePage($page, $page_array);
$page->setBodyTop(drupal_render($page_array['page_top']));
$page->setBodyBottom(drupal_render($page_array['page_bottom']));
$page->setContent(drupal_render($page_array));
// Collect cache tags for all the content in all the regions on the page.
$page->setCacheTags($page_array['#cache']['tags']);
$page->setStatusCode($status_code);
return $page;
......
......@@ -158,5 +158,15 @@ public function getStatusCode() {
return $this->statusCode;
}
/**
* Sets the cache tags associated with this HTML page.
*
* @param array $cache_tags
* The cache tags associated with this HTML page.
*/
public function setCacheTags(array $cache_tags) {
$this->cache['tags'] = $cache_tags;
}
}
......@@ -65,7 +65,7 @@ function testPageCacheTags() {
$cid_parts = array(url($path, array('absolute' => TRUE)), 'html');
$cid = sha1(implode(':', $cid_parts));
$cache_entry = \Drupal::cache('page')->get($cid);
$this->assertIdentical($cache_entry->tags, array('content:1', 'system_test_cache_tags_page:1'));
$this->assertIdentical($cache_entry->tags, array('content:1', 'system_test_cache_tags_page:1', 'pre_render:1'));
Cache::invalidateTags($tags);
$this->drupalGet($path);
......
......@@ -500,6 +500,7 @@ function testDrupalRenderPostRenderCache() {
'#markup' => '<p>#cache enabled, GET</p>',
'#attached' => $test_element['#attached'],
'#post_render_cache' => $test_element['#post_render_cache'],
'#cache' => array('tags' => array()),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
......@@ -619,6 +620,7 @@ function testDrupalRenderChildrenPostRenderCache() {
$context_3,
)
),
'#cache' => array('tags' => array()),
);
$dom = Html::load($cached_element['#markup']);
......@@ -702,6 +704,7 @@ function testDrupalRenderChildrenPostRenderCache() {
$context_3,
)
),
'#cache' => array('tags' => array()),
);
$dom = Html::load($cached_parent_element['#markup']);
......@@ -727,6 +730,7 @@ function testDrupalRenderChildrenPostRenderCache() {
$context_3,
)
),
'#cache' => array('tags' => array()),
);
$dom = Html::load($cached_child_element['#markup']);
......@@ -830,6 +834,7 @@ function testDrupalRenderRenderCachePlaceholder() {
$expected_token => $context,
),
),
'#cache' => array('tags' => array()),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
......@@ -920,6 +925,7 @@ function testDrupalRenderChildElementRenderCachePlaceholder() {
$expected_token => $context,
),
),
'#cache' => array('tags' => array()),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
......@@ -944,6 +950,7 @@ function testDrupalRenderChildElementRenderCachePlaceholder() {
$expected_token => $context,
),
),
'#cache' => array('tags' => array()),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the parent element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
......@@ -972,6 +979,7 @@ function testDrupalRenderChildElementRenderCachePlaceholder() {
$expected_token => $context,
),
),
'#cache' => array('tags' => array()),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
......
......@@ -27,7 +27,6 @@ public function getFormId() {
public function buildForm(array $form, array &$form_state) {
$form['#action'] = url('ajax-test/dialog');
$form['#cache'] = TRUE;
$form['description'] = array(
'#markup' => '<p>' . t("Ajax Form contents description.") . '</p>',
......
......@@ -41,14 +41,27 @@ public function lockExit() {
/**
* Set cache tag on on the returned render array.
*/
function system_test_cache_tags_page() {
public function system_test_cache_tags_page() {
$build['main'] = array(
'#markup' => 'Cache tags page example',
'#cache' => array('tags' => array('system_test_cache_tags_page' => TRUE)),
'#pre_render' => array(
'\Drupal\system_test\Controller\SystemTestController::preRenderCacheTags',
),
'message' => array(
'#markup' => 'Cache tags page example',
),
);
return $build;
}
/**
* Sets a cache tag on an element to help test #pre_render and cache tags.
*/
public static function preRenderCacheTags($elements) {
$elements['#cache']['tags']['pre_render'] = TRUE;
return $elements;
}
/**
* @todo Remove system_test_authorize_init_page().
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment