Completed
Push — master ( b1744c...51aee2 )
by Matze
04:34
created

Cache::generateCacheKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace BrainExe\Core\Middleware;
4
5
use BrainExe\Annotations\Annotations\Inject;
6
use BrainExe\Core\Annotations\Middleware;
7
use BrainExe\Core\Traits\CacheTrait;
8
use BrainExe\Core\Traits\LoggerTrait;
9
use DateTime;
10
use Symfony\Component\Cache\Adapter\AdapterInterface;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\Routing\Route;
14
15
/**
16
 * @todo X-Invalidate
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
17
 * @Middleware("Middleware.Cache")
18
 */
19
class Cache extends AbstractMiddleware
20
{
21
    use CacheTrait;
22
    use LoggerTrait;
23
24
    const DEFAULT_TTL = 60;
25
    const PREFIX = 'cache:';
26
27
    /**
28
     * @var bool
29
     */
30
    private $enabled;
31
32
    /**
33
     * @Inject("%cache.enabled%")
34
     * @param bool $cacheEnabled
35
     */
36 3
    public function __construct(bool $cacheEnabled)
37
    {
38 3
        $this->enabled = $cacheEnabled;
39 3
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 3
    public function processRequest(Request $request, Route $route)
45
    {
46 3
        if (!$this->enabled || !$route->hasOption('cache') || !$request->isMethod('GET')) {
47 1
            return null;
48
        }
49
50 2
        $cacheKey = $this->generateCacheKey($request);
51
52 2
        $ttl   = $route->getOption('cache');
53 2
        $cache = $this->getCache();
54 2
        if ($cache->hasItem($cacheKey)) {
55 1
            return $this->handleCached($cache, $cacheKey, $ttl);
56
        }
57
58
        // enable cache for current request. Store response later in given key
59 1
        $request->attributes->set('_cacheKey', $cacheKey);
60 1
        $request->attributes->set('_cacheTTL', $ttl);
61
62 1
        return null;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 2
    public function processResponse(Request $request, Response $response)
69
    {
70 2
        if (!$response->isOk()) {
71 1
            return;
72
        }
73
74 2
        $cacheKey = $request->attributes->get('_cacheKey');
75 2
        $ttl      = $request->attributes->get('_cacheTTL');
76 2
        if (empty($cacheKey)) {
77 1
            return;
78
        }
79
80 1
        $cache = $this->getCache();
81
82 1
        $this->info(sprintf('miss: save into cache: %s', $cacheKey), [
83 1
            'application' => 'cache',
84 1
            'type'        => 'miss',
85 1
            'cacheKey'    => $cacheKey,
86 1
            'ttl'         => $ttl,
87
        ]);
88
89 1
        $item = $cache->getItem($cacheKey);
90 1
        $item->set($response);
91 1
        $item->expiresAfter($ttl);
92 1
        $cache->save($item);
93
94 1
        $response->headers->set('X-Cache', 'miss');
95 1
        $response->setMaxAge($ttl);
96 1
        $response->setExpires(new DateTime(sprintf('+%d seconds', $ttl)));
97 1
    }
98
99
    /**
100
     * @param AdapterInterface $cache
101
     * @param string $cacheKey
102
     * @param int $ttl
103
     * @return Response
104
     */
105 1
    private function handleCached(AdapterInterface $cache, string $cacheKey, int $ttl) : Response
106
    {
107 1
        $this->info(sprintf('hit: fetch from cache: %s', $cacheKey), [
108 1
            'application' => 'cache',
109 1
            'type'        => 'hit',
110 1
            'cacheKey'    => $cacheKey,
111 1
            'ttl'         => $ttl,
112
        ]);
113
114
        /** @var Response $response */
115 1
        $response = $cache->getItem($cacheKey)->get();
116
117 1
        $response->headers->set('X-Cache', 'hit');
118 1
        $response->setMaxAge($ttl);
119 1
        $response->setExpires(new DateTime(sprintf('+%d seconds', $ttl)));
120
121 1
        return $response;
122
    }
123
124
    /**
125
     * @param Request $request
126
     * @return string
127
     */
128 2
    private function generateCacheKey(Request $request) : string
129
    {
130 2
        return self::PREFIX . $request->getRequestUri();
131
    }
132
}
133