src/Superdesk/ContentApiSdk/Api/Response.php
<?php
/**
* This file is part of the PHP SDK library for the Superdesk Content API.
*
* Copyright 2015 Sourcefabric z.u. and contributors.
*
* For the full copyright and license information, please see the
* AUTHORS and LICENSE files distributed with this source code.
*
* @copyright 2015 Sourcefabric z.รบ.
* @license http://www.superdesk.org/license
*/
namespace Superdesk\ContentApiSdk\Api;
use Superdesk\ContentApiSdk\ContentApiSdk;
use Superdesk\ContentApiSdk\Exception\ResponseException;
use Superdesk\ContentApiSdk\Exception\InvalidDataException;
use stdClass;
use SimpleXMLElement;
use Exception;
/**
* API Response object.
*/
class Response
{
const TYPE_ITEMS = 'items';
const TYPE_PACKAGES = 'packages';
const CONTENT_TYPE_JSON = 'application/json';
const CONTENT_TYPE_XML = 'application/xml';
/**
* Unprocessed body as returned by the api.
*
* @var string
*/
protected $rawBody;
/**
* Content type of the response, we should support xml and json.
*
* @var string
*/
protected $contentType;
/**
* Type of response.
*
* @var string
*/
protected $type;
/**
* Request URI.
*
* @var string
*/
protected $href;
/**
* List of response headers.
*
* @var array|null
*/
protected $headers;
/**
* Current page.
*
* @var int
*/
protected $page;
/**
* Next page.
*
* @var int
*/
protected $nextPage;
/**
* Previous page.
*
* @var int
*/
protected $prevPage;
/**
* Last page.
*
* @var int
*/
protected $lastPage;
/**
* Maximum of results on 1 page.
*
* @var int
*/
protected $maxResults;
/**
* Total amount of results for current parameters.
*
* @var int
*/
protected $total;
/**
* Array container resources or stdClass with properties.
*
* @var array|stdClass
*/
protected $resources;
/**
* Array of keys which are not part of the actual single data (item or
* package).
*
* @var array
*/
protected $metaKeys = array(
'_links'
);
/**
* Constructs Response.
*
* @param string $body Body of a response as string
* @param array|null $headers List of headers
*/
public function __construct($body, array $headers = null)
{
$this->rawBody = $body;
$this->headers = $headers;
$this->determineContentType();
$this->processRawBody();
}
/**
* Determine the content type of the response via header. If header is not
* set, then content will be analyzed. Throws exception on failure.
*
* @return string Content type of the response
*
* @throws ResponseException
*/
private function determineContentType()
{
if (isset($this->headers['Content-Type']) && in_array($this->headers['Content-Type'], $this->getSupportedContenTypes())) {
$this->contentType = $this->headers['Content-Type'];
return;
}
// Try to determine content type based on body
try {
new SimpleXMLElement($this->rawBody);
$this->contentType = self::CONTENT_TYPE_XML;
return;
} catch (Exception $e) {
// Not valid XML
}
$json = json_decode($this->rawBody);
if (!is_null($json) && json_last_error() === JSON_ERROR_NONE) {
$this->contentType = self::CONTENT_TYPE_JSON;
return;
}
throw new ResponseException('Could not determine response content-type.');
}
/**
* Return valid response content types.
*
* @return string[]
*/
public static function getSupportedContenTypes()
{
return array(
self::CONTENT_TYPE_JSON,
self::CONTENT_TYPE_XML,
);
}
/**
* Sets properties based on response body.
*
* @throws ResponseException
*/
private function processRawBody()
{
switch ($this->contentType) {
case self::CONTENT_TYPE_JSON:
try {
$responseJson = ContentApiSdk::getValidJsonObj($this->rawBody);
} catch (InvalidDataException $e) {
throw new ResponseException($e->getMessage(), $e->getCode(), $e);
}
$this->type = $responseJson->_links->self->title;
$this->href = $responseJson->_links->self->href;
if (property_exists($responseJson, '_meta')) {
$this->page = $responseJson->_meta->page;
$this->maxResults = $responseJson->_meta->max_results;
$this->total = $responseJson->_meta->total;
$this->nextPage = (property_exists($responseJson->_links, 'next')) ? $this->page + 1 : $this->page;
$this->prevPage = (property_exists($responseJson->_links, 'prev')) ? $this->page - 1 : $this->page;
$this->lastPage = (property_exists($responseJson->_links, 'last')) ? (int) ceil($this->total / $this->maxResults) : $this->page;
$this->resources = $responseJson->_items;
} else {
$resourceObj = new stdClass();
foreach ($responseJson as $key => $value) {
if (in_array($key, $this->metaKeys)) {
continue;
}
$resourceObj->$key = $value;
}
$this->resources = $resourceObj;
}
break;
case self::CONTENT_TYPE_XML:
break;
}
return;
}
/**
* Returns content type.
*
* @return string
*/
public function getContentType()
{
return $this->contentType;
}
/**
* Returns response type. Package or item.
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Returns the response href. In most cases this is the request uri.
*
* @return string
*/
public function getHref()
{
return $this->href;
}
/**
* Returns current page number.
*
* @return int
*/
public function getCurrentPage()
{
return $this->page;
}
/**
* Returns next page number.
*
* @return int
*/
public function getNextPage()
{
return $this->nextPage;
}
/**
* Returns previous page number.
*
* @return int
*/
public function getPreviousPage()
{
return $this->prevPage;
}
/**
* Returns last page number.
*
* @return int
*/
public function getLastPage()
{
return $this->lastPage;
}
/**
* Returns first page number.
*
* @return int
*/
public function getFirstPage()
{
return 1;
}
/**
* Returns whether current page is last page.
*
* @return bool
*/
public function isLastPage()
{
return $this->getCurrentPage() === $this->getLastPage();
}
/**
* Returns whether current page is first page.
*
* @return bool
*/
public function isFirstPage()
{
return $this->getCurrentPage() === $this->getFirstPage();
}
/**
* Returns maximum results displayed per page.
*
* @return int
*/
public function getMaxResults()
{
return $this->maxResults;
}
/**
* Returns total amount of results.
*
* @return int
*/
public function getTotalResults()
{
return $this->total;
}
/**
* Returns the response resources, items or packages.
*
* @return array
*/
public function getResources()
{
return $this->resources;
}
}