Merge branch '3.x'

This commit is contained in:
Guilhem Niot 2021-11-04 00:06:42 +01:00
commit 200ec0fdcb
6 changed files with 124 additions and 1 deletions

View File

@ -50,6 +50,7 @@ final class Configuration implements ConfigurationInterface
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
]
)
@ -90,6 +91,10 @@ final class Configuration implements ConfigurationInterface
->defaultFalse()
->info('whether to filter by annotation')
->end()
->booleanNode('disable_default_routes')
->defaultFalse()
->info('if set disables default routes without annotations')
->end()
->arrayNode('documentation')
->useAttributeAsKey('key')
->defaultValue([])

View File

@ -109,6 +109,7 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
&& 0 === count($areaConfig['host_patterns'])
&& 0 === count($areaConfig['name_patterns'])
&& false === $areaConfig['with_annotation']
&& false === $areaConfig['disable_default_routes']
) {
$container->setDefinition(sprintf('nelmio_api_doc.routes.%s', $area), $routesDefinition)
->setPublic(false);

View File

@ -137,7 +137,6 @@ A: We removed the google fonts in 3.3 to avoid the external request for GDPR rea
.. code-block:: twig
{# templates/bundles/NelmioApiDocBundle/SwaggerUi/index.html.twig #}
{#
To avoid a "reached nested level" error an exclamation mark `!` has to be added
See https://symfony.com/blog/new-in-symfony-3-4-improved-the-overriding-of-templates
@ -197,3 +196,17 @@ A: Use ``@OA\Tag`` annotation.
{
//...
}
Disable Default Section
-----------------------
Q: I don't want to render the "default" section, how do I do that?
A: Use ``disable_default_routes`` config in your area.
.. code-block:: yaml
nelmio_api_doc:
areas:
default:
disable_default_routes: true

View File

@ -45,11 +45,13 @@ final class FilteredRouteCollectionBuilder
'host_patterns' => [],
'name_patterns' => [],
'with_annotation' => false,
'disable_default_routes' => false,
])
->setAllowedTypes('path_patterns', 'string[]')
->setAllowedTypes('host_patterns', 'string[]')
->setAllowedTypes('name_patterns', 'string[]')
->setAllowedTypes('with_annotation', 'boolean')
->setAllowedTypes('disable_default_routes', 'boolean')
;
if (array_key_exists(0, $options)) {
@ -73,6 +75,7 @@ final class FilteredRouteCollectionBuilder
&& $this->matchHost($route)
&& $this->matchAnnotation($route)
&& $this->matchName($name)
&& $this->defaultRouteDisabled($route)
) {
$filteredRoutes->add($name, $route);
}
@ -138,4 +141,31 @@ final class FilteredRouteCollectionBuilder
return (null !== $areas) ? $areas->has($this->area) : false;
}
private function defaultRouteDisabled(Route $route): bool
{
if (false === $this->options['disable_default_routes']) {
return true;
}
$method = $this->controllerReflector->getReflectionMethod(
$route->getDefault('_controller') ?? ''
);
if (null === $method) {
return false;
}
$annotations = $this->annotationReader->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if (false !== strpos(get_class($annotation), 'Nelmio\\ApiDocBundle\\Annotation')
|| false !== strpos(get_class($annotation), 'OpenApi\\Annotations')
) {
return true;
}
}
return false;
}
}

View File

@ -29,6 +29,7 @@ class ConfigurationTest extends TestCase
'host_patterns' => [],
'name_patterns' => [],
'with_annotation' => false,
'disable_default_routes' => false,
'documentation' => [],
],
],
@ -46,6 +47,7 @@ class ConfigurationTest extends TestCase
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
'internal' => [
'path_patterns' => ['/internal'],
@ -53,6 +55,7 @@ class ConfigurationTest extends TestCase
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
'commercial' => [
'path_patterns' => ['/internal'],
@ -60,6 +63,7 @@ class ConfigurationTest extends TestCase
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
]]]);

View File

@ -14,9 +14,11 @@ namespace Nelmio\ApiDocBundle\Tests\Routing;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\Reader;
use Nelmio\ApiDocBundle\Annotation\Areas;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder;
use Nelmio\ApiDocBundle\Util\ControllerReflector;
use PHPUnit\Framework\TestCase;
use OpenApi\Annotations\Parameter;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException;
@ -246,6 +248,74 @@ class FilteredRouteCollectionBuilderTest extends TestCase
];
}
/**
* @dataProvider getRoutesWithDisabledDefaultRoutes
*
* @param array<Operation|Parameter> $annotations
* @param array<string|boolean> $options
*/
public function testRoutesWithDisabledDefaultRoutes(
string $name,
Route $route,
array $annotations,
array $options,
int $expectedRoutesCount
): void {
$routes = new RouteCollection();
$routes->add($name, $route);
$area = 'area';
$reflectionMethodStub = $this->createMock(\ReflectionMethod::class);
$controllerReflectorStub = $this->createMock(ControllerReflector::class);
$controllerReflectorStub->method('getReflectionMethod')->willReturn($reflectionMethodStub);
$annotationReader = $this->createMock(Reader::class);
$annotationReader
->method('getMethodAnnotations')
->willReturn($annotations)
;
$routeBuilder = new FilteredRouteCollectionBuilder(
$annotationReader,
$controllerReflectorStub,
$area,
$options
);
$filteredRoutes = $routeBuilder->filter($routes);
$this->assertCount($expectedRoutesCount, $filteredRoutes);
}
/**
* @return array<string,array>
*/
public function getRoutesWithDisabledDefaultRoutes(): array
{
return [
'non matching route without Annotation' => [
'r10',
new Route('/api/foo', ['_controller' => 'ApiController::fooAction']),
[],
['disable_default_routes' => true],
0,
],
'matching route with Nelmio Annotation' => [
'r10',
new Route('/api/foo', ['_controller' => 'ApiController::fooAction']),
[new Operation([])],
['disable_default_routes' => true],
1,
],
'matching route with Swagger Annotation' => [
'r10',
new Route('/api/foo', ['_controller' => 'ApiController::fooAction']),
[new Parameter([])],
['disable_default_routes' => true],
1,
],
];
}
private function createControllerReflector(): ControllerReflector
{
if (class_exists(ControllerNameParser::class)) {