You are here

public function HtmlRenderer::renderResponse in Drupal 10

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse()
  2. 9 core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse()

The entire HTML: takes a #type 'page' and wraps it in a #type 'html'.

Overrides MainContentRendererInterface::renderResponse

File

core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php, line 127

Class

HtmlRenderer
Default main content renderer for HTML requests.

Namespace

Drupal\Core\Render\MainContent

Code

public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) {
  [
    $page,
    $title,
  ] = $this
    ->prepare($main_content, $request, $route_match);
  if (!isset($page['#type']) || $page['#type'] !== 'page') {
    throw new \LogicException('Must be #type page');
  }
  $page['#title'] = $title;

  // Now render the rendered page.html.twig template inside the html.html.twig
  // template, and use the bubbled #attached metadata from $page to ensure we
  // load all attached assets.
  $html = [
    '#type' => 'html',
    'page' => $page,
  ];

  // The special page regions will appear directly in html.html.twig, not in
  // page.html.twig, hence add them here, just before rendering html.html.twig.
  $this
    ->buildPageTopAndBottom($html);

  // Render, but don't replace placeholders yet, because that happens later in
  // the render pipeline. To not replace placeholders yet, we use
  // RendererInterface::render() instead of RendererInterface::renderRoot().
  // @see \Drupal\Core\Render\HtmlResponseAttachmentsProcessor.
  $render_context = new RenderContext();
  $this->renderer
    ->executeInRenderContext($render_context, function () use (&$html) {

    // RendererInterface::render() renders the $html render array and updates
    // it in place. We don't care about the return value (which is just
    // $html['#markup']), but about the resulting render array.
    // @todo Simplify this when https://www.drupal.org/node/2495001 lands.
    $this->renderer
      ->render($html);
  });

  // RendererInterface::render() always causes bubbleable metadata to be
  // stored in the render context, no need to check it conditionally.
  $bubbleable_metadata = $render_context
    ->pop();
  $bubbleable_metadata
    ->applyTo($html);
  $content = $this->renderCache
    ->getCacheableRenderArray($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.)
  $content['#cache']['contexts'] = Cache::mergeContexts($content['#cache']['contexts'], $this->rendererConfig['required_cache_contexts']);

  // Also associate the "rendered" cache tag. This allows us to invalidate the
  // entire render cache, regardless of the cache bin.
  $content['#cache']['tags'][] = 'rendered';
  $response = new HtmlResponse($content, 200, [
    'Content-Type' => 'text/html; charset=UTF-8',
  ]);
  return $response;
}