diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index a3b0de8ef2..1b08f2f2a8 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -162,7 +162,7 @@ class Form extends FieldGroup * already merged into the data array. * * @param array $taintedValues The form data of the $_POST array - * @param array $taintedFiles The form data of the $_FILES array + * @param array $taintedFiles An array of uploaded files * @return boolean Whether the form is valid */ final public function bind($taintedValues, array $taintedFiles = null) @@ -173,8 +173,6 @@ class Form extends FieldGroup } $taintedFiles = array(); - } else { - $taintedFiles = self::convertFileInformation(self::fixPhpFilesArray($taintedFiles)); } if (null === $taintedValues) { @@ -458,69 +456,4 @@ class Form extends FieldGroup return $array1; } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * @param array $data - * @return array - */ - static protected function fixPhpFilesArray(array $data) - { - $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); - $keys = array_keys($data); - sort($keys); - - $files = $data; - - if ($fileKeys == $keys && isset($data['name']) && is_array($data['name'])) { - foreach ($fileKeys as $k) { - unset($files[$k]); - } - - foreach (array_keys($data['name']) as $key) { - $files[$key] = self::fixPhpFilesArray(array( - 'error' => $data['error'][$key], - 'name' => $data['name'][$key], - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - )); - } - } - - return $files; - } - - /** - * Converts uploaded files to instances of clsas UploadedFile. - * - * @param array $files A (multi-dimensional) array of uploaded file information - * @return array A (multi-dimensional) array of UploadedFile instances - */ - static protected function convertFileInformation(array $files) - { - $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); - - foreach ($files as $key => $data) { - if (is_array($data)) { - $keys = array_keys($data); - sort($keys); - - if ($keys == $fileKeys) { - $files[$key] = new UploadedFile($data['tmp_name'], $data['name'], $data['type'], $data['size'], $data['error']); - } else { - $files[$key] = self::convertFileInformation($data); - } - } - } - - return $files; - } } diff --git a/src/Symfony/Component/File/Exception/AccessDeniedException.php b/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php similarity index 91% rename from src/Symfony/Component/File/Exception/AccessDeniedException.php rename to src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php index f26b298123..5bc2f59a7e 100644 --- a/src/Symfony/Component/File/Exception/AccessDeniedException.php +++ b/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php @@ -1,6 +1,6 @@ $data) { - $files[$key] = $this->fixPhpFilesArray($data); + $fixedFiles = array(); + + foreach ($files as $key => $data) { + $fixedFiles[$key] = $this->fixPhpFilesArray($data); + } + + $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); + foreach ($fixedFiles as $key => $data) { + if (is_array($data)) { + $keys = array_keys($data); + sort($keys); + + if ($keys == $fileKeys) { + $fixedFiles[$key] = new UploadedFile($data['tmp_name'], $data['name'], $data['type'], $data['size'], $data['error']); + } else { + $fixedFiles[$key] = $this->convertFileInformation($data); + } + } + } + + return $fixedFiles; + } + + /** + * Fixes a malformed PHP $_FILES array. + * + * PHP has a bug that the format of the $_FILES array differs, depending on + * whether the uploaded file fields had normal field names or array-like + * field names ("normal" vs. "parent[child]"). + * + * This method fixes the array to look like the "normal" $_FILES array. + * + * It's safe to pass an already converted array, in which case this method + * just returns the original array unmodified. + * + * @param array $data + * @return array + */ + protected function fixPhpFilesArray($data) + { + $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); + $keys = array_keys($data); + sort($keys); + + if ($fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { + return $data; + } + + $files = $data; + foreach ($fileKeys as $k) { + unset($files[$k]); + } + foreach (array_keys($data['name']) as $key) { + $files[$key] = $this->fixPhpFilesArray(array( + 'error' => $data['error'][$key], + 'name' => $data['name'][$key], + 'type' => $data['type'][$key], + 'tmp_name' => $data['tmp_name'][$key], + 'size' => $data['size'][$key], + )); } return $files; @@ -888,31 +944,4 @@ class Request 'atom' => 'application/atom+xml', ); } - - static protected function fixPhpFilesArray($data) - { - $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); - $keys = array_keys($data); - sort($keys); - - if ($fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach ($fileKeys as $k) { - unset($files[$k]); - } - foreach (array_keys($data['name']) as $key) { - $files[$key] = self::fixPhpFilesArray(array( - 'error' => $data['error'][$key], - 'name' => $data['name'][$key], - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - )); - } - - return $files; - } } diff --git a/src/Symfony/Component/Validator/Constraints/FileValidator.php b/src/Symfony/Component/Validator/Constraints/FileValidator.php index 5651e75d91..a741560279 100644 --- a/src/Symfony/Component/Validator/Constraints/FileValidator.php +++ b/src/Symfony/Component/Validator/Constraints/FileValidator.php @@ -6,7 +6,7 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; -use Symfony\Component\File\File as FileObject; +use Symfony\Component\HttpFoundation\File\File as FileObject; class FileValidator extends ConstraintValidator { diff --git a/tests/Symfony/Tests/Component/Form/FormTest.php b/tests/Symfony/Tests/Component/Form/FormTest.php index fb06b90c90..f5829c8fd7 100644 --- a/tests/Symfony/Tests/Component/Form/FormTest.php +++ b/tests/Symfony/Tests/Component/Form/FormTest.php @@ -11,7 +11,6 @@ use Symfony\Component\Form\HiddenField; use Symfony\Component\Form\FieldGroup; use Symfony\Component\Form\HtmlGenerator; use Symfony\Component\Form\PropertyPath; -use Symfony\Component\File\UploadedFile; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Tests\Component\Form\Fixtures\Author; @@ -220,99 +219,6 @@ class FormTest extends \PHPUnit_Framework_TestCase $form->bind(array()); // irrelevant } - public function testBindConvertsUploadedFiles() - { - $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); - - $field = $this->createMockField('file'); - $field->expects($this->once()) - ->method('bind') - ->with($this->equalTo($file)); - - $form = new Form('author', new Author(), $this->validator); - $form->add($field); - - // test - $form->bind(array(), array('file' => array( - 'name' => basename($tmpFile), - 'type' => 'text/plain', - 'tmp_name' => $tmpFile, - 'error' => 0, - 'size' => 100 - ))); - } - - public function testBindConvertsUploadedFilesWithPhpBug() - { - $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); - - $field = $this->createMockField('file'); - $field->expects($this->once()) - ->method('bind') - ->with($this->equalTo($file)); - - $form = new Form('author', new Author(), $this->validator); - $form->add($field); - - // test - $form->bind(array(), array( - 'name' => array( - 'file' => basename($tmpFile), - ), - 'type' => array( - 'file' => 'text/plain', - ), - 'tmp_name' => array( - 'file' => $tmpFile, - ), - 'error' => array( - 'file' => 0, - ), - 'size' => array( - 'file' => 100, - ), - )); - } - - public function testBindConvertsNestedUploadedFilesWithPhpBug() - { - $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); - - $group = $this->getMock( - 'Symfony\Component\Form\FieldGroup', - array('bind'), - array('child', array('property_path' => null)) - ); - $group->expects($this->once()) - ->method('bind') - ->with($this->equalTo(array('file' => $file))); - - $form = new Form('author', new Author(), $this->validator); - $form->add($group); - - // test - $form->bind(array(), array( - 'name' => array( - 'child' => array('file' => basename($tmpFile)), - ), - 'type' => array( - 'child' => array('file' => 'text/plain'), - ), - 'tmp_name' => array( - 'child' => array('file' => $tmpFile), - ), - 'error' => array( - 'child' => array('file' => 0), - ), - 'size' => array( - 'child' => array('file' => 100), - ), - )); - } - public function testMultipartFormsWithoutParentsRequireFiles() { $form = new Form('author', new Author(), $this->validator); @@ -405,11 +311,6 @@ class FormTest extends \PHPUnit_Framework_TestCase return $field; } - protected function createTempFile() - { - return tempnam(sys_get_temp_dir(), 'FormTest'); - } - protected function createMockValidator() { return $this->getMock('Symfony\Component\Validator\ValidatorInterface'); diff --git a/tests/Symfony/Tests/Component/File/FileTest.php b/tests/Symfony/Tests/Component/HttpFoundation/File/FileTest.php similarity index 86% rename from tests/Symfony/Tests/Component/File/FileTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/File/FileTest.php index 7367f94088..a9cd82c158 100644 --- a/tests/Symfony/Tests/Component/File/FileTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/File/FileTest.php @@ -1,9 +1,9 @@ getMock('Symfony\Component\File\MimeType\MimeTypeGuesserInterface'); + $guesser = $this->getMock('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface'); $guesser->expects($this->once()) ->method('guess') ->with($this->equalTo($path)) diff --git a/tests/Symfony/Tests/Component/File/Fixtures/test b/tests/Symfony/Tests/Component/HttpFoundation/File/Fixtures/test similarity index 100% rename from tests/Symfony/Tests/Component/File/Fixtures/test rename to tests/Symfony/Tests/Component/HttpFoundation/File/Fixtures/test diff --git a/tests/Symfony/Tests/Component/File/Fixtures/test.gif b/tests/Symfony/Tests/Component/HttpFoundation/File/Fixtures/test.gif similarity index 100% rename from tests/Symfony/Tests/Component/File/Fixtures/test.gif rename to tests/Symfony/Tests/Component/HttpFoundation/File/Fixtures/test.gif diff --git a/tests/Symfony/Tests/Component/File/UploadedFileTest.php b/tests/Symfony/Tests/Component/HttpFoundation/File/UploadedFileTest.php similarity index 81% rename from tests/Symfony/Tests/Component/File/UploadedFileTest.php rename to tests/Symfony/Tests/Component/HttpFoundation/File/UploadedFileTest.php index 18469d1329..4e4e9108af 100644 --- a/tests/Symfony/Tests/Component/File/UploadedFileTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/File/UploadedFileTest.php @@ -1,8 +1,8 @@ setExpectedException('Symfony\Component\File\Exception\FileException'); + $this->setExpectedException('Symfony\Component\HttpFoundation\File\Exception\FileException'); new UploadedFile( __DIR__.'/Fixtures/test.gif', diff --git a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php index 2164b017a3..9062c18fed 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php @@ -12,6 +12,7 @@ namespace Symfony\Tests\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\File\UploadedFile; class RequestTest extends \PHPUnit_Framework_TestCase { @@ -107,4 +108,83 @@ class RequestTest extends \PHPUnit_Framework_TestCase $request->server->set('QUERY_STRING', 'foo=1&foo=2'); $this->assertEquals('foo=1&foo=2', $request->getQueryString(), '->getQueryString() allows repeated parameters'); } + + public function testInitializeConvertsUploadedFiles() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $request = Request::create('', 'get', array(), array(), array('file' => array( + 'name' => basename($tmpFile), + 'type' => 'text/plain', + 'tmp_name' => $tmpFile, + 'error' => 0, + 'size' => 100 + ))); + + $this->assertEquals($file, $request->files->get('file')); + } + + public function testInitializeConvertsUploadedFilesWithPhpBug() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $request = Request::create('', 'get', array(), array(), array( + 'child' => array( + 'name' => array( + 'file' => basename($tmpFile), + ), + 'type' => array( + 'file' => 'text/plain', + ), + 'tmp_name' => array( + 'file' => $tmpFile, + ), + 'error' => array( + 'file' => 0, + ), + 'size' => array( + 'file' => 100, + ), + ) + )); + + $files = $request->files->all(); + $this->assertEquals($file, $files['child']['file']); + } + + public function testInitializeConvertsNestedUploadedFilesWithPhpBug() + { + $tmpFile = $this->createTempFile(); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + + $request = Request::create('', 'get', array(), array(), array( + 'child' => array( + 'name' => array( + 'sub' => array('file' => basename($tmpFile)) + ), + 'type' => array( + 'sub' => array('file' => 'text/plain') + ), + 'tmp_name' => array( + 'sub' => array('file' => $tmpFile) + ), + 'error' => array( + 'sub' => array('file' => 0) + ), + 'size' => array( + 'sub' => array('file' => 100) + ), + ) + )); + + $files = $request->files->all(); + $this->assertEquals($file, $files['child']['sub']['file']); + } + + protected function createTempFile() + { + return tempnam(sys_get_temp_dir(), 'FormTest'); + } } diff --git a/tests/Symfony/Tests/Component/Validator/Constraints/FileValidatorTest.php b/tests/Symfony/Tests/Component/Validator/Constraints/FileValidatorTest.php index 4ddacdac93..fc9950aa6b 100644 --- a/tests/Symfony/Tests/Component/Validator/Constraints/FileValidatorTest.php +++ b/tests/Symfony/Tests/Component/Validator/Constraints/FileValidatorTest.php @@ -120,7 +120,7 @@ class FileValidatorTest extends \PHPUnit_Framework_TestCase public function testValidMimeType() { - $file = $this->getMock('Symfony\Component\File\File', array(), array(), '', false); + $file = $this->getMock('Symfony\Component\HttpFoundation\File\File', array(), array(), '', false); $file->expects($this->any()) ->method('getPath') ->will($this->returnValue($this->path)); @@ -137,7 +137,7 @@ class FileValidatorTest extends \PHPUnit_Framework_TestCase public function testInvalidMimeType() { - $file = $this->getMock('Symfony\Component\File\File', array(), array(), '', false); + $file = $this->getMock('Symfony\Component\HttpFoundation\File\File', array(), array(), '', false); $file->expects($this->any()) ->method('getPath') ->will($this->returnValue($this->path));