CacheMiddleware   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 9
dl 0
loc 67
ccs 14
cts 14
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B process() 0 25 5
A isResponseCacheable() 0 5 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Acelaya\Website\Middleware;
5
6
use Doctrine\Common\Cache\Cache;
7
use Fig\Http\Message\StatusCodeInterface;
8
use Interop\Http\ServerMiddleware\DelegateInterface;
9
use Interop\Http\ServerMiddleware\MiddlewareInterface;
10
use Psr\Http\Message\ResponseInterface as Response;
11
use Psr\Http\Message\ServerRequestInterface as Request;
12
use Zend\Expressive\Router\RouterInterface;
13
14
class CacheMiddleware implements MiddlewareInterface, StatusCodeInterface
15
{
16
    /**
17
     * @var RouterInterface
18
     */
19
    protected $router;
20
    /**
21
     * @var Cache
22
     */
23
    protected $cache;
24
25
    public function __construct(Cache $cache, RouterInterface $router)
26
    {
27
        $this->cache = $cache;
28
        $this->router = $router;
29 3
    }
30
31 3
    /**
32 3
     * Process an incoming server request and return a response, optionally delegating
33 3
     * to the next middleware component to create the response.
34
     *
35
     * @param Request $request
36
     * @param DelegateInterface $delegate
37
     *
38
     * @return Response
39
     * @throws \RuntimeException
40
     * @throws \InvalidArgumentException
41
     */
42
    public function process(Request $request, DelegateInterface $delegate)
43
    {
44
        // Bypass cache if provided bypass-cache param
45
        if (array_key_exists('bypass-cache', $request->getQueryParams())) {
46
            return $delegate->process($request);
47
        }
48
49
        $currentRoute = $this->router->match($request);
50
        $currentRoutePath = $request->getUri()->getPath();
51
52
        // If current route is a success route and it has been previously cached, write cached content and return
53
        if ($currentRoute->isSuccess() && $this->cache->contains($currentRoutePath)) {
54
            $resp = new \Zend\Diactoros\Response();
55
            $resp->getBody()->write($this->cache->fetch($currentRoutePath));
56
            return $resp;
57
        }
58
59
        // If the response is not cached, process the next middleware and get its response, then cache it
60 3
        $resp = $delegate->process($request);
61
        if ($this->isResponseCacheable($resp, $currentRoute->getMatchedParams())) {
62 3
            $this->cache->save($currentRoutePath, (string) $resp->getBody());
63 3
        }
64
65
        return $resp;
66 3
    }
67 1
68 1
    /**
69
     * Tells if a response is cacheable based on its status and current route params
70
     *
71
     * @param Response $resp
72 2
     * @param array $routeParams
73 2
     * @return bool
74 1
     */
75
    protected function isResponseCacheable(Response $resp, array $routeParams = []): bool
76
    {
77 2
        $isCacheable = (bool) ($routeParams['cacheable'] ?? false);
78
        return $resp->getStatusCode() === self::STATUS_OK && $isCacheable;
79
    }
80
}
81