Add php docs support

This commit is contained in:
Ener-Getick 2016-07-13 23:05:14 +02:00
parent 42a2aefb41
commit 3490b01d1d
No known key found for this signature in database
GPG Key ID: 9E5D2DB67BF054DD
8 changed files with 151 additions and 27 deletions

View File

@ -16,6 +16,7 @@ use gossi\swagger\Swagger;
class ApiDocGenerator
{
private $swagger;
private $extractors;
/**
@ -31,11 +32,15 @@ class ApiDocGenerator
*/
public function extract()
{
$swagger = new Swagger();
foreach ($this->extractors as $extractor) {
$extractor->extractIn($swagger);
if (null !== $this->swagger) {
return $this->swagger;
}
return $swagger;
$this->swagger = new Swagger();
foreach ($this->extractors as $extractor) {
$extractor->extractIn($this->swagger);
}
return $this->swagger;
}
}

View File

@ -11,6 +11,8 @@
namespace EXSyst\Bundle\ApiDocBundle\DependencyInjection;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use phpDocumentor\Reflection\DocBlockFactory;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@ -35,5 +37,13 @@ class EXSystApiDocExtension extends Extension
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
// Removes useless services
if (!class_exists(ApiDoc::class)) {
$container->removeDefinition('exsyst_api_doc.routing_extractors.nelmio_annotation');
}
if (!class_exists(DocBlockFactory::class)) {
$container->removeDefinition('exsyst_api_doc.routing_extractors.php_doc');
}
}
}

View File

@ -22,20 +22,14 @@ class NelmioAnnotationExtractor implements RouteExtractorInterface
use RouteExtractorTrait;
private $annotationReader;
private $nelmioLoaded;
public function __construct(Reader $annotationReader)
{
$this->annotationReader = $annotationReader;
$this->nelmioLoaded = class_exists(ApiDoc::class);
}
public function extractIn(Swagger $api, Route $route, \ReflectionMethod $reflectionMethod)
{
if (!$this->nelmioLoaded) {
return;
}
$annotation = $this->annotationReader->getMethodAnnotation($reflectionMethod, ApiDoc::class);
if (null === $annotation) {
return;
@ -48,9 +42,7 @@ class NelmioAnnotationExtractor implements RouteExtractorInterface
if ($annotation->getDescription()) {
$operation->setDescription($annotation->getDescription());
}
if (null !== $annotation->getDeprecated()) {
$operation->setDeprecated($operation->getDeprecated || $annotation->getDeprecated());
}
$operation->setDeprecated($operation->getDeprecated() || $annotation->getDeprecated());
// Request parameters
foreach ($annotation->getParameters() as $name => $configuration) {

View File

@ -0,0 +1,61 @@
<?php
/*
* This file is part of the ApiDocBundle package.
*
* (c) EXSyst
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace EXSyst\Bundle\ApiDocBundle\Extractor\Routing;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\DocBlockFactoryInterface;
use Doctrine\Common\Annotations\Reader;
use gossi\swagger\Parameter;
use gossi\swagger\Swagger;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\Routing\Route;
class PhpDocExtractor implements RouteExtractorInterface
{
use RouteExtractorTrait;
private $docBlockFactory;
public function __construct(DocBlockFactoryInterface $docBlockFactory = null)
{
if (null === $docBlockFactory) {
$docBlockFactory = DocBlockFactory::createInstance();
}
$this->docBlockFactory = $docBlockFactory;
}
public function extractIn(Swagger $api, Route $route, \ReflectionMethod $reflectionMethod)
{
$classDocBlock = null;
$docBlock = null;
try {
$classDocBlock = $this->docBlockFactory->create($reflectionMethod->getDeclaringClass());
} catch (\Exception $e) {
}
try {
$docBlock = $this->docBlockFactory->create($reflectionMethod);
} catch (\Exception $e) {
}
foreach ($this->getOperations($api, $route) as $operation) {
if (null !== $docBlock) {
$operation->setSummary($docBlock->getSummary());
$operation->setDescription((string) $docBlock->getDescription());
$operation->setDeprecated($operation->getDeprecated() || $docBlock->hasTag('deprecated'));
}
if (null !== $classDocBlock) {
$operation->setDeprecated($operation->getDeprecated() || $classDocBlock->hasTag('deprecated'));
}
}
}
}

View File

@ -19,13 +19,17 @@
<!-- Routing Extractors -->
<service id="exsyst_api_doc.routing_extractors.route_metadata" class="EXSyst\Bundle\ApiDocBundle\Extractor\Routing\RouteMetadataExtractor" public="false">
<tag name="exsyst_api_doc.routing_extractor" />
<tag name="exsyst_api_doc.routing_extractor" priority="-50" />
</service>
<service id="exsyst_api_doc.routing_extractors.php_doc" class="EXSyst\Bundle\ApiDocBundle\Extractor\Routing\PhpDocExtractor" public="false">
<tag name="exsyst_api_doc.routing_extractor" priority="-70" />
</service>
<service id="exsyst_api_doc.routing_extractors.nelmio_annotation" class="EXSyst\Bundle\ApiDocBundle\Extractor\Routing\NelmioAnnotationExtractor" public="false">
<argument type="service" id="annotation_reader" />
<tag name="exsyst_api_doc.routing_extractor" />
<tag name="exsyst_api_doc.routing_extractor" priority="-100" />
</service>
</services>

View File

@ -11,6 +11,7 @@
namespace EXSyst\Bundle\ApiDocBundle\Tests\Functional\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ApiController
@ -21,4 +22,26 @@ class ApiController
public function userAction()
{
}
/**
* @Route("/nelmio", methods={"POST"})
* @ApiDoc(
* description="This action is described."
* )
*/
public function nelmioAction()
{
}
/**
* This action is deprecated.
*
* Please do not use this action.
*
* @Route("/deprecated", methods={"GET"})
* @deprecated
*/
public function deprecatedAction()
{
}
}

View File

@ -15,18 +15,14 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class FunctionalTest extends WebTestCase
{
public function testUserActionApiController()
public function testUserAction()
{
$api = $this->getSwaggerDefinition();
$paths = $api->getPaths();
$this->assertTrue($paths->has('/test/{user}'));
$action = $paths->get('/test/{user}');
$this->assertTrue($action->hasOperation('get'));
$operation = $action->getOperation('get');
$operation = $this->getOperation('/test/{user}', 'get');
$this->assertEquals(['https'], $operation->getSchemes()->toArray());
$this->assertEmpty($operation->getSummary());
$this->assertEmpty($operation->getDescription());
$this->assertFalse($operation->getDeprecated());
$parameters = $operation->getParameters();
$this->assertTrue($parameters->search('user', 'path'));
@ -37,10 +33,40 @@ class FunctionalTest extends WebTestCase
$this->assertEquals('/foo/', $parameter->getFormat());
}
public function testNelmioAction()
{
$operation = $this->getOperation('/nelmio', 'post');
$this->assertEquals('This action is described.', $operation->getDescription());
$this->assertFalse($operation->getDeprecated());
}
public function testDeprecatedAction()
{
$operation = $this->getOperation('/deprecated', 'get');
$this->assertEquals('This action is deprecated.', $operation->getSummary());
$this->assertEquals('Please do not use this action.', $operation->getDescription());
$this->assertTrue($operation->getDeprecated());
}
private function getSwaggerDefinition()
{
static::createClient();
return static::$kernel->getContainer()->get('exsyst_api_doc.generator')->extract();
}
private function getOperation($path, $method)
{
$api = $this->getSwaggerDefinition();
$paths = $api->getPaths();
$this->assertTrue($paths->has($path));
$action = $paths->get($path);
$this->assertTrue($action->hasOperation($method));
return $action->getOperation($method);
}
}

View File

@ -17,10 +17,13 @@
"symfony/browser-kit": "~2.8|~3.0",
"symfony/phpunit-bridge": "^3.2@dev",
"sensio/framework-extra-bundle": "~3.0",
"nelmio/api-doc-bundle": "^2.0"
"nelmio/api-doc-bundle": "^2.0",
"phpdocumentor/reflection-docblock": "^3.1",
"phpunit/phpunit": "^5.4"
},
"suggest": {
"nelmio/api-doc-bundle": "For using the ApiDoc annotation."
"nelmio/api-doc-bundle": "For using the ApiDoc annotation.",
"phpdocumentor/reflection-docblock": "For parsing php docs."
},
"autoload": {
"psr-4": {