Completed
Push — master ( ef3dc6...e28065 )
by David
03:47
created

HttpApi   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 213
Duplicated Lines 16.9 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 80.52%

Importance

Changes 0
Metric Value
wmc 27
lcom 2
cbo 7
dl 36
loc 213
ccs 62
cts 77
cp 0.8052
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A hydrateResponse() 0 12 4
B handleErrors() 0 20 7
A httpGet() 0 16 3
A httpPost() 0 4 1
A httpPostRaw() 12 12 2
A httpPut() 12 12 2
A httpDelete() 12 12 2
A createRequestBody() 0 17 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\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
    private $httpClient;
33
34
    /**
35
     * @var Hydrator
36
     */
37
    protected $hydrator;
38
39
    /**
40
     * @var RequestBuilder
41
     */
42
    protected $requestBuilder;
43
44
    /**
45
     * @param HttpClient     $httpClient
46
     * @param RequestBuilder $requestBuilder
47
     * @param Hydrator       $hydrator
48
     */
49 39
    public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
50
    {
51 39
        $this->httpClient = $httpClient;
52 39
        $this->requestBuilder = $requestBuilder;
53 39
        if (!$hydrator instanceof NoopHydrator) {
54 39
            $this->hydrator = $hydrator;
55 39
        }
56 39
    }
57
58
    /**
59
     * @param ResponseInterface $response
60
     * @param string            $class
61
     *
62
     * @return mixed|ResponseInterface
63
     *
64
     * @throws \Exception
65
     */
66 33
    protected function hydrateResponse(ResponseInterface $response, $class)
67
    {
68 33
        if (!$this->hydrator) {
69
            return $response;
70
        }
71
72 33
        if (200 !== $response->getStatusCode() && 201 !== $response->getStatusCode()) {
73 6
            $this->handleErrors($response);
74
        }
75
76 27
        return $this->hydrator->hydrate($response, $class);
77
    }
78
79
    /**
80
     * Throw the correct exception for this error.
81
     *
82
     * @param ResponseInterface $response
83
     *
84
     * @throws \Exception
85
     */
86 6
    protected function handleErrors(ResponseInterface $response)
87
    {
88 6
        $statusCode = $response->getStatusCode();
89
        switch ($statusCode) {
90 6
            case 400:
91 2
                throw HttpClientException::badRequest($response);
92 4
            case 401:
93
                throw HttpClientException::unauthorized($response);
94 4
            case 402:
95
                throw HttpClientException::requestFailed($response);
96 4
            case 404:
97 4
                throw HttpClientException::notFound($response);
98
            case 413:
99
                throw HttpClientException::payloadTooLarge($response);
100
            case 500 <= $statusCode:
101
                throw HttpServerException::serverError($statusCode);
102
            default:
103
                throw new UnknownErrorException();
104
        }
105
    }
106
107
    /**
108
     * Send a GET request with query parameters.
109
     *
110
     * @param string $path           Request path
111
     * @param array  $parameters     GET parameters
112
     * @param array  $requestHeaders Request Headers
113
     *
114
     * @return ResponseInterface
115
     */
116 7
    protected function httpGet($path, array $parameters = [], array $requestHeaders = [])
117
    {
118 7
        if (count($parameters) > 0) {
119 4
            $path .= '?'.http_build_query($parameters);
120 4
        }
121
122
        try {
123 7
            $response = $this->httpClient->sendRequest(
124 7
                $this->requestBuilder->create('GET', $path, $requestHeaders)
125 7
            );
126 7
        } catch (HttplugException\NetworkException $e) {
127
            throw HttpServerException::networkError($e);
128
        }
129
130 7
        return $response;
131
    }
132
133
    /**
134
     * Send a POST request with parameters.
135
     *
136
     * @param string $path           Request path
137
     * @param array  $parameters     POST parameters
138
     * @param array  $requestHeaders Request headers
139
     *
140
     * @return ResponseInterface
141
     */
142 5
    protected function httpPost($path, array $parameters = [], array $requestHeaders = [])
143
    {
144 5
        return $this->httpPostRaw($path, $this->createRequestBody($parameters), $requestHeaders);
145
    }
146
147
    /**
148
     * Send a POST request with raw data.
149
     *
150
     * @param string       $path           Request path
151
     * @param array|string $body           Request body
152
     * @param array        $requestHeaders Request headers
153
     *
154
     * @return ResponseInterface
155
     */
156 5 View Code Duplication
    protected function httpPostRaw($path, $body, array $requestHeaders = [])
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...
157
    {
158
        try {
159 5
            $response = $this->httpClient->sendRequest(
160 5
                $this->requestBuilder->create('POST', $path, $requestHeaders, $body)
161 5
            );
162 5
        } catch (HttplugException\NetworkException $e) {
163
            throw HttpServerException::networkError($e);
164
        }
165
166 5
        return $response;
167
    }
168
169
    /**
170
     * Send a PUT request.
171
     *
172
     * @param string $path           Request path
173
     * @param array  $parameters     PUT parameters
174
     * @param array  $requestHeaders Request headers
175
     *
176
     * @return ResponseInterface
177
     */
178 4 View Code Duplication
    protected function httpPut($path, array $parameters = [], array $requestHeaders = [])
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...
179
    {
180
        try {
181 4
            $response = $this->httpClient->sendRequest(
182 4
                $this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createRequestBody($parameters))
183 4
            );
184 4
        } catch (HttplugException\NetworkException $e) {
185
            throw HttpServerException::networkError($e);
186
        }
187
188 4
        return $response;
189
    }
190
191
    /**
192
     * Send a DELETE request.
193
     *
194
     * @param string $path           Request path
195
     * @param array  $parameters     DELETE parameters
196
     * @param array  $requestHeaders Request headers
197
     *
198
     * @return ResponseInterface
199
     */
200 6 View Code Duplication
    protected function httpDelete($path, array $parameters = [], array $requestHeaders = [])
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...
201
    {
202
        try {
203 6
            $response = $this->httpClient->sendRequest(
204 6
                $this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createRequestBody($parameters))
205 6
            );
206 6
        } catch (HttplugException\NetworkException $e) {
207
            throw HttpServerException::networkError($e);
208
        }
209
210 6
        return $response;
211
    }
212
213
    /**
214
     * Prepare a set of key-value-pairs to be encoded as multipart/form-data.
215
     *
216
     * @param array $parameters Request parameters
217
     *
218
     * @return array
219
     */
220 15
    protected function createRequestBody(array $parameters)
221
    {
222 15
        $resources = [];
223 15
        foreach ($parameters as $key => $values) {
224 8
            if (!is_array($values)) {
225 8
                $values = [$values];
226 8
            }
227 8
            foreach ($values as $value) {
228 8
                $resources[] = [
229 8
                    'name' => $key,
230 8
                    'content' => $value,
231
                ];
232 8
            }
233 15
        }
234
235 15
        return $resources;
236
    }
237
}
238