From c10bc75a4623d5f87c6289bc27089d4469ccfcc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20lombardot?= Date: Mon, 18 Nov 2024 19:40:08 +0100 Subject: [PATCH 1/3] Fix MultipartDecoder to support more denormalization types --- core/file-upload.md | 67 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/core/file-upload.md b/core/file-upload.md index 703ba86fef0..85726341b7c 100644 --- a/core/file-upload.md +++ b/core/file-upload.md @@ -394,10 +394,15 @@ We need to create our own decoder to do it: requestStack->getCurrentRequest(); - if (!$request) { + if (!$request || !isset($context['resource_class'])) { return null; } - return array_map(static function (string $element) { + // Retrieve the target class from the context + $targetClass = $context['resource_class']; + + // Get the expected types for the target entity + $expectedTypes = $this->getPropertyTypes($targetClass); + + $arrayMapWithKeys = function (callable $callback, array $array) { + $result = []; + + foreach ($array as $key => $value) { + $result[$key] = $callback($value, $key); + } + + return $result; + }; + + $map = $arrayMapWithKeys(static function (string $element, string $key) use ($expectedTypes) { // Multipart form values will be encoded in JSON. $decoded = json_decode($element, true); - return \is_array($decoded) ? $decoded : $element; - }, $request->request->all()) + $request->files->all(); + if (is_array($decoded)) { + return $decoded; + } + + if ('null' == $element) { + return null; + } + + if (!isset($expectedTypes[$key])) { + return $element; + } + + return match ($expectedTypes[$key]) { + 'bool' => filter_var($element, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE), + 'int' => is_numeric($element) ? (int) $element : $element, + 'float' => is_numeric($element) ? (float) $element : $element, + Collection::class => !is_array($element) ? [] : $element, + default => $element, + }; + }, $request->request->all()); + + // dd($map + $request->files->all()); + + return $map + $request->files->all(); } public function supportsDecoding(string $format): bool { return self::FORMAT === $format; } + + private function getPropertyTypes(string $className): array + { + $reflectionClass = new ReflectionClass($className); + $types = []; + + foreach ($reflectionClass->getProperties() as $property) { + $type = $property->getType(); + if ($type instanceof ReflectionNamedType) { + $types[$property->getName()] = $type->getName(); + } + } + + return $types; + } } + ``` If you're not using `autowiring` and `autoconfiguring`, don't forget to register the service and tag it as `serializer.encoder`. From 595ced315adcfbaccb3ac4f1982a1621f236c319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20lombardot?= Date: Mon, 18 Nov 2024 19:45:06 +0100 Subject: [PATCH 2/3] Update file-upload.md --- core/file-upload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/file-upload.md b/core/file-upload.md index 85726341b7c..a2b9f3316bd 100644 --- a/core/file-upload.md +++ b/core/file-upload.md @@ -456,7 +456,7 @@ final class MultipartDecoder implements DecoderInterface 'bool' => filter_var($element, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE), 'int' => is_numeric($element) ? (int) $element : $element, 'float' => is_numeric($element) ? (float) $element : $element, - Collection::class => !is_array($element) ? [] : $element, + Collection::class => '' == $element ? [] : $element, default => $element, }; }, $request->request->all()); From 8606c79d0ad93da77887f6f64c82333a27d02870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20lombardot?= Date: Mon, 18 Nov 2024 19:49:33 +0100 Subject: [PATCH 3/3] Update file-upload.md --- core/file-upload.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/file-upload.md b/core/file-upload.md index a2b9f3316bd..736fc1a2bee 100644 --- a/core/file-upload.md +++ b/core/file-upload.md @@ -460,9 +460,7 @@ final class MultipartDecoder implements DecoderInterface default => $element, }; }, $request->request->all()); - - // dd($map + $request->files->all()); - + return $map + $request->files->all(); }