primo commit
This commit is contained in:
360
libraries/f0f/view/json.php
Normal file
360
libraries/f0f/view/json.php
Normal file
@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FrameworkOnFramework
|
||||
* @subpackage view
|
||||
* @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
|
||||
*/
|
||||
// Protect from unauthorized access
|
||||
defined('F0F_INCLUDED') or die;
|
||||
|
||||
/**
|
||||
* FrameworkOnFramework JSON View class. Renders the data as a JSON object or
|
||||
* array. It can optionally output HAL links as well.
|
||||
*
|
||||
* @package FrameworkOnFramework
|
||||
* @since 2.0
|
||||
*/
|
||||
class F0FViewJson extends F0FViewHtml
|
||||
{
|
||||
/**
|
||||
* When set to true we'll add hypermedia to the output, implementing the
|
||||
* HAL specification (http://stateless.co/hal_specification.html)
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $useHypermedia = false;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param array $config The component's configuration array
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
if (isset($config['use_hypermedia']))
|
||||
{
|
||||
$this->useHypermedia = (bool) $config['use_hypermedia'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The event which runs when we are displaying the record list JSON view
|
||||
*
|
||||
* @param string $tpl The view sub-template to use
|
||||
*
|
||||
* @return boolean True to allow display of the view
|
||||
*/
|
||||
protected function onDisplay($tpl = null)
|
||||
{
|
||||
// Load the model
|
||||
$model = $this->getModel();
|
||||
|
||||
$items = $model->getItemList();
|
||||
$this->items = $items;
|
||||
|
||||
$document = F0FPlatform::getInstance()->getDocument();
|
||||
|
||||
if ($document instanceof JDocument)
|
||||
{
|
||||
if ($this->useHypermedia)
|
||||
{
|
||||
$document->setMimeEncoding('application/hal+json');
|
||||
}
|
||||
else
|
||||
{
|
||||
$document->setMimeEncoding('application/json');
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($tpl))
|
||||
{
|
||||
$tpl = 'json';
|
||||
}
|
||||
|
||||
F0FPlatform::getInstance()->setErrorHandling(E_ALL, 'ignore');
|
||||
|
||||
$hasFailed = false;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $this->loadTemplate($tpl, true);
|
||||
|
||||
if ($result instanceof Exception)
|
||||
{
|
||||
$hasFailed = true;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$hasFailed = true;
|
||||
}
|
||||
|
||||
if ($hasFailed)
|
||||
{
|
||||
// Default JSON behaviour in case the template isn't there!
|
||||
if ($this->useHypermedia)
|
||||
{
|
||||
$haldocument = $this->_createDocumentWithHypermedia($items, $model);
|
||||
$json = $haldocument->render('json');
|
||||
}
|
||||
else
|
||||
{
|
||||
$json = json_encode($items);
|
||||
}
|
||||
|
||||
// JSONP support
|
||||
$callback = $this->input->get('callback', null, 'raw');
|
||||
|
||||
if (!empty($callback))
|
||||
{
|
||||
echo $callback . '(' . $json . ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$defaultName = $this->input->getCmd('view', 'joomla');
|
||||
$filename = $this->input->getCmd('basename', $defaultName);
|
||||
|
||||
$document->setName($filename);
|
||||
echo $json;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $result;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The event which runs when we are displaying a single item JSON view
|
||||
*
|
||||
* @param string $tpl The view sub-template to use
|
||||
*
|
||||
* @return boolean True to allow display of the view
|
||||
*/
|
||||
protected function onRead($tpl = null)
|
||||
{
|
||||
$model = $this->getModel();
|
||||
|
||||
$item = $model->getItem();
|
||||
$this->item = $item;
|
||||
|
||||
$document = F0FPlatform::getInstance()->getDocument();
|
||||
|
||||
if ($document instanceof JDocument)
|
||||
{
|
||||
if ($this->useHypermedia)
|
||||
{
|
||||
$document->setMimeEncoding('application/hal+json');
|
||||
}
|
||||
else
|
||||
{
|
||||
$document->setMimeEncoding('application/json');
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($tpl))
|
||||
{
|
||||
$tpl = 'json';
|
||||
}
|
||||
|
||||
F0FPlatform::getInstance()->setErrorHandling(E_ALL, 'ignore');
|
||||
|
||||
$hasFailed = false;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $this->loadTemplate($tpl, true);
|
||||
|
||||
if ($result instanceof Exception)
|
||||
{
|
||||
$hasFailed = true;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$hasFailed = true;
|
||||
}
|
||||
|
||||
if ($hasFailed)
|
||||
{
|
||||
// Default JSON behaviour in case the template isn't there!
|
||||
|
||||
if ($this->useHypermedia)
|
||||
{
|
||||
$haldocument = $this->_createDocumentWithHypermedia($item, $model);
|
||||
$json = $haldocument->render('json');
|
||||
}
|
||||
else
|
||||
{
|
||||
$json = json_encode($item);
|
||||
}
|
||||
|
||||
// JSONP support
|
||||
$callback = $this->input->get('callback', null);
|
||||
|
||||
if (!empty($callback))
|
||||
{
|
||||
echo $callback . '(' . $json . ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
$defaultName = $this->input->getCmd('view', 'joomla');
|
||||
$filename = $this->input->getCmd('basename', $defaultName);
|
||||
$document->setName($filename);
|
||||
echo $json;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $result;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a F0FHalDocument using the provided data
|
||||
*
|
||||
* @param array $data The data to put in the document
|
||||
* @param F0FModel $model The model of this view
|
||||
*
|
||||
* @return F0FHalDocument A HAL-enabled document
|
||||
*/
|
||||
protected function _createDocumentWithHypermedia($data, $model = null)
|
||||
{
|
||||
// Create a new HAL document
|
||||
|
||||
if (is_array($data))
|
||||
{
|
||||
$count = count($data);
|
||||
}
|
||||
else
|
||||
{
|
||||
$count = null;
|
||||
}
|
||||
|
||||
if ($count == 1)
|
||||
{
|
||||
reset($data);
|
||||
$document = new F0FHalDocument(end($data));
|
||||
}
|
||||
else
|
||||
{
|
||||
$document = new F0FHalDocument($data);
|
||||
}
|
||||
|
||||
// Create a self link
|
||||
$uri = (string) (JUri::getInstance());
|
||||
$uri = $this->_removeURIBase($uri);
|
||||
$uri = JRoute::_($uri);
|
||||
$document->addLink('self', new F0FHalLink($uri));
|
||||
|
||||
// Create relative links in a record list context
|
||||
|
||||
if (is_array($data) && ($model instanceof F0FModel))
|
||||
{
|
||||
$pagination = $model->getPagination();
|
||||
|
||||
if ($pagination->get('pages.total') > 1)
|
||||
{
|
||||
// Try to guess URL parameters and create a prototype URL
|
||||
// NOTE: You are better off specialising this method
|
||||
$protoUri = $this->_getPrototypeURIForPagination();
|
||||
|
||||
// The "first" link
|
||||
$uri = clone $protoUri;
|
||||
$uri->setVar('limitstart', 0);
|
||||
$uri = JRoute::_((string) $uri);
|
||||
|
||||
$document->addLink('first', new F0FHalLink($uri));
|
||||
|
||||
// Do we need a "prev" link?
|
||||
|
||||
if ($pagination->get('pages.current') > 1)
|
||||
{
|
||||
$prevPage = $pagination->get('pages.current') - 1;
|
||||
$limitstart = ($prevPage - 1) * $pagination->limit;
|
||||
$uri = clone $protoUri;
|
||||
$uri->setVar('limitstart', $limitstart);
|
||||
$uri = JRoute::_((string) $uri);
|
||||
|
||||
$document->addLink('prev', new F0FHalLink($uri));
|
||||
}
|
||||
|
||||
// Do we need a "next" link?
|
||||
|
||||
if ($pagination->get('pages.current') < $pagination->get('pages.total'))
|
||||
{
|
||||
$nextPage = $pagination->get('pages.current') + 1;
|
||||
$limitstart = ($nextPage - 1) * $pagination->limit;
|
||||
$uri = clone $protoUri;
|
||||
$uri->setVar('limitstart', $limitstart);
|
||||
$uri = JRoute::_((string) $uri);
|
||||
|
||||
$document->addLink('next', new F0FHalLink($uri));
|
||||
}
|
||||
|
||||
// The "last" link?
|
||||
$lastPage = $pagination->get('pages.total');
|
||||
$limitstart = ($lastPage - 1) * $pagination->limit;
|
||||
$uri = clone $protoUri;
|
||||
$uri->setVar('limitstart', $limitstart);
|
||||
$uri = JRoute::_((string) $uri);
|
||||
|
||||
$document->addLink('last', new F0FHalLink($uri));
|
||||
}
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an absolute URI to a relative one
|
||||
*
|
||||
* @param string $uri The URI to convert
|
||||
*
|
||||
* @return string The relative URL
|
||||
*/
|
||||
protected function _removeURIBase($uri)
|
||||
{
|
||||
static $root = null, $rootlen = 0;
|
||||
|
||||
if (is_null($root))
|
||||
{
|
||||
$root = rtrim(F0FPlatform::getInstance()->URIbase(), '/');
|
||||
$rootlen = strlen($root);
|
||||
}
|
||||
|
||||
if (substr($uri, 0, $rootlen) == $root)
|
||||
{
|
||||
$uri = substr($uri, $rootlen);
|
||||
}
|
||||
|
||||
return ltrim($uri, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JUri instance with a prototype URI used as the base for the
|
||||
* other URIs created by the JSON renderer
|
||||
*
|
||||
* @return JUri The prototype JUri instance
|
||||
*/
|
||||
protected function _getPrototypeURIForPagination()
|
||||
{
|
||||
$protoUri = new JUri('index.php');
|
||||
$protoUri->setQuery($this->input->getData());
|
||||
$protoUri->delVar('savestate');
|
||||
$protoUri->delVar('base_path');
|
||||
|
||||
return $protoUri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user