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 (#3)
by Cees-Jan
02:02
created

ResponseCacheMiddleware::sortUrls()   B

Complexity

Conditions 8
Paths 5

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 7.7777
c 0
b 0
f 0
cc 8
eloc 10
nc 5
nop 1
crap 8
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 1
    public function __construct(array $urls, array $headers = [], CacheInterface $cache = null, Clock $clock = null)
57
    {
58 1
        $this->sortUrls($urls);
59 1
        $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 1
        $this->cache = $cache instanceof CacheInterface ? $cache : new ArrayCache();
61 1
        $this->clock = $clock instanceof CacheInterface ? $clock : new SystemClock();
0 ignored issues
show
Documentation Bug introduced by
It seems like $clock instanceof React\...cci\Clock\SystemClock() can also be of type React\Cache\CacheInterface. However, the property $clock is declared as type Lcobucci\Clock\Clock. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
62 1
    }
63
64 1
    public function __invoke(ServerRequestInterface $request, callable $next)
65
    {
66 1
        if ($request->getMethod() !== 'GET') {
67
            return resolve($next($request));
68
        }
69
70 1
        $uri = $request->getUri()->getPath();
71 1
        if (!in_array($uri, $this->staticUrls, true) && !$this->matchesPrefixUrl($uri)) {
72
            return resolve($next($request));
73
        }
74
75 1
        $key = $uri;
76 1
        $query = $request->getUri()->getQuery();
77 1
        if (strlen($query) > 0 && $this->queryInKey($uri)) {
78
            $key .= '?' . $query;
79
        }
80
81 1
        return $this->cache->get($key)->then(function ($json) {
82 1
            $cachedResponse = json_decode($json);
83 1
            $headers = (array)$cachedResponse->headers;
84
            // Todo at 2 October 2018 remove the check around this assignment
85 1
            if (isset($cachedResponse->time)) {
86 1
                $headers['Age'] = (int)$this->clock->now()->format('U') - (string)$cachedResponse->time;
87
            }
88
89 1
            return new Response($cachedResponse->code, $headers, stream_for($cachedResponse->body));
90
        }, function () use ($next, $request, $key) {
91
            return resolve($next($request))->then(function (ResponseInterface $response) use ($key) {
92
                if ($response->getBody() instanceof HttpBodyStream) {
93
                    return $response;
94
                }
95
96
                $body = (string)$response->getBody();
97
                $headers = [];
98
                foreach ($this->headers as $header) {
99
                    if (!$response->hasHeader($header)) {
100
                        continue;
101
                    }
102
103
                    $headers[$header] = $response->getHeaderLine($header);
104
                }
105
                $cachedResponse = json_encode([
106
                    'body' => $body,
107
                    'headers' => $headers,
108
                    'code' => $response->getStatusCode(),
109
                    'time' => (int)$this->clock->now()->format('U'),
110
                ]);
111
                $this->cache->set($key, $cachedResponse);
112
113
                return $response->withBody(stream_for($body));
114
            });
115 1
        });
116
    }
117
118 1
    private function sortUrls(array $urls)
119
    {
120 1
        foreach ($urls as $url) {
121 1
            if (!(strlen($url) >= 3 && in_array(substr($url, -3), self::PREFIXES, true))) {
122 1
                $this->staticUrls[] = $url;
123
124 1
                continue;
125
            }
126
127 1
            if (strlen($url) >= 3 && substr($url, -3) === self::PREFIX_WITHOUT_QUERY) {
128 1
                $this->prefixUrlsWithoutQuery[] = substr($url, 0, -3);
129
130 1
                continue;
131
            }
132
133 1
            if (strlen($url) >= 3 && substr($url, -3) === self::PREFIX_WITH_QUERY) {
134 1
                $this->prefixUrlsWithQuery[] = substr($url, 0, -3);
135
136 1
                continue;
137
            }
138
        }
139 1
    }
140
141
    private function matchesPrefixUrl(string $uri): bool
142
    {
143
        if ($this->urlMatchesPrefixes($this->prefixUrlsWithoutQuery, $uri)) {
144
            return true;
145
        }
146
147
        return $this->urlMatchesPrefixes($this->prefixUrlsWithQuery, $uri);
148
    }
149
150
    private function queryInKey(string $uri): bool
151
    {
152
        return $this->urlMatchesPrefixes($this->prefixUrlsWithQuery, $uri);
153
    }
154
155
    private function urlMatchesPrefixes(array $urls, string $uri): bool
156
    {
157
        foreach ($urls as $url) {
158
            $urlLength = strlen($url);
159
            if (substr($uri, 0, $urlLength) === $url) {
160
                return true;
161
            }
162
        }
163
164
        return false;
165
    }
166
}
167