diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 4e1481a8634..af76ecf6c11 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -711,30 +711,16 @@ function hook_field_widget_error($element, $error) { * - settings: An array whose keys are the names of the settings available * for the formatter type, and whose values are the default values for * those settings. - * - behaviors: (optional) An array describing behaviors of the formatter. - * - multiple values: - * FIELD_BEHAVIOR_DEFAULT (default) if the formatter displays one single - * 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 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( 'text_default' => array( 'label' => t('Default'), 'field types' => array('text', 'text_long', 'text_with_summary'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), 'text_plain' => array( 'label' => t('Plain text'), 'field types' => array('text', 'text_long', 'text_with_summary'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), // The text_trimmed formatter displays the trimmed version of the @@ -745,9 +731,6 @@ function hook_field_formatter_info() { 'text_trimmed' => array( 'label' => t('Trimmed'), 'field types' => array('text', 'text_long', 'text_with_summary'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), // The 'summary or trimmed' field formatter for text_with_summary @@ -757,9 +740,6 @@ function hook_field_formatter_info() { 'text_summary_or_trimmed' => array( 'label' => t('Summary or trimmed'), 'field types' => array('text_with_summary'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), ); } @@ -827,46 +807,60 @@ function hook_field_formatter_prepare_view($obj_type, $objects, $field, $instanc * The field instance. * @param $langcode * The language associated to $items. - * @param $display - * The display settings to use, as found in the 'display' entry of instance - * definitions. * @param $items * Array of values for this field. - * @param $delta + * @param $display + * The display settings to use, as found in the 'display' entry of instance + * definitions. The array notably contains the following keys and values; + * - type: The name of the formatter to use. + * - settings: The array of formatter settings. * * @return + * A renderable array for the $items, as an array of child elements keyed + * by numeric indexes starting from 0. */ -function hook_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) { +function hook_field_formatter($obj_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); $settings = $display['settings']; switch ($display['type']) { - case 'field_test_default': - // Sample code for a 'single' formatter, displaying one single field - // value (the hook_field_formatter_info() entry uses - // 'multiple values' = FIELD_BEHAVIOR_DEFAULT). - $item = $items[$delta]; - $result = array( - '#markup' => $item['value'], - ); + case 'sample_field_formatter_simple': + // Common case: each value is displayed individually in a sub-element + // keyed by delta. The field.tpl.php template specifies the markup + // wrapping each value. + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => $settings['some_setting'] . $item['value']); + } break; - case 'field_test_multiple': - // Sample code for a 'multiple' formatter, displaying all the field - // values (the hook_field_formatter_info() entry uses - // 'multiple values' = FIELD_BEHAVIOR_CUSTOM). - $array = array(); + case 'sample_field_formatter_themeable': + // More elaborate formatters can defer to a theme function for easier + // customization. foreach ($items as $delta => $item) { - $array[] = $delta .':'. $item['value']; + $element[$delta] = array( + '#theme' => 'mymodule_theme_sample_field_formatter_themeable', + '#data' => $item['value'], + '#some_setting' => $settings['some_setting'], + ); } - $result = array( - '#markup' => implode('|', $array), + break; + + case 'sample_field_formatter_combined': + // Some formatters might need to display all values within a single piece + // of markup. + $rows = array(); + foreach ($items as $delta => $item) { + $rows[] = array($delta, $item['value']); + } + $element[0] = array( + '#theme' => 'table', + '#header' => array(t('Delta'), t('Value')), + '#rows' => $rows, ); break; } - return array( - '#markup' => $output, - ); + return $element; } /** diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index 7daca8468fc..1b55180cdb1 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -1134,15 +1134,7 @@ function field_attach_prepare_view($obj_type, $objects, $build_mode = 'full') { * '#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). - * ), - * // ... + * // hook_field_formatter(). * ), * ); * @endcode diff --git a/modules/field/field.default.inc b/modules/field/field.default.inc index b86f8b222ad..7ab203d1455 100644 --- a/modules/field/field.default.inc +++ b/modules/field/field.default.inc @@ -90,44 +90,41 @@ function field_default_view($obj_type, $object, $field, $instance, $langcode, $i list($id, $vid, $bundle) = entity_extract_ids($obj_type, $object); $addition = array(); - $display = $instance['display'][$build_mode]; + $display = $instance['display'][$build_mode]; if ($display['type'] !== 'hidden') { + // We never want to index fields labels. if ($build_mode == 'search_index') { $display['label'] = 'hidden'; } - $element = array( - '#theme' => 'field', - '#weight' => $display['weight'], - '#title' => t($instance['label']), - '#access' => field_access('view', $field, $obj_type, $object), - '#label_display' => $display['label'], - '#build_mode' => $build_mode, - '#language' => $langcode, - '#field_name' => $field['field_name'], - '#field_type' => $field['type'], - '#object_type' => $obj_type, - '#bundle' => $bundle, - '#object' => $object, - '#items' => $items, - '#formatter' => $display['type'], - ); - // Calling the formatter function through module_invoke() can have a // performance impact on pages with many fields and values. - $formatter_function = $display['module'] . '_field_formatter'; - if (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT) { - foreach ($items as $delta => $item) { - $element[$delta] = $formatter_function($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta); - $element[$delta]['#weight'] = $delta; - } - } - else { - $element[0] = $formatter_function($obj_type, $object, $field, $instance, $langcode, $display, $items, 0); + $function = $display['module'] . '_field_formatter'; + if (function_exists($function)) { + $elements = $function($obj_type, $object, $field, $instance, $langcode, $items, $display); } - $addition = array($field['field_name'] => $element); + if ($elements) { + $info = array( + '#theme' => 'field', + '#weight' => $display['weight'], + '#title' => t($instance['label']), + '#access' => field_access('view', $field, $obj_type, $object), + '#label_display' => $display['label'], + '#build_mode' => $build_mode, + '#language' => $langcode, + '#field_name' => $field['field_name'], + '#field_type' => $field['type'], + '#object_type' => $obj_type, + '#bundle' => $bundle, + '#object' => $object, + '#items' => $items, + '#formatter' => $display['type'] + ); + + $addition[$field['field_name']] = array_merge($info, $elements); + } } return $addition; diff --git a/modules/field/field.info.inc b/modules/field/field.info.inc index 13d5030f710..e4df3a391c6 100644 --- a/modules/field/field.info.inc +++ b/modules/field/field.info.inc @@ -326,25 +326,6 @@ function field_behaviors_widget($op, $instance) { return isset($info['behaviors'][$op]) ? $info['behaviors'][$op] : FIELD_BEHAVIOR_DEFAULT; } -/** - * Determines the behavior of a formatter with respect to an operation. - * - * @param $op - * The name of the operation. Currently supported: 'multiple values'. - * @param $display - * The $instance['display'][$build_mode] array. - * - * @return - * One of these values: - * - FIELD_BEHAVIOR_NONE: Do nothing for this operation. - * - FIELD_BEHAVIOR_CUSTOM: Use the formatter's callback function. - * - FIELD_BEHAVIOR_DEFAULT: Use field module default behavior. - */ -function field_behaviors_formatter($op, $display) { - $info = field_info_formatter_types($display['type']); - return isset($info['behaviors'][$op]) ? $info['behaviors'][$op] : FIELD_BEHAVIOR_DEFAULT; -} - /** * Returns information about field types from hook_field_info(). * diff --git a/modules/field/modules/list/list.module b/modules/field/modules/list/list.module index b52dfd40b12..0b8496f44e6 100644 --- a/modules/field/modules/list/list.module +++ b/modules/field/modules/list/list.module @@ -300,27 +300,30 @@ function list_field_formatter_info() { /** * Implements hook_field_formatter(). */ -function list_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $value = $items[$delta]['value']; +function list_field_formatter($object_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); 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; + foreach ($items as $delta => $item) { + if (isset($allowed_values[$item['value']])) { + $output = $allowed_values[$item['value']]; + } + else { + // If no match was found in allowed values, fall back to the key. + $output = $value; + } + $element[$delta] = array('#markup' => $output); } break; case 'list_key': - $output = $value; + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => $item['value']); + } break; } - return array( - '#markup' => $output, - ); + return $element; } diff --git a/modules/field/modules/number/number.module b/modules/field/modules/number/number.module index 710d82e5487..5c03db5a59c 100644 --- a/modules/field/modules/number/number.module +++ b/modules/field/modules/number/number.module @@ -242,34 +242,34 @@ function number_field_formatter_info() { /** * Implements hook_field_formatter(). */ -function number_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $value = $items[$delta]['value']; +function number_field_formatter($object_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); + $settings = $display['settings']; 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; + foreach ($items as $delta => $item) { + $output = number_format($item['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($item['value'], $prefixes[0], $prefixes[1]) : $prefixes[0]; + $suffix = (count($suffixes) > 1) ? format_plural($item['value'], $suffixes[0], $suffixes[1]) : $suffixes[0]; + $output = $prefix . $output . $suffix; + } + $element[$delta] = array('#markup' => $output); } break; case 'number_unformatted': - $output = $value; + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => $item['value']); + } break; } - return array( - '#markup' => $output, - ); + return $element; } /** diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module index 97b71571f28..06609fcd96b 100644 --- a/modules/field/modules/text/text.module +++ b/modules/field/modules/text/text.module @@ -251,37 +251,43 @@ function text_field_formatter_info() { /** * Implements hook_field_formatter(). */ -function text_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $item = $items[$delta]; +function text_field_formatter($object_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); switch ($display['type']) { case 'text_default': case 'text_trimmed': - $output = _text_sanitize($instance, $langcode, $item, 'value'); - if ($display['type'] == 'text_trimemd') { - $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL); + foreach ($items as $delta => $item) { + $output = _text_sanitize($instance, $langcode, $item, 'value'); + if ($display['type'] == 'text_trimemd') { + $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL); + } + $element[$delta] = array('#markup' => $output); } break; case 'text_summary_or_trimmed': - if (!empty($item['summary'])) { - $output = _text_sanitize($instance, $langcode, $item, 'summary'); - } - else { - $output = _text_sanitize($instance, $langcode, $item, 'value'); - $size = variable_get('teaser_length_' . $instance['bundle'], 600); - $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $size); + foreach ($items as $delta => $item) { + if (!empty($item['summary'])) { + $output = _text_sanitize($instance, $langcode, $item, 'summary'); + } + else { + $output = _text_sanitize($instance, $langcode, $item, 'value'); + $size = variable_get('teaser_length_' . $instance['bundle'], 600); + $output = text_summary($output, $instance['settings']['text_processing'] ? $item['format'] : NULL, $size); + } + $element[$delta] = array('#markup' => $output); } break; case 'text_plain': - $output = strip_tags($item['value']); + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => strip_tags($item['value'])); + } break; } - return array( - '#markup' => $output, - ); + return $element; } /** diff --git a/modules/field/tests/field_test.field.inc b/modules/field/tests/field_test.field.inc index 5097a3357a9..89def7e1068 100644 --- a/modules/field/tests/field_test.field.inc +++ b/modules/field/tests/field_test.field.inc @@ -211,9 +211,6 @@ function field_test_field_formatter_info() { 'settings' => array( 'test_formatter_setting_multiple' => 'dummy test string', ), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - ), ), 'field_test_needs_additional_data' => array( 'label' => t('Tests hook_field_formatter_prepare_view()'), @@ -246,32 +243,33 @@ function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $i /** * Implements hook_field_formatter(). */ -function field_test_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) { +function field_test_field_formatter($object_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); $settings = $display['settings']; switch ($display['type']) { case 'field_test_default': - $item = $items[$delta]; - $output = $settings['test_formatter_setting'] . '|' . $item['value']; + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => $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']; + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => $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']; + $array[] = $delta . ':' . $item['value']; } - $output = $settings['test_formatter_setting_multiple'] . '|' . implode('|', $array); + $element[0] = array('#markup' => $settings['test_formatter_setting_multiple'] . '|' . implode('|', $array)); break; } - return array( - '#markup' => $output, - ); + return $element; } /** diff --git a/modules/field/theme/field.tpl.php b/modules/field/theme/field.tpl.php index a35fd761583..1c8be235da2 100644 --- a/modules/field/theme/field.tpl.php +++ b/modules/field/theme/field.tpl.php @@ -38,15 +38,13 @@ * @see template_preprocess_field() */ ?> - -
> - -
>
- -
> - $item) : ?> -
>
- -
+
> + +
>
+ +
> + $item) : ?> +
>
+
- +
diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc index 7470d3d1e61..456598606e2 100644 --- a/modules/file/file.field.inc +++ b/modules/file/file.field.inc @@ -373,9 +373,6 @@ function file_field_formatter_info() { 'file_table' => array( 'label' => t('Table of files'), 'field types' => array('file'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - ), ), 'file_url_plain' => array( 'label' => t('URL to file'), @@ -846,33 +843,35 @@ function theme_file_upload_help($variables) { /** * Implements hook_field_formatter(). */ -function file_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $item = $items[$delta]; +function file_field_formatter($obj_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); switch ($display['type']) { case 'file_default': - $result = array( - '#theme' => 'file_link', - '#file' => (object) $item, - ); + foreach ($items as $delta => $item) { + $element[$delta] = array( + '#theme' => 'file_link', + '#file' => (object) $item, + ); + } break; case 'file_url_plain': - $result = array( - '#markup' => empty($item['uri']) ? '' : file_create_url($item['uri']), - ); + foreach ($items as $delta => $item) { + $element[$delta] = array('#markup' => empty($item['uri']) ? '' : file_create_url($item['uri'])); + } break; case 'file_table': - // Multiple formatter, dealing with all $items. - $result = array( + // Display all values in a single element.. + $element[0] = array( '#theme' => 'file_formatter_table', '#items' => $items, ); break; } - return $result; + return $element; } /** diff --git a/modules/image/image.field.inc b/modules/image/image.field.inc index 3ab6f709029..f52193cb99a 100644 --- a/modules/image/image.field.inc +++ b/modules/image/image.field.inc @@ -450,31 +450,37 @@ function image_field_formatter_info() { /** * Implements hook_field_formatter(). */ -function image_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $item = $items[$delta]; - $image_style = ''; - $path = ''; +function image_field_formatter($obj_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); - // Check if this requires a particular image style. + // Check if the formatter involves a particular image style. $matches = array(); if (preg_match('/__([a-z0-9_]+)/', $display['type'], $matches)) { $image_style = $matches[1]; } + // Check if the formatter involves a link. 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']); + $link_file = TRUE; } - return array( - '#theme' => 'image_formatter', - '#item' => $item, - '#image_style' => $image_style, - '#path' => $path, - ); + foreach ($items as $delta => $item) { + if (isset($link_file)) { + $path = file_create_url($item['uri']); + } + $element[$delta] = array( + '#theme' => 'image_formatter', + '#item' => $item, + '#image_style' => isset($image_style) ? $image_style : '', + '#path' => isset($path) ? $path : '', + ); + } + + return $element; } /** diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module index 1eb295d3902..a15e7b4ba37 100644 --- a/modules/taxonomy/taxonomy.module +++ b/modules/taxonomy/taxonomy.module @@ -1087,16 +1087,10 @@ function taxonomy_field_formatter_info() { 'taxonomy_term_link' => array( 'label' => t('Link'), 'field types' => array('taxonomy_term'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), 'taxonomy_term_plain' => array( 'label' => t('Plain text'), 'field types' => array('taxonomy_term'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), ), ); } @@ -1104,34 +1098,38 @@ function taxonomy_field_formatter_info() { /** * Implements hook_field_formatter(). */ -function taxonomy_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) { - $item = $items[$delta]; +function taxonomy_field_formatter($object_type, $object, $field, $instance, $langcode, $items, $display) { + $element = array(); switch ($display['type']) { case 'taxonomy_term_link': - // @todo Remove this when "node_build() does not call - // field_attach_prepare_view()" bug is fixed. - // See http://drupal.org/node/493314. - if (!isset($item['taxonomy_term'])) { - $item['taxonomy_term'] = taxonomy_term_load($item['tid']); + foreach ($items as $delta => $item) { + // @todo Remove this when "node_build() does not call + // field_attach_prepare_view()" bug is fixed. + // See http://drupal.org/node/493314. + if (!isset($item['taxonomy_term'])) { + $item['taxonomy_term'] = taxonomy_term_load($item['tid']); + } + $term = $item['taxonomy_term']; + $element[$delta] = array( + '#type' => 'link', + '#title' => $term->name, + '#href' => 'taxonomy/term/' . $term->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), - ); + foreach ($items as $delta => $item) { + $term = $item['taxonomy_term']; + $element[$delta] = array( + '#markup' => check_plain($term->name), + ); + } break; } - return $result; + return $element; } /**