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
some_function() is drupal_render().
re-rendering node content twice smells pretty bad from a performance point of view.
victory!
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?
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.
Nancy Dru
template_preprocess_node
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).