Issue #2185617 by Wim Leers, voidberg, drifter: Each page cache entry should have a theme cache tag.
parent
f130cc3e7b
commit
407f1d1180
|
@ -1925,6 +1925,22 @@ function drupal_pre_render_html(array $element) {
|
|||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for the page element type.
|
||||
*
|
||||
* @param array $element
|
||||
* A structured array containing the page element type build properties.
|
||||
*
|
||||
* @see system_element_info()
|
||||
*/
|
||||
function drupal_pre_render_page(array $element) {
|
||||
global $theme;
|
||||
$element['#cache']['tags']['theme'] = $theme;
|
||||
$element['#cache']['tags']['theme_global_settings'] = TRUE;
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares variables for HTML document templates.
|
||||
*
|
||||
|
|
|
@ -43,9 +43,9 @@ class LanguageCacheContext implements CacheContextInterface {
|
|||
*/
|
||||
public function getContext() {
|
||||
$context_parts = array();
|
||||
if ($this->language_manager->isMultilingual()) {
|
||||
foreach ($this->language_manager->getLanguageTypes() as $type) {
|
||||
$context_parts[] = $this->language_manager->getCurrentLanguage($type)->id;
|
||||
if ($this->languageManager->isMultilingual()) {
|
||||
foreach ($this->languageManager->getLanguageTypes() as $type) {
|
||||
$context_parts[] = $this->languageManager->getCurrentLanguage($type)->id;
|
||||
}
|
||||
}
|
||||
return implode(':', $context_parts);
|
||||
|
|
|
@ -74,6 +74,7 @@ class BlockViewBuilder extends EntityViewBuilder {
|
|||
'content' => TRUE,
|
||||
'block_view' => TRUE,
|
||||
'block' => array($entity->id()),
|
||||
'theme' => $entity->get('theme'),
|
||||
);
|
||||
$build[$entity_id]['#cache']['tags'] = NestedArray::mergeDeep($default_cache_tags, $plugin->getCacheTags());
|
||||
|
||||
|
|
|
@ -160,8 +160,7 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin
|
|||
// When placing a new block, invalidate all cache entries for this theme,
|
||||
// since any page that uses this theme might be affected.
|
||||
else {
|
||||
// @todo Replace with theme cache tag: https://drupal.org/node/2185617
|
||||
Cache::invalidateTags(array('content' => TRUE));
|
||||
Cache::invalidateTags(array('theme' => $this->theme));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -281,6 +281,8 @@ class BlockTest extends BlockTestBase {
|
|||
$cid = sha1(implode(':', $cid_parts));
|
||||
$cache_entry = \Drupal::cache('render')->get($cid);
|
||||
$expected_cache_tags = array(
|
||||
'theme:stark',
|
||||
'theme_global_settings:1',
|
||||
'content:1',
|
||||
'block_view:1',
|
||||
'block:powered',
|
||||
|
@ -288,6 +290,13 @@ class BlockTest extends BlockTestBase {
|
|||
);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:en:stark');
|
||||
$expected_cache_tags = array(
|
||||
'content:1',
|
||||
'block_view:1',
|
||||
'block:powered',
|
||||
'theme:stark',
|
||||
'block_plugin:system_powered_by_block',
|
||||
);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
|
||||
// The "Powered by Drupal" block is modified; verify a cache miss.
|
||||
|
@ -312,6 +321,8 @@ class BlockTest extends BlockTestBase {
|
|||
$cid = sha1(implode(':', $cid_parts));
|
||||
$cache_entry = \Drupal::cache('render')->get($cid);
|
||||
$expected_cache_tags = array(
|
||||
'theme:stark',
|
||||
'theme_global_settings:1',
|
||||
'content:1',
|
||||
'block_view:1',
|
||||
'block:powered-2',
|
||||
|
@ -323,6 +334,7 @@ class BlockTest extends BlockTestBase {
|
|||
'content:1',
|
||||
'block_view:1',
|
||||
'block:powered',
|
||||
'theme:stark',
|
||||
'block_plugin:system_powered_by_block',
|
||||
);
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:en:stark');
|
||||
|
@ -331,6 +343,7 @@ class BlockTest extends BlockTestBase {
|
|||
'content:1',
|
||||
'block_view:1',
|
||||
'block:powered-2',
|
||||
'theme:stark',
|
||||
'block_plugin:system_powered_by_block',
|
||||
);
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered-2:en:stark');
|
||||
|
|
|
@ -221,7 +221,7 @@ class BlockViewBuilderTest extends DrupalUnitTestBase {
|
|||
$this->container->get('request')->setMethod('GET');
|
||||
|
||||
$default_keys = array('entity_view', 'block', 'test_block', 'en', 'cache_context.theme');
|
||||
$default_tags = array('content' => TRUE, 'block_view' => TRUE, 'block' => array('test_block'), 'block_plugin' => array('test_cache'));
|
||||
$default_tags = array('content' => TRUE, 'block_view' => TRUE, 'block' => array('test_block'), 'theme' => 'stark', 'block_plugin' => array('test_cache'));
|
||||
|
||||
// Advanced: cached block, but an alter hook adds an additional cache key.
|
||||
$this->setBlockCacheConfig(array(
|
||||
|
@ -236,7 +236,7 @@ class BlockViewBuilderTest extends DrupalUnitTestBase {
|
|||
$this->assertIdentical(drupal_render($build), '');
|
||||
$cache_entry = $this->container->get('cache.render')->get($cid);
|
||||
$this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.');
|
||||
$expected_flattened_tags = array('content:1', 'block_view:1', 'block:test_block', 'block_plugin:test_cache');
|
||||
$expected_flattened_tags = array('content:1', 'block_view:1', 'block:test_block', 'theme:stark', 'block_plugin:test_cache');
|
||||
$this->assertIdentical($cache_entry->tags, array_combine($expected_flattened_tags, $expected_flattened_tags)); //, 'The block render element has been cached with the expected cache tags.');
|
||||
$this->container->get('cache.render')->delete($cid);
|
||||
|
||||
|
@ -250,7 +250,7 @@ class BlockViewBuilderTest extends DrupalUnitTestBase {
|
|||
$this->assertIdentical(drupal_render($build), '');
|
||||
$cache_entry = $this->container->get('cache.render')->get($cid);
|
||||
$this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.');
|
||||
$expected_flattened_tags = array('content:1', 'block_view:1', 'block:test_block', 'block_plugin:test_cache', $alter_add_tag . ':1');
|
||||
$expected_flattened_tags = array('content:1', 'block_view:1', 'block:test_block', 'theme:stark', 'block_plugin:test_cache', $alter_add_tag . ':1');
|
||||
$this->assertIdentical($cache_entry->tags, array_combine($expected_flattened_tags, $expected_flattened_tags)); //, 'The block render element has been cached with the expected cache tags.');
|
||||
$this->container->get('cache.render')->delete($cid);
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ class MenuCacheTagsTest extends PageCacheTagsTestBase {
|
|||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags.
|
||||
$expected_tags = array(
|
||||
'theme:stark',
|
||||
'theme_global_settings:1',
|
||||
'content:1',
|
||||
'block_view:1',
|
||||
'block:' . $block->id(),
|
||||
|
@ -117,7 +119,7 @@ class MenuCacheTagsTest extends PageCacheTagsTestBase {
|
|||
$this->verifyPageCache($path, 'MISS');
|
||||
|
||||
// Verify a cache hit.
|
||||
$this->verifyPageCache($path, 'HIT', array('content:1'));
|
||||
$this->verifyPageCache($path, 'HIT', array('content:1', 'theme:stark', 'theme_global_settings:1'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -419,6 +419,16 @@ class ThemeSettingsForm extends ConfigFormBase {
|
|||
|
||||
theme_settings_convert_to_config($values, $config)->save();
|
||||
|
||||
// Invalidate either the theme-specific cache tag or the global theme
|
||||
// settings cache tag, depending on whose settings were actually changed.
|
||||
if (isset($values['theme'])) {
|
||||
Cache::invalidateTags(array('theme' => $values['theme']));
|
||||
}
|
||||
else {
|
||||
Cache::invalidateTags(array('theme_global_settings' => TRUE));
|
||||
}
|
||||
|
||||
// @todo Remove this in https://drupal.org/node/2124957.
|
||||
Cache::invalidateTags(array('content' => TRUE));
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\system\Plugin\Block;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\block\BlockBase;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
|
@ -44,7 +45,7 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $current_user;
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Creates a SystemBrandingBlock instance.
|
||||
|
@ -92,6 +93,12 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
'use_site_name' => TRUE,
|
||||
'use_site_slogan' => TRUE,
|
||||
'label_display' => FALSE,
|
||||
// Modify the default max age for the 'Site branding' block: the site
|
||||
// logo, name and slogan are static for a given language, except when the
|
||||
// theme settings are updated (global theme settings or theme-specific
|
||||
// settings). Cache tags for those cases ensure that a cached version of
|
||||
// this block is invalidated automatically.
|
||||
'cache' => array('max_age' => \Drupal\Core\Cache\Cache::PERMANENT),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -108,12 +115,12 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
|
||||
if ($administer_themes_access) {
|
||||
// Get paths to theme settings pages.
|
||||
$appearance_url = $this->urlGenerator->generateFromRoute('system.themes_page');
|
||||
$appearance_settings_url = $this->urlGenerator->generateFromRoute('system.theme_settings');
|
||||
$theme_settings_url = $this->urlGenerator->generateFromRoute('system.theme_settings_theme', array('theme' => $theme));
|
||||
|
||||
// Provide links to the Appearance and Theme Settings pages
|
||||
// Provide links to the Appearance Settings and Theme Settings pages
|
||||
// if the user has access to administer themes.
|
||||
$site_logo_description = $this->t('Defined on the <a href="@appearance">Appearance</a> or <a href="@theme">Theme Settings</a> page.', array('@appearance' => $appearance_url, '@theme' => $theme_settings_url));
|
||||
$site_logo_description = $this->t('Defined on the <a href="@appearance">Appearance Settings</a> or <a href="@theme">Theme Settings</a> page.', array('@appearance' => $appearance_settings_url, '@theme' => $theme_settings_url));
|
||||
}
|
||||
else {
|
||||
// Explain that the user does not have access to the Appearance and Theme
|
||||
|
@ -200,4 +207,29 @@ class SystemBrandingBlock extends BlockBase implements ContainerFactoryPluginInt
|
|||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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.
|
||||
$tags = array(
|
||||
'theme_global_setting' => TRUE,
|
||||
);
|
||||
return NestedArray::mergeDeep(parent::getCacheTags(), $tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getRequiredCacheContexts() {
|
||||
// The 'Site branding' block must be cached per theme and per language: the
|
||||
// site logo, name and slogan are defined on a per-theme basis, and the name
|
||||
// and slogan may be translated.
|
||||
// We don't need to return 'cache_context.theme' also, because that cache
|
||||
// context is automatically applied to all blocks.
|
||||
// @see \Drupal\block\BlockViewBuilder::viewMultiple()
|
||||
return array('cache_context.language');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,7 +66,14 @@ class PageCacheTest extends WebTestBase {
|
|||
$cid = sha1(implode(':', $cid_parts));
|
||||
$cache_entry = \Drupal::cache('render')->get($cid);
|
||||
sort($cache_entry->tags);
|
||||
$this->assertIdentical($cache_entry->tags, array('content:1', 'pre_render:1', 'system_test_cache_tags_page:1'));
|
||||
$expected_tags = array(
|
||||
'content:1',
|
||||
'pre_render:1',
|
||||
'system_test_cache_tags_page:1',
|
||||
'theme:stark',
|
||||
'theme_global_settings:1',
|
||||
);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_tags);
|
||||
|
||||
Cache::invalidateTags($tags);
|
||||
$this->drupalGet($path);
|
||||
|
|
|
@ -77,6 +77,8 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
|
|||
// Full node page 1.
|
||||
$this->verifyPageCacheTags('node/' . $node_1->id(), array(
|
||||
'content:1',
|
||||
'theme:bartik',
|
||||
'theme_global_settings:1',
|
||||
'block_view:1',
|
||||
'block:bartik_content',
|
||||
'block:bartik_tools',
|
||||
|
@ -100,6 +102,8 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
|
|||
// Full node page 2.
|
||||
$this->verifyPageCacheTags('node/' . $node_2->id(), array(
|
||||
'content:1',
|
||||
'theme:bartik',
|
||||
'theme_global_settings:1',
|
||||
'block_view:1',
|
||||
'block:bartik_content',
|
||||
'block:bartik_tools',
|
||||
|
|
|
@ -210,6 +210,8 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
$non_referencing_entity_path = $this->non_referencing_entity->getSystemPath();
|
||||
$listing_path = 'entity_test/list/' . $entity_type . '_reference/' . $entity_type . '/' . $this->entity->id();
|
||||
|
||||
$theme_cache_tags = array('content:1', 'theme:stark', 'theme_global_settings:1');
|
||||
|
||||
// Generate the standardized entity cache tags.
|
||||
$cache_tag = $entity_type . ':' . $this->entity->id();
|
||||
$view_cache_tag = $entity_type . '_view:1';
|
||||
|
@ -232,7 +234,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
$this->verifyPageCache($referencing_entity_path, 'MISS');
|
||||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags.
|
||||
$tags = array_merge(array('content:1'), $referencing_entity_cache_tags);
|
||||
$tags = array_merge($theme_cache_tags, $referencing_entity_cache_tags);
|
||||
$this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
|
||||
|
||||
// Also verify the existence of an entity render cache entry.
|
||||
|
@ -245,7 +247,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
$this->verifyPageCache($non_referencing_entity_path, 'MISS');
|
||||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags.
|
||||
$tags = array_merge(array('content:1'), $non_referencing_entity_cache_tags);
|
||||
$tags = array_merge($theme_cache_tags, $non_referencing_entity_cache_tags);
|
||||
$this->verifyPageCache($non_referencing_entity_path, 'HIT', $tags);
|
||||
|
||||
// Also verify the existence of an entity render cache entry.
|
||||
|
@ -259,7 +261,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
$this->verifyPageCache($listing_path, 'MISS');
|
||||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags.
|
||||
$tags = array_merge(array('content:1'), $referencing_entity_cache_tags);
|
||||
$tags = array_merge($theme_cache_tags, $referencing_entity_cache_tags);
|
||||
$this->verifyPageCache($listing_path, 'HIT', $tags);
|
||||
|
||||
|
||||
|
@ -407,13 +409,12 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
|
|||
$this->verifyPageCache($non_referencing_entity_path, 'HIT');
|
||||
|
||||
// Verify cache hits.
|
||||
$tags = array(
|
||||
'content:1',
|
||||
$tags = array_merge($theme_cache_tags, array(
|
||||
'entity_test_view:1',
|
||||
'entity_test:' . $this->referencing_entity->id(),
|
||||
);
|
||||
));
|
||||
$this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
|
||||
$this->verifyPageCache($listing_path, 'HIT', array('content:1'));
|
||||
$this->verifyPageCache($listing_path, 'HIT', $theme_cache_tags);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -290,6 +290,7 @@ function system_element_info() {
|
|||
);
|
||||
$types['page'] = array(
|
||||
'#show_messages' => TRUE,
|
||||
'#pre_render' => array('drupal_pre_render_page'),
|
||||
'#theme' => 'page',
|
||||
'#title' => '',
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue