function EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext

Same name in other branches
  1. 9 core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php \Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext()
  2. 8.9.x core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php \Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext()
  3. 10 core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php \Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext()

Wraps a controller execution in a render context.

Parameters

callable $controller: The controller to execute.

array $arguments: The arguments to pass to the controller.

Return value

mixed The return value of the controller.

Throws

\LogicException When early rendering has occurred in a controller that returned a Response or domain object that cares about attachments or cacheability.

See also

\Symfony\Component\HttpKernel\HttpKernel::handleRaw()

1 call to EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext()
EarlyRenderingControllerWrapperSubscriber::onController in core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php
Ensures bubbleable metadata from early rendering is not lost.

File

core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php, line 118

Class

EarlyRenderingControllerWrapperSubscriber
Subscriber that wraps controllers, to handle early rendering.

Namespace

Drupal\Core\EventSubscriber

Code

protected function wrapControllerExecutionInRenderContext($controller, array $arguments) {
    $context = new RenderContext();
    $response = $this->renderer
        ->executeInRenderContext($context, function () use ($controller, $arguments) {
        // Now call the actual controller, just like HttpKernel does.
        return call_user_func_array($controller, $arguments);
    });
    // If early rendering happened, i.e. if code in the controller called
    // RendererInterface::render() outside of a render context, then the
    // bubbleable metadata for that is stored in the current render context.
    if (!$context->isEmpty()) {
        
        /** @var \Drupal\Core\Render\BubbleableMetadata $early_rendering_bubbleable_metadata */
        $early_rendering_bubbleable_metadata = $context->pop();
        // If a render array or AjaxResponse is returned by the controller, merge
        // the "lost" bubbleable metadata.
        if (is_array($response)) {
            BubbleableMetadata::createFromRenderArray($response)->merge($early_rendering_bubbleable_metadata)
                ->applyTo($response);
        }
        elseif ($response instanceof AjaxResponse) {
            $response->addAttachments($early_rendering_bubbleable_metadata->getAttachments());
            // @todo Make AjaxResponse cacheable in
            //   https://www.drupal.org/node/956186. Meanwhile, allow contrib
            //   subclasses to be.
            if ($response instanceof CacheableResponseInterface) {
                $response->addCacheableDependency($early_rendering_bubbleable_metadata);
            }
        }
        elseif ($response instanceof CacheableResponseInterface) {
            $response->addCacheableDependency($early_rendering_bubbleable_metadata);
        }
        elseif ($response instanceof AttachmentsInterface || $response instanceof CacheableDependencyInterface) {
            throw new \LogicException(sprintf('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Ensure you are not rendering content too early. Returned object class: %s.', get_class($response)));
        }
        else {
            // A Response or domain object is returned that does not care about
            // attachments nor cacheability; for instance, a RedirectResponse. It is
            // safe to discard any early rendering metadata.
        }
    }
    return $response;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.