E56C [HttpKernel] Enhance MapRequestPayload adding format and validation g… · symfony/symfony@3ae9131 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3ae9131

Browse files
author
Renan
committed
[HttpKernel] Enhance MapRequestPayload adding format and validation group
1 parent f842797 commit 3ae9131

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

src/Symfony/Component/HttpKernel/Attribute/MapRequestPayload.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\HttpKernel\Attribute;
1313

1414
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver;
15+
use Symfony\Component\Validator\Constraints\GroupSequence;
1516

1617
/**
1718
* Controller parameter tag to map the request content to typed object and validate it.
@@ -22,7 +23,9 @@
2223
class MapRequestPayload extends ValueResolver
2324
{
2425
public function __construct(
26+
public readonly array|string|null $format = null,
2527
public readonly array $context = [],
28+
public readonly string|GroupSequence|array|null|false $groups = null,
2629
string $resolver = RequestPayloadValueResolver::class,
2730
) {
2831
parent::__construct($resolver);

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
6969
continue;
7070
}
7171

72-
if (!$type = $argument->getType()) {
72+
if (!$argument->getType()) {
7373
throw new \LogicException(sprintf('Could not resolve the "$%s" controller argument: argument should be typed.', $argument->getName()));
7474
}
7575

7676
if ($this->validator) {
7777
$violations = new ConstraintViolationList();
7878
try {
79-
$payload = $this->$payloadMapper($request, $type, $attributes[0]);
79+
$payload = $this->$payloadMapper($request, $argument, $attributes[0]);
8080
} catch (PartialDenormalizationException $e) {
8181
$trans = $this->translator ? $this->translator->trans(...) : fn ($m, $p) => strtr($m, $p);
8282
foreach ($e->getErrors() as $error) {
@@ -92,15 +92,15 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
9292
}
9393

9494
if (null !== $payload) {
95-
$violations->addAll($this->validator->validate($payload));
95+
$violations->addAll($this->validator->validate($payload, null, $attributes[0]->groups ?? null));
9696
}
9797

9898
if (\count($violations)) {
9999
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($payload, $violations));
100100
}
101101
} else {
102102
try {
103-
$payload = $this->$payloadMapper($request, $type, $attributes[0]);
103+
$payload = $this->$payloadMapper($request, $argument, $attributes[0]);
104104
} catch (PartialDenormalizationException $e) {
105105
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), $e->getErrors())), $e);
106106
}
@@ -114,19 +114,19 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
114114
return [];
115115
}
116116

117-
private function mapQueryString(Request $request, string $type, MapQueryString $attribute): ?object
117+
private function mapQueryString(Request $request, ArgumentMetadata $argument, MapQueryString $attribute): ?object
118118
{
119119
if (!$data = $request->query->all()) {
120120
return null;
121121
}
122122

123-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->context);
123+
return $this->serializer->denormalize($data, $argument->getType(), null, self::CONTEXT_DENORMALIZE + $attribute->context);
124124
}
125125

126-
private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object
126+
private function mapRequestPayload(Request $request, ArgumentMetadata $argument, MapRequestPayload $attribute): ?object
127127
{
128128
if ($data = $request->request->all()) {
129-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->context);
129+
return $this->serializer->denormalize($data, $argument->getType(), null, self::CONTEXT_DENORMALIZE + $attribute->context);
130130
}
131131

132132
if ('' === $data = $request->getContent()) {
@@ -137,12 +137,17 @@ private function mapRequestPayload(Request $request, string $type, MapRequestPay
137137
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, 'Unsupported format.');
138138
}
139139

140+
$acceptedFormats = \is_string($attribute->format) ? [$attribute->format] : $attribute->format;
141+
if (\is_array($attribute->format) && !\in_array($format, $acceptedFormats, true)) {
142+
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', $acceptedFormats), $format));
143+
}
144+
140145
if ('form' === $format) {
141146
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Request payload contains invalid "form" data.');
142147
}
143148

144149
try {
145-
return $this->serializer->deserialize($data, $type, $format, self::CONTEXT_DESERIALIZE + $attribute->context);
150+
return $this->serializer->deserialize($data, $argument->getType(), $format, self::CONTEXT_DESERIALIZE + $attribute->context);
146151
} catch (UnsupportedFormatException $e) {
147152
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format: "%s".', $format), $e);
148153
} catch (NotEncodableValueException $e) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ public function testRequestInputValidationPassed()
181181

182182
$this->assertEquals($payload, $resolver->resolve($request, $argument)[0]);
183183
}
184+
185+
public function testNonSupportedRestrictedFormatMustThrowUnsupportedMediaTypeException()
186+
{
187+
}
188+
189+
public function testRestrictGroupValidation()
190+
{
191+
}
184192
}
185193

186194
class RequestPayload

0 commit comments

Comments
 (0)
0