diff --git a/Describer/OpenApiPhpDescriber.php b/Describer/OpenApiPhpDescriber.php index 4f03918..96aad2d 100644 --- a/Describer/OpenApiPhpDescriber.php +++ b/Describer/OpenApiPhpDescriber.php @@ -47,7 +47,7 @@ final class OpenApiPhpDescriber $classAnnotations = []; /** @var \ReflectionMethod $method */ - foreach ($this->getMethodsToParse() as $method => list($path, $httpMethods)) { + foreach ($this->getMethodsToParse() as $method => list($path, $httpMethods, $routeName)) { $declaringClass = $method->getDeclaringClass(); $path = Util::getPath($api, $path); @@ -134,6 +134,10 @@ final class OpenApiPhpDescriber $operation = Util::getOperation($path, $httpMethod); $operation->merge($implicitAnnotations); $operation->mergeProperties($mergeProperties); + + if (OA\UNDEFINED === $operation->operationId) { + $operation->operationId = $httpMethod.'_'.$routeName; + } } } @@ -143,7 +147,7 @@ final class OpenApiPhpDescriber private function getMethodsToParse(): \Generator { - foreach ($this->routeCollection->all() as $route) { + foreach ($this->routeCollection->all() as $routeName => $route) { if (!$route->hasDefault('_controller')) { continue; } @@ -161,7 +165,7 @@ final class OpenApiPhpDescriber continue; } - yield $reflectedMethod => [$path, $supportedHttpMethods]; + yield $reflectedMethod => [$path, $supportedHttpMethods, $routeName]; } } diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 4a40897..69372d3 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -26,7 +26,7 @@ use OpenApi\Annotations as OA; use Symfony\Component\Routing\Annotation\Route; /** - * @Route("/api", host="api.example.com") + * @Route("/api", name="api_", host="api.example.com") */ class ApiController { @@ -232,4 +232,23 @@ class ApiController public function discriminatorMappingAction() { } + + /** + * @Route("/named_route-operation-id", name="named_route_operation_id", methods={"GET", "POST"}) + * + * @OA\Response(response=200, description="success") + */ + public function namedRouteOperationIdAction() + { + } + + /** + * @Route("/custom-operation-id", methods={"GET", "POST"}) + * + * @Operation(operationId="custom-operation-id") + * @OA\Response(response=200, description="success") + */ + public function customOperationIdAction() + { + } } diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 8b2b372..6094466 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -506,7 +506,25 @@ class FunctionalTest extends WebTestCase public function testDefaultOperationId() { $operation = $this->getOperation('/api/article/{id}', 'get'); - $this->assertNull($operation->operationId); + $this->assertEquals('get_api_nelmio_apidoc_tests_functional_api_fetcharticle', $operation->operationId); + } + + public function testNamedRouteOperationId() + { + $operation = $this->getOperation('/api/named_route-operation-id', 'get'); + $this->assertEquals('get_api_named_route_operation_id', $operation->operationId); + + $operation = $this->getOperation('/api/named_route-operation-id', 'post'); + $this->assertEquals('post_api_named_route_operation_id', $operation->operationId); + } + + public function testCustomOperationId() + { + $operation = $this->getOperation('/api/custom-operation-id', 'get'); + $this->assertEquals('custom-operation-id', $operation->operationId); + + $operation = $this->getOperation('/api/custom-operation-id', 'post'); + $this->assertEquals('custom-operation-id', $operation->operationId); } /**