summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/field/field.module131
-rw-r--r--modules/field/tests/field.test88
-rw-r--r--modules/field/tests/field_test.field.inc8
3 files changed, 134 insertions, 93 deletions
diff --git a/modules/field/field.module b/modules/field/field.module
index 9b21d3ba4..5370838db 100644
--- a/modules/field/field.module
+++ b/modules/field/field.module
@@ -471,98 +471,50 @@ function _field_filter_xss_display_allowed_tags() {
}
/**
- * Format a field item for display.
+ * Returns a renderable array for a single field value.
*
- * TODO D7 : do we still need field_format ?
- * - backwards compatibility of templates - check what fallbacks we can propose...
- * - was used by Views integration in CCK in D6 - do we need now?
- * At least needs a little rehaul/update...
- *
- * Used to display a field's values outside the context of the $node, as
- * when fields are displayed in Views, or to display a field in a template
- * using a different formatter than the one set up on the 'Manage display' tab
- * for the node's context.
- *
- * @param $field
- * Either a field array or the name of the field.
+ * @param $entity_type
+ * The type of $entity; e.g. 'node' or 'user'.
+ * @param $entity
+ * The entity containing the field to display. Must at least contain the id
+ * key and the field data to display.
+ * @param $field_name
+ * The name of the field to display.
* @param $item
- * The field item(s) to be formatted (such as $node->field_foo[0],
- * or $node->field_foo if the formatter handles multiple values itself)
- * @param $formatter_type
- * The name of the formatter type to use.
- * @param $node
- * Optionally, the containing node object for context purposes and
- * field-instance options.
- *
+ * The field value to display, as found in
+ * $entity->field_name[$langcode][$delta].
+ * @param $display
+ * Can be either the name of a view mode, or an array of display settings.
+ * See field_view_field() for more information.
+ * @param $langcode
+ * (Optional) The language of the value in $item. If not provided, the
+ * current language will be assumed.
* @return
- * A string containing the contents of the field item(s) sanitized for display.
- * It will have been passed through the necessary check_plain() or check_markup()
- * functions as necessary.
+ * A renderable array for the field value.
*/
-function field_format($entity_type, $entity, $field, $item, $formatter_type = NULL, $formatter_settings = array()) {
- if (!is_array($field)) {
- $field = field_info_field($field);
- }
-
- if (field_access('view', $field, $entity_type, $entity)) {
- $field_type = field_info_field_types($field['type']);
+function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL) {
+ $output = array();
- // We need $field, $instance, $entity_type, $entity to be able to display a value...
- list(, , $bundle) = entity_extract_ids($entity_type, $entity);
- $instance = field_info_instance($entity_type, $field['field_name'], $bundle);
+ if ($field = field_info_field($field_name)) {
+ $langcode = field_multilingual_valid_language($langcode, FALSE);
- $display = array(
- 'type' => $formatter_type ? $formatter_type : $field_type['default_formatter'],
- 'settings' => $formatter_settings,
- );
- $display['settings'] += field_info_formatter_settings($display['type']);
-
- if ($display['type'] !== 'hidden') {
- $theme = $formatter['module'] . '_formatter_' . $display['type'];
-
- $element = array(
- '#theme' => $theme,
- '#field_name' => $field['field_name'],
- '#object_type' => $entity_type,
- '#bundle' => $bundle,
- '#formatter' => $display['type'],
- '#settings' => $display['settings'],
- '#object' => $entity,
- '#object_type' => $entity_type,
- '#delta' => isset($item['#delta']) ? $item['#delta'] : NULL,
- );
-
- if (field_behaviors_formatter('multiple values', $display) == FIELD_BEHAVIOR_DEFAULT) {
- // Single value formatter.
-
- // hook_field('sanitize') expects an array of items, so we build one.
- $items = array($item);
- $function = $field['module'] . '_field_sanitize';
- if (function_exists($function)) {
- $function($entity_type, $entity, $field, $instance, $items);
- }
+ // Determine the langcode that will be used by language fallback.
+ $langcode = current(field_multilingual_available_languages($entity_type, $field, array($langcode)));
- $element['#item'] = $items[0];
- }
- else {
- // Multiple values formatter.
- $items = $item;
- $function = $field['module'] . '_field_sanitize';
- if (function_exists($function)) {
- $function($entity_type, $entity, $field, $instance, $items);
- }
+ // Push the item as the single value for the field, and defer to
+ // field_view_field() to build the render array for the whole field.
+ $clone = clone $entity;
+ $clone->{$field_name}[$langcode] = array($item);
+ $elements = field_view_field($entity_type, $clone, $field_name, $display, $langcode);
- foreach ($items as $delta => $item) {
- $element[$delta] = array(
- '#item' => $item,
- '#weight' => $delta,
- );
- }
- }
-
- return theme($theme, $element);
+ // Extract the part of the render array we need.
+ $output = isset($elements[0]) ? $elements[0] : array();
+ if (isset($elements['#access'])) {
+ $output['#access'] = $elements['#access'];
}
}
+
+ return $output;
}
/**
@@ -638,12 +590,17 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
// 'single field' mode, to reuse the language fallback logic.
$options = array('field_name' => $field_name, 'language' => field_multilingual_valid_language($langcode, FALSE));
$null = NULL;
- list($id) = entity_extract_ids($entity_type, $entity);
- // First let the field types do their preparation.
- _field_invoke_multiple('prepare_view', $entity_type, array($id => $entity), $display, $null, $options);
- // Then let the formatters do their own specific massaging.
- _field_invoke_multiple_default('prepare_view', $entity_type, array($id => $entity), $display, $null, $options);
+ // Invoke prepare_view steps if needed.
+ if (empty($entity->_field_view_prepared)) {
+ list($id) = entity_extract_ids($entity_type, $entity);
+
+ // First let the field types do their preparation.
+ _field_invoke_multiple('prepare_view', $entity_type, array($id => $entity), $display, $null, $options);
+ // Then let the formatters do their own specific massaging.
+ _field_invoke_multiple_default('prepare_view', $entity_type, array($id => $entity), $display, $null, $options);
+ }
+
// Build the renderable array.
$result = _field_invoke_default('view', $entity_type, $entity, $display, $null, $options);
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index f1bc28c71..dc56f4eb5 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -925,7 +925,7 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
$this->instance['display'] = array(
'full' => array(
'label' => 'above',
- 'type' => 'field_test_needs_additional_data',
+ 'type' => 'field_test_with_prepare_view',
'settings' => array(
'test_formatter_setting_additional' => $formatter_setting,
)
@@ -1805,7 +1805,7 @@ class FieldDisplayAPITestCase extends FieldTestCase {
/**
* Test the field_view_field() function.
*/
- function testFieldBuildField() {
+ function testFieldViewField() {
// No display settings: check that default display settings are used.
$output = field_view_field('test_entity', $this->entity, $this->field_name);
$this->drupalSetContent(drupal_render($output));
@@ -1834,6 +1834,23 @@ class FieldDisplayAPITestCase extends FieldTestCase {
}
$this->assertText($setting . '|' . implode('|', $array), t('Values were displayed with expected setting.'));
+ // Check the prepare_view steps are invoked.
+ $display = array(
+ 'label' => 'hidden',
+ 'type' => 'field_test_with_prepare_view',
+ 'settings' => array(
+ 'test_formatter_setting_additional' => $this->randomName(),
+ ),
+ );
+ $output = field_view_field('test_entity', $this->entity, $this->field_name, $display);
+ $view = drupal_render($output);
+ $this->drupalSetContent($view);
+ $setting = $display['settings']['test_formatter_setting_additional'];
+ $this->assertNoText($this->label, t('Label was not displayed.'));
+ foreach ($this->values as $delta => $value) {
+ $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+
// View mode: check that display settings specified in the instance are
// used.
$output = field_view_field('test_entity', $this->entity, $this->field_name, 'full');
@@ -1854,6 +1871,73 @@ class FieldDisplayAPITestCase extends FieldTestCase {
$this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
}
}
+
+ /**
+ * Test the field_view_value() function.
+ */
+ function testFieldViewValue() {
+ // No display settings: check that default display settings are used.
+ $settings = field_info_formatter_settings('field_test_default');
+ $setting = $settings['test_formatter_setting'];
+ foreach ($this->values as $delta => $value) {
+ $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
+ $output = field_view_value('test_entity', $this->entity, $this->field_name, $item);
+ $this->drupalSetContent(drupal_render($output));
+ $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+
+ // Check that explicit display settings are used.
+ $display = array(
+ 'type' => 'field_test_multiple',
+ 'settings' => array(
+ 'test_formatter_setting_multiple' => $this->randomName(),
+ ),
+ );
+ $setting = $display['settings']['test_formatter_setting_multiple'];
+ $array = array();
+ foreach ($this->values as $delta => $value) {
+ $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
+ $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, $display);
+ $this->drupalSetContent(drupal_render($output));
+ $this->assertText($setting . '|0:' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+
+ // Check that prepare_view steps are invoked.
+ $display = array(
+ 'type' => 'field_test_with_prepare_view',
+ 'settings' => array(
+ 'test_formatter_setting_additional' => $this->randomName(),
+ ),
+ );
+ $setting = $display['settings']['test_formatter_setting_additional'];
+ $array = array();
+ foreach ($this->values as $delta => $value) {
+ $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
+ $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, $display);
+ $this->drupalSetContent(drupal_render($output));
+ $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+
+ // View mode: check that display settings specified in the instance are
+ // used.
+ $setting = $this->instance['display']['full']['settings']['test_formatter_setting'];
+ foreach ($this->values as $delta => $value) {
+ $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
+ $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'full');
+ $this->drupalSetContent(drupal_render($output));
+ $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+
+ // Unknown view mode: check that display settings for 'full' view mode
+ // are used.
+ $setting = $this->instance['display']['full']['settings']['test_formatter_setting'];
+ foreach ($this->values as $delta => $value) {
+ $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
+ $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'unknown_view_mode');
+ $this->drupalSetContent(drupal_render($output));
+ $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
+ }
+ }
}
class FieldCrudTestCase extends FieldTestCase {
diff --git a/modules/field/tests/field_test.field.inc b/modules/field/tests/field_test.field.inc
index 1213d4d4d..faf1b1469 100644
--- a/modules/field/tests/field_test.field.inc
+++ b/modules/field/tests/field_test.field.inc
@@ -248,7 +248,7 @@ function field_test_field_formatter_info() {
'test_formatter_setting_multiple' => 'dummy test string',
),
),
- 'field_test_needs_additional_data' => array(
+ 'field_test_with_prepare_view' => array(
'label' => t('Tests hook_field_formatter_prepare_view()'),
'field types' => array('test_field'),
'settings' => array(
@@ -264,8 +264,8 @@ function field_test_field_formatter_info() {
function field_test_field_formatter_prepare_view($entity_type, $entities, $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 ($displays[$id]['type'] == 'field_test_needs_additional_data') {
+ // 'field_test_with_prepare_view' formatter.
+ if ($displays[$id]['type'] == 'field_test_with_prepare_view') {
foreach ($item as $delta => $value) {
// Don't add anything on empty values.
if ($value) {
@@ -290,7 +290,7 @@ function field_test_field_formatter_view($entity_type, $entity, $field, $instanc
}
break;
- case 'field_test_needs_additional_data':
+ case 'field_test_with_prepare_view':
foreach ($items as $delta => $item) {
$element[$delta] = array('#markup' => $settings['test_formatter_setting_additional'] . '|' . $item['value'] . '|' . $item['additional_formatter_value']);
}