<?php
namespace OpenObjects\Component\Http;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\ClientException;
use InvalidArgumentException;
/**
* RESTful class is responsible for interfacing with the Guzzle
* HTTP client to make requests to external sources.
*
* Class RESTfulService
* @package OpenObjects\Component\Http
*/
class RESTfulService
{
/**
* The API endpoint.
*
* @var string
*/
protected $endpoint = null;
/**
* The response body as a string.
*
* @var string
*/
protected $responseBody;
/**
* The Guzzle HTTP client.
*
* @var Client;
*/
protected $guzzleHttpClient;
/**
* @var
*/
protected $httpClientResponse = null;
/**
* The format the requests should return in.
*
* @var string json|xml
*/
protected $responseFormat = 'json';
/**
* @var bool
*/
protected $asyncRequest = false;
/**
* RESTfulService constructor.
*
* @param $endpoint
* @param Client $client
*/
public function __construct($endpoint, Client $client)
{
// Assign endpoint for the request.
$this->endpoint = $endpoint;
// Assign Guzzles client to class property.
$this->setClient($client);
}
/**
* Get guzzleHttpClient.
*
* @return Client
*/
public function getClient()
{
return $this->guzzleHttpClient;
}
/**
* Set guzzleHttpClient.
*
* @param Client $guzzleHttpClient
*/
public function setClient($guzzleHttpClient)
{
$this->guzzleHttpClient = $guzzleHttpClient;
}
/**
* Get httpClientResponse.
*
* @return Response
*/
public function getHttpClientResponse()
{
return $this->httpClientResponse;
}
/**
* Set httpClientResponse.
*
* @param Response $httpClientResponse
* @return $this
*/
public function setHttpClientResponse(Response $httpClientResponse)
{
$this->httpClientResponse = $httpClientResponse;
return $this;
}
/**
* Get responseBody.
*
* @return string
*/
public function getResponseBody()
{
if (!$this->getHttpClientResponse()) {
return null;
}
$body = (string)$this->getHttpClientResponse()->getBody();
$json = json_decode($body, true);
if (json_last_error() == JSON_ERROR_NONE) {
if (isset($json['error'])) {
return $json['error'];
}
return $json;
}
return $body;
}
/**
* Get responseFormat.
*
* @return Client
*/
public function getResponseFormat()
{
return $this->responseFormat;
}
/**
* Set responseFormat.
*
* @param string $responseFormat
*/
public function setResponseFormat($responseFormat)
{
$this->responseFormat = $responseFormat;
}
/**
* @param bool $isAsync
* @return $this
*/
public function setAsyncRequest($isAsync)
{
$this->asyncRequest = $isAsync;
return $this;
}
/**
* @return bool
*/
public function isAsyncRequest()
{
return $this->asyncRequest;
}
/**
* Make an HTTP call to the external resource.
*
* @param string $method The HTTP method
* @param array $args An array of parameters
*
* @return object
*/
public function __call($method, $args)
{
if (count($args) < 1) {
throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
}
$uri = $args[0];
$opts = isset($args[1]) ? $args[1] : [];
return $this->requestBroker($method, $uri, $opts);
}
/**
* @return string
*/
protected function getEndPoint()
{
return $this->endpoint;
}
/**
* @param $endpoint
* @return $this
*/
protected function setEndpoint($endpoint = null)
{
if ($endpoint !== null) {
$this->endpoint = $endpoint;
}
return $this;
}
/**
* Send the post request and return the array result of the the response data.
*
* @param string $action
* @param string $verb
* @param array $params
*
* @return object|boolean
*/
protected function requestBroker($action, $verb = null, array $params = [])
{
try {
if (false === $this->isAsyncRequest()) {
// Send the POST request using the client.
$response = $this->guzzleHttpClient->$action(
$this->getEndPoint() . $verb,
$params
);
} else {
// Send an asynchronous request.
$headers = isset($params['headers']) ? $params['headers'] : [];
$body = isset($params['body']) ? $params['body'] : [];
$request = new Request($action, $this->getEndPoint() . $verb,
$headers, $body);
$promise = $this->guzzleHttpClient->sendAsync($request)->then(function (
$response
) {
$this->setHttpClientResponse($response);
});
$promise->wait();
}
$this->setHttpClientResponse($response);
// Catch empty an empty response body.
if ('' == (string) $response->getBody() && $this->getResponseFormat() != 'file') {
return json_encode($response->getHeaders());
}
switch ($this->getResponseFormat()) {
case 'raw':
return (string) $response->getBody();
break;
case 'array':
return json_decode((string) $response->getBody(), true);
break;
case 'json':
return json_encode((string) $response->getBody());
break;
case 'xml':
return simplexml_load_string((string) $response->getBody());
break;
case 'file':
return $response;
break;
default:
return json_encode($response->getHeaders());
}
} catch (ClientException $e) {
if ($e->getResponse() !== null) {
$this->setHttpClientResponse($e->getResponse());
}
return false;
} catch (\Exception $e) {
if ($e->getResponse() !== null) {
$this->setHttpClientResponse($e->getResponse());
}
return false;
}
return $response;
}
}