Hello,

I've encountered some odd behaviour related to node_load and user reference fields with multiple values. Unfortunately I haven't found a succinct way to explain it, so please bear with me.

I have a module with two functions and a cron hook.

The first function (which, for clarity, I'll refer to as "Function 1") creates a node with a specific title if that node does not already exist. The node's type is a custom one (created using CCK) with a user reference field. Function 1 ignores the user reference field when creating the node, which results in that field being assigned a null value when the node is saved.

The second function ("Function 2") loads the specific node (whether it was created during the current cron run or not), and adds a specific user reference to any existing user references if the specific user it's trying to add isn't already referred to.

In the cron hook of the module, Function 1 is called once, and Function 2 is called twice, each time with a different user but on the same node. In pseudo-code, it looks something like:

function Function 1 ($title_of_node_to_create){
  if (node with title $title_of_node_to_create exists){
    // Do nothing
  }
  else{
    $node->title = $title_of_node_to_create;
    Save the node (using node_validate, node_submit, and node_save).
  }
}

function Function 2 ($user_id,$title_of_node_to_add_user_reference_to){
Load node with title $title_of_node_to... (using node_load).
  if (uid $user_id is not listed in the array for the user reference field){
    Insert reference into the array for the user refernce field.
    Save the node.
  }
}

function module_name_cron(){
  Function 1('Test node');
  Function 2('123','Test node');
  Function 2('456','Test node');
}

Theoretically, after cron is run once with this module enabled, a node should be created and it should have two user references. However, what actually happens is this:

First cron run: The node is created. Only the second user reference, i.e. the reference to the user with a uid of 456, actually gets stored.
Second cron run: The node isn't created (since it already exists; this is correct). Now, the first user reference is stored, and the second user isn't added again because Function 2 recognizes that their uid is already in the array for the user reference field.
Third cron run: Nothing happens because the node already exists and both user references are stored.

After using print_r to look at the array for the user reference field in a few different places, it seems that node_save and node_load act rather strangely when it comes to user reference fields: if a node is loaded, its user reference field is altered, and the node is saved, if it is loaded again, the node object returned will not reflect the changes made to the user reference field. However, once the cron run ends, if the node is viewed via the browser, the user reference field will reflect the changes. If cron is then run again, when the node is loaded its user reference field will reflect the changes made by the last node_save call in the previous cron, and so on. This is why adding two user references (each with a separate load, edit, and save cycle) takes two cron runs instead of one (the second time Function 2 is called, it loads a version of the node without the user reference added by the first call of Function 2, so when it saves the node in the first cron run only the reference to user 456 is present).

Does anyone know if there's a way around this behaviour? I saw some older threads regarding node_load and node references not getting stored, but they were for version 4 of Drupal and didn't seem to be relevant to this issue.

Anyhow, sorry about this lengthy support request; any assistance with this issue would be very much appreciated.

Comments

dopry’s picture

Status: Active » Closed (fixed)

You need to examine the form_processing for the field and the data returned to nodeapi by content.module when a node is created... I suggest looking into content_nodeapi and working your way through the node life cycle that way... What is loaded is not always what is saved. The hook_field transforms the data on load and on save...