diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index b701344..0a2c6b3 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -143,6 +143,11 @@ public function renderResponse(array $main_content, Request $request, RouteMatch ->merge($bubbleable_metadata) ->applyTo($html); } + // Also associate the required cache contexts. + // (Because we use ::render() above and not ::renderRoot(), we manually must + // ensure the HTML response varies by the required cache contexts.) + $html = $this->renderer->applyRequiredCacheContexts($html); + $content = $this->renderCache->getCacheableRenderArray($html); // Also associate the "rendered" cache tag. This allows us to invalidate the diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index 7e3d428..4314113 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -255,6 +255,8 @@ protected function doRender(&$elements, $is_root_call = FALSE) { // - this is a render cacheable subtree, to ensure that the cached data has // the configurable defaults (which may affect the ID and invalidation). if ($is_root_call || isset($elements['#cache']['keys'])) { + // This is inlined for performance reasons. Also see + // applyRequiredCacheContexts() function below. $required_cache_contexts = $this->rendererConfig['required_cache_contexts']; if (isset($elements['#cache']['contexts'])) { $elements['#cache']['contexts'] = Cache::mergeContexts($elements['#cache']['contexts'], $required_cache_contexts); @@ -555,6 +557,21 @@ protected function doRender(&$elements, $is_root_call = FALSE) { /** * {@inheritdoc} */ + public function applyRequiredCacheContexts(array $elements) { + $required_cache_contexts = $this->rendererConfig['required_cache_contexts']; + if (isset($elements['#cache']['contexts'])) { + $elements['#cache']['contexts'] = Cache::mergeContexts($elements['#cache']['contexts'], $required_cache_contexts); + } + else { + $elements['#cache']['contexts'] = $required_cache_contexts; + } + + return $elements; + } + + /** + * {@inheritdoc} + */ public function hasRenderContext() { return (bool) $this->getCurrentRenderContext(); } diff --git a/core/lib/Drupal/Core/Render/RendererInterface.php b/core/lib/Drupal/Core/Render/RendererInterface.php index 155eec4..c2c3012 100644 --- a/core/lib/Drupal/Core/Render/RendererInterface.php +++ b/core/lib/Drupal/Core/Render/RendererInterface.php @@ -365,6 +365,21 @@ public function hasRenderContext(); public function executeInRenderContext(RenderContext $context, callable $callable); /** + * Applies the required cache contexts to a render array. + * + * Note: This function should only be needed in edge-case circumstances; e.g. + * when interacting directly with the RenderCache class or by rendering + * without replacing placeholders. + * + * @param array $elements + * The render array to apply the required cache contexts to. + * + * @return array + * A render array with the required cache contexts added. + */ + public function applyRequiredCacheContexts(array $elements); + + /** * Merges the bubbleable rendering metadata o/t 2nd render array with the 1st. * * @param array $a