Completed
Push — master ( 97f6b5...9ef69c )
by Matze
08:25
created

Cache::processRequest()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 10
cts 10
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 2
crap 4
1
<?php
2
3
namespace BrainExe\Core\Middleware;
4
5
use BrainExe\Core\Annotations\Middleware;
6
use BrainExe\Core\Traits\CacheTrait;
7
use BrainExe\Core\Traits\LoggerTrait;
8
use DateTime;
9
use Symfony\Component\Cache\Adapter\AdapterInterface;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\Routing\Route;
13
14
/**
15
 * @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...
16
 * @Middleware("Middleware.Cache")
17
 */
18
class Cache extends AbstractMiddleware
19
{
20
    use CacheTrait;
21
    use LoggerTrait;
22
23
    const DEFAULT_TTL = 60;
24
    const PREFIX = 'cache#';
25
26
    /**
27
     * {@inheritdoc}
28
     */
29 3
    public function processRequest(Request $request, Route $route)
30
    {
31 3
        if (!$route->hasOption('cache') || !$request->isMethod('GET')) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
32
           // return null;
33
        }
34
35 3
        $cacheKey = $this->generateCacheKey($request);
36
37 3
        $ttl   = $route->getOption('cache');
38 3
        $cache = $this->getCache();
39 3
        if ($cache->hasItem($cacheKey)) {
40 1
            return $this->handleCached($cache, $cacheKey, $ttl);
41
        }
42
43
        // enable cache for current request. Store response later in given key
44 2
        $request->attributes->set('_cacheKey', $cacheKey);
45 2
        $request->attributes->set('_cacheTTL', $ttl);
46
47 2
        return null;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 2
    public function processResponse(Request $request, Response $response)
54
    {
55 2
        if (!$response->isOk()) {
56 1
            return;
57
        }
58
59 2
        $cacheKey = $request->attributes->get('_cacheKey');
60 2
        $ttl      = $request->attributes->get('_cacheTTL');
61 2
        if (empty($cacheKey)) {
62
            return;
63
        }
64
65 2
        $cache = $this->getCache();
66
67 2
        $this->info(sprintf('miss: save into cache: %s', $cacheKey), [
68 2
            'application' => 'cache',
69 2
            'type'        => 'miss',
70 2
            'cacheKey'    => $cacheKey,
71 2
            'ttl'         => $ttl,
72
        ]);
73
74 2
        $item = $cache->getItem($cacheKey);
75 2
        $item->set($response);
76 1
        $item->expiresAfter($ttl);
77 1
        $cache->save($item);
78
79 1
        $response->headers->set('X-Cache', 'miss');
80 1
        $response->setMaxAge($ttl);
81 1
        $response->setExpires(new DateTime(sprintf('+%d seconds', $ttl)));
82 1
    }
83
84
    /**
85
     * @param AdapterInterface $cache
86
     * @param string $cacheKey
87
     * @param int $ttl
88
     * @return Response
89
     */
90 1
    private function handleCached(AdapterInterface $cache, string $cacheKey, int $ttl) : Response
91
    {
92 1
        $this->info(sprintf('hit: fetch from cache: %s', $cacheKey), [
93 1
            'application' => 'cache',
94 1
            'type'        => 'hit',
95 1
            'cacheKey'    => $cacheKey,
96 1
            'ttl'         => $ttl,
97
        ]);
98
99
        /** @var Response $response */
100 1
        $response = $cache->getItem($cacheKey)->get();
101
102 1
        $response->headers->set('X-Cache', 'hit');
103 1
        $response->setMaxAge($ttl);
104 1
        $response->setExpires(new DateTime(sprintf('+%d seconds', $ttl)));
105
106 1
        return $response;
107
    }
108
109
    /**
110
     * @param Request $request
111
     * @return string
112
     */
113 3
    private function generateCacheKey(Request $request) : string
114
    {
115 3
        return self::PREFIX . str_replace('/', '#', $request->getRequestUri());
116
    }
117
}
118