Completed
Push — master ( 0f5433...3fbd33 )
by David
01:51
created

HttpApi::httpPost()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2013 Mailgun
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license. See the LICENSE file for details.
10
 */
11
12
namespace Mailgun\Api;
13
14
use Http\Client\Exception as HttplugException;
15
use Http\Client\HttpClient;
16
use Mailgun\Exception\UnknownErrorException;
17
use Mailgun\Hydrator\Hydrator;
18
use Mailgun\Hydrator\NoopHydrator;
19
use Mailgun\Exception\HttpClientException;
20
use Mailgun\Exception\HttpServerException;
21
use Mailgun\HttpClient\RequestBuilder;
22
use Psr\Http\Message\ResponseInterface;
23
24
/**
25
 * @author Tobias Nyholm <[email protected]>
26
 */
27
abstract class HttpApi
28
{
29
    /**
30
     * The HTTP client.
31
     *
32
     * @var HttpClient
33
     */
34
    protected $httpClient;
35
36
    /**
37
     * @var Hydrator|null
38
     */
39
    protected $hydrator;
40
41
    /**
42
     * @var RequestBuilder
43
     */
44
    protected $requestBuilder;
45
46 87
    public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
47
    {
48 87
        $this->httpClient = $httpClient;
49 87
        $this->requestBuilder = $requestBuilder;
50 87
        if (!$hydrator instanceof NoopHydrator) {
51 87
            $this->hydrator = $hydrator;
52
        }
53 87
    }
54
55
    /**
56
     * @return mixed|ResponseInterface
57
     *
58
     * @throws \Exception
59
     */
60 66
    protected function hydrateResponse(ResponseInterface $response, string $class)
61
    {
62 66
        if (null === $this->hydrator) {
63
            return $response;
64
        }
65
66 66
        if (200 !== $response->getStatusCode() && 201 !== $response->getStatusCode()) {
67
            $this->handleErrors($response);
68
        }
69
70 66
        return $this->hydrator->hydrate($response, $class);
71
    }
72
73
    /**
74
     * Throw the correct exception for this error.
75
     *
76
     * @throws \Exception
77
     */
78
    protected function handleErrors(ResponseInterface $response)
79
    {
80
        $statusCode = $response->getStatusCode();
81
        switch ($statusCode) {
82
            case 400:
83
                throw HttpClientException::badRequest($response);
84
            case 401:
85
                throw HttpClientException::unauthorized($response);
86
            case 402:
87
                throw HttpClientException::requestFailed($response);
88
            case 404:
89
                throw HttpClientException::notFound($response);
90
            case 413:
91
                throw HttpClientException::payloadTooLarge($response);
92
            case 500 <= $statusCode:
93
                throw HttpServerException::serverError($statusCode);
94
            default:
95
                throw new UnknownErrorException();
96
        }
97
    }
98
99
    /**
100
     * Send a GET request with query parameters.
101
     *
102
     * @param string $path           Request path
103
     * @param array  $parameters     GET parameters
104
     * @param array  $requestHeaders Request Headers
105
     */
106 17
    protected function httpGet(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
107
    {
108 17
        if (count($parameters) > 0) {
109 5
            $path .= '?'.http_build_query($parameters);
110
        }
111
112
        try {
113 17
            $response = $this->httpClient->sendRequest(
114 17
                $this->requestBuilder->create('GET', $path, $requestHeaders)
115
            );
116
        } catch (HttplugException\NetworkException $e) {
117
            throw HttpServerException::networkError($e);
118
        }
119
120 17
        return $response;
121
    }
122
123
    /**
124
     * Send a POST request with parameters.
125
     *
126
     * @param string $path           Request path
127
     * @param array  $parameters     POST parameters
128
     * @param array  $requestHeaders Request headers
129
     */
130 7
    protected function httpPost(string $path, array $parameters = [], array $requestHeaders = []): ResponseInterface
131
    {
132 7
        return $this->httpPostRaw($path, $this->createRequestBody($parameters), $requestHeaders);
133
    }
134
135
    /**
136
     * Send a POST request with raw data.
137
     *
138
     * @param string       $path           Request path
139
     * @param array|string $body           Request body
140
     * @param array        $requestHeaders Request headers
141
     */
142 8 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...
143
    {
144
        try {
145 8
            $response = $this->httpClient->sendRequest(
146 8
                $this->requestBuilder->create('POST', $path, $requestHeaders, $body)
147
            );
148
        } catch (HttplugException\NetworkException $e) {
149
            throw HttpServerException::networkError($e);
150
        }
151
152 8
        return $response;
153
    }
154
155
    /**
156
     * Send a PUT request.
157
     *
158
     * @param string $path           Request path
159
     * @param array  $parameters     PUT parameters
160
     * @param array  $requestHeaders Request headers
161
     */
162 5 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...
163
    {
164
        try {
165 5
            $response = $this->httpClient->sendRequest(
166 5
                $this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createRequestBody($parameters))
167
            );
168
        } catch (HttplugException\NetworkException $e) {
169
            throw HttpServerException::networkError($e);
170
        }
171
172 5
        return $response;
173
    }
174
175
    /**
176
     * Send a DELETE request.
177
     *
178
     * @param string $path           Request path
179
     * @param array  $parameters     DELETE parameters
180
     * @param array  $requestHeaders Request headers
181
     */
182 10 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...
183
    {
184
        try {
185 10
            $response = $this->httpClient->sendRequest(
186 10
                $this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createRequestBody($parameters))
187
            );
188
        } catch (HttplugException\NetworkException $e) {
189
            throw HttpServerException::networkError($e);
190
        }
191
192 10
        return $response;
193
    }
194
195
    /**
196
     * Prepare a set of key-value-pairs to be encoded as multipart/form-data.
197
     *
198
     * @param array $parameters Request parameters
199
     */
200 22
    private function createRequestBody(array $parameters): array
201
    {
202 22
        $resources = [];
203 22
        foreach ($parameters as $key => $values) {
204 11
            if (!is_array($values)) {
205 11
                $values = [$values];
206
            }
207 11
            foreach ($values as $value) {
208 11
                $resources[] = [
209 11
                    'name' => $key,
210 11
                    'content' => $value,
211
                ];
212
            }
213
        }
214
215 22
        return $resources;
216
    }
217
}
218