function hook_node_presave

You are here

7 node.api.php hook_node_presave($node)
8 node.api.php hook_node_presave(\Drupal\node\NodeInterface $node)

Act on a node being inserted or updated.

This hook is invoked from node_save() before the node is saved to the database.

Parameters

$node: The node that is being inserted or updated.

Related topics

5 functions implement hook_node_presave()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

book_node_presave in modules/book/book.module
Implements hook_node_presave().
entity_crud_hook_test_node_presave in modules/simpletest/tests/entity_crud_hook_test.module
Implements hook_node_presave().
forum_node_presave in modules/forum/forum.module
Implements hook_node_presave().
node_test_node_presave in modules/node/tests/node_test.module
Implements hook_node_presave().
trigger_node_presave in modules/trigger/trigger.module
Implements hook_node_presave().
3 invocations of hook_node_presave()
field_attach_presave in modules/field/field.attach.inc
Perform necessary operations just before fields data get saved.
node_save in modules/node/node.module
Saves changes to a node or adds a new node.
user_save in modules/user/user.module
Save changes to a user account or add a new user.

File

modules/node/node.api.php, line 684
Hooks provided by the Node module.

Code

function hook_node_presave($node) {
  if ($node->nid && $node->moderate) {
    // Reset votes when node is updated:
    $node->score = 0;
    $node->users = '';
    $node->votes = 0;
  }
}

Comments

You can access the original contents of the node at:

<?php
$node
->original
?>

maybe it's obvious, but $node->original will not exist for inserts.

How can I access original content in hook_node_validate. I want to through an error if value of a checkbox is newly selected. i-e shouldnt through error if already selected.

The example is wrong.
$node has to be returned in order to have an effect.

With PHP 5, objects passed as arguments for a function are passed by reference. The example is correct, since Drupal 7 requires PHP 5.

Altering the node variable is certainly having an effect on the data that is saved. This supports your statement, but why is the argument in the documentation not shown as "&$node" to indicate the passing of the reference?

Because objects passed as arguments in PHP5 are already passed by reference as default. I might be wrong but I think you actually get notices for marking an object as reference in a function declaration

Your interesting comment is not squaring with what I'm seeing in the PHP docs.

http://www.php.net/manual/en/language.references.pass.php

There is some commentary there on 'call time pass by reference', but if that's the way it's going down, it puts the syntax in this documentation into question again.

sorry... i didn't see the distinction at "objects" being passed by reference so the docs I posted are not relevant.

is there a way to prevent saving the node? (can't do form validate as this is not necessarily done on form submit)

A drupal_goto would probably short-circuit the save?

What about other module hooks that may have fired before *your* module that already acted on the node - possibly adding linked records in other tables? Using drupal_goto could leave orphaned records or a mismatched condition between fields in the node and data in other tables.

You'd probably need to get at it well before it reaches hook_presave().

Try using hook_form_alter() to intercept the node form, and changing $form['actions']['submit']['#submit'][0] from node_form_submit to a custom function that can then do whatever you want with the node submission (including conditionally passing it off to node_form_submit() if you DO want it saved).

Note that bypassing the normal node_form_submit() will mean that NOTHING happens, not even returning you to the node view (you'll just land on the edit form again) so if you want that to happen you'll need to do it yourself (look to node_form_submit() for details on how to accomplish any of the normal actions.)

Here's an example that would prevent saving of a node:

<?php
function MODULE_form_alter(&$form, &$form_state, $form_id){
  if(
$form_id == 'CONTENTTYPE_node_form' ){
   
$form['actions']['submit']['#submit'][0] = 'MODULE_my_custom_submit_handler';
  }
}
?>
<?php
function MODULE_my_custom_submit_handler($form, &$form_state){
 
// do nothing.. or something...
}
?>

Don't use drupal_goto() if you're importing multiple nodes. If you're using something like Feeds it will cause problems and prevent subsequent nodes from importing. Instead just thrown an error during presave, i.e.:

function mymodule_node_presave($node){
  if(empty($node->title)){
    throw new Exception('Error saving node: Title cannot be empty');
  }
}

The node_save() function has a try...catch block wrapping the presave step that will catch the exception. Any further processes will continue as normal, such as saving the next node.

A cool thing about this hook is that it fires both on node save and node update, so if you need to do something both on the creation and the updating of a node, in most cases you can just implement this hook instead of separate hook_node_insert() and hook_node_update() implementations. (Just be aware this hook fires earlier in the node saving process than the other two - consult the code of node_save() if it might make a difference in your case.)

Simple example of the use of this hook to force first char to uppercase

/**
* Implementation of hook_node_presave().
*
*/

function CUSTOM_MODULE_node_presave($node) {
    $node->title = ucfirst($node->title);
}

This works well:

<?php

function mymodule_node_presave() {
 
$var = $node->original->field_my_field['und'][0]['value'];
  if (
$var == 'something') {do_something();}
}
?>

I would like to access original property with Entity Metadata Wrapper, like explained in entity_test.module:

<?php
function mymodule_node_presave() {
 
$wrap = entity_metadata_wrapper('node', $node);
 
$var = $wrap->original->field_my_field->value();
  if (
$var == 'something') {do_something();}
}
?>

but I get this error:

EntityMetadataWrapperException: Unknown data property original. in EntityStructureWrapper->getPropertyInfo()

Some suggestions?