Skip to content

Commit 860bbed

Browse files
committed
Returns open api parameters according to schema
1 parent 42b759e commit 860bbed

File tree

3 files changed

+323
-7
lines changed

3 files changed

+323
-7
lines changed

src/Doctrine/Orm/Filter/AbstractUuidFilter.php

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,38 @@ public function getOpenApiParameters(Parameter $parameter): array
172172
{
173173
$in = $parameter instanceof QueryParameter ? 'query' : 'header';
174174
$key = $parameter->getKey();
175+
$schema = $parameter->getSchema();
176+
$addStringParam = false;
177+
$addArrayParam = false;
178+
$openApiParameters = [];
179+
180+
if (null === $schema) {
181+
$addStringParam = true;
182+
$addArrayParam = true;
183+
}
175184

176-
return [
177-
new OpenApiParameter(
185+
foreach ($schema['oneOf'] ?? [$schema] as $item) {
186+
if (!isset($item['type']) || 'string' === $item['type']) {
187+
$addStringParam = true;
188+
}
189+
190+
if (!isset($item['type']) || 'array' === $item['type']) {
191+
$addArrayParam = true;
192+
}
193+
}
194+
195+
if ($addStringParam) {
196+
$openApiParameters[] = new OpenApiParameter(
178197
name: $key,
179198
in: $in,
180199
schema: self::UUID_SCHEMA,
181200
style: 'form',
182201
explode: false
183-
),
184-
new OpenApiParameter(
202+
);
203+
}
204+
205+
if ($addArrayParam) {
206+
$openApiParameters[] = new OpenApiParameter(
185207
name: $key.'[]',
186208
in: $in,
187209
description: 'One or more Uuids',
@@ -191,12 +213,26 @@ public function getOpenApiParameters(Parameter $parameter): array
191213
],
192214
style: 'deepObject',
193215
explode: true
194-
),
195-
];
216+
);
217+
}
218+
219+
return $openApiParameters;
196220
}
197221

198222
public function getSchema(Parameter $parameter): array
199223
{
200-
return self::UUID_SCHEMA;
224+
if (null !== $parameter->getSchema()) {
225+
return $parameter->getSchema();
226+
}
227+
228+
return [
229+
'oneOf' => [
230+
self::UUID_SCHEMA,
231+
[
232+
'type' => 'array',
233+
'items' => self::UUID_SCHEMA,
234+
],
235+
],
236+
];
201237
}
202238
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity\Uuid;
15+
16+
use ApiPlatform\Doctrine\Orm\Filter\UuidFilter;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use ApiPlatform\Metadata\GetCollection;
20+
use ApiPlatform\Metadata\Post;
21+
use ApiPlatform\Metadata\QueryParameter;
22+
use Doctrine\ORM\Mapping as ORM;
23+
use Symfony\Component\Uid\Uuid;
24+
25+
#[ApiResource(operations: [
26+
new Get(),
27+
new GetCollection(
28+
parameters: [
29+
'id' => new QueryParameter(
30+
filter: new UuidFilter(),
31+
),
32+
'idfoo' => new QueryParameter(
33+
schema: ['type' => 'string', 'format' => 'uuid'],
34+
filter: new UuidFilter(),
35+
),
36+
'idbar' => new QueryParameter(
37+
schema: ['type' => 'array'],
38+
filter: new UuidFilter(),
39+
),
40+
'idquz' => new QueryParameter(
41+
schema: [
42+
'oneOf' => [
43+
['type' => 'string'],
44+
[
45+
'type' => 'array',
46+
'items' => ['type' => 'string'],
47+
],
48+
],
49+
],
50+
filter: new UuidFilter(),
51+
),
52+
]
53+
),
54+
new Post(),
55+
])]
56+
#[ORM\Entity]
57+
class UuidFilterWithCustomSchema
58+
{
59+
#[ORM\Id]
60+
#[ORM\Column(type: 'symfony_uuid', unique: true)]
61+
public Uuid $id;
62+
63+
public function __construct(?Uuid $id = null)
64+
{
65+
$this->id = $id ?? Uuid::v7();
66+
}
67+
}
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Functional\Uuid;
15+
16+
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
17+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Uuid\UuidFilterWithCustomSchema;
18+
use ApiPlatform\Tests\RecreateSchemaTrait;
19+
use ApiPlatform\Tests\SetupClassResourcesTrait;
20+
21+
class UuidFilterWithCustomSchemaTest extends ApiTestCase
22+
{
23+
use RecreateSchemaTrait;
24+
use SetupClassResourcesTrait;
25+
26+
protected static ?bool $alwaysBootKernel = false;
27+
28+
protected function setUp(): void
29+
{
30+
parent::setUp();
31+
32+
if ($this->isMongoDB()) {
33+
$this->markTestSkipped();
34+
}
35+
}
36+
37+
/**
38+
* @return class-string[]
39+
*/
40+
public static function getResources(): array
41+
{
42+
return [
43+
UuidFilterWithCustomSchema::class,
44+
];
45+
}
46+
47+
public function testGetOpenApiDescriptionWhenNoCustomerSchema(): void
48+
{
49+
$response = self::createClient()->request('GET', '/docs', [
50+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
51+
]);
52+
53+
$json = $response->toArray();
54+
55+
self::assertContains(
56+
[
57+
'name' => 'id',
58+
'in' => 'query',
59+
'description' => '',
60+
'required' => false,
61+
'deprecated' => false,
62+
'schema' => [
63+
'type' => 'string',
64+
'format' => 'uuid',
65+
],
66+
'style' => 'form',
67+
'explode' => false,
68+
],
69+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
70+
);
71+
72+
self::assertContains(
73+
[
74+
'name' => 'id[]',
75+
'in' => 'query',
76+
'description' => 'One or more Uuids',
77+
'required' => false,
78+
'deprecated' => false,
79+
'schema' => [
80+
'type' => 'array',
81+
'items' => [
82+
'type' => 'string',
83+
'format' => 'uuid',
84+
],
85+
],
86+
'style' => 'deepObject',
87+
'explode' => true,
88+
],
89+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
90+
);
91+
}
92+
93+
public function testGetOpenApiDescriptionWhenSchemaIsOnlyString(): void
94+
{
95+
$response = self::createClient()->request('GET', '/docs', [
96+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
97+
]);
98+
99+
$json = $response->toArray();
100+
101+
self::assertContains(
102+
[
103+
'name' => 'idfoo',
104+
'in' => 'query',
105+
'description' => '',
106+
'required' => false,
107+
'deprecated' => false,
108+
'schema' => [
109+
'type' => 'string',
110+
'format' => 'uuid',
111+
],
112+
'style' => 'form',
113+
'explode' => false,
114+
],
115+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
116+
);
117+
118+
self::assertNotContains(
119+
'idfoo[]',
120+
array_column($json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters'], 'name')
121+
);
122+
}
123+
124+
public function testGetOpenApiDescriptionWhenSchemaIsOnlyArray(): void
125+
{
126+
$response = self::createClient()->request('GET', '/docs', [
127+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
128+
]);
129+
130+
$json = $response->toArray();
131+
132+
self::assertNotContains(
133+
'idbar',
134+
array_column($json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters'], 'name')
135+
);
136+
self::assertContains(
137+
[
138+
'name' => 'idbar[]',
139+
'in' => 'query',
140+
'description' => 'One or more Uuids',
141+
'required' => false,
142+
'deprecated' => false,
143+
'schema' => [
144+
'type' => 'array',
145+
'items' => [
146+
'type' => 'string',
147+
'format' => 'uuid',
148+
],
149+
],
150+
'style' => 'deepObject',
151+
'explode' => true,
152+
],
153+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
154+
);
155+
}
156+
157+
public function testGetOpenApiDescriptionIsOneOfArrayOrString(): void
158+
{
159+
$response = self::createClient()->request('GET', '/docs', [
160+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
161+
]);
162+
163+
$json = $response->toArray();
164+
165+
self::assertContains(
166+
[
167+
'name' => 'idquz',
168+
'in' => 'query',
169+
'description' => '',
170+
'required' => false,
171+
'deprecated' => false,
172+
'schema' => [
173+
'type' => 'string',
174+
'format' => 'uuid',
175+
],
176+
'style' => 'form',
177+
'explode' => false,
178+
],
179+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
180+
);
181+
182+
self::assertContains(
183+
[
184+
'name' => 'idquz[]',
185+
'in' => 'query',
186+
'description' => 'One or more Uuids',
187+
'required' => false,
188+
'deprecated' => false,
189+
'schema' => [
190+
'type' => 'array',
191+
'items' => [
192+
'type' => 'string',
193+
'format' => 'uuid',
194+
],
195+
],
196+
'style' => 'deepObject',
197+
'explode' => true,
198+
],
199+
$json['paths']['/uuid_filter_with_custom_schemas']['get']['parameters']
200+
);
201+
}
202+
203+
protected function tearDown(): void
204+
{
205+
if ($this->isMongoDB()) {
206+
return;
207+
}
208+
209+
$this->recreateSchema(static::getResources());
210+
211+
parent::tearDown();
212+
}
213+
}

0 commit comments

Comments
 (0)