Client::buildUrl()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Kosv\RandomUser\Client;
6
7
use Kosv\RandomUser\Exceptions\TransportRequestException;
8
use Kosv\RandomUser\Exceptions\UnexpectedResponseException;
9
use Kosv\RandomUser\Interfaces\QueryBuilderInterface;
10
use Kosv\RandomUser\Interfaces\TransportInterface;
11
use Kosv\RandomUser\Transport\CurlTransport;
12
13
final class Client
14
{
15
    private const API_HOST = 'randomuser.me';
16
    private const API_PATH = 'api/1.3';
17
    private const API_SCHEME = 'https';
18
19
    private TransportInterface $transport;
20
21
    public function __construct(?TransportInterface $transport = null)
22
    {
23
        $this->transport = $transport ?? new CurlTransport();
24
    }
25
26
    /**
27
     * @throws UnexpectedResponseException
28
     * @throws TransportRequestException
29
     */
30
    public function request(QueryBuilderInterface $qb): Response
31
    {
32
        $response = $this->transport->get($this->buildUrl($qb));
33
        if ($response->getStatusCode() !== 200) {
34
            throw new UnexpectedResponseException('The http-server returned an unexpected http-code.');
35
        }
36
37
        try {
38
            $json = $this->decodeResponse($response->getBody());
39
        } catch (\JsonException $e) {
40
            throw new UnexpectedResponseException('The response came in an unsupported format, must be JSON.');
41
        }
42
43
        if (isset($json['error'])) {
44
            throw new UnexpectedResponseException(sprintf('Service returned error. Error text: "%s".', $json['error']));
45
        }
46
47
        if (!isset($json['info'], $json['results'])) {
48
            throw new UnexpectedResponseException('The response does not contain required data.');
49
        }
50
51
        return new Response($json['info'], $json['results']);
52
    }
53
54
    private function buildUrl(QueryBuilderInterface $qb): string
55
    {
56
        return $qb
57
            ->build()
58
            ->setScheme(self::API_SCHEME)
59
            ->setHost(self::API_HOST)
60
            ->setPath(self::API_PATH)
61
            ->setParam('format', ['json'])
62
            ->build();
63
    }
64
65
    private function decodeResponse(string $response): array
66
    {
67
        return json_decode($response, true, 512, \JSON_THROW_ON_ERROR);
68
    }
69
}
70