Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 48a9d02

Browse files
committed
Narrow down the use-cases to route parameters resolution
1 parent 7bcee62 commit 48a9d02

File tree

2 files changed

+34
-51
lines changed

2 files changed

+34
-51
lines changed

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

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,27 @@
1111

1212
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
1313

14-
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
1514
use Symfony\Component\HttpFoundation\Request;
1615
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
1716
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
17+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1818

1919
/**
20-
* Attempt to resolve backed enum cases from request attributes.
20+
* Attempt to resolve backed enum cases from request attributes, for a route path parameter,
21+
* leading to a 404 Not Found if the attribute value isn't a valid backing value for the enum type.
2122
*
2223
* @author Maxime Steinhausser <[email protected]>
2324
*/
2425
class BackedEnumValueResolver implements ArgumentValueResolverInterface
2526
{
2627
public function supports(Request $request, ArgumentMetadata $argument): bool
2728
{
28-
if (!is_subclass_of($argument->getType(), \BackedEnum::class, true)) {
29+
if (!is_subclass_of($argument->getType(), \BackedEnum::class)) {
30+
return false;
31+
}
32+
33+
if ($argument->isVariadic()) {
34+
// only target route path parameters, which cannot be variadic.
2935
return false;
3036
}
3137

@@ -37,24 +43,25 @@ public function supports(Request $request, ArgumentMetadata $argument): bool
3743

3844
public function resolve(Request $request, ArgumentMetadata $argument): iterable
3945
{
40-
/** @var interface-string<\BackedEnum> $enumType */
41-
$enumType = $argument->getType();
42-
$values = $argument->isVariadic() ? $request->attributes->all($argument->getName()) : [$request->attributes->get($argument->getName())];
46+
$value = $request->attributes->get($argument->getName());
4347

44-
foreach ($values as $value) {
45-
if (null === $value) {
46-
yield null;
48+
if (null === $value) {
49+
yield null;
4750

48-
continue;
49-
}
51+
return;
52+
}
53+
54+
if (!\is_int($value) && !\is_string($value)) {
55+
throw new \LogicException(sprintf('Could not resolve the "%s $%s" controller argument: expecting an int or string, got %s.', $argument->getType(), $argument->getName(), get_debug_type($value)));
56+
}
5057

51-
try {
52-
yield $enumType::from($value);
58+
/** @var class-string<\BackedEnum> $enumType */
59+
$enumType = $argument->getType();
5360

54-
continue;
55-
} catch (\ValueError|\TypeError $error) {
56-
throw new BadRequestException(sprintf('Could not resolve the "%s" controller argument: %s', $argument->getName(), $error->getMessage()), $error->getCode(), $error);
57-
}
61+
try {
62+
yield $enumType::from($value);
63+
} catch (\ValueError $error) {
64+
throw new NotFoundHttpException(sprintf('Could not resolve the "%s $%s" controller argument: %s', $argument->getType(), $argument->getName(), $error->getMessage()), $error);
5865
}
5966
}
6067
}

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

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver;
1313

1414
use PHPUnit\Framework\TestCase;
15-
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
1615
use Symfony\Component\HttpFoundation\Request;
1716
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\BackedEnumValueResolver;
1817
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
18+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1919
use Symfony\Component\HttpKernel\Tests\Fixtures\Suit;
2020

2121
/**
@@ -59,14 +59,14 @@ public function provideTestSupportsData(): iterable
5959
false,
6060
];
6161

62-
yield 'supports variadics' => [
62+
yield 'unsupported variadic' => [
6363
self::createRequest(['suit' => ['H', 'S']]),
6464
self::createArgumentMetadata(
6565
'suit',
6666
Suit::class,
6767
variadic: true,
6868
),
69-
true,
69+
false,
7070
];
7171
}
7272

@@ -98,54 +98,30 @@ public function provideTestResolveData(): iterable
9898
),
9999
[null],
100100
];
101-
102-
yield 'with variadics' => [
103-
self::createRequest(['suits' => ['H', null, 'S']]),
104-
self::createArgumentMetadata(
105-
'suits',
106-
Suit::class,
107-
variadic: true
108-
),
109-
[Suit::Hearts, null, Suit::Spades],
110-
];
111101
}
112102

113-
public function testResolveThrowsOnInvalidValue()
103+
public function testResolveThrowsNotFoundOnInvalidValue()
114104
{
115105
$resolver = new BackedEnumValueResolver();
116106
$request = self::createRequest(['suit' => 'foo']);
117107
$metadata = self::createArgumentMetadata('suit', Suit::class);
118108

119-
$this->expectException(BadRequestException::class);
120-
$this->expectExceptionMessage('Could not resolve the "suit" controller argument: "foo" is not a valid backing value for enum "Symfony\Component\HttpKernel\Tests\Fixtures\Suit"');
109+
$this->expectException(NotFoundHttpException::class);
110+
$this->expectExceptionMessage('Could not resolve the "Symfony\Component\HttpKernel\Tests\Fixtures\Suit $suit" controller argument: "foo" is not a valid backing value for enum');
121111

122112
/** @var \Generator $results */
123113
$results = $resolver->resolve($request, $metadata);
124114
iterator_to_array($results);
125115
}
126116

127-
public function testResolveThrowsOnNonVariadicArgumentWithMultipleValues()
117+
public function testResolveThrowsOnUnexpectedType()
128118
{
129119
$resolver = new BackedEnumValueResolver();
130-
$request = self::createRequest(['suit' => ['H', 'S']]);
120+
$request = self::createRequest(['suit' => false]);
131121
$metadata = self::createArgumentMetadata('suit', Suit::class);
132122

133-
$this->expectException(BadRequestException::class);
134-
$this->expectExceptionMessage('Could not resolve the "suit" controller argument: Symfony\Component\HttpKernel\Tests\Fixtures\Suit::from(): Argument #1 ($value) must be of type string, array given');
135-
136-
/** @var \Generator $results */
137-
$results = $resolver->resolve($request, $metadata);
138-
iterator_to_array($results);
139-
}
140-
141-
public function testResolveThrowsOnVariadicArgumentWithNonArrayValue()
142-
{
143-
$resolver = new BackedEnumValueResolver();
144-
$request = self::createRequest(['suits' => 'H']);
145-
$metadata = self::createArgumentMetadata('suits', Suit::class, variadic: true);
146-
147-
$this->expectException(BadRequestException::class);
148-
$this->expectExceptionMessage('Unexpected value for parameter "suits": expecting "array", got "string".');
123+
$this->expectException(\LogicException::class);
124+
$this->expectExceptionMessage('Could not resolve the "Symfony\Component\HttpKernel\Tests\Fixtures\Suit $suit" controller argument: expecting an int or string, got bool.');
149125

150126
/** @var \Generator $results */
151127
$results = $resolver->resolve($request, $metadata);

0 commit comments

Comments
 (0)