diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2be8a0f..75f90ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,8 +6,8 @@ First of all, **thank you** for contributing, **you are awesome**! Here are a few rules to follow in order to ease code reviews, and discussions before maintainers accept and merge your work. -You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and -[PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of them, you +You MUST follow the [PSR-1](http://www.php-fig.org/psr/psr-1/) and +[PSR-2](http://www.php-fig.org/psr/psr-2/). If you don't know about any of them, you should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer tool](http://cs.sensiolabs.org/). diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 77af246..affdbb6 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -62,6 +62,7 @@ final class Configuration implements ConfigurationInterface 'host_patterns' => [], 'with_annotation' => false, 'documentation' => [], + 'name_patterns' => [], ], ] ) @@ -93,6 +94,11 @@ final class Configuration implements ConfigurationInterface ->example(['^api\.']) ->prototype('scalar')->end() ->end() + ->arrayNode('name_patterns') + ->defaultValue([]) + ->example(['^api_v1']) + ->prototype('scalar')->end() + ->end() ->booleanNode('with_annotation') ->defaultFalse() ->info('whether to filter by annotation') diff --git a/DependencyInjection/NelmioApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php index 0261496..5f7d749 100644 --- a/DependencyInjection/NelmioApiDocExtension.php +++ b/DependencyInjection/NelmioApiDocExtension.php @@ -103,6 +103,7 @@ final class NelmioApiDocExtension extends Extension implements PrependExtensionI unset($areaConfig['documentation']); if (0 === count($areaConfig['path_patterns']) && 0 === count($areaConfig['host_patterns']) + && 0 === count($areaConfig['name_patterns']) && false === $areaConfig['with_annotation'] ) { $container->setDefinition(sprintf('nelmio_api_doc.routes.%s', $area), $routesDefinition) diff --git a/Resources/doc/areas.rst b/Resources/doc/areas.rst index 390dd11..ed3d05a 100644 --- a/Resources/doc/areas.rst +++ b/Resources/doc/areas.rst @@ -9,6 +9,7 @@ We've already seen that you can configure which routes are documented using ``ne areas: path_patterns: [ ^/api ] host_patterns: [ ^api\. ] + name_patterns: [ ^api_v1 ] But in fact, this config option is way more powerful and allows you to split your documentation in several parts. diff --git a/Routing/FilteredRouteCollectionBuilder.php b/Routing/FilteredRouteCollectionBuilder.php index 4679e66..fb23807 100644 --- a/Routing/FilteredRouteCollectionBuilder.php +++ b/Routing/FilteredRouteCollectionBuilder.php @@ -43,10 +43,12 @@ final class FilteredRouteCollectionBuilder ->setDefaults([ 'path_patterns' => [], 'host_patterns' => [], + 'name_patterns' => [], 'with_annotation' => false, ]) ->setAllowedTypes('path_patterns', 'string[]') ->setAllowedTypes('host_patterns', 'string[]') + ->setAllowedTypes('name_patterns', 'string[]') ->setAllowedTypes('with_annotation', 'boolean') ; @@ -67,7 +69,11 @@ final class FilteredRouteCollectionBuilder { $filteredRoutes = new RouteCollection(); foreach ($routes->all() as $name => $route) { - if ($this->matchPath($route) && $this->matchHost($route) && $this->matchAnnotation($route)) { + if ($this->matchPath($route) + && $this->matchHost($route) + && $this->matchAnnotation($route) + && $this->matchName($name) + ) { $filteredRoutes->add($name, $route); } } @@ -97,6 +103,17 @@ final class FilteredRouteCollectionBuilder return 0 === count($this->options['host_patterns']); } + private function matchName(string $name): bool + { + foreach ($this->options['name_patterns'] as $namePattern) { + if (preg_match('{'.$namePattern.'}', $name)) { + return true; + } + } + + return 0 === count($this->options['name_patterns']); + } + private function matchAnnotation(Route $route): bool { if (false === $this->options['with_annotation']) { diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 068c984..5c9509b 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -27,6 +27,7 @@ class ConfigurationTest extends TestCase 'default' => [ 'path_patterns' => ['/foo'], 'host_patterns' => [], + 'name_patterns' => [], 'with_annotation' => false, 'documentation' => [], ], @@ -44,18 +45,21 @@ class ConfigurationTest extends TestCase 'host_patterns' => [], 'with_annotation' => false, 'documentation' => [], + 'name_patterns' => [], ], 'internal' => [ 'path_patterns' => ['/internal'], 'host_patterns' => ['^swagger\.'], 'with_annotation' => false, 'documentation' => [], + 'name_patterns' => [], ], 'commercial' => [ 'path_patterns' => ['/internal'], 'host_patterns' => [], 'with_annotation' => false, 'documentation' => [], + 'name_patterns' => [], ], ]]]); @@ -166,6 +170,7 @@ class ConfigurationTest extends TestCase 'default' => [ 'path_patterns' => ['/foo'], 'host_patterns' => [], + 'name_patterns' => [], 'with_annotation' => false, 'documentation' => [], ], diff --git a/Tests/Routing/FilteredRouteCollectionBuilderTest.php b/Tests/Routing/FilteredRouteCollectionBuilderTest.php index 8dfd8c0..8b2390a 100644 --- a/Tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/Tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -120,6 +120,11 @@ class FilteredRouteCollectionBuilderTest extends TestCase [['with_annotation' => ['an array']]], [['path_patterns' => 'a string']], [['path_patterns' => 11]], + [['name_patterns' => 22]], + [['name_patterns' => 'a string']], + [['name_patterns' => [22]]], + [['name_patterns' => [null]]], + [['name_patterns' => [new \stdClass()]]], ]; } @@ -167,7 +172,7 @@ class FilteredRouteCollectionBuilderTest extends TestCase ['r1', new Route('/api/bar/action1')], ['r2', new Route('/api/foo/action1'), ['path_patterns' => ['^/api', 'i/fo', 'n1$']]], ['r3', new Route('/api/foo/action2'), ['path_patterns' => ['^/api/foo/action2$']]], - ['r4', new Route('/api/demo'), ['path_patterns' => ['/api/demo']]], + ['r4', new Route('/api/demo'), ['path_patterns' => ['/api/demo'], 'name_patterns' => ['r4']]], ['r9', new Route('/api/bar/action1', [], [], [], 'api.example.com'), ['path_patterns' => ['^/api/'], 'host_patterns' => ['^api\.ex']]], ['r10', new Route('/api/areas/new'), ['path_patterns' => ['^/api']]], ]; @@ -247,7 +252,7 @@ class FilteredRouteCollectionBuilderTest extends TestCase { return [ ['r1', new Route('/api/bar/action1'), ['path_patterns' => ['^/apis']]], - ['r2', new Route('/api/foo/action1'), ['path_patterns' => ['^/apis', 'i/foo/b', 'n1/$']]], + ['r2', new Route('/api/foo/action1'), ['path_patterns' => ['^/apis', 'i/foo/b', 'n1/$'], 'name_patterns' => ['r2']]], ['r3_matching_path_and_non_matching_host', new Route('/api/foo/action2'), ['path_patterns' => ['^/api/foo/action2$'], 'host_patterns' => ['^api\.']]], ['r4_matching_path_and_non_matching_host', new Route('/api/bar/action1', [], [], [], 'www.example.com'), ['path_patterns' => ['^/api/'], 'host_patterns' => ['^api\.']]], ['r5_non_matching_path_and_matching_host', new Route('/admin/bar/action1', [], [], [], 'api.example.com'), ['path_patterns' => ['^/api/'], 'host_patterns' => ['^api\.']]],