Skip to content

Commit 7f61bfd

Browse files
Merge branch '8.0' into 8.1
* 8.0: [TwigBridge] Fix Bootstrap 4 horizontal layout broken by form errors moved outside label [HttpKernel] Fix denormalization format detection for pre-parsed request data
2 parents f76bada + 2aba779 commit 7f61bfd

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

Controller/ArgumentResolver/RequestPayloadValueResolver.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private function mapRequestPayload(Request $request, ArgumentMetadata $argument,
232232
if (\is_array($data)) {
233233
$data = $this->mergeParamsAndFiles($data, $request->files->all());
234234

235-
return $this->serializer->denormalize($data, $type, 'form' === $format ? 'csv' : $format, $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ('form' === $format ? ['filter_bool' => true] : []));
235+
return $this->serializer->denormalize($data, $type, self::hasNonStringScalar($data) ? $format : 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ('form' === $format ? ['filter_bool' => true] : []));
236236
}
237237

238238
if ('form' === $format) {
@@ -319,4 +319,21 @@ private function resolveValidationGroups(Expression|string|GroupSequence|\Closur
319319

320320
return $validationGroups;
321321
}
322+
323+
private static function hasNonStringScalar(array $data): bool
324+
{
325+
$stack = [$data];
326+
327+
while ($stack) {
328+
foreach (array_pop($stack) as $v) {
329+
if (\is_array($v)) {
330+
$stack[] = $v;
331+
} elseif (!\is_string($v)) {
332+
return true;
333+
}
334+
}
335+
}
336+
337+
return false;
338+
}
322339
}

Tests/Controller/ArgumentResolver/RequestPayloadValueResolverTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,32 @@ public function testMapRequestPayloadWithFormDataCoercesStringToBool()
13141314
$this->assertInstanceOf(FormPayloadWithBool::class, $payload);
13151315
$this->assertFalse($payload->active);
13161316
}
1317+
1318+
public function testMapRequestPayloadWithJsonContentTypeStringValuesCoercesToBool()
1319+
{
1320+
$serializer = new Serializer(
1321+
[new ObjectNormalizer(null, null, null, new ReflectionExtractor())],
1322+
[]
1323+
);
1324+
1325+
$resolver = new RequestPayloadValueResolver($serializer);
1326+
1327+
$argument = new ArgumentMetadata('payload', FormPayloadWithBool::class, false, false, null, false, [
1328+
MapRequestPayload::class => new MapRequestPayload(),
1329+
]);
1330+
$request = new Request([], ['active' => '0'], [], [], [], ['CONTENT_TYPE' => 'application/json']);
1331+
1332+
$kernel = $this->createStub(HttpKernelInterface::class);
1333+
$arguments = $resolver->resolve($request, $argument);
1334+
$event = new ControllerArgumentsEvent($kernel, static fn () => null, $arguments, $request, HttpKernelInterface::MAIN_REQUEST);
1335+
1336+
$resolver->onKernelControllerArguments($event);
1337+
1338+
/** @var FormPayloadWithBool $payload */
1339+
[$payload] = $event->getArguments();
1340+
$this->assertInstanceOf(FormPayloadWithBool::class, $payload);
1341+
$this->assertFalse($payload->active);
1342+
}
13171343
}
13181344

13191345
class RequestPayload

0 commit comments

Comments
 (0)