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

Commit

Permalink
Merge branch 'hotfix/312-normalize-nested-uploaded-files'
Browse files Browse the repository at this point in the history
Close #312
Fixes #311
  • Loading branch information
weierophinney committed Jul 9, 2018
2 parents 43c791e + 2bbccb7 commit 63d920d
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 16 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.8.1 - TBD
## 1.8.1 - 2018-07-09

### Added

Expand All @@ -23,7 +23,8 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- Nothing.
- [#312](https://github.com/zendframework/zend-diactoros/pull/312) fixes how the `normalizeUploadedFiles()` utility function handles nested trees of
uploaded files, ensuring it detects them properly.

## 1.8.0 - 2018-06-27

Expand Down
63 changes: 49 additions & 14 deletions src/functions/normalize_uploaded_files.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,47 @@
*/
function normalizeUploadedFiles(array $files)
{
/**
* Traverse a nested tree of uploaded file specifications.
*
* @param string[]|array[] $tmpNameTree
* @param int[]|array[] $sizeTree
* @param int[]|array[] $errorTree
* @param string[]|array[]|null $nameTree
* @param string[]|array[]|null $typeTree
* @return UploadedFile[]|array[]
*/
$recursiveNormalize = function (
array $tmpNameTree,
array $sizeTree,
array $errorTree,
array $nameTree = null,
array $typeTree = null
) use (&$recursiveNormalize) {
$normalized = [];
foreach ($tmpNameTree as $key => $value) {
if (is_array($value)) {
// Traverse
$normalized[$key] = $recursiveNormalize(
$tmpNameTree[$key],
$sizeTree[$key],
$errorTree[$key],
isset($nameTree[$key]) ? $nameTree[$key] : null,
isset($typeTree[$key]) ? $typeTree[$key] : null
);
continue;
}
$normalized[$key] = createUploadedFile([
'tmp_name' => $tmpNameTree[$key],
'size' => $sizeTree[$key],
'error' => $errorTree[$key],
'name' => isset($nameTree[$key]) ? $nameTree[$key] : null,
'type' => isset($typeTree[$key]) ? $typeTree[$key] : null
]);
}
return $normalized;
};

/**
* Normalize an array of file specifications.
*
Expand All @@ -38,7 +79,7 @@ function normalizeUploadedFiles(array $files)
* @param array $files
* @return UploadedFile[]
*/
$normalizeUploadedFileSpecification = function (array $files = []) {
$normalizeUploadedFileSpecification = function (array $files = []) use (&$recursiveNormalize) {
if (! isset($files['tmp_name']) || ! is_array($files['tmp_name'])
|| ! isset($files['size']) || ! is_array($files['size'])
|| ! isset($files['error']) || ! is_array($files['error'])
Expand All @@ -51,19 +92,13 @@ function normalizeUploadedFiles(array $files)
));
}


$normalized = [];
foreach (array_keys($files['tmp_name']) as $key) {
$spec = [
'tmp_name' => $files['tmp_name'][$key],
'size' => $files['size'][$key],
'error' => $files['error'][$key],
'name' => isset($files['name'][$key]) ? $files['name'][$key] : null,
'type' => isset($files['type'][$key]) ? $files['type'][$key] : null,
];
$normalized[$key] = createUploadedFile($spec);
}
return $normalized;
return $recursiveNormalize(
$files['tmp_name'],
$files['size'],
$files['error'],
isset($files['name']) ? $files['name'] : null,
isset($files['type']) ? $files['type'] : null
);
};

$normalized = [];
Expand Down
160 changes: 160 additions & 0 deletions test/functions/NormalizeUploadedFilesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php
/**
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
*/

namespace ZendTest\Diactoros;

use PHPUnit\Framework\TestCase;
use Psr\Http\Message\UploadedFileInterface;

use function Zend\Diactoros\normalizeUploadedFiles;

class NormalizeUploadedFilesTest extends TestCase
{
public function testCreatesUploadedFileFromFlatFileSpecification()
{
$files = [
'avatar' => [
'tmp_name' => 'phpUxcOty',
'name' => 'my-avatar.png',
'size' => 90996,
'type' => 'image/png',
'error' => 0,
],
];

$normalised = normalizeUploadedFiles($files);

$this->assertCount(1, $normalised);
$this->assertInstanceOf(UploadedFileInterface::class, $normalised['avatar']);
$this->assertEquals('my-avatar.png', $normalised['avatar']->getClientFilename());
}

public function testTraversesNestedFileSpecificationToExtractUploadedFile()
{
$files = [
'my-form' => [
'details' => [
'avatar' => [
'tmp_name' => 'phpUxcOty',
'name' => 'my-avatar.png',
'size' => 90996,
'type' => 'image/png',
'error' => 0,
],
],
],
];

$normalised = normalizeUploadedFiles($files);

$this->assertCount(1, $normalised);
$this->assertEquals('my-avatar.png', $normalised['my-form']['details']['avatar']->getClientFilename());
}

public function testTraversesNestedFileSpecificationContainingNumericIndicesToExtractUploadedFiles()
{
$files = [
'my-form' => [
'details' => [
'avatars' => [
'tmp_name' => [
0 => 'abc123',
1 => 'duck123',
2 => 'goose123',
],
'name' => [
0 => 'file1.txt',
1 => 'file2.txt',
2 => 'file3.txt',
],
'size' => [
0 => 100,
1 => 240,
2 => 750,
],
'type' => [
0 => 'plain/txt',
1 => 'image/jpg',
2 => 'image/png',
],
'error' => [
0 => 0,
1 => 0,
2 => 0,
],
],
],
],
];

$normalised = normalizeUploadedFiles($files);

$this->assertCount(3, $normalised['my-form']['details']['avatars']);
$this->assertEquals('file1.txt', $normalised['my-form']['details']['avatars'][0]->getClientFilename());
$this->assertEquals('file2.txt', $normalised['my-form']['details']['avatars'][1]->getClientFilename());
$this->assertEquals('file3.txt', $normalised['my-form']['details']['avatars'][2]->getClientFilename());
}

/**
* This case covers upfront numeric index which moves the tmp_name/size/etc
* fields further up the array tree
*/
public function testTraversesDenormalizedNestedTreeOfIndicesToExtractUploadedFiles()
{
$files = [
'slide-shows' => [
'tmp_name' => [
// Note: Nesting *under* tmp_name/etc
0 => [
'slides' => [
0 => '/tmp/phpYzdqkD',
1 => '/tmp/phpYzdfgh',
],
],
],
'error' => [
0 => [
'slides' => [
0 => 0,
1 => 0,
],
],
],
'name' => [
0 => [
'slides' => [
0 => 'foo.txt',
1 => 'bar.txt',
],
],
],
'size' => [
0 => [
'slides' => [
0 => 123,
1 => 200,
],
],
],
'type' => [
0 => [
'slides' => [
0 => 'text/plain',
1 => 'text/plain',
],
],
],
],
];

$normalised = normalizeUploadedFiles($files);

$this->assertCount(2, $normalised['slide-shows'][0]['slides']);
$this->assertEquals('foo.txt', $normalised['slide-shows'][0]['slides'][0]->getClientFilename());
$this->assertEquals('bar.txt', $normalised['slide-shows'][0]['slides'][1]->getClientFilename());
}
}

0 comments on commit 63d920d

Please sign in to comment.