setErrorBodyConverter()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
declare(strict_types=1);
8
9
namespace Tebru\Retrofit\Internal\ServiceMethod;
10
11
use LogicException;
12
use Tebru\Retrofit\CallAdapter;
13
use Tebru\Retrofit\ParameterHandler;
14
use Tebru\Retrofit\ResponseBodyConverter;
15
use Tebru\Retrofit\ServiceMethodBuilder;
16
17
/**
18
 * Class DefaultServiceMethodBuilder
19
 *
20
 * Constructs a [@ServiceMethod]
21
 *
22
 * @author Nate Brunette <[email protected]>
23
 */
24
final class DefaultServiceMethodBuilder implements ServiceMethodBuilder
25
{
26
    /**
27
     * The request method
28
     *
29
     * @var string
30
     */
31
    private $method;
32
33
    /**
34
     * The request base url
35
     *
36
     * @var string
37
     */
38
    private $baseUrl;
39
40
    /**
41
     * The request path
42
     *
43
     * @var string
44
     */
45
    private $path;
46
47
    /**
48
     * True if the request has a body
49
     *
50
     * @var bool
51
     */
52
    private $hasBody;
53
54
    /**
55
     * The request body content type
56
     *
57
     * @var string
58
     */
59
    private $contentType;
60
61
    /**
62
     * Array of headers
63
     *
64
     * @var array
65
     */
66
    private $headers = [];
67
68
    /**
69
     * Array of Parameter handlers, indexed to match the position of the parameters
70
     *
71
     * @var ParameterHandler[]
72
     */
73
    private $parameterHandlers = [];
74
75
    /**
76
     * Converts successful response bodies to expected value
77
     *
78
     * @var ResponseBodyConverter
79
     */
80
    private $responseBodyConverter;
81
82
    /**
83
     * Converts error response bodies to expected value
84
     *
85
     * @var ResponseBodyConverter
86
     */
87
    private $errorBodyConverter;
88
89
    /**
90
     * Adapts a [@see Call] to expected value
91
     *
92
     * @var CallAdapter
93
     */
94
    private $callAdapter;
95
96
    /**
97
     * Set the request method (e.g. GET, POST)
98
     *
99
     * @param string $method
100
     * @return ServiceMethodBuilder
101
     * @throws \LogicException
102
     */
103 33
    public function setMethod(string $method): ServiceMethodBuilder
104
    {
105 33
        if ($this->method !== null) {
106 1
            throw new LogicException(sprintf(
107 1
                'Retrofit: Only one http method is allowed. Trying to set %s, but %s already exists',
108 1
                strtoupper($method),
109 1
                $this->method
110
            ));
111
        }
112
113 33
        $this->method = strtoupper($method);
114
115 33
        return $this;
116
    }
117
118
    /**
119
     * Set the request base url (e.g. http://example.com)
120
     *
121
     * @param string $baseUrl
122
     * @return ServiceMethodBuilder
123
     */
124 29
    public function setBaseUrl(string $baseUrl): ServiceMethodBuilder
125
    {
126 29
        $this->baseUrl = $baseUrl;
127
128 29
        return $this;
129
    }
130
131
    /**
132
     * Set the request path
133
     *
134
     * @param string $path
135
     * @return ServiceMethodBuilder
136
     */
137 30
    public function setPath(string $path): ServiceMethodBuilder
138
    {
139 30
        $this->path = $path;
140
141 30
        return $this;
142
    }
143
144
    /**
145
     * Set to true if an annotation exists that denotes a request body. This should also set
146
     * the request content type.
147
     *
148
     * @param bool $hasBody
149
     * @return ServiceMethodBuilder
150
     * @throws \LogicException
151
     */
152 34
    public function setHasBody(bool $hasBody): ServiceMethodBuilder
153
    {
154 34
        if ($this->hasBody !== null && $this->hasBody !== $hasBody) {
155 2
            throw new LogicException(
156
                'Retrofit: Body cannot be changed after it has been set. This indicates a conflict between ' .
157
                'HTTP Request annotations, body annotations, and request type annotations. For example, ' .
158 2
                '@GET cannot be used with @Body, @Field, or @Part annotations'
159
            );
160
        }
161
162 34
        $this->hasBody = $hasBody;
163
164 34
        return $this;
165
    }
166
167
    /**
168
     * Set the content type of the request. A content type should not be set if there
169
     * isn't a request body.
170
     *
171
     * @param string $contentType
172
     * @return ServiceMethodBuilder
173
     * @throws \LogicException
174
     */
175 19
    public function setContentType(string $contentType): ServiceMethodBuilder
176
    {
177 19
        if ($this->contentType !== null && $this->contentType !== $contentType) {
178 1
            throw new LogicException(
179
                'Retrofit: Content type cannot be changed after it has been set. This indicates a conflict between ' .
180
                'HTTP Request annotations, body annotations, and request type annotations. For example, ' .
181 1
                '@GET cannot be used with @Body, @Field, or @Part annotations'
182
            );
183
        }
184
185 19
        $this->contentType = $contentType;
186
187 19
        return $this;
188
    }
189
190
    /**
191
     * Convenience method to declare that the request has content and is json
192
     *
193
     * @return ServiceMethodBuilder
194
     * @throws \LogicException
195
     */
196 10
    public function setIsJson(): ServiceMethodBuilder
197
    {
198 10
        $this->setHasBody(true);
199 9
        $this->setContentType('application/json');
200
201 9
        return $this;
202
    }
203
204
205
    /**
206
     * Convenience method to declare that the request has content and is form encoded
207
     *
208
     * @return ServiceMethodBuilder
209
     * @throws \LogicException
210
     */
211 5
    public function setIsFormUrlEncoded(): ServiceMethodBuilder
212
    {
213 5
        $this->setHasBody(true);
214 5
        $this->setContentType('application/x-www-form-urlencoded');
215
216 4
        return $this;
217
    }
218
219
    /**
220
     * Convenience method to declare that the request has content and is multipart
221
     *
222
     * @return ServiceMethodBuilder
223
     * @throws \LogicException
224
     */
225 4
    public function setIsMultipart(): ServiceMethodBuilder
226
    {
227 4
        $this->setHasBody(true);
228 4
        $this->setContentType('multipart/form-data');
229
230 4
        return $this;
231
    }
232
233
    /**
234
     * Add a request header. Header name should be normalized.
235
     *
236
     * @param string $name
237
     * @param string $header
238
     * @return ServiceMethodBuilder
239
     */
240 11
    public function addHeader(string $name, string $header): ServiceMethodBuilder
241
    {
242 11
        $this->headers[strtolower($name)][] = $header;
243
244 11
        return $this;
245
    }
246
247
    /**
248
     * Add a [@see ParameterHandler] at the position the parameter exists
249
     *
250
     * @param int $index
251
     * @param ParameterHandler $parameterHandler
252
     * @return ServiceMethodBuilder
253
     */
254 25
    public function addParameterHandler(int $index, ParameterHandler $parameterHandler): ServiceMethodBuilder
255
    {
256 25
        $this->parameterHandlers[$index] = $parameterHandler;
257
258 25
        return $this;
259
    }
260
261
    /**
262
     * Set the [@see CallAdapter]
263
     *
264
     * @param CallAdapter $callAdapter
265
     * @return ServiceMethodBuilder
266
     */
267 23
    public function setCallAdapter(CallAdapter $callAdapter): ServiceMethodBuilder
268
    {
269 23
        $this->callAdapter = $callAdapter;
270
271 23
        return $this;
272
    }
273
274
    /**
275
     * Set the response body converter to convert successful responses
276
     *
277
     * @param ResponseBodyConverter $responseBodyConverter
278
     * @return ServiceMethodBuilder
279
     */
280 24
    public function setResponseBodyConverter(ResponseBodyConverter $responseBodyConverter): ServiceMethodBuilder
281
    {
282 24
        $this->responseBodyConverter = $responseBodyConverter;
283
284 24
        return $this;
285
    }
286
287
    /**
288
     * Set the response body converter to convert error responses
289
     *
290
     * @param ResponseBodyConverter $errorBodyConverter
291
     * @return ServiceMethodBuilder
292
     */
293 23
    public function setErrorBodyConverter(ResponseBodyConverter $errorBodyConverter): ServiceMethodBuilder
294
    {
295 23
        $this->errorBodyConverter = $errorBodyConverter;
296
297 23
        return $this;
298
    }
299
300
    /**
301
     * Create a new [@see DefaultServiceMethod] from previously set parameters
302
     *
303
     * @return DefaultServiceMethod
304
     * @throws \LogicException
305
     */
306 30
    public function build(): DefaultServiceMethod
307
    {
308 30
        if ($this->method === null) {
309 1
            throw new LogicException(
310 1
                'Retrofit: Cannot build service method without HTTP method. Please specify @GET, @POST, etc'
311
            );
312
        }
313
314 29
        if ($this->baseUrl === null) {
315 1
            throw new LogicException(
316 1
                'Retrofit: Cannot build service method without base url. Please specify on RetrofitBuilder'
317
            );
318
        }
319
320 28
        if ($this->path === null) {
321 1
            throw new LogicException(
322 1
                'Retrofit: Cannot build service method without HTTP method. Please specify @GET, @POST, etc'
323
            );
324
        }
325
326 27
        if ($this->hasBody === true && $this->contentType === null) {
327 1
            throw new LogicException(
328
                'Retrofit: Cannot build service method with body and no content type. Set one using @Body, ' .
329 1
                '@Field, or @Part'
330
            );
331
        }
332
333 26
        if ($this->hasBody !== true && $this->contentType !== null) {
334 1
            throw new LogicException(
335
                'Retrofit: Cannot set a content-type without a body. This indicates a conflict between ' .
336
                'HTTP Request annotations, body annotations, and request type annotations. For example, ' .
337 1
                '@GET cannot be used with @Body, @Field, or @Part annotations'
338
            );
339
        }
340
341 25
        if ($this->responseBodyConverter === null) {
342 1
            throw new LogicException(
343 1
                'Retrofit: Cannot build service method without response body converter'
344
            );
345
        }
346
347 24
        if ($this->errorBodyConverter === null) {
348 1
            throw new LogicException(
349 1
                'Retrofit: Cannot build service method without error body converter'
350
            );
351
        }
352
353 23
        if ($this->callAdapter === null) {
354 1
            throw new LogicException(
355 1
                'Retrofit: Cannot build service method without call adapter'
356
            );
357
        }
358
359 22
        if ($this->contentType !== null && !isset($this->headers['content-type'])) {
360 7
            $this->addHeader('content-type', $this->contentType);
361
        }
362
363 22
        if ($this->hasBody === null) {
364 2
            $this->hasBody = false;
365
        }
366
367 22
        ksort($this->parameterHandlers);
368
369 22
        return new DefaultServiceMethod(
370 22
            $this->method,
371 22
            $this->baseUrl,
372 22
            $this->path,
373 22
            $this->headers,
374 22
            $this->parameterHandlers,
375 22
            $this->callAdapter,
376 22
            $this->responseBodyConverter,
377 22
            $this->errorBodyConverter
378
        );
379
    }
380
}
381