HowTo: Emulate "preprocess" theme functions in Drupal 5

Drupal 6 introduced the concept of a theme preprocess function. In short, it allows themes, theme engines, and even modules to step into the theming process and manipulate the variables that get sent to a template. It replaces the older, clunkier _phptemplate_variables() function from Drupal 5's phptemplate templating engine, but serves much the same purpose.

While we can't backport all of that new functionality, it is possible to greatly simplify _phptemplate_variables() in Drupal 5 in a way that looks a lot like Drupal 6. Specifically, we can break up _phptemplate_variables() into separate functions that act like a theme's preprocess functions in Drupal 6.

To get that simplification, simply specify your _phptemplate_variables() function in template.php like so:

<?php
function _phptemplate_variables($hook, $vars) {

 
$function = 'phptemplate_preprocess_'. str_replace('-', '_', $hook);
  if (
function_exists($function)) {
   
$function($vars);
  }

  return
$vars;
}
?>

First, we ensure that the theme hook is in a format that can be used as part of a function name, and build the name of what the preprocessing function would be called. Then if it exists, we call it with the $vars array. Note that we do not accept a return value from the preprocessing function. Instead, in the called function, we accept the parameter by reference like so:

<?php
function phptemplate_preprocess_page(&$vars) {
 
// Manipulate the $vars array here.
}
?>

Now we can, in the theme, step into any template file's variable building process add, remove, or modify variables to be sent to the template just by declaring the appropriate function. Although it doesn't actually give us any new functionality, it is easier to read and maintain than a giant switch statement in _phptemplate_variables() and will also be easier to upgrade to Drupal 6 later.

Separate var files

sirkitree - December 17, 2007 - 14:38

Here's a great technique that we use when the template function starts to become unmanageable, separate them into their own vars files:

<?php
/**
* Intercept template variables
*
* @param $hook
*   The name of the theme function being executed
* @param $vars
*   A sequential array of variables passed to the theme function.
*/
function _phptemplate_variables($hook, $vars = array()) {
  global
$user;

 
$vars['user'] = $user;
 
$vars['path'] = base_path() . path_to_theme() .'/';
 
$vars['admin'] = $user->roles[3] || $user->uid == 1 ? TRUE : FALSE;
 
$vars['moderator'] = $user->roles[4] ? TRUE : FALSE;
 
$vars['editor'] = $user->roles[5] ? TRUE : FALSE;
 
$vars['authenticated'] = $user->uid ? TRUE : FALSE;
 
$vars['theme'] = 'my_theme_name';

 
// Include broad variables for each hook.
 
if (file_exists($vars['directory'] .'/'. $hook .'.vars.php')) {
    include_once
$vars['directory'] .'/'. $hook .'.vars.php';
   
$function = $vars['theme'] .'_variables_'. str_replace('-', '_', $hook);
   
$vars = $function($vars);
  }

 
// Specific variables for node types.
 
if ($hook == 'node') {
    if (
file_exists($vars['directory'] .'/node-'. $vars['node']->type .'.vars.php')) {
      include_once
$vars['directory'] .'/node-'. $vars['node']->type .'.vars.php';
     
$function = $vars['theme'] .'_variables_node_'. $vars['node']->type;
     
$vars = $function($vars);
    }
  }

  return
$vars;
}
?>

Nate Haug showed me this. Thanks Nate! (modified slightly so specify theme name in a var)

Further enhancements

yhager - August 4, 2008 - 07:01

That's a very good tip, it really structures the code well.

I added another convenience to it:

<?php
function phptemplate_preprocess_node(&$vars) {
 
$node = $vars['node'];
 
$type = $node->type

 
// general node variables processing

  // preprocess by node type
 
if (function_exists($function = "phptemplate_preprocess_node_$type")) {
   
$function($node, $vars);
  }
}
?>

which lets me use a different preprocess function per node type, for example:

<?php
function phptemplate_preprocess_node_story($node, &$vars) {
 
// specific story variable processing
}
?>

 
 

Drupal is a registered trademark of Dries Buytaert.