Current CVS documentation for hook_example_validate() includes the example

function node_example_validate(&$node) {
  [ ... if ($node->quantity) { ]
    // Let an empty field mean "zero."
    $node->quantity = 0;
  }
} 

But since 4.7 it looks like any changes to $node made in hook_validate are ignored. E.g. in modules/node/node.module we have

function node_validate($node, $form = array()) {
  ...
  node_invoke($node, 'validate', $form);
  node_invoke_nodeapi($node, 'validate', $form);
}

which is pass-by-value rather than pass-by-reference. So although node_invoke() passes by reference, no changes to $node can "escape" out of node_validate.

I'm guessing this is by design, but if so the documentation should say what to do instead. E.g. I *think* form_set_value() should now be used, but its a bit non-obvious. For example, I used something similar to the following elsewhere (in 4.7):

  form_set_value(array('#parents' => array('quantity')), 0);

Is this now the recommended route to change nodes? (or not?). Mark.

PS Looks like the change to validation operation in 4.7 also caused problems for node_import, which ideally should be able to validate a node without requiring a form to be present, so a documentation update might help getting validation working there too.

CommentFileSizeAuthor
#3 node_example.module.patch2.44 KBplumbley

Comments

plumbley’s picture

Title: hook_validate() should not change $node » Update needed to node_example.module

Renamed now I finally found out what I probably should have found much earlier about the 4.7 submit process (see e.g. http://drupal.org/node/22218#node_hook_order). Please ignore my previous rubbish about form_set_value().

It looks like node_example.module as appears in 4.7 at http://api.drupal.org/api/4.7/file/developer/examples/node_example.module and CVS at http://api.drupal.org/api/HEAD/file/developer/examples/node_example.module actually applies to 4.6, and is in need of update.

I'm still a bit new here but perhaps hook_validate() should now be pass-by-value and read e.g.:

function node_example_validate($node) {
  // If the field is set, it must be a number
  if (!empty($node->quantity) && !is_numeric($node->quantity)) {
    form_set_error('quantity', t('The quantity must be a number.'));
  }
}

with a new hook_submit() which performs the modification

function node_example_submit(&$node) {
  if (empty($node->quantity)) {
    // Let an empty field mean "zero."
    $node->quantity = 0;
  }
}

If its too fiddly to fix for the moment, perhaps just a note to say "node_example.module applies to 4.6, see http://api.drupal.org/api/4.7/file/developer/hooks/node.php for up to date documentation" in the meantime? Mark.

pwolanin’s picture

I think form_set_value *is* needed to chage a vlue at the validate sage, as opposed to being able to directly change the node in 4.6. I was just try to help someone figure this out recently: http://drupal.org/node/83130

plumbley’s picture

Status: Active » Needs review
StatusFileSize
new2.44 KB

OK, the attached patch corrects node_example.module for 4.7. I have not tested with HEAD, but I believe it should work with that too.

Main fix is to separate out the change to $node that was in hook_validate() into a new hook_submit(), as indicated above. I've tested this works with 4.7, but I don't have a working HEAD yet (as it were).

As a bonus, this patch also includes "E_ALL Compliance" fixes to remove PHP Notices. Many modules produce these on "create" forms by failing to check whether the default value is set yet, so it would be nice for node_example.module to do this as now recommended too.

Best wishes,

Mark.

dokumori’s picture

Project: Documentation » Drupal core
Version: » 7.x-dev
Component: Developer Guide » documentation

Changed the component to reflect the new component categorization. See http://drupal.org/node/301443
-dokumori

catch’s picture

Status: Needs review » Closed (won't fix)

4.7 is no longer supported.