0

This is the first time I've tried to do this so I may be missing something really obvious. I'm developing a module which uses hook_node_insert() to catch the creation of a node, and puts the node into Drupal Queue for later treatment by a cron process.

At the end of the process, I want to update a field in the node and save it. I've tried using entity_metadata_wrapper as well as node_save, but in both cases I get an error "PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '3011' for key 'PRIMARY': INSERT INTO {node}....". Apparently, Drupal is unaware that the node exists already despite the fact that $node->nid is set (which is why we get a duplicate entry integrity constraint).

Looking at the node_save() code, it certainly seems to be supposed to check and load the node first if the nid is set (which it is - I've followed this step by step in debug). I must be doing something wrong, but what?

Here is the code from hook_node_insert which queues the node for treatment:

if ($node->type == "sms_message") {
  $queue = DrupalQueue::get('sms_message');
  $node_wrapper = entity_metadata_wrapper('node', $node);
  $node_wrapper->field_queued->set(1);
  drupal_set_message($node_wrapper->label() . ' has been queued');
  $queue->createItem($node);
}

And here is the relevant code from the callback module for hook_cron_queue_info

function sms_textlocal_outgoing($node) {
  global $user;
  $user = user_load(1);
  $node_wrapper = entity_metadata_wrapper('node', $node);
  $message = $node_wrapper->field_sms->value();
  $sms_sent = 0;
// Then we do some processing...
  $node_wrapper->field_sms_sent->set($sms_sent);
  node_save($node);

I've also tried:

$node_wrapper->save();

instead of node_save, but with the same result.

2 Answers 2

0

please see the documentation of the hook https://api.drupal.org/api/drupal/modules!node!node.api.php/function/hook_node_insert/7

Notice that it says that the hook is invoked (i.e. triggered) by node_save and that means that the data is NOT yet written in the database! so you essentially create an infinite loop.

Try to do something like $node->yourfield['und'][0]['value']= 'yourvalue_here' and DO NOT call node_save again. Also do not use a wrapper because in this case only adds complexity. Notice that if you dont use the wrapper you must provide the langauage (['und'] in my example) the number of the item ([0] ie the first one in my example) and the key of the table that stores the value (['value'] in my example). This is done automatically when you re using an entity wrapper but since your node is not ready yet it is not the best option because you clone the object by value and not by reference and then even if you change it the changes are not reflected in the original one that will be fed into the database.

1
  • I'm not sure you've understood the question. Please note that there are two quite different moments in the process. The first is the implementation of hook_node_insert - this actually works fine. The problem occurs when the cron process is run - by this time the node has been saved ok and I am just trying to change one field value. The node is certainly in the database because I have a NID (in fact my problem is that it is trying to save instead of update)
    – Martin K
    Commented Nov 22, 2015 at 19:37
0

In fact, the problem seems to be due to the fact that the node had not been loaded prior to node_save(). It's a bit of a shame - I had despatched the entire node to the queue in the hopes that the Drupal Queue callback function would just be able to take the node off the queue and update it direct, but apparently not.

So, this worked:

function sms_textlocal_outgoing($node) {
  global $user;
  $user = user_load(1);
  $node_upd = node_load($node->nid);
  $node_wrapper = entity_metadata_wrapper('node', $node_upd);
  $message = $node_wrapper->field_sms->value();
  $sms_sent = 0;
// Then we do some processing...
  $node_wrapper->field_sms_sent->set($sms_sent);
  $node_wrapper->save();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.