Version 1
[yaffs-website] / web / core / lib / Drupal / Core / DependencyInjection / Compiler / StackedKernelPass.php
1 <?php
2
3 namespace Drupal\Core\DependencyInjection\Compiler;
4
5 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6 use Symfony\Component\DependencyInjection\ContainerBuilder;
7 use Symfony\Component\DependencyInjection\Reference;
8
9 /**
10  * Provides a compiler pass for stacked HTTP kernels.
11  *
12  * Builds the HTTP kernel by collecting all services tagged 'http_middleware'
13  * and assembling them into a StackedKernel. The middleware with the highest
14  * priority ends up as the outermost while the lowest priority middleware wraps
15  * the actual HTTP kernel defined by the http_kernel.basic service.
16  *
17  * The 'http_middleware' service tag additionally accepts a 'responder'
18  * parameter. It should be set to TRUE if many or most requests will be handled
19  * directly by the middleware. Any underlying middleware and the HTTP kernel are
20  * then flagged as 'lazy'. As a result those low priority services and their
21  * dependencies are only initialized if the 'responder' middleware fails to
22  * generate a response and the request is delegated to the underlying kernel.
23  *
24  * In general middlewares should not have heavy dependencies. This is especially
25  * important for high-priority services which need to run before the internal
26  * page cache.
27  *
28  * An example of a high priority middleware.
29  * @code
30  * http_middleware.reverse_proxy:
31  *   class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
32  *   arguments: ['@settings']
33  *   tags:
34  *     - { name: http_middleware, priority: 300 }
35  * @endcode
36  *
37  * An example of a responder middleware:
38  * @code
39  * http_middleware.page_cache:
40  *   class: Drupal\page_cache\StackMiddleware\PageCache
41  *   arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy']
42  *   tags:
43  *     - { name: http_middleware, priority: 200, responder: true }
44  * @endcode
45  *
46  * @see \Stack\Builder
47  */
48 class StackedKernelPass implements CompilerPassInterface {
49
50   /**
51    * {@inheritdoc}
52    */
53   public function process(ContainerBuilder $container) {
54
55     if (!$container->hasDefinition('http_kernel')) {
56       return;
57     }
58
59     $stacked_kernel = $container->getDefinition('http_kernel');
60
61     // Return now if this is not a stacked kernel.
62     if ($stacked_kernel->getClass() !== 'Stack\StackedHttpKernel') {
63       return;
64     }
65
66     $middlewares = [];
67     $priorities = [];
68     $responders = [];
69
70     foreach ($container->findTaggedServiceIds('http_middleware') as $id => $attributes) {
71       $priorities[$id] = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
72       $middlewares[$id] = $container->getDefinition($id);
73       $responders[$id] = !empty($attributes[0]['responder']);
74     }
75
76     array_multisort($priorities, SORT_ASC, $middlewares, $responders);
77
78     $decorated_id = 'http_kernel.basic';
79     $middlewares_param = [new Reference($decorated_id)];
80
81     $first_responder = array_search(TRUE, array_reverse($responders, TRUE), TRUE);
82     if ($first_responder) {
83       $container->getDefinition($decorated_id)->setLazy(TRUE);
84     }
85
86     foreach ($middlewares as $id => $decorator) {
87       // Prepend a reference to the middlewares container parameter.
88       array_unshift($middlewares_param, new Reference($id));
89
90       // Prepend the inner kernel as first constructor argument.
91       $arguments = $decorator->getArguments();
92       array_unshift($arguments, new Reference($decorated_id));
93       $decorator->setArguments($arguments);
94
95       if ($first_responder === $id) {
96         $first_responder = FALSE;
97       }
98       elseif ($first_responder) {
99         $decorator->setLazy(TRUE);
100       }
101
102       $decorated_id = $id;
103     }
104
105     $arguments = [$middlewares_param[0], $middlewares_param];
106     $stacked_kernel->setArguments($arguments);
107   }
108
109 }