Version 1
[yaffs-website] / web / core / lib / Drupal / Core / EventSubscriber / MainContentViewSubscriber.php
1 <?php
2
3 namespace Drupal\Core\EventSubscriber;
4
5 use Drupal\Core\Cache\CacheableMetadata;
6 use Drupal\Core\Cache\CacheableResponseInterface;
7 use Drupal\Core\DependencyInjection\ClassResolverInterface;
8 use Drupal\Core\Routing\RouteMatchInterface;
9 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10 use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
11 use Symfony\Component\HttpKernel\KernelEvents;
12
13 /**
14  * View subscriber rendering main content render arrays into responses.
15  *
16  * Additional target rendering formats can be defined by adding another service
17  * that implements \Drupal\Core\Render\MainContent\MainContentRendererInterface
18  * and tagging it as a @code render.main_content_renderer @endcode, then
19  * \Drupal\Core\Render\MainContent\MainContentRenderersPass will detect it and
20  * use it when appropriate.
21  *
22  * @see \Drupal\Core\Render\MainContent\MainContentRendererInterface
23  * @see \Drupal\Core\Render\MainContentControllerPass
24  */
25 class MainContentViewSubscriber implements EventSubscriberInterface {
26
27   /**
28    * The class resolver service.
29    *
30    * @var \Drupal\Core\Controller\ControllerResolverInterface
31    */
32   protected $classResolver;
33
34   /**
35    * The current route match.
36    *
37    * @var \Drupal\Core\Routing\RouteMatchInterface
38    */
39   protected $routeMatch;
40
41   /**
42    * The available main content renderer services, keyed per format.
43    *
44    * @var array
45    */
46   protected $mainContentRenderers;
47
48   /**
49    * URL query attribute to indicate the wrapper used to render a request.
50    *
51    * The wrapper format determines how the HTML is wrapped, for example in a
52    * modal dialog.
53    */
54   const WRAPPER_FORMAT = '_wrapper_format';
55
56   /**
57    * Constructs a new MainContentViewSubscriber object.
58    *
59    * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
60    *   The class resolver service.
61    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
62    *   The current route match.
63    * @param array $main_content_renderers
64    *   The available main content renderer service IDs, keyed by format.
65    */
66   public function __construct(ClassResolverInterface $class_resolver, RouteMatchInterface $route_match, array $main_content_renderers) {
67     $this->classResolver = $class_resolver;
68     $this->routeMatch = $route_match;
69     $this->mainContentRenderers = $main_content_renderers;
70   }
71
72   /**
73    * Sets a response given a (main content) render array.
74    *
75    * @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
76    *   The event to process.
77    */
78   public function onViewRenderArray(GetResponseForControllerResultEvent $event) {
79     $request = $event->getRequest();
80     $result = $event->getControllerResult();
81
82     // Render the controller result into a response if it's a render array.
83     if (is_array($result) && ($request->query->has(static::WRAPPER_FORMAT) || $request->getRequestFormat() == 'html')) {
84       $wrapper = $request->query->get(static::WRAPPER_FORMAT, 'html');
85
86       // Fall back to HTML if the requested wrapper envelope is not available.
87       $wrapper = isset($this->mainContentRenderers[$wrapper]) ? $wrapper : 'html';
88
89       $renderer = $this->classResolver->getInstanceFromDefinition($this->mainContentRenderers[$wrapper]);
90       $response = $renderer->renderResponse($result, $request, $this->routeMatch);
91       // The main content render array is rendered into a different Response
92       // object, depending on the specified wrapper format.
93       if ($response instanceof CacheableResponseInterface) {
94         $main_content_view_subscriber_cacheability = (new CacheableMetadata())->setCacheContexts(['url.query_args:' . static::WRAPPER_FORMAT]);
95         $response->addCacheableDependency($main_content_view_subscriber_cacheability);
96       }
97       $event->setResponse($response);
98     }
99   }
100
101   /**
102    * {@inheritdoc}
103    */
104   public static function getSubscribedEvents() {
105     $events[KernelEvents::VIEW][] = ['onViewRenderArray'];
106
107     return $events;
108   }
109
110 }