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

Skip to content

Commit 4d87be0

Browse files
DjordyKoertnicolas-grekas
authored andcommitted
[HttpKernel] Support variadic with #[MapRequestPayload]
1 parent f6fbaeb commit 4d87be0

4 files changed

Lines changed: 79 additions & 10 deletions

File tree

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ CHANGELOG
2121
* Deprecate the `Symfony\Component\HttpKernel\DependencyInjection\Extension` class, use the parent `Symfony\Component\DependencyInjection\Extension\Extension` class instead
2222
* Allow using Expression or \Closure for `validationGroups` in `#[MapRequestPayload]` and `#[MapQueryString]`
2323
* Deprecate passing a `ControllerArgumentsEvent` to the `ViewEvent` constructor; pass a `ControllerArgumentsMetadata` instead
24+
* Support variadic argument with `#[MapRequestPayload]`
2425

2526
8.0
2627
---

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
8484
return [];
8585
}
8686

87-
if (!$attribute instanceof MapUploadedFile && $argument->isVariadic()) {
87+
if ($attribute instanceof MapQueryString && $argument->isVariadic()) {
8888
throw new \LogicException(\sprintf('Mapping variadic argument "$%s" is not supported.', $argument->getName()));
8989
}
9090

@@ -93,7 +93,7 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable
9393
if (!$attribute->type) {
9494
throw new NearMissValueResolverException(\sprintf('Please set the $type argument of the #[%s] attribute to the type of the objects in the expected array.', MapRequestPayload::class));
9595
}
96-
} elseif ($attribute->type) {
96+
} elseif ($attribute->type && !$argument->isVariadic()) {
9797
throw new NearMissValueResolverException(\sprintf('Please set its type to "array" when using argument $type of #[%s].', MapRequestPayload::class));
9898
}
9999
}
@@ -176,7 +176,11 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event): vo
176176
};
177177
}
178178

179-
$arguments[$i] = $payload;
179+
if ($argument->metadata->isVariadic()) {
180+
array_splice($arguments, $i, 1, $payload);
181+
} else {
182+
$arguments[$i] = $payload;
183+
}
180184
}
181185

182186
$event->setArguments($arguments);
@@ -212,11 +216,11 @@ private function mapRequestPayload(Request $request, ArgumentMetadata $argument,
212216
throw new UnsupportedMediaTypeHttpException(\sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', (array) $attribute->acceptFormat), $format));
213217
}
214218

215-
if ('array' === $argument->getType() && null !== $attribute->type) {
216-
$type = $attribute->type.'[]';
217-
} else {
218-
$type = $argument->getType();
219-
}
219+
$type = match (true) {
220+
$argument->isVariadic() => ($attribute->type ?? $argument->getType()).'[]',
221+
'array' === $argument->getType() && null !== $attribute->type => $attribute->type.'[]',
222+
default => $argument->getType(),
223+
};
220224

221225
if (\is_array($data)) {
222226
$data = $this->mergeParamsAndFiles($data, $request->files->all());

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

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ public function testItThrowsOnVariadicArgument()
592592
$resolver = new RequestPayloadValueResolver($serializer, $validator);
593593

594594
$argument = new ArgumentMetadata('variadic', RequestPayload::class, true, false, null, false, [
595-
MapRequestPayload::class => new MapRequestPayload(),
595+
MapQueryString::class => new MapQueryString(),
596596
]);
597597
$request = Request::create('/', 'POST');
598598

@@ -978,6 +978,70 @@ public function testConfigKeyForQueryString()
978978
$this->assertSame(1.0, $event->getArguments()[0]->page);
979979
}
980980

981+
public function testMapRequestPayloadVariadic()
982+
{
983+
$input = [
984+
['price' => '50'],
985+
['price' => '23'],
986+
];
987+
$payload = [
988+
new RequestPayload(50),
989+
new RequestPayload(23),
990+
];
991+
992+
$serializer = new Serializer([new ArrayDenormalizer(), new ObjectNormalizer()], ['json' => new JsonEncoder()]);
993+
994+
$validator = $this->createMock(ValidatorInterface::class);
995+
$validator->expects($this->once())
996+
->method('validate')
997+
->willReturn(new ConstraintViolationList());
998+
999+
$resolver = new RequestPayloadValueResolver($serializer, $validator);
1000+
1001+
$argument = new ArgumentMetadata('prices', RequestPayload::class, true, false, null, false, [
1002+
MapRequestPayload::class => new MapRequestPayload(),
1003+
]);
1004+
$request = Request::create('/', 'POST', $input);
1005+
1006+
$kernel = $this->createStub(HttpKernelInterface::class);
1007+
$arguments = $resolver->resolve($request, $argument);
1008+
$event = new ControllerArgumentsEvent($kernel, static function () {}, $arguments, $request, HttpKernelInterface::MAIN_REQUEST);
1009+
1010+
$resolver->onKernelControllerArguments($event);
1011+
1012+
$this->assertEquals($payload, $event->getArguments());
1013+
}
1014+
1015+
public function testMapRequestPayloadVariadicJson()
1016+
{
1017+
$payload = [
1018+
new RequestPayload(50),
1019+
new RequestPayload(23),
1020+
];
1021+
1022+
$serializer = new Serializer([new ArrayDenormalizer(), new ObjectNormalizer()], ['json' => new JsonEncoder()]);
1023+
1024+
$validator = $this->createMock(ValidatorInterface::class);
1025+
$validator->expects($this->once())
1026+
->method('validate')
1027+
->willReturn(new ConstraintViolationList());
1028+
1029+
$resolver = new RequestPayloadValueResolver($serializer, $validator);
1030+
1031+
$argument = new ArgumentMetadata('prices', RequestPayload::class, true, false, null, false, [
1032+
MapRequestPayload::class => new MapRequestPayload(),
1033+
]);
1034+
$request = Request::create('/', 'POST', server: ['CONTENT_TYPE' => 'application/json'], content: '[{"price": 50}, {"price": 23}]');
1035+
1036+
$kernel = $this->createStub(HttpKernelInterface::class);
1037+
$arguments = $resolver->resolve($request, $argument);
1038+
$event = new ControllerArgumentsEvent($kernel, static function () {}, $arguments, $request, HttpKernelInterface::MAIN_REQUEST);
1039+
1040+
$resolver->onKernelControllerArguments($event);
1041+
1042+
$this->assertEquals($payload, $event->getArguments());
1043+
}
1044+
9811045
public function testMapRequestPayloadWithUploadedFiles()
9821046
{
9831047
$image = new UploadedFile(self::FIXTURES_BASE_PATH.'/file-small.txt', 'file-small.txt');

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ static function () {},
319319
$resolver->onKernelControllerArguments($event);
320320

321321
/** @var UploadedFile[] $data */
322-
$data = $event->getArguments()[0];
322+
$data = $event->getArguments();
323323

324324
$this->assertCount(2, $data);
325325
$this->assertSame('file-small.txt', $data[0]->getFilename());

0 commit comments

Comments
 (0)