diff --git a/src/RouteDescriber/FosRestDescriber.php b/src/RouteDescriber/FosRestDescriber.php index 3ee28847d..2c6df5451 100644 --- a/src/RouteDescriber/FosRestDescriber.php +++ b/src/RouteDescriber/FosRestDescriber.php @@ -149,6 +149,14 @@ private function getFormat($requirements): ?string private function getEnum($requirements): ?array { if ($requirements instanceof Choice) { + if (null != $requirements->callback) { + if (!\is_callable($choices = $requirements->callback)) { + return null; + } + + return $choices(); + } + return $requirements->choices; } @@ -217,7 +225,14 @@ private function describeCommonSchemaFromAnnotation(OA\Schema $schema, AbstractS $enum = $this->getEnum($annotation->requirements); if (null !== $enum) { - $schema->enum = $enum; + if ($annotation->requirements instanceof Choice) { + if ($annotation->requirements->multiple) { + $schema->type = 'array'; + $schema->items = Util::createChild($schema, OA\Items::class, ['type' => 'string', 'enum' => $enum]); + } else { + $schema->enum = $enum; + } + } } } diff --git a/tests/RouteDescriber/FosRestDescriberTest.php b/tests/RouteDescriber/FosRestDescriberTest.php index 51da37a65..65c3c91b3 100644 --- a/tests/RouteDescriber/FosRestDescriberTest.php +++ b/tests/RouteDescriber/FosRestDescriberTest.php @@ -47,4 +47,57 @@ public function testQueryParamWithChoiceConstraintIsAddedAsEnum(): void self::assertSame($choices, $api->paths[0]->get->parameters[0]->schema->enum); } + + public function testQueryParamWithChoiceConstraintCallbackIsAddedAsEnum(): void + { + $queryParam = new QueryParam(); + $choice = new Choice(); + $choice->callback = function () { + return ['foo', 'bar']; + }; + + $queryParam->requirements = $choice; + $readerMock = $this->createMock(Reader::class); + $readerMock->method('getMethodAnnotations')->willReturn([ + $queryParam, + ]); + + $fosRestDescriber = new FosRestDescriber($readerMock, []); + $api = new OpenApi([]); + + $fosRestDescriber->describe( + $api, + new Route('/'), + $this->createMock(\ReflectionMethod::class) + ); + + self::assertSame(['foo', 'bar'], $api->paths[0]->get->parameters[0]->schema->enum); + } + + public function testQueryParamWithChoiceConstraintAsArray(): void + { + $choices = ['foo', 'bar']; + + $queryParam = new QueryParam(); + $choice = new Choice($choices); + $choice->multiple = true; + $queryParam->requirements = $choice; + + $readerMock = $this->createMock(Reader::class); + $readerMock->method('getMethodAnnotations')->willReturn([ + $queryParam, + ]); + + $fosRestDescriber = new FosRestDescriber($readerMock, []); + $api = new OpenApi([]); + + $fosRestDescriber->describe( + $api, + new Route('/'), + $this->createMock(\ReflectionMethod::class) + ); + + self::assertEquals('array', $api->paths[0]->get->parameters[0]->schema->type); + self::assertSame($choices, $api->paths[0]->get->parameters[0]->schema->items->enum); + } }