Skip to content

Commit 482d5f7

Browse files
committed
Fixes php-http#226 TypeError thrown by requests with nested files
1 parent 1ce09e7 commit 482d5f7

File tree

2 files changed

+66
-8
lines changed

2 files changed

+66
-8
lines changed

src/Psr17Factory.php

+47-7
Original file line numberDiff line numberDiff line change
@@ -266,17 +266,57 @@ private function normalizeFiles(array $files): array
266266
continue;
267267
} elseif (!isset($value['tmp_name'])) {
268268
$normalized[$key] = $this->normalizeFiles($value);
269-
} elseif (\is_array($value['tmp_name'])) {
270-
foreach ($value['tmp_name'] as $k => $v) {
271-
$file = $this->createStreamFromFile($value['tmp_name'][$k], 'r');
272-
$normalized[$key][$k] = $this->createUploadedFile($file, $value['size'][$k], $value['error'][$k], $value['name'][$k], $value['type'][$k]);
273-
}
274269
} else {
275-
$file = $this->createStreamFromFile($value['tmp_name'], 'r');
276-
$normalized[$key] = $this->createUploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']);
270+
$normalized[$key] = $this->createUploadedFileFromSpec($value);
277271
}
278272
}
279273

280274
return $normalized;
281275
}
276+
277+
/**
278+
* Create and return an UploadedFile instance from a $_FILES specification.
279+
*
280+
* If the specification represents an array of values, this method will
281+
* delegate to normalizeNestedFileSpec() and return that return value.
282+
*
283+
* @param array $value $_FILES struct
284+
*
285+
* @return UploadedFileInterface|UploadedFileInterface[]
286+
*/
287+
private function createUploadedFileFromSpec(array $value)
288+
{
289+
if (is_array($value['tmp_name'])) {
290+
return $this->normalizeNestedFileSpec($value);
291+
}
292+
293+
$file = $this->createStreamFromFile($value['tmp_name'], 'r');
294+
return $this->createUploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']);
295+
}
296+
297+
/**
298+
* Normalize an array of file specifications.
299+
*
300+
* Loops through all nested files and returns a normalized array of
301+
* UploadedFileInterface instances.
302+
*
303+
* @return UploadedFileInterface[]
304+
*/
305+
private function normalizeNestedFileSpec(array $files = []): array
306+
{
307+
$normalizedFiles = [];
308+
309+
foreach (array_keys($files['tmp_name']) as $key) {
310+
$spec = [
311+
'tmp_name' => $files['tmp_name'][$key],
312+
'size' => $files['size'][$key] ?? null,
313+
'error' => $files['error'][$key] ?? null,
314+
'name' => $files['name'][$key] ?? null,
315+
'type' => $files['type'][$key] ?? null,
316+
];
317+
$normalizedFiles[$key] = $this->createUploadedFileFromSpec($spec);
318+
}
319+
320+
return $normalizedFiles;
321+
}
282322
}

tests/Psr17FactoryTest.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,14 @@ public function testFromGlobals()
285285
'tmp_name' => 'php://memory',
286286
'error' => UPLOAD_ERR_OK,
287287
'size' => 123,
288-
]
288+
],
289+
'files' => [
290+
'name' => ['file_0' => [0 => 'NestedFile.txt']],
291+
'type' => ['file_0' => [0 => 'text/plain']],
292+
'tmp_name' => ['file_0' => [0 => 'php://memory']],
293+
'error' => ['file_0' => [0 => UPLOAD_ERR_OK]],
294+
'size' => ['file_0' => [0 => 123]],
295+
],
289296
];
290297

291298
$factory = new Psr17Factory();
@@ -318,6 +325,17 @@ public function testFromGlobals()
318325
'MyFile.txt',
319326
'text/plain'
320327
),
328+
'files' => [
329+
'file_0' => [
330+
0 => $factory->createUploadedFile(
331+
$server->getUploadedFiles()['files']['file_0'][0]->getStream(),
332+
123,
333+
UPLOAD_ERR_OK,
334+
'NestedFile.txt',
335+
'text/plain'
336+
),
337+
],
338+
],
321339
];
322340

323341
self::assertEquals($expectedFiles, $server->getUploadedFiles());

0 commit comments

Comments
 (0)