You have a multivalue field. You want to display only the first image. You have a problem.
Views does it by cloning $entity and removing the deltas it doesn't need.
Token does it by defining it's own view mode: http://drupalbin.com/17204.

So, we need an extra param. Call it $index. Call it $delta. Just call it something :)

Filing against 7.x in hope we can get something before D8. Otherwise we'll have to continue with workarounds...

CommentFileSizeAuthor
#6 field_view_value_doc-1017850.patch1 KByched

Comments

dave reid’s picture

Token making its own view mode isn't really related, we just made a duplicate copy of field_attach_view() that returns a specific index's value output rather than all of them.

bojanz’s picture

Thanks for the clarification.
In any case, we can do better :)

yched’s picture

Unless I'm missing something, that's what field_view_value() is about - return the render array for a single formatted value (with no field wrapping markup) ?

catch’s picture

Status: Active » Postponed (maintainer needs more info)

I thought field_view_value() was for this as well, has this been tried?

bojanz’s picture

Category: bug » support
Status: Postponed (maintainer needs more info) » Fixed

I had no idea field_view_value() existed.
And it actually uses the same approach dereine & I implemented in Views (clone the entity, remove all field deltas except the one being displayed).
Plus, the "no wrapping markup" tip is gold.

I guess that's it then. Thank you for your help.

yched’s picture

Status: Fixed » Needs review
StatusFileSize
new1 KB

In fact, field_view_values() was written specifically to support Views' use case :-)

Attached patch adds a hint about field_view_value() in the phpdoc for field_view_field().

antiorario’s picture

Title: field_view_value() doesn't return anything useful (and possible solution) » field_view_field() needs to support rendering one value from a multivalue field
Category: bug » support

It seems to me that field_view_value() isn't extracting anything. All I get when I use it is something like:

Array
(
    [#theme] => image_formatter
    [#item] => 3
    [#image_style] => 
    [#path] => 
    [#access] => 1
)

Particularly the last part of the function doesn't seem to be doing what it claims to do:

<?php
    // Extract the part of the render array we need.
    $output = isset($elements[0]) ? $elements[0] : array();
    if (isset($elements['#access'])) {
      $output['#access'] = $elements['#access'];
    }
?>

Does anyone else have the same feeling, or am I just not understanding this?

Update: see my next comment for a solution.

antiorario’s picture

Title: field_view_field() needs to support rendering one value from a multivalue field » field_view_value() doesn't return anything useful (and possible solution)
Category: support » bug

Here's a version of field_view_value() that works:

<?php
function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL) {

  $output = array();

  if ($field = field_info_field($field_name)) {
    // Determine the langcode that will be used by language fallback.
    $langcode = field_language($entity_type, $entity, $field_name, $langcode);

    // 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.

    $elements = field_view_field($entity_type, $entity, $field_name, $display, $langcode);

    // Extract the part of the render array we need.
    $elements['#items'] = array($item => $elements['#items'][$item]);
    $output = $elements;
  }

  return $output;
}
?>

Beside the final part that, as I mentioned in #7, wasn't really doing anything, I also noticed that <?php $clone->{$field_name}[$langcode] = array($item); ?> was removing the actual field information from the object—the main reason why the function wasn't returning anything.

Do we really need $langcode as argument, if it gets systematically owerwritten in the function?

Also, I removed the part where $entity gets cloned, as it seemed pointless. Maybe there was a good reason for the cloning, and if so I'll be happy to know.

One last thing: I'm not sure we need to specify, as a condition, <?php if ($field = field_info_field($field_name)) { ?>. Wouldn't <?php if (field_info_field($field_name)) { ?> be enough? After all, $field never gets called again.

yched’s picture

Title: field_view_field() needs to support rendering one value from a multivalue field » field_view_value() doesn't return anything useful (and possible solution)
Category: support » bug

@antiorario : You're calling field_view_value() with $item param set to 3. Re-read the phpdoc of the function, $item should be something like $node->field_image['und'][3]. http://api.drupal.org/api/drupal/modules--field--field.module/function/f....

$node = node_load(7);
$item = $node->field_image['und'][0];
$output = field_view_value('node', $node, 'field_image', $item);
dsm($output);
dsm(drupal_render($output));

Gives :

array(
  '#theme' => 'image_formatter',
  '#item' => array(
    'fid' => '5',
    'alt' => '',
    'title' => '',
    'uid' => '1',
    'filename' => 'my_image.png',
    'uri' => 'public://field/image/my_image.png',
    'filemime' => 'image/png',
    'filesize' => '2994',
    'status' => '1',
    'timestamp' => '1303563156',
    'rdf_mapping' => array(),
  ),
  '#image_style' => '',
  '#path' => '',
  '#access' => TRUE,
)

and after drupal_render() :
<img typeof="foaf:Image" src="http://localhost.d7/sites/default/files/field/image/my_image.png" alt="" />

Also, the various changes proposed in #8 are incorrect. Main reason is : you can't assume a formatter will return one sub render array per incoming value in $entity->field_name[$langcode]. Some formatters will munge all multiple values in a single piece of HTML (e.g points in a graph, or markers on a map). The only assumption you can make is that you'll get a render array with numerically indexed child elements, starting at 0 - see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/....

The correct approach is to alter the incoming $entity->field_name[$langcode] and pretend there is only one incoming value. Since we alter $entity, we need to clone it.

antiorario’s picture

Thanks, I'll re-read the instructions. Seems that's all I've done today, but I guess I missed some stuff.

dave reid’s picture

Status: Needs review » Reviewed & tested by the community

Doc patch in #6 looks great to me.

plach’s picture

Title: field_view_value() doesn't return anything useful (and possible solution) » Improve documentation for field_view_value()
Version: 7.x-dev » 8.x-dev
Category: bug » task
Priority: Major » Normal
Issue tags: +Needs backport to D7
webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 8.x and 7.x. Thanks!

Status: Fixed » Closed (fixed)
Issue tags: -Needs backport to D7

Automatically closed -- issue fixed for 2 weeks with no activity.