8000 feature #38323 [Mime] Allow multiple parts with the same name in Form… · symfony/symfony@a3e8c11 · GitHub
[go: up one dir, main page]

Skip to content

Commit a3e8c11

Browse files
committed
feature #38323 [Mime] Allow multiple parts with the same name in FormDataPart (HypeMC)
This PR was merged into the 5.2-dev branch. Discussion ---------- [Mime] Allow multiple parts with the same name in FormDataPart | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #38258 | License | MIT | Doc PR | - Added the possibility to choose whether multiple parts with the same name should be suffixed or not: ```php $f1 = new FormDataPart([ 'foo' => [ 'one', 'two', ], ]); var_dump($f1->toString()); ``` ``` Content-Type: multipart/form-data; boundary=6rqazwiG --6rqazwiG Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo[0]" one --6rqazwiG Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo[1]" two --6rqazwiG-- ``` ```php $f1 = new FormDataPart([ ['foo' => 'one'], ['foo' => 'two'], ]); var_dump($f1->toString()); ``` ``` Content-Type: multipart/form-data; boundary=xxW9dGzq --xxW9dGzq Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo" one --xxW9dGzq Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo" two --xxW9dGzq-- ``` Only applies to numeric keys: ```php $f1 = new FormDataPart([ 'foo' => [ 'a' => 'one', 'b' => 'two', ], ], true); var_dump($f1->toString()); ``` ``` Content-Type: multipart/form-data; boundary=W6qkqgrD --W6qkqgrD Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo[a]" one --W6qkqgrD Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Disposition: form-data; name="foo[b]" two --W6qkqgrD-- ``` Commits ------- 1f7f2c6 Allow multiple parts with the same name in FormDataPart
2 parents 9d6333a + 1f7f2c6 commit a3e8c11

File tree

2 files changed

+119
-4
lines changed

2 files changed

+119
-4
lines changed

src/Symfony/Component/Mime/Part/Multipart/FormDataPart.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,16 @@ private function prepareFields(array $fields): array
5858
$values = [];
5959

6060
$prepare = function ($item, $key, $root = null) use (&$values, &$prepare) {
61-
$fieldName = $root ? sprintf('%s[%s]', $root, $key) : $key;
61+
if (\is_int($key) && \is_array($item)) {
62+
if (1 !== \count($item)) {
63+
throw new InvalidArgumentException(sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item)));
64+
}
65+
66+
$key = key($item);
67+
$item = $item[$key];
68+
}
69+
70+
$fieldName = null !== $root ? sprintf('%s[%s]', $root, $key) : $key;
6271

6372
if (\is_array($item)) {
6473
array_walk($item, $prepare, $fieldName);

src/Symfony/Component/Mime/Tests/Part/Multipart/FormDataPartTest.php

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Mime\Tests\Part\Multipart;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Mime\Exception\InvalidArgumentException;
1516
use Symfony\Component\Mime\Part\DataPart;
1617
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
1718
use Symfony\Component\Mime\Part\TextPart;
@@ -58,21 +59,126 @@ public function testNestedArrayParts()
5859
'qux' => clone $p1,
5960
],
6061
],
62+
'quux' => [
63+
clone $p1,
64+
clone $p1,
65+
],
66+
'quuz' => [
67+
'corge' => [
68+
clone $p1,
69+
clone $p1,
70+
],
71+
],
72+
'2' => clone $p1,
73+
'0' => clone $p1,
74+
75+
'bar2' => [
76+
['baz' => clone $p1],
77+
'baz' => [
78+
'qux' => clone $p1,
79+
],
80+
],
81+
['quux2' => clone $p1],
82+
['quux2' => clone $p1],
83+
'quuz2' => [
84+
['corge' => clone $p1],
85+
['corge' => clone $p1],
86+
],
87+
['2' => clone $p1],
88+
['2' => clone $p1],
89+
['0' => clone $p1],
90+
['0' => clone $p1],
91+
92+
['2[0]' => clone $p1],
93+
['2[1]' => clone $p1],
94+
['0[0]' => clone $p1],
95+
['0[1]' => clone $p1],
6196
]);
6297

6398
$this->assertEquals('multipart', $f->getMediaType());
6499
$this->assertEquals('form-data', $f->getMediaSubtype());
65100

101+
$parts = [];
102+
103+
$parts[] = $p1;
66104
$p1->setName('foo');
67105
$p1->setDisposition('form-data');
68106

69-
$p2 = clone $p1;
107+
$parts[] = $p2 = clone $p1;
70108
$p2->setName('bar[baz][0]');
71109

72-
$p3 = clone $p1;
110+
$parts[] = $p3 = clone $p1;
73111
$p3->setName('bar[baz][qux]');
74112

75-
$this->assertEquals([$p1, $p2, $p3], $f->getParts());
113+
$parts[] = $p4 = clone $p1;
114+
$p4->setName('quux[0]');
115+
$parts[] = $p5 = clone $p1;
116+
$p5->setName('quux[1]');
117+
118+
$parts[] = $p6 = clone $p1;
119+
$p6->setName('quuz[corge][0]');
120+
$parts[] = $p7 = clone $p1;
121+
$p7->setName('quuz[corge][1]');
122+
123+
$parts[] = $p8 = clone $p1;
124+
$p8->setName('2');
125+
126+
$parts[] = $p9 = clone $p1;
127+
$p9->setName('0');
128+
129+
$parts[] = $p10 = clone $p1;
130+
$p10->setName('bar2[baz]');
131+
132+
$parts[] = $p11 = clone $p1;
133+
$p11->setName('bar2[baz][qux]');
134+
135+
$parts[] = $p12 = clone $p1;
136+
$p12->setName('quux2');
137+
$parts[] = $p13 = clone $p1;
138+
$p13->setName('quux2');
139+
140+
$parts[] = $p14 = clone $p1;
141+
$p14->setName('quuz2[corge]');
142+
$parts[] = $p15 = clone $p1;
143+
$p15->setName('quuz2[corge]');
144+
145+
$parts[] = $p16 = clone $p1;
146+
$p16->setName('2');
147+
$parts[] = $p17 = clone $p1;
148+
$p17->setName('2');
149+
150+
$parts[] = $p18 = clone $p1;
151+
$p18->setName('0');
152+
$parts[] = $p19 = clone $p1;
153+
$p19->setName('0');
154+
155+
$parts[] = $p16 = clone $p1;
156+
$p16->setName('2[0]');
157+
$parts[] = $p17 = clone $p1;
158+
$p17->setName('2[1]');
159+
160+
$parts[] = $p18 = clone $p1;
161+
$p18->setName('0[0]');
162+
$parts[] = $p19 = clone $p1;
163+
$p19->setName('0[1]');
164+
165+
$this->assertEquals($parts, $f->getParts());
166+
}
167+
168+
public function testExceptionOnFormFieldsWithIntegerKeysAndMultipleValues()
169+
{
170+
$p1 = new TextPart('content', 'utf-8', 'plain', '8bit');
171+
$f = new FormDataPart([
172+
[
173+
clone $p1,
174+
clone $p1,
175+
],
176+
]);
177+
178+
$this->expectException(InvalidArgumentException::class);
179+
$this->expectExceptionMessage('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, 2 provided.');
180+
181+
$f->getParts();
76182
}
77183

78184
public function testToString()

0 commit comments

Comments
 (0)
0