Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit bfcd041

Browse files
Adam Bensonweierophinney
authored andcommitted
#311 - Update NormalizeUploadedFiles to handle multi-dimension recursively
1 parent 43c791e commit bfcd041

File tree

2 files changed

+205
-14
lines changed

2 files changed

+205
-14
lines changed

src/functions/normalize_uploaded_files.php

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,45 @@
2424
*/
2525
function normalizeUploadedFiles(array $files)
2626
{
27+
/**
28+
* @param string[]|array[] $tmpNameTree
29+
* @param int[]|array[] $sizeTree
30+
* @param int[]|array[] $errorTree
31+
* @param string[]|array[]|null $nameTree
32+
* @param string[]|array[]|null $typeTree
33+
* @return UploadedFile[]|array[]
34+
*/
35+
$recursiveNormalize = function (
36+
array $tmpNameTree,
37+
array $sizeTree,
38+
array $errorTree,
39+
array $nameTree = null,
40+
array $typeTree = null
41+
) use (&$recursiveNormalize) {
42+
$normalized = [];
43+
foreach ($tmpNameTree as $key => $value) {
44+
if (is_array($value)) {
45+
// Traverse
46+
$normalized[$key] = $recursiveNormalize(
47+
$tmpNameTree[$key],
48+
$sizeTree[$key],
49+
$errorTree[$key],
50+
$nameTree[$key] ?? null,
51+
$typeTree[$key] ?? null
52+
);
53+
continue;
54+
}
55+
$normalized[$key] = createUploadedFile([
56+
'tmp_name' => $tmpNameTree[$key],
57+
'size' => $sizeTree[$key],
58+
'error' => $errorTree[$key],
59+
'name' => $nameTree[$key] ?? null,
60+
'type' => $typeTree[$key] ?? null
61+
]);
62+
}
63+
return $normalized;
64+
};
65+
2766
/**
2867
* Normalize an array of file specifications.
2968
*
@@ -38,7 +77,7 @@ function normalizeUploadedFiles(array $files)
3877
* @param array $files
3978
* @return UploadedFile[]
4079
*/
41-
$normalizeUploadedFileSpecification = function (array $files = []) {
80+
$normalizeUploadedFileSpecification = function (array $files = []) use (&$recursiveNormalize) {
4281
if (! isset($files['tmp_name']) || ! is_array($files['tmp_name'])
4382
|| ! isset($files['size']) || ! is_array($files['size'])
4483
|| ! isset($files['error']) || ! is_array($files['error'])
@@ -51,19 +90,13 @@ function normalizeUploadedFiles(array $files)
5190
));
5291
}
5392

54-
55-
$normalized = [];
56-
foreach (array_keys($files['tmp_name']) as $key) {
57-
$spec = [
58-
'tmp_name' => $files['tmp_name'][$key],
59-
'size' => $files['size'][$key],
60-
'error' => $files['error'][$key],
61-
'name' => isset($files['name'][$key]) ? $files['name'][$key] : null,
62-
'type' => isset($files['type'][$key]) ? $files['type'][$key] : null,
63-
];
64-
$normalized[$key] = createUploadedFile($spec);
65-
}
66-
return $normalized;
93+
return $recursiveNormalize(
94+
$files['tmp_name'],
95+
$files['size'],
96+
$files['error'],
97+
$files['name'] ?? null,
98+
$files['type'] ?? null
99+
);
67100
};
68101

69102
$normalized = [];
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4+
* @copyright Copyright (c) 2015-2017 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\Diactoros;
9+
10+
use PHPUnit\Framework\TestCase;
11+
use Psr\Http\Message\UploadedFileInterface;
12+
use function Zend\Diactoros\normalizeUploadedFiles;
13+
14+
class NormalizeUploadedFilesTest extends TestCase
15+
{
16+
public function testFlatFile()
17+
{
18+
$files = [
19+
'avatar' => [
20+
'tmp_name' => 'phpUxcOty',
21+
'name' => 'my-avatar.png',
22+
'size' => 90996,
23+
'type' => 'image/png',
24+
'error' => 0,
25+
],
26+
];
27+
28+
$normalised = normalizeUploadedFiles($files);
29+
30+
$this->assertCount(1, $normalised);
31+
$this->assertInstanceOf(UploadedFileInterface::class, $normalised['avatar']);
32+
$this->assertEquals('my-avatar.png', $normalised['avatar']->getClientFilename());
33+
}
34+
35+
public function testNestedFile()
36+
{
37+
$files = [
38+
'my-form' => [
39+
'details' => [
40+
'avatar' => [
41+
'tmp_name' => 'phpUxcOty',
42+
'name' => 'my-avatar.png',
43+
'size' => 90996,
44+
'type' => 'image/png',
45+
'error' => 0,
46+
],
47+
],
48+
],
49+
];
50+
51+
$normalised = normalizeUploadedFiles($files);
52+
53+
$this->assertCount(1, $normalised);
54+
$this->assertEquals('my-avatar.png', $normalised['my-form']['details']['avatar']->getClientFilename());
55+
}
56+
57+
public function testNumericIndexedFiles()
58+
{
59+
$files = [
60+
'my-form' => [
61+
'details' => [
62+
'avatars' => [
63+
'tmp_name' => [
64+
0 => 'abc123',
65+
1 => 'duck123',
66+
2 => 'goose123',
67+
],
68+
'name' => [
69+
0 => 'file1.txt',
70+
1 => 'file2.txt',
71+
2 => 'file3.txt',
72+
],
73+
'size' => [
74+
0 => 100,
75+
1 => 240,
76+
2 => 750,
77+
],
78+
'type' => [
79+
0 => 'plain/txt',
80+
1 => 'image/jpg',
81+
2 => 'image/png',
82+
],
83+
'error' => [
84+
0 => 0,
85+
1 => 0,
86+
2 => 0,
87+
],
88+
],
89+
],
90+
],
91+
];
92+
93+
$normalised = normalizeUploadedFiles($files);
94+
95+
$this->assertCount(3, $normalised['my-form']['details']['avatars']);
96+
$this->assertEquals('file1.txt', $normalised['my-form']['details']['avatars'][0]->getClientFilename());
97+
$this->assertEquals('file2.txt', $normalised['my-form']['details']['avatars'][1]->getClientFilename());
98+
$this->assertEquals('file3.txt', $normalised['my-form']['details']['avatars'][2]->getClientFilename());
99+
}
100+
101+
/**
102+
* This case covers upfront numeric index which moves the tmp_name/size/etc fields further up the array tree
103+
*/
104+
public function testNumericFirstIndexedFiles()
105+
{
106+
$files = [
107+
'slide-shows' => [
108+
'tmp_name' => [
109+
// Note: Nesting *under* tmp_name/etc
110+
0 => [
111+
'slides' => [
112+
0 => '/tmp/phpYzdqkD',
113+
1 => '/tmp/phpYzdfgh',
114+
],
115+
],
116+
],
117+
'error' => [
118+
0 => [
119+
'slides' => [
120+
0 => 0,
121+
1 => 0,
122+
],
123+
],
124+
],
125+
'name' => [
126+
0 => [
127+
'slides' => [
128+
0 => 'foo.txt',
129+
1 => 'bar.txt',
130+
],
131+
],
132+
],
133+
'size' => [
134+
0 => [
135+
'slides' => [
136+
0 => 123,
137+
1 => 200,
138+
],
139+
],
140+
],
141+
'type' => [
142+
0 => [
143+
'slides' => [
144+
0 => 'text/plain',
145+
1 => 'text/plain',
146+
],
147+
],
148+
],
149+
],
150+
];
151+
152+
$normalised = normalizeUploadedFiles($files);
153+
154+
$this->assertCount(2, $normalised['slide-shows'][0]['slides']);
155+
$this->assertEquals('foo.txt', $normalised['slide-shows'][0]['slides'][0]->getClientFilename());
156+
$this->assertEquals('bar.txt', $normalised['slide-shows'][0]['slides'][1]->getClientFilename());
157+
}
158+
}

0 commit comments

Comments
 (0)