Skip to content

Commit

Permalink
feat: add arrays of enums and enum callbacks for query params (#2096)
Browse files Browse the repository at this point in the history
This adds support for the `callback` option in Choice constraint in
QueryParams to allow providing enum choices at runtime. Also adds
support for arrays of enums using the `multiple` QueryParam option.

---------

Co-authored-by: indexxd <[email protected]>
Co-authored-by: Djordy Koert <[email protected]>
  • Loading branch information
3 people authored Jun 19, 2024
1 parent 8f43de5 commit d590880
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/RouteDescriber/FosRestDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
}
}
}

Expand Down
53 changes: 53 additions & 0 deletions tests/RouteDescriber/FosRestDescriberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit d590880

Please sign in to comment.