diff --git a/src/Form.php b/src/Form.php index bf790eb8..55b0374c 100644 --- a/src/Form.php +++ b/src/Form.php @@ -49,6 +49,39 @@ public function addField(string $name, string $content, ?string $contentType = n $this->fields[] = new FormField($name, BufferedContent::fromString($content, $contentType)); } + /** + * Adds each member of the array as an entry for the given key name. Array keys are persevered. + * + * @param array $fields + */ + public function addNestedFields(string $name, array $fields): void + { + foreach ($this->flattenArray($fields) as $key => $value) { + $this->addField($name . $key, $value); + } + } + + /** + * @return array + */ + private function flattenArray(array $fields): array + { + $result = []; + foreach ($fields as $outerKey => $value) { + $key = "[{$outerKey}]"; + if (!\is_array($value)) { + $result[$key] = (string) $value; + continue; + } + + foreach ($this->flattenArray($value) as $innerKey => $flattened) { + $result[$key . $innerKey] = $flattened; + } + } + + return $result; + } + public function addStream(string $name, HttpContent $content, ?string $filename = null): void { if ($this->used) { diff --git a/test/FormTest.php b/test/FormTest.php index af792222..78e5483a 100644 --- a/test/FormTest.php +++ b/test/FormTest.php @@ -16,8 +16,36 @@ public function testUrlEncoded(): void $body->addField('d', 'd'); $body->addField('encoding', '1+2'); + $body->addNestedFields('list', ['one', 'two']); + $body->addNestedFields('map', ['one' => 'one', 'two' => 'two']); + + $content = buffer($body->getContent()); + $this->assertEquals("a=a&b=b&c=c&d=d&encoding=1%2B2&list%5B0%5D=one&list%5B1%5D=two&map%5Bone%5D=one&map%5Btwo%5D=two", $content); + } + + public function testNestedArrays(): void + { + $body = new Form(); + + $body->addNestedFields('map', [ + [ + 'one' => 'one', + 'two' => 'two', + ], + [ + 'one' => [1], + 'two' => [1, 2], + 'three' => [1, 2, 3], + ], + [ + 3 => 'three', + 10 => 'ten', + 42 => 'forty-two', + ], + ]); + $content = buffer($body->getContent()); - $this->assertEquals("a=a&b=b&c=c&d=d&encoding=1%2B2", $content); + $this->assertEquals("map%5B0%5D%5Bone%5D=one&map%5B0%5D%5Btwo%5D=two&map%5B1%5D%5Bone%5D%5B0%5D=1&map%5B1%5D%5Btwo%5D%5B0%5D=1&map%5B1%5D%5Btwo%5D%5B1%5D=2&map%5B1%5D%5Bthree%5D%5B0%5D=1&map%5B1%5D%5Bthree%5D%5B1%5D=2&map%5B1%5D%5Bthree%5D%5B2%5D=3&map%5B2%5D%5B3%5D=three&map%5B2%5D%5B10%5D=ten&map%5B2%5D%5B42%5D=forty-two", $content); } public function testMultiPartFieldsStream(): void