GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 5d27ce...6ee2cf )
by Krzysztof
02:23
created

Client::getTickerByCoinId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Coinpaprika;
4
5
use Coinpaprika\Exception\InvalidResponseException;
6
use Coinpaprika\Exception\RateLimitExceededException;
7
use Coinpaprika\Exception\ResponseErrorException;
8
use Coinpaprika\Http\Request;
9
use Coinpaprika\Model\Coin;
10
use Coinpaprika\Model\GlobalStats;
11
use Coinpaprika\Model\Search;
12
use Coinpaprika\Model\Ticker;
13
use JMS\Serializer\SerializerBuilder;
14
use JMS\Serializer\Serializer;
15
use GuzzleHttp\Exception\GuzzleException;
16
use Psr\Http\Message\ResponseInterface;
17
18
/**
19
 * Class Client
20
 *
21
 * @package Coinpaprika
22
 *
23
 * @author Krzysztof Przybyszewski <[email protected]>
24
 */
25
class Client
26
{
27
    const BASE_URL = 'https://api.coinpaprika.com/%ver%/';
28
29
    /**
30
     * @var string
31
     */
32
    private $apiVersion;
33
34
    /**
35
     * @var \GuzzleHttp\Client
36
     */
37
    private $httpClient;
38
39
    /**
40
     * @var Serializer
41
     */
42
    private $serializer;
43
44
    /**
45
     * Client constructor.
46
     *
47
     * @param   string|null         $cacheDir
48
     * @param   \GuzzleHttp\Client  $httpClient
49
     */
50 12
    public function __construct(
51
        string $cacheDir = null,
52
        \GuzzleHttp\Client $httpClient = null
53
    ) {
54 12
        $serializerBuilder = SerializerBuilder::create()
55 12
            ->addMetadataDir(__DIR__.'/Resource/config/serializer');
56
57 12
        if ($cacheDir !== null) {
58 1
            $serializerBuilder->setCacheDir($cacheDir);
59
        }
60
61 12
        $this->apiVersion = 'v1';
62 12
        $this->serializer = $serializerBuilder->build();
63
64 12
        if ($httpClient === null) {
65 1
            $httpClient = new \GuzzleHttp\Client();
66
        }
67
68 12
        $this->httpClient = $httpClient;
69 12
    }
70
71
    /**
72
     * Get global stats
73
     *
74
     * @throws  GuzzleException
75
     * @throws  ResponseErrorException
76
     * @throws  RateLimitExceededException
77
     * @throws  InvalidResponseException
78
     *
79
     * @return  GlobalStats
80
     */
81 1
    public function getGlobalStats(): GlobalStats
82
    {
83 1
        $response = $this->sendRequest(
84 1
            Request::METHOD_GET,
85 1
            $this->getEndpointUrl('global')
86
        );
87
88 1
        return $this->response($response, GlobalStats::class);
89
    }
90
91
    /**
92
     * Get tickers
93
     *
94
     * @throws  GuzzleException
95
     * @throws  ResponseErrorException
96
     * @throws  RateLimitExceededException
97
     * @throws  InvalidResponseException
98
     *
99
     * @return  array|Ticker[]
100
     */
101 1
    public function getTickers(): array
102
    {
103 1
        $response = $this->sendRequest(
104 1
            Request::METHOD_GET,
105 1
            $this->getEndpointUrl('ticker')
106
        );
107
108 1
        return $this->response($response, sprintf('array<%s>', Ticker::class));
109
    }
110
111
    /**
112
     * Get coin`s ticker data
113
     *
114
     * @param   string $id
115
     *
116
     * @throws  GuzzleException
117
     * @throws  ResponseErrorException
118
     * @throws  RateLimitExceededException
119
     * @throws  InvalidResponseException
120
     *
121
     * @return  Ticker
122
     */
123 4
    public function getTickerByCoinId(string $id): Ticker
124
    {
125 4
        $response = $this->sendRequest(
126 4
            Request::METHOD_GET,
127 4
            $this->getEndpointUrl(sprintf('ticker/%s', $id))
128
        );
129
130 4
        return $this->response($response, Ticker::class);
131
    }
132
133
    /**
134
     * Get coins list
135
     *
136
     * @throws  GuzzleException
137
     * @throws  ResponseErrorException
138
     * @throws  RateLimitExceededException
139
     * @throws  InvalidResponseException
140
     *
141
     * @return  array|Coin[]
142
     */
143 1
    public function getCoins(): array
144
    {
145 1
        $response = $this->sendRequest(
146 1
            Request::METHOD_GET,
147 1
            $this->getEndpointUrl('coins')
148
        );
149
150 1
        return $this->response($response, sprintf('array<%s>', Coin::class));
151
152
    }
153
154
    /**
155
     * @param   string     $query
156
     * @param   array|null $categories
157
     * @param   null       $limit
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $limit is correct as it would always require null to be passed?
Loading history...
158
     *
159
     * @throws  InvalidResponseException
160
     * @throws  RateLimitExceededException
161
     * @throws  ResponseErrorException
162
     * @throws  GuzzleException
163
     *
164
     * @return Search
165
     */
166 4
    public function search(string $query, array $categories = null, $limit = null): Search
167
    {
168 4
        $params = array_filter([
169 4
            'q' => $query,
170 4
            'c' => $categories ? implode(',', $categories) : null,
171 4
            'limit' => $limit
172
        ]);
173
174 4
        $response = $this->sendRequest(
175 4
            Request::METHOD_GET,
176 4
            $this->getEndpointUrl('global'),
177 4
            $params
178
        );
179
180 4
        return $this->response($response, Search::class);
181
    }
182
183
    /**
184
     * Get the API version
185
     *
186
     * @return  string
187
     */
188 12
    public function getApiVersion(): string
189
    {
190 12
        return $this->apiVersion;
191
    }
192
193
    /**
194
     * Get the endpoint URL.
195
     *
196
     * @param   string  $endpoint
197
     *
198
     * @return  string
199
     */
200 11
    protected function getEndpointUrl(string $endpoint): string
201
    {
202 11
        return str_replace('%ver%', $this->getApiVersion(), static::BASE_URL).$endpoint;
203
    }
204
205
    /**
206
     * @param   string $method
207
     * @param   string $url
208
     * @param   array  $params
209
     * @param   array  $headers
210
     *
211
     * @return  ResponseInterface
212
     * @throws \GuzzleHttp\Exception\GuzzleException
213
     */
214 11
    protected function sendRequest(
215
        string $method,
216
        string $url,
217
        array $params = [],
0 ignored issues
show
Unused Code introduced by
The parameter $params is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

217
        /** @scrutinizer ignore-unused */ array $params = [],

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
        array $headers = []
219
    ): ResponseInterface {
220
221
        $defaultHeaders = [
222 11
            'User-Agent' => 'Coinpaprika API Client - PHP'
223
        ];
224
225 11
        if (Request::METHOD_GET === $method) {
226
227
        }
228
229 11
        return $this->httpClient->request($method, $url, [
230 11
            'headers' => array_merge($defaultHeaders, $headers)
231
        ]);
232
    }
233
234
    /**
235
     * @param   ResponseInterface   $response
236
     *
237
     * @throws  InvalidResponseException
238
     * @throws  RateLimitExceededException
239
     * @throws  ResponseErrorException
240
     */
241 11
    protected function validateResponse(ResponseInterface $response): void
242
    {
243 11
        $statusCode = $response->getStatusCode();
244
245
        // rate limit exceeded
246 11
        if ($statusCode === 429) {
247 1
            throw new RateLimitExceededException('Response code from API 429. Rate limit exceeded.');
248
        }
249
250
        // check for errors
251 10
        if ($statusCode >= 400 && $statusCode <= 500) {
252
253 3
            if (array_key_exists('error', $e = json_decode($response->getBody(), true))) {
254
255 2
                throw new ResponseErrorException(sprintf(
256 2
                    'Response code: %s, error: %s',
257 2
                    $statusCode,
258 2
                    $e['error']
259
                ));
260
            }
261
262 1
            throw new InvalidResponseException(sprintf(
263 1
                'Bad response from a server - status code: %s, but error field does not exists.',
264 1
                $statusCode
265
            ));
266
        }
267 7
    }
268
269
    /**
270
     * Unmarshal JSON
271
     *
272
     * @param   ResponseInterface $response
273
     * @param   string            $type
274
     *
275
     * @throws  ResponseErrorException
276
     * @throws  RateLimitExceededException
277
     * @throws  InvalidResponseException
278
     *
279
     * @see     https://api.coinpaprika.com/#section/Errors
280
     *
281
     * @return  mixed
282
     */
283 11
    protected function response(ResponseInterface $response, string $type)
284
    {
285 11
        $this->validateResponse($response);
286
287 7
        return $this->serializer->deserialize($response->getBody(), $type, 'json');
288
    }
289
}
290