Skip to content

Commit

Permalink
fix(state): store parameter value without its key (#6456)
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka authored Jul 8, 2024
1 parent 83745df commit 93e4b3d
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 21 deletions.
16 changes: 6 additions & 10 deletions src/Doctrine/Common/ParameterValueExtractorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,20 @@

namespace ApiPlatform\Doctrine\Common;

use ApiPlatform\Metadata\Parameter;

trait ParameterValueExtractorTrait
{
/**
* @param array<string, mixed> $values
*
* @return array<string, mixed>
*/
private function extractParameterValue(array $values): array
private function extractParameterValue(Parameter $parameter, mixed $value): array
{
if (!$values) {
return $values;
}

$key = key($values);
$key = $parameter->getKey();
if (!str_contains($key, ':property')) {
return $values;
return [$key => $value];
}

return [str_replace('[:property]', '', $key) => $values[$key]];
return [str_replace('[:property]', '', $key) => $value];
}
}
5 changes: 3 additions & 2 deletions src/Doctrine/Odm/Extension/ParameterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use ApiPlatform\Doctrine\Common\ParameterValueExtractorTrait;
use ApiPlatform\Doctrine\Odm\Filter\FilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ParameterNotFound;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Psr\Container\ContainerInterface;

Expand All @@ -35,11 +36,11 @@ public function __construct(private readonly ContainerInterface $filterLocator)
private function applyFilter(Builder $aggregationBuilder, ?string $resourceClass = null, ?Operation $operation = null, array &$context = []): void
{
foreach ($operation->getParameters() ?? [] as $parameter) {
$values = $this->extractParameterValue($parameter->getValue() ?? []);
if (!$values) {
if (!($v = $parameter->getValue()) || $v instanceof ParameterNotFound) {
continue;
}

$values = $this->extractParameterValue($parameter, $v);
if (null === ($filterId = $parameter->getFilter())) {
continue;
}
Expand Down
5 changes: 3 additions & 2 deletions src/Doctrine/Orm/Extension/ParameterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use ApiPlatform\Doctrine\Orm\Filter\FilterInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ParameterNotFound;
use Doctrine\ORM\QueryBuilder;
use Psr\Container\ContainerInterface;

Expand All @@ -39,11 +40,11 @@ public function __construct(private readonly ContainerInterface $filterLocator)
private function applyFilter(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
{
foreach ($operation?->getParameters() ?? [] as $parameter) {
$values = $this->extractParameterValue($parameter->getValue() ?? []);
if (!$values) {
if (!($v = $parameter->getValue()) || $v instanceof ParameterNotFound) {
continue;
}

$values = $this->extractParameterValue($parameter, $v);
if (null === ($filterId = $parameter->getFilter())) {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/State/Provider/ParameterProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
}

$parameters->add($parameter->getKey(), $parameter = $parameter->withExtraProperties(
$parameter->getExtraProperties() + ['_api_values' => [$parameter->getKey() => $value]]
$parameter->getExtraProperties() + ['_api_values' => $value]
));

if (null === ($provider = $parameter->getProvider())) {
Expand Down
4 changes: 2 additions & 2 deletions src/State/Tests/ParameterProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public function has(string $id): bool
$operation = $request->attributes->get('_api_operation');

$this->assertEquals('ok', $operation->getName());
$this->assertEquals(['order' => ['foo' => 'asc']], $operation->getParameters()->get('order', QueryParameter::class)->getValue());
$this->assertEquals(['search[:property]' => ['a' => 'bar']], $operation->getParameters()->get('search[:property]', QueryParameter::class)->getValue());
$this->assertEquals(['foo' => 'asc'], $operation->getParameters()->get('order', QueryParameter::class)->getValue());
$this->assertEquals(['a' => 'bar'], $operation->getParameters()->get('search[:property]', QueryParameter::class)->getValue());
}

public static function provide(): void
Expand Down
13 changes: 11 additions & 2 deletions src/Symfony/Validator/State/ParameterValidatorProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\Symfony\Validator\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ParameterNotFound;
use ApiPlatform\State\ProviderInterface;
use ApiPlatform\State\Util\ParameterParserTrait;
use ApiPlatform\Validator\Exception\ValidationException;
Expand All @@ -39,19 +40,27 @@ public function __construct(

public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if (!($request = $context['request']) instanceof Request || false === $operation->getQueryParameterValidationEnabled()) {
if (!($request = $context['request']) instanceof Request) {
return $this->decorated->provide($operation, $uriVariables, $context);
}

$operation = $request->attributes->get('_api_operation') ?? $operation;
if (!($operation->getQueryParameterValidationEnabled() ?? true)) {
return $this->decorated->provide($operation, $uriVariables, $context);
}

$constraintViolationList = new ConstraintViolationList();
foreach ($operation->getParameters() ?? [] as $parameter) {
if (!$constraints = $parameter->getConstraints()) {
continue;
}

$key = $parameter->getKey();
$value = $parameter->getValue()[$key] ?? null;
$value = $parameter->getValue();
if ($value instanceof ParameterNotFound) {
$value = null;
}

$violations = $this->validator->validate($value, $constraints);
foreach ($violations as $violation) {
$constraintViolationList->add(new ConstraintViolation(
Expand Down
4 changes: 2 additions & 2 deletions tests/Functional/Parameters/ParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public function testHeaderAndQuery(): void
{
$response = self::createClient()->request('GET', 'with_parameters_header_and_query?q=blabla', ['headers' => ['q' => '(complex stuff)']]);
$this->assertEquals($response->toArray(), [
['q' => ['(complex stuff)']],
['q' => 'blabla'],
['(complex stuff)'],
'blabla',
]);
}
}

0 comments on commit 93e4b3d

Please sign in to comment.