Completed
Pull Request — master (#476)
by Karel
04:58
created

SessionListener::onFinishRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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 Symfony\Component\EventDispatcher\EventSubscriberInterface;
15
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
16
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
17
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
18
use Symfony\Component\HttpKernel\EventListener\SessionListener as BaseSessionListener;
19
20
/**
21
 * Decorates the default Symfony session listener.
22
 *
23
 * Since Symfony 3.4, the default Symfony session listener automatically
24
 * overwrites the Cache-Control headers to `private` in case the session has
25
 * been started. This destroys the user context feature of FOSHttpCache.
26
 * Since Symfony 4.1, there is a header we can set to skip this behaviour. We
27
 * set that header in UserContextListener.
28
 * For Symfony 3.4 and 4.0, we decorate the listener to only call the default
29
 * behaviour if `Vary` contains neither the context hash header nor any of the
30
 * user identifier headers, to avoid impacts on other parts of your application.
31
 *
32
 * @author Yanick Witschi <[email protected]>
33
 */
34
final class SessionListener implements EventSubscriberInterface
35
{
36
    /**
37
     * @var BaseSessionListener
38
     */
39
    private $inner;
40
41
    /**
42
     * @var string
43
     */
44
    private $userHashHeader;
45
46
    /**
47
     * @var array
48
     */
49
    private $userIdentifierHeaders;
50
51
    /**
52
     * @param BaseSessionListener $inner
53
     * @param string              $userHashHeader        Must be lower-cased
54
     * @param array               $userIdentifierHeaders Must be lower-cased
55
     */
56 7
    public function __construct(BaseSessionListener $inner, string $userHashHeader, array $userIdentifierHeaders)
57
    {
58 7
        $this->inner = $inner;
59 7
        $this->userHashHeader = $userHashHeader;
60 7
        $this->userIdentifierHeaders = $userIdentifierHeaders;
61 7
    }
62
63 1
    public function onKernelRequest(GetResponseEvent $event)
64
    {
65 1
        return $this->inner->onKernelRequest($event);
66
    }
67
68 5
    public function onKernelResponse(FilterResponseEvent $event)
69
    {
70 5
        if (!$event->isMasterRequest()) {
71
            return;
72
        }
73
74 5
        $varyHeaders = array_map('strtolower', $event->getResponse()->getVary());
75 5
        $relevantHeaders = array_merge($this->userIdentifierHeaders, [$this->userHashHeader]);
76
77
        // Call default behaviour if it's an irrelevant request for the user context
78 5
        if (0 === count(array_intersect($varyHeaders, $relevantHeaders))) {
79 2
            $this->inner->onKernelResponse($event);
80
        }
81
82
        // noop, see class description
83 5
    }
84
85 1
    public function onFinishRequest(FinishRequestEvent $event)
86
    {
87
        // this hook has been added in symfony 3.4.12 - older versions of the listener do not register for it
88 1
        $this->inner->onFinishRequest($event);
89 1
    }
90
91
    public static function getSubscribedEvents(): array
92
    {
93
        return BaseSessionListener::getSubscribedEvents();
94
    }
95
}
96