PurgeListener::handlePurge()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6.1893

Importance

Changes 0
Metric Value
cc 6
eloc 23
c 0
b 0
f 0
nc 6
nop 1
dl 0
loc 40
ccs 19
cts 23
cp 0.8261
crap 6.1893
rs 8.9297
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\ClearableInterface;
0 ignored issues
show
Bug introduced by
The type Toflar\Psr6HttpCacheStore\ClearableInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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
    public const DEFAULT_PURGE_METHOD = 'PURGE';
29
30
    public 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
    /**
47
     * When creating the purge listener, you can configure an additional option.
48
     *
49
     * - purge_method: HTTP method that identifies purge requests.
50
     *
51
     * @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
     */
57 9
    public function __construct(array $options = [])
58
    {
59 9
        parent::__construct($options);
60
61 7
        $options = $this->getOptionsResolver()->resolve($options);
62 7
        $this->purgeMethod = $options['purge_method'];
63 7
        $this->clearCacheHeader = $options['clear_cache_header'];
64 7
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 1
    public static function getSubscribedEvents(): array
70
    {
71
        return [
72 1
            Events::PRE_INVALIDATE => 'handlePurge',
73
        ];
74
    }
75
76
    /**
77
     * Look at unsafe requests and handle purge requests.
78
     *
79
     * Prevents access when the request comes from a non-authorized client.
80
     */
81 6
    public function handlePurge(CacheEvent $event)
82
    {
83 6
        $request = $event->getRequest();
84 6
        if ($this->purgeMethod !== $request->getMethod()) {
85 1
            return;
86
        }
87
88 5
        if (!$this->isRequestAllowed($request)) {
89 2
            $event->setResponse(new Response('', 400));
90
91 2
            return;
92
        }
93
94 3
        $response = new Response();
95 3
        $store = $event->getKernel()->getStore();
0 ignored issues
show
Bug introduced by
The method getStore() does not exist on FOS\HttpCache\SymfonyCache\CacheInvalidation. Since it exists in all sub-types, consider adding an abstract or default implementation to FOS\HttpCache\SymfonyCache\CacheInvalidation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        $store = $event->getKernel()->/** @scrutinizer ignore-call */ getStore();
Loading history...
96
97
        // Purge whole cache
98 3
        if ($request->headers->has($this->clearCacheHeader)) {
99 1
            if (!$store instanceof ClearableInterface) {
100 1
                $response->setStatusCode(400);
101 1
                $response->setContent('Store must be an instance of '.ClearableInterface::class.'. Please check your proxy configuration.');
102 1
                $event->setResponse($response);
103
104 1
                return;
105
            }
106
107
            $store->clear();
108
109
            $response->setStatusCode(200, 'Purged');
110
            $event->setResponse($response);
111
112
            return;
113
        }
114
115 2
        if ($store->purge($request->getUri())) {
116 1
            $response->setStatusCode(200, 'Purged');
117
        } else {
118 1
            $response->setStatusCode(200, 'Not found');
119
        }
120 2
        $event->setResponse($response);
121 2
    }
122
123
    /**
124
     * Add the purge_method option.
125
     *
126
     * @return OptionsResolver
127
     */
128 9
    protected function getOptionsResolver()
129
    {
130 9
        $resolver = parent::getOptionsResolver();
131 9
        $resolver->setDefault('purge_method', static::DEFAULT_PURGE_METHOD);
132 9
        $resolver->setDefault('clear_cache_header', static::DEFAULT_CLEAR_CACHE_HEADER);
133 9
        $resolver->setAllowedTypes('purge_method', 'string');
134 9
        $resolver->setAllowedTypes('clear_cache_header', 'string');
135
136 9
        return $resolver;
137
    }
138
}
139