1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the FOSHttpCache 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\HttpCache\SymfonyCache; |
13
|
|
|
|
14
|
|
|
use Symfony\Component\HttpFoundation\Response; |
15
|
|
|
use Symfony\Component\OptionsResolver\OptionsResolver; |
16
|
|
|
use Toflar\Psr6HttpCacheStore\Psr6StoreInterface; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Purge handler for the symfony built-in HttpCache. |
20
|
|
|
* |
21
|
|
|
* @author David Buchmann <[email protected]> |
22
|
|
|
* @author Yanick Witschi <[email protected]> |
23
|
|
|
* |
24
|
|
|
* {@inheritdoc} |
25
|
|
|
*/ |
26
|
|
|
class PurgeListener extends AccessControlledListener |
27
|
|
|
{ |
28
|
|
|
const DEFAULT_PURGE_METHOD = 'PURGE'; |
29
|
|
|
|
30
|
|
|
const DEFAULT_CLEAR_CACHE_HEADER = 'Clear-Cache'; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* The purge method to use. |
34
|
|
|
* |
35
|
|
|
* @var string |
36
|
|
|
*/ |
37
|
|
|
private $purgeMethod; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* The clear cache header to use. |
41
|
|
|
* |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
private $clearCacheHeader; |
45
|
|
|
|
46
|
8 |
|
/** |
47
|
|
|
* When creating the purge listener, you can configure an additional option. |
48
|
8 |
|
* |
49
|
|
|
* - purge_method: HTTP method that identifies purge requests. |
50
|
6 |
|
* |
51
|
6 |
|
* @param array $options Options to overwrite the default options |
52
|
|
|
* |
53
|
|
|
* @throws \InvalidArgumentException if unknown keys are found in $options |
54
|
|
|
* |
55
|
|
|
* @see AccessControlledListener::__construct |
56
|
1 |
|
*/ |
57
|
|
|
public function __construct(array $options = []) |
58
|
|
|
{ |
59
|
1 |
|
parent::__construct($options); |
60
|
|
|
|
61
|
|
|
$options = $this->getOptionsResolver()->resolve($options); |
62
|
|
|
$this->purgeMethod = $options['purge_method']; |
63
|
|
|
$this->clearCacheHeader = $options['clear_cache_header']; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* {@inheritdoc} |
68
|
|
|
*/ |
69
|
|
|
public static function getSubscribedEvents() |
70
|
5 |
|
{ |
71
|
|
|
return [ |
72
|
5 |
|
Events::PRE_INVALIDATE => 'handlePurge', |
73
|
5 |
|
]; |
74
|
1 |
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
4 |
|
* Look at unsafe requests and handle purge requests. |
78
|
2 |
|
* |
79
|
|
|
* Prevents access when the request comes from a non-authorized client. |
80
|
2 |
|
* |
81
|
|
|
* @param CacheEvent $event |
82
|
|
|
*/ |
83
|
2 |
|
public function handlePurge(CacheEvent $event) |
84
|
2 |
|
{ |
85
|
1 |
|
$request = $event->getRequest(); |
86
|
|
|
if ($this->purgeMethod !== $request->getMethod()) { |
87
|
1 |
|
return; |
88
|
|
|
} |
89
|
2 |
|
|
90
|
2 |
|
if (!$this->isRequestAllowed($request)) { |
91
|
|
|
$event->setResponse(new Response('', 400)); |
92
|
|
|
|
93
|
|
|
return; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
$response = new Response(); |
97
|
8 |
|
$store = $event->getKernel()->getStore(); |
98
|
|
|
|
99
|
8 |
|
// Purge whole cache |
100
|
8 |
|
if ($request->headers->has($this->clearCacheHeader)) { |
101
|
8 |
View Code Duplication |
if (!$store instanceof Psr6StoreInterface) { |
|
|
|
|
102
|
|
|
$response->setStatusCode(400); |
103
|
8 |
|
$response->setContent('Store must be an instance of '.Psr6StoreInterface::class.'. Please check your proxy configuration.'); |
104
|
|
|
$event->setResponse($response); |
105
|
|
|
|
106
|
|
|
return; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$store->prune(); |
110
|
|
|
|
111
|
|
|
$response->setStatusCode(200, 'Pruned'); |
112
|
|
|
$event->setResponse($response); |
113
|
|
|
|
114
|
|
|
return; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
if ($store->purge($request->getUri())) { |
118
|
|
|
$response->setStatusCode(200, 'Purged'); |
119
|
|
|
} else { |
120
|
|
|
$response->setStatusCode(200, 'Not found'); |
121
|
|
|
} |
122
|
|
|
$event->setResponse($response); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Add the purge_method option. |
127
|
|
|
* |
128
|
|
|
* @return OptionsResolver |
129
|
|
|
*/ |
130
|
|
View Code Duplication |
protected function getOptionsResolver() |
|
|
|
|
131
|
|
|
{ |
132
|
|
|
$resolver = parent::getOptionsResolver(); |
133
|
|
|
$resolver->setDefault('purge_method', static::DEFAULT_PURGE_METHOD); |
134
|
|
|
$resolver->setDefault('clear_cache_header', static::DEFAULT_CLEAR_CACHE_HEADER); |
135
|
|
|
$resolver->setAllowedTypes('purge_method', 'string'); |
136
|
|
|
$resolver->setAllowedTypes('clear_cache_header', 'string'); |
137
|
|
|
|
138
|
|
|
return $resolver; |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.