Emulate "preprocess" theme functions

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 when the template function starts to become unmanageable

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;
}
?>

Note:Thanks Nate! (modified slightly so specify theme name in a var)

Further enhancements

Adding 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 let us 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.