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