2015-05-14 23:23:41 +02:00

196 lines
6.3 KiB
PHP

<?php
/*
* This file is part of the NelmioApiDocBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Extractor\AnnotationsProvider;
use Dunglas\ApiBundle\Api\Operation\OperationInterface;
use Dunglas\ApiBundle\Api\ResourceCollectionInterface;
use Dunglas\ApiBundle\Api\ResourceInterface;
use Dunglas\ApiBundle\Hydra\ApiDocumentationBuilderInterface;
use Dunglas\ApiBundle\Mapping\ClassMetadataFactoryInterface;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface;
use Nelmio\ApiDocBundle\Parser\DunglasApiParser;
/**
* Creates ApiDoc annotations for DunglasApiBundle.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DunglasApiProvider implements AnnotationsProviderInterface
{
/**
* @var ResourceCollectionInterface
*/
private $resourceCollection;
/**
* @var ApiDocumentationBuilderInterface
*/
private $apiDocumentationBuilder;
/**
* @var ClassMetadataFactoryInterface
*/
private $classMetadataFactory;
public function __construct(
ResourceCollectionInterface $resourceCollection,
ApiDocumentationBuilderInterface $apiDocumentationBuilder,
ClassMetadataFactoryInterface $classMetadataFactory
) {
$this->resourceCollection = $resourceCollection;
$this->apiDocumentationBuilder = $apiDocumentationBuilder;
$this->classMetadataFactory = $classMetadataFactory;
}
/**
* {@inheritdoc}
*/
public function getAnnotations()
{
$annotations = [];
$hydraDoc = $this->apiDocumentationBuilder->getApiDocumentation();
$entrypointHydraDoc = $this->getResourceHydraDoc($hydraDoc, '#Entrypoint');
/**
* @var ResourceInterface
*/
foreach ($this->resourceCollection as $resource) {
$classMetadata = $this->classMetadataFactory->getMetadataFor($resource->getEntityClass());
$prefixedShortName = ($iri = $classMetadata->getIri()) ? $iri : '#'.$resource->getShortName();
$resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName);
if ($hydraDoc) {
foreach ($resource->getCollectionOperations() as $operation) {
$annotations[] = $this->getApiDoc(true, $resource, $operation, $resourceHydraDoc, $entrypointHydraDoc);
}
foreach ($resource->getItemOperations() as $operation) {
$annotations[] = $this->getApiDoc(false, $resource, $operation, $resourceHydraDoc);
}
}
}
return $annotations;
}
/**
* Builds ApiDoc annotation from DunglasApiBundle data.
*
* @param bool $collection
* @param ResourceInterface $resource
* @param OperationInterface $operation
* @param array $resourceHydraDoc
* @param array $entrypointHydraDoc
*
* @return ApiDoc
*/
private function getApiDoc(
$collection,
ResourceInterface $resource,
OperationInterface $operation,
array $resourceHydraDoc,
array $entrypointHydraDoc = []
) {
$method = $operation->getRoute()->getMethods()[0];
if ($collection) {
$operationHydraDoc = $this->getCollectionOperationHydraDoc($resource->getShortName(), $method, $entrypointHydraDoc);
} else {
$operationHydraDoc = $this->getOperationHydraDoc($operation->getRoute()->getMethods()[0], $resourceHydraDoc);
}
$route = $operation->getRoute();
$data = [
'resource' => $route->getPath(),
'description' => $operationHydraDoc['hydra:title'],
'resourceDescription' => $resourceHydraDoc['hydra:title'],
];
$entityClass = $resource->getEntityClass();
if (isset($operationHydraDoc['expects']) && 'owl:Nothing' !== $operationHydraDoc['expects']) {
$data['input'] = sprintf('%s:%s', DunglasApiParser::IN_PREFIX, $entityClass);
}
if (isset($operationHydraDoc['returns']) && 'owl:Nothing' !== $operationHydraDoc['returns']) {
$data['output'] = sprintf('%s:%s', DunglasApiParser::OUT_PREFIX, $entityClass);
}
$data['filters'] = [];
foreach ($resource->getFilters() as $filter) {
foreach ($filter->getDescription($resource) as $name => $data) {
$data['filters'][] = ['name' => $name] + $data;
}
}
$apiDoc = new ApiDoc($data);
$apiDoc->setRoute($route);
return $apiDoc;
}
/**
* Gets Hydra documentation for the given resource.
*
* @param array $hydraApiDoc
* @param string $prefixedShortName
*
* @return array|null
*/
private function getResourceHydraDoc(array $hydraApiDoc, $prefixedShortName)
{
foreach ($hydraApiDoc['hydra:supportedClass'] as $supportedClass) {
if ($supportedClass['@id'] === $prefixedShortName) {
return $supportedClass;
}
}
}
/**
* Gets the Hydra documentation of a given operation.
*
* @param string $method
* @param array $hydraDoc
*
* @return array|null
*/
private function getOperationHydraDoc($method, array $hydraDoc)
{
foreach ($hydraDoc['hydra:supportedOperation'] as $supportedOperation) {
if ($supportedOperation['hydra:method'] === $method) {
return $supportedOperation;
}
}
}
/**
* Gets the Hydra documentation for the collection operation.
*
* @param string $shortName
* @param string $method
* @param array $hydraEntrypointDoc
*
* @return array|null
*/
private function getCollectionOperationHydraDoc($shortName, $method, array $hydraEntrypointDoc)
{
$propertyName = '#Entrypoint/'.lcfirst($shortName);
foreach ($hydraEntrypointDoc['hydra:supportedProperty'] as $supportedProperty) {
$hydraProperty = $supportedProperty['hydra:property'];
if ($hydraProperty['@id'] === $propertyName) {
return $this->getOperationHydraDoc($method, $hydraProperty);
}
}
}
}