? .cache
? .settings
Index: modules/field/field.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v
retrieving revision 1.50
diff -u -p -r1.50 field.api.php
--- modules/field/field.api.php	12 Nov 2009 21:03:36 -0000	1.50
+++ modules/field/field.api.php	24 Nov 2009 17:34:26 -0000
@@ -621,15 +621,16 @@ function hook_field_widget_info_alter(&$
  * contains the base form element properties derived from the field
  * configuration.
  *
- * Field API will set the weight, field name and delta values for each
- * form element. If there are multiple values for this field, the
- * Field API will call this function as many times as needed.
+ * @todo note about $form_state['storage']['field_info']
+ *
+ * Field API will set the weight, field name and delta values for each form
+ * element. If there are multiple values for this field, the Field API will
+ * call this function as many times as needed.
  *
  * @param $form
  *   The entire form array.
  * @param $form_state
- *   The form_state, $form_state['values'][$field['field_name']]
- *   holds the field's form values.
+ *   An associative array containing the current state of the form.
  * @param $field
  *   The field structure.
  * @param $instance
@@ -645,6 +646,7 @@ function hook_field_widget_info_alter(&$
  *   - #object_type: The name of the object the field is attached to.
  *   - #bundle: The name of the field bundle the field is contained in.
  *   - #field_name: The name of the field.
+ *   - #language: The language the field is being edited in.
  *   - #columns: A list of field storage columns of the field.
  *   - #title: The sanitized element label for the field instance, ready for
  *     output.
@@ -655,7 +657,6 @@ function hook_field_widget_info_alter(&$
  *     required.
  *   - #delta: The order of this item in the array of subelements; see $delta
  *     above.
- *
  * @return
  *   The form elements for a single widget for this field.
  */
@@ -680,8 +681,12 @@ function hook_field_widget(&$form, &$for
  *   - 'error': the error code. Complex widgets might need to report different
  *     errors to different form elements inside the widget.
  *   - 'message': the human readable message to be displayed.
+ * @param $form
+ *   The form array.
+ * @param $form_state
+ *   An associative array containing the current state of the form.
  */
-function hook_field_widget_error($element, $error) {
+function hook_field_widget_error($element, $error, $form, &$form_state) {
   form_error($element['value'], $error['message']);
 }
 
Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.59
diff -u -p -r1.59 field.attach.inc
--- modules/field/field.attach.inc	8 Nov 2009 19:11:56 -0000	1.59
+++ modules/field/field.attach.inc	24 Nov 2009 14:24:35 -0000
@@ -414,21 +414,10 @@ function _field_invoke_multiple_default(
  *   is provided the default site language will be used.
  * @return
  *   The form elements are added by reference at the top level of the $form
- *   parameter. Sample structure:
+ *   parameter. Processing information is added by reference in
+ *   $form_state['storage']['field_info'].
+ *   Sample structure for $form:
  *   @code
- *   array(
- *     '#fields' => array(
- *       // One sub-array per field appearing in the form, keyed by field name.
- *       'field_foo' => array (
- *         'field' => the field definition structure,
- *         'instance' => the field instance definition structure,
- *         'form_path' => an array of keys indicating the path to the field
- *           element within the full $form structure, used by the 'add more
- *           values' AHAH button. Any 3rd party module using form_alter() to
- *           modify the structure of the form should update this entry as well.
- *       ),
- *     ),
- *
  *     // One sub-array per field appearing in the form, keyed by field name.
  *     // The structure of the array differs slightly depending on whether the
  *     // widget is 'single-value' (provides the input for one field value,
@@ -436,12 +425,12 @@ function _field_invoke_multiple_default(
  *     // needed, or 'multiple-values' (one single widget allows the input of
  *     // several values, e.g checkboxes, select box...).
  *     // The sub-array is nested into a $langcode key where $langcode has the
- *     // same value of the $langcode parameter above. This allow us to match
- *     // the field data structure ($field_name[$langcode][$delta][$column]).
+ *     // same value of the $langcode parameter above.
  *     // The '#language' key holds the same value of $langcode and it is used
  *     // to access the field sub-array when $langcode is unknown.
  *     'field_foo' => array(
  *       '#tree' => TRUE,
+ *       '#field_name' => the name of the field
  *       '#language' => $langcode,
  *       $langcode => array(
  *         '#field_name' => the name of the field,
@@ -481,6 +470,26 @@ function _field_invoke_multiple_default(
  *     ),
  *   )
  *   @endcode
+ *
+ *   Sample structure for $form_state['storage']['field_info']: @todo
+ *   @code
+ *   array(
+ *       // One sub-array per field appearing in the form, keyed by field name.
+ *       'field_foo' => array (
+ *         // One sub-array per language the field is being edited in.
+ *         // @todo compare with above.
+ *         'xxz' => array (
+ *           'field' => the field definition structure,
+ *           'instance' => the field instance definition structure,
+ *           'parents' => @todo
+ *           'array_parents' => @todo an array of keys indicating the path to the field
+ *             element within the full $form structure, used by the 'add more
+ *             values' AHAH button.
+ *           'errors' => @todo
+ *         ),
+ *       ),
+ *     ),
+ *
  */
 function field_attach_form($obj_type, $object, &$form, &$form_state, $langcode = NULL) {
   // If no language is provided use the default site language.
@@ -743,7 +752,12 @@ function field_attach_form_validate($obj
   catch (FieldValidationException $e) {
     // Pass field-level validation errors back to widgets for accurate error
     // flagging.
-    _field_invoke_default('form_errors', $obj_type, $object, $form, $e->errors);
+    foreach ($e->errors as $field_name => $field_errors) {
+      foreach ($field_errors as $langcode => $language_errors) {
+        $form_state['storage']['field_info'][$field_name][$langcode]['errors'] = $language_errors;
+      }
+    }
+    _field_invoke_default('form_errors', $obj_type, $object, $form, $form_state);
   }
 }
 
Index: modules/field/field.default.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v
retrieving revision 1.23
diff -u -p -r1.23 field.default.inc
--- modules/field/field.default.inc	9 Nov 2009 18:23:41 -0000	1.23
+++ modules/field/field.default.inc	24 Nov 2009 14:24:35 -0000
@@ -11,13 +11,31 @@
  * the corresponding field_attach_[operation]() function.
  */
 
+/**
+ * @todo
+ * @param $obj_type
+ * @param $object
+ * @param $field
+ * @param $instance
+ * @param $langcode
+ * @param $items
+ * @param $form
+ * @param $form_state
+ */
 function field_default_extract_form_values($obj_type, $object, $field, $instance, $langcode, &$items, $form, &$form_state) {
   $field_name = $field['field_name'];
+  $field_info = $form_state['storage']['field_info'][$field_name][$langcode];
+
+  // Navigate to the right part of the submitted values.
+  $values = $form_state['values'];
+  foreach ($field_info['parents'] as $key) {
+    $values = isset($values[$key]) ? $values[$key] : NULL;
+  }
 
-  if (isset($form_state['values'][$field_name][$langcode])) {
-    $items = $form_state['values'][$field_name][$langcode];
+  if (isset($values)) {
     // Remove the 'value' of the 'add more' button.
-    unset($items['add_more']);
+    unset($values['add_more']);
+    $items = $values;
   }
 }
 
Index: modules/field/field.form.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v
retrieving revision 1.35
diff -u -p -r1.35 field.form.inc
--- modules/field/field.form.inc	20 Nov 2009 04:51:27 -0000	1.35
+++ modules/field/field.form.inc	24 Nov 2009 17:38:21 -0000
@@ -17,16 +17,15 @@ function field_default_form($obj_type, $
   }
 
   $field_name = $field['field_name'];
+  $addition[$field_name] = array();
 
-  // Put field information at the top of the form, so that it can be easily
-  // retrieved.
-  // Note : widgets and other form handling code should *always* fetch field
-  // and instance information from $form['#fields'] rather than from
-  // field_info_field(). This lets us build forms for 'variants' of a field,
-  // for instance on admin screens.
-  $form['#fields'][$field_name] = array(
+  // Store field information in $form_state['storage'].
+  $form_state['storage']['field_info'][$field_name][$langcode] = array(
     'field' => $field,
     'instance' => $instance,
+    'parents' => array(),
+    'array_parents' => array(),
+    'errors' => array(),
   );
 
   // Populate widgets with default values when creating a new object.
@@ -34,13 +33,13 @@ function field_default_form($obj_type, $
     $items = field_get_default_value($obj_type, $object, $field, $instance, $langcode);
   }
 
-  $field_elements = array();
-
+  // Collect widget elements.
+  $elements = array();
   if (field_access('edit', $field, $obj_type, $object)) {
     // If field module handles multiple values for this form element, and we
     // are displaying an individual element, process the multiple value form.
     if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-      $field_elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
+      $elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
     }
     // If the widget is handling multiple values (e.g Options), or if we are
     // displaying an individual element, just get a single form element and
@@ -53,6 +52,7 @@ function field_default_form($obj_type, $
           '#object_type' => $instance['object_type'],
           '#bundle' => $instance['bundle'],
           '#field_name' => $field_name,
+          '#language' => $langcode,
           '#columns' => array_keys($field['columns']),
           '#title' => check_plain(t($instance['label'])),
           '#description' => field_filter_xss($instance['description']),
@@ -67,23 +67,17 @@ function field_default_form($obj_type, $
           // assumptions about how the field is structured, just merge in the
           // returned element.
           if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-            $field_elements[$delta] = $element;
+            $elements[$delta] = $element;
           }
           else {
-            $field_elements = $element;
+            $elements = $element;
           }
         }
       }
     }
   }
 
-  if ($field_elements) {
-    // Add the field form element as a child keyed by language code to match
-    // the field data structure:
-    // $object->{$field_name}[$langcode][$delta][$column].
-    // The '#language' key can be used to access the field's form element
-    // when $langcode is unknown. The #weight property is inherited from the
-    // field's form element.
+  if ($elements) {
     // Also aid in theming of field widgets by rendering a classified
     // container.
     $addition[$field_name] = array(
@@ -95,29 +89,32 @@ function field_default_form($obj_type, $
           'field-widget-' . drupal_html_class($instance['widget']['type']),
         ),
       ),
-      '#tree' => TRUE,
       '#weight' => $instance['widget']['weight'],
-      '#language' => $langcode,
-      $langcode => $field_elements,
     );
   }
   else {
     // The field is not accessible, or the widget did not return anything. Make
     // sure the items are available in the submitted form values.
     foreach ($items as $delta => $item) {
-      $field_elements[$delta] = array(
+      $elements[$delta] = array(
         '#type' => 'value',
         '#value' => $item,
       );
     }
-    $addition[$field_name] = array(
-      '#tree' => TRUE,
-      '#language' => $langcode,
-      $langcode => $field_elements,
-    );
   }
 
-  $form['#fields'][$field_name]['form_path'] = array($field_name);
+  // @todo A word of explanation.
+  $elements['#after_build'][] = 'field_form_element_after_build';
+  $elements['#field_name'] = $field_name;
+  $elements['#language'] = $langcode;
+
+  $addition[$field_name] += array(
+    '#tree' => TRUE,
+    // The '#language' key can be used to access the field's form element
+    // when $langcode is unknown.
+    '#language' => $langcode,
+    $langcode => $elements,
+  );
 
   return $addition;
 }
@@ -153,7 +150,7 @@ function field_multiple_value_form($fiel
 
   $title = check_plain(t($instance['label']));
   $description = field_filter_xss(t($instance['description']));
-  $wrapper_id = drupal_html_class($field_name) . '-wrapper';
+  $wrapper_id = drupal_html_class($field_name) . '-add-more-wrapper';
   $field_elements = array();
 
   $function = $instance['widget']['module'] . '_field_widget';
@@ -164,6 +161,7 @@ function field_multiple_value_form($fiel
         '#object_type' => $instance['object_type'],
         '#bundle' => $instance['bundle'],
         '#field_name' => $field_name,
+        '#language' => $langcode,
         '#columns' => array_keys($field['columns']),
         // For multiple fields, title and description are handled by the wrapping table.
         '#title' => $multiple ? '' : $title,
@@ -299,36 +297,61 @@ function theme_field_multiple_value_form
   return $output;
 }
 
+/**
+ * Stores information about the built form structure in the form storage.
+ *
+ * This ensures Field API form features do not break if the form structure is
+ * modified in hook_form_alter().
+ *
+ * The 'parents' array is used by to extract field values from the submitted
+ * values.
+ * @see field_default_extract_form_values()
+ *
+ * The 'array_parents' array is used to assign validation errors to actual form
+ * elements, and to identify the form element to return in the AJAX 'add more'
+ * button handler.
+ * @see field_default_form_errors()
+ * @see field_add_more_js()
+ */
+function field_form_element_after_build($element, &$form_state) {
+  $field_name = $element['#field_name'];
+  $langcode = $element['#language'];
+  $form_state['storage']['field_info'][$field_name][$langcode]['parents'] = $element['#parents'];
+  $form_state['storage']['field_info'][$field_name][$langcode]['array_parents'] = $element['#array_parents'];
+
+  return $element;
+}
 
 /**
  * Transfer field-level validation errors to widgets.
  */
-function field_default_form_errors($obj_type, $object, $field, $instance, $langcode, $items, $form, $errors) {
+function field_default_form_errors($obj_type, $object, $field, $instance, $langcode, $items, $form, &$form_state) {
   $field_name = $field['field_name'];
-  if (!empty($errors[$field_name][$langcode])) {
+  $field_info = $form_state['storage']['field_info'][$field_name][$langcode];
+
+  if (!empty($field_info['errors'])) {
     $function = $instance['widget']['module'] . '_field_widget_error';
     $function_exists = function_exists($function);
 
     // Walk the form down to where the widget lives.
-    $form_path = $form['#fields'][$field_name]['form_path'];
     $element = $form;
-    foreach ($form_path as $key) {
+    foreach ($field_info['array_parents'] as $key) {
       $element = $element[$key];
     }
 
     $multiple_widget = field_behaviors_widget('multiple values', $instance) != FIELD_BEHAVIOR_DEFAULT;
-    foreach ($errors[$field_name][$langcode] as $delta => $delta_errors) {
+    foreach ($field_info['errors'] as $delta => $delta_errors) {
       // For multiple single-value widgets, pass errors by delta.
       // For a multiple-value widget, all errors are passed to the main widget.
-      $error_element = $multiple_widget ? $element[$langcode] : $element[$langcode][$delta];
+      $error_element = $multiple_widget ? $element : $element[$delta];
       foreach ($delta_errors as $error) {
         if ($function_exists) {
-          $function($error_element, $error);
+          $function($error_element, $error, $form, $form_state);
         }
         else {
           // Make sure that errors are reported (even incorrectly flagged) if
           // the widget module fails to implement hook_field_widget_error().
-          form_error($error_element, $error['error']);
+          form_error($error_element, $error['error'], $form, $form_state);
         }
       }
     }
@@ -360,22 +383,25 @@ function field_add_more_submit($form, &$
 function field_add_more_js($form, $form_state) {
   // Retrieve field information.
   $field_name = $form_state['clicked_button']['#field_name'];
-  $field = $form['#fields'][$field_name]['field'];
+  $langcode = $form_state['clicked_button']['#language'];
+  $field_info = $form_state['storage']['field_info'][$field_name][$langcode];
+  $field = $field_info['field'];
+
   if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
     ajax_render(array());
   }
-  // Navigate to the right part of the form.
-  $form_path = $form['#fields'][$field_name]['form_path'];
-  $field_form = $form;
-  foreach ($form_path as $key) {
-    $field_form = $field_form[$key];
+
+  // Navigate to the right element in the the form.
+  $element = $form;
+
+  foreach ($field_info['array_parents'] as $key) {
+    $element = $element[$key];
   }
 
   // Add a DIV around the new field to receive the AJAX effect.
-  $langcode = $field_form['#language'];
-  $delta = $field_form[$langcode]['#max_delta'];
-  $field_form[$langcode][$delta]['#prefix'] = '<div class="ajax-new-content">' . (isset($field_form[$langcode][$delta]['#prefix']) ? $field_form[$langcode][$delta]['#prefix'] : '');
-  $field_form[$langcode][$delta]['#suffix'] = (isset($field_form[$langcode][$delta]['#suffix']) ? $field_form[$langcode][$delta]['#suffix'] : '') . '</div>';
+  $delta = $element['#max_delta'];
+  $element[$delta]['#prefix'] = '<div class="ajax-new-content">' . (isset($element[$delta]['#prefix']) ? $element[$delta]['#prefix'] : '');
+  $element[$delta]['#suffix'] = (isset($element[$delta]['#suffix']) ? $element[$delta]['#suffix'] : '') . '</div>';
 
-  return drupal_render($field_form);
+  return $element;
 }
Index: modules/field/modules/number/number.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/number/number.module,v
retrieving revision 1.28
diff -u -p -r1.28 number.module
--- modules/field/modules/number/number.module	12 Nov 2009 21:03:36 -0000	1.28
+++ modules/field/modules/number/number.module	24 Nov 2009 14:24:35 -0000
@@ -336,8 +336,8 @@ function number_field_widget(&$form, &$f
  * FAPI validation of an individual number element.
  */
 function number_field_widget_validate($element, &$form_state) {
-  $field = $form_state['complete form']['#fields'][$element['#field_name']]['field'];
-  $instance = $form_state['complete form']['#fields'][$element['#field_name']]['instance'];
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
 
   $type = $element['#number_type'];
   $value = $element['#value'];
@@ -372,6 +372,6 @@ function number_field_widget_validate($e
 /**
  * Implement hook_field_widget_error().
  */
-function number_field_widget_error($element, $error) {
+function number_field_widget_error($element, $error, $form, &$form_state) {
   form_error($element['value'], $error['message']);
 }
Index: modules/field/modules/options/options.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.module,v
retrieving revision 1.18
diff -u -p -r1.18 options.module
--- modules/field/modules/options/options.module	20 Nov 2009 05:14:13 -0000	1.18
+++ modules/field/modules/options/options.module	24 Nov 2009 14:24:35 -0000
@@ -115,8 +115,8 @@ function options_field_widget(&$form, &$
  * Form element validation handler for options element.
  */
 function options_field_widget_validate($element, &$form_state) {
-  $field = $form_state['complete form']['#fields'][$element['#field_name']]['field'];
-  $instance = $form_state['complete form']['#fields'][$element['#field_name']]['instance'];
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
 
   // Transpose selections from field => delta to delta => field, turning
   // multiple selected options into multiple parent elements.
@@ -252,7 +252,7 @@ function options_array_transpose($array)
 /**
  * Implement hook_field_widget_error().
  */
-function options_field_widget_error($element, $error) {
+function options_field_widget_error($element, $error, $form, &$form_state) {
   form_error($element, $error['message']);
 }
 
Index: modules/field/modules/text/text.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v
retrieving revision 1.37
diff -u -p -r1.37 text.module
--- modules/field/modules/text/text.module	22 Nov 2009 08:14:27 -0000	1.37
+++ modules/field/modules/text/text.module	24 Nov 2009 14:24:35 -0000
@@ -579,7 +579,7 @@ function text_field_widget(&$form, &$for
 /**
  * Implement hook_field_widget_error().
  */
-function text_field_widget_error($element, $error) {
+function text_field_widget_error($element, $error, $form, &$form_state) {
   switch ($error['error']) {
     case 'text_summary_max_length':
       $error_element = $element[$element['#columns'][1]];
@@ -598,17 +598,10 @@ function text_field_widget_error($elemen
  *
  * Build the form element. When creating a form using FAPI #process,
  * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
- *
- * TODO: For widgets to be actual FAPI 'elements', reusable outside of a
- * 'field' context, they shoudn't rely on $field and $instance. The bits of
- * information needed to adjust the behavior of the 'element' should be
- * extracted in hook_field_widget() above.
  */
 function text_textfield_elements_process($element, $form_state, $form) {
-  $field = $form['#fields'][$element['#field_name']]['field'];
-  $instance = $form['#fields'][$element['#field_name']]['instance'];
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
   $field_key = $element['#columns'][0];
   $delta = $element['#delta'];
 
@@ -638,12 +631,10 @@ function text_textfield_elements_process
  *
  * Build the form element. When creating a form using FAPI #process,
  * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
  */
 function text_textarea_elements_process($element, $form_state, $form) {
-  $field = $form['#fields'][$element['#field_name']]['field'];
-  $instance = $form['#fields'][$element['#field_name']]['instance'];
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
   $field_key = $element['#columns'][0];
   $delta = $element['#delta'];
 
@@ -671,12 +662,10 @@ function text_textarea_elements_process(
  *
  * Build the form element. When creating a form using FAPI #process,
  * note that $element['#value'] is already set.
- *
- * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
  */
 function text_textarea_with_summary_process($element, $form_state, $form) {
-  $field = $form['#fields'][$element['#field_name']]['field'];
-  $instance = $form['#fields'][$element['#field_name']]['instance'];
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
   $delta = $element['#delta'];
 
   $field_key = $element['#columns'][1];
Index: modules/field/tests/field_test.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.field.inc,v
retrieving revision 1.1
diff -u -p -r1.1 field_test.field.inc
--- modules/field/tests/field_test.field.inc	20 Nov 2009 23:29:28 -0000	1.1
+++ modules/field/tests/field_test.field.inc	24 Nov 2009 14:24:35 -0000
@@ -179,7 +179,7 @@ function field_test_field_widget(&$form,
 /**
  * Implements hook_field_widget_error().
  */
-function field_test_field_widget_error($element, $error) {
+function field_test_field_widget_error($element, $error, $form, &$form_state) {
   form_error($element['value'], $error['message']);
 }
 
Index: modules/field_ui/field_ui.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v
retrieving revision 1.29
diff -u -p -r1.29 field_ui.admin.inc
--- modules/field_ui/field_ui.admin.inc	11 Nov 2009 06:58:24 -0000	1.29
+++ modules/field_ui/field_ui.admin.inc	24 Nov 2009 17:40:43 -0000
@@ -1220,21 +1220,13 @@ function field_ui_default_value_widget($
   $instance['description'] = '';
   $items = $instance['default_value'];
   // Set up form info that the default value widget will need.
-  $form['#fields'] = array(
-    $field['field_name'] => array(
-      'field' => $field,
-      'instance' => $instance,
-    ),
+  $form_state['storage']['field_info'][$field['field_name']][FIELD_LANGUAGE_NONE] = array(
+    'field' => $field,
+    'instance' => $instance,
   );
-  function_exists('field_default_form');
   // @todo Allow multiple values (requires more work on 'add more' JS handler).
   $widget_form = field_default_form(NULL, NULL, $field, $instance, FIELD_LANGUAGE_NONE, $items, $form, $form_state, 0);
   $form['instance']['default_value_widget'] += $widget_form;
-  $form['#fields'][$field['field_name']]['form_path'] = array(
-    'instance',
-    'default_value_widget',
-    $field['field_name'],
-  );
 }
 
 /**
Index: modules/file/file.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/file/file.field.inc,v
retrieving revision 1.10
diff -u -p -r1.10 file.field.inc
--- modules/file/file.field.inc	11 Nov 2009 08:32:35 -0000	1.10
+++ modules/file/file.field.inc	24 Nov 2009 14:50:13 -0000
@@ -503,9 +503,9 @@ function file_field_widget(&$form, &$for
     $elements['#process'] = array('file_field_widget_process_multiple');
     $elements['#title'] = $element['#title'];
     $elements['#description'] = $element['#description'];
-    $elements['#object_type'] = $element['#object_type'];
-    $elements['#bundle'] = $element['#bundle'];
     $elements['#field_name'] = $element['#field_name'];
+    $elements['#language'] = $element['#language'];
+    $elements['#display_field'] = $field['settings']['display_field'];
 
     // Add some properties that will eventually be added to the file upload
     // field. These are added here so that they may be referenced easily through
@@ -573,7 +573,7 @@ function file_field_widget_value($elemen
   if ($input) {
     // Checkboxes lose their value when empty.
     // If the display field is present make sure its unchecked value is saved.
-    $field = field_info_field($element['#field_name']);
+    $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
     if (empty($input['display'])) {
       $input['display'] = $field['settings']['display_field'] ? 0 : 1;
     }
@@ -601,8 +601,8 @@ function file_field_widget_process($elem
   $item = $element['#value'];
   $item['fid'] = $element['fid']['#value'];
 
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
+  $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
   $settings = $instance['widget']['settings'];
 
   $element['#theme'] = 'file_widget';
@@ -713,9 +713,6 @@ function theme_file_widget($variables) {
 function theme_file_widget_multiple($variables) {
   $element = $variables['element'];
 
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
-
   // Get our list of widgets in order.
   $widgets = array();
   foreach (element_children($element) as $key) {
@@ -730,7 +727,7 @@ function theme_file_widget_multiple($var
   // Build up a table of applicable fields.
   $headers = array();
   $headers[] = t('File information');
-  if (!empty($field['settings']['display_field'])) {
+  if ($element['#display_field']) {
     $headers[] = array(
       'data' => t('Display'),
       'class' => array('checkbox'),
@@ -758,7 +755,7 @@ function theme_file_widget_multiple($var
 
     // Render the "Display" option in its own own column.
     $display = '';
-    if (!empty($field['settings']['display_field'])) {
+    if ($element['#display_field']) {
       unset($element[$key]['display']['#title']);
       $display = array(
         'data' => drupal_render($element[$key]['display']),
@@ -776,7 +773,7 @@ function theme_file_widget_multiple($var
 
     $row = array();
     $row[] = $information;
-    if (!empty($field['settings']['display_field'])) {
+    if ($element['#display_field']) {
       $row[] = $display;
     }
     $row[] = $weight;
Index: modules/image/image.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.field.inc,v
retrieving revision 1.4
diff -u -p -r1.4 image.field.inc
--- modules/image/image.field.inc	1 Nov 2009 14:05:32 -0000	1.4
+++ modules/image/image.field.inc	24 Nov 2009 14:24:35 -0000
@@ -346,8 +346,8 @@ function image_field_widget_process($ele
   $item = $element['#value'];
   $item['fid'] = $element['fid']['#value'];
 
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
+  $instance = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['instance'];
+
   $settings = $instance['settings'];
   $widget_settings = $instance['widget']['settings'];
 
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.540
diff -u -p -r1.540 taxonomy.module
--- modules/taxonomy/taxonomy.module	20 Nov 2009 05:14:13 -0000	1.540
+++ modules/taxonomy/taxonomy.module	24 Nov 2009 16:32:52 -0000
@@ -1232,7 +1232,7 @@ function taxonomy_autocomplete_validate(
   // them here and process them independently.
   if ($tags = $element['#value']) {
     // Collect candidate vocabularies.
-    $field = $form_state['complete form']['#fields'][$element['#field_name']]['field'];
+    $field = $form_state['storage']['field_info'][$element['#field_name']][$element['#language']]['field'];
     $vids = array();
     foreach ($field['settings']['allowed_values'] as $tree) {
       $vids[] = $tree['vid'];
@@ -1270,7 +1270,7 @@ function taxonomy_autocomplete_validate(
 /**
  * Implement hook_field_widget_error().
  */
-function taxonomy_field_widget_error($element, $error) {
+function taxonomy_field_widget_error($element, $error, $form, &$form_state) {
   if ($element['#type'] == 'textfield') {
     form_error($element, $error['message']);
   }
