public function halObjects()
 {
     $entity = new Entity(['foo' => 'bar'], 'identifier', 'route');
     $link = new Link('self');
     $link->setRoute('resource/route')->setRouteParams(['id' => 'identifier']);
     $entity->getLinks()->add($link);
     $collection = new Collection([$entity]);
     $collection->setCollectionRoute('collection/route');
     $collection->setEntityRoute('resource/route');
     return ['entity' => [$entity], 'collection' => [$collection]];
 }
Exemple #2
0
 private function createSelfLink($resource, $route, $routeIdentifier)
 {
     $link = new Link('self');
     $link->setRoute($route);
     $routeParams = $this->getRouteParams($resource, $routeIdentifier);
     if (!empty($routeParams)) {
         $link->setRouteParams($routeParams);
     }
     $routeOptions = $this->getRouteOptions($resource);
     if (!empty($routeOptions)) {
         $link->setRouteOptions($routeOptions);
     }
     return $link;
 }
 /**
  * Return a HAL entity with just a self link
  */
 public function extract($value)
 {
     if (is_null($value)) {
         return $value;
     }
     $entityValues = $this->getHydratorForEntity($value)->extract($value);
     $entityMetadata = $this->getMetadataMap()[ClassUtils::getRealClass(get_class($value))];
     $link = new Link('self');
     $link->setRoute($entityMetadata['route_name']);
     $link->setRouteParams(array($entityMetadata['route_identifier_name'] => $entityValues[$entityMetadata['entity_identifier_name']]));
     $linkCollection = new LinkCollection();
     $linkCollection->add($link);
     $halEntity = new HalEntity(new stdClass());
     $halEntity->setLinks($linkCollection);
     return $halEntity;
 }
    public function halObjects()
    {
        $entity = new Entity(array(
            'foo' => 'bar',
        ), 'identifier', 'route');
        $link = new Link('self');
        $link->setRoute('resource/route')->setRouteParams(array('id' => 'identifier'));
        $entity->getLinks()->add($link);

        $collection = new Collection(array($entity));
        $collection->setCollectionRoute('collection/route');
        $collection->setEntityRoute('resource/route');

        return array(
            'entity'     => array($entity),
            'collection' => array($collection),
        );
    }
 public function extract($value)
 {
     if (!method_exists($value, 'getTypeClass')) {
         return;
     }
     $config = $this->getMetadataMap()[$value->getTypeClass()->name];
     $filter = new FilterChain();
     $filter->attachByName('WordCamelCaseToUnderscore')->attachByName('StringToLower');
     // Better way to create mapping name?
     // FIXME: use zf-hal collection_name
     $link = new Link('self');
     $link->setRoute($config['route_name']);
     $link->setRouteParams(array('id' => null));
     $filterValue = array('field' => $value->getMapping()['mappedBy'] ?: $value->getMapping()['inversedBy'], 'type' => isset($value->getMapping()['joinTable']) ? 'ismemberof' : 'eq', 'value' => $value->getOwner()->getId());
     $link->setRouteOptions(array('query' => array($this->getFilterKey() => array($filterValue))));
     $linkCollection = new LinkCollection();
     $linkCollection->add($link);
     $halEntity = new HalEntity(new stdClass());
     $halEntity->setLinks($linkCollection);
     return $halEntity;
 }
 public function extract($value)
 {
     $config = $this->getServiceManager()->get('Config');
     if (!method_exists($value, 'getTypeClass') || !isset($config['zf-hal']['metadata_map'][$value->getTypeClass()->name])) {
         return;
     }
     $config = $config['zf-hal']['metadata_map'][$value->getTypeClass()->name];
     $mapping = $value->getMapping();
     $filter = new FilterChain();
     $filter->attachByName('WordCamelCaseToUnderscore')->attachByName('StringToLower');
     $link = new Link($filter($mapping['fieldName']));
     $link->setRoute($config['route_name']);
     $link->setRouteParams(array('id' => null));
     if (isset($config['zf-doctrine-querybuilder-options']['filter_key'])) {
         $filterKey = $config['zf-doctrine-querybuilder-options']['filter_key'];
     } else {
         $filterKey = 'filter';
     }
     $link->setRouteOptions(array('query' => array($filterKey => array(array('field' => $mapping['mappedBy'], 'type' => 'eq', 'value' => $value->getOwner()->getId())))));
     return $link;
 }
 public function indexAction()
 {
     $request = $this->getRequest();
     $httpMethod = $request->getMethod();
     $module = $this->params()->fromRoute('name', false);
     $controllerServiceName = $this->params()->fromRoute('controller_service_name', false);
     $controllerType = $this->params()->fromRoute('controller_type');
     // rest or rpc
     $routeName = $this->deriveRouteName($this->getEvent()->getRouteMatch()->getMatchedRouteName());
     switch ($httpMethod) {
         case HttpRequest::METHOD_GET:
             $result = new HalEntity($this->model->fetchDocumentation($module, $controllerServiceName), 'documentation');
             $self = new HalLink('self');
             $self->setRoute($routeName);
             $result->getLinks()->add($self);
             break;
         case HttpRequest::METHOD_PUT:
             $documentation = $this->bodyParams();
             $result = new HalEntity($this->model->storeDocumentation($module, $controllerType, $controllerServiceName, $documentation, true), 'documentation');
             $self = new HalLink('self');
             $self->setRoute($routeName);
             $result->getLinks()->add($self);
             break;
         case HttpRequest::METHOD_PATCH:
             $documentation = $this->bodyParams();
             $result = new HalEntity($this->model->storeDocumentation($module, $controllerType, $controllerServiceName, $documentation, false), 'documentation');
             $self = new HalLink('self');
             $self->setRoute($routeName);
             $result->getLinks()->add($self);
             break;
         case HttpRequest::METHOD_DELETE:
         case HttpRequest::METHOD_POST:
         default:
             return new ApiProblemResponse(new ApiProblem(404, 'Unsupported method.'));
     }
     $e = $this->getEvent();
     $e->setParam('ZFContentNegotiationFallback', 'HalJson');
     return new ViewModel(['payload' => $result]);
 }
Exemple #8
0
 /**
  * Extract a collection as an array
  *
  * @todo   Remove 'resource' from event parameters for 1.0.0
  * @todo   Remove trigger of 'renderCollection.resource' for 1.0.0
  * @param  Collection $halCollection
  * @param  int $depth                   depth of the current rendering recursion
  * @param  int $maxDepth                maximum rendering depth for the current metadata
  * @return array
  */
 protected function extractCollection(Collection $halCollection, $depth = 0, $maxDepth = null)
 {
     $collection = [];
     $events = $this->getEventManager();
     $routeIdentifierName = $halCollection->getRouteIdentifierName();
     $entityRoute = $halCollection->getEntityRoute();
     $entityRouteParams = $halCollection->getEntityRouteParams();
     $entityRouteOptions = $halCollection->getEntityRouteOptions();
     $metadataMap = $this->getMetadataMap();
     foreach ($halCollection->getCollection() as $entity) {
         $eventParams = new ArrayObject(['collection' => $halCollection, 'entity' => $entity, 'resource' => $entity, 'route' => $entityRoute, 'routeParams' => $entityRouteParams, 'routeOptions' => $entityRouteOptions]);
         $events->trigger('renderCollection.resource', $this, $eventParams);
         $events->trigger('renderCollection.entity', $this, $eventParams);
         $entity = $eventParams['entity'];
         if (is_object($entity) && $metadataMap->has($entity)) {
             $entity = $this->getResourceFactory()->createEntityFromMetadata($entity, $metadataMap->get($entity));
         }
         if ($entity instanceof Entity) {
             // Depth does not increment at this level
             $collection[] = $this->renderEntity($entity, $this->getRenderCollections(), $depth, $maxDepth);
             continue;
         }
         if (!is_array($entity)) {
             $entity = $this->getEntityExtractor()->extract($entity);
         }
         foreach ($entity as $key => $value) {
             if (is_object($value) && $metadataMap->has($value)) {
                 $value = $this->getResourceFactory()->createEntityFromMetadata($value, $metadataMap->get($value));
             }
             if ($value instanceof Entity) {
                 $this->extractEmbeddedEntity($entity, $key, $value, $depth + 1, $maxDepth);
             }
             if ($value instanceof Collection) {
                 $this->extractEmbeddedCollection($entity, $key, $value, $depth + 1, $maxDepth);
             }
         }
         $id = $this->getIdFromEntity($entity);
         if ($id === false) {
             // Cannot handle entities without an identifier
             // Return as-is
             $collection[] = $entity;
             continue;
         }
         if ($eventParams['entity'] instanceof LinkCollectionAwareInterface) {
             $links = $eventParams['entity']->getLinks();
         } else {
             $links = new LinkCollection();
         }
         if (isset($entity['links']) && $entity['links'] instanceof LinkCollection) {
             $links = $entity['links'];
         }
         /* $entity is always an array here. We don't have metadata config for arrays so the self link is forced
            by default (at the moment) and should be removed manually if not required. But at some point it should
            be discussed if it makes sense to force self links in this particular use-case.  */
         $selfLink = new Link('self');
         $selfLink->setRoute($eventParams['route'], array_merge($eventParams['routeParams'], [$routeIdentifierName => $id]), $eventParams['routeOptions']);
         $links->add($selfLink);
         $entity['_links'] = $this->fromLinkCollection($links);
         $collection[] = $entity;
     }
     return $collection;
 }
 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;
 }
Exemple #11
0
 /**
  * Creates a link object, given metadata and a resource
  *
  * @param  Metadata $metadata
  * @param  object $object
  * @param  null|string $id
  * @param  null|string $routeIdentifierName
  * @param  string $relation
  * @return Link
  * @throws Exception\RuntimeException
  */
 public function marshalLinkFromMetadata(Metadata $metadata, $object, $id = null, $routeIdentifierName = null, $relation = 'self')
 {
     $link = new Link($relation);
     if ($metadata->hasUrl()) {
         $link->setUrl($metadata->getUrl());
         return $link;
     }
     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)));
     }
     $params = $metadata->getRouteParams();
     // process any callbacks
     foreach ($params as $key => $param) {
         // bind to the object if supported
         if ($param instanceof Closure && version_compare(PHP_VERSION, '5.4.0') >= 0) {
             $param = $param->bindTo($object);
         }
         // pass the object for callbacks and non-bound closures
         if (is_callable($param)) {
             $params[$key] = call_user_func_array($param, [$object]);
         }
     }
     if ($routeIdentifierName) {
         $params = array_merge($params, [$routeIdentifierName => $id]);
     }
     if ($relation !== 'self' && $id) {
         $link->setProps(array_merge($link->getProps(), ['id' => $id]));
     }
     $link->setRoute($metadata->getRoute(), $params, $metadata->getRouteOptions());
     return $link;
 }
Exemple #12
0
 /**
  * @group 101
  */
 public function testNotExistingRouteInMetadataLinks()
 {
     $object = new TestAsset\Entity('foo', 'Foo');
     $object->first_child = new TestAsset\EmbeddedEntity('bar', 'Bar');
     $entity = new Entity($object, 'foo');
     $self = new Link('self');
     $self->setRoute('hostname/resource', ['id' => 'foo']);
     $entity->getLinks()->add($self);
     $metadata = new MetadataMap(['ZFTest\\Hal\\Plugin\\TestAsset\\EmbeddedEntity' => ['hydrator' => 'Zend\\Hydrator\\ObjectProperty', 'route' => 'hostname/embedded', 'route_identifier_name' => 'id', 'entity_identifier_name' => 'id', 'links' => ['link' => ['rel' => 'link', 'route' => ['name' => 'non_existing_route']]]]]);
     $this->plugin->setMetadataMap($metadata);
     $expectedExceptionClass = class_exists(V2RouterException\RuntimeException::class) ? V2RouterException\RuntimeException::class : RouterException\RuntimeException::class;
     $this->setExpectedException($expectedExceptionClass);
     $this->plugin->renderEntity($entity);
 }
Exemple #13
0
    protected function createNestedEntity()
    {
        $object = new TestAsset\Entity('foo', 'Foo');
        $object->first_child  = new TestAsset\EmbeddedEntityWithBackReference('bar', $object);
        $entity = new Entity($object, 'foo');
        $self = new Link('self');
        $self->setRoute('hostname/resource', array('id' => 'foo'));
        $entity->getLinks()->add($self);

        return $entity;
    }
Exemple #14
0
 public function testIsCompleteReturnsTrueWhenRouteIsSet()
 {
     $link = new Link('describedby');
     $link->setRoute('api/docs');
     $this->assertTrue($link->isComplete());
 }
Exemple #15
0
 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']);
     }
 }
 /**
  * @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));
 }