node_load() during signup's node_save() breaks node data cached by CCK

markus_petrux - October 15, 2009 - 16:29
Project:Signup
Version:6.x-1.0-rc6
Component:Code
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review
Description

Here's an issue that has been bugging for a while.

I'm using filefiels_paths for an imagefield where the filepath uses a custom token. This means that filefield_paths will move the file to the final location and update the record in the {file} table to reflect the new filepath.

On the other hand, during node_load(), CCK caches the data of the fields, and it happens that filefield loads the record of the {file} table here, which is then cached by CCK.

When a node is updated, CCK clears the cache entry, but when a node is created, if something in your system causes a node load after the node has been saved by node module, but before filefield_paths updates the record in the {file} table, it will happen that this node_load() will make CCK cache an incorrect version of the file data, because it has not been updated yet by fieldfield_paths.

The solution to this is pretty simple. Just make sure the CCK cached version of the node is cleared if filefield_paths_file_move() succeeds.

I'm not 100% sure this is the best way to fix, but a quick one is:

<?php
      
if (filefield_paths_file_move($file)) {
+       
cache_clear_all('content:'. $node->nid .':'. $node->vid, content_cache_tablename());
?>

I don't know what causes a node_load() between the node has been created and this step in filefield_paths, but it seems to me it was signup module in my case, in signup_save_node(). I guess it could also happen from other modules, so this is why I'm reporting this here. If the CCK cache is cleared here, then no matter if other modules do a node_load() for whatever reason.

#1

markus_petrux - October 15, 2009 - 20:04
Project:FileField Paths» Signup
Version:6.x-1.3» 6.x-1.0-rc6
Status:active» needs review

Actually, the fix above does not work because signup executes after filefield_paths module, so the node_load() performed by signup module causes the node data to be cached by CCK after the fix above happens.

I'm moving this issue to the signup queue, as I have finally found a method to fix this in that module. I'm using 6.x-1.0-rc6 of signup module, and the following change to signup/includes/node_form.inc, function signup_save_node() fixed the issue here:

<?php
   $node
= node_load($node->nid);
+  if (
module_exists('content')) {
+   
cache_clear_all('content:'. $node->nid .':'. $node->vid, content_cache_tablename());
+  }
   if (
_signup_node_completed($node) && !empty($node->signup_status)) {
?>

In the meantime, I'm using a custom module that I use for hacks, that has a weight higher than other modules, and here I'm implementing the following hook_nodeapi(), that also works:

<?php
/**
* Implementation of hook_nodeapi().
*/
function MODULE_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch (
$op) {
    case
'insert':
    case
'update':
     
// Ensure content cache is cleared to account for changes in {file}
      // records when these have been updated by filefield_paths module
      // using tokens, broken by signup module doing a node_load() during
      // a node_save() operation.
      // See http ://drupal.org/node/605594
     
cache_clear_all('content:'. $node->nid .':'. $node->vid, content_cache_tablename());
      break;
  }
}
?>

#2

markus_petrux - October 15, 2009 - 20:05
Title:Clear content cache after updating {file} data» node_load() during signup's node_save() breaks node data cached by CCK

Adjusting issue title.

#3

Oliver Coleman - October 26, 2009 - 00:03

Wow, this is nasty... I have several different content types with various types of CCK fields, and whenever trying to create a new node for any of those types (regardless of whether they were signup enabled) the CCK fields wouldn't save (but would when editing them).

The first patch in #1 seems to have fixed the problem, thanks!

 
 

Drupal is a registered trademark of Dries Buytaert.