? private_upload-948630.patch
Index: private_upload.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/private_upload/private_upload.module,v
retrieving revision 1.13.2.11
diff -u -p -r1.13.2.11 private_upload.module
--- private_upload.module	29 Nov 2009 18:42:14 -0000	1.13.2.11
+++ private_upload.module	5 Nov 2010 16:55:16 -0000
@@ -252,7 +252,20 @@ function private_upload_file_download($f
  * Implementation of hook_nodeapi().
  */
 function private_upload_nodeapi(&$node, $op, $teaser) {
+  static $files_processed;
   switch ($op) {   
+    case 'load':
+      // add a private property into the file objects of the node, be sure to
+      // do it once
+      if (variable_get("upload_$node->type", 1) == 1 && $files_processed === NULL) {
+        $output['files'] = upload_load($node);
+        foreach ($output['files'] as $fid => $file) {
+          $output['files'][$fid]->private = _private_upload_is_file_private($file->filepath);
+        }
+        $files_processed = TRUE;
+        return $output;
+      }
+      break;
     case 'insert':
     case 'update':
       // ******************************************************
@@ -333,131 +346,96 @@ function private_upload_nodeapi(&$node, 
 }
 
 /**
- * hook_form_alter().
+ * Implementation of hook_form_alter().
  * 
  * Inject the 'private' checkboxes into the upload form.
  * Also change the #theme to something that will show the checkboxes
  *   and overwrite the href in the description.
  * Two paths - one for normal submit, one for javascript.
  */
-function private_upload_form_alter(&$form, $from_state, $form_id) {
-  if (isset($form['type'])) {
+function private_upload_form_alter(&$form, $form_state, $form_id) {
+  
+  if (strpos($form_id, '_node_form')) {
     $node = $form['#node'];
-    if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) {
-      $form['#submit'][] = 'private_upload_form_submit';
-      if (is_array($node->files) && count($node->files)) { // hijack theme function
-        $form['attachments']['wrapper']['files']['#theme'] = 'private_upload_form';
-        $form['#validate']['private_upload_form_validate'] = array();
-//        $form['#submit'] = array('private_upload_form_submit');
-        foreach ($node->files as $fid => $file) {
-          // Add private checkbox.
-
-          if (is_array($file) && isset($file['private'])) {
-            $default_value = $file['private']; // Preview
-          }
-          else { // node load
-            $default_value = _private_upload_is_file_private($file->filepath);
-          }
-          
-          $form['attachments']['wrapper']['files'][$fid]['private'] = array(
-            '#type' => 'checkbox', 
-            '#default_value' => $default_value,
-          );
-          if (!realpath($file->filepath)) {
-            $form['attachments']['wrapper']['files'][$fid]['msg'] = array(
-              '#value' => ' <span style="color:red">*Missing*</span>',
-            );
-            drupal_set_message("File is not where it should be: $file->filepath", 'warning');
-          }
-         
-          // Overwrite URL in description with special URL if file is private.
-          $href = _private_upload_create_url($file);
-          $description = "<small>". check_plain($href) ."</small>";
-          $form['attachments']['wrapper']['files'][$fid]['description'] = array(
-            '#type' => 'textfield', 
-            '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, 
-            '#maxlength' => 256, 
-            '#description' => $description, 
-          );
-         }
-      }     
+    if ($node && variable_get('upload_' . $node->type, TRUE)) {
+      // update the form with our stuff
+      private_upload_update_attachements_form($form['attachments']['wrapper'], $node);
     }
   }  
-  elseif ($form_id == 'upload_js') {
-    $form['files']['#theme'] = 'private_upload_form';
-//    $form['#submit'][] = 'private_upload_form_submit'; // ???
-    
-    foreach ($form['files'] as $fid => $file) {
-      if (!_private_upload_starts_with($fid, '#')) { // Ignore the properties.
-        if ($_POST['files'][$fid]) { 
-          $private = $_POST['files'][$fid]['private'];
-          // While I am here lets fix the problem with delete and list as well.
-          // Q: Do I still need this fix in D6?
-          $form['files'][$fid]['list']['#default_value'] = $_POST['files'][$fid]['list'];
-          $form['files'][$fid]['remove']['#default_value'] = $_POST['files'][$fid]['remove'];
-        }
-        else { // File is newly uploaded so set private to default.
-          $private = (variable_get('private_upload_default', 'private') == 'private');
-        }
-        
-        $form['files'][$fid]['private'] = array(
-            '#type' => 'checkbox', 
-            '#default_value' => $private,
-        );
-      }
+  
+  if ($form_id == 'upload_js') {
+    
+    // Load the form from the Form API cache and merge our changes in. This is
+    // import because upload_js() alters the forms cached version and thus
+    // removes our checkboxes, causing a lot of trouble
+    
+    $cached_form_state = array();
+    
+    if (!($cached_form = form_get_cache($_POST['form_build_id'], $cached_form_state)) || !isset($cached_form['#node']) || !isset($cached_form['attachments'])) {
+      
+      // this check is alread performed by upload_js().
+      form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
+      $output = theme('status_messages');
+      print drupal_to_js(array('status' => TRUE, 'data' => $output));
+      exit();
     }
+    
+    // update the form with our stuff
+    private_upload_update_attachements_form($form);
+    
+    // rebuild the form cache
+    $cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form);
+    form_set_cache($_POST['form_build_id'], $cached_form, $form_state);
+    
   }
 }
 
 /**
- * Called to validate the upload form.
+ * Helper function to apply changes to the upload form
+ *
+ * @param array $form 
+ * @param object $node 
+ * @return void
  */
-function private_upload_form_validate($form_id, $form_values) {
-  if (is_array($form_values['files']) && count($form_values['files'])) {
-    $file = array_shift($form_values['files']);
-    if (!isset($file['private'])) {
-      drupal_set_message( t("Private Upload cannot find privacy settings."), 'error' );
-      // Be sure we are going after core upload.module.
-      $upload_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'upload'"));
-      $private_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'private_upload'"));
-      if ($private_weight <= $upload_weight) {
-        $new_weight = $upload_weight + 1;
-        drupal_set_message(t("Adjusting private_upload's weight to !new_weight", array('!new_weight' => $new_weight)), 'warning');
-        db_query("UPDATE {system} SET weight = '%d' WHERE name = 'private_upload'", $new_weight);
+
+function private_upload_update_attachements_form(&$form, $node = NULL) {
+  
+  if (!isset($form['files'])) {
+    return;
+  }
+  
+  // add in our theme function
+  $form['files']['#theme'] = 'private_upload_form';
+  
+  foreach ($form['files'] as $fid => $file) {
+    
+    // iterate over all files, ignoring the properties (starting with #)
+    if (is_numeric($fid)) {
+      
+      if ($node !== NULL && isset($node->files[$fid])) {
+        // initial form creation, all info comes from the node itself
+        $private = $node->files[$fid]->private;
+      }
+      elseif (isset($form['#post']['files'][$fid])) {
+        // form submit, maybe upload_js()
+        $private = $form['#post']['files'][$fid]['private'];
       }
       else {
-        drupal_set_message(t("Please check for modules that conflicts with Private Upload."), error);
+        // file is new from upload_js
+        $private = variable_get('private_upload_default', 'private') == 'private';
       }
+      
+      $form['files'][$fid]['private'] = array(
+        '#type' => 'checkbox',
+        '#title' => NULL,
+        '#default_value' => $private,
+      );
+      
     }
   }
+  
 }
 
-/**
- * Fixes edge case: When the node is first being created, the file->private info does not
- *  get moved automatically into the node. So we need to copy it by hand.
- * This seems like a bug in Drupal 6, but might just represent my limited understanding of
- *  the FormAPI changes.
- *
- * @param $form
- * @param $form_state
- */
-function private_upload_form_submit($form, &$form_state) {
-  if ($form_state['values'] && $form_state['values']['files']) {
-    foreach ($form_state['values']['files'] as $fid => $file) {
-      if (!isset($file->private)) { // Newly inserted file.
-        if (isset($form['attachments']['wrapper']['files'])) {
-          // I know it is naughty to look at the $_POST, but I can't find this value anywhere else.
-          // Seems like it should be in $form_state somewhere.
-          $private = $_POST['files'][$fid]['private']; 
-        }
-        else {
-          $private = (variable_get('private_upload_default', 'private') == 'private'); // Sumbit before Attach
-        }
-        $form_state['values']['files'][$fid]['private'] = $private;
-      }
-    }
-  }
-}
 // *****************************************************************************
 // Settings Functions **********************************************************
 // *****************************************************************************
@@ -648,6 +626,7 @@ function private_upload_theme() {
  *  Adding the Private checkbox.
  */
 function theme_private_upload_form(&$form) {
+  
   $header = array(t('Delete'), t('List'), t('Private'), t('Description'), t('Weight'), t('Size'), '');
   drupal_add_tabledrag('upload-attachments', 'order', 'sibling', 'upload-weight');
   
