3

I'm creating a custom module which adds a submit handler to a form. The idea is that it checks whether a hidden "honeytrap" field has been filled in.

If the field has been filled in, a success message is shown, but the form content is not e-mailed. If the field has not been filled in, the form is submitted as normal.

I don't want to use a form validator here (so this answer on DSE is unfortunately no use). I want the spam robot to think that the form has been submitted, so that it doesn't try again and learn about my special field.

At present, I have the following code:

function par_report_repair_form_webform_client_form_26_alter(&$form, &$form_state, $form_id)
{
    array_unshift($form['#submit'], 'honeytrap_submit_handler');
}

function honeytrap_submit_handler($form, $form_state)
{
    // what goes here?
}

I'm not clear what to put in my submit handler. I'd like the following behaviour:

  • If the honeytrap field has been filled in, display a "success" message but don't allow any additional handlers to run
  • If the honeytrap field hasn't been filled in, continue as normal.

Any suggestions? I've tried simply setting $form['#submit'] to be an empty array, but that didn't help.

1 Answer 1

5

By the time your submit handler is running you cannot change the other submit handlers that are running.

What you could do is make sure your form alter runs last (change the weight of your drupal module in your install file to a highier number to make it run later). That way you can be a bit more sure that no one else is adding submit handlers after your form alter.

Then in your form alter do something like this:

// Add the original submit handlers to the form state for us to use later.
$form_state['original_submit_handlers'] = $form['#submit'];
// Replace the original submit handlers with out own.
$form['#submit'] = array('honeytrap_submit_handler');

Then in your submit handler:

if (honey_trap_fails) {
  // Do whatever, but don't call the original submit handlers.
}
else {
  // Do whatever, and then:
  // Call the original submit handler because it was a successful submission.
  // Replacing yours as it has already been called.
  $form['#submit'] = $form_state['original_submit_handlers'];
  form_execute_handlers('submit', $form, $form_state);
}

There is something important to take into account here: If there are submit handlers on the button that was clicked then they will take precedence over submit functions attached to the form. See form_execute_handlers() for a bit of further insight on how to handle button submit handlers.

6
  • Also consider hook_module_implements_alter to adjust when your form_alter hook runs relative to other modules. api.drupal.org/api/drupal/modules!system!system.api.php/… Commented Apr 30, 2013 at 12:48
  • Nice one, that's a good addition.
    – rooby
    Commented Apr 30, 2013 at 12:52
  • This almost does it, but there's a problem when honeytrap isn't triggered (i.e. when the original handlers are called): The form alter function (par_report_repair_form_webform_client_form_26_alter in my case) is called not only when the form loads but also when it's submitted. This means that the honeytrap function is added again and we get infinite recursion: honeytrap_submit_handler() followed by form_execute_handlers() followed by honeytrap_submit_handler() ... Really appreciate your help so far, we're definitely getting there! Any ideas about this bit?
    – Sam
    Commented Apr 30, 2013 at 15:18
  • Ah, I've solved that issue: Replace $form_state['#submit'] = $form_state['original_submit_handlers']; with $form['#submit'] = $form_state['original_submit_handlers'];
    – Sam
    Commented May 7, 2013 at 11:22
  • 1
    You can also use: $form_state['submit_handlers']; Commented Nov 25, 2015 at 23:10

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.