/** * @param object $object * @param Metadata $metadata * @return Collection */ public function createCollectionFromMetadata($object, Metadata $metadata) { $halCollection = new Collection($object); $halCollection->setCollectionName($metadata->getCollectionName()); $halCollection->setCollectionRoute($metadata->getRoute()); $halCollection->setEntityRoute($metadata->getEntityRoute()); $halCollection->setRouteIdentifierName($metadata->getRouteIdentifierName()); $halCollection->setEntityIdentifierName($metadata->getEntityIdentifierName()); $links = $halCollection->getLinks(); $this->marshalMetadataLinks($metadata, $links); $forceSelfLink = $metadata->getForceSelfLink(); if ($forceSelfLink && !$links->has('self') && ($metadata->hasUrl() || $metadata->hasRoute())) { $link = $this->marshalLinkFromMetadata($metadata, $object); $links->add($link); } return $halCollection; }
public function testAllowsSpecifyingAlternateCallbackForReturningEntityId() { $this->setUpHelpers(); $this->helpers->get('Hal')->getEventManager()->attach('getIdFromEntity', function ($e) { $entity = $e->getParam('entity'); if (!is_array($entity)) { return false; } if (array_key_exists('name', $entity)) { return $entity['name']; } return false; }, 10); $prototype = array('foo' => 'bar'); $items = array(); foreach (range(1, 100) as $id) { $item = $prototype; $item['name'] = $id; $items[] = $item; } $collection = new Collection($items); $collection->setCollectionRoute('resource'); $collection->setEntityRoute('resource'); $links = $collection->getLinks(); $self = new Link('self'); $self->setRoute('resource'); $links->add($self); $model = new HalJsonModel(array('payload' => $collection)); $test = $this->renderer->render($model); $test = json_decode($test); $this->assertInstanceof('stdClass', $test, var_export($test, 1)); $this->assertRelationalLinkEquals('http://localhost.localdomain/resource', 'self', $test); $this->assertObjectHasAttribute('_embedded', $test); $this->assertInstanceof('stdClass', $test->_embedded); $this->assertObjectHasAttribute('items', $test->_embedded); $this->assertInternalType('array', $test->_embedded->items); $this->assertEquals(100, count($test->_embedded->items)); foreach ($test->_embedded->items as $key => $item) { $id = $key + 1; $this->assertRelationalLinkEquals('http://localhost.localdomain/resource/' . $id, 'self', $item); $this->assertObjectHasAttribute('name', $item, var_export($item, 1)); $this->assertEquals($id, $item->name); $this->assertObjectHasAttribute('foo', $item); $this->assertEquals('bar', $item->foo); } }
public function setUpChildCollection() { $children = array(array('luke', 'Luke Skywalker'), array('leia', 'Leia Organa')); $this->collection = array(); foreach ($children as $info) { $collection[] = call_user_func_array(array($this, 'setUpChildResource'), $info); } $collection = new HalCollection($this->collection); $collection->setCollectionRoute('parent/child'); $collection->setEntityRoute('parent/child'); $collection->setPage(1); $collection->setPageSize(10); $collection->setCollectionName('child'); $link = new Link('self'); $link->setRoute('parent/child'); $collection->getLinks()->add($link); return $collection; }
public function indexAction() { $event = $this->getEvent(); $routeMatch = $event->getRouteMatch(); $route = $this->deriveRouteName($routeMatch->getMatchedRouteName()); $request = $this->getRequest(); $module = $this->params()->fromRoute('name', false); $controller = $this->params()->fromRoute('controller_service_name', false); $inputFilterName = $this->params()->fromRoute('input_filter_name', false); if (!$module || !$this->model->moduleExists($module)) { return new ApiProblemResponse(new ApiProblem(404, 'The module specified does not exist')); } if (!$controller || !$this->model->controllerExists($module, $controller)) { return new ApiProblemResponse(new ApiProblem(404, 'The controller specified does not exist')); } switch ($request->getMethod()) { case $request::METHOD_GET: $result = $this->model->fetch($module, $controller, $inputFilterName); if (false === $result) { return new ApiProblemResponse(new ApiProblem(404, 'The input filter specified does not exist')); } if ($result instanceof InputFilterCollection) { $result = new HalCollection($result); $result->setCollectionName('input_filter'); $result->getLinks()->add(Link::factory(array('rel' => 'self', 'route' => array('name' => $route, 'params' => array('name' => $module, 'controller_service_name' => str_replace('\\', '-', $controller)))))); $result->setEntityRoute($route); break; } $name = $result['input_filter_name']; $result = new HalEntity($result, $name); $this->injectEntitySelfLink($result->getLinks(), $route, $module, $controller, $name); break; case $request::METHOD_POST: if ($inputFilterName) { return new ApiProblemResponse(new ApiProblem(400, 'POST requests are not allowed to individual input filters')); } // Intentionally not breaking, as remainder of logic remains the same as PUT // Intentionally not breaking, as remainder of logic remains the same as PUT case $request::METHOD_PUT: $inputFilter = $this->bodyParams(); $result = $this->model->update($module, $controller, $inputFilter); if (!$result) { return new ApiProblemResponse(new ApiProblem(500, 'There was an unexpected error updating the input filter; please verify the module and controller specified are valid')); } $name = $result['input_filter_name']; $result = new HalEntity($result, $name); $this->injectEntitySelfLink($result->getLinks(), $route, $module, $controller, $name); break; case $request::METHOD_DELETE: if (empty($inputFilterName)) { return new ApiProblemResponse(new ApiProblem(400, 'The input filter name has not been specified')); } $result = $this->model->remove($module, $controller, $inputFilterName); if (!$result) { return new ApiProblemResponse(new ApiProblem(404, 'The input filter specified does not exist')); } return $this->getResponse()->setStatusCode(204); } $e = $this->getEvent(); $e->setParam('ZFContentNegotiationFallback', 'HalJson'); return new ViewModel(array('payload' => $result)); }
public function testAllowsSpecifyingAlternateCallbackForReturningEntityId() { $this->plugin->getEventManager()->attach('getIdFromEntity', function ($e) { $entity = $e->getParam('entity'); if (!is_array($entity)) { return false; } if (array_key_exists('name', $entity)) { return $entity['name']; } return false; }, 10); $prototype = ['foo' => 'bar']; $items = []; foreach (range(1, 100) as $id) { $item = $prototype; $item['name'] = $id; $items[] = $item; } $collection = new Collection($items); $collection->setCollectionRoute('resource'); $collection->setEntityRoute('resource'); $links = $collection->getLinks(); $self = new Link('self'); $self->setRoute('resource'); $links->add($self); $result = $this->plugin->renderCollection($collection); $this->assertInternalType('array', $result, var_export($result, 1)); $this->assertRelationalLinkEquals('http://localhost.localdomain/resource', 'self', $result); $this->assertArrayHasKey('_embedded', $result); $this->assertInternalType('array', $result['_embedded']); $this->assertArrayHasKey('items', $result['_embedded']); $this->assertInternalType('array', $result['_embedded']['items']); $this->assertEquals(100, count($result['_embedded']['items'])); foreach ($result['_embedded']['items'] as $key => $item) { $id = $key + 1; $this->assertRelationalLinkEquals('http://localhost.localdomain/resource/' . $id, 'self', $item); $this->assertArrayHasKey('name', $item, var_export($item, 1)); $this->assertEquals($id, $item['name']); $this->assertArrayHasKey('foo', $item); $this->assertEquals('bar', $item['foo']); } }
public function testLinkCollectionMayBeInjected() { $hal = new Collection(array(), 'item/route'); $links = new LinkCollection(); $hal->setLinks($links); $this->assertSame($links, $hal->getLinks()); }
/** * Prepare a HAL collection with the metadata for the current instance. * * @param HalCollection $collection * @return HalCollection|ApiProblem */ protected function prepareHalCollection(HalCollection $collection) { if (!$collection->getLinks()->has('self')) { $plugin = $this->plugin('Hal'); $plugin->injectSelfLink($collection, $this->route); } $collection->setCollectionRoute($this->route); $collection->setRouteIdentifierName($this->getRouteIdentifierName()); $collection->setEntityRoute($this->route); $collection->setCollectionName($this->collectionName); $collection->setPageSize($this->getPageSize()); try { $collection->setPage($this->getRequest()->getQuery('page', 1)); } catch (HalInvalidArgumentException $e) { return new ApiProblem(400, $e->getMessage()); } return $collection; }
/** * @group 14 */ public function testRenderingNonPaginatorCollectionRendersCountOfTotalItems() { $embedded = new Entity((object) array('id' => 'foo', 'name' => 'foo'), 'foo'); $links = $embedded->getLinks(); $self = new Link('self'); $self->setRoute('hostname/users', array('id' => 'foo')); $links->add($self); $collection = new Collection(array($embedded)); $collection->setCollectionName('users'); $self = new Link('self'); $self->setRoute('hostname/users'); $collection->getLinks()->add($self); $rendered = $this->plugin->renderCollection($collection); $expectedKeys = array('_links', '_embedded', 'total_items'); $this->assertEquals($expectedKeys, array_keys($rendered)); }
/** * Generate HAL links for a paginated collection * * @param Collection $halCollection * @return boolean */ 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; }