4

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.

6
  • 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.
    – avpaderno
    Commented Mar 9, 2017 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. Commented Mar 9, 2017 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.
    – avpaderno
    Commented Mar 9, 2017 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.
    – avpaderno
    Commented Mar 9, 2017 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. Commented Mar 9, 2017 at 10:04

2 Answers 2

7

The code you are using doesn't work as expected because you first set $node->changed and then call node_save(), which sets $node->changed to REQUEST_TIME using the following code.

// 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(). For example, with the code you show, I would add the following line.

$node->release_change_date = strtotime($data->Release->LastChangeDate);

In hook_node_presave(), you would then use the following code.

$node->changed = $node->release_change_date
9
  • I think this is exactly what I'm looking for =) Commented Mar 9, 2017 at 10:25
  • 1
    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.
    – avpaderno
    Commented Mar 9, 2017 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. Commented Mar 9, 2017 at 10:27
  • This works as expected Commented Mar 9, 2017 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
    Commented Mar 20, 2018 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 and acknowledge you have read our privacy policy.

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