summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--modules/file/file.field.inc48
-rw-r--r--modules/file/file.module3
-rw-r--r--modules/image/image.field.inc72
-rw-r--r--modules/image/image.module10
-rw-r--r--modules/locale/locale.field.inc2
-rw-r--r--modules/node/node.module6
-rw-r--r--modules/rdf/rdf.module37
-rw-r--r--modules/taxonomy/taxonomy.module44
17 files changed, 418 insertions, 464 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));
diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc
index fb0d34925..7470d3d1e 100644
--- a/modules/file/file.field.inc
+++ b/modules/file/file.field.inc
@@ -844,33 +844,47 @@ function theme_file_upload_help($variables) {
}
/**
- * 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']),
);
}
diff --git a/modules/file/file.module b/modules/file/file.module
index 0768b1916..6b7ed6ad3 100644
--- a/modules/file/file.module
+++ b/modules/file/file.module
@@ -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),
),
diff --git a/modules/image/image.field.inc b/modules/image/image.field.inc
index b78425ea8..3ab6f7090 100644
--- a/modules/image/image.field.inc
+++ b/modules/image/image.field.inc
@@ -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
diff --git a/modules/image/image.module b/modules/image/image.module
index 77a9317ce..8786d1032 100644
--- a/modules/image/image.module
+++ b/modules/image/image.module
@@ -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),
),
);
}
diff --git a/modules/locale/locale.field.inc b/modules/locale/locale.field.inc
index 8093f3520..3ad4672ff 100644
--- a/modules/locale/locale.field.inc
+++ b/modules/locale/locale.field.inc
@@ -52,7 +52,7 @@ function locale_field_fallback_view(&$output, $context) {
// 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();
diff --git a/modules/node/node.module b/modules/node/node.module
index 543c40f77..0f0d171cf 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -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);
diff --git a/modules/rdf/rdf.module b/modules/rdf/rdf.module
index 2da297a1d..7993b24c7 100644
--- a/modules/rdf/rdf.module
+++ b/modules/rdf/rdf.module
@@ -427,12 +427,11 @@ function rdf_preprocess_field(&$variables) {
$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(&$variables) {
}
/**
- * 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 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'];
+ 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'];
+ }
+ }
+ }
}
}
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 290162e26..1eb295d39 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -1102,20 +1102,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];
+
+ 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']);
+ }
+ $term = $item['taxonomy_term'];
+ $result = array(
+ '#type' => 'link',
+ '#title' => $term->name,
+ '#href' => 'taxonomy/term/' . $term->tid,
+ );
+ break;
-/**
- * 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);
+ case 'taxonomy_term_plain':
+ $term = $item['taxonomy_term'];
+ $result = array(
+ '#markup' => check_plain($term->name),
+ );
+ break;
+ }
+
+ return $result;
}
/**
@@ -1140,12 +1156,12 @@ function taxonomy_allowed_values($field) {
}
/**
- * Implements hook_field_load().
+ * Implements hook_field_formatter_prepare_view().
*
* 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_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
$tids = array();
// Collect every possible term attached to any of the fieldable entities.