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
Pull Request — master (#2)
by Cees-Jan
44:23 queued 34:23
created

Client::getHeaders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php declare(strict_types=1);
2
3
namespace ApiClients\Foundation\Transport;
4
5
use ApiClients\Foundation\Middleware\MiddlewareRunner;
6
use ApiClients\Foundation\Middleware\MiddlewareInterface;
7
use ApiClients\Foundation\Transport\CommandBus;
8
use Clue\React\Buzz\Browser;
9
use RingCentral\Psr7\Request as Psr7Request;
10
use RingCentral\Psr7\Uri;
11
use Interop\Container\ContainerInterface;
12
use Psr\Http\Message\RequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use React\EventLoop\LoopInterface;
15
use React\Promise\PromiseInterface;
16
use function React\Promise\reject;
17
use function React\Promise\resolve;
18
use function WyriHaximus\React\futureFunctionPromise;
19
20
class Client
21
{
22
    const DEFAULT_OPTIONS = [
23
        Options::SCHEMA => 'https',
24
        Options::PATH => '/',
25
        Options::USER_AGENT => 'WyriHaximus/php-api-client',
26
        Options::HEADERS => [],
27
    ];
28
29
    /**
30
     * @var LoopInterface
31
     */
32
    protected $loop;
33
34
    /**
35
     * @var ContainerInterface
36
     */
37
    protected $container;
38
39
    /**
40
     * @var GuzzleClient
41
     */
42
    protected $handler;
43
44
    /**
45
     * @var array
46
     */
47
    protected $options = [];
48
49
    /**
50
     * @var MiddlewareInterface[]
51
     */
52
    protected $middleware = [];
53
54
    /**
55
     * @param LoopInterface $loop
56
     * @param ContainerInterface $container
57
     * @param Browser $buzz
58
     * @param array $options
59
     */
60
    public function __construct(
61
        LoopInterface $loop,
62
        ContainerInterface $container,
63
        Browser $buzz,
64
        array $options = []
65
    ) {
66
        $this->loop = $loop;
67
        $this->container = $container;
68
        $this->handler = $buzz;
0 ignored issues
show
Documentation Bug introduced by
It seems like $buzz of type object<Clue\React\Buzz\Browser> is incompatible with the declared type object<ApiClients\Founda...Transport\GuzzleClient> of property $handler.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
69
        $this->options = $options + self::DEFAULT_OPTIONS;
70
71
        if (isset($this->options[Options::MIDDLEWARE])) {
72
            $this->middleware = $this->options[Options::MIDDLEWARE];
73
        }
74
    }
75
76
    protected function constructMiddlewares(array $options): MiddlewareRunner
77
    {
78
        $set = $this->middleware;
79
80
        if (isset($options[Options::MIDDLEWARE])) {
81
            $set = $this->combinedMiddlewares($options[Options::MIDDLEWARE]);
82
        }
83
84
        $args = [];
85
        $args[] = $options;
86
        foreach ($set as $middleware) {
87
            if (!is_subclass_of($middleware, MiddlewareInterface::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \ApiClients\Foundation\M...dlewareInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
88
                continue;
89
            }
90
91
            $middlewares[] = $this->container->get($middleware);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$middlewares was never initialized. Although not strictly required by PHP, it is generally a good practice to add $middlewares = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
92
        }
93
94
        return new MiddlewareRunner(...$args);
95
    }
96
97
    protected function combinedMiddlewares(array $extraMiddlewares): array
98
    {
99
        $set = $this->middleware;
100
101
        foreach ($extraMiddlewares as $middleware) {
102
            if (in_array($middleware, $set)) {
103
                continue;
104
            }
105
106
            $set[] = $middleware;
107
        }
108
109
        return $set;
110
    }
111
112
    /**
113
     * @param RequestInterface $request
114
     * @param array $options
115
     * @return PromiseInterface
116
     */
117
    public function request(RequestInterface $request, array $options = []): PromiseInterface
118
    {
119
        $request = $this->applyApiSettingsToRequest($request);
120
        $options = $this->applyRequestOptions($options);
121
        $executioner = $this->constructMiddlewares($options);
122
123
        return $executioner->pre($request)->then(function ($request) use ($options) {
124
            return resolve($this->handler->send(
125
                $request
126
            ));
127
        }, function (ResponseInterface $response) {
128
            return resolve($response);
129
        })->then(function (ResponseInterface $response) use ($executioner) {
130
            return $executioner->post($response);
131
        });
132
    }
133
134
    protected function applyApiSettingsToRequest(RequestInterface $request): RequestInterface
135
    {
136
        $uri = $request->getUri();
137
        if (strpos((string)$uri, '://') === false) {
138
            $uri = Uri::resolve(
139
                new Uri(
140
                    $this->options[Options::SCHEMA] .
141
                    '://' .
142
                    $this->options[Options::HOST] .
143
                    $this->options[Options::PATH]
144
                ),
145
                $request->getUri()
146
            );
147
        }
148
149
        return new Psr7Request(
150
            $request->getMethod(),
151
            $uri,
152
            $this->options[Options::HEADERS] + $request->getHeaders(),
153
            $request->getBody(),
154
            $request->getProtocolVersion()
155
        );
156
    }
157
158
    public function applyRequestOptions(array $options): array
159
    {
160
        if (!isset($this->options[Options::DEFAULT_REQUEST_OPTIONS])) {
161
            return $options;
162
        }
163
164
        return array_merge_recursive(
165
            $this->options[Options::DEFAULT_REQUEST_OPTIONS],
166
            $options
167
        );
168
    }
169
}
170