Passed
Push — master ( 376082...008670 )
by Paul
04:04
created

AbstractRequest::sendRequest()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 12.4085

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 4
nop 3
dl 0
loc 14
ccs 3
cts 9
cp 0.3333
crap 12.4085
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace CCT\Component\Rest\Http;
6
7
use CCT\Component\Rest\Config;
8
use CCT\Component\Rest\Exception\InvalidParameterException;
9
use CCT\Component\Rest\Exception\ServiceUnavailableException;
10
use CCT\Component\Rest\Http\Definition\QueryParams;
11
use CCT\Component\Rest\Http\Definition\RequestHeaders;
12
use GuzzleHttp\Client as GuzzleClient;
13
use GuzzleHttp\Exception\ConnectException;
14
use GuzzleHttp\Exception\RequestException;
15
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
16
17
abstract class AbstractRequest implements RequestInterface
18
{
19
    /**
20
     * @var GuzzleClient
21
     */
22
    protected $client;
23
24
    /**
25
     * Request headers
26
     *
27
     * @var RequestHeaders
28
     */
29
    protected $headers;
30
31
    /**
32
     * The name of the response class used to
33
     *
34
     * @var Config
35
     */
36
    protected $config;
37
38
    /**
39
     * AbstractRequest constructor.
40
     *
41
     * @param GuzzleClient $client
42
     * @param Config $config
43
     */
44 4
    public function __construct(GuzzleClient $client, Config $config)
45
    {
46 4
        $this->client = $client;
47 4
        $this->config = $config;
48
49 4
        $this->setUp();
50 4
    }
51
52
    /**
53
     * @param string $uri
54
     * @param QueryParams|null $queryParams
55
     *
56
     * @return ResponseInterface
57
     * @throws \ReflectionException
58
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
59
     * @throws \RuntimeException
60
     * @throws \GuzzleHttp\Exception\RequestException
61
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
62
     */
63 3
    protected function requestGet($uri, QueryParams $queryParams = null): ResponseInterface
64
    {
65 3
        return $this->execute(self::METHOD_GET, $uri, [], $queryParams);
66
    }
67
68
    /**
69
     * @param string $uri
70
     * @param QueryParams|null $queryParams
71
     *
72
     * @return ResponseInterface
73
     * @throws \ReflectionException
74
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
75
     * @throws \RuntimeException
76
     * @throws \GuzzleHttp\Exception\RequestException
77
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
78
     */
79
    protected function requestDelete($uri, QueryParams $queryParams = null): ResponseInterface
80
    {
81
        return $this->execute(self::METHOD_DELETE, $uri, [], $queryParams);
82
    }
83
84
    /**
85
     * @param string $uri
86
     * @param array|object $formData
87
     * @param QueryParams|null $queryParams
88
     *
89
     * @return ResponseInterface
90
     * @throws \ReflectionException
91
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
92
     * @throws \RuntimeException
93
     * @throws \GuzzleHttp\Exception\RequestException
94
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
95
     */
96
    protected function requestPost($uri, $formData, QueryParams $queryParams = null): ResponseInterface
97
    {
98
        return $this->execute(self::METHOD_POST, $uri, $formData, $queryParams);
0 ignored issues
show
Bug introduced by
It seems like $formData can also be of type object; however, parameter $formData of CCT\Component\Rest\Http\AbstractRequest::execute() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
        return $this->execute(self::METHOD_POST, $uri, /** @scrutinizer ignore-type */ $formData, $queryParams);
Loading history...
99
    }
100
101
    /**
102
     * @param string $uri
103
     * @param array|object $formData
104
     * @param QueryParams|null $queryParams
105
     *
106
     * @return ResponseInterface
107
     * @throws \ReflectionException
108
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
109
     * @throws \RuntimeException
110
     * @throws \GuzzleHttp\Exception\RequestException
111
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
112
     */
113
    protected function requestPatch($uri, $formData, QueryParams $queryParams = null): ResponseInterface
114
    {
115
        return $this->execute(self::METHOD_PATCH, $uri, $formData, $queryParams);
0 ignored issues
show
Bug introduced by
It seems like $formData can also be of type object; however, parameter $formData of CCT\Component\Rest\Http\AbstractRequest::execute() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
        return $this->execute(self::METHOD_PATCH, $uri, /** @scrutinizer ignore-type */ $formData, $queryParams);
Loading history...
116
    }
117
118
    /**
119
     * @param string $uri
120
     * @param array|object $formData
121
     * @param QueryParams|null $queryParams
122
     *
123
     * @return ResponseInterface
124
     * @throws \ReflectionException
125
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
126
     * @throws \RuntimeException
127
     * @throws \GuzzleHttp\Exception\RequestException
128
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
129
     */
130
    protected function requestPut($uri, $formData, QueryParams $queryParams = null): ResponseInterface
131
    {
132
        return $this->execute(self::METHOD_PUT, $uri, $formData, $queryParams);
0 ignored issues
show
Bug introduced by
It seems like $formData can also be of type object; however, parameter $formData of CCT\Component\Rest\Http\AbstractRequest::execute() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

132
        return $this->execute(self::METHOD_PUT, $uri, /** @scrutinizer ignore-type */ $formData, $queryParams);
Loading history...
133
    }
134
135
    /**
136
     * @param string $method
137
     * @param string $uri
138
     * @param array|object $formData
139
     * @param QueryParams|null $queryParams
140
     *
141
     * @return ResponseInterface
142
     * @throws \ReflectionException
143
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
144
     * @throws \GuzzleHttp\Exception\RequestException
145
     * @throws \RuntimeException
146
     * @throws \CCT\Component\Rest\Exception\ServiceUnavailableException
147
     */
148 3
    protected function execute(
149
        $method,
150
        string $uri,
151
        array $formData = [],
152
        QueryParams $queryParams = null
153
    ): ResponseInterface {
154 3
        $options = $this->getRequestOptions($formData, $queryParams);
155
156 3
        $response = $this->sendRequest($method, $uri, $options);
157
158 3
        return $this->createResponseRefFromResponse($response);
159
    }
160
161
    /**
162
     * @param array|object $formData
163
     * @param QueryParams|null $queryParams
164
     *
165
     * @return array
166
     */
167 3
    protected function getRequestOptions(array $formData = [], QueryParams $queryParams = null): array
168
    {
169
        return [
170 3
            'form_params' => $formData,
171 3
            'headers' => $this->getHeaders()->toArray(),
172
            'query' => $queryParams !== null ? $queryParams->toArray() : []
173
        ];
174
    }
175
176
    /**
177
     * @param string $method
178
     * @param string $uri
179
     * @param array $options
180
     *
181
     * @throws \GuzzleHttp\Exception\RequestException
182
     * @throws ServiceUnavailableException
183
     *
184
     * @return PsrResponseInterface|object
185
     */
186 3
    protected function sendRequest($method, string $uri, array $options = [])
187
    {
188
        try {
189 3
            $response = $this->client->request($method, $uri, $options);
190
        } catch (ConnectException $e) {
191
            throw new ServiceUnavailableException($e->getRequest(), $e->getMessage());
192
        } catch (RequestException $e) {
193
            if (null !== $e->getResponse() && null === $e->getResponse()->getBody()) {
194
                throw $e;
195
            }
196
            $response = $e->getResponse();
197
        }
198
199 3
        return $response;
200
    }
201
202
    /**
203
     * Set headers for request
204
     *
205
     * @param RequestHeaders $headers
206
     */
207 3
    protected function setHeaders(RequestHeaders $headers): void
208
    {
209 3
        $this->headers = $headers;
210 3
    }
211
212
    /**
213
     * Get headers for request
214
     *
215
     * @return RequestHeaders
216
     */
217 3
    protected function getHeaders(): RequestHeaders
218
    {
219 3
        return $this->headers;
220
    }
221
222
    /**
223
     * Create Response reflection from a response
224
     *
225
     * @param PsrResponseInterface $response
226
     *
227
     * @return ResponseInterface|object
228
     * @throws \ReflectionException
229
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
230
     * @throws \RuntimeException
231
     */
232 3
    protected function createResponseRefFromResponse(PsrResponseInterface $response)
233
    {
234 3
        $responseRef = $this->createResponseReflectionInstance();
235
236 3
        return $responseRef->newInstance(
237 3
            $response->getBody()->getContents(),
238 3
            $response->getStatusCode(),
239 3
            $response->getHeaders()
240
        );
241
    }
242
243
    /**
244
     * Creates a Reflection Response class.
245
     *
246
     * @return \ReflectionClass
247
     * @throws \CCT\Component\Rest\Exception\InvalidParameterException
248
     * @throws \ReflectionException
249
     */
250 3
    private function createResponseReflectionInstance(): \ReflectionClass
251
    {
252 3
        $responseClass = $this->config->get(Config::RESPONSE_CLASS, Response::class);
253 3
        $responseRef = new \ReflectionClass($responseClass);
254
255 3
        if (!$responseRef->implementsInterface(ResponseInterface::class)) {
256
            throw new InvalidParameterException(sprintf(
257
                'The response class must be an implementation of %s',
258
                ResponseInterface::class
259
            ));
260
        }
261
262 3
        return $responseRef;
263
    }
264
265
    /**
266
     * @return string|null
267
     */
268 3
    public function getUri(): ?string
269
    {
270 3
        return $this->config->get(Config::URI_PREFIX, '/');
271
    }
272
273
    /**
274
     * Initialization of the request.
275
     *
276
     * @return void
277
     */
278
    abstract protected function setUp(): void;
279
}
280