/** * Generates a context according to the type requested. * * @param Request $request * @param $shortName * * @return array */ public function __invoke(Request $request, $shortName) { $request->attributes->set('_api_format', 'jsonld'); if ('Entrypoint' === $shortName) { return ['@context' => $this->contextBuilder->getEntrypointContext()]; } if (isset(self::$reservedShortNames[$shortName])) { $resource = null; } else { $resource = $this->resourceTypeCollection->getResourceForShortName($shortName); if (!$resource) { throw new NotFoundHttpException(); } } return ['@context' => $this->contextBuilder->getContext($resource)]; }
/** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = []) { $resource = $this->resourceResolver->guessResource($object, $context); if (isset($context['jsonld_sub_level'])) { $data = []; foreach ($object as $index => $obj) { $data[$index] = $this->serializer->normalize($obj, $format, $context); } } else { $context = $this->createContext($resource, $context); $data = ['@context' => $this->contextBuilder->getResourceContext($resource, $context), '@id' => $context['request_uri'], '@type' => self::HYDRA_COLLECTION, 'hydra:member' => []]; foreach ($object as $obj) { $data['hydra:member'][] = $this->serializer->normalize($obj, $format, $context); } } return $data; }
/** * {@inheritdoc} */ public function normalize($object, $format = null, array $context = array()) { $resource = $this->guessResource($object, $context); list($context, $data) = $this->contextBuilder->bootstrap($resource, $context); if (isset($context['json_ld_sub_level'])) { $data = []; foreach ($object as $index => $obj) { $data[$index] = $this->serializer->normalize($obj, $format, $context); } } else { $data['@id'] = $context['request_uri']; list($parts, $parameters) = $this->parseRequestUri($context['request_uri']); if ($object instanceof PaginatorInterface) { $data['@type'] = self::HYDRA_PAGED_COLLECTION; $currentPage = $object->getCurrentPage(); $lastPage = $object->getLastPage(); if (1.0 !== $currentPage) { $previousPage = $currentPage - 1.0; $data['hydra:previousPage'] = $this->getPageUrl($parts, $parameters, $previousPage); } if ($currentPage !== $lastPage) { $data['hydra:nextPage'] = $this->getPageUrl($parts, $parameters, $currentPage + 1.0); } $data['hydra:totalItems'] = $object->getTotalItems(); $data['hydra:itemsPerPage'] = $object->getItemsPerPage(); $data['hydra:firstPage'] = $this->getPageUrl($parts, $parameters, 1.0); $data['hydra:lastPage'] = $this->getPageUrl($parts, $parameters, $lastPage); } else { $data['@type'] = self::HYDRA_COLLECTION; } $data['hydra:member'] = []; foreach ($object as $obj) { $data['hydra:member'][] = $this->serializer->normalize($obj, $format, $context); } $filters = $resource->getFilters(); if (!empty($filters)) { $data['hydra:search'] = $this->getSearch($resource, $parts, $filters); } } return $data; }
/** * Builds the JSON-LD context for the given resource. * * @param ResourceInterface|null $resource * * @return array */ public function getContext(ResourceInterface $resource = null) { $context = parent::getContext($resource); if ($resource) { $normalizedOutput = $this->documentationHelper->normalizeClassParameter($resource->getEntityClass(), $resource); $data = $this->documentationHelper->getParametersParser($normalizedOutput, $resource); $embeds = $this->documentationHelper->transformerHelper->getAvailableIncludes($resource->getShortName()); $context['@embed'] = implode(',', $embeds); foreach ($data as $key => $value) { $context[$key] = '#' . $resource->getShortName() . '/' . $key; } } return $context; }
/** * {@inheritdoc} * * @throws RuntimeException * @throws CircularReferenceException * @throws InvalidArgumentException */ public function normalize($object, $format = null, array $context = []) { if (!$this->serializer instanceof NormalizerInterface) { throw new RuntimeException('The serializer must implement the NormalizerInterface.'); } if (is_object($object) && $this->isCircularReference($object, $context)) { return $this->handleCircularReference($object); } $resource = $this->guessResource($object, $context, true); $data = []; if (!isset($context['json_ld_has_context'])) { $data['@context'] = $this->contextBuilder->getContextUri($resource); } $context = $this->createContext($resource, $context); $classMetadata = $this->getMetadata($resource, $context); $attributesMetadata = $classMetadata->getAttributes(); $data['@id'] = $this->iriConverter->getIriFromItem($object); $data['@type'] = ($iri = $classMetadata->getIri()) ? $iri : $resource->getShortName(); foreach ($attributesMetadata as $attributeMetadata) { $attributeName = $attributeMetadata->getName(); if ('id' === $attributeName || !$attributeMetadata->isReadable()) { continue; } $attributeValue = $this->propertyAccessor->getValue($object, $attributeName); if ($this->nameConverter) { $attributeName = $this->nameConverter->normalize($attributeName); } if (isset($attributeMetadata->getTypes()[0])) { $type = $attributeMetadata->getTypes()[0]; if ($attributeValue && $type->isCollection() && ($collectionType = $type->getCollectionType()) && ($subResource = $this->getResourceFromType($collectionType))) { $values = []; foreach ($attributeValue as $index => $obj) { $values[$index] = $this->normalizeRelation($attributeMetadata, $obj, $subResource, $context); } $data[$attributeName] = $values; continue; } if ($attributeValue && ($subResource = $this->getResourceFromType($type))) { $data[$attributeName] = $this->normalizeRelation($attributeMetadata, $attributeValue, $subResource, $context); continue; } } $data[$attributeName] = $this->serializer->normalize($attributeValue, self::FORMAT, $context); } return $data; }
/** * Denormalizes a relation. * * @param ResourceInterface $currentResource * @param AttributeMetadataInterface $attributeMetadata * @param string $class * @param mixed $value * * @return object|null * * @throws InvalidArgumentException */ private function denormalizeRelation(ResourceInterface $currentResource, AttributeMetadataInterface $attributeMetadata, $class, $value) { if ('DateTime' === $class) { return $this->serializer->denormalize($value, $class ?: null, self::FORMAT); } $attributeName = $attributeMetadata->getName(); // Always allow IRI to be compliant with the Hydra spec if (is_string($value)) { $item = $this->iriConverter->getItemFromIri($value); if (null === $item) { throw new InvalidArgumentException(sprintf('IRI not supported (found "%s" in "%s" of "%s")', $value, $attributeName, $currentResource->getEntityClass())); } return $item; } if (!$this->resourceCollection->getResourceForEntity($class)) { throw new InvalidArgumentException(sprintf('Type not supported (found "%s" in attribute "%s" of "%s")', $class, $attributeName, $currentResource->getEntityClass())); } $context = $this->contextBuilder->bootstrapRelation($currentResource, $class); if (!$attributeMetadata->isDenormalizationLink()) { return $this->serializer->denormalize($value, $class, self::FORMAT, $context); } throw new InvalidArgumentException(sprintf('Nested objects for attribute "%s" of "%s" are not enabled. Use serialization groups to change that behavior.', $attributeName, $currentResource->getEntityClass())); }
/** * Builds the JSON-LD context for the API documentation. * * @return array */ private function getContext() { return array_merge($this->contextBuilder->getContext(), ['rdf' => ContextBuilder::RDF_NS, 'rdfs' => ContextBuilder::RDFS_NS, 'xmls' => ContextBuilder::XML_NS, 'owl' => ContextBuilder::OWL_NS, 'domain' => ['@id' => 'rdfs:domain', '@type' => '@id'], 'range' => ['@id' => 'rdfs:range', '@type' => '@id'], 'subClassOf' => ['@id' => 'rdfs:subClassOf', '@type' => '@id'], 'expects' => ['@id' => 'hydra:expects', '@type' => '@id'], 'returns' => ['@id' => 'hydra:returns', '@type' => '@id']]); }