diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index 53b914b..d0a4ecd 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -223,9 +223,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch continue; } - // Ensure we don't render another placeholder. - $placeholder_elements['#cache_no_placeholder'] = TRUE; - $placeholder_markup = $this->renderer->render($placeholder_elements, TRUE); + $placeholder_markup = $this->renderer->renderPlaceholder($placeholder, $placeholder_elements, TRUE); if ($placeholder_markup == '') { continue; diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index a22fc6f..29911cf 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -134,6 +134,21 @@ public function renderPlain(&$elements) { /** * {@inheritdoc} + * @todo Need to fix the interface for that. + */ + public function renderPlaceholder($placeholder, &$elements, $is_root_call = FALSE) { + if (isset($this->placeholderData[$placeholder])) { + // Replace $elements with the statically cached data. + $elements = $this->placeholderData[$placeholder]; + } + + $elements['#cache_no_placeholder'] = TRUE; + return $this->render($elements, $is_root_call); + } + + + /** + * {@inheritdoc} */ public function render(&$elements, $is_root_call = FALSE) { // Since #pre_render, #post_render, #post_render_cache callbacks and theme @@ -552,9 +567,7 @@ protected function processPlaceholders(array &$elements) { foreach ($elements['#cache']['placeholders'] as $placeholder => $placeholder_elements) { // @todo Move to static placeholdering strategy. if (isset($this->placeholderData[$placeholder])) { - $cached_element = $this->placeholderData[$placeholder]; - $cached_element['#cache_no_placeholder'] = TRUE; - $markup = $this->doRender($cached_element); + $markup = $this->renderPlaceholder($placeholder, $placeholder_elements); $elements['#markup'] = str_replace('
', $markup, $elements['#markup']); unset($elements['#cache']['placeholders'][$placeholder]); } @@ -563,8 +576,7 @@ protected function processPlaceholders(array &$elements) { global $process_remaining_placeholders; if (isset($process_remaining_placeholders)) { - $placeholder_elements['#cache_no_placeholder'] = TRUE; - $markup = $this->doRender($placeholder_elements); + $markup = $this->renderPlaceholder($placeholder, $placeholder_elements); $elements['#markup'] = str_replace('
', $markup, $elements['#markup']); unset($elements['#cache']['placeholders'][$placeholder]); } @@ -639,7 +651,7 @@ protected function cacheGet(array $elements, $is_recursive = FALSE) { } // Do we need to create a placeholder? - if (!empty($cache_redirect['#cache_placeholder']) || (isset($elements['#cache']['max-age']) && $elements['#cache']['max-age'] == 0)) { + if (!empty($cache_redirect['#cache_placeholder']) || !empty($cached_element['#cache_placeholder']) || (isset($elements['#cache']['max-age']) && $elements['#cache']['max-age'] == 0)) { $elements['#cache_placeholder'] = TRUE; } @@ -677,6 +689,7 @@ protected function checkPlaceholders(array $placeholders) { $cached_placeholders[$placeholder] = $this->placeholderData[$placeholder]; continue; } + $elements['#cache_no_placeholder'] = TRUE; $cached_placeholders[$placeholder] = $this->cacheGet($elements); } @@ -750,7 +763,6 @@ protected function cacheSet(array &$elements, array $pre_bubbling_elements) { $cid = $this->createCacheID($elements); $data = $this->getCacheableRenderArray($elements); - $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'render'; $expire = ($elements['#cache']['max-age'] === Cache::PERMANENT) ? Cache::PERMANENT : (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME') + $elements['#cache']['max-age']; $cache = $this->cacheFactory->get($bin); @@ -762,6 +774,12 @@ protected function cacheSet(array &$elements, array $pre_bubbling_elements) { if (!isset($pre_bubbling_elements['#cache_no_placeholder']) && $pre_bubbling_cid && ($cid || isset($pre_bubbling_elements['#pre_render_cache']))) { // Check if we want to placeholder. if (!empty($elements['#cache_placeholder']) || (isset($elements['#cache']['max-age']) && $elements['#cache']['max-age'] == 0)) { + // Ensure bubbling works correctly by copying the render cache properties over. + $data = [ + 'rendered' => $data, + '#cache_placeholder' => TRUE, + ]; + $data['#cache'] = $pre_bubbling_elements['#cache']; $elements = $this->createRenderCacheArrayPlaceholder($pre_bubbling_elements, $data); // Now update the #cache_redirect array or create it. @@ -961,6 +979,10 @@ protected function cacheSet(array &$elements, array $pre_bubbling_elements) { $data['#cache']['contexts'] = $merged_cache_contexts; } } + // If there is a hint to use a placeholder, keep that in the cache entry. + if (!empty($pre_bubbling_elements['#cache_placeholder']) || !empty($elements['#cache_placeholder'])) { + $data['#cache_placeholder'] = TRUE; + } $cache->set($cid, $data, $expire, Cache::mergeTags($data['#cache']['tags'], ['rendered'])); } diff --git a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php index 77c354a..7dba56c 100644 --- a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php @@ -193,6 +193,7 @@ public function build() { $build['site_slogan']['#debug'] = TRUE; */ $build['site_slogan']['#cache']['contexts'] = ['user']; + $build['site_slogan']['#cache']['tags'] = ['site_branding_block_custom']; // $build['site_slogan']['dynamic'] = [ '#markup' => '
It is: ' . time(NULL) . '
' ]; $build['site_slogan']['dynamic'] = [ '#pre_render_cache' => [get_class($this) . '::buildDynamic' => []] ]; @@ -201,6 +202,20 @@ public function build() { // This is a stage, where a placeholder can be created. $build['site_slogan']['dynamic']['#cache']['keys'] = [ 'fabian', 'site-branding-dynamic' ]; +// Cacheable per route thing. + $build['site_slogan']['cacheable_per_route'] = [ + '#pre_render' => [ + [$this, 'buildCacheable'], + ], + ]; + // @todo Setting the [route] here confuses the renderer. + $build['site_slogan']['cacheable_per_route']['#cache']['contexts'] = [ 'route' ]; + + // We don't want the route to bubble up: too dynamic. + //$build['site_slogan']['cacheable_per_route']['#cache_placeholder'] = TRUE; + $build['site_slogan']['cacheable_per_route']['#cache']['keys'] = [ 'fabian', 'site-branding-cacheable' ]; + $build['site_slogan']['cacheable_per_route']['#cache']['tags'] = ['site_branding_cacheable_custom']; + return $build; } @@ -214,6 +229,14 @@ public static function buildDynamic($build, $context) { return $build; } + public function buildCacheable($build) { + $build['#markup'] = '
The current path is: ' . \Drupal::service('path.current')->getPath() . '
'; + $build['#cache']['contexts'] = ['route']; + $build['#cache_placeholder'] = TRUE; + usleep(500*1000); + return $build; + } + /** * {@inheritdoc} */