Skip to content

Commit

Permalink
[3.x]: Hide the default section per area with new config parameter (#…
Browse files Browse the repository at this point in the history
…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>
  • Loading branch information
Havrin and Frederik Holz committed Oct 6, 2021
1 parent 1306106 commit aa18c6c
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 0 deletions.
5 changes: 5 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public function getConfigTreeBuilder()
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
]
)
Expand Down Expand Up @@ -103,6 +104,10 @@ public function getConfigTreeBuilder()
->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([])
Expand Down
1 change: 1 addition & 0 deletions DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public function load(array $configs, ContainerBuilder $container)
&& 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);
Expand Down
14 changes: 14 additions & 0 deletions Resources/doc/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
30 changes: 30 additions & 0 deletions Routing/FilteredRouteCollectionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ public function __construct(
'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)) {
Expand All @@ -73,6 +75,7 @@ public function filter(RouteCollection $routes): RouteCollection
&& $this->matchHost($route)
&& $this->matchAnnotation($route)
&& $this->matchName($name)
&& $this->defaultRouteDisabled($route)
) {
$filteredRoutes->add($name, $route);
}
Expand Down Expand Up @@ -135,4 +138,31 @@ private function matchAnnotation(Route $route): bool

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;
}
}
5 changes: 5 additions & 0 deletions Tests/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function testDefaultArea()
'host_patterns' => [],
'name_patterns' => [],
'with_annotation' => false,
'disable_default_routes' => false,
'documentation' => [],
],
],
Expand All @@ -46,20 +47,23 @@ public function testAreas()
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
'internal' => [
'path_patterns' => ['/internal'],
'host_patterns' => ['^swagger\.'],
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
'commercial' => [
'path_patterns' => ['/internal'],
'host_patterns' => [],
'with_annotation' => false,
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
],
]]]);

Expand Down Expand Up @@ -173,6 +177,7 @@ public function testDefaultConfig()
'host_patterns' => [],
'name_patterns' => [],
'with_annotation' => false,
'disable_default_routes' => false,
'documentation' => [],
],
],
Expand Down
70 changes: 70 additions & 0 deletions Tests/Routing/FilteredRouteCollectionBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
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 Swagger\Annotations\Parameter;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Routing\Route;
Expand Down Expand Up @@ -245,6 +247,74 @@ public function getNonMatchingRoutes(): array
];
}

/**
* @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)) {
Expand Down

0 comments on commit aa18c6c

Please sign in to comment.