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.

| improve this question | | | | |

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.

| improve this answer | | | | |
  • 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/… – Alfred Armstrong Apr 30 '13 at 12:48
  • Nice one, that's a good addition. – rooby Apr 30 '13 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 Apr 30 '13 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 May 7 '13 at 11:22
  • 1
    You can also use: $form_state['submit_handlers']; – masterchief Nov 25 '15 at 23:10

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.