mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-02 23:59:26 +03:00
[3.x]: Hide the default section per area with new config parameter (#1868)
* Add new config node disable_default_routes to prevent registering RouteDescriber to specific areas which allowes disabling rendering of default routes, Adjust tests accordingly * Add documentation for new config variable * Change disable_default_routes to filter route collection instead of disabling route describer, Add test for new handling in FilteredRouteCollectionBuilder * Change naming of matching method for disabling default routes * Fix codestyle issue * Fix codestyle issue * Change naming of dataProvider to match testing name Co-authored-by: Frederik Holz <team-orange@auxmoney.com>
This commit is contained in:
parent
1306106931
commit
aa18c6c83b
@ -63,6 +63,7 @@ final class Configuration implements ConfigurationInterface
|
|||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
|
'disable_default_routes' => false,
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -103,6 +104,10 @@ final class Configuration implements ConfigurationInterface
|
|||||||
->defaultFalse()
|
->defaultFalse()
|
||||||
->info('whether to filter by annotation')
|
->info('whether to filter by annotation')
|
||||||
->end()
|
->end()
|
||||||
|
->booleanNode('disable_default_routes')
|
||||||
|
->defaultFalse()
|
||||||
|
->info('if set disables default routes without annotations')
|
||||||
|
->end()
|
||||||
->arrayNode('documentation')
|
->arrayNode('documentation')
|
||||||
->useAttributeAsKey('key')
|
->useAttributeAsKey('key')
|
||||||
->defaultValue([])
|
->defaultValue([])
|
||||||
|
@ -106,6 +106,7 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI
|
|||||||
&& 0 === count($areaConfig['host_patterns'])
|
&& 0 === count($areaConfig['host_patterns'])
|
||||||
&& 0 === count($areaConfig['name_patterns'])
|
&& 0 === count($areaConfig['name_patterns'])
|
||||||
&& false === $areaConfig['with_annotation']
|
&& false === $areaConfig['with_annotation']
|
||||||
|
&& false === $areaConfig['disable_default_routes']
|
||||||
) {
|
) {
|
||||||
$container->setDefinition(sprintf('nelmio_api_doc.routes.%s', $area), $routesDefinition)
|
$container->setDefinition(sprintf('nelmio_api_doc.routes.%s', $area), $routesDefinition)
|
||||||
->setPublic(false);
|
->setPublic(false);
|
||||||
|
@ -197,3 +197,17 @@ A: Use ``@SWG\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
|
||||||
|
@ -45,11 +45,13 @@ final class FilteredRouteCollectionBuilder
|
|||||||
'host_patterns' => [],
|
'host_patterns' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
|
'disable_default_routes' => false,
|
||||||
])
|
])
|
||||||
->setAllowedTypes('path_patterns', 'string[]')
|
->setAllowedTypes('path_patterns', 'string[]')
|
||||||
->setAllowedTypes('host_patterns', 'string[]')
|
->setAllowedTypes('host_patterns', 'string[]')
|
||||||
->setAllowedTypes('name_patterns', 'string[]')
|
->setAllowedTypes('name_patterns', 'string[]')
|
||||||
->setAllowedTypes('with_annotation', 'boolean')
|
->setAllowedTypes('with_annotation', 'boolean')
|
||||||
|
->setAllowedTypes('disable_default_routes', 'boolean')
|
||||||
;
|
;
|
||||||
|
|
||||||
if (array_key_exists(0, $options)) {
|
if (array_key_exists(0, $options)) {
|
||||||
@ -73,6 +75,7 @@ final class FilteredRouteCollectionBuilder
|
|||||||
&& $this->matchHost($route)
|
&& $this->matchHost($route)
|
||||||
&& $this->matchAnnotation($route)
|
&& $this->matchAnnotation($route)
|
||||||
&& $this->matchName($name)
|
&& $this->matchName($name)
|
||||||
|
&& $this->defaultRouteDisabled($route)
|
||||||
) {
|
) {
|
||||||
$filteredRoutes->add($name, $route);
|
$filteredRoutes->add($name, $route);
|
||||||
}
|
}
|
||||||
@ -135,4 +138,31 @@ final class FilteredRouteCollectionBuilder
|
|||||||
|
|
||||||
return (null !== $areas) ? $areas->has($this->area) : false;
|
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), 'Swagger\\Annotations')
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'host_patterns' => [],
|
'host_patterns' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
|
'disable_default_routes' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -46,6 +47,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
|
'disable_default_routes' => false,
|
||||||
],
|
],
|
||||||
'internal' => [
|
'internal' => [
|
||||||
'path_patterns' => ['/internal'],
|
'path_patterns' => ['/internal'],
|
||||||
@ -53,6 +55,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
|
'disable_default_routes' => false,
|
||||||
],
|
],
|
||||||
'commercial' => [
|
'commercial' => [
|
||||||
'path_patterns' => ['/internal'],
|
'path_patterns' => ['/internal'],
|
||||||
@ -60,6 +63,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
|
'disable_default_routes' => false,
|
||||||
],
|
],
|
||||||
]]]);
|
]]]);
|
||||||
|
|
||||||
@ -173,6 +177,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'host_patterns' => [],
|
'host_patterns' => [],
|
||||||
'name_patterns' => [],
|
'name_patterns' => [],
|
||||||
'with_annotation' => false,
|
'with_annotation' => false,
|
||||||
|
'disable_default_routes' => false,
|
||||||
'documentation' => [],
|
'documentation' => [],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -14,9 +14,11 @@ namespace Nelmio\ApiDocBundle\Tests\Routing;
|
|||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
use Doctrine\Common\Annotations\Reader;
|
use Doctrine\Common\Annotations\Reader;
|
||||||
use Nelmio\ApiDocBundle\Annotation\Areas;
|
use Nelmio\ApiDocBundle\Annotation\Areas;
|
||||||
|
use Nelmio\ApiDocBundle\Annotation\Operation;
|
||||||
use Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder;
|
use Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder;
|
||||||
use Nelmio\ApiDocBundle\Util\ControllerReflector;
|
use Nelmio\ApiDocBundle\Util\ControllerReflector;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Swagger\Annotations\Parameter;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
||||||
use Symfony\Component\DependencyInjection\Container;
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
use Symfony\Component\Routing\Route;
|
use Symfony\Component\Routing\Route;
|
||||||
@ -245,6 +247,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
|
private function createControllerReflector(): ControllerReflector
|
||||||
{
|
{
|
||||||
if (class_exists(ControllerNameParser::class)) {
|
if (class_exists(ControllerNameParser::class)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user