I have a module that tacks some stuff onto selected nodes. (Date Reminder, if you must know.) I've been racking my brain over a problem and I think I've figured out the problem, but not how to fix it.

The problem: Date Reminder uses a date field in the node. If the node is updated, changing the date field, Date Reminder needs to update some of its own state to reflect the node's new date. I implement hook_node_update() and update Date Reminder state if the node in question has a reminder set.

My problem: datereminder_node_update() gets called before the date field has been updated, so when it updates state it gets it wrong. The state is updated based on the old date field value rather than the new. Obviously, this leads to odd behavior.

Any suggestions how to deal with this? Is there a way to ensure that some action happens after the node and all of its content have been updated?

Comments

nevets’s picture

I wonder what your code look likes, the fields are saved before that hook is called. So $node passed to the hook, should reflect the updated value.

dwillcox’s picture

Buried a number of levels down within datereminder_node_update(), there's code that does:

   $field = $node->{$fieldname};

That's not the actual code, but that's what it does. $fieldname is the name of the date field in the node. It most definitely has the old data value in it at that point.

I'm not sure when field updates are done, but it's after my module was called. I think that the basic problem is that hook_node_update() is called before hook_entity_update(). I see the hack to alter the order of hooks within a group, but that doesn't help with changing the order of hooks.

nevets’s picture

node_save() has a call to update the fields, but it is possible some are handle by the call the hook_entity_update().

So what I would try is two fold, switch from using hook_node_update() to hook_entity_update() and in the system name change the weight of your module to a large positive number so it runs last (this last part can by done with myphpadmin, long term it is better to do it has part of the modules .install file).

dwillcox’s picture

I switched to hook_entity_update() and had also updated weight in the system table. (Aside: I'm surprised that there isn't a defined way to change the weight of your module other than patching the database.)

I also tried the hook_module_implements_alter() hack. No joy there, too.

The problem is, for a repeating field, the data values are an array in the node. I'm sure that the values in that array are derived and don't actually get written to the database, but whatever recomputes that list apparently isn't called on an node update.

Sigh. Getting too late. Real paying working in the morning. Must sleep.

Jaypan’s picture

Add a submit handler to the node form:

function my_module_form_alter(&$form, &$form_state, $form_id)
{
  if($form_id == 'some_node_form')
  {
    $form['actions']['submit']['#submit'][] = 'my_custom_handler';
  }
}

function my_custom_handler($form, &$form_state)
{
  // Do your custom stuff here
}
dwillcox’s picture

Actually, I'm already doing this since I'm also adding a form element there. That particular element doesn't depend on the modified date field so that hasn't been a problem.

But the submit happens long before hook_node_update() or hook_entity_update().

Jaypan’s picture

When you add a submit handler, it is called after all the node processing has been done - including hook_node_update() and hook_entity_update().

dwillcox’s picture

Not the first time I've had to say that. I shouldn't try to work on software late at night after a full workday.

Turns out my code was forgetting about the in-memory node object and was re-loading the node and looking in the reloaded node for the date value. And since this was before the date was actually written out, it had the old value.

Thanks for the replies everyone. If nothing else, I've learned some useful new things during this endeavor.