Completed
Push — develop ( 66130e...e39ec3 )
by Adam
14:00
created

src/Common/Api/AbstractApi.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace IBM\Watson\Common\Api;
6
7
use Http\Client\HttpClient;
8
use IBM\Watson\Common\Exception\Api\BadRequestException;
9
use IBM\Watson\Common\Exception\Domain\InsufficientPrivilegesException;
10
use IBM\Watson\Common\Exception\Domain\NotFoundException;
11
use IBM\Watson\Common\Exception\Domain\UnknownErrorException;
12
use IBM\Watson\Common\Hydrator\HydratorInterface;
13
use IBM\Watson\Common\RequestBuilder;
14
use IBM\Watson\Common\Util\ValidateQueryParams;
15
use Psr\Http\Message\ResponseInterface;
16
use Psr\Http\Message\StreamInterface;
17
use Psr\Http\Message\UriInterface;
18
19
/**
20
 *
21
 */
22
abstract class AbstractApi
23
{
24
    use ValidateQueryParams;
25
26
    /**
27
     * @var string HTTP methods
28
     */
29
    private const HTTP_METHOD_GET       = 'GET';
30
    private const HTTP_METHOD_POST      = 'POST';
31
    private const HTTP_METHOD_PUT       = 'PUT';
32
    private const HTTP_METHOD_PATCH     = 'PATCH';
33
    private const HTTP_METHOD_DELETE    = 'DELETE';
34
35
    /**
36
     * @var \Http\Client\HttpClient
37
     */
38
    private $httpClient;
39
40
    /**
41
     * @var \IBM\Watson\Common\Hydrator\HydratorInterface
42
     */
43
    protected $hydrator;
44
45
    /**
46
     * @var \IBM\Watson\Common\RequestBuilder
47
     */
48
    private $requestBuilder;
49
50
    /**
51
     * @param \Http\Client\HttpClient                       $httpClient
52
     * @param \IBM\Watson\Common\Hydrator\HydratorInterface $hydrator
53
     * @param \IBM\Watson\Common\RequestBuilder             $requestBuilder
54
     */
55
    public function __construct(
56
        HttpClient $httpClient,
57
        HydratorInterface $hydrator,
58
        RequestBuilder $requestBuilder
59
    ) {
60
        $this->httpClient     = $httpClient;
61
        $this->hydrator = $hydrator;
62
        $this->requestBuilder = $requestBuilder;
63
        $this->setAllowedParams();
64
    }
65
66
    /**
67
     * @param string|UriInterface $path
68
     * @param array               $params
69
     * @param array               $headers
70
     *
71
     * @return \Psr\Http\Message\ResponseInterface
72
     * @throws \Http\Client\Exception
73
     */
74
    protected function get($path, array $params = [], array $headers = []): ResponseInterface
75
    {
76
        $params = $this->validateQueryParams($params);
77
        $path = $this->buildQueryPath($path, $params);
0 ignored issues
show
It seems like $path can also be of type object<Psr\Http\Message\UriInterface>; however, IBM\Watson\Common\Api\Ab...ctApi::buildQueryPath() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
78
79
        return $this->httpClient->sendRequest(
80
            $this->requestBuilder->create(static::HTTP_METHOD_GET, $path, $headers)
81
        );
82
    }
83
84
    /**
85
     * @param string|UriInterface $path
86
     * @param array               $params
87
     * @param array               $headers
88
     *
89
     * @return \Psr\Http\Message\ResponseInterface
90
     * @throws \Http\Client\Exception
91
     */
92
    protected function post($path, array $params = [], array $headers = []): ResponseInterface
93
    {
94
        $params = $this->validateQueryParams($params);
95
96
        return $this->postRaw($path, \http_build_query($params), $headers);
97
    }
98
99
    /**
100
     * @param string|UriInterface                  $path
101
     * @param resource|string|StreamInterface|null $body
102
     * @param array                                $headers
103
     *
104
     * @return \Psr\Http\Message\ResponseInterface
105
     * @throws \Http\Client\Exception
106
     */
107
    protected function postRaw($path, $body, array $headers = []): ResponseInterface
108
    {
109
        return $this->httpClient->sendRequest(
110
            $this->requestBuilder->create(static::HTTP_METHOD_POST, $path, $headers, $body)
111
        );
112
    }
113
114
    /**
115
     * @param string|UriInterface $path
116
     * @param array               $params
117
     * @param array               $headers
118
     *
119
     * @return \Psr\Http\Message\ResponseInterface
120
     * @throws \Http\Client\Exception
121
     */
122
    protected function put($path, array $params = [], array $headers = []): ResponseInterface
123
    {
124
        $params = $this->validateQueryParams($params);
125
126
        return $this->httpClient->sendRequest(
127
            $this->requestBuilder->create(static::HTTP_METHOD_PUT, $path, $headers, \http_build_query($params))
128
        );
129
    }
130
131
    /**
132
     * @param string|UriInterface $path
133
     * @param array               $params
134
     * @param array               $headers
135
     *
136
     * @return \Psr\Http\Message\ResponseInterface
137
     * @throws \Http\Client\Exception
138
     */
139
    protected function patch($path, array $params = [], array $headers = []): ResponseInterface
140
    {
141
        $params = $this->validateQueryParams($params);
142
143
        return $this->httpClient->sendRequest(
144
            $this->requestBuilder->create(static::HTTP_METHOD_PATCH, $path, $headers, \json_encode($params))
145
        );
146
    }
147
148
    /**
149
     * @param string|UriInterface $path
150
     * @param array               $params
151
     * @param array               $headers
152
     *
153
     * @return \Psr\Http\Message\ResponseInterface
154
     * @throws \Http\Client\Exception
155
     */
156
    protected function delete($path, array $params = [], array $headers = []): ResponseInterface
157
    {
158
        $params = $this->validateQueryParams($params);
159
160
        return $this->httpClient->sendRequest(
161
            $this->requestBuilder->create(static::HTTP_METHOD_DELETE, $path, $headers, \http_build_query($params))
162
        );
163
    }
164
165
    /**
166
     * Handle errors from response
167
     *
168
     * @param ResponseInterface $response
169
     *
170
     * @return void
171
     *
172
     * @throws \IBM\Watson\Common\Exception\Api\BadRequestException
173
     * @throws \IBM\Watson\Common\Exception\Domain\InsufficientPrivilegesException
174
     * @throws \IBM\Watson\Common\Exception\Domain\NotFoundException
175
     * @throws \IBM\Watson\Common\Exception\Domain\UnknownErrorException
176
     */
177
    protected function handleErrors(ResponseInterface $response): void
178
    {
179
        $body = $response->getBody()->__toString();
180
        $content = \json_decode($body, true);
181
        $message = '';
182
183
        if (JSON_ERROR_NONE === \json_last_error()) {
184
            $message = $content['error'];
185
        }
186
187
        switch ($response->getStatusCode()) {
188
            case 400:
189
                throw new BadRequestException($message);
190
                break;
0 ignored issues
show
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...
191
            case 401:
192
                throw new InsufficientPrivilegesException($message);
193
                break;
0 ignored issues
show
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...
194
            case 404:
195
                throw new NotFoundException($message);
196
                break;
0 ignored issues
show
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...
197
            case 500:
198
                throw new UnknownErrorException($message);
199
                break;
0 ignored issues
show
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...
200
            default:
201
                throw new UnknownErrorException($message);
202
                break;
0 ignored issues
show
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...
203
        }
204
    }
205
206
    /**
207
     * @param string $path
208
     * @param array  $params
209
     *
210
     * @return string
211
     */
212
    private function buildQueryPath(string $path, array $params): string
213
    {
214
        if (count($params) > 0) {
215
            $path .= '?' . \http_build_query($params);
216
        }
217
218
        return $path;
219
    }
220
221
    /**
222
     * @return $this
223
     */
224
    abstract protected function setAllowedParams(): self;
225
}
226