Commit 34a8a369 authored by webchick's avatar webchick
Browse files

#367595 by plach, catch, sun, yched, et al: Added support for translatable fields to Field API.

parent bc23bfaa
......@@ -248,11 +248,12 @@ EOF;
}
function createSampleNodes() {
$langcode = FIELD_LANGUAGE_NONE;
// Post 5 articles.
for ($i = 0; $i < 5; $i++) {
$edit = array();
$edit['title'] = $this->randomName();
$edit['body[0][value]'] = $this->randomName();
$edit["body[$langcode][0][value]"] = $this->randomName();
$this->drupalPost('node/add/article', $edit, t('Save'));
}
}
......
......@@ -152,7 +152,8 @@ class BlogTestCase extends DrupalWebTestCase {
// Edit blog node.
$edit = array();
$edit['title'] = 'node/' . $node->nid;
$edit['body[0][value]'] = $this->randomName(256);
$langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = $this->randomName(256);
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$this->assertRaw(t('Blog entry %title has been updated.', array('%title' => $edit['title'])), t('Blog node was edited'));
......
......@@ -213,7 +213,7 @@ function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $conte
}
else {
$edit['title'] = blogapi_blogger_title($content);
$edit['body'][0]['value'] = $content;
$edit['body'][FIELD_LANGUAGE_NONE][0]['value'] = $content;
}
if (!node_access('create', $edit['type'])) {
......@@ -274,12 +274,12 @@ function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $cont
// Check for bloggerAPI vs. metaWeblogAPI.
if (is_array($content)) {
$node->title = $content['title'];
$node->body[0]['value'] = $content['description'];
$node->body[FIELD_LANGUAGE_NONE][0]['value'] = $content['description'];
_blogapi_mt_extra($node, $content);
}
else {
$node->title = blogapi_blogger_title($content);
$node->body[0]['value'] = $content;
$node->body[FIELD_LANGUAGE_NONE][0]['value'] = $content;
}
module_invoke_all('node_blogapi_edit', $node);
......@@ -895,14 +895,14 @@ function _blogapi_mt_extra($node, $struct) {
// Merge the 3 body sections (description, mt_excerpt, mt_text_more) into one body.
if ($struct['mt_excerpt']) {
$node->body[0]['value'] = $struct['mt_excerpt'] . '<!--break-->' . $node->body[0]['value'];
$node->body[FIELD_LANGUAGE_NONE][0]['value'] = $struct['mt_excerpt'] . '<!--break-->' . $node->body[FIELD_LANGUAGE_NONE][0]['value'];
}
if ($struct['mt_text_more']) {
$node->body[0]['value'] = $node->body[0]['value'] . '<!--extended-->' . $struct['mt_text_more'];
$node->body[FIELD_LANGUAGE_NONE][0]['value'] = $node->body[FIELD_LANGUAGE_NONE][0]['value'] . '<!--extended-->' . $struct['mt_text_more'];
}
if ($struct['mt_convert_breaks']) {
$node->body[0]['format'] = $struct['mt_convert_breaks'];
$node->body[FIELD_LANGUAGE_NONE][0]['format'] = $struct['mt_convert_breaks'];
}
if ($struct['dateCreated']) {
......@@ -925,8 +925,8 @@ function _blogapi_get_post($node, $bodies = TRUE) {
);
if ($bodies) {
$body = $node->body[0]['value'];
$format = $node->body[0]['format'];
$body = $node->body[FIELD_LANGUAGE_NONE][0]['value'];
$format = $node->body[FIELD_LANGUAGE_NONE][0]['format'];
if ($node->comment == 1) {
$comment = 2;
}
......
......@@ -141,7 +141,7 @@ class BookTestCase extends DrupalWebTestCase {
// Check printer friendly version.
$this->drupalGet('book/export/html/' . $node->nid);
$this->assertText($node->title, t('Printer friendly title found.'));
$this->assertRaw(check_markup($node->body[0]['value'], $node->body[0]['format']), t('Printer friendly body found.'));
$this->assertRaw(check_markup($node->body[FIELD_LANGUAGE_NONE][0]['value'], $node->body[FIELD_LANGUAGE_NONE][0]['format']), t('Printer friendly body found.'));
$number++;
}
......@@ -173,7 +173,8 @@ class BookTestCase extends DrupalWebTestCase {
$edit = array();
$edit['title'] = $number . ' - SimpleTest test node ' . $this->randomName(10);
$edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomName(32) . ' ' . $this->randomName(32);
$langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = 'SimpleTest test body ' . $this->randomName(32) . ' ' . $this->randomName(32);
$edit['book[bid]'] = $book_nid;
if ($parent !== NULL) {
......
......@@ -330,9 +330,10 @@ class DBLogTestCase extends DrupalWebTestCase {
break;
default:
$langcode = FIELD_LANGUAGE_NONE;
$content = array(
'title' => $this->randomName(8),
'body[0][value]' => $this->randomName(32),
"body[$langcode][0][value]" => $this->randomName(32),
);
break;
}
......@@ -355,8 +356,9 @@ class DBLogTestCase extends DrupalWebTestCase {
break;
default:
$langcode = FIELD_LANGUAGE_NONE;
$content = array(
'body[0][value]' => $this->randomName(32),
"body[$langcode][0][value]" => $this->randomName(32),
);
break;
}
......
......@@ -350,6 +350,8 @@ function hook_field_schema($field) {
* The field structure for the operation.
* @param $instances
* Array of instance structures for $field for each object, keyed by object id.
* @param $langcode
* The language associated to $items.
* @param $items
* Array of field values already loaded for the objects, keyed by object id.
* @param $age
......@@ -359,9 +361,7 @@ function hook_field_schema($field) {
* Changes or additions to field values are done by altering the $items
* parameter by reference.
*/
function hook_field_load($obj_type, $objects, $field, $instances, &$items, $age) {
global $language;
function hook_field_load($obj_type, $objects, $field, $instances, $langcode, &$items, $age) {
foreach ($objects as $id => $object) {
foreach ($items[$id] as $delta => $item) {
if (!empty($instances[$id]['settings']['text_processing'])) {
......@@ -369,10 +369,9 @@ function hook_field_load($obj_type, $objects, $field, $instances, &$items, $age)
// handled by hook_field_sanitize().
$format = $item['format'];
if (filter_format_allowcache($format)) {
$lang = isset($object->language) ? $object->language : $language->language;
$items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang, FALSE) : '';
$items[$id][$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $langcode, FALSE) : '';
if ($field['type'] == 'text_with_summary') {
$items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang, FALSE) : '';
$items[$id][$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $langcode, FALSE) : '';
}
}
}
......@@ -401,11 +400,12 @@ function hook_field_load($obj_type, $objects, $field, $instances, &$items, $age)
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
*/
function hook_field_sanitize($obj_type, $object, $field, $instance, $items) {
global $language;
function hook_field_sanitize($obj_type, $object, $field, $instance, $langcode, &$items) {
foreach ($items as $delta => $item) {
// Only sanitize items which were not already processed inside
// hook_field_load(), i.e. items with uncacheable text formats, or coming
......@@ -413,10 +413,9 @@ function hook_field_sanitize($obj_type, $object, $field, $instance, $items) {
if (!isset($items[$delta]['safe'])) {
if (!empty($instance['settings']['text_processing'])) {
$format = $item['format'];
$lang = isset($object->language) ? $object->language : $language->language;
$items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $lang) : '';
$items[$delta]['safe'] = isset($item['value']) ? check_markup($item['value'], $format, $langcode) : '';
if ($field['type'] == 'text_with_summary') {
$items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $lang) : '';
$items[$delta]['safe_summary'] = isset($item['summary']) ? check_markup($item['summary'], $format, $langcode) : '';
}
}
else {
......@@ -444,8 +443,10 @@ function hook_field_sanitize($obj_type, $object, $field, $instance, $items) {
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
* @param $errors
* The array of errors, keyed by field name and by value delta, that have
* already been reported for the object. The function should add its errors
......@@ -454,7 +455,7 @@ function hook_field_sanitize($obj_type, $object, $field, $instance, $items) {
* - 'error': an error code (should be a string, prefixed with the module name)
* - 'message': the human readable message to be displayed.
*/
function hook_field_validate($obj_type, $object, $field, $instance, $items, &$errors) {
function hook_field_validate($obj_type, $object, $field, $instance, $langcode, &$items, &$errors) {
foreach ($items as $delta => $item) {
if (!empty($item['value'])) {
if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) {
......@@ -478,10 +479,12 @@ function hook_field_validate($obj_type, $object, $field, $instance, $items, &$er
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_presave($obj_type, $object, $field, $instance, $items) {
function hook_field_presave($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -495,10 +498,12 @@ function hook_field_presave($obj_type, $object, $field, $instance, $items) {
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_insert($obj_type, $object, $field, $instance, $items) {
function hook_field_insert($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -512,10 +517,12 @@ function hook_field_insert($obj_type, $object, $field, $instance, $items) {
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_update($obj_type, $object, $field, $instance, $items) {
function hook_field_update($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -531,10 +538,12 @@ function hook_field_update($obj_type, $object, $field, $instance, $items) {
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_delete($obj_type, $object, $field, $instance, $items) {
function hook_field_delete($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -551,10 +560,12 @@ function hook_field_delete($obj_type, $object, $field, $instance, $items) {
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_delete_revision($obj_type, $object, $field, $instance, $items) {
function hook_field_delete_revision($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -570,10 +581,12 @@ function hook_field_delete_revision($obj_type, $object, $field, $instance, $item
* The field structure for the operation.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $langcode
* The language associated to $items.
* @param $items
* $object->{$field['field_name']}, or an empty array if unset.
* $object->{$field['field_name']}[$langcode], or an empty array if unset.
*/
function hook_field_prepare_translation($obj_type, $object, $field, $instance, $items) {
function hook_field_prepare_translation($obj_type, $object, $field, $instance, $langcode, &$items) {
}
/**
......@@ -902,7 +915,7 @@ function theme_field_formatter_FORMATTER_MULTIPLE($element) {
*
* See field_attach_form() for details and arguments.
*/
function hook_field_attach_form($obj_type, $object, &$form, &$form_state) {
function hook_field_attach_form($obj_type, $object, &$form, &$form_state, $langcode) {
}
/**
......@@ -987,6 +1000,23 @@ function hook_field_attach_submit($obj_type, $object, $form, &$form_state) {
function hook_field_attach_presave($obj_type, $object) {
}
/**
* Act on field_attach_preprocess.
*
* This hook is invoked while preprocessing the field.tpl.php template file.
*
* @param $variables
* The variables array is passed by reference and will be populated with field values.
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $object
* The object with fields to render.
* @param $element
* The structured array containing the values ready for rendering.
*/
function hook_field_attach_preprocess_alter(&$variables, $obj_type, $object, $element) {
}
/**
* Act on field_attach_insert.
*
......@@ -1094,8 +1124,10 @@ function hook_field_attach_delete_revision($obj_type, $object) {
* The object with fields to render.
* @param $build_mode
* Build mode, e.g. 'full', 'teaser'...
* @param $langcode
* The language in which the field values will be displayed.
*/
function hook_field_attach_view_alter($output, $obj_type, $object, $build_mode) {
function hook_field_attach_view_alter($output, $obj_type, $object, $build_mode, $langcode) {
}
/**
......
......@@ -176,6 +176,7 @@ function _field_invoke($op, $obj_type, $object, &$a = NULL, &$b = NULL, $options
$default_options = array(
'default' => FALSE,
'deleted' => FALSE,
'language' => NULL,
);
$options += $default_options;
......@@ -196,32 +197,38 @@ function _field_invoke($op, $obj_type, $object, &$a = NULL, &$b = NULL, $options
// When in 'single field' mode, only act on the specified field.
if ((!isset($options['field_id']) || $options['field_id'] == $instance['field_id']) && (!isset($options['field_name']) || $options['field_name'] == $field_name)) {
$field = field_info_field($field_name);
$field_translations = array();
$suggested_languages = empty($options['language']) ? NULL : array($options['language']);
// Extract the field values into a separate variable, easily accessed by
// hook implementations.
$items = isset($object->$field_name) ? $object->$field_name : array();
// Initialize field translations according to the available languages.
foreach (field_multilingual_available_languages($obj_type, $field, $suggested_languages) as $langcode) {
$field_translations[$langcode] = isset($object->{$field_name}[$langcode]) ? $object->{$field_name}[$langcode] : array();
}
// Invoke the field hook and collect results.
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
if (drupal_function_exists($function)) {
$result = $function($obj_type, $object, $field, $instance, $items, $a, $b);
if (isset($result)) {
// For hooks with array results, we merge results together.
// For hooks with scalar results, we collect results in an array.
if (is_array($result)) {
$return = array_merge($return, $result);
// Iterate over all the field translations.
foreach ($field_translations as $langcode => $items) {
$result = $function($obj_type, $object, $field, $instance, $langcode, $items, $a, $b);
if (isset($result)) {
// For hooks with array results, we merge results together.
// For hooks with scalar results, we collect results in an array.
if (is_array($result)) {
$return = array_merge($return, $result);
}
else {
$return[] = $result;
}
}
else {
$return[] = $result;
// Populate $items back in the field values, but avoid replacing missing
// fields with an empty array (those are not equivalent on update).
if ($items !== array() || isset($object->{$field_name}[$langcode])) {
$object->{$field_name}[$langcode] = $items;
}
}
}
// Populate field values back in the object, but avoid replacing missing
// fields with an empty array (those are not equivalent on update).
if ($items !== array() || property_exists($object, $field_name)) {
$object->$field_name = $items;
}
}
}
......@@ -273,6 +280,7 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
$default_options = array(
'default' => FALSE,
'deleted' => FALSE,
'language' => NULL,
);
$options += $default_options;
......@@ -314,7 +322,10 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
$grouped_objects[$field_id][$id] = $objects[$id];
// Extract the field values into a separate variable, easily accessed
// by hook implementations.
$grouped_items[$field_id][$id] = isset($object->$field_name) ? $object->$field_name : array();
$suggested_languages = empty($options['language']) ? NULL : array($options['language']);
foreach (field_multilingual_available_languages($obj_type, $fields[$field_id], $suggested_languages) as $langcode) {
$grouped_items[$field_id][$langcode][$id] = isset($object->{$field_name}[$langcode]) ? $object->{$field_name}[$langcode] : array();
}
}
}
// Initialize the return value for each object.
......@@ -326,17 +337,20 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
$field_name = $field['field_name'];
$function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
if (drupal_function_exists($function)) {
$results = $function($obj_type, $grouped_objects[$field_id], $field, $grouped_instances[$field_id], $grouped_items[$field_id], $options, $a, $b);
if (isset($results)) {
// Collect results by object.
// For hooks with array results, we merge results together.
// For hooks with scalar results, we collect results in an array.
foreach ($results as $id => $result) {
if (is_array($result)) {
$return[$id] = array_merge($return[$id], $result);
}
else {
$return[$id][] = $result;
// Iterate over all the field translations.
foreach ($grouped_items[$field_id] as $langcode => $items) {
$results = $function($obj_type, $grouped_objects[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $options, $a, $b);
if (isset($results)) {
// Collect results by object.
// For hooks with array results, we merge results together.
// For hooks with scalar results, we collect results in an array.
foreach ($results as $id => $result) {
if (is_array($result)) {
$return[$id] = array_merge($return[$id], $result);
}
else {
$return[$id][] = $result;
}
}
}
}
......@@ -345,8 +359,10 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
// Populate field values back in the objects, but avoid replacing missing
// fields with an empty array (those are not equivalent on update).
foreach ($grouped_objects[$field_id] as $id => $object) {
if ($grouped_items[$field_id][$id] !== array() || property_exists($object, $field_name)) {
$object->$field_name = $grouped_items[$field_id][$id];
foreach ($grouped_items[$field_id] as $langcode => $items) {
if ($grouped_items[$field_id][$langcode][$id] !== array() || isset($object->{$field_name}[$langcode])) {
$object->{$field_name}[$langcode] = $grouped_items[$field_id][$langcode][$id];
}
}
}
}
......@@ -394,6 +410,9 @@ function _field_invoke_multiple_default($op, $obj_type, $objects, &$a = NULL, &$
* The form structure to fill in.
* @param $form_state
* An associative array containing the current state of the form.
* @param $langcode
* The language the field values are going to be entered, if no language
* is provided the default site language will be used.
* @return
* The form elements are added by reference at the top level of the $form
* parameter. Sample structure:
......@@ -417,45 +436,57 @@ function _field_invoke_multiple_default($op, $obj_type, $objects, &$a = NULL, &$
* // most common case), and will therefore be repeated as many times as
* // needed, or 'multiple-values' (one single widget allows the input of
* // several values, e.g checkboxes, select box...).
* // The sub-array is nested into a $langcode key where $langcode has the
* // same value of the $langcode parameter above. This allow us to match
* // the field data structure ($field_name[$langcode][$delta][$column]).
* // The '#language' key holds the same value of $langcode and it is used
* // to access the field sub-array when $langcode is unknown.
* 'field_foo' => array(
* '#field_name' => the name of the field,
* '#tree' => TRUE,
* '#required' => whether or not the field is required,
* '#title' => the label of the field instance,
* '#description' => the description text for the field instance,
*
* // Only for 'single' widgets:
* '#theme' => 'field_multiple_value_form',
* '#multiple' => the field cardinality,
* // One sub-array per copy of the widget, keyed by delta.
* 0 => array(
* '#title' => the title to be displayed by the widget,
* '#default_value' => the field value for delta 0,
* '#required' => whether the widget should be marked required,
* '#delta' => 0,
* '#language' => $langcode,
* $langcode => array(
* '#field_name' => the name of the field,
* '#bundle' => the name of the bundle,
* '#columns' => the array of field columns,
* '#tree' => TRUE,
* '#required' => whether or not the field is required,
* '#title' => the label of the field instance,
* '#description' => the description text for the field instance,
*
* // Only for 'single' widgets:
* '#theme' => 'field_multiple_value_form',
* '#multiple' => the field cardinality,
* // One sub-array per copy of the widget, keyed by delta.
* 0 => array(
* '#title' => the title to be displayed by the widget,
* '#default_value' => the field value for delta 0,
* '#required' => whether the widget should be marked required,
* '#delta' => 0,
* '#field_name' => the name of the field,
* '#bundle' => the name of the bundle,
* '#columns' => the array of field columns,
* // The remaining elements in the sub-array depend on the widget.
* '#type' => the type of the widget,
* ...
* ),
* 1 => array(
* ...
* ),
*
* // Only for multiple widgets:
* '#bundle' => $instance['bundle'],
* '#columns' => array_keys($field['columns']),
* // The remaining elements in the sub-array depend on the widget.
* '#type' => the type of the widget,
* ...
* ),
* 1 => array(
* ...
* ),
*
* // Only for multiple widgets:
* '#bundle' => $instance['bundle'],
* '#columns' => array_keys($field['columns']),
* // The remaining elements in the sub-array depend on the widget.
* '#type' => the type of the widget,
* ...
* ),
* )
* @endcode
*/
function field_attach_form($obj_type, $object, &$form, &$form_state) {
$form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state);
function field_attach_form($obj_type, $object, &$form, &$form_state, $langcode = NULL) {
// If no language is provided use the default site language.
$options = array('language' => field_multilingual_valid_language($langcode));
$form += (array) _field_invoke_default('form', $obj_type, $object, $form, $form_state, $options);
// Add custom weight handling.
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
......@@ -991,6 +1022,9 @@ function field_attach_query_revisions($field_id, $conditions, $count, &$cursor =
* The object with fields to render.
* @param $build_mode
* Build mode, e.g. 'full', 'teaser'...
* @param $langcode
* 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:
......@@ -1042,11 +1076,15 @@ function field_attach_query_revisions($field_id, $conditions, $count, &$cursor =
* );
* @endcode
*/
function field_attach_view($obj_type, $object, $build_mode = 'full') {
function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode = NULL) {
// If no language is provided use the current UI language.
$options = array('language' => field_multilingual_valid_language($langcode, FALSE));
// Let field modules sanitize their data for output.
_field_invoke('sanitize', $obj_type, $object);
$null = NULL;
_field_invoke('sanitize', $obj_type, $object, $null, $null, $options);
$output = _field_invoke_default('view', $obj_type, $object, $build_mode);
$output = _field_invoke_default('view', $obj_type, $object, $build_mode, $null, $options);
// Add custom weight handling.
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
......@@ -1057,7 +1095,39 @@ function field_attach_view($obj_type, $object, $build_mode = 'full') {
drupal_alter('field_attach_view', $output, $obj_type, $object, $build_mode);
return $output;
}
/**
* Populate the template variables with the field values available for rendering.
*
* The $variables array will be populated with all the field instance values
* associated with the given entity type, keyed by field name; in case of
* translatable fields the language currently chosen for display will be
* selected.
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $object
* The object with fields to render.
* @param $element
* The structured array containing the values ready for rendering.
* @param $variables
* The variables array is passed by reference and will be populated with field
* values.
*/
function field_attach_preprocess($obj_type, $object, $element, &$variables) {
list(, , $bundle) = field_attach_extract_ids($obj_type, $object);
foreach (field_info_instances($bundle) as $instance) {
$field_name = $instance['field_name'];
if (isset($element[$field_name]['#language'])) {
$langcode = $element[$field_name]['#language'];
$variables[$field_name] = isset($object->{$field_name}[$langcode]) ? $object->{$field_name}[$langcode] : NULL;