I noticed the Drupal 6 theme API enphasizes preprocess hooks as a way to customize behavior. It used to be possble to change the output after the template produced it. Now, I can't find a way to do this sort of "postprocessing". Help!

Here's an example of a theme_page override from Drupal 5. How can I do this in Drupal 6?

// Drupal 5 code takes the output produced by page.tpl.php, then munges it...
function fb_fbml_page($content, $show_blocks = TRUE) {
  $output = phptemplate_page($content, $show_blocks);
  
  if (function_exists('fb_canvas_process')) {
	$output = fb_canvas_process($output);
  }
  return $output;
  
}

Comments

Dave Cohen’s picture

(and yes I know how to spell emphasizes. Just noticed my typo but I can't go back and edit it)

Dave Cohen’s picture

Thanks to Earl Miles for pointing me in the right direction. This code seems to be working. (But stands little chance of working in subsequent versions of Drupal).


function fb_fbml_page($content, $show_blocks = TRUE, $show_messages = TRUE) {
  $variables = array('template_files' => array(),
					 'content' => $content,
					 'show_blocks' => $show_blocks,
					 'show_messages' => $show_messages,
					 );
  $hook = 'page';
  template_preprocess($variables, $hook);
  template_preprocess_page($variables, $hook);
  // If any modules implement a preprocess function, they're SOL, we don't know about it.

  $template_file = path_to_theme() . '/page.tpl.php';
  $output = theme_render_template($template_file, $variables);
  
  if (function_exists('fb_canvas_process')) {
	$output = fb_canvas_process($output);
  }
  return $output;
}
gpk’s picture

Subscribe.

>stands little chance of working in subsequent versions of Drupal
But something like it should surely? Looks like this nifty bit of code is just emulating the behaviour of theme('page', ...) and adding your postprocessing at the end.

gpk
----
www.alexoria.co.uk

dvessel’s picture

This will work too. It might take a tiny performance hit since the render function is intercepted for all templated hooks but it should be very minor.

A big plus on this is that you can sneak in any number of "post process" functions for any hook without recreating the flow of the theme() function.


/**
 * "page" hook preprocess function.
 */
function THEMENAME_preprocess_page(&$vars) {
  // Set post process function.
  $vars['postprocess'] = 'fb_canvas_process';
}

/**
 * Intercepts the render function. It can be either the theme name or theme
 * engine the theme is running under. Theme name is recommended.
 */
function THEMENAME_render_template($file, $vars) {
  // Render output.
  $output = theme_render_template($file, $vars);

  // Check for post process function set from a preprocess function.
  if (isset($vars['postprocess']) && function_exists($vars['postprocess'])) {
    $output = call_user_func($vars['postprocess'], $output);
  }

  return $output;
}

joon park
www.dvessel.com

generalredneck’s picture

I don't know that this was the case in D6 but now in D7, you can't expect this to run always. render_template is only ever called when a file template is rendered... not a function template. Since most themes use functions these days as opposed to actual files, this causes the issue of missing the postprocess phase.

jduhls’s picture

I've spent about 8 hours researching the same question. Then I smacked my forehead. The template file should also be considered the "postprocess" function. My example is related to theming the user registration form. First you create a theme hook for the form:

<?php
function THEMENAME_theme(&$existing, $type, $theme, $path) {
	$hooks['user_register'] = array(
		'template' => 'templates/user-register', //this defines your tpl file
		'arguments' => array('form' => NULL)
	);
  return $hooks;
}
?>

...a "PREprocess" function is optional. Use this if you want to change or add vars to use in the tpl:

<?php
function THEMENAME_preprocess_user_register(&$vars) {
//edit/add vars
//the form is in $vars['form']
}
?>

...I then created user-register.tpl.php and did POSTprocessing on the $vars['form'], which is now just $form:

<?php
//POSTprocessesing stuff on $form
print drupal_render($form);
?>

It's actually quite elegant. Good luck, drupalers!

draenen’s picture

I object slightly to the elegant comment as it is frowned upon to put logic/processing in a template file. I think dvessel's method above is much more elegant and "Drupal-like" as it allows any module or theme to add postprocess functions to the render array.

--
Caleb Thorne
Developer | Monarch Digital
https://www.calebthorne.com