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.
Completed
Push — master ( bbeb53...693765 )
by Cees-Jan
110:07 queued 70:16
created

LoggerMiddleware::error()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6.031

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 19
cts 21
cp 0.9048
rs 8.6737
c 0
b 0
f 0
cc 6
nc 10
nop 3
crap 6.031
1
<?php declare(strict_types=1);
2
3
namespace ApiClients\Middleware\Log;
4
5
use ApiClients\Foundation\Middleware\Annotation\Last;
6
use ApiClients\Foundation\Middleware\MiddlewareInterface;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\UriInterface;
10
use Psr\Log\LoggerInterface;
11
use React\Promise\CancellablePromiseInterface;
12
use Throwable;
13
use function React\Promise\reject;
14
use function React\Promise\resolve;
15
16
class LoggerMiddleware implements MiddlewareInterface
17
{
18
    private const REQUEST  = 'request';
19
    private const RESPONSE = 'response';
20
    private const ERROR    = 'error';
21
22
    /**
23
     * @var LoggerInterface
24
     */
25
    private $logger;
26
27
    private $context = [];
28
29 4
    public function __construct(LoggerInterface $logger)
30
    {
31 4
        $this->logger = $logger;
32 4
    }
33
34
    /**
35
     * @Last()
36
     */
37 4
    public function pre(
38
        RequestInterface $request,
39
        string $transactionId,
40
        array $options = []
41
    ): CancellablePromiseInterface {
42 4
        if (!isset($options[self::class][Options::LEVEL]) && !isset($options[self::class][Options::ERROR_LEVEL])) {
43 1
            return resolve($request);
44
        }
45
46 3
        $this->context[$transactionId][self::REQUEST]['method'] = $request->getMethod();
47 3
        $this->context[$transactionId][self::REQUEST]['uri'] = (string)$this->stripQueryItems(
48 3
            $request->getUri(),
49 3
            $options
50
        );
51 3
        $this->context[$transactionId][self::REQUEST]['protocol_version'] = (string)$request->getProtocolVersion();
52 3
        $ignoreHeaders = $options[self::class][Options::IGNORE_HEADERS] ?? [];
53 3
        $this->context[$transactionId] = $this->iterateHeaders(
54 3
            $this->context[$transactionId],
55 3
            self::REQUEST,
56 3
            $request->getHeaders(),
57 3
            $ignoreHeaders
58
        );
59
60 3
        if (!isset($options[self::class][Options::URL_LEVEL])) {
61 2
            return resolve($request);
62
        }
63
64 1
        $message = 'Requesting: ' . $this->context[$transactionId][self::REQUEST]['uri'];
65 1
        $this->logger->log($options[self::class][Options::URL_LEVEL], $message, $this->context[$transactionId]);
66
67 1
        return resolve($request);
68
    }
69
70
    /**
71
     * @Last()
72
     */
73 2
    public function post(
74
        ResponseInterface $response,
75
        string $transactionId,
76
        array $options = []
77
    ): CancellablePromiseInterface {
78 2
        if (!isset($this->context[$transactionId])) {
79 1
            return resolve($response);
80
        }
81
82 1
        $context = $this->context[$transactionId];
83 1
        if (!isset($options[self::class][Options::LEVEL]) && !isset($options[self::class][Options::ERROR_LEVEL])) {
84
            unset($this->context[$transactionId]);
85
        }
86
87 1
        if (!isset($options[self::class][Options::LEVEL])) {
88
            return resolve($response);
89
        }
90
91 1
        $message = 'Request ' . $transactionId . ' completed.';
92
93 1
        $context = $this->addResponseToContext($context, $response, $options);
94
95 1
        $this->logger->log($options[self::class][Options::LEVEL], $message, $context);
96
97 1
        return resolve($response);
98
    }
99
100
    /**
101
     * @Last()
102
     */
103 3
    public function error(
104
        Throwable $throwable,
105
        string $transactionId,
106
        array $options = []
107
    ): CancellablePromiseInterface {
108 3
        if (!isset($this->context[$transactionId])) {
109 1
            return reject($throwable);
110
        }
111
112 2
        $context = $this->context[$transactionId];
113 2
        unset($this->context[$transactionId]);
114
115 2
        if (!isset($options[self::class][Options::ERROR_LEVEL])) {
116
            return reject($throwable);
117
        }
118
119 2
        $message = $throwable->getMessage();
120
121 2
        $response = null;
122 2
        if (method_exists($throwable, 'getResponse')) {
123 1
            $response = $throwable->getResponse();
124
        }
125 2
        if ($response instanceof ResponseInterface) {
126 1
            $context = $this->addResponseToContext($context, $response, $options);
127
        }
128
129 2
        $context[self::ERROR]['code']  = $throwable->getCode();
130 2
        $context[self::ERROR]['file']  = $throwable->getFile();
131 2
        $context[self::ERROR]['line']  = $throwable->getLine();
132 2
        $context[self::ERROR]['trace'] = $throwable->getTraceAsString();
133
134 2
        if (method_exists($throwable, 'getContext')) {
135
            $context[self::ERROR]['context'] = $throwable->getContext();
136
        }
137
138 2
        $this->logger->log($options[self::class][Options::ERROR_LEVEL], $message, $context);
139
140 2
        return reject($throwable);
141
    }
142
143 3
    protected function iterateHeaders(
144
        array $context,
145
        string $prefix,
146
        array $headers,
147
        array $ignoreHeaders
148
    ): array {
149 3
        foreach ($headers as $header => $value) {
150 3
            if (in_array($header, $ignoreHeaders, true)) {
151 3
                continue;
152
            }
153
154 3
            $context[$prefix]['headers'][$header] = $value;
155
        }
156
157 3
        return $context;
158
    }
159
160 2
    private function addResponseToContext(
161
        array $context,
162
        ResponseInterface $response,
163
        array $options
164
    ): array {
165 2
        $context[self::RESPONSE]['status_code']      = $response->getStatusCode();
166 2
        $context[self::RESPONSE]['status_reason']    = $response->getReasonPhrase();
167 2
        $context[self::RESPONSE]['protocol_version'] = $response->getProtocolVersion();
168 2
        $ignoreHeaders = $options[self::class][Options::IGNORE_HEADERS] ?? [];
169 2
        $context  = $this->iterateHeaders(
170 2
            $context,
171 2
            self::RESPONSE,
172 2
            $response->getHeaders(),
173 2
            $ignoreHeaders
174
        );
175
176 2
        return $context;
177
    }
178
179 3
    private function stripQueryItems(UriInterface $uri, array $options): UriInterface
180
    {
181 3
        parse_str($uri->getQuery(), $query);
182 3
        foreach ($options[self::class][Options::IGNORE_URI_QUERY_ITEMS] ?? [] as $item) {
183 1
            unset($query[$item], $query[$item . '[]']);
184
        }
185
186 3
        return $uri->withQuery(http_build_query($query));
187
    }
188
}
189