primo commit
This commit is contained in:
229
libraries/f0f/hal/document.php
Normal file
229
libraries/f0f/hal/document.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage hal
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* Implementation of the Hypertext Application Language document in PHP. It can
|
||||
* be used to provide hypermedia in a web service context.
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.1
|
||||
*/
|
||||
class F0FHalDocument
|
||||
{
|
||||
/**
|
||||
* The collection of links of this document
|
||||
*
|
||||
* @var F0FHalLinks
|
||||
*/
|
||||
private $_links = null;
|
||||
|
||||
/**
|
||||
* The data (resource state or collection of resource state objects) of the
|
||||
* document.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_data = null;
|
||||
|
||||
/**
|
||||
* Embedded documents. This is an array of F0FHalDocument instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_embedded = array();
|
||||
|
||||
/**
|
||||
* When $_data is an array we'll output the list of data under this key
|
||||
* (JSON) or tag (XML)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_dataKey = '_list';
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param mixed $data The data of the document (usually, the resource state)
|
||||
*/
|
||||
public function __construct($data = null)
|
||||
{
|
||||
$this->_data = $data;
|
||||
$this->_links = new F0FHalLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a link to the document
|
||||
*
|
||||
* @param string $rel The relation of the link to the document.
|
||||
* See RFC 5988 http://tools.ietf.org/html/rfc5988#section-6.2.2 A document MUST always have
|
||||
* a "self" link.
|
||||
* @param F0FHalLink $link The actual link object
|
||||
* @param boolean $overwrite When false and a link of $rel relation exists, an array of links is created. Otherwise the
|
||||
* existing link is overwriten with the new one
|
||||
*
|
||||
* @see F0FHalLinks::addLink
|
||||
*
|
||||
* @return boolean True if the link was added to the collection
|
||||
*/
|
||||
public function addLink($rel, F0FHalLink $link, $overwrite = true)
|
||||
{
|
||||
return $this->_links->addLink($rel, $link, $overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add links to the document
|
||||
*
|
||||
* @param string $rel The relation of the link to the document. See RFC 5988
|
||||
* @param array $links An array of F0FHalLink objects
|
||||
* @param boolean $overwrite When false and a link of $rel relation exists, an array of
|
||||
* links is created. Otherwise the existing link is overwriten
|
||||
* with the new one
|
||||
*
|
||||
* @see F0FHalLinks::addLinks
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function addLinks($rel, array $links, $overwrite = true)
|
||||
{
|
||||
return $this->_links->addLinks($rel, $links, $overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to the document
|
||||
*
|
||||
* @param stdClass $data The data to add
|
||||
* @param boolean $overwrite Should I overwrite existing data?
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addData($data, $overwrite = true)
|
||||
{
|
||||
if (is_array($data))
|
||||
{
|
||||
$data = (object) $data;
|
||||
}
|
||||
|
||||
if ($overwrite)
|
||||
{
|
||||
$this->_data = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_array($this->_data))
|
||||
{
|
||||
$this->_data = array($this->_data);
|
||||
}
|
||||
|
||||
$this->_data[] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an embedded document
|
||||
*
|
||||
* @param string $rel The relation of the embedded document to its container document
|
||||
* @param F0FHalDocument $document The document to add
|
||||
* @param boolean $overwrite Should I overwrite existing data with the same relation?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function addEmbedded($rel, F0FHalDocument $document, $overwrite = true)
|
||||
{
|
||||
if (!array_key_exists($rel, $this->_embedded) || !$overwrite)
|
||||
{
|
||||
$this->_embedded[$rel] = $document;
|
||||
}
|
||||
elseif (array_key_exists($rel, $this->_embedded) && !$overwrite)
|
||||
{
|
||||
if (!is_array($this->_embedded[$rel]))
|
||||
{
|
||||
$this->_embedded[$rel] = array($this->_embedded[$rel]);
|
||||
}
|
||||
|
||||
$this->_embedded[$rel][] = $document;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection of links of this document
|
||||
*
|
||||
* @param string $rel The relation of the links to fetch. Skip to get all links.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLinks($rel = null)
|
||||
{
|
||||
return $this->_links->getLinks($rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection of embedded documents
|
||||
*
|
||||
* @param string $rel Optional; the relation to return the embedded documents for
|
||||
*
|
||||
* @return array|F0FHalDocument
|
||||
*/
|
||||
public function getEmbedded($rel = null)
|
||||
{
|
||||
if (empty($rel))
|
||||
{
|
||||
return $this->_embedded;
|
||||
}
|
||||
elseif (isset($this->_embedded[$rel]))
|
||||
{
|
||||
return $this->_embedded[$rel];
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data attached to this document
|
||||
*
|
||||
* @return array|stdClass
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate and call a suitable renderer class to render this document
|
||||
* into the specified format.
|
||||
*
|
||||
* @param string $format The format to render the document into, e.g. 'json'
|
||||
*
|
||||
* @return string The rendered document
|
||||
*
|
||||
* @throws RuntimeException If the format is unknown, i.e. there is no suitable renderer
|
||||
*/
|
||||
public function render($format = 'json')
|
||||
{
|
||||
$class_name = 'F0FHalRender' . ucfirst($format);
|
||||
|
||||
if (!class_exists($class_name, true))
|
||||
{
|
||||
throw new RuntimeException("Unsupported HAL Document format '$format'. Render aborted.");
|
||||
}
|
||||
|
||||
$renderer = new $class_name($this);
|
||||
|
||||
return $renderer->render(
|
||||
array(
|
||||
'data_key' => $this->_dataKey
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
137
libraries/f0f/hal/link.php
Normal file
137
libraries/f0f/hal/link.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage hal
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* Implementation of the Hypertext Application Language link in PHP.
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.1
|
||||
*/
|
||||
class F0FHalLink
|
||||
{
|
||||
/**
|
||||
* For indicating the target URI. Corresponds with the ’Target IRI’ as
|
||||
* defined in Web Linking (RFC 5988). This attribute MAY contain a URI
|
||||
* Template (RFC6570) and in which case, SHOULD be complemented by an
|
||||
* additional templated attribtue on the link with a boolean value true.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_href = '';
|
||||
|
||||
/**
|
||||
* This attribute SHOULD be present with a boolean value of true when the
|
||||
* href of the link contains a URI Template (RFC6570).
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_templated = false;
|
||||
|
||||
/**
|
||||
* For distinguishing between Resource and Link elements that share the
|
||||
* same relation
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_name = null;
|
||||
|
||||
/**
|
||||
* For indicating what the language of the result of dereferencing the link should be.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_hreflang = null;
|
||||
|
||||
/**
|
||||
* For labeling the destination of a link with a human-readable identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_title = null;
|
||||
|
||||
/**
|
||||
* Public constructor of a F0FHalLink object
|
||||
*
|
||||
* @param string $href See $this->_href
|
||||
* @param boolean $templated See $this->_templated
|
||||
* @param string $name See $this->_name
|
||||
* @param string $hreflang See $this->_hreflang
|
||||
* @param string $title See $this->_title
|
||||
*
|
||||
* @throws RuntimeException If $href is empty
|
||||
*/
|
||||
public function __construct($href, $templated = false, $name = null, $hreflang = null, $title = null)
|
||||
{
|
||||
if (empty($href))
|
||||
{
|
||||
throw new RuntimeException('A HAL link must always have a non-empty href');
|
||||
}
|
||||
|
||||
$this->_href = $href;
|
||||
$this->_templated = $templated;
|
||||
$this->_name = $name;
|
||||
$this->_hreflang = $hreflang;
|
||||
$this->_title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a valid link? Checks the existence of required fields, not their
|
||||
* values.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
return !empty($this->_href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for the protected properties
|
||||
*
|
||||
* @param string $name The name of the property to retrieve, sans the underscore
|
||||
*
|
||||
* @return mixed Null will always be returned if the property doesn't exist
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$property = '_' . $name;
|
||||
|
||||
if (property_exists($this, $property))
|
||||
{
|
||||
return $this->$property;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter for the protected properties
|
||||
*
|
||||
* @param string $name The name of the property to set, sans the underscore
|
||||
* @param mixed $value The value of the property to set
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (($name == 'href') && empty($value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$property = '_' . $name;
|
||||
|
||||
if (property_exists($this, $property))
|
||||
{
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
124
libraries/f0f/hal/links.php
Normal file
124
libraries/f0f/hal/links.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage hal
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* Implementation of the Hypertext Application Language links in PHP. This is
|
||||
* actually a collection of links.
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.1
|
||||
*/
|
||||
class F0FHalLinks
|
||||
{
|
||||
/**
|
||||
* The collection of links, sorted by relation
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_links = array();
|
||||
|
||||
/**
|
||||
* Add a single link to the links collection
|
||||
*
|
||||
* @param string $rel The relation of the link to the document. See RFC 5988
|
||||
* http://tools.ietf.org/html/rfc5988#section-6.2.2 A document
|
||||
* MUST always have a "self" link.
|
||||
* @param F0FHalLink $link The actual link object
|
||||
* @param boolean $overwrite When false and a link of $rel relation exists, an array of
|
||||
* links is created. Otherwise the existing link is overwriten
|
||||
* with the new one
|
||||
*
|
||||
* @return boolean True if the link was added to the collection
|
||||
*/
|
||||
public function addLink($rel, F0FHalLink $link, $overwrite = true)
|
||||
{
|
||||
if (!$link->check())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_key_exists($rel, $this->_links) || $overwrite)
|
||||
{
|
||||
$this->_links[$rel] = $link;
|
||||
}
|
||||
elseif (array_key_exists($rel, $this->_links) && !$overwrite)
|
||||
{
|
||||
if (!is_array($this->_links[$rel]))
|
||||
{
|
||||
$this->_links[$rel] = array($this->_links[$rel]);
|
||||
}
|
||||
|
||||
$this->_links[$rel][] = $link;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple links to the links collection
|
||||
*
|
||||
* @param string $rel The relation of the links to the document. See RFC 5988.
|
||||
* @param array $links An array of F0FHalLink objects
|
||||
* @param boolean $overwrite When false and a link of $rel relation exists, an array
|
||||
* of links is created. Otherwise the existing link is
|
||||
* overwriten with the new one
|
||||
*
|
||||
* @return boolean True if the link was added to the collection
|
||||
*/
|
||||
public function addLinks($rel, array $links, $overwrite = true)
|
||||
{
|
||||
if (empty($links))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$localOverwrite = $overwrite;
|
||||
|
||||
foreach ($links as $link)
|
||||
{
|
||||
if ($link instanceof F0FHalLink)
|
||||
{
|
||||
$this->addLink($rel, $link, $localOverwrite);
|
||||
}
|
||||
|
||||
// After the first time we call this with overwrite on we have to
|
||||
// turn it off so that the other links are added to the set instead
|
||||
// of overwriting the first item that's already added.
|
||||
if ($localOverwrite)
|
||||
{
|
||||
$localOverwrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection of links
|
||||
*
|
||||
* @param string $rel Optional; the relation to return the links for
|
||||
*
|
||||
* @return array|F0FHalLink
|
||||
*/
|
||||
public function getLinks($rel = null)
|
||||
{
|
||||
if (empty($rel))
|
||||
{
|
||||
return $this->_links;
|
||||
}
|
||||
elseif (isset($this->_links[$rel]))
|
||||
{
|
||||
return $this->_links[$rel];
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
libraries/f0f/hal/render/interface.php
Normal file
26
libraries/f0f/hal/render/interface.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage hal
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* Interface for HAL document renderers
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.1
|
||||
*/
|
||||
interface F0FHalRenderInterface
|
||||
{
|
||||
/**
|
||||
* Render a HAL document into a representation suitable for consumption.
|
||||
*
|
||||
* @param array $options Renderer-specific options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render($options = array());
|
||||
}
|
||||
177
libraries/f0f/hal/render/json.php
Normal file
177
libraries/f0f/hal/render/json.php
Normal file
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage hal
|
||||
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* Implements the HAL over JSON renderer
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.1
|
||||
*/
|
||||
class F0FHalRenderJson implements F0FHalRenderInterface
|
||||
{
|
||||
/**
|
||||
* When data is an array we'll output the list of data under this key
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_dataKey = '_list';
|
||||
|
||||
/**
|
||||
* The document to render
|
||||
*
|
||||
* @var F0FHalDocument
|
||||
*/
|
||||
protected $_document;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param F0FHalDocument &$document The document to render
|
||||
*/
|
||||
public function __construct(&$document)
|
||||
{
|
||||
$this->_document = $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a HAL document in JSON format
|
||||
*
|
||||
* @param array $options Rendering options. You can currently only set json_options (json_encode options)
|
||||
*
|
||||
* @return string The JSON representation of the HAL document
|
||||
*/
|
||||
public function render($options = array())
|
||||
{
|
||||
if (isset($options['data_key']))
|
||||
{
|
||||
$this->_dataKey = $options['data_key'];
|
||||
}
|
||||
|
||||
if (isset($options['json_options']))
|
||||
{
|
||||
$jsonOptions = $options['json_options'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$jsonOptions = 0;
|
||||
}
|
||||
|
||||
$serialiseThis = new stdClass;
|
||||
|
||||
// Add links
|
||||
$collection = $this->_document->getLinks();
|
||||
$serialiseThis->_links = new stdClass;
|
||||
|
||||
foreach ($collection as $rel => $links)
|
||||
{
|
||||
if (!is_array($links))
|
||||
{
|
||||
$serialiseThis->_links->$rel = $this->_getLink($links);
|
||||
}
|
||||
else
|
||||
{
|
||||
$serialiseThis->_links->$rel = array();
|
||||
|
||||
foreach ($links as $link)
|
||||
{
|
||||
array_push($serialiseThis->_links->$rel, $this->_getLink($link));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add embedded documents
|
||||
|
||||
$collection = $this->_document->getEmbedded();
|
||||
|
||||
if (!empty($collection))
|
||||
{
|
||||
$serialiseThis->_embedded->$rel = new stdClass;
|
||||
|
||||
foreach ($collection as $rel => $embeddeddocs)
|
||||
{
|
||||
if (!is_array($embeddeddocs))
|
||||
{
|
||||
$embeddeddocs = array($embeddeddocs);
|
||||
}
|
||||
|
||||
foreach ($embeddeddocs as $embedded)
|
||||
{
|
||||
$renderer = new F0FHalRenderJson($embedded);
|
||||
array_push($serialiseThis->_embedded->$rel, $renderer->render($options));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add data
|
||||
$data = $this->_document->getData();
|
||||
|
||||
if (is_object($data))
|
||||
{
|
||||
if ($data instanceof F0FTable)
|
||||
{
|
||||
$data = $data->getData();
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
if (!empty($data))
|
||||
{
|
||||
foreach ($data as $k => $v)
|
||||
{
|
||||
$serialiseThis->$k = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (is_array($data))
|
||||
{
|
||||
$serialiseThis->{$this->_dataKey} = $data;
|
||||
}
|
||||
|
||||
return json_encode($serialiseThis, $jsonOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a F0FHalLink object into a stdClass object which will be used
|
||||
* for JSON serialisation
|
||||
*
|
||||
* @param F0FHalLink $link The link you want converted
|
||||
*
|
||||
* @return stdClass The converted link object
|
||||
*/
|
||||
protected function _getLink(F0FHalLink $link)
|
||||
{
|
||||
$ret = array(
|
||||
'href' => $link->href
|
||||
);
|
||||
|
||||
if ($link->templated)
|
||||
{
|
||||
$ret['templated'] = 'true';
|
||||
}
|
||||
|
||||
if (!empty($link->name))
|
||||
{
|
||||
$ret['name'] = $link->name;
|
||||
}
|
||||
|
||||
if (!empty($link->hreflang))
|
||||
{
|
||||
$ret['hreflang'] = $link->hreflang;
|
||||
}
|
||||
|
||||
if (!empty($link->title))
|
||||
{
|
||||
$ret['title'] = $link->title;
|
||||
}
|
||||
|
||||
return (object) $ret;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user