? ico/doc.png
? ico/gif.png
? ico/jpeg.png
? ico/jpg.png
? ico/pdf.png
? ico/png.png
? ico/txt.png
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	22 May 2007 17:25:19 -0000
@@ -76,8 +76,6 @@
     case 'database columns':
       $columns = array(
         'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
-        'description' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
-        'list' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
       );
       return $columns;
   }
@@ -108,15 +106,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['description'], $file['list']);
     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 +133,36 @@
 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['description'], $file['list']);
+    }
+    else {
+      db_query('UPDATE {file_revisions} SET description = "%s", list = %d
+                WHERE fid = %d AND vid = %d',
+               $file['description'], $file['list'], $file['fid'], $node->vid);
+    }
   }
   return $file;
 }
@@ -154,18 +173,31 @@
 function filefield_field($op, $node, $field, &$node_field, $teaser, $page) {
   $fieldname = $field['field_name'];
   switch ($op) {
+    // called after content.module loads default data.
     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']);
+            $file = filefield_file_load($file['fid'], $node->vid);
+
+            // In certain cases, content.module calls this function with
+            // $node_field[$delta] set, even if the field has not yet been
+            // stored at all or has already been deleted. In that case,
+            // $file['fid'] == 0 and file_load() returns an empty array.
+            // When that happens, unset() the delta so that subsequent hooks
+            // are not bothered.
+            if (empty($file)) {
+              unset($node_field[$delta]);
+            }
+            else { // otherwise, merge our info with CCK's, and all is fine.
+              $node_field[$delta] = array_merge((array)$node_field[$delta], $file);
+            }
           }
-          $output = array($fieldname => $node_field);
         }
+        $node_field = array_values($node_field); // compact deltas
+        return array($fieldname => $node_field);
       }
-      break; 
+      return array();
 
     // called before content.module defaults.
     case 'insert':
@@ -183,7 +215,7 @@
 
     case 'delete':
       foreach ($node_field as $delta => $item) {
-        _filefield_file_delete($node, $field, $item); 
+        filefield_file_delete($node, $field, $item); 
       }
       break;
   }
@@ -258,12 +290,13 @@
   }
 }
 
-function _filefield_file_delete($node, $field, $file) {
+function filefield_file_delete($node, $field, $file, $session_name = 'filefield') {
   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']]);
+    unset($_SESSION[$session_name][$field['field_name']][$file['sessionid']]);
   }
   module_invoke_all('filefield', 'delete', $node, $field, $file);
   return file_delete($file['filepath']);
@@ -443,7 +476,7 @@
   );
   $form['list'] = array(
     '#type' => 'checkbox', 
-    '#default_value' => $file['list'],
+    '#default_value' => isset($file['list']) ? $file['list'] : 1,
     '#title' => t('List'),
   );
 
@@ -477,6 +510,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,20 +584,48 @@
   if(!isset($item['fid'])) {
     return '';
   }
-  $file = _filefield_file_load($item['fid']);
-  return theme('filefield', $file, $item);
+  return theme('filefield', $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)) {
+    $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
+    $file = db_fetch_array($result);
+    if ($file) {
+      // load revision info, or use default values if no revision is given
+      $revision_info = array('list' => 1, 'description' => $file['filename']);
+      if (!empty($vid) && is_numeric($vid)) {
+        $exists = FALSE;
+        $result = db_query('SELECT * FROM {file_revisions}
+                            WHERE fid = %d AND vid = %d', $fid, $vid);
+        while ($rev = db_fetch_object($result)) {
+          $exists = TRUE;
+          $revision_info = array(
+            'list' => $rev->list,
+            'description' => $rev->description
+          );
+        }
+        if (!$exists) {
+          return array();
+        }
       }
+      // $file is the combination of the data in {files} and {file_revisions}
+      $file = array_merge($file, $revision_info);
+      // 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.
@@ -551,7 +667,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);
