#834018: Data serialized in a field's data column is lost after field_file_load if...
authorNathan Haug
Tue, 29 Jun 2010 19:14:17 +0000 (19:14 +0000)
committerNathan Haug
Tue, 29 Jun 2010 19:14:17 +0000 (19:14 +0000)
field_file.inc
filefield_field.inc
filefield_meta/filefield_meta.module
filefield_widget.inc
tests/filefield.test

index 0be3bca..1763b44 100644 (file)
@@ -38,7 +38,7 @@ function field_file_load($fid, $reset = NULL) {
     }
 
     if (!$file) {
-      $file = array('fid' => 0, 'filepath' => '', 'filename' => '', 'filemime' => '', 'filesize' => 0);
+      $file = (object) array('fid' => 0, 'filepath' => '', 'filename' => '', 'filemime' => '', 'filesize' => 0);
     }
 
     foreach (module_implements('file_load') as $module) {
index 1e8fdd2..eb20522 100644 (file)
@@ -272,25 +272,26 @@ function filefield_field_sanitize($node, $field, &$items, $teaser, $page) {
         continue;
       }
     }
-    // Load the complete file if a filepath is not available.
-    if (!empty($item['fid']) && empty($item['filepath'])) {
-      $items[$delta] = array_merge($item, field_file_load($item['fid']));
-    }
+
     // Add nid so formatters can create a link to the node.
     $items[$delta]['nid'] = $node->nid;
 
-    // TODO: This is only necessary for Views, which doesn't call the "load"
-    // $op. It might be preferable to move this to Views integration somehow.
-    if (!empty($items['data']) && is_string($items[$delta]['data'])) {
-      $item['data'] = unserialize($item['data']);
-    }
-    // Temporary fix to unserialize data serialized multiple times.
+    // Get the 'data' column stored by CCK into an array. This is necessary
+    // for Views, which doesn't call the "load" $op and to fix an issue with
+    // CCK double-serializing data.
     // See the FileField issue http://drupal.org/node/402860.
     // And the CCK issue http://drupal.org/node/407446.
     while (!empty($items[$delta]['data']) && is_string($items[$delta]['data'])) {
       $items[$delta]['data'] = unserialize($items[$delta]['data']);
     }
 
+    // Load the complete file if a filepath is not available.
+    if (!empty($item['fid']) && empty($item['filepath'])) {
+      $file = (array) field_file_load($item['fid']);
+      $items[$delta]['data'] = array_merge($item['data'], $file['data']);
+      $items[$delta] = array_merge($item, $file);
+    }
+
     // Verify the file exists on the server.
     if (!empty($item['filepath']) && !file_exists($item['filepath'])) {
       watchdog('filefield', 'FileField was trying to display the file %file, but it does not exist.', array('%file' => $item['filepath']), WATCHDOG_WARNING);
index 49c9ac9..eae0f96 100644 (file)
@@ -76,7 +76,7 @@ function filefield_meta_file_load(&$file) {
 function filefield_meta_file_insert(&$file) {
   if (!empty($file->fid)) {
     filefield_meta($file);
-    $record = array_merge(array('fid' => $file->fid), $file->data);
+    $record = array_merge($file->data, array('fid' => $file->fid));
     drupal_write_record('filefield_meta', $record);
   }
 }
index 1b3a1fa..4d3d85d 100644 (file)
@@ -204,7 +204,7 @@ function filefield_widget_value($element, $edit = FALSE) {
     $item = $element['#default_value'];
   }
   else {
-    $item = array_merge($element['#default_value'], $edit);
+    $item = $edit;
     $field = content_fields($element['#field_name'], $element['#type_name']);
 
     // Uploads take priority over value of fid text field.
@@ -236,6 +236,9 @@ function filefield_widget_value($element, $edit = FALSE) {
     }
   }
   // Merge file and item data so it is available to all widgets.
+  if (isset($item['data']) && isset($file['data'])) {
+    $file['data'] = array_merge($item['data'], $file['data']);
+  }
   $item = array_merge($item, $file);
 
   return $item;
index 0f33c1e..bd33b1d 100644 (file)
@@ -8,9 +8,9 @@ class FileFieldTestCase extends DrupalWebTestCase {
    * Implementation of setUp().
    */
   function setUp() {
-    // Views and ImageCache are included here just so that they don't whine
-    // when CCK tries to clear thier caches.
-    $modules = array_merge(func_get_args(), array('content', 'filefield', 'mimedetect', 'token', 'views'));
+    // Views is included here just so that it doesn't whine when CCK tries to
+    // clear the caches.
+    $modules = array_merge(func_get_args(), array('content', 'filefield', 'filefield_meta', 'getid3', 'mimedetect', 'token', 'views'));
     call_user_func_array(array($this, 'parent::setUp'), $modules);
 
     // Create and login user
@@ -88,7 +88,8 @@ class FileFieldTestCase extends DrupalWebTestCase {
   /**
    * Upload a file to a node.
    */
-  function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE) {
+  function uploadNodeFile($file, $field, $nid_or_type, $new_revision = TRUE) {
+    $field_name = $field['field_name'];
     $edit = array(
       'title' => $this->randomName(),
       'revision' => (string) (int) $new_revision,
@@ -101,14 +102,26 @@ class FileFieldTestCase extends DrupalWebTestCase {
       $this->drupalPost('node/' . $nid_or_type . '/edit', $edit, t('Save'));
     }
     else {
-      $edit['files[' . $field_name . '_0]'] = realpath($file->filepath);
+      $delta = '0';
+      $edit['files[' . $field_name . '_' . $delta . ']'] = realpath($file->filepath);
       $type = str_replace('_', '-', $nid_or_type);
       $this->drupalPost('node/add/' . $type, $edit, t('Save'));
     }
 
     $matches = array();
     preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
-    return isset($matches[1]) ? $matches[1] : FALSE;
+    $nid = isset($matches[1]) ? $matches[1] : FALSE;
+
+    // Edit the node and add a description if possible.
+    if ($nid && $field['description_field']) {
+      $edit = array(
+        'revision' => 0,
+        $field_name . '[' . $delta . '][data][description]' => $this->randomString(),
+      );
+      $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+    }
+
+    return $nid;
   }
 
   /**
@@ -200,12 +213,15 @@ class FileFieldRevisionTestCase extends FileFieldTestCase {
   function testRevisions() {
     $field_name = 'field_' . strtolower($this->randomName());
     $type = $this->drupalCreateContentType();
-    $field = $this->createFileField($field_name, $type->name);
+    $field_options = array(
+      'description_field' => '1',
+    );
+    $field = $this->createFileField($field_name, $type->name, $field_options);
 
     $test_file = $this->getTestFile('text');
 
     // Create a new node with the uploaded file.
-    $nid = $this->uploadNodeFile($test_file, $field_name, $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
 
     // Check that the file exists on disk and in the database.
     $node = node_load($nid, NULL, TRUE);
@@ -234,6 +250,12 @@ class FileFieldRevisionTestCase extends FileFieldTestCase {
     $node = node_load($nid, NULL, TRUE);
     $node_file_r3 = $node->{$field['field_name']}[0];
     $node_vid_r3 = $node->vid;
+
+    // FileField Meta's extensive meta data can be difficult to match up exactly
+    // (mostly differences between strings and integers). Just compare the
+    // descriptions.
+    $node_file_r2['data'] = array('description' => $node_file_r2['data']['description']);
+    $node_file_r3['data'] = array('description' => $node_file_r3['data']['description']);
     $this->assertEqual($node_file_r2, $node_file_r3, t('Previous revision file still in place after creating a new revision without a new file.'));
 
     // Revert to the first revision and check that the original file is active.
@@ -288,8 +310,8 @@ class FileFieldDisplayTestCase extends FileFieldTestCase {
     $test_file = $this->getTestFile('text');
 
     // Create a new node with the uploaded file.
-    $nid = $this->uploadNodeFile($test_file, $field_name, $type->name);
-    $this->drupalGet('node/' . $nid . '/edit');
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
+    $this->drupalGet('node/' . $nid);
 
     // Check that the default formatter is displaying with the file name.
     $node = node_load($nid, NULL, TRUE);
@@ -325,7 +347,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
    * Implementation of setUp().
    */
   function setUp() {
-    $modules = array_merge(func_get_args(), array('content', 'filefield', 'mimedetect', 'token', 'views'));
+    $modules = array_merge(func_get_args(), array('content', 'filefield', 'filefield_meta', 'getid3', 'mimedetect', 'token', 'views'));
     call_user_func_array(array($this, 'parent::setUp'), $modules);
 
     $this->node_type = $this->drupalCreateContentType();
@@ -353,7 +375,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->assertRaw(t('%title field is required.', array('%title' => $field['widget']['label'])), t('Node save failed when required file field was empty.'));
 
     // Create a new node with the uploaded file.
-    $nid = $this->uploadNodeFile($test_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading to the required field.'));
@@ -369,7 +391,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->assertRaw(t('%title field is required.', array('%title' => $field['widget']['label'])), t('Node save failed when required multiple value file field was empty.'));
 
     // Create a new node with the uploaded file into the multivalue field.
-    $nid = $this->uploadNodeFile($test_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading to the required multiple value field.'));
@@ -401,14 +423,14 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
       $this->updateFileField($field['field_name'], $type->name, array(), array('max_filesize_per_file' => $max_filesize_per_file));
 
       // Create a new node with the small file, which should pass.
-      $nid = $this->uploadNodeFile($small_file, $field['field_name'], $type->name);
+      $nid = $this->uploadNodeFile($small_file, $field, $type->name);
       $node = node_load($nid, NULL, TRUE);
       $node_file = $node->{$field['field_name']}[0];
       $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_filesize_per_file)));
       $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_filesize_per_file)));
 
       // Check that uploading the large file fails (1M limit).
-      $nid = $this->uploadNodeFile($large_file, $field['field_name'], $type->name);
+      $nid = $this->uploadNodeFile($large_file, $field, $type->name);
       $error_message = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($large_file->filesize), '%maxsize' => format_size($file_limit)));
       $this->assertRaw($error_message, t('Node save failed when file (%filesize) exceeded the max upload size (%maxsize).', array('%filesize' => format_size($large_file->filesize), '%maxsize' => $max_filesize_per_file)));
     }
@@ -417,7 +439,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->updateFileField($field['field_name'], $type->name, array(), array('max_filesize_per_file' => ''));
 
     // Upload the big file successfully.
-    $nid = $this->uploadNodeFile($large_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($large_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) with no max limit.', array('%filesize' => format_size($large_file->filesize))));
@@ -440,26 +462,26 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->updateFileField($field['field_name'], $type->name, array('multiple' => '1'), array('max_filesize_per_node' => $max_node_limit));
 
     // Create a new node with the small file, which should pass.
-    $nid = $this->uploadNodeFile($small_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($small_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
     $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
 
     // Add a second file to the same node which should pass.
-    $nid = $this->uploadNodeFile($small_file, $field['field_name'], $nid);
+    $nid = $this->uploadNodeFile($small_file, $field, $nid);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
     $this->assertFileEntryExists($node_file, t('File entry exists after uploading a file (%filesize) under the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
 
     // Add a third file to the same node which should fail.
-    $nid = $this->uploadNodeFile($small_file, $field['field_name'], $nid);
+    $nid = $this->uploadNodeFile($small_file, $field, $nid);
     $error_message = t('exceeds field settings of %msize.', array('%msize' => format_size($file_limit)));
     $this->assertRaw($error_message, t('File not uploaded as the file (%filesize) exceeds the max node limit (%maxsize).', array('%filesize' => format_size($small_file->filesize), '%maxsize' => $max_node_limit)));
 
     // Check that uploading the large file fails (1M limit).
-    $nid = $this->uploadNodeFile($large_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($large_file, $field, $type->name);
     $error_message = t('exceeds field settings of %msize.', array('%msize' => format_size($file_limit)));
     $this->assertRaw($error_message, t('File not uploaded as the file (%filesize) exceeds the max node limit (%maxsize).', array('%filesize' => format_size($large_file->filesize), '%maxsize' => $max_node_limit)));
 
@@ -487,7 +509,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->updateFileField($field['field_name'], $type->name, array(), array('file_extensions' => ''));
 
     // Check that the file can be uploaded with no extension checking.
-    $nid = $this->uploadNodeFile($test_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading a file with no extension checking.'));
@@ -497,7 +519,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
     $this->updateFileField($field['field_name'], $type->name, array(), array('file_extensions' => "txt png jpg $extention"));
 
     // Check that the file can be uploaded with extension checking.
-    $nid = $this->uploadNodeFile($test_file, $field['field_name'], $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
     $node = node_load($nid, NULL, TRUE);
     $node_file = $node->{$field['field_name']}[0];
     $this->assertFileExists($node_file, t('File exists after uploading a file with extension checking.'));
@@ -505,7 +527,7 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
 
     // Check that a mismatched extension cannot be uploaded.
     if (module_exists('mimedetect')) {
-      $this->uploadNodeFile($wrong_extension_file, $field['field_name'], $type->name);
+      $this->uploadNodeFile($wrong_extension_file, $field, $type->name);
       $error_pattern = "/The file contents \([a-z\-\/]+\) do not match its extension \([a-z]+\)\./";
       $this->assertPattern($error_pattern, t('File prevented from uploading because its extension does not match its content.'));
     }
@@ -540,7 +562,7 @@ class FileFieldPathTestCase extends FileFieldTestCase {
     $test_file = $this->getTestFile('text');
 
     // Create a new node.
-    $nid = $this->uploadNodeFile($test_file, $field_name, $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
 
     // Check that the file was uploaded to the file root.
     $node = node_load($nid, NULL, TRUE);
@@ -551,7 +573,7 @@ class FileFieldPathTestCase extends FileFieldTestCase {
     $field = $this->updateFileField($field['field_name'], $type->name, array(), array('file_path' => 'foo/bar/baz'));
 
     // Upload a new file into the subdirectories.
-    $nid = $this->uploadNodeFile($test_file, $field_name, $type->name);
+    $nid = $this->uploadNodeFile($test_file, $field, $type->name);
 
     // Check that the file was uploaded into the subdirectory.
     $node = node_load($nid, NULL, TRUE);
@@ -564,7 +586,7 @@ class FileFieldPathTestCase extends FileFieldTestCase {
       $field = $this->updateFileField($field['field_name'], $type->name, array(), array('file_path' => '[uid]/[user-raw]'));
 
       // Upload a new file into the token subdirectories.
-      $nid = $this->uploadNodeFile($test_file, $field_name, $type->name);
+      $nid = $this->uploadNodeFile($test_file, $field, $type->name);
 
       // Check that the file was uploaded into the subdirectory.
       $node = node_load($nid, NULL, TRUE);