Skip to content

Commit c840214

Browse files
committed
fix(openapi): properly document list parameters
fixes #7657
1 parent 39c5583 commit c840214

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/Doctrine/Common/Filter/OpenApiFilterTrait.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,12 @@ trait OpenApiFilterTrait
2424
public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null
2525
{
2626
$schema = $parameter->getSchema();
27-
$isArraySchema = 'array' === ($schema['type'] ?? null);
28-
$castToArray = $parameter->getCastToArray();
29-
30-
// Use non-array notation if:
31-
// 1. Schema type is explicitly set to a non-array type (string, number, etc.)
32-
// 2. OR castToArray is explicitly false
33-
$hasNonArraySchema = null !== $schema && !$isArraySchema;
34-
35-
if ($hasNonArraySchema || false === $castToArray) {
27+
if (false === $parameter->getCastToArray() || (isset($schema['type']) && 'array' !== $schema['type'])) {
3628
return new OpenApiParameter(name: $parameter->getKey(), in: 'query');
3729
}
3830

39-
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);
31+
$arraySchema = ['type' => 'array', 'items' => $schema ?? ['type' => 'string']];
32+
33+
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true, schema: $arraySchema);
4034
}
4135
}

tests/Fixtures/TestBundle/Entity/ProductWithQueryParameter.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
property: 'category',
5757
castToArray: false
5858
),
59+
'tags' => new QueryParameter(
60+
filter: new ExactFilter(),
61+
property: 'tags',
62+
schema: ['anyOf' => [['type' => 'array', 'items' => ['type' => 'string']], ['type' => 'string']]]
63+
),
5964
]
6065
),
6166
]

tests/Functional/Parameters/DoctrineTest.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ private function loadProductFixtures(string $resourceClass): void
302302
}
303303

304304
#[DataProvider('openApiParameterDocumentationProvider')]
305-
public function testOpenApiParameterDocumentation(string $parameterName, bool $shouldHaveArrayNotation, string $expectedStyle, bool $expectedExplode, ?string $expectedSchemaType = null, string $expectedDescription = ''): void
305+
public function testOpenApiParameterDocumentation(string $parameterName, bool $shouldHaveArrayNotation, string $expectedStyle, bool $expectedExplode, ?string $expectedSchemaType = null, string $expectedDescription = '', ?array $expectedSchema = null): void
306306
{
307307
if ($this->isMongoDB()) {
308308
$this->markTestSkipped('Not tested with mongodb.');
@@ -342,6 +342,11 @@ public function testOpenApiParameterDocumentation(string $parameterName, bool $s
342342
if (isset($foundParameter['expectedDescription'])) {
343343
$this->assertSame($expectedDescription, $foundParameter['description'] ?? '', \sprintf('Description should be %s', $expectedDescription));
344344
}
345+
346+
if ($expectedSchema) {
347+
$this->assertSame($expectedSchema, $foundParameter['schema'], 'Parameter schema should match expected schema');
348+
}
349+
345350
$this->assertSame($expectedStyle, $foundParameter['style'] ?? 'form', \sprintf('Style should be %s', $expectedStyle));
346351
$this->assertSame($expectedExplode, $foundParameter['explode'] ?? false, \sprintf('Explode should be %s', $expectedExplode ? 'true' : 'false'));
347352
}
@@ -354,7 +359,8 @@ public static function openApiParameterDocumentationProvider(): array
354359
'shouldHaveArrayNotation' => true,
355360
'expectedStyle' => 'deepObject',
356361
'expectedExplode' => true,
357-
'expectedSchemaType' => 'string',
362+
'expectedSchemaType' => null,
363+
'expectedSchema' => ['type' => 'array', 'items' => ['type' => 'string']],
358364
],
359365
'default behavior with an extra description' => [
360366
'parameterName' => 'brandWithDescription',
@@ -370,13 +376,23 @@ public static function openApiParameterDocumentationProvider(): array
370376
'expectedStyle' => 'form',
371377
'expectedExplode' => false,
372378
'expectedSchemaType' => 'string',
379+
'expectedSchema' => null,
373380
],
374381
'castToArray false should not use array notation' => [
375382
'parameterName' => 'exactCategory',
376383
'shouldHaveArrayNotation' => false,
377384
'expectedStyle' => 'form',
378385
'expectedExplode' => false,
379386
'expectedSchemaType' => 'string',
387+
'expectedSchema' => null,
388+
],
389+
'with schema and default castToArray should wrap schema in array type' => [
390+
'parameterName' => 'tags',
391+
'shouldHaveArrayNotation' => true,
392+
'expectedStyle' => 'deepObject',
393+
'expectedExplode' => true,
394+
'expectedSchemaType' => null,
395+
'expectedSchema' => ['type' => 'array', 'items' => ['anyOf' => [['type' => 'array', 'items' => ['type' => 'string']], ['type' => 'string']]]],
380396
],
381397
];
382398
}

0 commit comments

Comments
 (0)