mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-09 02:59:27 +03:00
Merge pull request #2 from EXSyst/FILTER_ROUTES
Allow to filter routes based on their path
This commit is contained in:
commit
9b82da1d85
@ -19,7 +19,21 @@ class Configuration implements ConfigurationInterface
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('exsyst_api_doc');
|
||||
$treeBuilder
|
||||
->root('exsyst_api_doc')
|
||||
->children()
|
||||
->arrayNode('routes')
|
||||
->info('Filter the routes that are documented')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->arrayNode('path_patterns')
|
||||
->example(array('^/api', '^/api(?!/admin)'))
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ class EXSystApiDocExtension extends Extension
|
||||
|
||||
$loader->load('services.xml');
|
||||
|
||||
// Filter routes
|
||||
$routeCollectionBuilder = $container->getDefinition('exsyst_api_doc.describers.route.filtered_route_collection_builder');
|
||||
$routeCollectionBuilder->replaceArgument(0, $config['routes']['path_patterns']);
|
||||
|
||||
// Import services needed for each library
|
||||
if (class_exists(ApiDoc::class)) {
|
||||
$loader->load('nelmio_apidoc.xml');
|
||||
|
@ -17,25 +17,25 @@ use EXSyst\Component\Swagger\Swagger;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class RouteDescriber implements DescriberInterface
|
||||
{
|
||||
private $container;
|
||||
private $router;
|
||||
private $routeCollection;
|
||||
private $controllerNameParser;
|
||||
private $routeDescribers;
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
* @param RouterInterface $router
|
||||
* @param RouteCollection $routeCollection
|
||||
* @param ControllerNameParser $controllerNameParser
|
||||
* @param RouteDescriberInterface[] $routeDescribers
|
||||
*/
|
||||
public function __construct(ContainerInterface $container, RouterInterface $router, ControllerNameParser $controllerNameParser, array $routeDescribers)
|
||||
public function __construct(ContainerInterface $container, RouteCollection $routeCollection, ControllerNameParser $controllerNameParser, array $routeDescribers)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->router = $router;
|
||||
$this->routeCollection = $routeCollection;
|
||||
$this->controllerNameParser = $controllerNameParser;
|
||||
$this->routeDescribers = $routeDescribers;
|
||||
}
|
||||
@ -46,7 +46,7 @@ class RouteDescriber implements DescriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getRoutes() as $route) {
|
||||
foreach ($this->routeCollection->all() as $route) {
|
||||
// if able to resolve the controller
|
||||
if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) {
|
||||
// Extract as many informations as possible about this route
|
||||
@ -57,16 +57,6 @@ class RouteDescriber implements DescriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of route to inspect.
|
||||
*
|
||||
* @return Route[] An array of routes
|
||||
*/
|
||||
private function getRoutes()
|
||||
{
|
||||
return $this->router->getRouteCollection()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ReflectionMethod for the given controller string.
|
||||
*
|
||||
|
@ -9,9 +9,23 @@
|
||||
</service>
|
||||
|
||||
<!-- Extractors -->
|
||||
<service id="exsyst_api_doc.describers.route.filtered_route_collection_builder" class="EXSyst\Bundle\ApiDocBundle\Routing\FilteredRouteCollectionBuilder" public="false">
|
||||
<argument type="collection" /> <!-- Path patterns -->
|
||||
</service>
|
||||
|
||||
|
||||
<service id="exsyst_api_doc.describers.route" class="EXSyst\Bundle\ApiDocBundle\Describer\RouteDescriber" public="false">
|
||||
<argument type="service" id="service_container" />
|
||||
<argument type="service" id="router" />
|
||||
<argument type="service">
|
||||
<service class="Symfony\Component\Routing\RouteCollection">
|
||||
<factory service="exsyst_api_doc.describers.route.filtered_route_collection_builder" method="filter" />
|
||||
<argument type="service">
|
||||
<service class="Symfony\Component\Routing\RouteCollection">
|
||||
<factory service="router" method="getRouteCollection" />
|
||||
</service>
|
||||
</argument>
|
||||
</service>
|
||||
</argument>
|
||||
<argument type="service" id="controller_name_converter" />
|
||||
<argument type="collection" />
|
||||
|
||||
|
48
Routing/FilteredRouteCollectionBuilder.php
Normal file
48
Routing/FilteredRouteCollectionBuilder.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the ApiDocBundle package.
|
||||
*
|
||||
* (c) EXSyst
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace EXSyst\Bundle\ApiDocBundle\Routing;
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
final class FilteredRouteCollectionBuilder
|
||||
{
|
||||
private $pathPatterns;
|
||||
|
||||
public function __construct(array $pathPatterns = [])
|
||||
{
|
||||
$this->pathPatterns = $pathPatterns;
|
||||
}
|
||||
|
||||
public function filter(RouteCollection $routes): RouteCollection
|
||||
{
|
||||
$filteredRoutes = new RouteCollection();
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
if ($this->match($route)) {
|
||||
$filteredRoutes->add($name, $route);
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredRoutes;
|
||||
}
|
||||
|
||||
private function match(Route $route): bool
|
||||
{
|
||||
foreach ($this->pathPatterns as $pathPattern) {
|
||||
if (!preg_match('{'.$pathPattern.'}', $route->getPath())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ namespace EXSyst\Bundle\ApiDocBundle\Tests\Functional\Controller;
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
|
||||
/**
|
||||
* @Route("/api")
|
||||
*/
|
||||
class ApiController
|
||||
{
|
||||
/**
|
||||
@ -45,4 +48,13 @@ class ApiController
|
||||
public function deprecatedAction()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This action is not documented. It is excluded by the config.
|
||||
*
|
||||
* @Route("/admin", methods={"GET"})
|
||||
*/
|
||||
public function adminAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
27
Tests/Functional/Controller/UndocumentedController.php
Normal file
27
Tests/Functional/Controller/UndocumentedController.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the ApiDocBundle package.
|
||||
*
|
||||
* (c) EXSyst
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace EXSyst\Bundle\ApiDocBundle\Tests\Functional\Controller;
|
||||
|
||||
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
|
||||
class UndocumentedController
|
||||
{
|
||||
/**
|
||||
* This path is excluded by the config (only /api allowed).
|
||||
*
|
||||
* @Route("/undocumented", methods={"GET"})
|
||||
*/
|
||||
public function undocumentedAction()
|
||||
{
|
||||
}
|
||||
}
|
@ -15,9 +15,16 @@ use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class FunctionalTest extends WebTestCase
|
||||
{
|
||||
public function testUndocumentedAction()
|
||||
{
|
||||
$paths = $this->getSwaggerDefinition()->getPaths();
|
||||
$this->assertFalse($paths->has('/undocumented'));
|
||||
$this->assertFalse($paths->has('/api/admin'));
|
||||
}
|
||||
|
||||
public function testUserAction()
|
||||
{
|
||||
$operation = $this->getOperation('/test/{user}', 'get');
|
||||
$operation = $this->getOperation('/api/test/{user}', 'get');
|
||||
|
||||
$this->assertEquals(['https'], $operation->getSchemes());
|
||||
$this->assertEmpty($operation->getSummary());
|
||||
@ -35,7 +42,7 @@ class FunctionalTest extends WebTestCase
|
||||
|
||||
public function testNelmioAction()
|
||||
{
|
||||
$operation = $this->getOperation('/nelmio/{foo}', 'post');
|
||||
$operation = $this->getOperation('/api/nelmio/{foo}', 'post');
|
||||
|
||||
$this->assertEquals('This action is described.', $operation->getDescription());
|
||||
$this->assertNull($operation->getDeprecated());
|
||||
@ -47,7 +54,7 @@ class FunctionalTest extends WebTestCase
|
||||
|
||||
public function testDeprecatedAction()
|
||||
{
|
||||
$operation = $this->getOperation('/deprecated', 'get');
|
||||
$operation = $this->getOperation('/api/deprecated', 'get');
|
||||
|
||||
$this->assertEquals('This action is deprecated.', $operation->getSummary());
|
||||
$this->assertEquals('Please do not use this action.', $operation->getDescription());
|
||||
|
@ -59,5 +59,12 @@ class TestKernel extends Kernel
|
||||
'test' => null,
|
||||
'validation' => null,
|
||||
]);
|
||||
|
||||
// Filter routes
|
||||
$c->loadFromExtension('exsyst_api_doc', [
|
||||
'routes' => [
|
||||
'path_patterns' => ['^/api(?!/admin)'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user