core/modules/block/lib/Drupal/block/BlockBase.php | 7 +++++ .../block/lib/Drupal/block/BlockViewBuilder.php | 30 ++++++++++---------- .../system/Plugin/Block/SystemPoweredByBlock.php | 14 +++++++++ .../Tests/Cache/PageCacheTagsIntegrationTest.php | 30 ++++++++++++++++++++ 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/core/modules/block/lib/Drupal/block/BlockBase.php b/core/modules/block/lib/Drupal/block/BlockBase.php index 59ea159..cef4c69 100644 --- a/core/modules/block/lib/Drupal/block/BlockBase.php +++ b/core/modules/block/lib/Drupal/block/BlockBase.php @@ -11,6 +11,7 @@ use Drupal\block\BlockInterface; use Drupal\Component\Utility\Unicode; use Drupal\Core\Language\Language; +use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableInterface; use Drupal\Core\Session\AccountInterface; @@ -118,6 +119,12 @@ public function buildConfigurationForm(array $form, array &$form_state) { '#default_value' => $this->configuration['cache']['max_age'], '#options' => drupal_map_assoc(array(0, 60, 300, 1800, 3600, 21600, 86400, 604800, 2592000, 31536000, 315360000), 'format_interval'), ); + // Don't allow the user to configure the max age for this block if the block + // plugin declares itself not cacheable or if it declares itself permanently + // cacheable. + if (!$this->isCacheable() || $this->getCacheMaxAge() === Cache::PERMANENT) { + $form['cache']['#access'] = FALSE; + } // Add plugin-specific settings for this block type. $form += $this->blockForm($form, $form_state); return $form; diff --git a/core/modules/block/lib/Drupal/block/BlockViewBuilder.php b/core/modules/block/lib/Drupal/block/BlockViewBuilder.php index 2005632..d6e5056 100644 --- a/core/modules/block/lib/Drupal/block/BlockViewBuilder.php +++ b/core/modules/block/lib/Drupal/block/BlockViewBuilder.php @@ -68,25 +68,25 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la ); $build[$entity_id]['#configuration']['label'] = check_plain($configuration['label']); + // Set cache tags; these always need to be set, whether the block is + // cacheable or not, so that the page cache is correctly informed. + $default_cache_tags = array( + 'content' => TRUE, + 'block_view' => TRUE, + 'block' => array($entity->id()), + ); + $build[$entity_id]['#cache']['tags'] = NestedArray::mergeDeep($default_cache_tags, $plugin->getCacheTags()); + + if ($plugin->isCacheable()) { + $build[$entity_id]['#pre_render'][] = array($this, 'buildBlock'); // Generic cache keys, with the block plugin's custom keys appended // (usually cache context keys like DRUPAL_CACHE_PER_ROLE). $default_cache_keys = array('entity_view', 'block', $entity->id(), $entity->langcode); - $default_cache_tags = array( - 'content' => TRUE, - 'block_view' => TRUE, - 'block' => array($entity->id()), - ); - $build[$entity_id] += array( - '#pre_render' => array( - array($this, 'buildBlock'), - ), - '#cache' => array( - 'keys' => array_merge($default_cache_keys, $plugin->getCacheKeys()), - 'bin' => $plugin->getCacheBin(), - 'tags' => NestedArray::mergeDeep($default_cache_tags, $plugin->getCacheTags()), - 'expire' => REQUEST_TIME + $plugin->getCacheMaxAge(), - ), + $build[$entity_id]['#cache'] += array( + 'keys' => array_merge($default_cache_keys, $plugin->getCacheKeys()), + 'bin' => $plugin->getCacheBin(), + 'expire' => REQUEST_TIME + $plugin->getCacheMaxAge(), ); } else { diff --git a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemPoweredByBlock.php b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemPoweredByBlock.php index 742af7b..e5a5e63 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemPoweredByBlock.php +++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemPoweredByBlock.php @@ -26,4 +26,18 @@ public function build() { return array('#markup' => '' . t('Powered by Drupal', array('@poweredby' => 'http://drupal.org')) . ''); } + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + return \Drupal\Core\Cache\Cache::PERMANENT; + } + + /** + * {@inheritdoc} + */ + public function isCacheable() { + return TRUE; + } + } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/PageCacheTagsIntegrationTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/PageCacheTagsIntegrationTest.php index 4b4c799..91951bf 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/PageCacheTagsIntegrationTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/PageCacheTagsIntegrationTest.php @@ -64,9 +64,28 @@ function testPageCacheTags() { 'promote' => NODE_PROMOTED, ))->id(); + // Place a block, but only make it visible on full node page 2. + $block = $this->drupalPlaceBlock('views_block:comments_recent-block_1', array( + 'visibility' => array( + 'path' => array( + 'visibility' => BLOCK_VISIBILITY_LISTED, + 'pages' => $node_2_path, + ), + ) + )); + // Full node page 1. $this->verifyPageCacheTags($node_1_path, array( 'content:1', + 'block_view:1', + 'block:bartik_content', + 'block:bartik_login', + 'block:bartik_footer', + 'block:bartik_powered', + 'block_plugin:system_main_block', + 'block_plugin:user_login_block', + 'block_plugin:system_menu_block__footer', + 'block_plugin:system_powered_by_block', 'user:' . $author_1->id(), 'filter_format:basic_html', 'menu:footer', @@ -76,6 +95,17 @@ function testPageCacheTags() { // Full node page 2. $this->verifyPageCacheTags($node_2_path, array( 'content:1', + 'block_view:1', + 'block:bartik_content', + 'block:bartik_login', + 'block:' . $block->id(), + 'block:bartik_footer', + 'block:bartik_powered', + 'block_plugin:system_main_block', + 'block_plugin:user_login_block', + 'block_plugin:views_block__comments_recent-block_1', + 'block_plugin:system_menu_block__footer', + 'block_plugin:system_powered_by_block', 'user:' . $author_2->id(), 'filter_format:full_html', 'menu:footer',