示例#1
0
文件: Hal.php 项目: zfcampus/zf-hal
 /**
  * Render an individual entity
  *
  * Creates a hash representation of the Entity. The entity is first
  * converted to an array, and its associated links are injected as the
  * "_links" member. If any members of the entity are themselves
  * Entity objects, they are extracted into an "_embedded" hash.
  *
  * @param  Entity $halEntity
  * @param  bool $renderEntity
  * @param  int $depth           depth of the current rendering recursion
  * @param  int $maxDepth        maximum rendering depth for the current metadata
  * @throws Exception\CircularReferenceException
  * @return array
  */
 public function renderEntity(Entity $halEntity, $renderEntity = true, $depth = 0, $maxDepth = null)
 {
     $this->getEventManager()->trigger(__FUNCTION__, $this, ['entity' => $halEntity]);
     $entity = $halEntity->getEntity();
     $entityLinks = clone $halEntity->getLinks();
     // Clone to prevent link duplication
     $metadataMap = $this->getMetadataMap();
     if (is_object($entity)) {
         if ($maxDepth === null && $metadataMap->has($entity)) {
             $maxDepth = $metadataMap->get($entity)->getMaxDepth();
         }
         if ($maxDepth === null) {
             $entityHash = spl_object_hash($entity);
             if (isset($this->entityHashStack[$entityHash])) {
                 // we need to clear the stack, as the exception may be caught and the plugin may be invoked again
                 $this->entityHashStack = [];
                 throw new Exception\CircularReferenceException(sprintf("Circular reference detected in '%s'. %s", get_class($entity), "Either set a 'max_depth' metadata attribute or remove the reference"));
             }
             $this->entityHashStack[$entityHash] = get_class($entity);
         }
     }
     if (!$renderEntity || $maxDepth !== null && $depth > $maxDepth) {
         $entity = [];
     }
     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), $this->getRenderEmbeddedEntities());
         }
         if ($value instanceof Entity) {
             $this->extractEmbeddedEntity($entity, $key, $value, $depth + 1, $maxDepth);
         }
         if ($value instanceof Collection) {
             $this->extractEmbeddedCollection($entity, $key, $value, $depth + 1, $maxDepth);
         }
         if ($value instanceof Link) {
             // We have a link; add it to the entity if it's not already present.
             $entityLinks = $this->injectPropertyAsLink($value, $entityLinks);
             unset($entity[$key]);
         }
         if ($value instanceof LinkCollection) {
             foreach ($value as $link) {
                 $entityLinks = $this->injectPropertyAsLink($link, $entityLinks);
             }
             unset($entity[$key]);
         }
     }
     $halEntity->setLinks($entityLinks);
     $entity['_links'] = $this->fromResource($halEntity);
     $payload = new ArrayObject($entity);
     $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, ['payload' => $payload, 'entity' => $halEntity]);
     if (isset($entityHash)) {
         unset($this->entityHashStack[$entityHash]);
     }
     return $payload->getArrayCopy();
 }
示例#2
0
 public function testRendersEmbeddedEntitiesOfIndividualPaginatedCollections()
 {
     $routeClass = class_exists(V2Segment::class) ? V2Segment::class : Segment::class;
     $this->router->addRoute('user', new $routeClass('/user[/:id]'));
     $child = new Entity(['id' => 'matthew', 'name' => 'matthew', 'github' => 'weierophinney'], 'matthew');
     $link = new Link('self');
     $link->setRoute('user')->setRouteParams(['id' => 'matthew']);
     $child->getLinks()->add($link);
     $prototype = ['foo' => 'bar', 'user' => $child];
     $items = [];
     foreach (range(1, 3) as $id) {
         $item = $prototype;
         $item['id'] = $id;
         $items[] = $item;
     }
     $adapter = new ArrayPaginator($items);
     $paginator = new Paginator($adapter);
     $collection = new Collection($paginator);
     $collection->setPageSize(5);
     $collection->setPage(1);
     $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));
     $collection = $result['_embedded']['items'];
     foreach ($collection as $item) {
         $this->assertArrayHasKey('_embedded', $item, var_export($item, 1));
         $embedded = $item['_embedded'];
         $this->assertArrayHasKey('user', $embedded);
         $user = $embedded['user'];
         $this->assertRelationalLinkContains('/user/matthew', 'self', $user);
         foreach ($child->getEntity() as $key => $value) {
             $this->assertArrayHasKey($key, $user);
             $this->assertEquals($value, $user[$key]);
         }
     }
 }
 /**
  * Inject links for the service services of a module
  *
  * @param Entity $halEntity
  * @param HalJsonModel $model
  * @param EventInterface $e
  * @return void
  */
 private function injectServiceLinks(Entity $halEntity, HalJsonModel $model, EventInterface $e)
 {
     $entity = $halEntity->getEntity();
     $links = $halEntity->getLinks();
     if ($entity instanceof Model\ModuleEntity) {
         $this->injectModuleResourceRelationalLinks($entity, $links, $model);
     }
     if ($entity instanceof Model\RestServiceEntity || $entity instanceof Model\RpcServiceEntity) {
         $this->normalizeEntityControllerServiceName($entity, $links, $model);
     }
     if ($entity instanceof Model\InputFilterEntity) {
         $this->normalizeEntityInputFilterName($entity, $links, $model);
     }
 }