? .cache
? .settings
Index: modules/field/field.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v
retrieving revision 1.51
diff -u -p -r1.51 field.api.php
--- modules/field/field.api.php	2 Dec 2009 19:26:21 -0000	1.51
+++ modules/field/field.api.php	8 Dec 2009 23:28:30 -0000
@@ -252,7 +252,7 @@ function hook_field_schema($field) {
  * for subsequent loads. You should never use this hook to load fieldable
  * entities, since this is likely to cause infinite recursions when
  * hook_field_load() is run on those as well. Use
- * hook_field_formatter_prepare_view() instead.
+ * hook_field_formatter_prepare() instead.
  *
  * @param $obj_type
  *   The type of $object.
@@ -688,30 +688,15 @@ function hook_field_widget_error($elemen
 /**
  * Expose Field API formatter types.
  *
- * Formatters are mainly theme functions that handle the output of individual
+ * @todo Formatters are mainly theme functions that handle the output of individual
  * field values. These theme calls are typically triggered during the execution
  * of drupal_render() on the render structure built by field_attach_view().
  *
- * The name of the theme hook invoked when displaying the values is derived
- * from formatter type names, using the pattern field_formatter_FORMATTER_NAME.
- * field.module takes care of exposing the corresponding theme functions
- * through hook_theme(). Specifically, field.module defines the theme
- * hook:
- *
- * @code
- *   'field_formatter_FORMATTER_NAME' => array(
- *     'render_element' => 'element',
- *   )
- * @code
- *
- * If a formatter requires a different theme hook definition,
- * implement hook_theme_registry_alter().
  *
  * @see hook_field_formatter_info().
  * @see hook_field_formatter_info_alter().
- * @see theme_field_formatter_FORMATTER_NAME().
- * @see hook_theme().
- * @see hook_theme_registry_alter().
+ * @see hook_field_formatter().
+ * @see hook_field_formatter_prepare().
  *
  * @return
  *   An array describing the formatter types implemented by the module.
@@ -733,8 +718,8 @@ function hook_field_widget_error($elemen
  *       field value (most common case). The formatter theme will be invoked
  *       iteratively on each of the field valies.
  *       FIELD_BEHAVIOR_CUSTOM if one single invocation of the formatter theme
- *       takes care of displays all the field values. Examples: points on
- *       a generated graph picture, a Google map, a single link to a popup...
+ *       takes care of displaying all the field values. Examples: points on a
+ *       generated graph picture, a Google map, a single link to a popup...
  */
 function hook_field_formatter_info() {
   return array(
@@ -799,57 +784,21 @@ function hook_field_formatter_info_alter
 }
 
 /**
- * Theme function for a field formatter.
- *
- * This is an example of a 'single' formatter, displaying one single field
- * value (the hook_field_formatter_info() entry uses
- * 'multiple values' = FIELD_BEHAVIOR_DEFAULT).
+ * Returns a renderable array for a field value.
  *
- * @param $variables
- *   An associative array containing:
- *   - element: A render structure sub-array, containing the following keys:
- *     - #item: The field value being displayed.
- *     - #delta: The index of the value being displayed within the object's
- *       values for the field.
- *     - #field_name: The name of the field being displayed.
- *     - #bundle: The bundle of the object being displayed.
- *     - #object: The object being displayed.
- *     - #object_type: The type of the object being displayed.
- *     - #formatter: The name of the formatter being used.
- *     - #settings: The array of formatter settings.
- */
-function theme_field_formatter_FORMATTER_SINGLE($variables) {
-  // This relies on a 'safe' element being prepared in hook_field_sanitize().
-  return $variables['element']['#item']['safe'];
-}
-
-/**
- * Theme function for a field formatter.
- *
- * This is an example of a 'single' formatter, displaying all the field values
- * (the hook_field_formatter_info() entry uses
- * 'multiple values' = FIELD_BEHAVIOR_CUSTOM).
+ * @param $obj_type
+ * @param $object
+ * @param $field
+ * @param $instance
+ * @param $langcode
+ * @param $display
+ * @param $items
+ * @param $delta
  *
- * @param $variables
- *   An associative array containing:
- *   - element: A render structure sub-array, containing the following keys:
- *     - #field_name: The name of the field being displayed.
- *     - #bundle: The bundle of the object being displayed.
- *     - #object: The object being displayed.
- *     - #object_type: The type of the object being displayed.
- *     - #formatter: The name of the formatter being used.
- *     - #settings: The array of formatter settings.
- *     - numeric indexes: the field values being displayed.
+ * @return
  */
-function theme_field_formatter_FORMATTER_MULTIPLE($variables) {
-  $element = $variables['element'];
+function hook_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
 
-  $items = array();
-  foreach (element_children($element) as $key) {
-    $items[$key] = $key .':'. $element[$key]['#item']['value'];
-  }
-  $output = implode('|', $items);
-  return $output;
 }
 
 /**
@@ -876,11 +825,42 @@ function theme_field_formatter_FORMATTER
  *   Changes or additions to field values are done by altering the $items
  *   parameter by reference.
  */
-function hook_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
+function hook_field_formatter_prepare($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
 
 }
 
 /**
+ * @todo Theme function for a field formatter.
+ *
+ * This is an example of a 'single' formatter, displaying one single field
+ * value (the hook_field_formatter_info() entry uses
+ * 'multiple values' = FIELD_BEHAVIOR_DEFAULT).
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: A render structure sub-array, containing the following keys:
+ *     - #item: The field value being displayed.
+ *     - #delta: The index of the value being displayed within the object's
+ *       values for the field.
+ *     - #field_name: The name of the field being displayed.
+ *     - #bundle: The bundle of the object being displayed.
+ *     - #object: The object being displayed.
+ *     - #object_type: The type of the object being displayed.
+ *     - #formatter: The name of the formatter being used.
+ *     - #settings: The array of formatter settings.
+ */
+
+/**
+ * Theme function for a field formatter.
+ *
+ * This is an example of a 'single' formatter, displaying all the field values
+ * (the hook_field_formatter_info() entry uses
+ * 'multiple values' = FIELD_BEHAVIOR_CUSTOM).
+ *
+ * @todo
+ */
+
+/**
  * @} End of "ingroup field_type"
  */
 
Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.60
diff -u -p -r1.60 field.attach.inc
--- modules/field/field.attach.inc	4 Dec 2009 16:49:46 -0000	1.60
+++ modules/field/field.attach.inc	8 Dec 2009 23:28:30 -0000
@@ -1113,10 +1113,39 @@ function field_attach_prepare_view($obj_
 }
 
 /**
- * Generate and return a structured content array tree suitable for
- * drupal_render() for all of the fields on an object. The format of
- * each field's rendered content depends on the display formatter and
- * its settings.
+ * Returns a renderable array for the fields on an object.
+ *
+ * Each field is displayed according to the display options specified in the
+ * $instance definition for the given $build_mode.
+ *
+ * Sample structure:
+ * @code
+ * array(
+ *   'field_foo' => array(
+ *     '#theme' => 'field',
+ *     '#title' => the label of the field instance,
+ *     '#label_display' => the label display mode,
+ *     '#object' => the fieldable object being displayed,
+ *     '#object_type' => the type of the object being displayed,
+ *     '#language' => the language of the field values being displayed,
+ *     '#build_mode' => the build mode,
+ *     '#field_name' => the name of the field,
+ *     '#field_type' => the type of the field,
+ *     '#formatter' => the name of the formatter,
+ *     '#items' => the field values being displayed,
+ *     // The element's children are the formatted values returned by
+ *     // hook_field_formatter(), keyed by delta.
+ *     0 => array(
+ *       // Renderable array for value 0, or for all values if the formatter
+ *       // is 'multiple-values'.
+ *     ),
+ *     1 => array(
+ *       // Renderable array for value 1 (only for 'single-value' formatters).
+ *     ),
+ *     // ...
+ *   ),
+ * );
+ * @endcode
  *
  * @param $obj_type
  *   The type of $object; e.g. 'node' or 'user'.
@@ -1128,56 +1157,7 @@ function field_attach_prepare_view($obj_
  *   The language the field values are to be shown in. If no language is
  *   provided the current language is used.
  * @return
- *   A structured content array tree for drupal_render().
- *   Sample structure:
- *   @code
- *   array(
- *     'field_foo' => array(
- *       // The structure of the array differs slightly depending on whether
- *       // the formatter is 'single-value' (displays one single field value,
- *       // most common case) or 'multiple-values' (displays all the field's
- *       // values, e.g. points on a graph or a map).
- *       '#theme' => 'field',
- *       '#title' => the label of the field instance,
- *       '#label_display' => the label display mode,
- *       '#object' => the fieldable object being displayed,
- *       '#object_type' => the type of the object being displayed,
- *       '#language' => the language of the field values being displayed,
- *       '#build_mode' => the build mode,
- *       '#field_name' => the name of the field,
- *       '#formatter_single' => boolean indicating whether the formatter is single or
- *          multiple,
- *       'items' => array(
- *         // One sub-array per field value, keyed by delta.
- *         0 => array(
- *           '#item' => the field value for delta 0,
- *
- *           // Only for 'single-value' formatters:
- *           '#theme' => the formatter's theme function,
- *           '#formatter' => name of the formatter,
- *           '#settings' => array of formatter settings,
- *           '#object' => the fieldable object being displayed,
- *           '#object_type' => the type of the object being displayed,
- *           '#field_name' => the name of the field,
- *           '#bundle' => the object's bundle,
- *           '#delta' => 0,
- *         ),
- *         1 => array(
- *           ...
- *         ),
- *
- *         // Only for 'multiple-values' formatters:
- *         '#theme' => the formatter's theme function,
- *         '#formatter' => name of the formatter,
- *         '#settings' => array of formatter settings,
- *         '#object' => the fieldable object being displayed,
- *         '#object_type' => the type of the object being displayed,
- *         '#field_name' => the name of the field,
- *         '#bundle' => the object's bundle,
- *       ),
- *     ),
- *   );
- *   @endcode
+ *   A renderable array for the field values.
  */
 function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode = NULL) {
   // If no language is provided use the current UI language.
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	8 Dec 2009 23:28:30 -0000
@@ -54,7 +54,7 @@ function field_default_insert($obj_type,
 }
 
 /**
- * Invoke hook_field_formatter_prepare_view() on the relavant formatters.
+ * Invoke hook_field_formatter_prepare() on the relavant formatters.
  */
 function field_default_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $options, $build_mode) {
   // Group objects, instances and items by formatter module.
@@ -64,13 +64,13 @@ function field_default_prepare_view($obj
     $modules[$module] = $module;
     $grouped_objects[$module][$id] = $objects[$id];
     $grouped_instances[$module][$id] = $instance;
-    // hook_field_formatter_prepare_view() alters $items by reference.
+    // hook_field_formatter_prepare() alters $items by reference.
     $grouped_items[$module][$id] = &$items[$id];
   }
 
   foreach ($modules as $module) {
-    // Invoke hook_field_formatter_prepare_view().
-    $function = $module . '_field_formatter_prepare_view';
+    // Invoke hook_field_formatter_prepare().
+    $function = $module . '_field_formatter_prepare';
     if (function_exists($function)) {
       $function($obj_type, $grouped_objects[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $build_mode);
     }
@@ -89,57 +89,35 @@ function field_default_view($obj_type, $
   $display = $instance['display'][$build_mode];
 
   if ($display['type'] !== 'hidden') {
-    $theme = 'field_formatter_' . $display['type'];
-    $single = (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT);
-
-    $label_display = $display['label'];
     if ($build_mode == 'search_index') {
-      $label_display = 'hidden';
+      $display['label'] = 'hidden';
     }
 
-    $info = array(
-      '#field_name' => $field['field_name'],
-      '#object_type' => $obj_type,
-      '#bundle' => $bundle,
-      '#object' => $object,
-    );
-
-    $element = $info + array(
+    $element = array(
       '#theme' => 'field',
       '#weight' => $display['weight'],
-      '#title' => check_plain(t($instance['label'])),
+      '#title' => t($instance['label']),
       '#access' => field_access('view', $field, $obj_type, $object),
-      '#label_display' => $label_display,
+      '#label_display' => $display['label'],
       '#build_mode' => $build_mode,
       '#language' => $langcode,
-      '#formatter_single' => $single,
-      'items' => array(),
-    );
-
-    // Fill-in items.
-    foreach ($items as $delta => $item) {
-      $element['items'][$delta] = array(
-        '#item' => $item,
-        '#weight' => $delta,
-      );
-    }
-
-    // Append formatter information either on each item ('single-value' formatter)
-    // or at the upper 'items' level ('multiple-value' formatter)
-    $format_info = $info + array(
-      '#theme' => $theme,
+      '#field_name' => $field['field_name'],
+      '#field_type' => $field['type'],
+      '#object_type' => $obj_type,
+      '#bundle' => $bundle,
+      '#object' => $object,
+      '#items' => $items,
       '#formatter' => $display['type'],
-      '#settings' => $display['settings'],
     );
 
-    if ($single) {
+    if (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT) {
       foreach ($items as $delta => $item) {
-        $element['items'][$delta] += $format_info;
-        $element['items'][$delta]['#item']['#delta'] = $delta;
+        $element[$delta] = module_invoke($display['module'], 'field_formatter', $obj_type, $object, $field, $instance, $langcode, $display, $items, $delta);
+        $element[$delta]['#weight'] = $delta;
       }
     }
     else {
-      $element['items'] += $format_info;
+      $element[0] = module_invoke($display['module'], 'field_formatter', $obj_type, $object, $field, $instance, $langcode, $display, $items, 0);
     }
 
     $addition = array($field['field_name'] => $element);
Index: modules/field/field.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.module,v
retrieving revision 1.51
diff -u -p -r1.51 field.module
--- modules/field/field.module	4 Dec 2009 16:49:46 -0000	1.51
+++ modules/field/field.module	8 Dec 2009 23:28:30 -0000
@@ -181,15 +181,7 @@ function field_theme() {
       'render element' => 'element',
     ),
   );
-  $field_formatters = field_info_formatter_types(NULL);
-  foreach ($field_formatters as $key => $field_formatter) {
-    $items['field_formatter_' . $key] = array(
-      'render element' => 'element',
-    );
-    if (isset($field_formatter['theme'])) {
-      $items['field_formatter_' . $key] += $field_formatter['theme'];
-    }
-  }
+
   return $items;
 }
 
@@ -686,24 +678,16 @@ function field_extract_bundle($obj_type,
  */
 function template_preprocess_field(&$variables) {
   $element = $variables['element'];
-  list(, , $bundle) = entity_extract_ids($element['#object_type'], $element['#object']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $bundle);
+  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
   $field = field_info_field($element['#field_name']);
 
-  $field_type_css = strtr($field['type'], '_', '-');
-  $field_name_css = strtr($field['field_name'], '_', '-');
+  $field_type_css = drupal_html_class($field['type']);
+  $field_name_css = drupal_html_class($field['field_name']);
 
   // Prepare an $items variable that the template can simply loop on.
-  if ($element['#formatter_single']) {
-    // Filter out non-children properties that might have been added if the
-    // renderable array has gone through form_builder().
-    $items = array_intersect_key($element['items'], array_flip(element_children($element['items'])));
-  }
-  else {
-    // If the formatter is multiple, the template sees only one 'item', which
-    // will include all values.
-    $items = array($element['items']);
-  }
+  // Filter out non-children properties that might have been added if the
+  // renderable array has gone through form_builder().
+  $items = array_intersect_key($element, array_flip(element_children($element)));
 
   $additions = array(
     'object' => $element['#object'],
@@ -715,7 +699,7 @@ function template_preprocess_field(&$var
     'field_name' => $field['field_name'],
     'field_type_css' => $field_type_css,
     'field_name_css' => $field_name_css,
-    'label' => $element['#title'],
+    'label' => check_plain($element['#title']),
     'label_display' => $element['#label_display'],
     'label_hidden' => $element['#label_display'] == 'hidden',
     'field_language' => $element['#language'],
@@ -728,8 +712,8 @@ function template_preprocess_field(&$var
     'template_files' => array(
       'field',
       'field-' . $element['#field_name'],
-      'field-' . $bundle,
-      'field-' . $element['#field_name'] . '-' . $bundle,
+      'field-' . $element['#bundle'],
+      'field-' . $element['#field_name'] . '-' . $element['#bundle'],
     ),
   );
   $variables = array_merge($variables, $additions);
Index: modules/field/modules/list/list.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/list/list.module,v
retrieving revision 1.19
diff -u -p -r1.19 list.module
--- modules/field/modules/list/list.module	4 Dec 2009 16:49:46 -0000	1.19
+++ modules/field/modules/list/list.module	8 Dec 2009 23:28:30 -0000
@@ -298,22 +298,29 @@ function list_field_formatter_info() {
 }
 
 /**
- * Theme function for 'default' list field formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_list_default($variables) {
-  $element = $variables['element'];
-  $field = field_info_field($element['#field_name']);
-  if (($allowed_values = list_allowed_values($field)) && isset($allowed_values[$element['#item']['value']])) {
-    return $allowed_values[$element['#item']['value']];
+function list_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $value = $items[$delta]['value'];
+
+  switch ($display['type']) {
+    case 'list_default':
+      $allowed_values = list_allowed_values($field);
+      if (isset($allowed_values[$value])) {
+        $output = $allowed_values[$value];
+      }
+      else {
+        // If no match was found in allowed values, fall back to the key.
+        $output = $value;
+      }
+      break;
+
+    case 'list_key':
+      $output = $value;
+      break;
   }
-  // If no match was found in allowed values, fall back to the key.
-  return $element['#item']['safe'];
-}
 
-/**
- * Theme function for 'key' list field formatter.
- */
-function theme_field_formatter_list_key($variables) {
-  $element = $variables['element'];
-  return $element['#item']['safe'];
+  return array(
+    '#markup' => $output,
+  );
 }
Index: modules/field/modules/number/number.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/number/number.module,v
retrieving revision 1.29
diff -u -p -r1.29 number.module
--- modules/field/modules/number/number.module	4 Dec 2009 16:49:46 -0000	1.29
+++ modules/field/modules/number/number.module	8 Dec 2009 23:28:30 -0000
@@ -7,15 +7,6 @@
  */
 
 /**
- * Implements hook_theme_alter().
- */
-function number_theme_registry_alter(&$theme_registry) {
-  // The number_integer and number_decimal formatters use the same function.
-  $theme_registry['field_formatter_number_default']['function'] = 'theme_field_formatter_number';
-  $theme_registry['field_formatter_number_decimal']['function'] = 'theme_field_formatter_number';
-}
-
-/**
  * Implements hook_field_info().
  */
 function number_field_info() {
@@ -25,7 +16,7 @@ function number_field_info() {
       'description' => t('This field stores a number in the database as an integer.'),
       'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
       'default_widget' => 'number',
-      'default_formatter' => 'number_default',
+      'default_formatter' => 'number_integer',
     ),
     'number_decimal' => array(
       'label' => t('Decimal'),
@@ -221,7 +212,7 @@ function number_field_is_empty($item, $f
  */
 function number_field_formatter_info() {
   return array(
-    'number_default' => array(
+    'number_integer' => array(
       'label' => t('default'),
       'field types' => array('number_integer'),
       'settings' =>  array(
@@ -249,39 +240,36 @@ function number_field_formatter_info() {
 }
 
 /**
- * Theme function for 'unformatted' number field formatter.
- */
-function theme_field_formatter_number_unformatted($variables) {
-  $element = $variables['element'];
-  return $element['#item']['value'];
-}
-
-/**
- * Proxy theme function for number field formatters.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_number($variables) {
-  $element = $variables['element'];
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
-  $value = $element['#item']['value'];
-  $settings = $element['#settings'];
-  $formatter_type = $element['#formatter'];
+function number_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $value = $items[$delta]['value'];
 
-  if (empty($value) && $value !== '0') {
-    return '';
-  }
-
-  $output = number_format($value, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
+  switch ($display['type']) {
+    case 'number_integer':
+    case 'number_decimal':
+      $settings = $display['settings'];
+      if (empty($value) && $value !== '0') {
+        return '';
+      }
+      $output = number_format($value, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
+      if ($settings['prefix_suffix']) {
+        $prefixes = isset($instance['settings']['prefix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['prefix'])) : array('');
+        $suffixes = isset($instance['settings']['suffix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['suffix'])) : array('');
+        $prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
+        $suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
+        $output = $prefix . $output . $suffix;
+      }
+      break;
 
-  if ($settings['prefix_suffix']) {
-    $prefixes = isset($instance['settings']['prefix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['prefix'])) : array('');
-    $suffixes = isset($instance['settings']['suffix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['suffix'])) : array('');
-    $prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
-    $suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
-    $output = $prefix . $output . $suffix;
+    case 'number_unformatted':
+      $output = $value;
+      break;
   }
 
-  return $output;
+  return array(
+    '#markup' => $output,
+  );
 }
 
 /**
Index: modules/field/modules/text/text.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v
retrieving revision 1.40
diff -u -p -r1.40 text.module
--- modules/field/modules/text/text.module	4 Dec 2009 16:49:46 -0000	1.40
+++ modules/field/modules/text/text.module	8 Dec 2009 23:28:30 -0000
@@ -191,49 +191,12 @@ function text_field_validate($obj_type, 
 function text_field_load($obj_type, $objects, $field, $instances, $langcode, &$items) {
   foreach ($objects as $id => $object) {
     foreach ($items[$id] as $delta => $item) {
-      if (!empty($instances[$id]['settings']['text_processing'])) {
-        // Only process items with a cacheable format, the rest will be
-        // handled by text_field_sanitize().
-        $format_id = $item['format'];
-        if (filter_format_allowcache($format_id)) {
-          $items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format_id, $langcode) : '';
-          if ($field['type'] == 'text_with_summary') {
-            $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format_id, $langcode) : '';
-          }
-        }
-      }
-      else {
-        $items[$id][$delta]['safe'] = check_plain($item['value']);
+      // Only process items with a cacheable format, the rest will be
+      // handled by formatters if needed.
+      if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) {
+        $items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($item, 'value', $instances[$id], $langcode) : '';
         if ($field['type'] == 'text_with_summary') {
-          $items[$id][$delta]['safe_summary'] = check_plain($item['summary']);
-        }
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_field_sanitize().
- *
- * @see text_field_load()
- */
-function text_field_sanitize($obj_type, $object, $field, $instance, $langcode, &$items) {
-  foreach ($items as $delta => $item) {
-    // Only sanitize items which were not already processed inside
-    // text_field_load(), i.e. items with uncacheable text formats, or coming
-    // from a form preview.
-    if (!isset($items[$delta]['safe'])) {
-      if (!empty($instance['settings']['text_processing'])) {
-        $format_id = $item['format'];
-        $items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format_id, $langcode, TRUE) : '';
-        if ($field['type'] == 'text_with_summary') {
-          $items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format_id, $langcode, TRUE) : '';
-        }
-      }
-      else {
-        $items[$delta]['safe'] = check_plain($item['value']);
-        if ($field['type'] == 'text_with_summary') {
-          $items[$delta]['safe_summary'] = check_plain($item['summary']);
+          $items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($item, 'summary', $instances[$id], $langcode) : '';
         }
       }
     }
@@ -286,49 +249,57 @@ function text_field_formatter_info() {
 }
 
 /**
- * Theme function for 'default' text field formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_text_default($variables) {
-  $element = $variables['element'];
-  return $element['#item']['safe'];
-}
+function text_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $item = $items[$delta];
 
-/**
- * Theme function for 'plain' text field formatter.
- */
-function theme_field_formatter_text_plain($variables) {
-  $element = $variables['element'];
-  return strip_tags($element['#item']['safe']);
-}
+  switch ($display['type']) {
+    case 'text_default':
+    case 'text_trimmed':
+      $output = _text_sanitize($item, 'value', $instance, $langcode);
 
-/**
- * Theme function for 'trimmed' text field formatter.
- */
-function theme_field_formatter_text_trimmed($variables) {
-  $element = $variables['element'];
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
-  return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL);
+      if ($display['type'] == 'text_trimemd') {
+        $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL);
+      }
+      break;
+
+    case 'text_summary_or_trimmed':
+      if (!empty($item['summary'])) {
+        $output = _text_sanitize($item, 'summary', $instance, $langcode);
+      }
+      else {
+        $output = _text_sanitize($item, 'value', $instance, $langcode);
+        $size = variable_get('teaser_length_' . $instance['bundle'], 600);
+        $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $size);
+      }
+      break;
+
+    case 'text_plain':
+      $output = strip_tags($item['value']);
+      break;
+  }
+
+  return array(
+    '#markup' => $output,
+  );
 }
 
 /**
- * Theme function for 'summary or trimmed' field formatter for
- * text_with_summary fields. This formatter returns the summary
- * element of the field or, if the summary is empty, the trimmed
- * version of the full element of the field.
+ * @todo
+ *
+ * @param $item
+ * @param $key
+ * @param $instance
+ * @param $langcode
+ *
+ * @return
  */
-function theme_field_formatter_text_summary_or_trimmed($variables) {
-  $element = $variables['element'];
-  $field = field_info_field($element['#field_name']);
-  $instance = field_info_instance($element['#object_type'], $element['#field_name'], $element['#bundle']);
-
-  if (!empty($element['#item']['safe_summary'])) {
-    return $element['#item']['safe_summary'];
-  }
-  else {
-    $size = variable_get('teaser_length_' . $element['#bundle'], 600);
-    return text_summary($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL, $size);
+function _text_sanitize($item, $key, $instance, $langcode) {
+  if (isset($item["safe_$key"])) {
+    return $item["safe_$key"];
   }
+  return $instance['settings']['text_processing'] ? check_markup($item[$key], $item['format'], $langcode, TRUE) : check_plain($item[$key]);
 }
 
 /**
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.5
diff -u -p -r1.5 field.test
--- modules/field/tests/field.test	2 Dec 2009 19:26:22 -0000	1.5
+++ modules/field/tests/field.test	8 Dec 2009 23:28:30 -0000
@@ -892,7 +892,7 @@ class FieldAttachOtherTestCase extends F
     $this->content = $output;
     $this->assertRaw($display, "Multiple formatter: all values are displayed, formatter settings are applied.");
 
-    // Test a formatter that uses hook_field_formatter_prepare_view()..
+    // Test a formatter that uses hook_field_formatter_prepare().
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
     $this->instance['display'] = array(
Index: modules/field/tests/field_test.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.field.inc,v
retrieving revision 1.2
diff -u -p -r1.2 field_test.field.inc
--- modules/field/tests/field_test.field.inc	4 Dec 2009 16:49:46 -0000	1.2
+++ modules/field/tests/field_test.field.inc	8 Dec 2009 23:28:30 -0000
@@ -92,16 +92,6 @@ function field_test_field_validate($obj_
 }
 
 /**
- * Implements hook_field_sanitize().
- */
-function field_test_field_sanitize($obj_type, $object, $field, $instance, $langcode, &$items) {
-  foreach ($items as $delta => $item) {
-    $value = check_plain($item['value']);
-    $items[$delta]['safe'] = $value;
-  }
-}
-
-/**
  * Implements hook_field_is_empty().
  */
 function field_test_field_is_empty($item, $field) {
@@ -226,7 +216,7 @@ function field_test_field_formatter_info
       ),
     ),
     'field_test_needs_additional_data' => array(
-      'label' => t('Tests hook_field_formatter_prepare_view()'),
+      'label' => t('Tests hook_field_formatter_prepare()'),
       'field types' => array('test_field'),
       'settings' => array(
         'test_formatter_setting_additional' => 'dummy test string',
@@ -236,9 +226,9 @@ function field_test_field_formatter_info
 }
 
 /**
- * Implements hook_field_formatter_prepare_view().
+ * Implements hook_field_formatter_prepare().
  */
-function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
+function field_test_field_formatter_prepare($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
   foreach ($items as $id => $item) {
     // To keep the test non-intrusive, only act on the
     // 'field_test_needs_additional_data' formatter.
@@ -254,47 +244,38 @@ function field_test_field_formatter_prep
 }
 
 /**
- * Theme function for 'field_test_default' formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_field_test_default($variables) {
-  $element = $variables['element'];
+function field_test_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $settings = $display['settings'];
 
-  $value = $element['#item']['value'];
-  $settings = $element['#settings'];
-
-  return $settings['test_formatter_setting'] . '|' . $value;
-}
-
-/**
- * Theme function for 'field_test_multiple' formatter.
- */
-function theme_field_formatter_field_test_multiple($variables) {
-  $element = $variables['element'];
-
-  $settings = $element['#settings'];
-
-  $items = array();
-  foreach (element_children($element) as $key) {
-    $items[$key] = $key .':'. $element[$key]['#item']['value'];
+  switch ($display['type']) {
+    case 'field_test_default':
+      $item = $items[$delta];
+      $output = $settings['test_formatter_setting'] . '|' . $item['value'];
+      break;
+
+    case 'field_test_needs_additional_data':
+      $item = $items[$delta];
+      $output = $settings['test_formatter_setting_additional'] . '|' . $item['value'] . '|' . $item['additional_formatter_value'];
+      break;
+
+    case 'field_test_multiple':
+      $array = array();
+      foreach ($items as $delta => $item) {
+        $array[] = $delta .':'. $item['value'];
+      }
+      $output = $settings['test_formatter_setting_multiple'] . '|' . implode('|', $array);
+      break;
   }
-  $output = implode('|', $items);
-  return $settings['test_formatter_setting_multiple'] . '|' . $output;
-}
 
-/**
- * Theme function for 'field_test_needs_additional_data' formatter.
- */
-function theme_field_formatter_field_test_needs_additional_data($variables) {
-  $element = $variables['element'];
-  $value = $element['#item']['value'];
-  $additional = $element['#item']['additional_formatter_value'];
-  $settings = $element['#settings'];
-
-  return $settings['test_formatter_setting_additional'] . '|' . $value . '|' . $additional;
+  return array(
+    '#markup' => $output,
+  );
 }
 
 /**
- * Sample 'default vale' callback.
+ * Sample 'default value' callback.
  */
 function field_test_default_value($obj_type, $object, $field, $instance) {
   return array(array('value' => 99));
Index: modules/file/file.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/file/file.field.inc,v
retrieving revision 1.11
diff -u -p -r1.11 file.field.inc
--- modules/file/file.field.inc	4 Dec 2009 16:49:46 -0000	1.11
+++ modules/file/file.field.inc	8 Dec 2009 23:28:30 -0000
@@ -844,33 +844,47 @@ function theme_file_upload_help($variabl
 }
 
 /**
- * Theme function for 'default' file field formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_file_default($variables) {
-  $element = $variables['element'];
-  return theme('file_link', array('file' => (object) $element['#item']));
-}
+function file_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $item = $items[$delta];
 
-/**
- * Theme function for 'url_plain' file field formatter.
- */
-function theme_field_formatter_file_url_plain($variables) {
-  $element = $variables['element'];
-  return empty($element['#item']['uri']) ? '' : file_create_url($element['#item']['uri']);
+  switch ($display['type']) {
+    case 'file_default':
+      $result = array(
+        '#theme' => 'file_link',
+        '#file' => (object) $item,
+      );
+      break;
+
+    case 'file_url_plain':
+      $result = array(
+        '#markup' => empty($item['uri']) ? '' : file_create_url($item['uri']),
+      );
+      break;
+
+    case 'file_table':
+      // Multiple formatter, dealing with all $items.
+      $result = array(
+        '#theme' => 'file_formatter_table',
+        '#items' => $items,
+      );
+      break;
+  }
+
+  return $result;
 }
 
 /**
  * Theme function for the 'table' formatter.
  */
-function theme_field_formatter_file_table($variables) {
-  $element = $variables['element'];
-
+function theme_file_formatter_table($variables) {
   $header = array(t('Attachment'), t('Size'));
   $rows = array();
-  foreach (element_children($element) as $key) {
+  foreach ($variables['items'] as $delta => $item) {
     $rows[] = array(
-      theme('file_link', array('file' => (object) $element[$key]['#item'])),
-      format_size($element[$key]['#item']['filesize']),
+      theme('file_link', array('file' => (object) $item)),
+      format_size($item['filesize']),
     );
   }
 
Index: modules/file/file.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/file/file.module,v
retrieving revision 1.13
diff -u -p -r1.13 file.module
--- modules/file/file.module	4 Dec 2009 16:49:46 -0000	1.13
+++ modules/file/file.module	8 Dec 2009 23:28:30 -0000
@@ -81,6 +81,9 @@ function file_theme() {
     'file_widget_multiple' => array(
       'render element' => 'element',
     ),
+    'file_formatter_table' => array(
+      'variables' => array('items' => NULL),
+    ),
     'file_upload_help' => array(
       'variables' => array('description' => NULL, 'upload_validators' => NULL),
     ),
Index: modules/image/image.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.field.inc,v
retrieving revision 1.5
diff -u -p -r1.5 image.field.inc
--- modules/image/image.field.inc	4 Dec 2009 16:49:46 -0000	1.5
+++ modules/image/image.field.inc	8 Dec 2009 23:28:30 -0000
@@ -433,17 +433,14 @@ function image_field_formatter_info() {
     $formatters['image__' . $style['name']] = array(
       'label' => t('Image "@style"', array('@style' => $style['name'])),
       'field types' => array('image'),
-      'theme' => array('function' => 'theme_field_formatter_image'),
     );
     $formatters['image_link_content__' . $style['name']] = array(
       'label' => t('Image "@style" linked to content', array('@style' => $style['name'])),
       'field types' => array('image'),
-      'theme' => array('function' => 'theme_field_formatter_image_link_content'),
     );
     $formatters['image_link_file__' . $style['name']] = array(
       'label' => t('Image "@style" linked to file', array('@style' => $style['name'])),
       'field types' => array('image'),
-      'theme' => array('function' => 'theme_field_formatter_image_link_file'),
     );
   }
 
@@ -451,40 +448,57 @@ function image_field_formatter_info() {
 }
 
 /**
- * Theme function for 'image' image field formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_image($variables) {
-  $element = $variables['element'];
-  $image = array(
-    'path' => $element['#item']['uri'],
-    'alt' => $element['#item']['alt'],
-    'title' => $element['#item']['title'],
-  );
+function image_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $item = $items[$delta];
+  $image_style = '';
+  $path = '';
 
   // Check if this requires a particular image style.
   $matches = array();
-  if (preg_match('/__([a-z0-9_]+)/', $element['#formatter'], $matches)) {
-    $image['style_name'] = $matches[1];
-    return theme('image_style', $image);
+  if (preg_match('/__([a-z0-9_]+)/', $display['type'], $matches)) {
+    $image_style = $matches[1];
   }
-  else {
-    return theme('image', $image);
+
+  if (strpos($display['type'], 'image_link_content') === 0) {
+    list($id) = entity_extract_ids($obj_type, $object);
+    $path = $obj_type . '/' . $id;
+  }
+  elseif (strpos($display['type'], 'image_link_file') === 0) {
+    $path = file_create_url($item['uri']);
   }
-}
 
-/**
- * Theme function for 'image_link_content' image field formatter.
- */
-function theme_field_formatter_image_link_content($variables) {
-  $element = $variables['element'];
-  list($id, $vid, $bundle) = entity_extract_ids($element['#object_type'], $element['#object']);
-  return l(theme('field_formatter_image', $variables), $element['#object_type'] . '/' . $id, array('html' => TRUE));
+  return array(
+    '#theme' => 'image_formatter',
+    '#item' => $item,
+    '#image_style' => $image_style,
+    '#path' => $path,
+  );
 }
 
 /**
- * Theme function for 'image_link_file' image field formatter.
+ * Theme function for image field formatters.
  */
-function theme_field_formatter_image_link_file($variables) {
-  $element = $variables['element'];
-  return l(theme('field_formatter_image', $variables), file_create_url($element['#item']['uri']), array('html' => TRUE));
-}
+function theme_image_formatter($variables) {
+  $item = $variables['item'];
+  $image = array(
+    'path' => $item['uri'],
+    'alt' => $item['alt'],
+    'title' => $item['title'],
+  );
+
+  if ($variables['image_style']) {
+    $image['style_name'] = $variables['image_style'];
+    $output = theme('image_style', $image);
+  }
+  else {
+    $output = theme('image', $image);
+  }
+
+  if ($variables['path']) {
+    $output = l($output, $variables['path'], array('html' => TRUE));
+  }
+
+  return $output;
+}
\ No newline at end of file
Index: modules/image/image.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.module,v
retrieving revision 1.29
diff -u -p -r1.29 image.module
--- modules/image/image.module	4 Dec 2009 16:49:46 -0000	1.29
+++ modules/image/image.module	8 Dec 2009 23:28:30 -0000
@@ -212,14 +212,8 @@ function image_theme() {
     'image_widget' => array(
       'render element' => 'element',
     ),
-    'field_formatter_image' => array(
-      'render element' => 'element',
-    ),
-    'field_formatter_image_link_content' => array(
-      'render element' => 'element',
-    ),
-    'field_formatter_image_link_file' => array(
-      'render element' => 'element',
+    'image_formatter' => array(
+      'variables' => array('item' => NULL, 'path' => NULL, 'image_style' => NULL),
     ),
   );
 }
Index: modules/locale/locale.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.field.inc,v
retrieving revision 1.4
diff -u -p -r1.4 locale.field.inc
--- modules/locale/locale.field.inc	2 Dec 2009 19:26:22 -0000	1.4
+++ modules/locale/locale.field.inc	8 Dec 2009 23:28:30 -0000
@@ -52,7 +52,7 @@ function locale_field_fallback_view(&$ou
 
     // If the items array is empty then we have a missing field translation.
     // @todo: Verify this assumption.
-    if (isset($output[$field_name]) && empty($output[$field_name]['items'])) {
+    if (isset($output[$field_name]) && count(element_children($output[$field_name])) == 0) {
       if (!isset($fallback_candidates)) {
         require_once DRUPAL_ROOT . '/includes/language.inc';
         $fallback_candidates = language_fallback_get_candidates();
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1180
diff -u -p -r1.1180 node.module
--- modules/node/node.module	7 Dec 2009 03:42:27 -0000	1.1180
+++ modules/node/node.module	8 Dec 2009 23:28:30 -0000
@@ -2203,7 +2203,11 @@ function node_page_default() {
 function node_page_view($node) {
   $return = node_show($node);
   if (isset($return['nodes'][$node->nid]['title'])) {
-    drupal_set_title($return['nodes'][$node->nid]['title']['items'][0]['#item']['value']);
+    // Get the language that was determined by language fallback logic during the
+    // field_attach_display() workflow.
+    // @todo That logic should be made available separately.
+    $langcode = $return['nodes'][$node->nid]['title']['#language'];
+    drupal_set_title($node->title[$langcode][0]['value']);
   }
   // Set the node path as the canonical URL to prevent duplicate content.
   drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url('node/' . $node->nid)), TRUE);
Index: modules/rdf/rdf.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/rdf/rdf.module,v
retrieving revision 1.11
diff -u -p -r1.11 rdf.module
--- modules/rdf/rdf.module	6 Dec 2009 18:35:14 -0000	1.11
+++ modules/rdf/rdf.module	8 Dec 2009 23:37:27 -0000
@@ -427,12 +427,11 @@ function rdf_preprocess_field(&$variable
   $instance = $variables['instance'];
   $mapping = rdf_mapping_load($entity_type, $instance['bundle']);
   $field_name = $instance['field_name'];
+  $items = $variables['element']['#items'];
 
   if (!empty($mapping) && !empty($mapping[$field_name])) {
-    foreach ($variables['items'] as $delta => $item) {
-      if (!empty($item['#item'])) {
-        $variables['item_attributes_array'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item['#item']);
-      }
+    foreach ($items as $delta => $item) {
+      $variables['item_attributes_array'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
     }
   }
 }
@@ -554,15 +553,29 @@ function rdf_preprocess_comment(&$variab
 }
 
 /**
- * Implements MODULE_preprocess_HOOK().
+ * Implements hook_field_attach_view_alter().
  */
-function rdf_preprocess_field_formatter_taxonomy_term_link(&$variables) {
-  $term = $variables['element']['#item']['taxonomy_term'];
-  if (!empty($term->rdf_mapping['rdftype'])) {
-    $variables['link_options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
-  }
-  if (!empty($term->rdf_mapping['name']['predicates'])) {
-    $variables['link_options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
+function rdf_field_attach_view_alter(&$output, $context) {
+  // Append term mappings on displayed taxonomy links.
+  foreach (element_children($output) as $field_name) {
+    $element = &$output[$field_name];
+    if ($element['#field_type'] == 'taxonomy_term' && $element['#formatter'] == 'taxonomy_term_link') {
+      foreach ($element['#items'] as $delta => $item) {
+        // @todo Exceptions in forum.test without this check. Strange sequence
+        // through menu_execute_active_handler / comment_reply / node_build that
+        // skips 'prepare_view'
+        if (!isset($item['taxonomy_term'])) {
+          $item['taxonomy_term'] = taxonomy_term_load($item['tid']);
+        }
+        $term = $item['taxonomy_term'];
+        if (!empty($term->rdf_mapping['rdftype'])) {
+          $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
+        }
+        if (!empty($term->rdf_mapping['name']['predicates'])) {
+          $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
+        }
+      }
+    }
   }
 }
 
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.545
diff -u -p -r1.545 taxonomy.module
--- modules/taxonomy/taxonomy.module	4 Dec 2009 16:49:47 -0000	1.545
+++ modules/taxonomy/taxonomy.module	8 Dec 2009 23:37:29 -0000
@@ -1101,20 +1101,36 @@ function taxonomy_field_formatter_info()
 }
 
 /**
- * Theme function for 'link' term field formatter.
+ * Implements hook_field_formatter().
  */
-function theme_field_formatter_taxonomy_term_link($variables) {
-  $term = $variables['element']['#item']['taxonomy_term'];
-  $attributes = empty($variables['link_options']) ? array() : $variables['link_options'];
-  return l($term->name, 'taxonomy/term/' . $term->tid, $attributes);
-}
+function taxonomy_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+  $item = $items[$delta];
 
-/**
- * Theme function for 'plain' term field formatter.
- */
-function theme_field_formatter_taxonomy_term_plain($variables) {
-  $term = $variables['element']['#item']['taxonomy_term'];
-  return check_plain($term->name);
+  switch ($display['type']) {
+    case 'taxonomy_term_link':
+      // @todo Exceptions in forum.test without this check. Strange sequence
+      // through menu_execute_active_handler / comment_reply / node_build that
+      // skips 'prepare_view'
+      if (!isset($item['taxonomy_term'])) {
+        $item['taxonomy_term'] = taxonomy_term_load($item['tid']);
+      }
+      $term = $item['taxonomy_term'];
+      $result = array(
+        '#type' => 'link',
+        '#title' => $term->name,
+        '#href' => 'taxonomy/term/' . $term->tid,
+      );
+      break;
+
+    case 'taxonomy_term_plain':
+      $term = $item['taxonomy_term'];
+      $result = array(
+        '#markup' => check_plain($term->name),
+      );
+      break;
+  }
+
+  return $result;
 }
 
 /**
@@ -1139,12 +1155,12 @@ function taxonomy_allowed_values($field)
 }
 
 /**
- * Implements hook_field_load().
+ * Implements hook_field_formatter_prepare().
  *
  * This preloads all taxonomy terms for multiple loaded objects at once and
  * unsets values for invalid terms that do not exist.
  */
-function taxonomy_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $age) {
+function taxonomy_field_formatter_prepare($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
   $tids = array();
 
   // Collect every possible term attached to any of the fieldable entities.
