Merge branch 'dev' into CONFIG

This commit is contained in:
Guilhem N 2017-02-07 19:14:35 +01:00 committed by GitHub
commit cde91cc38c
15 changed files with 79 additions and 166 deletions

View File

@ -22,7 +22,6 @@ final class Model extends AbstractAnnotation
public static $_parents = [
'Swagger\Annotations\Parameter',
'Swagger\Annotations\Response',
'Swagger\Annotations\Swagger',
];
public $type;

View File

@ -14,7 +14,10 @@ namespace Nelmio\ApiDocBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class AddDescribersPass implements CompilerPassInterface
/**
* @internal
*/
final class AddDescribersPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;

View File

@ -14,7 +14,10 @@ namespace Nelmio\ApiDocBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class AddRouteDescribersPass implements CompilerPassInterface
/**
* @internal
*/
final class AddRouteDescribersPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;

View File

@ -27,7 +27,6 @@ final class Configuration implements ConfigurationInterface
->example(['info' => ['title' => 'My App']])
->prototype('variable')->end()
->end()
->scalarNode('source_folder')->defaultValue('%kernel.root_dir%/../src')->end()
->arrayNode('routes')
->info('Filter the routes that are documented')
->addDefaultsIfNotSet()

View File

@ -17,10 +17,19 @@ use Swagger\Annotations\Swagger;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
final class NelmioApiDocExtension extends Extension
final class NelmioApiDocExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritdoc}
*/
public function prepend(ContainerBuilder $container)
{
$container->prependExtensionConfig('framework', ['property_info' => ['enabled' => true]]);
}
/**
* {@inheritdoc}
*/
@ -36,15 +45,10 @@ final class NelmioApiDocExtension extends Extension
$routeCollectionBuilder->replaceArgument(0, $config['routes']['path_patterns']);
// Import services needed for each library
$loader->load('swagger_php.xml');
if (class_exists(DocBlockFactory::class)) {
$loader->load('php_doc.xml');
}
if (class_exists(Swagger::class)) {
$loader->load('swagger_php.xml');
$swaggerPHPDescriber = $container->getDefinition('nelmio_api_doc.describers.swagger_php');
$swaggerPHPDescriber->replaceArgument(0, $config['source_folder']);
}
if (interface_exists(ParamInterface::class)) {
$loader->load('fos_rest.xml');
}

View File

@ -14,37 +14,59 @@ namespace Nelmio\ApiDocBundle\Describer;
use Nelmio\ApiDocBundle\SwaggerPhp\AddDefaults;
use Nelmio\ApiDocBundle\SwaggerPhp\ModelRegister;
use Nelmio\ApiDocBundle\SwaggerPhp\OperationResolver;
use Nelmio\ApiDocBundle\Util\ControllerReflector;
use Swagger\Analyser;
use Swagger\Analysis;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Routing\RouteCollection;
final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelRegistryAwareInterface
{
use ModelRegistryAwareTrait;
private $operationResolver;
private $routeCollection;
private $controllerReflector;
public function __construct(string $projectPath, bool $overwrite = false)
public function __construct(RouteCollection $routeCollection, ControllerReflector $controllerReflector, bool $overwrite = false)
{
$nelmioNamespace = 'Nelmio\\ApiDocBundle\\';
if (!in_array($nelmioNamespace, Analyser::$whitelist)) {
Analyser::$whitelist[] = $nelmioNamespace;
}
$this->routeCollection = $routeCollection;
$this->controllerReflector = $controllerReflector;
parent::__construct(function () use ($projectPath) {
$options = ['processors' => $this->getProcessors()];
$annotation = \Swagger\scan($projectPath, $options);
parent::__construct(function () {
$whitelist = Analyser::$whitelist;
Analyser::$whitelist = false;
try {
$options = ['processors' => $this->getProcessors()];
$annotation = \Swagger\scan($this->getFinder(), $options);
return json_decode(json_encode($annotation));
return json_decode(json_encode($annotation));
} finally {
Analyser::$whitelist = $whitelist;
}
}, $overwrite);
}
/**
* If set, the describer will try to complete paths and create
* implicit operations.
*/
public function setOperationResolver(OperationResolver $operationResolver)
private function getFinder()
{
$this->operationResolver = $operationResolver;
$files = [];
foreach ($this->routeCollection->all() as $route) {
if (!$route->hasDefault('_controller')) {
continue;
}
// if able to resolve the controller
$controller = $route->getDefault('_controller');
if ($callable = $this->controllerReflector->getReflectionClassAndMethod($controller)) {
list($class, $method) = $callable;
$files[$class->getFileName()] = true;
}
}
$finder = new Finder();
$finder->append(array_keys($files));
return $finder;
}
private function getProcessors(): array
@ -52,10 +74,8 @@ final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelReg
$processors = [
new AddDefaults(),
new ModelRegister($this->modelRegistry),
new OperationResolver($this->routeCollection, $this->controllerReflector),
];
if (null !== $this->operationResolver) {
$processors[] = $this->operationResolver;
}
return array_merge($processors, Analysis::processors());
}

View File

@ -1,45 +0,0 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddDescribersPass;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddModelDescribersPass;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\AddRouteDescribersPass;
use Nelmio\ApiDocBundle\DependencyInjection\EXSystApiDocExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
final class EXSystApiDocBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new AddDescribersPass());
$container->addCompilerPass(new AddRouteDescribersPass());
$container->addCompilerPass(new AddModelDescribersPass());
}
/**
* {@inheritdoc}
*/
public function getContainerExtension()
{
if (null === $this->extension) {
$this->extension = new EXSystApiDocExtension();
}
if ($this->extension) {
return $this->extension;
}
}
}

View File

@ -21,7 +21,7 @@ class ScalarModelDescriber implements ModelDescriberInterface
Type::BUILTIN_TYPE_INT => 'integer',
Type::BUILTIN_TYPE_FLOAT => 'float',
Type::BUILTIN_TYPE_STRING => 'string',
Type::BUILTIN_TYPE_BOOL => 'boolean'
Type::BUILTIN_TYPE_BOOL => 'boolean',
];
public function describe(Model $model, Schema $schema)

View File

@ -5,31 +5,15 @@
<services>
<service id="nelmio_api_doc.describers.swagger_php" class="Nelmio\ApiDocBundle\Describer\SwaggerPhpDescriber" public="false">
<argument>%kernel.root_dir%</argument>
<call method="setOperationResolver">
<argument type="service" id="nelmio_api_doc.describers.swagger_php.operation_resolver" />
</call>
<argument type="service">
<service class="Symfony\Component\Routing\RouteCollection">
<factory service="router" method="getRouteCollection" />
</service>
</argument>
<argument type="service" id="nelmio_api_doc.controller_reflector" />
<tag name="nelmio_api_doc.describer" priority="-200" />
</service>
<service id="nelmio_api_doc.describers.swagger_php.path_resolver" class="Nelmio\ApiDocBundle\SwaggerPhp\PathResolver" public="false">
<argument type="service">
<service class="Symfony\Component\Routing\RouteCollection">
<factory service="router" method="getRouteCollection" />
</service>
</argument>
<argument type="service" id="nelmio_api_doc.controller_reflector" />
</service>
<service id="nelmio_api_doc.describers.swagger_php.operation_resolver" class="Nelmio\ApiDocBundle\SwaggerPhp\OperationResolver" public="false">
<argument type="service">
<service class="Symfony\Component\Routing\RouteCollection">
<factory service="router" method="getRouteCollection" />
</service>
</argument>
<argument type="service" id="nelmio_api_doc.controller_reflector" />
</service>
</services>
</container>

View File

@ -1,34 +0,0 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Tests\Describer;
use EXSyst\Component\Swagger\Swagger;
use Nelmio\ApiDocBundle\Describer\SwaggerPhpDescriber;
use Nelmio\ApiDocBundle\Model\ModelRegistry;
class SwaggerPhpDescriberTest extends AbstractDescriberTest
{
public function testDescribe()
{
$api = $this->getSwaggerDoc();
$info = $api->getInfo();
$this->assertEquals('My Awesome App', $info->getTitle());
$this->assertEquals('1.3', $info->getVersion());
}
protected function setUp()
{
$this->describer = new SwaggerPhpDescriber(__DIR__.'/../Fixtures');
$this->describer->setModelRegistry(new ModelRegistry([], new Swagger()));
}
}

View File

@ -1,24 +0,0 @@
<?php
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Tests\Functional\Fixtures\SwaggerPhp;
use Swagger\Annotations\Info;
/**
* @Info(
* title="My Awesome App",
* version="1.3"
* )
*/
class Api
{
}

View File

@ -13,9 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\Annotations\RequestParam;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\Dummy;
use Nelmio\ApiDocBundle\Tests\Functional\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Swagger\Annotations as SWG;
@ -41,7 +39,7 @@ class ApiController
* @SWG\Response(
* response="201",
* description="Operation automatically detected",
* @Model(type="Nelmio\ApiDocBundle\Tests\Functional\Entity\User")
* @Model(type=User::class)
* )
* @SWG\Parameter(
* name="foo",
@ -49,7 +47,7 @@ class ApiController
* description="This is a parameter",
* @SWG\Schema(
* type="array",
* @Model(type="Nelmio\ApiDocBundle\Tests\Functional\Entity\User")
* @Model(type=User::class)
* )
* )
*/

View File

@ -67,8 +67,7 @@ class TestKernel extends Kernel
'title' => 'My Test App',
],
],
'source_folder' => '%kernel.root_dir%',
'routes' => [
'routes' => [
'path_patterns' => ['^/api(?!/admin)'],
],
]);

View File

@ -22,6 +22,8 @@ final class ControllerReflector
private $container;
private $controllerNameParser;
private $controllers = [];
public function __construct(ContainerInterface $container, ControllerNameParser $controllerNameParser)
{
$this->container = $container;
@ -69,6 +71,10 @@ final class ControllerReflector
private function getClassAndMethod(string $controller)
{
if (isset($this->controllers[$controller])) {
return $this->controllers[$controller];
}
if (false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
$controller = $this->controllerNameParser->parse($controller);
}
@ -98,9 +104,11 @@ final class ControllerReflector
}
if (!isset($class) || !isset($method)) {
$this->controllers[$controller] = null;
return;
}
return [$class, $method];
return $this->controllers[$controller] = [$class, $method];
}
}

View File

@ -18,7 +18,8 @@
"php": "~7.0|~7.1",
"symfony/framework-bundle": "^2.8|^3.0",
"symfony/property-info": "^2.8|^3.0",
"exsyst/swagger": "~0.2.3"
"exsyst/swagger": "~0.2.3",
"zircote/swagger-php": "dev-master"
},
"require-dev": {
"symfony/twig-bundle": "^2.8|^3.0",
@ -34,13 +35,11 @@
"doctrine/annotations": "^1.2",
"phpdocumentor/reflection-docblock": "^3.1",
"zircote/swagger-php": "^2.0",
"api-platform/core": "^2.0",
"friendsofsymfony/rest-bundle": "^2.0"
},
"suggest": {
"phpdocumentor/reflection-docblock": "For parsing php docs.",
"zircote/swagger-php": "For using swagger annotations.",
"api-platform/core": "For using an API oriented framework.",
"friendsofsymfony/rest-bundle": "For using the parameters annotations."
},