HttpApi   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 5
dl 0
loc 147
ccs 0
cts 54
cp 0
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A httpGet() 0 10 2
A httpPost() 0 4 1
A httpPostRaw() 0 6 1
A httpPut() 0 6 1
A httpDelete() 0 6 1
A createJsonBody() 0 4 3
A handleErrors() 0 12 2
1
<?php
2
3
declare(strict_types=1);
4
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 FAPI\Boilerplate\Api;
11
12
use FAPI\Boilerplate\Exception\Domain as DomainExceptions;
13
use FAPI\Boilerplate\Exception\DomainException;
14
use FAPI\Boilerplate\Hydrator\NoopHydrator;
15
use Http\Client\HttpClient;
16
use FAPI\Boilerplate\Hydrator\Hydrator;
17
use FAPI\Boilerplate\RequestBuilder;
18
use Psr\Http\Message\ResponseInterface;
19
20
/**
21
 * @author Tobias Nyholm <[email protected]>
22
 */
23
abstract class HttpApi
24
{
25
    /**
26
     * @var HttpClient
27
     */
28
    protected $httpClient;
29
30
    /**
31
     * @var Hydrator
32
     */
33
    protected $hydrator;
34
35
    /**
36
     * @var RequestBuilder
37
     */
38
    protected $requestBuilder;
39
40
    /**
41
     * @param HttpClient     $httpClient
42
     * @param RequestBuilder $requestBuilder
43
     * @param Hydrator       $hydrator
44
     */
45
    public function __construct(HttpClient $httpClient, Hydrator $hydrator, RequestBuilder $requestBuilder)
46
    {
47
        $this->httpClient = $httpClient;
48
        $this->requestBuilder = $requestBuilder;
49
        if (!$hydrator instanceof NoopHydrator) {
50
            $this->hydrator = $hydrator;
51
        }
52
    }
53
54
    /**
55
     * Send a GET request with query parameters.
56
     *
57
     * @param string $path           Request path
58
     * @param array  $params         GET parameters
59
     * @param array  $requestHeaders Request Headers
60
     *
61
     * @return ResponseInterface
62
     */
63
    protected function httpGet(string $path, array $params = [], array $requestHeaders = []): ResponseInterface
64
    {
65
        if (count($params) > 0) {
66
            $path .= '?'.http_build_query($params);
67
        }
68
69
        return $this->httpClient->sendRequest(
70
            $this->requestBuilder->create('GET', $path, $requestHeaders)
71
        );
72
    }
73
74
    /**
75
     * Send a POST request with JSON-encoded parameters.
76
     *
77
     * @param string $path           Request path
78
     * @param array  $params         POST parameters to be JSON encoded
79
     * @param array  $requestHeaders Request headers
80
     *
81
     * @return ResponseInterface
82
     */
83
    protected function httpPost(string $path, array $params = [], array $requestHeaders = []): ResponseInterface
84
    {
85
        return $this->httpPostRaw($path, $this->createJsonBody($params), $requestHeaders);
86
    }
87
88
    /**
89
     * Send a POST request with raw data.
90
     *
91
     * @param string       $path           Request path
92
     * @param array|string $body           Request body
93
     * @param array        $requestHeaders Request headers
94
     *
95
     * @return ResponseInterface
96
     */
97
    protected function httpPostRaw(string $path, $body, array $requestHeaders = []): ResponseInterface
98
    {
99
        return $response = $this->httpClient->sendRequest(
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
100
            $this->requestBuilder->create('POST', $path, $requestHeaders, $body)
101
        );
102
    }
103
104
    /**
105
     * Send a PUT request with JSON-encoded parameters.
106
     *
107
     * @param string $path           Request path
108
     * @param array  $params         POST parameters to be JSON encoded
109
     * @param array  $requestHeaders Request headers
110
     *
111
     * @return ResponseInterface
112
     */
113
    protected function httpPut(string $path, array $params = [], array $requestHeaders = []): ResponseInterface
114
    {
115
        return $this->httpClient->sendRequest(
116
            $this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createJsonBody($params))
117
        );
118
    }
119
120
    /**
121
     * Send a DELETE request with JSON-encoded parameters.
122
     *
123
     * @param string $path           Request path
124
     * @param array  $params         POST parameters to be JSON encoded
125
     * @param array  $requestHeaders Request headers
126
     *
127
     * @return ResponseInterface
128
     */
129
    protected function httpDelete(string $path, array $params = [], array $requestHeaders = []): ResponseInterface
130
    {
131
        return $this->httpClient->sendRequest(
132
            $this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createJsonBody($params))
133
        );
134
    }
135
136
    /**
137
     * Create a JSON encoded version of an array of parameters.
138
     *
139
     * @param array $params Request parameters
140
     *
141
     * @return null|string
142
     */
143
    private function createJsonBody(array $params)
144
    {
145
        return (count($params) === 0) ? null : json_encode($params, empty($params) ? JSON_FORCE_OBJECT : 0);
146
    }
147
148
    /**
149
     * Handle HTTP errors.
150
     *
151
     * Call is controlled by the specific API methods.
152
     *
153
     * @param ResponseInterface $response
154
     *
155
     * @throws DomainException
156
     */
157
    protected function handleErrors(ResponseInterface $response)
158
    {
159
        switch ($response->getStatusCode()) {
160
            case 404:
161
                throw new DomainExceptions\NotFoundException();
162
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
163
164
            default:
165
                throw new DomainExceptions\UnknownErrorException();
166
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
167
        }
168
    }
169
}
170