8000 [HttpKernel] Fix default value ignored with pinned resolvers · symfony/symfony@f5ea04b · GitHub
[go: up one dir, main page]

Skip to content

Commit f5ea04b

Browse files
committed
[HttpKernel] Fix default value ignored with pinned resolvers
1 parent e1bf69c commit f5ea04b

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public function getArguments(Request $request, callable $controller, \Reflection
7272
}
7373

7474
$argumentValueResolvers = [$this->namedResolvers->get($resolverName)];
75+
76+
if ($this->namedResolvers->has(DefaultValueResolver::class) && !$argumentValueResolvers[0] instanceof DefaultValueResolver) {
77+
$argumentValueResolvers[] = $this->namedResolvers->get(DefaultValueResolver::class);
78+
}
7579
}
7680
}
7781

src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/QueryParameterValueResolver.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,8 @@ public function resolve(Request $request, ArgumentMetadata $argument): array
3131

3232
$name = $attribute->name ?? $argument->getName();
3333
if (!$request->query->has($name)) {
34-
if ($argument->hasDefaultValue()) {
35-
return [$argument->getDefaultValue()];
36-
}
37-
38-
if ($argument->isNullable()) {
39-
return [null];
34+
if ($argument->isNullable() || $argument->hasDefaultValue()) {
35+
return [];
4036
}
4137

4238
throw new NotFoundHttpException(sprintf('Missing query parameter "%s".', $name));

src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/QueryParameterValueResolverTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ public static function provideTestResolve(): iterable
179179
yield 'parameter not found but nullable' => [
180180
Request::create('/', 'GET'),
181181
new ArgumentMetadata('firstName', 'string', false, false, false, true, [new MapQueryParameter()]),
182-
[null],
182+
[],
183183
null,
184184
];
185185

186186
yield 'parameter not found but optional' => [
187187
Request::create('/', 'GET'),
188188
new ArgumentMetadata('firstName', 'string', false, true, false, attributes: [new MapQueryParameter()]),
189-
[false],
189+
[],
190190
null,
191191
];
192192

src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
2323
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
2424
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
25+
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
2526
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
27+
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
2628
use Symfony\Component\HttpKernel\Exception\ResolverNotFoundException;
2729
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest;
2830
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingSession;
@@ -296,6 +298,56 @@ public function testTargetedResolver()
296298
$this->assertSame([1], $resolver->getArguments($request, $controller));
297299
}
298300

301+
public function testTargetedResolverWithDefaultValue()
302+
{
303+
$resolver = self::getResolver([], [
304+
RequestAttributeValueResolver::class => new RequestAttributeValueResolver(),
305+
DefaultValueResolver::class => new DefaultValueResolver(),
306+
]);
307+
308+
$request = Request::create('/');
309+
$controller = $this->controllerTargetingResolverWithDefaultValue(...);
310+
311+
$this->assertSame([2], $resolver->getArguments($request, $controller));
312+
}
313+
314+
public function testTargetedResolverWithNullableValue()
315+
{
316+
$resolver = self::getResolver([], [
317+
RequestAttributeValueResolver::class => new RequestAttributeValueResolver(),
318+
DefaultValueResolver::class => new DefaultValueResolver(),
319+
]);
320+
321+
$request = Request::create('/');
322+
$controller = $this->controllerTargetingResolverWithNullableValue(...);
323+
324+
$this->assertSame([null], $resolver->getArguments($request, $controller));
325+
}
326+
327+
public function testDefaultValueResolverIsNotAddedIfAlreadyPinned()
328+
{
329+
$argumentMetadata = $this->createMock(ArgumentMetadata::class);
330+
$argumentMetadata->expects($this->once())->method('getAttributesOfType')->willReturn([new ValueResolver(DefaultValueResolver::class)]);
331+
$argumentMetadata->expects($this->once())->method('hasDefaultValue')->willReturn(false);
332+
$argumentMetadata->expects($this->once())->method('getType')->willReturn(\stdClass::class);
333+
$argumentMetadata->expects($this->once())->method('isNullable')->willReturn(false);
334+
335+
$argumentMetadataFactory = $this->createMock(ArgumentMetadataFactoryInterface::class);
336+
$argumentMetadataFactory->method('createArgumentMetadata')->willReturn([$argumentMetadata]);
337+
338+
$resolver = new ArgumentResolver(
339+
$argumentMetadataFactory,
340+
[],
341+
new ServiceLocator(array_map(fn ($resolver) => fn () => $resolver, [DefaultValueResolver::class => new DefaultValueResolver()]))
342+
);
343+
344+
$request = Request::create('/');
345+
346+
$this->expectException(\RuntimeException::class);
347+
348+
$resolver->getArguments($request, function () {});
349+
}
350+
299351
public function testDisabledResolver()
300352
{
301353
$resolver = self::getResolver(namedResolvers: []);
@@ -373,6 +425,14 @@ public function controllerTargetingResolver(#[ValueResolver(DefaultValueResolver
373425
{
374426
}
375427

428+
public function controllerTargetingResolverWithDefaultValue(#[ValueResolver(RequestAttributeValueResolver::class)] int $foo = 2)
429+
{
430+
}
431+
432+
public function controllerTargetingResolverWithNullableValue(#[ValueResolver(RequestAttributeValueResolver::class)] ?int $foo)
433+
{
434+
}
435+
376436
public function controllerDisablingResolver(#[ValueResolver(RequestAttributeValueResolver::class, disabled: true)] int $foo = 1)
377437
{
378438
}

0 commit comments

Comments
 (0)
0