Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 48a9d02

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

File tree

2 files changed

+34
-51
lines changed
Filter options

2 files changed

+34
-51
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/BackedEnumValueResolver.php
+24-17Lines 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 <maxime.steinhausser@gmail.com>
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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/BackedEnumValueResolverTest.php
+10-34Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.