Skip to content

Commit 641ebd7

Browse files
soyukavinceAmstoutz
authored andcommitted
fix(metadata): various parameter improvements (api-platform#6867)
- `Parameter::getValue()` now takes a default value as argument `getValue(mixed $default = new ParameterNotFound()): mixed` - `Parametes::get(string $key, string $parameterClass = QueryParameter::class)` (but also `has` and `remove`) now has a default value as second argument to `QueryParameter::class` - Constraint violation had the wrong message when using `property`, fixed by using the `key` instead:
1 parent 407c7ed commit 641ebd7

File tree

6 files changed

+88
-13
lines changed

6 files changed

+88
-13
lines changed

features/filter/filter_validation.feature

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ Feature: Validate filters based upon filter description
2525
Scenario: Required filter should throw an error if not set
2626
When I am on "/array_filter_validators"
2727
Then the response status code should be 422
28-
And the JSON node "detail" should be equal to 'arrayRequired: This value should not be blank.\nindexedArrayRequired: This value should not be blank.'
28+
And the JSON node "detail" should be equal to 'arrayRequired[]: This value should not be blank.\nindexedArrayRequired[foo]: This value should not be blank.'
2929

3030
When I am on "/array_filter_validators?arrayRequired[foo]=foo"
3131
Then the response status code should be 422
32-
And the JSON node "detail" should be equal to 'indexedArrayRequired: This value should not be blank.'
32+
And the JSON node "detail" should be equal to 'indexedArrayRequired[foo]: This value should not be blank.'
3333

3434
When I am on "/array_filter_validators?arrayRequired[]=foo"
3535
Then the response status code should be 422
36-
And the JSON node "detail" should be equal to 'indexedArrayRequired: This value should not be blank.'
36+
And the JSON node "detail" should be equal to 'indexedArrayRequired[foo]: This value should not be blank.'
3737

3838
Scenario: Test filter bounds: maximum
3939
When I am on "/filter_validators?required=foo&required-allow-empty&maximum=10"
@@ -49,7 +49,7 @@ Feature: Validate filters based upon filter description
4949

5050
When I am on "/filter_validators?required=foo&required-allow-empty&exclusiveMaximum=10"
5151
Then the response status code should be 422
52-
And the JSON node "detail" should be equal to 'maximum: This value should be less than 10.'
52+
And the JSON node "detail" should be equal to 'exclusiveMaximum: This value should be less than 10.'
5353

5454
Scenario: Test filter bounds: minimum
5555
When I am on "/filter_validators?required=foo&required-allow-empty&minimum=5"

src/Metadata/Parameter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ public function getSecurityMessage(): ?string
124124
*
125125
* @readonly
126126
*/
127-
public function getValue(): mixed
127+
public function getValue(mixed $default = new ParameterNotFound()): mixed
128128
{
129-
return $this->extraProperties['_api_values'] ?? new ParameterNotFound();
129+
return $this->extraProperties['_api_values'] ?? $default;
130130
}
131131

132132
/**

src/Metadata/Parameters.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function add(string $key, Parameter $value): self
7070
/**
7171
* @param class-string $parameterClass
7272
*/
73-
public function remove(string $key, string $parameterClass): self
73+
public function remove(string $key, string $parameterClass = QueryParameter::class): self
7474
{
7575
foreach ($this->parameters as $i => [$parameterName, $parameter]) {
7676
if ($parameterName === $key && $parameterClass === $parameter::class) {
@@ -86,7 +86,7 @@ public function remove(string $key, string $parameterClass): self
8686
/**
8787
* @param class-string $parameterClass
8888
*/
89-
public function get(string $key, string $parameterClass): ?Parameter
89+
public function get(string $key, string $parameterClass = QueryParameter::class): ?Parameter
9090
{
9191
foreach ($this->parameters as [$parameterName, $parameter]) {
9292
if ($parameterName === $key && $parameterClass === $parameter::class) {
@@ -100,7 +100,7 @@ public function get(string $key, string $parameterClass): ?Parameter
100100
/**
101101
* @param class-string $parameterClass
102102
*/
103-
public function has(string $key, string $parameterClass): bool
103+
public function has(string $key, string $parameterClass = QueryParameter::class): bool
104104
{
105105
foreach ($this->parameters as [$parameterName, $parameter]) {
106106
if ($parameterName === $key && $parameterClass === $parameter::class) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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\Metadata\Tests;
15+
16+
use ApiPlatform\Metadata\QueryParameter;
17+
use ApiPlatform\State\ParameterNotFound;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class ParameterTest extends TestCase
21+
{
22+
public function testDefaultValue(): void
23+
{
24+
$parameter = new QueryParameter();
25+
$this->assertSame('test', $parameter->getValue('test'));
26+
$this->assertInstanceOf(ParameterNotFound::class, $parameter->getValue());
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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\Metadata\Tests;
15+
16+
use ApiPlatform\Metadata\Parameters;
17+
use ApiPlatform\Metadata\QueryParameter;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class ParametersTest extends TestCase
21+
{
22+
public function testDefaultValue(): void
23+
{
24+
$r = new QueryParameter();
25+
$parameters = new Parameters(['a' => $r]);
26+
$this->assertSame($r, $parameters->get('a'));
27+
}
28+
}

src/Symfony/Validator/State/ParameterValidatorProvider.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
namespace ApiPlatform\Symfony\Validator\State;
1515

1616
use ApiPlatform\Metadata\Operation;
17+
use ApiPlatform\Metadata\Parameter;
1718
use ApiPlatform\State\ParameterNotFound;
1819
use ApiPlatform\State\ProviderInterface;
1920
use ApiPlatform\State\Util\ParameterParserTrait;
2021
use ApiPlatform\Validator\Exception\ValidationException;
2122
use Symfony\Component\HttpFoundation\Request;
2223
use Symfony\Component\Validator\ConstraintViolation;
24+
use Symfony\Component\Validator\ConstraintViolationInterface;
2325
use Symfony\Component\Validator\ConstraintViolationList;
2426
use Symfony\Component\Validator\Validator\ValidatorInterface;
2527

@@ -55,7 +57,6 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
5557
continue;
5658
}
5759

58-
$key = $parameter->getKey();
5960
$value = $parameter->getValue();
6061
if ($value instanceof ParameterNotFound) {
6162
$value = null;
@@ -76,9 +77,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
7677
$violation->getMessageTemplate(),
7778
$violation->getParameters(),
7879
$violation->getRoot(),
79-
$parameter->getProperty() ?? (
80-
str_contains($key, ':property') ? str_replace('[:property]', $violation->getPropertyPath(), $key) : $key.$violation->getPropertyPath()
81-
),
80+
$this->getProperty($parameter, $violation),
8281
$violation->getInvalidValue(),
8382
$violation->getPlural(),
8483
$violation->getCode(),
@@ -94,4 +93,24 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
9493

9594
return $this->decorated->provide($operation, $uriVariables, $context);
9695
}
96+
97+
// There's a `property` inside Parameter but it's used for hydra:search only as here we want the parameter name instead
98+
private function getProperty(Parameter $parameter, ConstraintViolationInterface $violation): string
99+
{
100+
$key = $parameter->getKey();
101+
102+
if (str_contains($key, '[:property]')) {
103+
return str_replace('[:property]', $violation->getPropertyPath(), $key);
104+
}
105+
106+
if (str_contains($key, ':property')) {
107+
return str_replace(':property', $violation->getPropertyPath(), $key);
108+
}
109+
110+
if ($p = $violation->getPropertyPath()) {
111+
return $p;
112+
}
113+
114+
return $key;
115+
}
97116
}

0 commit comments

Comments
 (0)