Index: filefield.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.module,v
retrieving revision 1.23
diff -u -r1.23 filefield.module
--- filefield.module	30 Mar 2007 03:20:24 -0000	1.23
+++ filefield.module	24 Apr 2007 08:33:26 -0000
@@ -108,15 +108,19 @@
   if (filefield_check_directory($widget_file_path) && $file = file_save_upload((object)$file, $filepath)) {
     $file = (array)$file;
     $file['fid'] = db_next_id('{files}_fid');
-    db_query('INSERT into {files} (fid, nid, filename, filepath, filemime, filesize)  
-             VALUES (%d, %d, "%s","%s","%s",%d)',
-            $file['fid'], $node->nid, $file['filename'], $file['filepath'], $file['filemime'], $file['filesize']);
+    db_query('INSERT into {files} (fid, nid, filename, filepath, filemime, filesize)
+              VALUES (%d, %d, "%s","%s","%s",%d)',
+             $file['fid'], $node->nid, $file['filename'], $file['filepath'],
+             $file['filemime'], $file['filesize']);
+    db_query('INSERT into {file_revisions} (fid, vid, description, list)
+              VALUES (%d, %d, "%s", %d)',
+             $file['fid'], $node->vid, $file['filename'], 0);
     module_invoke_all('filefield', 'file_save', $node, $field, $file);
     return (array)$file;
   }
   else {
     // Include file name in upload error.
-    form_set_error(NULL, t('file upload was unsuccessful.'));
+    form_set_error(NULL, t('File upload was unsuccessful.'));
     return FALSE;
   }
 }
@@ -131,19 +135,31 @@
 function filefield_file_update($node, $field, &$file) {
   $file = (array)$file; 
   if ($file['remove'] == TRUE) {
-     module_invoke_all('filefield', 'file_delete', $node, $field, $file);
-     _filefield_file_delete($node, $field, $file);
-     // should I return an array here instead as imagefield does, or is that a bug in 
-     // in imagefield. I remember I was working on a content.module patch that would
-     // delete multivalue fields whose value was NULL. Maybe a leftover.
-     return NULL;
+    db_query('DELETE FROM {file_revisions} WHERE fid = %d AND vid = %d',
+             $file['fid'], $node->vid);
+
+    // delete the file if it's not used by at least one revision
+    $filecount = db_result(db_query('SELECT COUNT(*) FROM {file_revisions}
+                                     WHERE fid = %d', $file['fid']));
+    if ($filecount == 0) {
+      module_invoke_all('filefield', 'file_delete', $node, $field, $file);
+      filefield_file_delete($node, $field, $file);
+      return array();
+    }
   }
   if ($file['fid'] == 'upload') {  
     return filefield_file_insert($node, $field, $file);
   }
   else {
     // if fid is not numeric here we should complain.
-    // else we update the file table.  
+    // else we update the file table.
+
+    // If the file is taken to a new revision unmodified, copy the db entry.
+    if (isset($file['old_vid'])) {
+      db_query('INSERT into {file_revisions} (fid, vid, description, list)
+                VALUES (%d, %d, "%s", %d)',
+               $file['fid'], $node->vid, $file['filename'], 0);
+    }
   }
   return $file;
 }
@@ -157,15 +173,22 @@
     case 'load':
       $output = array();
       if (count($node_field)) {
-        $values = array();
         foreach ($node_field as $delta => $file) {
           if (!empty($file)) {
-            $node_field[$delta] += _filefield_file_load($file['fid']);
+            // only load the file if it has got a valid database entry
+            $file = filefield_file_load($file['fid'], $node->vid);
+            if (empty($file)) {
+              unset($node_field[$delta]);
+            }
+            else {
+              $node_field[$delta] += $file;
+            }
           }
-          $output = array($fieldname => $node_field);
         }
+        $node_field = array_values($node_field); // compact deltas
       }
-      break; 
+      $output = array($fieldname => $node_field);
+      break;
 
     // called before content.module defaults.
     case 'insert':
@@ -183,7 +206,7 @@
 
     case 'delete':
       foreach ($node_field as $delta => $item) {
-        _filefield_file_delete($node, $field, $item); 
+        filefield_file_delete($node, $field, $item); 
       }
       break;
   }
@@ -258,9 +281,10 @@
   }
 }
 
-function _filefield_file_delete($node, $field, $file) {
+function filefield_file_delete($node, $field, $file) {
   if (is_numeric($file['fid'])) {
     db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']);
+    db_query('DELETE FROM {file_revisions} WHERE fid = %d', $file['fid']);
   }
   else {
     unset($_SESSION['filefield'][$field['field_name']][$file['sessionid']]);
@@ -477,6 +501,61 @@
   }
 }
 
+/**
+ * Implementation of hook_form_alter():
+ * Remove the file entries from the upload module's "Uploaded files" fieldset.
+ */
+function filefield_form_alter($form_id, &$form) {
+  filefield_hide_upload_files($form_id, $form, 'file');
+}
+
+/**
+ * Call this function from hook_form_alter() in order to keep the upload module
+ * from showing uploaded files in its own "Uploaded files" fieldset.
+ *
+ * @param $form_id  The form id, as passed to hook_form_alter().
+ * @param $form     The form array, as passed to hook_form_alter().
+ * @param $field_type
+ *   The type of the CCK field, as specified in hook_field_info()
+ *   (e.g. 'file', 'image', 'audio' or 'video').
+ */
+function filefield_hide_upload_files($form_id, &$form, $field_type) {
+  if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
+    $node = $form['#node'];
+
+    if (!empty($node->files)) {
+      $types = content_types($node->type);
+      if (!empty($types['fields'])) {
+        foreach ($types['fields'] as $field_info) {
+          if ($field_info['type'] !== $field_type) {
+            continue;
+          }
+          if (!empty($node->$field_info['field_name'])) {
+            foreach ($node->$field_info['field_name'] as $field) {
+              unset($form['attachments']['wrapper']['files'][$field['fid']]);
+            }
+          }
+        }
+
+        $files_left = FALSE;
+        if (!empty($form['attachments']['wrapper']['files'])) {
+          foreach ($form['attachments']['wrapper']['files'] as $key => $value) {
+            if (is_string($key) && $key[0] == '#') {
+              continue;
+            }
+            $files_left = TRUE;
+            break;
+          }
+        }
+        if (!$files_left) {
+          unset($form['attachments']['wrapper']['files']);
+          $form['attachments']['#collapsed'] = TRUE;
+        }
+      }
+    }
+  }
+}
+
 
 /**
  * Implementation of hook_field formatter.
@@ -496,21 +575,38 @@
   if(!isset($item['fid'])) {
     return '';
   }
-  $file = _filefield_file_load($item['fid']);
+  $file = filefield_file_load($item['fid']);
   return theme('filefield', $file, $item);
 }
 
-function _filefield_file_load($fid = NULL) {
-  if (isset($fid)) { 
-    if (is_numeric($fid)) {
-      $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
-      $file = db_fetch_array($result);
-      if ($file) {
-        // let modules load extended attributes.
-        $file += module_invoke_all('filefield', 'file_load', $node, $field, $file);
-        return $file;
+/**
+ * Load a file object from the database.
+ *
+ * @param $fid
+ *   The file id of the file that shall be loaded.
+ * @param $vid
+ *   If NULL, the file will be loaded no matter which revision it belongs to.
+ *   Otherwise, the file will only be loaded if it matches this revision id.
+ *
+ * @return  The file object if the given file exists in the database,
+ *          or an empty array if it doesn't.
+ */
+function filefield_file_load($fid = NULL, $vid = NULL) {
+  if (!empty($fid) && is_numeric($fid)) {
+    if (!empty($vid) && is_numeric($vid)) {
+      $filecount = db_result(db_query('SELECT COUNT(*) FROM {file_revisions}
+                                       WHERE fid = %d AND vid = %d', $fid, $vid));
+      if ($filecount == 0) {
+        return array();
       }
     }
+    $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
+    $file = db_fetch_array($result);
+    if ($file) {
+      // let modules load extended attributes.
+      $file += module_invoke_all('filefield', 'file_load', $node, $field, $file);
+      return $file;
+    }
   }
   // return an empty array if nothing was found.
   return array();
@@ -551,7 +647,7 @@
 if (!function_exists('upload_file_download')) {
   function filefield_file_download($file) {
     $file = file_create_path($file);
-    $result = db_query("SELECT f.* FROM {files} f WHERE filepath = '%s'", $file);
+    $result = db_query("SELECT * FROM {files} WHERE filepath = '%s'", $file);
     if ($file = db_fetch_object($result)) {
       if (user_access('view uploaded files')) {
         $node = node_load($file->nid);
