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 | 29 | View Code Duplication | public function __construct( |
72 | CacheManager $cacheManager, |
||
73 | UrlGeneratorInterface $urlGenerator, |
||
74 | RuleMatcherInterface $mustInvalidateRule, |
||
75 | ExpressionLanguage $expressionLanguage = null |
||
76 | ) { |
||
77 | 29 | $this->cacheManager = $cacheManager; |
|
78 | 29 | $this->urlGenerator = $urlGenerator; |
|
79 | 29 | $this->expressionLanguage = $expressionLanguage ?: new ExpressionLanguage(); |
|
80 | 29 | $this->mustInvalidateRule = $mustInvalidateRule; |
|
81 | 29 | } |
|
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 | 23 | public static function getSubscribedEvents() |
|
143 | { |
||
144 | return [ |
||
145 | 23 | KernelEvents::TERMINATE => 'onKernelTerminate', |
|
146 | 23 | KernelEvents::EXCEPTION => 'onKernelException', |
|
147 | 23 | ConsoleEvents::TERMINATE => 'onConsoleTerminate', |
|
148 | 23 | ConsoleEvents::EXCEPTION => 'onConsoleTerminate', |
|
149 | ]; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Handle the invalidation annotations and configured invalidators. |
||
154 | * |
||
155 | * @param Request $request |
||
156 | * @param Response $response |
||
157 | */ |
||
158 | 10 | private function handleInvalidation(Request $request, Response $response) |
|
159 | { |
||
160 | // Check controller annotations |
||
161 | 10 | if ($paths = $request->attributes->get('_invalidate_path')) { |
|
162 | 4 | $this->invalidatePaths($paths); |
|
163 | } |
||
164 | |||
165 | 10 | if ($routes = $request->attributes->get('_invalidate_route')) { |
|
166 | 2 | $this->invalidateRoutes($routes, $request); |
|
167 | } |
||
168 | |||
169 | // Check configured invalidators |
||
170 | 10 | if (!$invalidatorConfigs = $this->matchRule($request, $response)) { |
|
0 ignored issues
–
show
|
|||
171 | 6 | return; |
|
172 | } |
||
173 | |||
174 | 4 | $requestParams = $request->attributes->get('_route_params'); |
|
175 | 4 | foreach ($invalidatorConfigs as $route => $config) { |
|
176 | 4 | $path = $this->urlGenerator->generate($route, $requestParams); |
|
177 | // If extra route parameters should be ignored, strip the query |
||
178 | // string generated by the Symfony router from the path |
||
179 | 4 | if (isset($config['ignore_extra_params']) |
|
180 | 4 | && $config['ignore_extra_params'] |
|
181 | 4 | && $pos = strpos($path, '?') |
|
182 | ) { |
||
183 | 1 | $path = substr($path, 0, $pos); |
|
184 | } |
||
185 | |||
186 | 4 | $this->cacheManager->invalidatePath($path); |
|
187 | } |
||
188 | 4 | } |
|
189 | |||
190 | /** |
||
191 | * Invalidate paths from annotations. |
||
192 | * |
||
193 | * @param array|InvalidatePath[] $pathConfigurations |
||
194 | */ |
||
195 | 4 | private function invalidatePaths(array $pathConfigurations) |
|
196 | { |
||
197 | 4 | foreach ($pathConfigurations as $pathConfiguration) { |
|
198 | 4 | foreach ($pathConfiguration->getPaths() as $path) { |
|
199 | 4 | $this->cacheManager->invalidatePath($path); |
|
200 | } |
||
201 | } |
||
202 | 4 | } |
|
203 | |||
204 | /** |
||
205 | * Invalidate routes from annotations. |
||
206 | * |
||
207 | * @param array|InvalidateRoute[] $routes |
||
208 | * @param Request $request |
||
209 | */ |
||
210 | 2 | private function invalidateRoutes(array $routes, Request $request) |
|
211 | { |
||
212 | 2 | $values = $request->attributes->all(); |
|
213 | // if there is an attribute called "request", it needs to be accessed through the request. |
||
214 | 2 | $values['request'] = $request; |
|
215 | |||
216 | 2 | foreach ($routes as $route) { |
|
217 | 2 | $params = []; |
|
218 | |||
219 | 2 | if (null !== $route->getParams()) { |
|
220 | // Iterate over route params and try to evaluate their values |
||
221 | 2 | foreach ($route->getParams() as $key => $value) { |
|
222 | 2 | if (is_array($value)) { |
|
223 | 2 | $value = $this->expressionLanguage->evaluate($value['expression'], $values); |
|
224 | } |
||
225 | |||
226 | 2 | $params[$key] = $value; |
|
227 | } |
||
228 | } |
||
229 | |||
230 | 2 | $this->cacheManager->invalidateRoute($route->getName(), $params); |
|
231 | } |
||
232 | 2 | } |
|
233 | } |
||
234 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.