- Patch #612894 by yched, David_Rothstein: field_format() is just a pile of code that doesn't work.

merge-requests/26/head
Dries Buytaert 2010-03-12 19:51:40 +00:00
parent 2c3c1a9303
commit 8e39e9abb1
3 changed files with 134 additions and 93 deletions

View File

@ -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);
}
function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL) {
$output = array();
if (field_access('view', $field, $entity_type, $entity)) {
$field_type = field_info_field_types($field['type']);
if ($field = field_info_field($field_name)) {
$langcode = field_multilingual_valid_language($langcode, FALSE);
// 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);
// Determine the langcode that will be used by language fallback.
$langcode = current(field_multilingual_available_languages($entity_type, $field, array($langcode)));
$display = array(
'type' => $formatter_type ? $formatter_type : $field_type['default_formatter'],
'settings' => $formatter_settings,
);
$display['settings'] += field_info_formatter_settings($display['type']);
// 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);
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);
}
$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);
}
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);

View File

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

View File

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