Skip to content

Commit 1427dfa

Browse files
authored
feat(metadata): expose default attribute on parameters (#7551)
1 parent 7d9e6cf commit 1427dfa

File tree

7 files changed

+97
-11
lines changed

7 files changed

+97
-11
lines changed

src/Metadata/Parameter.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function __construct(
5656
protected ?bool $castToArray = null,
5757
protected ?bool $castToNativeType = null,
5858
protected mixed $castFn = null,
59+
protected mixed $default = null,
5960
) {
6061
}
6162

@@ -139,7 +140,7 @@ public function getSecurityMessage(): ?string
139140
*/
140141
public function getValue(mixed $default = new ParameterNotFound()): mixed
141142
{
142-
return $this->extraProperties['_api_values'] ?? $default;
143+
return $this->extraProperties['_api_values'] ?? $this->default ?? $default;
143144
}
144145

145146
/**
@@ -370,4 +371,17 @@ public function withCastFn(mixed $castFn): self
370371

371372
return $self;
372373
}
374+
375+
public function getDefault(): mixed
376+
{
377+
return $this->default;
378+
}
379+
380+
public function withDefault(mixed $default): self
381+
{
382+
$self = clone $this;
383+
$self->default = $default;
384+
385+
return $self;
386+
}
373387
}

src/Metadata/Tests/ParameterTest.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,40 @@
1313

1414
namespace ApiPlatform\Metadata\Tests;
1515

16+
use ApiPlatform\Metadata\Parameter;
1617
use ApiPlatform\Metadata\QueryParameter;
1718
use ApiPlatform\State\ParameterNotFound;
19+
use PHPUnit\Framework\Attributes\DataProvider;
1820
use PHPUnit\Framework\TestCase;
1921

2022
class ParameterTest extends TestCase
2123
{
2224
public function testDefaultValue(): void
2325
{
24-
$parameter = new QueryParameter();
25-
$this->assertSame('test', $parameter->getValue('test'));
26-
$this->assertInstanceOf(ParameterNotFound::class, $parameter->getValue());
26+
$this->assertInstanceOf(ParameterNotFound::class, (new QueryParameter())->getValue());
27+
}
28+
29+
#[DataProvider('provideDefaultValueCases')]
30+
public function testDefaultValueWithFallbackValue(Parameter $parameter, mixed $fallbackValue, mixed $expectedDefault): void
31+
{
32+
$this->assertSame($expectedDefault, $parameter->getValue($fallbackValue));
33+
}
34+
35+
/** @return iterable<array{Parameter, mixed, mixed}> */
36+
public static function provideDefaultValueCases(): iterable
37+
{
38+
$fallbackValue = new ParameterNotFound();
39+
40+
yield 'no default specified' => [
41+
new QueryParameter(), $fallbackValue, $fallbackValue,
42+
];
43+
44+
yield 'with a default specified' => [
45+
new QueryParameter(default: false), $fallbackValue, false,
46+
];
47+
48+
yield 'with null as default' => [
49+
new QueryParameter(default: null), $fallbackValue, $fallbackValue,
50+
];
2751
}
2852
}

src/OpenApi/Factory/OpenApiFactory.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,19 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
337337
}
338338

339339
$in = $p instanceof HeaderParameterInterface ? 'header' : 'query';
340+
$defaultSchema = ['type' => 'string'];
341+
if (null !== $p->getDefault()) {
342+
$defaultSchema['default'] = $p->getDefault();
343+
}
344+
340345
$defaultParameter = new Parameter(
341346
$key,
342347
$in,
343348
$p->getDescription() ?? "$resourceShortName $key",
344349
$p->getRequired() ?? false,
345350
false,
346351
null,
347-
$p->getSchema() ?? ['type' => 'string'],
352+
$p->getSchema() ?? $defaultSchema,
348353
);
349354

350355
$linkParameter = $p->getOpenApi();

src/State/Provider/ParameterProvider.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
7979
unset($parameter->getExtraProperties()['_api_values']);
8080
}
8181

82-
if (null !== ($default = $parameter->getSchema()['default'] ?? null) && $value instanceof ParameterNotFound) {
82+
if (null !== ($default = $parameter->getDefault() ?? $parameter->getSchema()['default'] ?? null) && $value instanceof ParameterNotFound) {
8383
$value = $default;
8484
}
8585

@@ -128,7 +128,7 @@ private function handlePathParameters(HttpOperation $operation, array $uriVariab
128128
unset($uriVariable->getExtraProperties()['_api_values']);
129129
}
130130

131-
if (($default = $uriVariable->getSchema()['default'] ?? false) && ($value instanceof ParameterNotFound || !$value)) {
131+
if (($default = $uriVariable->getDefault() ?? $uriVariable->getSchema()['default'] ?? false) && ($value instanceof ParameterNotFound || !$value)) {
132132
$value = $default;
133133
}
134134

tests/Fixtures/TestBundle/ApiResource/Issue7354/BooleanQueryParameter.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,27 @@
3131
],
3232
castToNativeType: true,
3333
),
34+
'anotherBooleanParameter' => new QueryParameter(
35+
default: true,
36+
),
3437
],
3538
provider: [self::class, 'provide'],
3639
),
3740
]
3841
)]
3942
class BooleanQueryParameter
4043
{
41-
public function __construct(public bool $booleanParameter)
42-
{
44+
public function __construct(
45+
public bool $booleanParameter,
46+
public bool $anotherBooleanParameter,
47+
) {
4348
}
4449

4550
public static function provide(Operation $operation): self
4651
{
47-
return new self($operation->getParameters()->get('booleanParameter')->getValue());
52+
return new self(
53+
$operation->getParameters()->get('booleanParameter')->getValue(),
54+
$operation->getParameters()->get('anotherBooleanParameter')->getValue(),
55+
);
4856
}
4957
}

tests/Fixtures/TestBundle/ApiResource/WithParameter.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use Symfony\Component\Validator\Constraints\All;
3939
use Symfony\Component\Validator\Constraints as Assert;
4040
use Symfony\Component\Validator\Constraints\Country;
41+
use Webmozart\Assert\Assert as Assertion;
4142

4243
#[Get(
4344
uriTemplate: 'with_parameters/{id}{._format}',
@@ -281,7 +282,25 @@
281282
],
282283
provider: [self::class, 'collectionProvider'],
283284
)]
284-
285+
#[GetCollection(
286+
uriTemplate: 'parameter_defaults',
287+
parameters: [
288+
'false_as_default' => new QueryParameter(
289+
default: false,
290+
),
291+
'true_as_default' => new QueryParameter(
292+
default: true,
293+
),
294+
'foo_as_default' => new QueryParameter(
295+
default: 'foo',
296+
),
297+
'required_with_a_default' => new QueryParameter(
298+
required: true,
299+
default: 'bar'
300+
),
301+
],
302+
provider: [self::class, 'checkParameterDefaults'],
303+
)]
285304
#[QueryParameter(key: 'everywhere')]
286305
class WithParameter
287306
{
@@ -372,4 +391,14 @@ public static function provideDummyFromParameter(Operation $operation, array $ur
372391
{
373392
return $operation->getParameters()->get('dummy')->getValue();
374393
}
394+
395+
public static function checkParameterDefaults(Operation $operation, array $uriVariables = [], array $context = []): JsonResponse
396+
{
397+
Assertion::false($operation->getParameters()->get('false_as_default')->getValue());
398+
Assertion::true($operation->getParameters()->get('true_as_default')->getValue());
399+
Assertion::same($operation->getParameters()->get('foo_as_default')->getValue(), 'foo');
400+
Assertion::same($operation->getParameters()->get('required_with_a_default')->getValue(), 'bar');
401+
402+
return new JsonResponse([]);
403+
}
375404
}

tests/Functional/Parameters/ParameterTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,10 @@ public static function provideCountriesValues(): iterable
215215
yield 'valid country' => ['country=FR', 200];
216216
yield 'array of countries' => ['country[]=FR', 200];
217217
}
218+
219+
public function testDefaultValues(): void
220+
{
221+
self::createClient()->request('GET', 'parameter_defaults');
222+
$this->assertResponseIsSuccessful();
223+
}
218224
}

0 commit comments

Comments
 (0)