so close, but so far, with hook_preprocess_node()

Events happening in the community are now at Drupal community events on www.drupal.org.
bryanhirsch's picture

Thanks everyone for your thoughts and suggestions at last night's meetup. I'm very close to a solving the problem I showed you. But I'm still missing a step (a function I think). Any help would be greatly appreciated.

Recap of problem:

I'm calling hook_nodeapi() to re-arrange weights of things like this...

$node->content['video']['#weight'] = 0;
$node->content['map']['#weight'] = 1;
$node->content['pic']['#weight'] = 2;
$node->content['body']['#weight'] = 3;

Then, something comes along and resets the weight of my body to 0, which is messing up the order of things on my node pages.

Solution: hook_preprocess_node()

The solution suggested last night was to use hook_preprocess_node(). Please see my notes in the code below to see where I'm hung up inside this new, exciting hook....


mymodule_preprocess_node(&$vars) {

   // This gets me back to $node->content with all the weights as I want them.
  $vars['node']->content['body']['#weight'] = 3;  
 
  // My problem is that Drupal seems to be done with $vars['node']->content.
  // $vars['content'] is what is getting printed. So I think I need to do something like this...
  $node = $vars['node'];
  $new_content = some_function($node->content); // re-generate the HTML from $node->content
  $vars['content'] = $new_content;

}

I feel certain that "some_function()" exists. Does anyone know it's name? Or am I barking up the wrong tree here?

Bryan

(A side note: hook_preprocess_node(), seems really powerful. But I don't see documentation about it at api.drupal.org. Strange. Am I missing something?)

Comments

some_function() is

moshe weitzman's picture

some_function() is drupal_render().

re-rendering node content twice smells pretty bad from a performance point of view.

victory!

bryanhirsch's picture

Thanks Moshe.

I definitely don't want performance to stink. Glad you flagged this.

I think I've arrived at a solution. Here's what I'm doing now, in case this is useful to anybody (my module's name is sws):

function sws_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch($op) {
    case 'view':
      if ($a4) { // page view
        $node->content['sws_body'] = $node->content['body'];
        $node->content['sws_body']['#weight'] = 3;
        $node->content['body']['#value'] = '';
   .
   .
   .

This way it doesn't matter if other modules change the weight of $node->content['body'], because there's no content there. The content I care about holds onto weight 3.

I thought about doing this...

    unset($node->content['body']);

...rather than this...
    $node->content['body']['#value'] = '';

...but I decided against it, in case any modules I install later need to use $node->content['body'] for anything.

Umm?

nancydru's picture

Why not set the other weights negative and just assume the body will always be 0 (or more usually, not set at all). That's what would happen if you used CCK to rearrange fields.

template_preprocess_node

barraponto's picture

It is documented, but its name is template_preprocess_node. And while modules can implement template_preprocess_*, it can be implemented in the theme's template.php and the theme's implementation will be the last one to run (overriding variables set in modules' implementations).

Boston

Group categories

More Specifically

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: