Skip to content

Commit 10e5189

Browse files
committed
[HttpKernel] Fix #[MapUploadedFile] handling for optional file uploads
1 parent 1084655 commit 10e5189

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ private function mapRequestPayload(Request $request, ArgumentMetadata $argument,
232232

233233
private function mapUploadedFile(Request $request, ArgumentMetadata $argument, MapUploadedFile $attribute): UploadedFile|array|null
234234
{
235-
return $request->files->get($attribute->name ?? $argument->getName(), []);
235+
if (!($files = $request->files->get($attribute->name ?? $argument->getName(), [])) && ($argument->isNullable() || $argument->hasDefaultValue())) {
236+
return null;
237+
}
238+
239+
return $files;
236240
}
237241
}

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,66 @@ static function () {},
307307
$resolver->onKernelControllerArguments($event);
308308
}
309309

310+
/**
311+
* @dataProvider provideContext
312+
*/
313+
public function testShouldAllowEmptyWhenNullable(RequestPayloadValueResolver $resolver, Request $request)
314+
{
315+
$attribute = new MapUploadedFile();
316+
$argument = new ArgumentMetadata(
317+
'qux',
318+
UploadedFile::class,
319+
false,
320+
false,
321+
null,
322+
true,
323+
[$attribute::class => $attribute]
324+
);
325+
/** @var HttpKernelInterface&MockObject $httpKernel */
326+
$httpKernel = $this->createMock(HttpKernelInterface::class);
327+
$event = new ControllerArgumentsEvent(
328+
$httpKernel,
329+
static function () {},
330+
$resolver->resolve($request, $argument),
331+
$request,
332+
HttpKernelInterface::MAIN_REQUEST
333+
);
334+
$resolver->onKernelControllerArguments($event);
335+
$data = $event->getArguments()[0];
336+
337+
$this->assertNull($data);
338+
}
339+
340+
/**
341+
* @dataProvider provideContext
342+
*/
343+
public function testShouldAllowEmptyWhenHasDefaultValue(RequestPayloadValueResolver $resolver, Request $request)
344+
{
345+
$attribute = new MapUploadedFile();
346+
$argument = new ArgumentMetadata(
347+
'qux',
348+
UploadedFile::class,
349+
false,
350+
true,
351+
null,
352+
false,
353+
[$attribute::class => $attribute]
354+
);
355+
/** @var HttpKernelInterface&MockObject $httpKernel */
356+
$httpKernel = $this->createMock(HttpKernelInterface::class);
357+
$event = new ControllerArgumentsEvent(
358+
$httpKernel,
359+
static function () {},
360+
$resolver->resolve($request, $argument),
361+
$request,
362+
HttpKernelInterface::MAIN_REQUEST
363+
);
364+
$resolver->onKernelControllerArguments($event);
365+
$data = $event->getArguments()[0];
366+
367+
$this->assertNull($data);
368+
}
369+
310370
public static function provideContext(): iterable
311371
{
312372
$resolver = new RequestPayloadValueResolver(

0 commit comments

Comments
 (0)