diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php index c35d5e7e29381..59a1030ca807d 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php @@ -170,7 +170,14 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event): vo }; } - $arguments[$i] = $payload; + if ($argument->metadata->isVariadic()) { + if (!\is_array($payload) || !\array_is_list($payload)) { + throw HttpException::fromStatusCode($validationFailedCode); + } + \array_splice($arguments, $i, \count($payload), $payload); + } else { + $arguments[$i] = $payload; + } } $event->setArguments($arguments); @@ -233,6 +240,11 @@ private function mapRequestPayload(Request $request, ArgumentMetadata $argument, private function mapUploadedFile(Request $request, ArgumentMetadata $argument, MapUploadedFile $attribute): UploadedFile|array|null { - return $request->files->get($attribute->name ?? $argument->getName(), []); + $default = null; + if ($argument->isVariadic() || 'array' === $argument->getType()) { + $default = []; + } + + return $request->files->get($attribute->name ?? $argument->getName(), $default); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UploadedFileValueResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UploadedFileValueResolverTest.php index 5eb0d32483ed5..8817ee64ae6ae 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UploadedFileValueResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UploadedFileValueResolverTest.php @@ -68,7 +68,7 @@ public function testEmpty(RequestPayloadValueResolver $resolver, Request $reques $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', - UploadedFile::class, + 'array', false, false, null, @@ -82,12 +82,70 @@ static function () {}, $request, HttpKernelInterface::MAIN_REQUEST ); + $resolver->onKernelControllerArguments($event); $data = $event->getArguments()[0]; $this->assertEmpty($data); } + /** + * @dataProvider provideContext + */ + public function testNotNullableFile(RequestPayloadValueResolver $resolver, Request $request) + { + $attribute = new MapUploadedFile(); + $argument = new ArgumentMetadata( + 'qux', + UploadedFile::class, + false, + false, + null, + false, + [$attribute::class => $attribute] + ); + $event = new ControllerArgumentsEvent( + $this->createMock(HttpKernelInterface::class), + static function () {}, + $resolver->resolve($request, $argument), + $request, + HttpKernelInterface::MAIN_REQUEST + ); + + $this->expectException(HttpException::class); + + $resolver->onKernelControllerArguments($event); + } + + /** + * @dataProvider provideContext + */ + public function testNullableFile(RequestPayloadValueResolver $resolver, Request $request) + { + $attribute = new MapUploadedFile(); + $argument = new ArgumentMetadata( + 'qux', + UploadedFile::class, + false, + true, + null, + true, + [$attribute::class => $attribute] + ); + $event = new ControllerArgumentsEvent( + $this->createMock(HttpKernelInterface::class), + static function () {}, + $resolver->resolve($request, $argument), + $request, + HttpKernelInterface::MAIN_REQUEST + ); + + $resolver->onKernelControllerArguments($event); + $data = $event->getArguments()[0]; + + $this->assertNull($data); + } + /** * @dataProvider provideContext */ @@ -269,7 +327,7 @@ static function () {}, $resolver->onKernelControllerArguments($event); /** @var UploadedFile[] $data */ - $data = $event->getArguments()[0]; + $data = $event->getArguments(); $this->assertCount(2, $data); $this->assertSame('file-small.txt', $data[0]->getFilename());