chacadwa.com

Technical blog and writings by Micah Webner.

Adding fake Drupal 7 node fields with custom theme functions

This example takes the node creation date and renders it as a fake field. It also creates a theme_mysite_pseudo_field() function that could be used as a template for any renderable array.

For our example, our content type is podcast, and we want to add a pseudo-field called mysite_podcast_date. This is a pretty standard implementation of hook_node_view(), but we're going to specify our mysite_pseudo_field theme wrapper and specify that we want our label to be inline. This adds our fake field to our node's output.

[code lang=php]
/**
* Implements hook_node_view().
*/
function mysite_node_view($node, $view_mode, $langcode) {
switch ($node->type) {
case 'podcast':
$node->content['mysite_podcast_date'] = array(
'#type' => 'item',
'#field_name' => 'mysite_podcast_date',
'#label' => t('Date:'),
'#markup' => format_date($node->created, 'custom', 'l, F j, Y'),
'#theme_wrappers' => array('mysite_pseudo_field'),
'#label_display' => 'inline',
);
break;
}
}
[/code]

Next we want to add our field to hook_field_extra_fields(). This allows us to include our field in the manage fields display for our content type.

Note: While writing this, I've noticed that I hard-coded the #label_display in hook_node_view() above, and it cannot be set in the site's UI. I can't recall the details behind that, but I think it's related to #1471706 which is an open issue for Drupal 8 core.

[code lang=php]
/**
* Implements hook_field_extra_fields().
*/
function mysite_field_extra_fields() {
$extra['node']['podcast']['display'] = array(
'mysite_podcast_date' => array(
'label' => t('Sermon Date'),
'description' => t('Display the node date like a field.'),
'weight' => 0,
),
);
return $extra;
}
[/code]

Now we invoke hook_theme() to add information about the mysite_pseudo_field theme wrapper.

Note: This is a fairly simple example using a theme function. Here's a better example that uses a template file and a template_preprocess() function.

[code lang=php]
/**
* Implements hook_theme().
*/
function mysite_theme() {
return array(
'mysite_pseudo_field' => array(
'render element' => 'element',
),
);
}
[/code]

Finally, we create our theme function, which more closely emulates Field API output than anything I've found (other than forging enough settings to use the actual field theming functions.)

[code lang=php]
/**
* Theme output of a pseudo_field.
*
* @see http://drupal.org/node/1471706
*/
function theme_mysite_pseudo_field($variables) {
$classes = array('clearfix', 'field');

if (isset($variables['element']['#field_name'])) {
$classes[] = 'field-name-' . strtr($variables['element']['#field_name'], '_', '-');
}

if (isset($variables['element']['#label_display'])) {
$classes[] = 'field-label-' . $variables['element']['#label_display'];
}

$output = '';
if (isset($variables['element']['#title'])) {
$output .= '' . $variables['element']['#title'] . ' ';
}
$output .= '' . $variables['element']['#markup'] . '';
$output .= '';
return $output;
}
[/code]

Acknowledgement

I combined several resources to figure this out. I learned about hook_node_view() from ComputerMinds: Add stuff to a node and configure it like fields.

Updates

  • April 24, 2013: Improved theme_mysite_pseudo_field() to add support for #field_name and streamline handling of #label_display, based on project collaboration with Donald Dille.
  • June 4, 2013: This commit on one of my current projects includes a template preprocess function and uses an external template file to generate the HTML for theming fake fields.
Topics: