Category Archives: Drupal

Always showing a teaser for lists of content in Drupal

For the main Middlebury and MIIS websites, we run a module named Monster Menus that adds hierarchical pages and permissions on top of Drupal. One of the effects of this is that we have many pages that are lists of nodes some of which we want to display in a full view, others of which we want to display as teasers. A common example is a list of news articles with a simple node stickied at the top. We want the news items to show up as teasers, allowing you to click through to see one of them in full view mode, but we also want that basic node at the top of the page to show up fully.

In Drupal 6 we achieved this by creating a custom template file outside of Drupal’s normal theme hooks and adding it to the template files array in the node preprocess function[ref]In order to make our preprocess functions a bit easier to read, we separate out the functionality for each content type into its own function using this method:

<?php
/**
* Prepares variables for node.tpl.php
*
* @see node.tpl.php
*/
function midd_preprocess_node(&$variables) {
$function = __FUNCTION__ . '__' . $variables['node']->type;
if (function_exists($function)) {
$function($variables);
}
}
/**
* Prepares variables for node--page.tpl.php
*
* @see node.tpl.php
*/
function midd_preprocess_node__page(&$variables) {
// Content type specific functionality.
}
[/ref] within template.php [ref]arg(1) is normally the node id when viewing a Drupal URL ending in /node/123. In Monster Menus, the node id is actually arg(3) since its URLs are of the form /mm/123/node/456 where the first number is the page id. I’ve used arg(1) in the examples to keep them familiar to most Drupal developers.[/ref].

<?php
function midd_preprocess_node_news(&$vars) {
if (arg(1) != $vars['nid']) {
$vars['template_files'][] = 'node-newslist';
}
}

Then we could have node-newslist.tpl.php along with node.tpl.php and show different markup. This all worked quite well in Drupal 6 because the CCK module exposed all the field data to the preprocess functions and you could manipulate it however you liked before outputting it. But it runs into trouble with Drupal 7’s field API and render arrays. You can still do it in Drupal 7, and just need to change “template_files” to “theme_hook_suggestions” in the example shown above, but I decided to go a different direction.

With Drupal 7’s new entity API, you can update how the render array is built based on the node’s metadata in hook_entity_view_mode_alter(). This has the advantage that the node now is rendered as a teaser and the fields set for that display mode in the admin interface show up as you’d normally expect them to, in the order defined, with the wrapper elements specified, and using the standard theme hook suggestion of node__TYPE__teaser.tpl.php.

<?php
/**
* Implements hook_entity_view_mode_alter().
*/
function midd_entity_view_mode_alter(&$view_mode, $context) {
if ($context['entity_type'] == 'node' &&
$context['entity']->nid != arg(1) &&
$context['entity']->type == 'news') {
$view_mode = 'teaser';
}
}