CustomTtlListener::useCustomTtl()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 12
ccs 9
cts 9
cp 1
crap 3
rs 10
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\EventDispatcher\EventSubscriberInterface;
15
16
/**
17
 * Custom TTL handler for the symfony built-in HttpCache.
18
 *
19
 * This allows to use a custom header to control time to live in HttpCache and
20
 * keep s-maxage for 3rd party proxies.
21
 *
22
 * @author David Buchmann <[email protected]>
23
 *
24
 * {@inheritdoc}
25
 */
26
class CustomTtlListener implements EventSubscriberInterface
27
{
28
    /**
29
     * @var string
30
     */
31
    private $ttlHeader;
32
33
    /**
34
     * @var bool
35
     */
36
    private $keepTtlHeader;
37
38
    /**
39
     * Header used for backing up the s-maxage.
40
     *
41
     * @var string
42
     */
43
    public const SMAXAGE_BACKUP = 'FOS-Smaxage-Backup';
44
45
    /**
46
     * @param string $ttlHeader     The header name that is used to specify the time to live
47
     * @param bool   $keepTtlHeader Keep the custom TTL header on the response for later usage (e.g. debugging)
48
     */
49 7
    public function __construct($ttlHeader = 'X-Reverse-Proxy-TTL', $keepTtlHeader = false)
50
    {
51 7
        $this->ttlHeader = $ttlHeader;
52 7
        $this->keepTtlHeader = $keepTtlHeader;
53 7
    }
54
55
    /**
56
     * Use the TTL from the custom header rather than the default one.
57
     *
58
     * If there is such a header, the original s_maxage is backed up to the
59
     * static::SMAXAGE_BACKUP header.
60
     */
61 3
    public function useCustomTtl(CacheEvent $e)
62
    {
63 3
        $response = $e->getResponse();
64 3
        if (!$response->headers->has($this->ttlHeader)) {
65 1
            return;
66
        }
67 2
        $backup = $response->headers->hasCacheControlDirective('s-maxage')
68 1
            ? $response->headers->getCacheControlDirective('s-maxage')
69 2
            : 'false'
70
        ;
71 2
        $response->headers->set(static::SMAXAGE_BACKUP, $backup);
0 ignored issues
show
Bug introduced by
It seems like $backup can also be of type boolean; however, parameter $values of Symfony\Component\HttpFo...esponseHeaderBag::set() does only seem to accept array|null|string, maybe add an additional type check? ( Ignorable by Annotation )

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

71
        $response->headers->set(static::SMAXAGE_BACKUP, /** @scrutinizer ignore-type */ $backup);
Loading history...
72 2
        $response->setTtl($response->headers->get($this->ttlHeader));
0 ignored issues
show
Bug introduced by
$response->headers->get($this->ttlHeader) of type string is incompatible with the type integer expected by parameter $seconds of Symfony\Component\HttpFo...tion\Response::setTtl(). ( Ignorable by Annotation )

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

72
        $response->setTtl(/** @scrutinizer ignore-type */ $response->headers->get($this->ttlHeader));
Loading history...
73 2
    }
74
75
    /**
76
     * Remove the custom TTL header and restore s_maxage from the backup.
77
     */
78 4
    public function cleanResponse(CacheEvent $e)
79
    {
80 4
        $response = $e->getResponse();
81 4
        if (!$response->headers->has($this->ttlHeader)
82 4
            && !$response->headers->has(static::SMAXAGE_BACKUP)
83
        ) {
84 1
            return;
85
        }
86
87 3
        if ($response->headers->has(static::SMAXAGE_BACKUP)) {
88 2
            $smaxage = $response->headers->get(static::SMAXAGE_BACKUP);
89 2
            if ('false' === $smaxage) {
90 1
                $response->headers->removeCacheControlDirective('s-maxage');
91
            } else {
92 1
                $response->headers->addCacheControlDirective('s-maxage', $smaxage);
93
            }
94
        }
95
96 3
        if (!$this->keepTtlHeader) {
97 3
            $response->headers->remove($this->ttlHeader);
98
        }
99 3
        $response->headers->remove(static::SMAXAGE_BACKUP);
100 3
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 1
    public static function getSubscribedEvents(): array
106
    {
107
        return [
108 1
            Events::PRE_STORE => 'useCustomTtl',
109 1
            Events::POST_HANDLE => 'cleanResponse',
110
        ];
111
    }
112
}
113