Skip to content
This repository
Browse code

BUGFIX: make UploadField aware of relations to derived classes (os7140)

UploadField was relying entirely on the File::get_class_for_file_extension to
select a class, so it could only create File or Image objects. This
would break the relationships based on derived objects. Also make it
respect the FileField::relationAutoSetting.
  • Loading branch information...
commit a9e7de0cf4b5ac07fb40839cb77e2fb6ab483039 1 parent 47d7392
Mateusz U authored
36  forms/UploadField.php
@@ -432,6 +432,7 @@ public function upload(SS_HTTPRequest $request) {
432 432
 		$tmpfile = $request->postVar($name);
433 433
 		$record = $this->getRecord();
434 434
 		
  435
+		// Check if the file has been uploaded into the temporary storage.
435 436
 		if (!$tmpfile) {
436 437
 			$return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found'));
437 438
 		} else {
@@ -444,7 +445,7 @@ public function upload(SS_HTTPRequest $request) {
444 445
 		}
445 446
 
446 447
 		// Check for constraints on the record to which the file will be attached.
447  
-		if (!$return['error'] && $record && $record->exists()) {
  448
+		if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
448 449
 			$tooManyFiles = false;
449 450
 			// Some relationships allow many files to be attached.
450 451
 			if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) {
@@ -464,20 +465,47 @@ public function upload(SS_HTTPRequest $request) {
464 465
 				), $this->getConfig('allowedMaxFileNumber'));
465 466
 			}
466 467
 		}
  468
+
  469
+		// Process the uploaded file
467 470
 		if (!$return['error']) {
  471
+			$fileObject = null;
  472
+
  473
+			if ($this->relationAutoSetting) {
  474
+				// Search for classes that can hold the uploaded files by traversing the relationship.
  475
+				if ($record->hasMethod($name)) {
  476
+					$remote = $record->$name();
  477
+					if ($remote instanceof DataList) {
  478
+						// has_many or many_many
  479
+						$desiredClass = $remote->dataClass();
  480
+					}
  481
+					else if (is_object($remote)) {
  482
+						// has_one
  483
+						$desiredClass = $remote->ClassName;
  484
+					}
  485
+
  486
+					// If we have a specific class, create new object explicitly. Otherwise rely on Upload::load to choose the class.
  487
+					if (is_string($desiredClass)) $fileObject = Object::create($desiredClass);
  488
+				}
  489
+			}
  490
+
  491
+			// Get the uploaded file into a new file object.
468 492
 			try {
469  
-				$this->upload->loadIntoFile($tmpfile, null, $this->folderName);
  493
+				$this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
470 494
 			} catch (Exception $e) {
471 495
 				// we shouldn't get an error here, but just in case
472 496
 				$return['error'] = $e->getMessage();
473 497
 			}
  498
+
474 499
 			if (!$return['error']) {
475 500
 				if ($this->upload->isError()) {
476 501
 					$return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors());
477 502
 				} else {
478  
-					// The file has been uploaded successfully, attach it to the related record.
479 503
 					$file = $this->upload->getFile();
480  
-					$this->attachFile($file);
  504
+
  505
+					// Attach the file to the related record.
  506
+					if ($this->relationAutoSetting) {
  507
+						$this->attachFile($file);
  508
+					}
481 509
 
482 510
 					// Collect all output data.
483 511
 					$file =  $this->customiseFile($file);
39  tests/forms/uploadfield/UploadFieldTest.php
@@ -55,6 +55,31 @@ function testUploadHasOneRelation() {
55 55
 		$this->assertEquals($record->HasOneFile()->Name, $tmpFileName);
56 56
 	}
57 57
 
  58
+	function testUploadHasOneRelationWithExtendedFile() {
  59
+		$this->loginWithPermission('ADMIN');
  60
+
  61
+		// Unset existing has_one relation before re-uploading
  62
+		$record = $this->objFromFixture('UploadFieldTest_Record', 'record1');
  63
+		$record->HasOneExtendedFileID = null;
  64
+		$record->write();
  65
+
  66
+		$tmpFileName = 'testUploadHasOneRelationWithExtendedFile.txt';
  67
+		$_FILES = array('HasOneExtendedFile' => $this->getUploadFile($tmpFileName));
  68
+		$response = $this->post(
  69
+			'UploadFieldTest_Controller/Form/field/HasOneExtendedFile/upload',
  70
+			array('HasOneExtendedFile' => $this->getUploadFile($tmpFileName))
  71
+		);
  72
+		$this->assertFalse($response->isError());
  73
+
  74
+		$this->assertFileExists(ASSETS_PATH . "/UploadFieldTest/$tmpFileName");
  75
+		$uploadedFile = DataObject::get_one('UploadFieldTest_ExtendedFile', sprintf('"Name" = \'%s\'', $tmpFileName));
  76
+		$this->assertTrue(is_object($uploadedFile), 'The file object is created');
  77
+
  78
+		$record = DataObject::get_by_id($record->class, $record->ID, false);
  79
+		$this->assertTrue($record->HasOneExtendedFile()->exists(), 'The extended file is attached to the class');
  80
+		$this->assertEquals($record->HasOneExtendedFile()->Name, $tmpFileName, 'Proper file has been attached');
  81
+	}
  82
+
58 83
 	function testUploadHasManyRelation() {
59 84
 		$this->loginWithPermission('ADMIN');
60 85
 
@@ -620,6 +645,7 @@ class UploadFieldTest_Record extends DataObject implements TestOnly {
620 645
 		'HasOneFile' => 'File',
621 646
 		'HasOneFileMaxOne' => 'File',
622 647
 		'HasOneFileMaxTwo' => 'File',
  648
+		'HasOneExtendedFile' => 'UploadFieldTest_ExtendedFile'
623 649
 	);
624 650
 
625 651
 	static $has_many = array(
@@ -666,6 +692,10 @@ function Form() {
666 692
 		$fieldHasOne = new UploadField('HasOneFile');
667 693
 		$fieldHasOne->setFolderName('UploadFieldTest');
668 694
 		$fieldHasOne->setRecord($record);
  695
+
  696
+		$fieldHasOneExtendedFile = new UploadField('HasOneExtendedFile');
  697
+		$fieldHasOneExtendedFile->setFolderName('UploadFieldTest');
  698
+		$fieldHasOneExtendedFile->setRecord($record);
669 699
 		
670 700
 		$fieldHasOneMaxOne = new UploadField('HasOneFileMaxOne');
671 701
 		$fieldHasOneMaxOne->setFolderName('UploadFieldTest');
@@ -712,6 +742,7 @@ function Form() {
712 742
 				$fieldHasOne,
713 743
 				$fieldHasOneMaxOne,
714 744
 				$fieldHasOneMaxTwo,
  745
+				$fieldHasOneExtendedFile,
715 746
 				$fieldHasMany,
716 747
 				$fieldHasManyMaxTwo,
717 748
 				$fieldManyMany,
@@ -727,6 +758,7 @@ function Form() {
727 758
 				'HasOneFile',
728 759
 				'HasOneFileMaxOne',
729 760
 				'HasOneFileMaxTwo',
  761
+				'HasOneExtendedFile',
730 762
 				'HasManyFiles',
731 763
 				'HasManyFilesMaxTwo',
732 764
 				'ManyManyFiles',
@@ -743,3 +775,10 @@ function submit($data, $form) {
743 775
 	}
744 776
 
745 777
 }
  778
+
  779
+/**
  780
+ * Used for testing the create-on-upload
  781
+ */
  782
+class UploadFieldTest_ExtendedFile extends File implements TestOnly {
  783
+
  784
+}

0 notes on commit a9e7de0

Please sign in to comment.
Something went wrong with that request. Please try again.