? .git
Index: filefield.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.module,v
retrieving revision 1.110
diff -u -p -r1.110 filefield.module
--- filefield.module	11 Jul 2008 11:55:18 -0000	1.110
+++ filefield.module	11 Jul 2008 19:04:06 -0000
@@ -24,16 +24,16 @@ function filefield_menu() {
   $items = array();
 
   $items['filefield/js/upload/%/%/%'] = array(
-    'page callback' => 'filefield_js',
-    'page arguments' => array(3, 4, 5, 'filefield_file_upload_js'),
+    'page callback' => 'filefield_file_upload_js',
+    'page arguments' => array(3, 4, 5),
     'access callback' => 'filefield_edit_access',
     'access arguments' => array(3),
     'type' => MENU_CALLBACK,
     'file' => 'filefield.widget.inc',
   );
   $items['filefield/js/delete/%/%/%'] = array(
-    'page callback' => 'filefield_js',
-    'page arguments' => array(3, 4, 5, 'filefield_file_edit_delete_js'),
+    'page callback' => 'filefield_file_edit_delete_js',
+    'page arguments' => array(3, 4, 5),
     'access callback' => 'filefield_edit_access',
     'access arguments' => array(3),
     'type' => MENU_CALLBACK,
@@ -80,7 +80,6 @@ function filefield_elements() {
   );
   $elements['filefield_file_edit'] = array(
     '#input' => TRUE,
-    '#process' => array('filefield_file_edit_process'),
     '#value_callback' => 'filefield_file_edit_value',
   );
   $elements['filefield_generic_edit'] = array(
Index: filefield.widget.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.widget.inc,v
retrieving revision 1.7
diff -u -p -r1.7 filefield.widget.inc
--- filefield.widget.inc	11 Jul 2008 12:23:53 -0000	1.7
+++ filefield.widget.inc	11 Jul 2008 19:04:06 -0000
@@ -41,7 +41,11 @@ function filefield_file_upload_form(&$fo
   $field_name_css = str_replace('_', '-', $field['field_name']);
   $id = 'filefield-'. $field_name_css .'-'. $delta .'-form';
 
-  $replaced_file = (isset($items[$delta]) && isset($items[$delta]['replaced_file']))
+  if (isset($items[$delta]['ahah_replaced'])) {
+    $ahah_replaced = TRUE;
+    unset($items[$delta]['ahah_replaced']);
+  }
+  $replaced_file = isset($items[$delta]['replaced_file'])
                     ? $items[$delta]['replaced_file'] : NULL;
 
   $requirements = _filefield_upload_requirements($field, $field['widget'], $items);
@@ -55,6 +59,10 @@ function filefield_file_upload_form(&$fo
     '#suffix' => '</div></div>',
     '#upload_requirements' => $requirements,
   );
+  if (!empty($ahah_replaced)) {
+    $widget['#prefix'] = '<div class="ahah-new-content">'. $widget['#prefix'];
+    $widget['#suffix'] = $widget['#suffix'] .'</div>';
+  }
 
   if ($requirements['upload possible']) {
     // Buttons inside custom form elements are not registered by the Forms API,
@@ -67,7 +75,7 @@ function filefield_file_upload_form(&$fo
       '#submit' => array('filefield_file_upload_submit'), // without JavaScript
       '#ahah' => array( // with JavaScript
         'path' => 'filefield/js/upload/'. $field['field_name'] .'/'. $field['type_name'] .'/'. $delta,
-        'wrapper' => $id,
+        'wrapper' => $field_name_css .'-items', // CCK's field form
         'method' => 'replace',
         'effect' => 'fade',
       ),
@@ -177,11 +185,36 @@ function filefield_file_upload_submit($f
 }
 
 /**
- * Form callback for the "Upload" button with JavaScript enabled,
- * invoked by filefield_js(). Uploads a file to the given field and delta.
+ * AHAH callback for the "Upload" button with JavaScript enabled.
+ */
+function filefield_file_upload_js($field_name, $type_name, $delta) {
+  module_load_include('inc', 'content', 'includes/content.node_form');
+  content_field_form_js($type_name, $field_name, 'filefield_file_upload', array(
+    'delta' => $delta,
+    'js output callback' => 'filefield_upload_print_js',
+  ));
+}
+
+/**
+ * This is drupal_json(), only without setting the text/javascript Content Type
+ * header. This is unfortunate (and the reason why Devel likes to append its
+ * own JavaScript to the page, breaking uploads), but setting the header
+ * breaks browsers instantly, which is clearly the worse of both evils.
  */
-function filefield_file_upload_js(&$form, &$form_state, $field, $delta) {
+function filefield_upload_print_js($var = NULL) {
+  if (isset($var)) {
+    echo drupal_to_js($var);
+  }
+}
+
+/**
+ * State alter callback for content_field_form_js():
+ * Upload a file to the given field and delta.
+ */
+function filefield_file_upload_js_state_alter($form, &$form_state, $field, $callback_options) {
+  $delta = $callback_options['delta'];
   _filefield_file_upload($form_state, $field, $delta);
+  $form_state['values'][$field['field_name']][$delta]['ahah_replaced'] = TRUE;
 }
 
 /**
@@ -470,6 +503,11 @@ function filefield_file_edit_form(&$form
   $field_name_css = str_replace('_', '-', $field['field_name']);
   $id = 'filefield-'. $field_name_css .'-'. $delta .'-form';
 
+  $ahah_replaced = !empty($file['ahah_replaced']);
+  if ($ahah_replaced) {
+    unset($file['ahah_replaced']);
+  }
+
   $classes = array(
     'filefield-'. $field_name_css .'-form',
     'filefield-file-form',
@@ -480,7 +518,12 @@ function filefield_file_edit_form(&$form
     '#field' => $field,
     '#prefix' => '<div id="'. $id .'" class="'. implode(' ', $classes) .'"><div class="filefield-file-edit">',
     '#suffix' => '</div></div>',
+    '#is_new_file' => $ahah_replaced, // required info for the value callback
   );
+  if (!empty($ahah_replaced)) {
+    $widget['#prefix'] = '<div class="ahah-new-content">'. $widget['#prefix'];
+    $widget['#suffix'] = $widget['#suffix'] .'</div>';
+  }
 
   // Buttons inside custom form elements are not registered by the Forms API,
   // so we make the "Delete" button a regular child element and not a part
@@ -498,7 +541,7 @@ function filefield_file_edit_form(&$form
     '#submit' => array('filefield_file_edit_delete_submit'), // without JavaScript
     '#ahah' => array( // with JavaScript
       'path' => 'filefield/js/delete/'. $field['field_name'] .'/'. $field['type_name'] .'/'. $delta,
-      'wrapper' => $id,
+      'wrapper' => $field_name_css .'-items', // CCK's field form
       'method' => 'replace',
       'effect' => 'fade',
     ),
@@ -549,9 +592,8 @@ function filefield_file_edit_value($elem
     return $file;
   }
 
-  // Form API is being mean to us and doesn't include the 'list' value
-  // for checkboxes if the checkbox is disabled (0), only if it's enabled (1).
-  // That means we need to go the extra mile.
+  // $_POST is being mean to us and doesn't provide any value for the checkbox
+  // being disabled, only when it's enabled. So we can't rely on $edit alone.
   $list = isset($element['flags']['list'])
           ? !empty($edit['flags']['list'])
           : $file['list'];
@@ -589,26 +631,37 @@ function filefield_file_edit_value($elem
 function filefield_file_edit_delete_submit($form, &$form_state) {
   $field = $form_state['clicked_button']['#field'];
   $delta = $form_state['clicked_button']['#delta'];
-  filefield_file_edit_delete($form_state, $field, $delta);
+  _filefield_file_edit_delete($form_state, $field, $delta);
 
   // Rebuild the form with the new deleted-file state.
   node_form_submit_build_node($form, $form_state);
 }
 
 /**
- * Form callback for the "Delete" button with JavaScript enabled,
- * invoked by filefield_js(). Marks the file in the given field and delta
- * as deleted, or deletes it right away (depending on the context).
+ * AHAH callback for the "Delete" button with JavaScript enabled.
+ */
+function filefield_file_edit_delete_js($field_name, $type_name, $delta) {
+  module_load_include('inc', 'content', 'includes/content.node_form');
+  content_field_form_js($type_name, $field_name, 'filefield_file_edit_delete',
+                        array('delta' => $delta));
+}
+
+/**
+ * State alter callback for content_field_form_js():
+ * Depending on the context, either mark the file in the given field and delta
+ * as deleted or delete it right away.
  */
-function filefield_file_edit_delete_js(&$form, &$form_state, $field, $delta) {
-  filefield_file_edit_delete($form_state, $field, $delta);
+function filefield_file_edit_delete_js_state_alter($form, &$form_state, $field, $callback_options) {
+  $delta = $callback_options['delta'];
+  _filefield_file_edit_delete($form_state, $field, $delta);
+  $form_state['values'][$field['field_name']][$delta]['ahah_replaced'] = TRUE;
 }
 
 /**
  * Update the form state so that the file for the given field and delta
  * is marked as deleted.
  */
-function filefield_file_edit_delete(&$form_state, $field, $delta) {
+function _filefield_file_edit_delete(&$form_state, $field, $delta) {
   $field_name = $field['field_name'];
   $file = &$form_state['values'][$field_name][$delta];
 
@@ -629,88 +682,3 @@ function filefield_file_edit_delete(&$fo
   }
   return $file;
 }
-
-/**
- * Shared AHAH callback for uploads and deletions. It just differs in a few
- * unimportant details (what happens to the file, and which form is used as
- * a replacement) so these details are taken care of by a form callback.
- */
-function filefield_js($field_name, $type_name, $delta, $form_callback) {
-  $field = content_fields($field_name, $type_name);
-
-  if (empty($field) || empty($_POST['form_build_id'])) {
-    // Invalid request.
-    print drupal_to_js(array('data' => ''));
-    exit;
-  }
-
-  // Build the new form.
-  $form_state = array('submitted' => FALSE);
-  $form_build_id = $_POST['form_build_id'];
-  $form = form_get_cache($form_build_id, $form_state);
-
-  if (!$form) {
-    // Invalid form_build_id.
-    print drupal_to_js(array('data' => ''));
-    exit;
-  }
-  // form_get_cache() doesn't yield the original $form_state,
-  // but form_builder() does. Needed for retrieving the file array.
-  $built_form = $form;
-  $built_form_state = $form_state;
-  $built_form += array('#post' => $_POST);
-  $built_form = form_builder($_POST['form_id'], $built_form, $built_form_state);
-
-  // Clean ids, so that the same element doesn't get a different element id
-  // when rendered once more further down.
-  form_clean_id(NULL, TRUE);
-
-  // Perform the action for this AHAH callback.
-  $form_callback($built_form, $built_form_state, $field, $delta);
-
-  // Ask CCK for the replacement form element. Going through CCK gets us
-  // the benefit of nice stuff like '#required' merged in correctly.
-  module_load_include('inc', 'content', 'includes/content.node_form');
-  $field_element = content_field_form($form, $built_form_state, $field, $delta);
-  $delta_element = $field_element[$field_name][0]; // there's only one element in there
-
-  // Add the new element at the right place in the form.
-  if (module_exists('fieldgroup') && ($group_name = _fieldgroup_field_get_group($type_name, $field_name))) {
-    $form[$group_name][$field_name][$delta] = $delta_element;
-  }
-  else {
-    $form[$field_name][$delta] = $delta_element;
-  }
-
-  // Write the (unbuilt, updated) form back to the form cache.
-  form_set_cache($form_build_id, $form, $form_state);
-
-  // Render the form for output.
-  $form += array(
-    '#post' => $_POST,
-    '#programmed' => FALSE,
-  );
-  drupal_alter('form', $form, array(), 'filefield_js');
-  $form_state = array('submitted' => FALSE);
-  $form = form_builder('filefield_js', $form, $form_state);
-  $field_form = empty($group_name) ? $form[$field_name] : $form[$group_name][$field_name];
-
-  // We add a div around the new content to tell AHAH to let this fade in.
-  $field_form[$delta]['#prefix'] = '<div class="ahah-new-content">'. (isset($field_form[$delta]['#prefix']) ? $field_form[$delta]['#prefix'] : '');
-  $field_form[$delta]['#suffix'] = (isset($field_form[$delta]['#suffix']) ? $field_form[$delta]['#suffix'] : '') .'</div>';
-
-  $output = theme('status_messages') . drupal_render($field_form[$delta]);
-
-  // AHAH is not being nice to us and doesn't know the "other" button (that is,
-  // either "Upload" or "Delete") yet. Which in turn causes it not to attach
-  // AHAH behaviours after replacing the element. So we need to tell it first.
-  $javascript = drupal_add_js(NULL, NULL);
-  if (isset($javascript['setting'])) {
-    $output .= '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>';
-  }
-
-  // For some reason, file uploads don't like drupal_json() with its manual
-  // setting of the text/javascript HTTP header. So use this one instead.
-  print drupal_to_js(array('status' => TRUE, 'data' => $output));
-  exit;
-}
