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\HttpCacheBundle\CacheManager; |
||
15 | use FOS\HttpCacheBundle\Configuration\Tag; |
||
16 | use FOS\HttpCacheBundle\Http\RuleMatcherInterface; |
||
17 | use FOS\HttpCacheBundle\Http\SymfonyResponseTagger; |
||
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||
19 | use Symfony\Component\ExpressionLanguage\ExpressionLanguage; |
||
20 | use Symfony\Component\HttpFoundation\Request; |
||
21 | use Symfony\Component\HttpKernel\Event\FilterResponseEvent; |
||
22 | use Symfony\Component\HttpKernel\HttpKernelInterface; |
||
23 | use Symfony\Component\HttpKernel\KernelEvents; |
||
24 | |||
25 | /** |
||
26 | * Event handler for the cache tagging tags. |
||
27 | * |
||
28 | * @author David de Boer <[email protected]> |
||
29 | */ |
||
30 | class TagListener extends AbstractRuleListener implements EventSubscriberInterface |
||
31 | { |
||
32 | /** |
||
33 | * @var CacheManager |
||
34 | */ |
||
35 | private $cacheManager; |
||
36 | |||
37 | /** |
||
38 | * @var SymfonyResponseTagger |
||
39 | */ |
||
40 | private $symfonyResponseTagger; |
||
41 | |||
42 | /** |
||
43 | * @var ExpressionLanguage |
||
44 | */ |
||
45 | private $expressionLanguage; |
||
46 | |||
47 | /** |
||
48 | * @var RuleMatcherInterface |
||
49 | */ |
||
50 | private $mustInvalidateRule; |
||
51 | |||
52 | /** |
||
53 | * @var RuleMatcherInterface |
||
54 | */ |
||
55 | private $cacheableRule; |
||
56 | |||
57 | /** |
||
58 | * Constructor. |
||
59 | * |
||
60 | * @param CacheManager $cacheManager |
||
61 | * @param SymfonyResponseTagger $tagHandler |
||
62 | * @param ExpressionLanguage|null $expressionLanguage |
||
63 | */ |
||
64 | 24 | View Code Duplication | public function __construct( |
0 ignored issues
–
show
|
|||
65 | CacheManager $cacheManager, |
||
66 | SymfonyResponseTagger $tagHandler, |
||
67 | RuleMatcherInterface $cacheableRule, |
||
68 | RuleMatcherInterface $mustInvalidateRule, |
||
69 | ExpressionLanguage $expressionLanguage = null |
||
70 | ) { |
||
71 | 24 | $this->cacheManager = $cacheManager; |
|
72 | 24 | $this->symfonyResponseTagger = $tagHandler; |
|
73 | 24 | $this->cacheableRule = $cacheableRule; |
|
74 | 24 | $this->mustInvalidateRule = $mustInvalidateRule; |
|
75 | 24 | $this->expressionLanguage = $expressionLanguage ?: new ExpressionLanguage(); |
|
76 | 24 | } |
|
77 | |||
78 | /** |
||
79 | * Process the _tags request attribute, which is set when using the Tag |
||
80 | * annotation. |
||
81 | * |
||
82 | * - For a safe (GET or HEAD) request, the tags are set on the response. |
||
83 | * - For a non-safe request, the tags will be invalidated. |
||
84 | * |
||
85 | * @param FilterResponseEvent $event |
||
86 | */ |
||
87 | 24 | public function onKernelResponse(FilterResponseEvent $event) |
|
88 | { |
||
89 | 24 | $request = $event->getRequest(); |
|
90 | 24 | $response = $event->getResponse(); |
|
91 | |||
92 | 24 | if (!$this->cacheableRule->matches($request, $response) |
|
93 | 24 | && !$this->mustInvalidateRule->matches($request, $response) |
|
94 | ) { |
||
95 | 4 | return; |
|
96 | } |
||
97 | |||
98 | 20 | $tags = $this->getAnnotationTags($request); |
|
99 | |||
100 | 20 | $configuredTags = $this->matchRule($request, $response); |
|
101 | 20 | if ($configuredTags) { |
|
102 | 5 | $tags = array_merge($tags, $configuredTags['tags']); |
|
103 | 5 | foreach ($configuredTags['expressions'] as $expression) { |
|
104 | 5 | $tags[] = $this->evaluateTag($expression, $request); |
|
105 | } |
||
106 | } |
||
107 | |||
108 | 20 | if ($this->cacheableRule->matches($request, $response)) { |
|
109 | // For safe requests (GET and HEAD), set cache tags on response |
||
110 | 12 | $this->symfonyResponseTagger->addTags($tags); |
|
111 | 12 | if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) { |
|
112 | 12 | $this->symfonyResponseTagger->tagSymfonyResponse($response); |
|
113 | } |
||
114 | 8 | } elseif (count($tags) |
|
115 | 8 | && $this->mustInvalidateRule->matches($request, $response) |
|
116 | ) { |
||
117 | 4 | $this->cacheManager->invalidateTags($tags); |
|
118 | } |
||
119 | 20 | } |
|
120 | |||
121 | /** |
||
122 | * {@inheritdoc} |
||
123 | */ |
||
124 | 23 | public static function getSubscribedEvents() |
|
125 | { |
||
126 | return [ |
||
127 | 23 | KernelEvents::RESPONSE => 'onKernelResponse', |
|
128 | ]; |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Get the tags from the annotations on the controller that was used in the |
||
133 | * request. |
||
134 | * |
||
135 | * @param Request $request |
||
136 | * |
||
137 | * @return array List of tags affected by the request |
||
138 | */ |
||
139 | 20 | private function getAnnotationTags(Request $request) |
|
140 | { |
||
141 | // Check for _tag request attribute that is set when using @Tag |
||
142 | // annotation |
||
143 | /** @var $tagConfigurations Tag[] */ |
||
144 | 20 | if (!$tagConfigurations = $request->attributes->get('_tag')) { |
|
145 | 9 | return []; |
|
146 | } |
||
147 | |||
148 | 11 | $tags = []; |
|
149 | 11 | foreach ($tagConfigurations as $tagConfiguration) { |
|
150 | 11 | if (null !== $tagConfiguration->getExpression()) { |
|
151 | 3 | $tags[] = $this->evaluateTag( |
|
152 | 3 | $tagConfiguration->getExpression(), |
|
153 | 3 | $request |
|
154 | ); |
||
155 | } else { |
||
156 | 11 | $tags = array_merge($tags, $tagConfiguration->getTags()); |
|
157 | } |
||
158 | } |
||
159 | |||
160 | 11 | return $tags; |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * Evaluate a tag that contains expressions. |
||
165 | * |
||
166 | * @param string $expression |
||
167 | * @param Request $request |
||
168 | * |
||
169 | * @return string Evaluated tag |
||
170 | */ |
||
171 | 8 | private function evaluateTag($expression, Request $request) |
|
172 | { |
||
173 | 8 | $values = $request->attributes->all(); |
|
174 | // if there is an attribute called "request", it needs to be accessed through the request. |
||
175 | 8 | $values['request'] = $request; |
|
176 | |||
177 | 8 | return $this->expressionLanguage->evaluate($expression, $values); |
|
178 | } |
||
179 | } |
||
180 |
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.