- Patch #657828 by yched: make hook_field_formatter() act on all field values.

merge-requests/26/head
Dries Buytaert 2009-12-12 20:16:03 +00:00
parent d0355f72ca
commit 6a13eb22fc
12 changed files with 192 additions and 220 deletions

View File

@ -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'],
);
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_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) {
$array[] = $delta .':'. $item['value'];
$element[$delta] = array('#markup' => $settings['some_setting'] . $item['value']);
}
$result = array(
'#markup' => implode('|', $array),
break;
case 'sample_field_formatter_themeable':
// More elaborate formatters can defer to a theme function for easier
// customization.
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'mymodule_theme_sample_field_formatter_themeable',
'#data' => $item['value'],
'#some_setting' => $settings['some_setting'],
);
}
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;
}
/**

View File

@ -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

View File

@ -90,14 +90,23 @@ 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(
// Calling the formatter function through module_invoke() can have a
// performance impact on pages with many fields and values.
$function = $display['module'] . '_field_formatter';
if (function_exists($function)) {
$elements = $function($obj_type, $object, $field, $instance, $langcode, $items, $display);
}
if ($elements) {
$info = array(
'#theme' => 'field',
'#weight' => $display['weight'],
'#title' => t($instance['label']),
@ -111,24 +120,12 @@ function field_default_view($obj_type, $object, $field, $instance, $langcode, $i
'#bundle' => $bundle,
'#object' => $object,
'#items' => $items,
'#formatter' => $display['type'],
'#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;
$addition[$field['field_name']] = array_merge($info, $elements);
}
}
else {
$element[0] = $formatter_function($obj_type, $object, $field, $instance, $langcode, $display, $items, 0);
}
$addition = array($field['field_name'] => $element);
}
return $addition;
}

View File

@ -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().
*

View File

@ -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];
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;
}

View File

@ -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']);
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($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
$suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
$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;
}
/**

View File

@ -251,19 +251,23 @@ 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':
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':
foreach ($items as $delta => $item) {
if (!empty($item['summary'])) {
$output = _text_sanitize($instance, $langcode, $item, 'summary');
}
@ -272,16 +276,18 @@ function text_field_formatter($object_type, $object, $field, $instance, $langcod
$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;
}
/**

View File

@ -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;
}
/**

View File

@ -38,8 +38,7 @@
* @see template_preprocess_field()
*/
?>
<?php if ($items) : ?>
<div class="field <?php print $classes; ?> clearfix"<?php print $attributes; ?>>
<div class="field <?php print $classes; ?> clearfix"<?php print $attributes; ?>>
<?php if (!$label_hidden) : ?>
<div class="field-label"<?php print $title_attributes; ?>><?php print $label ?>:&nbsp;</div>
<?php endif; ?>
@ -48,5 +47,4 @@
<div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>

View File

@ -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(
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;
}
/**

View File

@ -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(
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' => $image_style,
'#path' => $path,
'#image_style' => isset($image_style) ? $image_style : '',
'#path' => isset($path) ? $path : '',
);
}
return $element;
}
/**

View File

@ -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,11 +1098,12 @@ 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':
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.
@ -1116,22 +1111,25 @@ function taxonomy_field_formatter($object_type, $object, $field, $instance, $lan
$item['taxonomy_term'] = taxonomy_term_load($item['tid']);
}
$term = $item['taxonomy_term'];
$result = array(
$element[$delta] = array(
'#type' => 'link',
'#title' => $term->name,
'#href' => 'taxonomy/term/' . $term->tid,
);
}
break;
case 'taxonomy_term_plain':
foreach ($items as $delta => $item) {
$term = $item['taxonomy_term'];
$result = array(
$element[$delta] = array(
'#markup' => check_plain($term->name),
);
}
break;
}
return $result;
return $element;
}
/**