summaryrefslogtreecommitdiff
path: root/modules/field
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-12-11 16:49:40 +0000
committerDries Buytaert <dries@buytaert.net>2009-12-11 16:49:40 +0000
commitef2c240086e5014db6bdd37c43a75f045bcd5504 (patch)
treea5cfc85ab30d66cc5326085dcec570467be43c72 /modules/field
parent47182dfb1f65d2a107037a1386d85e6997afcd04 (diff)
downloadbrdo-ef2c240086e5014db6bdd37c43a75f045bcd5504.tar.gz
brdo-ef2c240086e5014db6bdd37c43a75f045bcd5504.tar.bz2
- Patch #652834 by yched, effulgentsia: changed Field formatters as render arrays to increase performance (and to clean-up the code).
Diffstat (limited to 'modules/field')
-rw-r--r--modules/field/field.api.php149
-rw-r--r--modules/field/field.attach.inc88
-rw-r--r--modules/field/field.default.inc71
-rw-r--r--modules/field/field.module34
-rw-r--r--modules/field/modules/list/list.module37
-rw-r--r--modules/field/modules/number/number.module68
-rw-r--r--modules/field/modules/text/text.module134
-rw-r--r--modules/field/tests/field.test4
-rw-r--r--modules/field/tests/field_test.field.inc75
9 files changed, 278 insertions, 382 deletions
diff --git a/modules/field/field.api.php b/modules/field/field.api.php
index ea0d70b2a..4e1481a86 100644
--- a/modules/field/field.api.php
+++ b/modules/field/field.api.php
@@ -688,30 +688,14 @@ function hook_field_widget_error($element, $error) {
/**
* Expose Field API formatter types.
*
- * 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().
+ * Formatters handle the display of field values. Formatter hooks are typically
+ * called by the Field Attach API field_attach_prepare_view() and
+ * field_attach_view() functions.
*
* @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_view().
*
* @return
* An array describing the formatter types implemented by the module.
@@ -733,8 +717,8 @@ function hook_field_widget_error($element, $error) {
* 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,61 +783,7 @@ function hook_field_formatter_info_alter(&$info) {
}
/**
- * 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.
- */
-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 $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.
- */
-function theme_field_formatter_FORMATTER_MULTIPLE($variables) {
- $element = $variables['element'];
-
- $items = array();
- foreach (element_children($element) as $key) {
- $items[$key] = $key .':'. $element[$key]['#item']['value'];
- }
- $output = implode('|', $items);
- return $output;
-}
-
-/**
- * Allow formatters to load information for multiple objects.
+ * Allow formatters to load information for field values being displayed.
*
* This should be used when a formatter needs to load additional information
* from the database in order to render a field, for example a reference field
@@ -866,18 +796,77 @@ function theme_field_formatter_FORMATTER_MULTIPLE($variables) {
* @param $field
* The field structure for the operation.
* @param $instances
- * Array of instance structures for $field for each object, keyed by object id.
+ * Array of instance structures for $field for each object, keyed by object
+ * id.
* @param $langcode
* The language the field values are to be shown in. If no language is
* provided the current language is used.
* @param $items
* Array of field values for the objects, keyed by object id.
+ * @param $displays
+ * Array of display settings to use for each object display, keyed by object
+ * id.
* @return
* 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_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
+
+}
+
+/**
+ * Builds a renderable array for a field value.
+ *
+ * @param $obj_type
+ * The type of $object.
+ * @param $object
+ * The object being displayed.
+ * @param $field
+ * The field structure.
+ * @param $instance
+ * 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
+ *
+ * @return
+ */
+function hook_field_formatter($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+ $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();
+ foreach ($items as $delta => $item) {
+ $array[] = $delta .':'. $item['value'];
+ }
+ $result = array(
+ '#markup' => implode('|', $array),
+ );
+ break;
+ }
+ return array(
+ '#markup' => $output,
+ );
}
/**
diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc
index 01b46b13e..7daca8468 100644
--- a/modules/field/field.attach.inc
+++ b/modules/field/field.attach.inc
@@ -1113,10 +1113,39 @@ function field_attach_prepare_view($obj_type, $objects, $build_mode = 'full') {
}
/**
- * 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_type, $objects, $build_mode = 'full') {
* 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.
diff --git a/modules/field/field.default.inc b/modules/field/field.default.inc
index e4d7a0102..b86f8b222 100644
--- a/modules/field/field.default.inc
+++ b/modules/field/field.default.inc
@@ -60,19 +60,23 @@ function field_default_prepare_view($obj_type, $objects, $field, $instances, $la
// Group objects, instances and items by formatter module.
$modules = array();
foreach ($instances as $id => $instance) {
- $module = $instance['display'][$build_mode]['module'];
- $modules[$module] = $module;
- $grouped_objects[$module][$id] = $objects[$id];
- $grouped_instances[$module][$id] = $instance;
- // hook_field_formatter_prepare_view() alters $items by reference.
- $grouped_items[$module][$id] = &$items[$id];
+ $display = $instance['display'][$build_mode];
+ if ($display['type'] !== 'hidden') {
+ $module = $display['module'];
+ $modules[$module] = $module;
+ $grouped_objects[$module][$id] = $objects[$id];
+ $grouped_instances[$module][$id] = $instance;
+ $grouped_displays[$module][$id] = $display;
+ // hook_field_formatter_prepare_view() 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';
if (function_exists($function)) {
- $function($obj_type, $grouped_objects[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $build_mode);
+ $function($obj_type, $grouped_objects[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $grouped_displays[$module]);
}
}
}
@@ -89,57 +93,38 @@ function field_default_view($obj_type, $object, $field, $instance, $langcode, $i
$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) {
+ // 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['items'][$delta] += $format_info;
- $element['items'][$delta]['#item']['#delta'] = $delta;
+ $element[$delta] = $formatter_function($obj_type, $object, $field, $instance, $langcode, $display, $items, $delta);
+ $element[$delta]['#weight'] = $delta;
}
}
else {
- $element['items'] += $format_info;
+ $element[0] = $formatter_function($obj_type, $object, $field, $instance, $langcode, $display, $items, 0);
}
$addition = array($field['field_name'] => $element);
diff --git a/modules/field/field.module b/modules/field/field.module
index 2bff9cea1..2861841a4 100644
--- a/modules/field/field.module
+++ b/modules/field/field.module
@@ -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,18 @@ function field_extract_bundle($obj_type, $bundle) {
*/
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']);
+ // @todo Convert to using drupal_html_class() after benchmarking the impact of
+ // doing so.
$field_type_css = strtr($field['type'], '_', '-');
$field_name_css = strtr($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 +701,7 @@ function template_preprocess_field(&$variables) {
'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 +714,8 @@ function template_preprocess_field(&$variables) {
'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);
diff --git a/modules/field/modules/list/list.module b/modules/field/modules/list/list.module
index ab2966814..b52dfd40b 100644
--- a/modules/field/modules/list/list.module
+++ b/modules/field/modules/list/list.module
@@ -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,
+ );
}
diff --git a/modules/field/modules/number/number.module b/modules/field/modules/number/number.module
index e03b26503..710d82e54 100644
--- a/modules/field/modules/number/number.module
+++ b/modules/field/modules/number/number.module
@@ -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, $field) {
*/
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'];
-
- if (empty($value) && $value !== '0') {
- return '';
- }
-
- $output = number_format($value, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
+function number_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+ $value = $items[$delta]['value'];
+
+ 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,
+ );
}
/**
diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module
index abae03be2..97b71571f 100644
--- a/modules/field/modules/text/text.module
+++ b/modules/field/modules/text/text.module
@@ -191,49 +191,12 @@ function text_field_validate($obj_type, $object, $field, $instance, $langcode, $
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']);
- 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) : '';
+ // 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($instances[$id], $langcode, $item, 'value') : '';
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($instances[$id], $langcode, $item, 'summary') : '';
}
}
}
@@ -286,49 +249,66 @@ 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];
+
+ 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);
+ }
+ break;
-/**
- * Theme function for 'plain' text field formatter.
- */
-function theme_field_formatter_text_plain($variables) {
- $element = $variables['element'];
- return strip_tags($element['#item']['safe']);
-}
+ 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);
+ }
+ break;
-/**
- * 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);
+ 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.
+ * Sanitizes the 'value' or 'summary' data of a text value.
+ *
+ * Depending on whether the field instance uses text processing, data is run
+ * through check_plain() or check_markup().
+ *
+ * @param $instance
+ * The instance definition.
+ * @param $langcode
+ * The language associated to $item.
+ * @param $item
+ * The field value to sanitize.
+ * @param $column
+ * The column to sanitize (either 'value' or 'summary').
+ *
+ * @return
+ * The sanitized string.
*/
-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($instance, $langcode, $item, $column) {
+ // If the value uses a cacheable text format, text_field_load() precomputes
+ // the sanitized string.
+ if (isset($item["safe_$column"])) {
+ return $item["safe_$column"];
}
+ return $instance['settings']['text_processing'] ? check_markup($item[$column], $item['format'], $langcode, TRUE) : check_plain($item[$column]);
}
/**
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index 286d1a493..418017f68 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -808,7 +808,7 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
}
/**
- * Test field_attach_view() and field_atach_prepare_view().
+ * Test field_attach_view() and field_attach_prepare_view().
*/
function testFieldAttachView() {
$entity_type = 'test_entity';
@@ -893,7 +893,7 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
$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_view().
$entity = clone($entity_init);
$formatter_setting = $this->randomName();
$this->instance['display'] = array(
diff --git a/modules/field/tests/field_test.field.inc b/modules/field/tests/field_test.field.inc
index 0bdc93ea6..5097a3357 100644
--- a/modules/field/tests/field_test.field.inc
+++ b/modules/field/tests/field_test.field.inc
@@ -92,16 +92,6 @@ function field_test_field_validate($obj_type, $object, $field, $instance, $langc
}
/**
- * 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) {
@@ -238,11 +228,11 @@ function field_test_field_formatter_info() {
/**
* Implements hook_field_formatter_prepare_view().
*/
-function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $build_mode) {
+function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
foreach ($items as $id => $item) {
// To keep the test non-intrusive, only act on the
// 'field_test_needs_additional_data' formatter.
- if ($instances[$id]['display'][$build_mode]['type'] == 'field_test_needs_additional_data') {
+ if ($displays[$id]['type'] == 'field_test_needs_additional_data') {
foreach ($item as $delta => $value) {
// Don't add anything on empty values.
if ($value) {
@@ -254,47 +244,38 @@ function field_test_field_formatter_prepare_view($obj_type, $objects, $field, $i
}
/**
- * Theme function for 'field_test_default' formatter.
+ * Implements hook_field_formatter().
*/
-function theme_field_formatter_field_test_default($variables) {
- $element = $variables['element'];
-
- $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'];
+function field_test_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
+ $settings = $display['settings'];
+
+ 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));