Trying to understand hook_nodeapi() invocation sequence from node.module
Good morning! I've run into some odd behavior from node.module in Drupal HEAD (updated as of 2005-11-23 at about 2300 UTC). I'm not reporting an "issue" on the module yet, because I strongly suspect the "problem" is ignorance on my part rather than a bug in the core code. I have a module that adds extra fields to node edit screens, similar to the way the upload.module does. The difference is that my module can have zero, one, or more instances of my custom fields, and I've got code that examines how many are defined and always ensures that all the existing ones are shown plus one blank one, on each preview or initial entry into the Edit page for an existing node. The particulars of my code aren't really relevant, and I'm not asking for help debugging that. Instead, what I'm seeking is to understand why hook_nodeapi() is being invoked in the particular sequence that I'm seeing. I have the following trace enabled in my hook_nodeapi() implementation: function mymodule_nodeapi(&$node, $op, $teaser=NULL, $page=NULL) { // DEBUG: Extra trace logic drupal_set_message("nodeapi $op $node->nid"); switch($op) { // .... the usual stuff here } } Now, on initial entry into the edit form on node with $nid == 8, here is the output of that drupal_set_message(): nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8 And on a "preview" of the node after editing, I see this: nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8 nodeapi validate 8 nodeapi view 8 nodeapi validate 8 My question is, why is $op=='load' being always invoked twice, and why is $op=='validate' being invoked twice for previews? The problem I'm having with *my* logic has to do with that second invocation of "load", and I'm finding that I have to build explicit conditional logic in the load function to detect whether I've already done it before. It seems to me that represents extra database hits, if nothing else, and in my particular case a design obstacle as well. I've checked the documentation for hook_nodeapi(), but it doesn't seem to be fully updated for 4.7 yet, and also doesn't really talk about the *sequence* of calls to the function, but rather treats each one individually. Can someone offer some general commentary on how this is supposed to work in 4.7? I suspect I'm not the only one who's confused. Or if I've overlooked it in the docs, please point me to a page, and I'll cheerfully apologize for wasting your time. I did try to RTFM before asking on list, but I may have missed something. Many thanks! Scott -- ------------------------------------------------------------------------------- Scott Courtney Drupal user name: "syscrusher" http://drupal.org/user/9184 scott at 4th dot com Drupal projects: http://drupal.org/project/user/9184 Sandbox: http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/syscrusher
On Thursday 24 November 2005 11:20, Syscrusher wrote:
Now, on initial entry into the edit form on node with $nid == 8, here is the output of that drupal_set_message():
nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8
And on a "preview" of the node after editing, I see this:
nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8 nodeapi validate 8 nodeapi view 8 nodeapi validate 8
My question is, why is $op=='load' being always invoked twice, and why is $op=='validate' being invoked twice for previews?
After examining the code in node.module, I've found what I think is the cause of this behavior, but I'm still not sure why it's done this way. At line 370, in function node_load(), we see the following: if ($node->nid) { // Call the node specific callback (if any) and piggy-back the // results to the node or overwrite some values. if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) { $node->$key = $value; } } if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) { $node->$key = $value; } } My module doesn't define a new node type, but just adds fields to existing types, so it doesn't define its own hook_load() function. Thus, the call to node_invoke($node, 'load') ends up calling node_load recursively, I think. Thus, the second recursion may be calling my module's hook_nodeapi() function again for each load. I'd still be curious to understand better what's going on here. Thanks for any comments. Scott -- ------------------------------------------------------------------------------- Scott Courtney Drupal user name: "syscrusher" http://drupal.org/user/9184 scott at 4th dot com Drupal projects: http://drupal.org/project/user/9184 Sandbox: http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/syscrusher
Also do a debug_backtrace() call on the extra logging line, and log that one too, so that you see from where you get called. That singles out the exact cause of the problem. This is surely a bug which should be fixed. Goba Syscrusher wrote:
On Thursday 24 November 2005 11:20, Syscrusher wrote:
Now, on initial entry into the edit form on node with $nid == 8, here is the output of that drupal_set_message():
nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8
And on a "preview" of the node after editing, I see this:
nodeapi load 8 nodeapi load 8 nodeapi prepare 8 nodeapi form 8 nodeapi validate 8 nodeapi view 8 nodeapi validate 8
My question is, why is $op=='load' being always invoked twice, and why is $op=='validate' being invoked twice for previews?
After examining the code in node.module, I've found what I think is the cause of this behavior, but I'm still not sure why it's done this way.
At line 370, in function node_load(), we see the following:
if ($node->nid) { // Call the node specific callback (if any) and piggy-back the // results to the node or overwrite some values. if ($extra = node_invoke($node, 'load')) { foreach ($extra as $key => $value) { $node->$key = $value; } }
if ($extra = node_invoke_nodeapi($node, 'load')) { foreach ($extra as $key => $value) { $node->$key = $value; } }
My module doesn't define a new node type, but just adds fields to existing types, so it doesn't define its own hook_load() function. Thus, the call to node_invoke($node, 'load') ends up calling node_load recursively, I think. Thus, the second recursion may be calling my module's hook_nodeapi() function again for each load.
I'd still be curious to understand better what's going on here.
Thanks for any comments.
Scott
And on a "preview" of the node after editing, I see this:
nodeapi load 8
node_menu
nodeapi load 8
node_page op'edit'
nodeapi prepare 8
node_object_prepare
nodeapi form 8
node_form()
nodeapi validate 8
drupal_get_form
nodeapi view 8 nodeapi validate 8
These should be reversed, you sure not mixed them? See node_form_add_preview, _validate is called before viewing. Regards NK
On Saturday 26 November 2005 20:12, Karoly Negyesi wrote:
And on a "preview" of the node after editing, I see this:
nodeapi load 8
node_menu
nodeapi load 8
node_page op'edit'
[....] Just wanted to say thanks to you and Goba for the replies...I got busy in my work life and haven't had a chance to try these suggestions yet, but will do so ASAP. Scott -- ------------------------------------------------------------------------------- Scott Courtney Drupal user name: "syscrusher" http://drupal.org/user/9184 scott at 4th dot com Drupal projects: http://drupal.org/project/user/9184 Sandbox: http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/syscrusher
participants (3)
-
Gabor Hojtsy -
Karoly Negyesi -
Syscrusher