1 | <?php |
||
35 | class InvalidationSubscriber extends AbstractRuleSubscriber implements EventSubscriberInterface |
||
36 | { |
||
37 | /** |
||
38 | * Cache manager. |
||
39 | * |
||
40 | * @var CacheManager |
||
41 | */ |
||
42 | private $cacheManager; |
||
43 | |||
44 | /** |
||
45 | * Router. |
||
46 | * |
||
47 | * @var UrlGeneratorInterface |
||
48 | */ |
||
49 | private $urlGenerator; |
||
50 | |||
51 | /** |
||
52 | * Router. |
||
53 | * |
||
54 | * @var ExpressionLanguage|null |
||
55 | */ |
||
56 | private $expressionLanguage; |
||
57 | |||
58 | /** |
||
59 | * Constructor. |
||
60 | * |
||
61 | * @param CacheManager $cacheManager |
||
62 | * @param UrlGeneratorInterface $urlGenerator |
||
63 | * @param ExpressionLanguage|null $expressionLanguage |
||
64 | */ |
||
65 | 29 | public function __construct( |
|
66 | CacheManager $cacheManager, |
||
67 | UrlGeneratorInterface $urlGenerator, |
||
68 | ExpressionLanguage $expressionLanguage = null |
||
69 | ) { |
||
70 | 29 | $this->cacheManager = $cacheManager; |
|
71 | 29 | $this->urlGenerator = $urlGenerator; |
|
72 | 29 | $this->expressionLanguage = $expressionLanguage; |
|
73 | 29 | } |
|
74 | |||
75 | /** |
||
76 | * Apply invalidators and flush cache manager. |
||
77 | * |
||
78 | * On kernel.terminate: |
||
79 | * - see if any invalidators apply to the current request and, if so, add |
||
80 | * their routes to the cache manager; |
||
81 | * - flush the cache manager in order to send invalidation requests to the |
||
82 | * HTTP cache. |
||
83 | * |
||
84 | * @param PostResponseEvent $event |
||
85 | */ |
||
86 | 19 | public function onKernelTerminate(PostResponseEvent $event) |
|
105 | |||
106 | /** |
||
107 | * Flush cache manager when kernel exception occurs. |
||
108 | */ |
||
109 | 2 | public function onKernelException() |
|
110 | { |
||
111 | try { |
||
112 | 2 | $this->cacheManager->flush(); |
|
113 | 2 | } catch (ExceptionCollection $e) { |
|
114 | // swallow exception |
||
115 | // there is the fos_http_cache.event_listener.log to log them |
||
116 | } |
||
117 | 2 | } |
|
118 | |||
119 | /** |
||
120 | * Flush cache manager when console terminates or errors. |
||
121 | * |
||
122 | * @throws ExceptionCollection If an exception occurs during flush. |
||
123 | */ |
||
124 | 9 | public function onConsoleTerminate(ConsoleEvent $event) |
|
125 | { |
||
126 | 9 | $num = $this->cacheManager->flush(); |
|
127 | |||
128 | 9 | if ($num > 0 && OutputInterface::VERBOSITY_VERBOSE <= $event->getOutput()->getVerbosity()) { |
|
129 | 5 | $event->getOutput()->writeln(sprintf('Sent %d invalidation request(s)', $num)); |
|
130 | 5 | } |
|
131 | 9 | } |
|
132 | |||
133 | /** |
||
134 | * {@inheritdoc} |
||
135 | */ |
||
136 | 23 | public static function getSubscribedEvents() |
|
137 | { |
||
138 | return array( |
||
139 | 23 | KernelEvents::TERMINATE => 'onKernelTerminate', |
|
140 | 23 | KernelEvents::EXCEPTION => 'onKernelException', |
|
141 | 23 | ConsoleEvents::TERMINATE => 'onConsoleTerminate', |
|
142 | 23 | ConsoleEvents::EXCEPTION => 'onConsoleTerminate', |
|
143 | 23 | ); |
|
144 | } |
||
145 | |||
146 | /** |
||
147 | * Handle the invalidation annotations and configured invalidators. |
||
148 | * |
||
149 | * @param Request $request |
||
150 | * @param Response $response |
||
151 | */ |
||
152 | 15 | private function handleInvalidation(Request $request, Response $response) |
|
153 | { |
||
154 | // Check controller annotations |
||
155 | 15 | if ($paths = $request->attributes->get('_invalidate_path')) { |
|
156 | 4 | $this->invalidatePaths($paths); |
|
157 | 4 | } |
|
158 | |||
159 | 15 | if ($routes = $request->attributes->get('_invalidate_route')) { |
|
160 | 2 | $this->invalidateRoutes($routes, $request); |
|
161 | 2 | } |
|
162 | |||
163 | // Check configured invalidators |
||
164 | 15 | if (!$invalidatorConfigs = $this->matchRule($request, $response)) { |
|
165 | 11 | return; |
|
166 | } |
||
167 | |||
168 | 4 | $requestParams = $request->attributes->get('_route_params'); |
|
169 | 4 | foreach ($invalidatorConfigs as $route => $config) { |
|
170 | 4 | $path = $this->urlGenerator->generate($route, $requestParams); |
|
171 | // If extra route parameters should be ignored, strip the query |
||
172 | // string generated by the Symfony router from the path |
||
173 | 4 | if (isset($config['ignore_extra_params']) |
|
174 | 4 | && $config['ignore_extra_params'] |
|
175 | 4 | && $pos = strpos($path, '?') |
|
176 | 4 | ) { |
|
177 | 1 | $path = substr($path, 0, $pos); |
|
178 | 1 | } |
|
179 | |||
180 | 4 | $this->cacheManager->invalidatePath($path); |
|
181 | 4 | } |
|
182 | 4 | } |
|
183 | |||
184 | /** |
||
185 | * Invalidate paths from annotations. |
||
186 | * |
||
187 | * @param array|InvalidatePath[] $pathConfigurations |
||
188 | */ |
||
189 | 4 | private function invalidatePaths(array $pathConfigurations) |
|
190 | { |
||
191 | 4 | foreach ($pathConfigurations as $pathConfiguration) { |
|
192 | 4 | foreach ($pathConfiguration->getPaths() as $path) { |
|
193 | 4 | $this->cacheManager->invalidatePath($path); |
|
194 | 4 | } |
|
195 | 4 | } |
|
196 | 4 | } |
|
197 | |||
198 | /** |
||
199 | * Invalidate routes from annotations. |
||
200 | * |
||
201 | * @param array|InvalidateRoute[] $routes |
||
202 | * @param Request $request |
||
203 | */ |
||
204 | 2 | private function invalidateRoutes(array $routes, Request $request) |
|
227 | |||
228 | /** |
||
229 | * Delay instantiating the expression language instance until we need it, |
||
230 | * to support a setup with only symfony 2.3. |
||
231 | * |
||
232 | * @return ExpressionLanguage |
||
233 | */ |
||
234 | 2 | private function getExpressionLanguage() |
|
242 | } |
||
243 |