Use field markup for any value anywhere.

By berliner, 8 November, 2013

Sometimes I just want to display specific pieces of information in, say, a node view. For styling reasons it is often preferable to have the same kind of basic wrapper markup as for fields. This would be particularly useful for pseudo fields that can be declared using hook_extra_fields. Those pseudo fields act almost like real fields in the Fields UI, meaning I can position them just like real fields, put them into groups, etc. But to display them I need to write all the markup myself or write custom theming functions to do this for me. But all I want is to have the same markup that is used for real fields.
Now instead of hardcoding the markup somewhere I came up with a little utility function that provides me with a drop in solution for those case:

/**
 * Helper function to render a pseudo field with the same markup as a normal
 * field.
 *
 * @param array or mixed $value 
 *  A render array or a string. It no array is given it will be turned into a
 *  render array of #type markup.
 * @param string $title 
 *  Set to NULL to hide the title.
 * @param string $field_name 
 *  The name of the pseudo field.
 * @param string $field_type 
 *  The field type, this can be something like text, number_float, see
 *  https://groups.drupal.org/node/124289 for more examples.
 * @param string $label_display 
 *  Can be 'above', 'inline' or 'hidden'.
 * @param string $entity_type 
 *  The type of the entity. This is used for class names.
 * @param string $bundle 
 *  The name of the bundle. This is used for class names.
 * @return void
 */
function pseudo_field_render($value, $title, $field_name, $field_type = 'text',
    $label_display = 'inline', $entity_type = 'node', $bundle = 'page') {

  $item = !is_array($value) ? array('#markup' => $value) : $value;
  return theme('field', array(
    'element' => array(
      '#label_display' => $title === NULL ? 'hidden' : $label_display,
      '#title' => $title,
      '#items' => array(
        0 => $item,
      ),
      '#field_name' => $field_name,
      '#field_type' => $field_type,
      '#entity_type' => 'node',
      '#bundle' => 'artwork',
      '#pseudo_field' => TRUE,
      0 => $item,
    ),
  ));
}

Having this code somewhere in my custom module space, I can simply call

function MY_MODULE_node_view($node, $view_mode, $langcode) {
  ...
  $label = t('My label for the pseudo field');
  $field_name = 'field_pseudo_field';
  $node->content['pseudo_field'] = pseudo_field_render($value, $label, $field_name);
  ...
}

Naturally this seems like an error prone approach as it pretends to have a field on a bundle where the field does not exists. It is even probable that this could brake some modules from contrib space that I'm not aware of and that need to do some altering based on specific bundle related conditions. But I did a little digging through the whole field theming in core and I didn't see any obvious error source. I will soon have this in production on one of my new projects and during development I haven't encountered any problems with this.

Version