mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-02 23:59:26 +03:00
Merge branch 'dev' into CONFIG
This commit is contained in:
commit
cde91cc38c
@ -22,7 +22,6 @@ final class Model extends AbstractAnnotation
|
|||||||
public static $_parents = [
|
public static $_parents = [
|
||||||
'Swagger\Annotations\Parameter',
|
'Swagger\Annotations\Parameter',
|
||||||
'Swagger\Annotations\Response',
|
'Swagger\Annotations\Response',
|
||||||
'Swagger\Annotations\Swagger',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public $type;
|
public $type;
|
||||||
|
@ -14,7 +14,10 @@ namespace Nelmio\ApiDocBundle\DependencyInjection\Compiler;
|
|||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
|
||||||
class AddDescribersPass implements CompilerPassInterface
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class AddDescribersPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
use PriorityTaggedServiceTrait;
|
use PriorityTaggedServiceTrait;
|
||||||
|
|
||||||
|
@ -14,7 +14,10 @@ namespace Nelmio\ApiDocBundle\DependencyInjection\Compiler;
|
|||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
|
||||||
class AddRouteDescribersPass implements CompilerPassInterface
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class AddRouteDescribersPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
use PriorityTaggedServiceTrait;
|
use PriorityTaggedServiceTrait;
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ final class Configuration implements ConfigurationInterface
|
|||||||
->example(['info' => ['title' => 'My App']])
|
->example(['info' => ['title' => 'My App']])
|
||||||
->prototype('variable')->end()
|
->prototype('variable')->end()
|
||||||
->end()
|
->end()
|
||||||
->scalarNode('source_folder')->defaultValue('%kernel.root_dir%/../src')->end()
|
|
||||||
->arrayNode('routes')
|
->arrayNode('routes')
|
||||||
->info('Filter the routes that are documented')
|
->info('Filter the routes that are documented')
|
||||||
->addDefaultsIfNotSet()
|
->addDefaultsIfNotSet()
|
||||||
|
@ -17,10 +17,19 @@ use Swagger\Annotations\Swagger;
|
|||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\Config\FileLocator;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||||
|
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
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}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -36,15 +45,10 @@ final class NelmioApiDocExtension extends Extension
|
|||||||
$routeCollectionBuilder->replaceArgument(0, $config['routes']['path_patterns']);
|
$routeCollectionBuilder->replaceArgument(0, $config['routes']['path_patterns']);
|
||||||
|
|
||||||
// Import services needed for each library
|
// Import services needed for each library
|
||||||
|
$loader->load('swagger_php.xml');
|
||||||
if (class_exists(DocBlockFactory::class)) {
|
if (class_exists(DocBlockFactory::class)) {
|
||||||
$loader->load('php_doc.xml');
|
$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)) {
|
if (interface_exists(ParamInterface::class)) {
|
||||||
$loader->load('fos_rest.xml');
|
$loader->load('fos_rest.xml');
|
||||||
}
|
}
|
||||||
|
@ -14,37 +14,59 @@ namespace Nelmio\ApiDocBundle\Describer;
|
|||||||
use Nelmio\ApiDocBundle\SwaggerPhp\AddDefaults;
|
use Nelmio\ApiDocBundle\SwaggerPhp\AddDefaults;
|
||||||
use Nelmio\ApiDocBundle\SwaggerPhp\ModelRegister;
|
use Nelmio\ApiDocBundle\SwaggerPhp\ModelRegister;
|
||||||
use Nelmio\ApiDocBundle\SwaggerPhp\OperationResolver;
|
use Nelmio\ApiDocBundle\SwaggerPhp\OperationResolver;
|
||||||
|
use Nelmio\ApiDocBundle\Util\ControllerReflector;
|
||||||
use Swagger\Analyser;
|
use Swagger\Analyser;
|
||||||
use Swagger\Analysis;
|
use Swagger\Analysis;
|
||||||
|
use Symfony\Component\Finder\Finder;
|
||||||
|
use Symfony\Component\Routing\RouteCollection;
|
||||||
|
|
||||||
final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelRegistryAwareInterface
|
final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelRegistryAwareInterface
|
||||||
{
|
{
|
||||||
use ModelRegistryAwareTrait;
|
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\\';
|
$this->routeCollection = $routeCollection;
|
||||||
if (!in_array($nelmioNamespace, Analyser::$whitelist)) {
|
$this->controllerReflector = $controllerReflector;
|
||||||
Analyser::$whitelist[] = $nelmioNamespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct(function () use ($projectPath) {
|
parent::__construct(function () {
|
||||||
|
$whitelist = Analyser::$whitelist;
|
||||||
|
Analyser::$whitelist = false;
|
||||||
|
try {
|
||||||
$options = ['processors' => $this->getProcessors()];
|
$options = ['processors' => $this->getProcessors()];
|
||||||
$annotation = \Swagger\scan($projectPath, $options);
|
$annotation = \Swagger\scan($this->getFinder(), $options);
|
||||||
|
|
||||||
return json_decode(json_encode($annotation));
|
return json_decode(json_encode($annotation));
|
||||||
|
} finally {
|
||||||
|
Analyser::$whitelist = $whitelist;
|
||||||
|
}
|
||||||
}, $overwrite);
|
}, $overwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getFinder()
|
||||||
* If set, the describer will try to complete paths and create
|
|
||||||
* implicit operations.
|
|
||||||
*/
|
|
||||||
public function setOperationResolver(OperationResolver $operationResolver)
|
|
||||||
{
|
{
|
||||||
$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
|
private function getProcessors(): array
|
||||||
@ -52,10 +74,8 @@ final class SwaggerPhpDescriber extends ExternalDocDescriber implements ModelReg
|
|||||||
$processors = [
|
$processors = [
|
||||||
new AddDefaults(),
|
new AddDefaults(),
|
||||||
new ModelRegister($this->modelRegistry),
|
new ModelRegister($this->modelRegistry),
|
||||||
|
new OperationResolver($this->routeCollection, $this->controllerReflector),
|
||||||
];
|
];
|
||||||
if (null !== $this->operationResolver) {
|
|
||||||
$processors[] = $this->operationResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_merge($processors, Analysis::processors());
|
return array_merge($processors, Analysis::processors());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,7 +21,7 @@ class ScalarModelDescriber implements ModelDescriberInterface
|
|||||||
Type::BUILTIN_TYPE_INT => 'integer',
|
Type::BUILTIN_TYPE_INT => 'integer',
|
||||||
Type::BUILTIN_TYPE_FLOAT => 'float',
|
Type::BUILTIN_TYPE_FLOAT => 'float',
|
||||||
Type::BUILTIN_TYPE_STRING => 'string',
|
Type::BUILTIN_TYPE_STRING => 'string',
|
||||||
Type::BUILTIN_TYPE_BOOL => 'boolean'
|
Type::BUILTIN_TYPE_BOOL => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function describe(Model $model, Schema $schema)
|
public function describe(Model $model, Schema $schema)
|
||||||
|
@ -5,31 +5,15 @@
|
|||||||
|
|
||||||
<services>
|
<services>
|
||||||
<service id="nelmio_api_doc.describers.swagger_php" class="Nelmio\ApiDocBundle\Describer\SwaggerPhpDescriber" public="false">
|
<service id="nelmio_api_doc.describers.swagger_php" class="Nelmio\ApiDocBundle\Describer\SwaggerPhpDescriber" public="false">
|
||||||
<argument>%kernel.root_dir%</argument>
|
<argument type="service">
|
||||||
<call method="setOperationResolver">
|
<service class="Symfony\Component\Routing\RouteCollection">
|
||||||
<argument type="service" id="nelmio_api_doc.describers.swagger_php.operation_resolver" />
|
<factory service="router" method="getRouteCollection" />
|
||||||
</call>
|
</service>
|
||||||
|
</argument>
|
||||||
|
<argument type="service" id="nelmio_api_doc.controller_reflector" />
|
||||||
|
|
||||||
<tag name="nelmio_api_doc.describer" priority="-200" />
|
<tag name="nelmio_api_doc.describer" priority="-200" />
|
||||||
</service>
|
</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>
|
</services>
|
||||||
|
|
||||||
</container>
|
</container>
|
||||||
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -13,9 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller;
|
|||||||
|
|
||||||
use FOS\RestBundle\Controller\Annotations\QueryParam;
|
use FOS\RestBundle\Controller\Annotations\QueryParam;
|
||||||
use FOS\RestBundle\Controller\Annotations\RequestParam;
|
use FOS\RestBundle\Controller\Annotations\RequestParam;
|
||||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
|
||||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\Dummy;
|
|
||||||
use Nelmio\ApiDocBundle\Tests\Functional\Entity\User;
|
use Nelmio\ApiDocBundle\Tests\Functional\Entity\User;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||||
use Swagger\Annotations as SWG;
|
use Swagger\Annotations as SWG;
|
||||||
@ -41,7 +39,7 @@ class ApiController
|
|||||||
* @SWG\Response(
|
* @SWG\Response(
|
||||||
* response="201",
|
* response="201",
|
||||||
* description="Operation automatically detected",
|
* description="Operation automatically detected",
|
||||||
* @Model(type="Nelmio\ApiDocBundle\Tests\Functional\Entity\User")
|
* @Model(type=User::class)
|
||||||
* )
|
* )
|
||||||
* @SWG\Parameter(
|
* @SWG\Parameter(
|
||||||
* name="foo",
|
* name="foo",
|
||||||
@ -49,7 +47,7 @@ class ApiController
|
|||||||
* description="This is a parameter",
|
* description="This is a parameter",
|
||||||
* @SWG\Schema(
|
* @SWG\Schema(
|
||||||
* type="array",
|
* type="array",
|
||||||
* @Model(type="Nelmio\ApiDocBundle\Tests\Functional\Entity\User")
|
* @Model(type=User::class)
|
||||||
* )
|
* )
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
|
@ -67,7 +67,6 @@ class TestKernel extends Kernel
|
|||||||
'title' => 'My Test App',
|
'title' => 'My Test App',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'source_folder' => '%kernel.root_dir%',
|
|
||||||
'routes' => [
|
'routes' => [
|
||||||
'path_patterns' => ['^/api(?!/admin)'],
|
'path_patterns' => ['^/api(?!/admin)'],
|
||||||
],
|
],
|
||||||
|
@ -22,6 +22,8 @@ final class ControllerReflector
|
|||||||
private $container;
|
private $container;
|
||||||
private $controllerNameParser;
|
private $controllerNameParser;
|
||||||
|
|
||||||
|
private $controllers = [];
|
||||||
|
|
||||||
public function __construct(ContainerInterface $container, ControllerNameParser $controllerNameParser)
|
public function __construct(ContainerInterface $container, ControllerNameParser $controllerNameParser)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
@ -69,6 +71,10 @@ final class ControllerReflector
|
|||||||
|
|
||||||
private function getClassAndMethod(string $controller)
|
private function getClassAndMethod(string $controller)
|
||||||
{
|
{
|
||||||
|
if (isset($this->controllers[$controller])) {
|
||||||
|
return $this->controllers[$controller];
|
||||||
|
}
|
||||||
|
|
||||||
if (false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
|
if (false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
|
||||||
$controller = $this->controllerNameParser->parse($controller);
|
$controller = $this->controllerNameParser->parse($controller);
|
||||||
}
|
}
|
||||||
@ -98,9 +104,11 @@ final class ControllerReflector
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($class) || !isset($method)) {
|
if (!isset($class) || !isset($method)) {
|
||||||
|
$this->controllers[$controller] = null;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [$class, $method];
|
return $this->controllers[$controller] = [$class, $method];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"php": "~7.0|~7.1",
|
"php": "~7.0|~7.1",
|
||||||
"symfony/framework-bundle": "^2.8|^3.0",
|
"symfony/framework-bundle": "^2.8|^3.0",
|
||||||
"symfony/property-info": "^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": {
|
"require-dev": {
|
||||||
"symfony/twig-bundle": "^2.8|^3.0",
|
"symfony/twig-bundle": "^2.8|^3.0",
|
||||||
@ -34,13 +35,11 @@
|
|||||||
"doctrine/annotations": "^1.2",
|
"doctrine/annotations": "^1.2",
|
||||||
|
|
||||||
"phpdocumentor/reflection-docblock": "^3.1",
|
"phpdocumentor/reflection-docblock": "^3.1",
|
||||||
"zircote/swagger-php": "^2.0",
|
|
||||||
"api-platform/core": "^2.0",
|
"api-platform/core": "^2.0",
|
||||||
"friendsofsymfony/rest-bundle": "^2.0"
|
"friendsofsymfony/rest-bundle": "^2.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"phpdocumentor/reflection-docblock": "For parsing php docs.",
|
"phpdocumentor/reflection-docblock": "For parsing php docs.",
|
||||||
"zircote/swagger-php": "For using swagger annotations.",
|
|
||||||
"api-platform/core": "For using an API oriented framework.",
|
"api-platform/core": "For using an API oriented framework.",
|
||||||
"friendsofsymfony/rest-bundle": "For using the parameters annotations."
|
"friendsofsymfony/rest-bundle": "For using the parameters annotations."
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user