Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/108'
Browse files Browse the repository at this point in the history
Close #108
  • Loading branch information
weierophinney committed Jul 16, 2015
2 parents 7813ca3 + 627e80d commit f1a1e83
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 87 deletions.
122 changes: 122 additions & 0 deletions src/Link/PaginationInjector.php
@@ -0,0 +1,122 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2014 Zend Technologies USA Inc. (http://www.zend.com)
*/

namespace ZF\Hal\Link;

use Zend\Paginator\Paginator;
use Zend\Stdlib\ArrayUtils;
use ZF\ApiProblem\ApiProblem;
use ZF\Hal\Collection;

class PaginationInjector implements PaginationInjectorInterface
{
/**
* @inheritDoc
*/
public function injectPaginationLinks(Collection $halCollection)
{
$collection = $halCollection->getCollection();
if (! $collection instanceof Paginator) {
return false;
}

$this->configureCollection($halCollection);

$pageCount = count($collection);
if ($pageCount === 0) {
return true;
}

$page = $halCollection->getPage();

if ($page < 1 || $page > $pageCount) {
return new ApiProblem(409, 'Invalid page provided');
}

$this->injectLinks($halCollection);

return true;
}

private function configureCollection(Collection $halCollection)
{
$collection = $halCollection->getCollection();
$page = $halCollection->getPage();
$pageSize = $halCollection->getPageSize();

$collection->setItemCountPerPage($pageSize);
$collection->setCurrentPageNumber($page);
}

private function injectLinks(Collection $halCollection)
{
$this->injectSelfLink($halCollection);
$this->injectFirstLink($halCollection);
$this->injectLastLink($halCollection);
$this->injectPrevLink($halCollection);
$this->injectNextLink($halCollection);
}

private function injectSelfLink(Collection $halCollection)
{
$page = $halCollection->getPage();
$link = $this->createPaginationLink('self', $halCollection, $page);
$halCollection->getLinks()->add($link, true);
}

private function injectFirstLink(Collection $halCollection)
{
$link = $this->createPaginationLink('first', $halCollection);
$halCollection->getLinks()->add($link);
}

private function injectLastLink(Collection $halCollection)
{
$page = $halCollection->getCollection()->count();
$link = $this->createPaginationLink('last', $halCollection, $page);
$halCollection->getLinks()->add($link);
}

private function injectPrevLink(Collection $halCollection)
{
$page = $halCollection->getPage();
$prev = ($page > 1) ? $page - 1 : false;

if ($prev) {
$link = $this->createPaginationLink('prev', $halCollection, $prev);
$halCollection->getLinks()->add($link);
}
}

private function injectNextLink(Collection $halCollection)
{
$page = $halCollection->getPage();
$pageCount = $halCollection->getCollection()->count();
$next = ($page < $pageCount) ? $page + 1 : false;

if ($next) {
$link = $this->createPaginationLink('next', $halCollection, $next);
$halCollection->getLinks()->add($link);
}
}

private function createPaginationLink($relation, Collection $halCollection, $page = null)
{
$options = ArrayUtils::merge(
$halCollection->getCollectionRouteOptions(),
['query' => ['page' => $page]]
);

return Link::factory([
'rel' => $relation,
'route' => [
'name' => $halCollection->getCollectionRoute(),
'params' => $halCollection->getCollectionRouteParams(),
'options' => $options,
],
]);
}
}
20 changes: 20 additions & 0 deletions src/Link/PaginationInjectorInterface.php
@@ -0,0 +1,20 @@
<?php
/**
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
* @copyright Copyright (c) 2014 Zend Technologies USA Inc. (http://www.zend.com)
*/

namespace ZF\Hal\Link;

use ZF\Hal\Collection;

interface PaginationInjectorInterface
{
/**
* Generate HAL links for a paginated collection
*
* @param Collection $halCollection
* @return boolean|ApiProblem
*/
public function injectPaginationLinks(Collection $halCollection);
}
129 changes: 42 additions & 87 deletions src/Plugin/Hal.php
Expand Up @@ -16,7 +16,6 @@
use Zend\EventManager\EventManagerInterface;
use Zend\Mvc\Controller\Plugin\PluginInterface as ControllerPluginInterface;
use Zend\Paginator\Paginator;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\DispatchableInterface;
use Zend\Stdlib\Extractor\ExtractionInterface;
use Zend\Stdlib\Hydrator\HydratorPluginManager;
Expand All @@ -31,6 +30,8 @@
use ZF\Hal\Link\Link;
use ZF\Hal\Link\LinkCollection;
use ZF\Hal\Link\LinkCollectionAwareInterface;
use ZF\Hal\Link\PaginationInjector;
use ZF\Hal\Link\PaginationInjectorInterface;
use ZF\Hal\Metadata\Metadata;
use ZF\Hal\Metadata\MetadataMap;
use ZF\Hal\Resource;
Expand Down Expand Up @@ -97,6 +98,11 @@ class Hal extends AbstractHelper implements
*/
protected $metadataMap;

/**
* @var PaginationInjectorInterface
*/
protected $paginationInjector;

/**
* @var ServerUrl
*/
Expand Down Expand Up @@ -157,7 +163,7 @@ public function getController()
*/
public function getEventManager()
{
if (!$this->events) {
if (! $this->events) {
$this->setEventManager(new EventManager());
}
return $this->events;
Expand Down Expand Up @@ -222,7 +228,7 @@ public function getHydratorManager()
*/
public function getMetadataMap()
{
if (!$this->metadataMap instanceof MetadataMap) {
if (! $this->metadataMap instanceof MetadataMap) {
$this->setMetadataMap(new MetadataMap());
}
return $this->metadataMap;
Expand All @@ -240,6 +246,27 @@ public function setMetadataMap(MetadataMap $map)
return $this;
}

/**
* @return PaginationInjectorInterface
*/
public function getPaginationInjector()
{
if (! $this->paginationInjector instanceof PaginationInjectorInterface) {
$this->setPaginationInjector(new PaginationInjector());
}
return $this->paginationInjector;
}

/**
* @param PaginationInjectorInterface $injector
* @return self
*/
public function setPaginationInjector(PaginationInjectorInterface $injector)
{
$this->paginationInjector = $injector;
return $this;
}

/**
* @param ServerUrl $helper
* @return self
Expand Down Expand Up @@ -287,7 +314,7 @@ public function setLinkCollectionExtractor(LinkCollectionExtractorInterface $ext
*/
public function addHydrator($class, $hydrator)
{
if (!$hydrator instanceof ExtractionInterface) {
if (! $hydrator instanceof ExtractionInterface) {
$hydrator = $this->hydrators->get($hydrator);
}

Expand Down Expand Up @@ -466,7 +493,7 @@ public function getHydratorForEntity($entity)
*
* <code>
* $params = $e->getParams();
* $params['routeOptions']['query'] = array('format' => 'json');
* $params['routeOptions']['query'] = ['format' => 'json'];
* </code>
*
* @param Collection $halCollection
Expand Down Expand Up @@ -593,7 +620,7 @@ public function renderEntity(Entity $halEntity, $renderEntity = true, $depth = 0
}
}

if (!$renderEntity || ($maxDepth !== null && $depth > $maxDepth)) {
if (! $renderEntity || ($maxDepth !== null && $depth > $maxDepth)) {
$entity = [];
}

Expand Down Expand Up @@ -778,7 +805,7 @@ public function createEntityFromMetadata($object, Metadata $metadata, $renderEmb

$id = ($entityIdentifierName) ? $data[$entityIdentifierName]: null;

if (!$renderEmbeddedEntities) {
if (! $renderEmbeddedEntities) {
$object = [];
}

Expand All @@ -788,7 +815,7 @@ public function createEntityFromMetadata($object, Metadata $metadata, $renderEmb
$this->marshalMetadataLinks($metadata, $links);

$forceSelfLink = $metadata->getForceSelfLink();
if ($forceSelfLink && !$links->has('self')) {
if ($forceSelfLink && ! $links->has('self')) {
$link = $this->marshalLinkFromMetadata($metadata, $object, $id, $metadata->getRouteIdentifierName());
$links->add($link);
}
Expand Down Expand Up @@ -846,7 +873,7 @@ public function createEntity($entity, $route, $routeIdentifierName)
break;
}
$metadata = (!is_array($entity) && $metadataMap->has($entity)) ? $metadataMap->get($entity) : false;
if (!$metadata || ($metadata && $metadata->getForceSelfLink())) {
if (! $metadata || ($metadata && $metadata->getForceSelfLink())) {
$this->injectSelfLink($halEntity, $route, $routeIdentifierName);
}
return $halEntity;
Expand All @@ -866,12 +893,12 @@ public function createCollection($collection, $route = null)
$collection = $this->createCollectionFromMetadata($collection, $metadataMap->get($collection));
}

if (!$collection instanceof Collection) {
if (! $collection instanceof Collection) {
$collection = new Collection($collection);
}

$metadata = $metadataMap->get($collection);
if (!$metadata || ($metadata && $metadata->getForceSelfLink())) {
if (! $metadata || ($metadata && $metadata->getForceSelfLink())) {
$this->injectSelfLink($collection, $route);
}
return $collection;
Expand All @@ -895,7 +922,7 @@ public function createCollectionFromMetadata($object, Metadata $metadata)
$this->marshalMetadataLinks($metadata, $links);

$forceSelfLink = $metadata->getForceSelfLink();
if ($forceSelfLink && !$links->has('self')
if ($forceSelfLink && ! $links->has('self')
&& ($metadata->hasUrl() || $metadata->hasRoute())
) {
$link = $this->marshalLinkFromMetadata($metadata, $object);
Expand Down Expand Up @@ -950,83 +977,11 @@ public function injectSelfLink(LinkCollectionAwareInterface $resource, $route, $
* Generate HAL links for a paginated collection
*
* @param Collection $halCollection
* @return boolean
* @return boolean|ApiProblem
*/
protected function injectPaginationLinks(Collection $halCollection)
{
$collection = $halCollection->getCollection();
$page = $halCollection->getPage();
$pageSize = $halCollection->getPageSize();
$route = $halCollection->getCollectionRoute();
$params = $halCollection->getCollectionRouteParams();
$options = $halCollection->getCollectionRouteOptions();

$collection->setItemCountPerPage($pageSize);
$collection->setCurrentPageNumber($page);

$count = count($collection);
if (!$count) {
return true;
}

if ($page < 1 || $page > $count) {
return new ApiProblem(409, 'Invalid page provided');
}

$links = $halCollection->getLinks();
$next = ($page < $count) ? $page + 1 : false;
$prev = ($page > 1) ? $page - 1 : false;

// self link
$link = new Link('self');
$link->setRoute($route);
$link->setRouteParams($params);
$link->setRouteOptions(ArrayUtils::merge($options, [
'query' => ['page' => $page],
]));
$links->add($link, true);

// first link
$link = new Link('first');
$link->setRoute($route);
$link->setRouteParams($params);
$link->setRouteOptions(ArrayUtils::merge($options, [
'query' => ['page' => null],
]));
$links->add($link);

// last link
$link = new Link('last');
$link->setRoute($route);
$link->setRouteParams($params);
$link->setRouteOptions(ArrayUtils::merge($options, [
'query' => ['page' => $count],
]));
$links->add($link);

// prev link
if ($prev) {
$link = new Link('prev');
$link->setRoute($route);
$link->setRouteParams($params);
$link->setRouteOptions(ArrayUtils::merge($options, [
'query' => ['page' => $prev],
]));
$links->add($link);
}

// next link
if ($next) {
$link = new Link('next');
$link->setRoute($route);
$link->setRouteParams($params);
$link->setRouteOptions(ArrayUtils::merge($options, [
'query' => ['page' => $next],
]));
$links->add($link);
}

return true;
return $this->getPaginationInjector()->injectPaginationLinks($halCollection);
}

/**
Expand Down Expand Up @@ -1292,7 +1247,7 @@ protected function marshalLinkFromMetadata(
return $link;
}

if (!$metadata->hasRoute()) {
if (! $metadata->hasRoute()) {
throw new Exception\RuntimeException(sprintf(
'Unable to create a self link for resource of type "%s"; metadata does not contain a route or a url',
get_class($object)
Expand Down

0 comments on commit f1a1e83

Please sign in to comment.