AbstractApiClient::__call()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.0466

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 11
ccs 6
cts 7
cp 0.8571
rs 10
cc 4
nc 5
nop 2
crap 4.0466
1
<?php
2
3
namespace App\Services;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\ClientException;
7
use Illuminate\Contracts\Cache\Repository as Cache;
8
use Illuminate\Log\Logger;
9
use InvalidArgumentException;
10
use SimpleXMLElement;
11
12
/**
13
 * @method object get($uri, ...$args)
14
 * @method object post($uri, ...$data)
15
 * @method object put($uri, ...$data)
16
 * @method object patch($uri, ...$data)
17
 * @method object head($uri, ...$data)
18
 * @method object delete($uri)
19
 */
20
abstract class AbstractApiClient
21
{
22
    protected $responseFormat = 'json';
23
    protected $client;
24
    protected $cache;
25
    protected $logger;
26
27
    /**
28
     * The query parameter name for the key.
29
     * For example, Last.fm use api_key, like this:
30
     * https://ws.audioscrobbler.com/2.0?method=artist.getInfo&artist=Kamelot&api_key=API_KEY.
31
     *
32
     * @var string
33
     */
34
    protected $keyParam = 'key';
35
36 132
    public function __construct(Client $client, Cache $cache, Logger $logger)
37
    {
38 132
        $this->client = $client;
39 132
        $this->cache = $cache;
40 132
        $this->logger = $logger;
41 132
    }
42
43
    /**
44
     * Make a request to the API.
45
     *
46
     * @param string  $method    The HTTP method
47
     * @param string  $uri       The API URI (segment)
48
     * @param bool    $appendKey Whether to automatically append the API key into the URI.
49
     *                           While it's usually the case, some services (like Last.fm) requires
50
     *                           an "API signature" of the request. Appending an API key will break the request.
51
     * @param mixed[] $params    An array of parameters
52
     *
53
     * @return mixed|SimpleXMLElement|null
54
     */
55 10
    public function request(string $method, string $uri, bool $appendKey = true, array $params = [])
56
    {
57
        try {
58 10
            $body = (string) $this->getClient()
59 10
                ->$method($this->buildUrl($uri, $appendKey), ['form_params' => $params])
60 10
                ->getBody();
61
62 10
            if ($this->responseFormat === 'json') {
63 5
                return json_decode($body);
64
            }
65
66 5
            if ($this->responseFormat === 'xml') {
67 5
                return simplexml_load_string($body);
68
            }
69
70
            return $body;
71
        } catch (ClientException $e) {
72
            $this->logger->error($e);
73
        }
74
    }
75
76
    /**
77
     * Make an HTTP call to the external resource.
78
     *
79
     * @param string  $method The HTTP method
80
     * @param mixed[] $args   An array of parameters
81
     *
82
     * @throws InvalidArgumentException
83
     *
84
     * @return mixed|null|SimpleXMLElement
85
     */
86 10
    public function __call(string $method, array $args)
87
    {
88 10
        if (count($args) < 1) {
89
            throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
90
        }
91
92 10
        $uri = $args[0];
93 10
        $opts = isset($args[1]) ? $args[1] : [];
94 10
        $appendKey = isset($args[2]) ? $args[2] : true;
95
96 10
        return $this->request($method, $uri, $appendKey, $opts);
97
    }
98
99
    /**
100
     * Turn a URI segment into a full API URL.
101
     *
102
     * @param bool $appendKey Whether to automatically append the API key into the URL.
103
     */
104 11
    public function buildUrl(string $uri, bool $appendKey = true): string
105
    {
106 11
        if (!starts_with($uri, ['http://', 'https://'])) {
107 11
            if ($uri[0] !== '/') {
108 6
                $uri = "/$uri";
109
            }
110
111 11
            $uri = $this->getEndpoint().$uri;
112
        }
113
114 11
        if ($appendKey) {
115 10
            if (parse_url($uri, PHP_URL_QUERY)) {
116 6
                $uri .= "&{$this->keyParam}=".$this->getKey();
117
            } else {
118 5
                $uri .= "?{$this->keyParam}=".$this->getKey();
119
            }
120
        }
121
122 11
        return $uri;
123
    }
124
125 13
    public function getClient(): Client
126
    {
127 13
        return $this->client;
128
    }
129
130
    abstract public function getKey(): ?string;
131
132
    abstract public function getSecret(): ?string;
133
134
    abstract public function getEndpoint(): ?string;
135
}
136