2

I am creating nodes programatically based on the feed from an external api. I have managed to create all nodes, assign field values and also set the created date. Now my problem is that I also need to set the changed date of each node to match the value returned from the feed. I have tried to set this value before saving the node without any success:

// $data contains the release information used to create and populate the node
$node = new stdClass();
$node->title = $data->Release->Title;
$node->type = 'release';
node_object_prepare($node);
$node->status = NODE_PUBLISHED;
$node->uid = 1;
$node->language = LANGUAGE_NONE;

// handle any field data - not really important
handleFields($node, $data);

// submit the node
$node = node_submit($node);

$node->created = strtotime($data->Release->PublishDate);
// here I'm trying to set the changed value for the node
$node->changed = strtotime($data->Release->LastChangeDate);

// finally save the node
node_save($node);

Would be nice if anyone have a solution to this problem. Perhaps I can make a raw query against the database in order to update the changed date of the node? The reason I need to set this value is because later on it will be used to compare against the modification date of a release in the feed so I can decide if the node needs to be updated or not. I know I could use a custom field for this purpose, storing the releases modification time and then compare against this value instead of the changed column in the node table.

  • Do you get any error, using that code? Drupal itself uses $node->changed, so the problem is not surely using that instead of something else. – kiamlaluno Mar 9 '17 at 8:26
  • @kiamlaluno - Nope I don't get any error. It just seems like drupal is not taking this custom value into account when saving the node. I know that drupal is using the changed column, but I don't understand why I may set the created but not the changed date? Not really sure what you mean by "so the problem is not surely using that instead of something else"? The reason I need to set the modification date is so that I later on can compare it against the modification date from the feed and decide if I need to update the node or not. I know this can be solved by using a separate field. – Cyclonecode Mar 9 '17 at 9:26
  • As side note, you can avoid calling node_submit(), since it just sets $node->uid and $node->created, which is something your code already does. – kiamlaluno Mar 9 '17 at 9:59
  • I mean that using $node->created is correct; it's not that you need to use, for example, $node->timestamp instead of $node->created. As for not using the value you set for $node->created, that could depend from what other modules do. It could be a module is changing its value. For sure, Drupal core sets $node->created, so setting it is correct. – kiamlaluno Mar 9 '17 at 10:03
  • 1
    @kiamlaluno - The problem is not the created date - I can set this without any problems as long as I do so after calling node_submit(). The problem is the changed date which I'm not able to set at the moment. – Cyclonecode Mar 9 '17 at 10:04
4

The code you are using doesn't work as expected because you are first setting $node->changed, and then calling node_save(), which then unconditionally sets its value.

The code it uses is the following one.

// Set the timestamp fields.
if (empty($node->created)) {
  $node->created = REQUEST_TIME;
}
// The changed timestamp is always updated for bookkeeping purposes,
// for example: revisions, searching, etc.
$node->changed = REQUEST_TIME;

$node->timestamp = REQUEST_TIME;
$update_node = TRUE;

// Let modules modify the node before it is saved to the database.
module_invoke_all('node_presave', $node);
module_invoke_all('entity_presave', $node, 'node');

If you want to set $node->changed, you would need to implement hook_node_presave(), which is invoked right after node_save() sets $node->changed.
For example, in the code you are showing, I would add $node->release_change_date = strtotime($data->Release->LastChangeDate);; your implementation of hook_node_presave() would then use $node->release_change_date to set $node->changed ($node->changed = $node->release_change_date).

  • I think this is exactly what I'm looking for =) – Cyclonecode Mar 9 '17 at 10:25
  • I would expect that Drupal first checks $node->changed is set, before setting it itself, as it does with $node->created. I find strange the decision of verifying a value is already set, but not doing the same for the other value. – kiamlaluno Mar 9 '17 at 10:26
  • 1
    Yes that was what I was thinking. But for some reason it does not so I will try to implement hook_node_presave() to store the modification date correctly. – Cyclonecode Mar 9 '17 at 10:27
  • This works as expected – Cyclonecode Mar 9 '17 at 16:38
  • 1
    "I would expect that Drupal first checks $node->changed is set" - The problem there is that a loaded node arrives with $node->changed already set. If the changed date was only set when there was no changed date set, the changed date would not change after node creation. – KingAndy Mar 20 '18 at 11:42
0

For drupal 7:

$update_node = node_load($nid_to_change);
$update_node->changed = $timestamp_in_unix_form;
drupal_write_record('node', $update_node, 'nid');

This is very dumb routine; it's bypassing a lot of error checking in node_save(). It expects a complete, intact node. so it's up to you to make sure the node integrity is good. Otherwise you risk corrupting your database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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