These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the FOSHttpCacheBundle package. |
||
5 | * |
||
6 | * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace FOS\HttpCacheBundle\EventListener; |
||
13 | |||
14 | use FOS\HttpCache\Exception\ExceptionCollection; |
||
15 | use FOS\HttpCacheBundle\CacheManager; |
||
16 | use FOS\HttpCacheBundle\Configuration\InvalidatePath; |
||
17 | use FOS\HttpCacheBundle\Configuration\InvalidateRoute; |
||
18 | use FOS\HttpCacheBundle\Http\RuleMatcherInterface; |
||
19 | use Symfony\Component\Console\ConsoleEvents; |
||
20 | use Symfony\Component\Console\Event\ConsoleEvent; |
||
21 | use Symfony\Component\Console\Output\OutputInterface; |
||
22 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||
23 | use Symfony\Component\ExpressionLanguage\ExpressionLanguage; |
||
24 | use Symfony\Component\HttpFoundation\Request; |
||
25 | use Symfony\Component\HttpFoundation\Response; |
||
26 | use Symfony\Component\HttpKernel\Event\PostResponseEvent; |
||
27 | use Symfony\Component\HttpKernel\KernelEvents; |
||
28 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||
29 | |||
30 | /** |
||
31 | * On kernel.terminate event, this event handler invalidates routes for the |
||
32 | * current request and flushes the CacheManager. |
||
33 | * |
||
34 | * @author David de Boer <[email protected]> |
||
35 | */ |
||
36 | class InvalidationListener extends AbstractRuleListener implements EventSubscriberInterface |
||
37 | { |
||
38 | /** |
||
39 | * Cache manager. |
||
40 | * |
||
41 | * @var CacheManager |
||
42 | */ |
||
43 | private $cacheManager; |
||
44 | |||
45 | /** |
||
46 | * Router. |
||
47 | * |
||
48 | * @var UrlGeneratorInterface |
||
49 | */ |
||
50 | private $urlGenerator; |
||
51 | |||
52 | /** |
||
53 | * Router. |
||
54 | * |
||
55 | * @var ExpressionLanguage|null |
||
56 | */ |
||
57 | private $expressionLanguage; |
||
58 | |||
59 | /** |
||
60 | * @var RuleMatcherInterface |
||
61 | */ |
||
62 | private $mustInvalidateRule; |
||
63 | |||
64 | /** |
||
65 | * Constructor. |
||
66 | * |
||
67 | * @param CacheManager $cacheManager |
||
68 | * @param UrlGeneratorInterface $urlGenerator |
||
69 | * @param ExpressionLanguage|null $expressionLanguage |
||
70 | */ |
||
71 | 30 | View Code Duplication | public function __construct( |
0 ignored issues
–
show
|
|||
72 | CacheManager $cacheManager, |
||
73 | UrlGeneratorInterface $urlGenerator, |
||
74 | RuleMatcherInterface $mustInvalidateRule, |
||
75 | ExpressionLanguage $expressionLanguage = null |
||
76 | ) { |
||
77 | 30 | $this->cacheManager = $cacheManager; |
|
78 | 30 | $this->urlGenerator = $urlGenerator; |
|
79 | 30 | $this->expressionLanguage = $expressionLanguage ?: new ExpressionLanguage(); |
|
80 | 30 | $this->mustInvalidateRule = $mustInvalidateRule; |
|
81 | 30 | } |
|
82 | |||
83 | /** |
||
84 | * Apply invalidators and flush cache manager. |
||
85 | * |
||
86 | * On kernel.terminate: |
||
87 | * - see if any invalidators apply to the current request and, if so, add |
||
88 | * their routes to the cache manager; |
||
89 | * - flush the cache manager in order to send invalidation requests to the |
||
90 | * HTTP cache. |
||
91 | * |
||
92 | * @param PostResponseEvent $event |
||
93 | */ |
||
94 | 19 | public function onKernelTerminate(PostResponseEvent $event) |
|
95 | { |
||
96 | 19 | $request = $event->getRequest(); |
|
97 | 19 | $response = $event->getResponse(); |
|
98 | |||
99 | // Don't invalidate any caches if the request was unsuccessful |
||
100 | 19 | if ($this->mustInvalidateRule->matches($request, $response)) { |
|
101 | 10 | $this->handleInvalidation($request, $response); |
|
102 | } |
||
103 | |||
104 | try { |
||
105 | 19 | $this->cacheManager->flush(); |
|
106 | } catch (ExceptionCollection $e) { |
||
107 | // swallow exception |
||
108 | // there is the fos_http_cache.event_listener.log to log them |
||
109 | } |
||
110 | 19 | } |
|
111 | |||
112 | /** |
||
113 | * Flush cache manager when kernel exception occurs. |
||
114 | */ |
||
115 | 1 | public function onKernelException() |
|
116 | { |
||
117 | try { |
||
118 | 1 | $this->cacheManager->flush(); |
|
119 | } catch (ExceptionCollection $e) { |
||
120 | // swallow exception |
||
121 | // there is the fos_http_cache.event_listener.log to log them |
||
122 | } |
||
123 | 1 | } |
|
124 | |||
125 | /** |
||
126 | * Flush cache manager when console terminates or errors. |
||
127 | * |
||
128 | * @throws ExceptionCollection If an exception occurs during flush |
||
129 | */ |
||
130 | 9 | public function onConsoleTerminate(ConsoleEvent $event) |
|
131 | { |
||
132 | 9 | $num = $this->cacheManager->flush(); |
|
133 | |||
134 | 9 | if ($num > 0 && OutputInterface::VERBOSITY_VERBOSE <= $event->getOutput()->getVerbosity()) { |
|
135 | 5 | $event->getOutput()->writeln(sprintf('Sent %d invalidation request(s)', $num)); |
|
136 | } |
||
137 | 9 | } |
|
138 | |||
139 | /** |
||
140 | * {@inheritdoc} |
||
141 | */ |
||
142 | 24 | public static function getSubscribedEvents() |
|
143 | { |
||
144 | return [ |
||
145 | 24 | KernelEvents::TERMINATE => 'onKernelTerminate', |
|
146 | 24 | KernelEvents::EXCEPTION => 'onKernelException', |
|
147 | 24 | ConsoleEvents::TERMINATE => 'onConsoleTerminate', |
|
148 | ]; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Handle the invalidation annotations and configured invalidators. |
||
153 | * |
||
154 | * @param Request $request |
||
155 | * @param Response $response |
||
156 | */ |
||
157 | 10 | private function handleInvalidation(Request $request, Response $response) |
|
158 | { |
||
159 | // Check controller annotations |
||
160 | 10 | if ($paths = $request->attributes->get('_invalidate_path')) { |
|
161 | 4 | $this->invalidatePaths($paths); |
|
162 | } |
||
163 | |||
164 | 10 | if ($routes = $request->attributes->get('_invalidate_route')) { |
|
165 | 2 | $this->invalidateRoutes($routes, $request); |
|
166 | } |
||
167 | |||
168 | // Check configured invalidators |
||
169 | 10 | if (!$invalidatorConfigs = $this->matchRule($request, $response)) { |
|
170 | 6 | return; |
|
171 | } |
||
172 | |||
173 | 4 | $requestParams = $request->attributes->get('_route_params'); |
|
174 | 4 | foreach ($invalidatorConfigs as $route => $config) { |
|
175 | 4 | $path = $this->urlGenerator->generate($route, $requestParams); |
|
176 | // If extra route parameters should be ignored, strip the query |
||
177 | // string generated by the Symfony router from the path |
||
178 | 4 | if (isset($config['ignore_extra_params']) |
|
179 | 4 | && $config['ignore_extra_params'] |
|
180 | 4 | && $pos = strpos($path, '?') |
|
181 | ) { |
||
182 | 1 | $path = substr($path, 0, $pos); |
|
183 | } |
||
184 | |||
185 | 4 | $this->cacheManager->invalidatePath($path); |
|
186 | } |
||
187 | 4 | } |
|
188 | |||
189 | /** |
||
190 | * Invalidate paths from annotations. |
||
191 | * |
||
192 | * @param array|InvalidatePath[] $pathConfigurations |
||
193 | */ |
||
194 | 4 | private function invalidatePaths(array $pathConfigurations) |
|
195 | { |
||
196 | 4 | foreach ($pathConfigurations as $pathConfiguration) { |
|
197 | 4 | foreach ($pathConfiguration->getPaths() as $path) { |
|
198 | 4 | $this->cacheManager->invalidatePath($path); |
|
199 | } |
||
200 | } |
||
201 | 4 | } |
|
202 | |||
203 | /** |
||
204 | * Invalidate routes from annotations. |
||
205 | * |
||
206 | * @param array|InvalidateRoute[] $routes |
||
207 | * @param Request $request |
||
208 | */ |
||
209 | 2 | private function invalidateRoutes(array $routes, Request $request) |
|
210 | { |
||
211 | 2 | $values = $request->attributes->all(); |
|
212 | // if there is an attribute called "request", it needs to be accessed through the request. |
||
213 | 2 | $values['request'] = $request; |
|
214 | |||
215 | 2 | foreach ($routes as $route) { |
|
216 | 2 | $params = []; |
|
217 | |||
218 | 2 | if (null !== $route->getParams()) { |
|
219 | // Iterate over route params and try to evaluate their values |
||
220 | 2 | foreach ($route->getParams() as $key => $value) { |
|
221 | 2 | if (is_array($value)) { |
|
222 | 2 | $value = $this->expressionLanguage->evaluate($value['expression'], $values); |
|
223 | } |
||
224 | |||
225 | 2 | $params[$key] = $value; |
|
226 | } |
||
227 | } |
||
228 | |||
229 | 2 | $this->cacheManager->invalidateRoute($route->getName(), $params); |
|
230 | } |
||
231 | 2 | } |
|
232 | } |
||
233 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.