Enabling CAPTCHA support on webforms is more error-prone than it ought to be - several of the documented methods don't seem to work anymore due to possibly API changes. The following will enable support for all CAPTCHAs, might it be worth adding to the Webform module?

/**
 * Implementation of hook_captcha_default_points_alter().
 *
 * Enable CAPTCHA integration for all Webforms.
 */
function webform_captcha_default_points_alter(&$items) {
  // Get the list of supported Webform content types.
  $webform_types = webform_node_types();
  if (!empty($webform_types)) {
    // Get a list of all nid's for all supported webform content types.
    $webforms = array();
    $nodes = db_select('node')
      ->fields('node', array('nid'))
      ->condition('type', $webform_types)
      ->execute();
    foreach ($nodes as $node) {
      // Webform form IDs follow this format.
      $webforms[] = 'webform_client_form_' . $node->nid;
    }

    // Enable CAPTCHA integration for each form, if it isn't already enabled.
    foreach ($webforms as $form_id) {
      if (!isset($items[$form_id])) {
        $captcha = new stdClass;
        $captcha->disabled = FALSE;
        $captcha->api_version = 1;
        $captcha->form_id = $form_id;
        $captcha->module = '';
        // This may be 'node', 'default', 'captcha/Math',
        // 'recaptcha/reCAPTCHA', etc.
        $captcha->captcha_type = 'default';
        $items[$form_id] = $captcha;
      }
    }
  }
}
CommentFileSizeAuthor
#2 webform-n2569509-2.patch1.51 KBDamienMcKenna
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

DamienMcKenna created an issue. See original summary.

DamienMcKenna’s picture

Status: Active » Needs review
FileSize
1.51 KB

In patch form.

DanChadwick’s picture

Status: Needs review » Closed (works as designed)

I agree that the feature is desirable. When integration code is needed between two modules, I look to the installed base of the two modules. Are there more webform users that don't use captcha or vice versa? The installed base of captcha is about half that of webform. Therefore it would be better if this code were put into captcha.

Closing this issue for the context of the webform issue queue, but you might move it to the captcha issue queue and re-open it.

DamienMcKenna’s picture

Project: Webform » CAPTCHA
Version: 7.x-4.x-dev » 8.x-1.x-dev
Status: Closed (works as designed) » Active

In that case I'll move it there.

ddrozdik’s picture

Status: Active » Needs work

This patch is outdated. Needs re-roll.

naveenvalecha’s picture

Issue tags: +Needs reroll
Pradnya Pingat’s picture

Issue tags: -Needs reroll

This patch applied cleanly in webform module because the changes is in webform module. so removing reroll tag.

acbramley’s picture

Now that CaptchaPoints are config entities based on the form ID this won't work any more. There's also the case where the webform is referenced in a webform field from a node, those form IDs then contain the node id of the referencing node so it isn't viable to do an alter in this case.

I think a better solution would be for the Captcha module to provide a WebformElement plugin so users can simply add the element to any form they like. I might have a look at implementing this tomorrow.

borisson_’s picture

I think a better solution would be for the Captcha module to provide a WebformElement plugin so users can simply add the element to any form they like.

This sounds like a solid solution, has anyone tried pinging @jrockowitz to validate this approach?

Jax’s picture

Now that CaptchaPoints are config entities based on the form ID this won't work any more.

If webform would always provide a base_form_id webform_submission_webform_machine_name then this problem would be automatically fixed, I think.

class WebformSubmissionForm extends ContentEntityForm {
...
  public function getFormId() {
    $form_id = $this->entity->getEntityTypeId();
    if ($this->entity->getEntityType()->hasKey('bundle')) {
      $form_id .= '_' . $this->entity->bundle();
    }
    if ($source_entity = $this->entity->getSourceEntity()) {
      $form_id .= '_' . $source_entity->getEntityTypeId() . '_' . $source_entity->id();
    }
    if ($this->operation != 'default') {
      $form_id .= $this->operation;
    }
    return $form_id . '_form';
  }

I'll see if I can get this working, my D8 fu is limited.

Jax’s picture

If you add webform_submission_form as captcha point /admin/config/people/captcha/captcha-points the captcha will appear on all webforms.

That doesn't seem to work. Sorry.

jrockowitz’s picture

I think this should be integrated into the Webform for 8 as a third party setting. (similar to how Honeypot is setup).

The challenge/issue is that I don't think CAPTCHA is working great on multi-step forms.

jzavrl’s picture

I don't think we can fix the issue like this. Instead, I found a different issue #2839891: Allow to target the base_form_id which provides you with the option to use the base form ID. So you can only put in one webform ID and it will work for all.

Mike Dodd’s picture

any one have any luck with getting this to work in D8

jzavrl’s picture

@Mike Dodd, have a look at #13.

acbramley’s picture

Funnily enough, I just discovered today that Webform does already provide an element for Captcha integration this issue should probably be closed as anyone can add these elements to any webform already?

jzavrl’s picture

Yes, you can. There is an element available in the builder. Although the functionality is limited to what Webform as a module is providing as far as I know. Not sure if you can use that to add in reCAPTCHA for example.

acbramley’s picture

@jzavrl you can :) The element lets you choose the challenge type. The only issue I've found with it so far is #2886323: Captcha element does not hide for users with the skip CAPTCHA permission

jzavrl’s picture

Status: Needs work » Closed (duplicate)

Ah I see. Well in that case we have a workaround to provide CAPTCHA for each Webform separately, an issue which provides us with a base form ID and another issue which in not related to this directly. I think we can close this issue mainly because of #2839891: Allow to target the base_form_id.