2015-12-19 16:36:44 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Services;
|
|
|
|
|
|
|
|
use GuzzleHttp\Client;
|
|
|
|
use GuzzleHttp\Exception\ClientException;
|
2018-08-31 13:47:15 +00:00
|
|
|
use Illuminate\Contracts\Cache\Repository as Cache;
|
2018-08-31 13:47:45 +00:00
|
|
|
use Illuminate\Log\Logger;
|
2015-12-19 16:36:44 +00:00
|
|
|
use InvalidArgumentException;
|
2018-08-24 15:27:19 +00:00
|
|
|
use SimpleXMLElement;
|
2015-12-19 16:36:44 +00:00
|
|
|
|
|
|
|
/**
|
2018-08-19 11:08:16 +00:00
|
|
|
* @method object get($uri, ...$args)
|
2017-06-03 23:21:50 +00:00
|
|
|
* @method object post($uri, ...$data)
|
|
|
|
* @method object put($uri, ...$data)
|
|
|
|
* @method object patch($uri, ...$data)
|
|
|
|
* @method object head($uri, ...$data)
|
2015-12-19 16:36:44 +00:00
|
|
|
* @method object delete($uri)
|
|
|
|
*/
|
2019-04-07 21:09:25 +00:00
|
|
|
abstract class AbstractApiClient
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
|
|
|
protected $responseFormat = 'json';
|
|
|
|
protected $client;
|
2018-08-31 13:47:15 +00:00
|
|
|
protected $cache;
|
|
|
|
protected $logger;
|
2015-12-19 16:36:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The query parameter name for the key.
|
|
|
|
* For example, Last.fm use api_key, like this:
|
|
|
|
* https://ws.audioscrobbler.com/2.0?method=artist.getInfo&artist=Kamelot&api_key=API_KEY.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $keyParam = 'key';
|
|
|
|
|
2018-08-31 13:47:15 +00:00
|
|
|
public function __construct(Client $client, Cache $cache, Logger $logger)
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
2018-08-19 11:08:16 +00:00
|
|
|
$this->client = $client;
|
2018-08-31 13:47:15 +00:00
|
|
|
$this->cache = $cache;
|
|
|
|
$this->logger = $logger;
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make a request to the API.
|
|
|
|
*
|
2018-08-24 15:27:19 +00:00
|
|
|
* @param string $method The HTTP method
|
|
|
|
* @param string $uri The API URI (segment)
|
|
|
|
* @param bool $appendKey Whether to automatically append the API key into the URI.
|
2018-08-29 07:07:44 +00:00
|
|
|
* While it's usually the case, some services (like Last.fm) requires
|
|
|
|
* an "API signature" of the request. Appending an API key will break the request.
|
2020-12-22 20:11:22 +00:00
|
|
|
* @param array<mixed> $params An array of parameters
|
2015-12-19 16:36:44 +00:00
|
|
|
*
|
2018-08-24 15:27:19 +00:00
|
|
|
* @return mixed|SimpleXMLElement|null
|
2015-12-19 16:36:44 +00:00
|
|
|
*/
|
2018-08-24 15:27:19 +00:00
|
|
|
public function request(string $method, string $uri, bool $appendKey = true, array $params = [])
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
|
|
|
try {
|
2018-08-19 11:13:29 +00:00
|
|
|
$body = (string) $this->getClient()
|
2018-08-24 15:27:19 +00:00
|
|
|
->$method($this->buildUrl($uri, $appendKey), ['form_params' => $params])
|
2015-12-19 16:36:44 +00:00
|
|
|
->getBody();
|
|
|
|
|
|
|
|
if ($this->responseFormat === 'json') {
|
|
|
|
return json_decode($body);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->responseFormat === 'xml') {
|
|
|
|
return simplexml_load_string($body);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $body;
|
|
|
|
} catch (ClientException $e) {
|
2018-08-31 13:47:15 +00:00
|
|
|
$this->logger->error($e);
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make an HTTP call to the external resource.
|
|
|
|
*
|
2018-08-24 15:27:19 +00:00
|
|
|
* @param string $method The HTTP method
|
2020-12-22 20:11:22 +00:00
|
|
|
* @param array<mixed> $args An array of parameters
|
2015-12-19 16:36:44 +00:00
|
|
|
*
|
2018-08-19 11:08:16 +00:00
|
|
|
* @throws InvalidArgumentException
|
2016-08-03 10:42:39 +00:00
|
|
|
*
|
2020-09-06 21:20:42 +00:00
|
|
|
* @return mixed|SimpleXMLElement|null
|
2015-12-19 16:36:44 +00:00
|
|
|
*/
|
2018-08-24 15:27:19 +00:00
|
|
|
public function __call(string $method, array $args)
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
|
|
|
if (count($args) < 1) {
|
|
|
|
throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
|
|
|
|
}
|
|
|
|
|
|
|
|
$uri = $args[0];
|
2020-12-22 20:11:22 +00:00
|
|
|
$opts = $args[1] ?? [];
|
|
|
|
$appendKey = $args[2] ?? true;
|
2015-12-19 16:36:44 +00:00
|
|
|
|
2015-12-20 12:17:35 +00:00
|
|
|
return $this->request($method, $uri, $appendKey, $opts);
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Turn a URI segment into a full API URL.
|
|
|
|
*
|
2020-09-06 21:20:42 +00:00
|
|
|
* @param bool $appendKey whether to automatically append the API key into the URL
|
2015-12-19 16:36:44 +00:00
|
|
|
*/
|
2018-08-24 15:27:19 +00:00
|
|
|
public function buildUrl(string $uri, bool $appendKey = true): string
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
|
|
|
if (!starts_with($uri, ['http://', 'https://'])) {
|
2016-08-16 15:12:11 +00:00
|
|
|
if ($uri[0] !== '/') {
|
2015-12-19 16:36:44 +00:00
|
|
|
$uri = "/$uri";
|
|
|
|
}
|
|
|
|
|
2020-12-22 20:11:22 +00:00
|
|
|
$uri = $this->getEndpoint() . $uri;
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|
|
|
|
|
2015-12-20 12:17:35 +00:00
|
|
|
if ($appendKey) {
|
|
|
|
if (parse_url($uri, PHP_URL_QUERY)) {
|
2020-12-22 20:11:22 +00:00
|
|
|
$uri .= "&{$this->keyParam}=" . $this->getKey();
|
2015-12-20 12:17:35 +00:00
|
|
|
} else {
|
2020-12-22 20:11:22 +00:00
|
|
|
$uri .= "?{$this->keyParam}=" . $this->getKey();
|
2015-12-20 12:17:35 +00:00
|
|
|
}
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $uri;
|
|
|
|
}
|
|
|
|
|
2018-08-24 15:27:19 +00:00
|
|
|
public function getClient(): Client
|
2015-12-19 16:36:44 +00:00
|
|
|
{
|
|
|
|
return $this->client;
|
|
|
|
}
|
|
|
|
|
2018-08-24 15:27:19 +00:00
|
|
|
abstract public function getKey(): ?string;
|
2015-12-19 16:36:44 +00:00
|
|
|
|
2018-08-24 15:27:19 +00:00
|
|
|
abstract public function getSecret(): ?string;
|
2015-12-19 16:36:44 +00:00
|
|
|
|
2018-08-29 10:36:05 +00:00
|
|
|
abstract public function getEndpoint(): ?string;
|
2015-12-19 16:36:44 +00:00
|
|
|
}
|