Skip to content

Commit 3d4a4e1

Browse files
bug symfony#52021 [Form] Fix merging params & files when "multiple" is enabled (priyadi)
This PR was merged into the 5.4 branch. Discussion ---------- [Form] Fix merging params & files when "multiple" is enabled | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | | License | MIT If a form field is configured with the "multiple" option, the request handler merges param values with uploaded files. However, it does not merge correctly if "multiple" is enabled. Example: <input type="file" name="param[]" /> <input type="hidden" name="param[]" value="data1" /> <input type="hidden" name="param[]" value="data2" /> With the example, the file field will incorrectly replace the first hidden field, when they should be merged. This commit fixes the problem. Commits ------- 4da09bc [Form] Fix merging params & files when "multiple" is enabled
2 parents a0df509 + 4da09bc commit 3d4a4e1

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Form\FormError;
1616
use Symfony\Component\Form\FormInterface;
1717
use Symfony\Component\Form\RequestHandlerInterface;
18+
use Symfony\Component\Form\Util\FormUtil;
1819
use Symfony\Component\Form\Util\ServerParams;
1920
use Symfony\Component\HttpFoundation\File\File;
2021
use Symfony\Component\HttpFoundation\File\UploadedFile;
@@ -95,7 +96,7 @@ public function handleRequest(FormInterface $form, $request = null)
9596
}
9697

9798
if (\is_array($params) && \is_array($files)) {
98-
$data = array_replace_recursive($params, $files);
99+
$data = FormUtil::mergeParamsAndFiles($params, $files);
99100
} else {
100101
$data = $params ?: $files;
101102
}

src/Symfony/Component/Form/NativeRequestHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Form;
1313

1414
use Symfony\Component\Form\Exception\UnexpectedTypeException;
15+
use Symfony\Component\Form\Util\FormUtil;
1516
use Symfony\Component\Form\Util\ServerParams;
1617

1718
/**
@@ -106,7 +107,7 @@ public function handleRequest(FormInterface $form, $request = null)
106107
}
107108

108109
if (\is_array($params) && \is_array($files)) {
109-
$data = array_replace_recursive($params, $files);
110+
$data = FormUtil::mergeParamsAndFiles($params, $files);
110111
} else {
111112
$data = $params ?: $files;
112113
}

src/Symfony/Component/Form/Tests/AbstractRequestHandlerTestCase.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,42 @@ public function testMergeParamsAndFiles($method)
236236
$this->assertSame($file, $form->get('field2')->getData());
237237
}
238238

239+
/**
240+
* @dataProvider methodExceptGetProvider
241+
*/
242+
public function testMergeParamsAndFilesMultiple($method)
243+
{
244+
$form = $this->createForm('param1', $method, true);
245+
$form->add($this->createBuilder('field1', false, ['allow_file_upload' => true, 'multiple' => true])->getForm());
246+
$file1 = $this->getUploadedFile();
247+
$file2 = $this->getUploadedFile();
248+
249+
$this->setRequestData($method, [
250+
'param1' => [
251+
'field1' => [
252+
'foo',
253+
'bar',
254+
'baz',
255+
],
256+
],
257+
], [
258+
'param1' => [
259+
'field1' => [
260+
$file1,
261+
$file2,
262+
],
263+
],
264+
]);
265+
266+
$this->requestHandler->handleRequest($form, $this->request);
267+
$data = $form->get('field1')->getData();
268+
269+
$this->assertTrue($form->isSubmitted());
270+
$this->assertIsArray($data);
271+
$this->assertCount(5, $data);
272+
$this->assertSame(['foo', 'bar', 'baz', $file1, $file2], $data);
273+
}
274+
239275
/**
240276
* @dataProvider methodExceptGetProvider
241277
*/

src/Symfony/Component/Form/Util/FormUtil.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,29 @@ public static function isEmpty($data)
4141
// not considered to be empty, ever.
4242
return null === $data || '' === $data;
4343
}
44+
45+
/**
46+
* Recursively replaces or appends elements of the first array with elements
47+
* of second array. If the key is an integer, the values will be appended to
48+
* the new array; otherwise, the value from the second array will replace
49+
* the one from the first array.
50+
*/
51+
public static function mergeParamsAndFiles(array $params, array $files): array
52+
{
53+
$result = [];
54+
55+
foreach ($params as $key => $value) {
56+
if (\is_array($value) && \is_array($files[$key] ?? null)) {
57+
$value = self::mergeParamsAndFiles($value, $files[$key]);
58+
unset($files[$key]);
59+
}
60+
if (\is_int($key)) {
61+
$result[] = $value;
62+
} else {
63+
$result[$key] = $value;
64+
}
65+
}
66+
67+
return array_merge($result, $files);
68+
}
4469
}

0 commit comments

Comments
 (0)