From 9fd614a8b669d34495e2d32c060c12f16a23e7c0 Mon Sep 17 00:00:00 2001 From: seb-jean Date: Wed, 30 Oct 2024 14:27:35 +0100 Subject: [PATCH] [HttpKernel] Support `Uid` in `#[MapQueryParameter]` --- src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../QueryParameterValueResolver.php | 14 +++++++++++++- .../QueryParameterValueResolverTest.php | 13 ++++++++++--- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 501ddbe6b7a8a..cc9da8a2a98af 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Add `$key` argument to `#[MapQueryString]` that allows using a specific key for argument resolving + * Support `Uid` in `#[MapQueryParameter]` 7.2 --- diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/QueryParameterValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/QueryParameterValueResolver.php index 1566119dfd376..5fe3d75313a43 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/QueryParameterValueResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/QueryParameterValueResolver.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\Uid\AbstractUid; /** * Resolve arguments of type: array, string, int, float, bool, \BackedEnum from query parameters. @@ -73,6 +74,12 @@ public function resolve(Request $request, ArgumentMetadata $argument): array $options['flags'] |= \FILTER_REQUIRE_SCALAR; } + $uidType = null; + if (is_subclass_of($type, AbstractUid::class)) { + $uidType = $type; + $type = 'uid'; + } + $enumType = null; $filter = match ($type) { 'array' => \FILTER_DEFAULT, @@ -80,10 +87,11 @@ public function resolve(Request $request, ArgumentMetadata $argument): array 'int' => \FILTER_VALIDATE_INT, 'float' => \FILTER_VALIDATE_FLOAT, 'bool' => \FILTER_VALIDATE_BOOL, + 'uid' => \FILTER_DEFAULT, default => match ($enumType = is_subclass_of($type, \BackedEnum::class) ? (new \ReflectionEnum($type))->getBackingType()->getName() : null) { 'int' => \FILTER_VALIDATE_INT, 'string' => \FILTER_DEFAULT, - default => throw new \LogicException(\sprintf('#[MapQueryParameter] cannot be used on controller argument "%s$%s" of type "%s"; one of array, string, int, float, bool or \BackedEnum should be used.', $argument->isVariadic() ? '...' : '', $argument->getName(), $type ?? 'mixed')), + default => throw new \LogicException(\sprintf('#[MapQueryParameter] cannot be used on controller argument "%s$%s" of type "%s"; one of array, string, int, float, bool, uid or \BackedEnum should be used.', $argument->isVariadic() ? '...' : '', $argument->getName(), $type ?? 'mixed')), }, }; @@ -105,6 +113,10 @@ public function resolve(Request $request, ArgumentMetadata $argument): array $value = \is_array($value) ? array_map($enumFrom, $value) : $enumFrom($value); } + if (null !== $uidType) { + $value = \is_array($value) ? array_map([$uidType, 'fromString'], $value) : $uidType::fromString($value); + } + if (null === $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) { throw HttpException::fromStatusCode($validationFailedCode, \sprintf('Invalid query parameter "%s".', $name)); } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/QueryParameterValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/QueryParameterValueResolverTest.php index 194cfd2e521b8..2b887db821e10 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/QueryParameterValueResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/QueryParameterValueResolverTest.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Tests\Fixtures\Suit; +use Symfony\Component\Uid\Ulid; class QueryParameterValueResolverTest extends TestCase { @@ -44,7 +45,7 @@ public function testSkipWhenNoAttribute() */ public function testResolvingSuccessfully(Request $request, ArgumentMetadata $metadata, array $expected) { - $this->assertSame($expected, $this->resolver->resolve($request, $metadata)); + $this->assertEquals($expected, $this->resolver->resolve($request, $metadata)); } /** @@ -231,6 +232,12 @@ public static function validDataProvider(): iterable new ArgumentMetadata('firstName', 'string', false, true, false, attributes: [new MapQueryParameter()]), [], ]; + + yield 'parameter found and ULID' => [ + Request::create('/', 'GET', ['groupId' => '01E439TP9XJZ9RPFH3T1PYBCR8']), + new ArgumentMetadata('groupId', Ulid::class, false, true, false, attributes: [new MapQueryParameter()]), + [Ulid::fromString('01E439TP9XJZ9RPFH3T1PYBCR8')], + ]; } /** @@ -245,13 +252,13 @@ public static function invalidArgumentTypeProvider(): iterable yield 'unsupported type' => [ Request::create('/', 'GET', ['standardClass' => 'test']), new ArgumentMetadata('standardClass', \stdClass::class, false, false, false, attributes: [new MapQueryParameter()]), - '#[MapQueryParameter] cannot be used on controller argument "$standardClass" of type "stdClass"; one of array, string, int, float, bool or \BackedEnum should be used.', + '#[MapQueryParameter] cannot be used on controller argument "$standardClass" of type "stdClass"; one of array, string, int, float, bool, uid or \BackedEnum should be used.', ]; yield 'unsupported type variadic' => [ Request::create('/', 'GET', ['standardClass' => 'test']), new ArgumentMetadata('standardClass', \stdClass::class, true, false, false, attributes: [new MapQueryParameter()]), - '#[MapQueryParameter] cannot be used on controller argument "...$standardClass" of type "stdClass"; one of array, string, int, float, bool or \BackedEnum should be used.', + '#[MapQueryParameter] cannot be used on controller argument "...$standardClass" of type "stdClass"; one of array, string, int, float, bool, uid or \BackedEnum should be used.', ]; }