From bbc1cb82702b678b21bef15394f067c146e47625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thierry=20Fran=C3=A7ois?= Date: Sat, 20 Sep 2014 17:09:48 +0300 Subject: [PATCH] FIX #3458 iframe transport multi file upload FIX #3343, FIX #3148 UploadField now handles multiple file upload through iframe transport correctly (mainly for IE) as well as upload errors on a per file basis. --- filesystem/Upload.php | 9 ++++++++ forms/UploadField.php | 25 ++++++++++++--------- tests/forms/uploadfield/UploadFieldTest.php | 9 ++++---- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/filesystem/Upload.php b/filesystem/Upload.php index 370116ff3..6c2e8a97e 100644 --- a/filesystem/Upload.php +++ b/filesystem/Upload.php @@ -270,9 +270,11 @@ class Upload extends Controller { /** * Clear out all errors (mostly set by {loadUploaded()}) + * including the validator's errors */ public function clearErrors() { $this->errors = array(); + $this->validator->clearErrors(); } /** @@ -342,6 +344,13 @@ class Upload_Validator { return $this->errors; } + /** + * Clear out all errors + */ + public function clearErrors() { + $this->errors = array(); + } + /** * Set information about temporary file produced by PHP. * @param array $tmpFile diff --git a/forms/UploadField.php b/forms/UploadField.php index e5b161da4..b09a126af 100644 --- a/forms/UploadField.php +++ b/forms/UploadField.php @@ -1222,20 +1222,25 @@ class UploadField extends FileField { $name = $this->getName(); $postVars = $request->postVar($name); - // Save the temporary file into a File object + // Extract uploaded files from Form data $uploadedFiles = $this->extractUploadedFileData($postVars); - $firstFile = reset($uploadedFiles); - $file = $this->saveTemporaryFile($firstFile, $error); - if(empty($file)) { - $return = array('error' => $error); - } else { - $return = $this->encodeFileAttributes($file); + $return = array(); + + // Save the temporary files into a File objects + // and save data/error on a per file basis + foreach ($uploadedFiles as $tempFile) { + $file = $this->saveTemporaryFile($tempFile, $error); + if(empty($file)) { + array_push($return, array('error' => $error)); + } else { + array_push($return, $this->encodeFileAttributes($file)); + } + $this->upload->clearErrors(); } - + // Format response with json - $response = new SS_HTTPResponse(Convert::raw2json(array($return))); + $response = new SS_HTTPResponse(Convert::raw2json($return)); $response->addHeader('Content-Type', 'text/plain'); - if (!empty($return['error'])) $response->setStatusCode(403); return $response; } diff --git a/tests/forms/uploadfield/UploadFieldTest.php b/tests/forms/uploadfield/UploadFieldTest.php index 89dac5e0c..666c6bd76 100644 --- a/tests/forms/uploadfield/UploadFieldTest.php +++ b/tests/forms/uploadfield/UploadFieldTest.php @@ -167,8 +167,9 @@ class UploadFieldTest extends FunctionalTest { 'UploadFieldTest_Controller/Form/field/AllowedExtensionsField/upload', array('AllowedExtensionsField' => $this->getUploadFile($invalidFile)) ); - $this->assertTrue($response->isError()); - $this->assertContains('Extension is not allowed', $response->getBody()); + $response = json_decode($response->getBody(), true); + $this->assertTrue(array_key_exists('error', $response[0])); + $this->assertContains('Extension is not allowed', $response[0]['error']); $validFile = 'valid.txt'; $_FILES = array('AllowedExtensionsField' => $this->getUploadFile($validFile)); @@ -176,8 +177,8 @@ class UploadFieldTest extends FunctionalTest { 'UploadFieldTest_Controller/Form/field/AllowedExtensionsField/upload', array('AllowedExtensionsField' => $this->getUploadFile($validFile)) ); - $this->assertFalse($response->isError()); - $this->assertNotContains('Extension is not allowed', $response->getBody()); + $response = json_decode($response->getBody(), true); + $this->assertFalse(array_key_exists('error', $response[0])); } /**