GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#2)
by Cees-Jan
03:35
created

ResponseCacheMiddleware   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Test Coverage

Coverage 97.22%

Importance

Changes 0
Metric Value
wmc 33
dl 0
loc 166
ccs 70
cts 72
cp 0.9722
rs 9.3999
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 3
A matchesPrefixUrl() 0 7 2
B sortUrls() 0 19 8
A queryInKey() 0 3 1
C __invoke() 0 67 16
A urlMatchesPrefixes() 0 10 3
1
<?php declare(strict_types=1);
2
3
namespace WyriHaximus\React\Http\Middleware;
4
5
use Lcobucci\Clock\Clock;
6
use Lcobucci\Clock\SystemClock;
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface;
9
use React\Cache\ArrayCache;
10
use React\Cache\CacheInterface;
11
use React\Http\Io\HttpBodyStream;
12
use React\Http\Response;
13
use function React\Promise\resolve;
14
use function RingCentral\Psr7\stream_for;
15
16
final class ResponseCacheMiddleware
17
{
18
    const PREFIX_WITHOUT_QUERY = '***';
19
    const PREFIX_WITH_QUERY = '???';
20
    const PREFIXES = [
21
        self::PREFIX_WITH_QUERY,
22
        self::PREFIX_WITHOUT_QUERY,
23
    ];
24
25
    /**
26
     * @var array
27
     */
28
    private $staticUrls = [];
29
30
    /**
31
     * @var array
32
     */
33
    private $prefixUrlsWithoutQuery = [];
34
35
    /**
36
     * @var array
37
     */
38
    private $prefixUrlsWithQuery = [];
39
40
    /**
41
     * @var CacheInterface
42
     */
43
    private $cache;
44
45
    /**
46
     * @var Clock
47
     */
48
    private $clock;
49
50
    /**
51
     * @param array               $urls
52
     * @param array               $headers
53
     * @param CacheInterface|null $cache
54
     * @param Clock               $clock
55
     */
56 2
    public function __construct(array $urls, array $headers = [], CacheInterface $cache = null, Clock $clock = null)
57
    {
58 2
        $this->sortUrls($urls);
59 2
        $this->headers = $headers;
0 ignored issues
show
Bug Best Practice introduced by
The property headers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
60 2
        $this->cache = $cache instanceof CacheInterface ? $cache : new ArrayCache();
61 2
        $this->clock = $clock instanceof Clock ? $clock : new SystemClock();
62 2
    }
63
64 2
    public function __invoke(ServerRequestInterface $request, callable $next)
65
    {
66 2
        if ($request->getMethod() !== 'GET') {
67
            return resolve($next($request));
68
        }
69
70
        /** @var Session $session */
71 2
        $session = null;
72
        if (
73 2
            class_exists(SessionMiddleware::class) &&
74 2
            $request->getAttribute(SessionMiddleware::ATTRIBUTE_NAME) !== null
75
        ) {
76 2
            $session = $request->getAttribute(SessionMiddleware::ATTRIBUTE_NAME);
77
        }
78
79 2
        if ($session !== null && $session->isActive() === true) {
80 1
            return resolve($next($request));
81
        }
82
83 2
        $uri = $request->getUri()->getPath();
84 2
        if (!in_array($uri, $this->staticUrls, true) && !$this->matchesPrefixUrl($uri)) {
85 1
            return resolve($next($request));
86
        }
87
88 2
        $key = $uri;
89 2
        $query = $request->getUri()->getQuery();
90 2
        if (strlen($query) > 0 && $this->queryInKey($uri)) {
91 1
            $key .= '?' . $query;
92
        }
93
94 1
        return $this->cache->get($key)->then(function ($json) {
95 1
            $cachedResponse = json_decode($json);
96 1
            $headers = (array)$cachedResponse->headers;
97
            // Todo at 2 October 2018 remove the check around this assignment
98 1
            if (isset($cachedResponse->time)) {
99 1
                $headers['Age'] = (int)$this->clock->now()->format('U') - (string)$cachedResponse->time;
100
            }
101
102 1
            return new Response($cachedResponse->code, $headers, stream_for($cachedResponse->body));
103
        }, function () use ($next, $request, $key, $session) {
104 2
            return resolve($next($request))->then(function (ResponseInterface $response) use ($key, $session) {
105 2
                if ($response->getBody() instanceof HttpBodyStream) {
106 1
                    return $response;
107
                }
108
109 2
                if ($session !== null && $session->isActive() === true) {
110 1
                    return $response;
111
                }
112
113 1
                $body = (string)$response->getBody();
114 1
                $headers = [];
115 1
                foreach ($this->headers as $header) {
116 1
                    if (!$response->hasHeader($header)) {
117
                        continue;
118
                    }
119
120 1
                    $headers[$header] = $response->getHeaderLine($header);
121
                }
122 1
                $cachedResponse = json_encode([
123 1
                    'body' => $body,
124 1
                    'headers' => $headers,
125 1
                    'code' => $response->getStatusCode(),
126 1
                    'time' => (int)$this->clock->now()->format('U'),
127
                ]);
128 1
                $this->cache->set($key, $cachedResponse);
129
130 1
                return $response->withBody(stream_for($body));
131 2
            });
132 2
        });
133
    }
134
135 2
    private function sortUrls(array $urls)
136
    {
137 2
        foreach ($urls as $url) {
138 2
            if (!(strlen($url) >= 3 && in_array(substr($url, -3), self::PREFIXES, true))) {
139 2
                $this->staticUrls[] = $url;
140
141 2
                continue;
142
            }
143
144 1
            if (strlen($url) >= 3 && substr($url, -3) === self::PREFIX_WITHOUT_QUERY) {
145 1
                $this->prefixUrlsWithoutQuery[] = substr($url, 0, -3);
146
147 1
                continue;
148
            }
149
150 1
            if (strlen($url) >= 3 && substr($url, -3) === self::PREFIX_WITH_QUERY) {
151 1
                $this->prefixUrlsWithQuery[] = substr($url, 0, -3);
152
153 1
                continue;
154
            }
155
        }
156 2
    }
157
158 1
    private function matchesPrefixUrl(string $uri): bool
159
    {
160 1
        if ($this->urlMatchesPrefixes($this->prefixUrlsWithoutQuery, $uri)) {
161 1
            return true;
162
        }
163
164 1
        return $this->urlMatchesPrefixes($this->prefixUrlsWithQuery, $uri);
165
    }
166
167 1
    private function queryInKey(string $uri): bool
168
    {
169 1
        return $this->urlMatchesPrefixes($this->prefixUrlsWithQuery, $uri);
170
    }
171
172 1
    private function urlMatchesPrefixes(array $urls, string $uri): bool
173
    {
174 1
        foreach ($urls as $url) {
175 1
            $urlLength = strlen($url);
176 1
            if (substr($uri, 0, $urlLength) === $url) {
177 1
                return true;
178
            }
179
        }
180
181 1
        return false;
182
    }
183
}
184