diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index 0b5d88e..ae2fc06 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -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;
}
diff --git a/DependencyInjection/EXSystApiDocExtension.php b/DependencyInjection/EXSystApiDocExtension.php
index 87758eb..22f4eb4 100644
--- a/DependencyInjection/EXSystApiDocExtension.php
+++ b/DependencyInjection/EXSystApiDocExtension.php
@@ -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');
diff --git a/Describer/RouteDescriber.php b/Describer/RouteDescriber.php
index f8e884e..2e67430 100644
--- a/Describer/RouteDescriber.php
+++ b/Describer/RouteDescriber.php
@@ -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.
*
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index c352ee3..378ff9f 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -9,9 +9,23 @@
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/Routing/FilteredRouteCollectionBuilder.php b/Routing/FilteredRouteCollectionBuilder.php
new file mode 100644
index 0000000..835d750
--- /dev/null
+++ b/Routing/FilteredRouteCollectionBuilder.php
@@ -0,0 +1,48 @@
+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;
+ }
+}
diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php
index 8fd84d8..4c50fc2 100644
--- a/Tests/Functional/Controller/ApiController.php
+++ b/Tests/Functional/Controller/ApiController.php
@@ -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()
+ {
+ }
}
diff --git a/Tests/Functional/Controller/UndocumentedController.php b/Tests/Functional/Controller/UndocumentedController.php
new file mode 100644
index 0000000..e0a2c5d
--- /dev/null
+++ b/Tests/Functional/Controller/UndocumentedController.php
@@ -0,0 +1,27 @@
+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());
diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php
index 7b7b110..621becd 100644
--- a/Tests/Functional/TestKernel.php
+++ b/Tests/Functional/TestKernel.php
@@ -59,5 +59,12 @@ class TestKernel extends Kernel
'test' => null,
'validation' => null,
]);
+
+ // Filter routes
+ $c->loadFromExtension('exsyst_api_doc', [
+ 'routes' => [
+ 'path_patterns' => ['^/api(?!/admin)'],
+ ],
+ ]);
}
}