protected function EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext in Drupal 8
Same name and namespace in other branches
- 9 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\EventSubscriberCode
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
// drupal_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 AttachmentsInterface || $response instanceof CacheableResponseInterface || $response instanceof CacheableDependencyInterface) {
throw new \LogicException(sprintf('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please 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;
}