Completed
Push — master ( 4a903b...b725ab )
by Tobias
03:23 queued 53s
created

HttpApi::hydrateResponse()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4.5923

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 4
cts 6
cp 0.6667
rs 9.8666
c 0
b 0
f 0
cc 4
nc 3
nop 2
crap 4.5923
1
<?php
2
3
/*
4
 * Copyright (C) 2013 Mailgun
5
 *
6
 * This software may be modified and distributed under the terms
7
 * of the MIT license. See the LICENSE file for details.
8
 */
9
10
namespace Mailgun\Api;
11
12
use Http\Client\Exception as HttplugException;
13
use Http\Client\HttpClient;
14
use Mailgun\Exception\UnknownErrorException;
15
use Mailgun\Hydrator\Hydrator;
16
use Mailgun\Hydrator\NoopHydrator;
17
use Mailgun\Exception\HttpClientException;
18
use Mailgun\Exception\HttpServerException;
19
use Mailgun\HttpClient\RequestBuilder;
20
use Psr\Http\Message\ResponseInterface;
21
22
/**
23
 * @author Tobias Nyholm <[email protected]>
24
 */
25
abstract class HttpApi
26
{
27
    /**
28
     * The HTTP client.
29
     *
30
     * @var HttpClient
31
     */
32
    protected $httpClient;
33
34
    /**
35
     * @var Hydrator
36
     */
37
    protected $hydrator;
38
39
    /**
40
     * @var RequestBuilder
41
     */
42
    protected $requestBuilder;
43
44 47
    public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
45
    {
46 47
        $this->httpClient = $httpClient;
47 47
        $this->requestBuilder = $requestBuilder;
48 47
        if (!$hydrator instanceof NoopHydrator) {
49 47
            $this->hydrator = $hydrator;
50
        }
51 47
    }
52
53
    /**
54
     * @param ResponseInterface $response
55
     * @param string            $class
56
     *
57
     * @return mixed|ResponseInterface
58
     *
59
     * @throws \Exception
60
     */
61 26
    protected function hydrateResponse(ResponseInterface $response, string $class)
62
    {
63 26
        if (!$this->hydrator) {
64
            return $response;
65
        }
66
67 26
        if (200 !== $response->getStatusCode() && 201 !== $response->getStatusCode()) {
68
            $this->handleErrors($response);
69
        }
70
71 26
        return $this->hydrator->hydrate($response, $class);
72
    }
73
74
    /**
75
     * Throw the correct exception for this error.
76
     *
77
     * @throws \Exception
78
     */
79
    protected function handleErrors(ResponseInterface $response)
80
    {
81
        $statusCode = $response->getStatusCode();
82
        switch ($statusCode) {
83
            case 400:
84
                throw HttpClientException::badRequest($response);
85
            case 401:
86
                throw HttpClientException::unauthorized($response);
87
            case 402:
88
                throw HttpClientException::requestFailed($response);
89
            case 404:
90
                throw HttpClientException::notFound($response);
91
            case 413:
92
                throw HttpClientException::payloadTooLarge($response);
93
            case 500 <= $statusCode:
94
                throw HttpServerException::serverError($statusCode);
95
            default:
96
                throw new UnknownErrorException();
97
        }
98
    }
99
100
    /**
101
     * Send a GET request with query parameters.
102
     *
103
     * @param string $path           Request path
104
     * @param array  $parameters     GET parameters
105
     * @param array  $requestHeaders Request Headers
106
     */
107 2
    protected function httpGet(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
108
    {
109 2
        if (count($parameters) > 0) {
110 1
            $path .= '?'.http_build_query($parameters);
111
        }
112
113
        try {
114 2
            $response = $this->httpClient->sendRequest(
115 2
                $this->requestBuilder->create('GET', $path, $requestHeaders)
116
            );
117
        } catch (HttplugException\NetworkException $e) {
118
            throw HttpServerException::networkError($e);
119
        }
120
121 2
        return $response;
122
    }
123
124
    /**
125
     * Send a POST request with parameters.
126
     *
127
     * @param string $path           Request path
128
     * @param array  $parameters     POST parameters
129
     * @param array  $requestHeaders Request headers
130
     */
131
    protected function httpPost(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
132
    {
133
        return $this->httpPostRaw($path, $this->createRequestBody($parameters), $requestHeaders);
134
    }
135
136
    /**
137
     * Send a POST request with raw data.
138
     *
139
     * @param string       $path           Request path
140
     * @param array|string $body           Request body
141
     * @param array        $requestHeaders Request headers
142
     */
143 View Code Duplication
    protected function httpPostRaw(string $path, $body, array $requestHeaders = []): ResponseInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145
        try {
146
            $response = $this->httpClient->sendRequest(
147
                $this->requestBuilder->create('POST', $path, $requestHeaders, $body)
148
            );
149
        } catch (HttplugException\NetworkException $e) {
150
            throw HttpServerException::networkError($e);
151
        }
152
153
        return $response;
154
    }
155
156
    /**
157
     * Send a PUT request.
158
     *
159
     * @param string $path           Request path
160
     * @param array  $parameters     PUT parameters
161
     * @param array  $requestHeaders Request headers
162
     */
163 View Code Duplication
    protected function httpPut(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
    {
165
        try {
166
            $response = $this->httpClient->sendRequest(
167
                $this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createRequestBody($parameters))
168
            );
169
        } catch (HttplugException\NetworkException $e) {
170
            throw HttpServerException::networkError($e);
171
        }
172
173
        return $response;
174
    }
175
176
    /**
177
     * Send a DELETE request.
178
     *
179
     * @param string $path           Request path
180
     * @param array  $parameters     DELETE parameters
181
     * @param array  $requestHeaders Request headers
182
     */
183 View Code Duplication
    protected function httpDelete(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
184
    {
185
        try {
186
            $response = $this->httpClient->sendRequest(
187
                $this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createRequestBody($parameters))
188
            );
189
        } catch (HttplugException\NetworkException $e) {
190
            throw HttpServerException::networkError($e);
191
        }
192
193
        return $response;
194
    }
195
196
    /**
197
     * Prepare a set of key-value-pairs to be encoded as multipart/form-data.
198
     *
199
     * @param array $parameters Request parameters
200
     *
201
     * @return array
202
     */
203
    private function createRequestBody(array $parameters): array
204
    {
205
        $resources = [];
206
        foreach ($parameters as $key => $values) {
207
            if (!is_array($values)) {
208
                $values = [$values];
209
            }
210
            foreach ($values as $value) {
211
                $resources[] = [
212
                    'name' => $key,
213
                    'content' => $value,
214
                ];
215
            }
216
        }
217
218
        return $resources;
219
    }
220
}
221