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.
/**
* 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;
}
}
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.
/**
* 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;
}
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.
/**
* Implements hook_theme().
*/
function mysite_theme() {
return array(
'mysite_pseudo_field' => array(
'render element' => 'element',
),
);
}
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.)
/**
* 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 = '<div class="' . implode(' ', $classes) . '">';
if (isset($variables['element']['#title'])) {
$output .= '<div class="field-label">' . $variables['element']['#title'] . ' </div>';
}
$output .= '<div class="field-items">' . $variables['element']['#markup'] . '</div>';
$output .= '</div>';
return $output;
}
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.