You are here

function captcha_form_alter in CAPTCHA 8

Same name and namespace in other branches
  1. 5.3 captcha.module \captcha_form_alter()
  2. 6.2 captcha.module \captcha_form_alter()
  3. 6 captcha.module \captcha_form_alter()
  4. 7 captcha.module \captcha_form_alter()

Implements hook_form_alter().

This function adds a CAPTCHA to forms for untrusted users if needed and adds. CAPTCHA administration links for site administrators if this option is enabled.

File

./captcha.module, line 162
This module enables basic CAPTCHA functionality.

Code

function captcha_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  $account = \Drupal::currentUser();
  $config = \Drupal::config('captcha.settings');
  $captchaService = \Drupal::service('captcha.helper');

  // Visitor does not have permission to skip CAPTCHAs.
  module_load_include('inc', 'captcha');
  if (!$account
    ->hasPermission('skip CAPTCHA')) {
    $query = \Drupal::entityQuery('captcha_point');
    $query
      ->condition('label', $form_id);
    $entity_ids = $query
      ->execute();

    // If empty, see if it is a form provided by default config.
    if (empty($entity_ids)) {
      $query = \Drupal::entityQuery('captcha_point');
      $query
        ->condition('formId', $form_id);
      $entity_ids = $query
        ->execute();
    }
    if (!empty($entity_ids) && is_array($entity_ids)) {
      $captcha_point_id = array_pop($entity_ids);

      /* @var CaptchaPoint $captcha_point */
      $captcha_point = \Drupal::entityTypeManager()
        ->getStorage('captcha_point')
        ->load($captcha_point_id);
    }

    // If there is no CaptchaPoint for the form_id, try to use the base_form_id.
    if (empty($captcha_point) || !$captcha_point
      ->status()) {
      $form_object = $form_state
        ->getFormObject();
      if ($form_object instanceof BaseFormIdInterface) {
        $base_form_id = $form_object
          ->getBaseFormId();
        if (!empty($base_form_id) && $base_form_id != $form_id) {
          $captcha_point = \Drupal::entityTypeManager()
            ->getStorage('captcha_point')
            ->load($base_form_id);
        }
      }
    }
    if (empty($captcha_point) && $config
      ->get('enabled_default')) {

      // Create fake captcha point without saving.
      $captcha_point = new CaptchaPoint([
        'formId' => $form_id,
        'captchaType' => $config
          ->get('default_challenge'),
      ], 'captcha_point');
      $captcha_point
        ->enable();
    }
    if (!empty($captcha_point) && $captcha_point
      ->status()) {

      // Build CAPTCHA form element.
      $captcha_element = [
        '#type' => 'captcha',
        '#captcha_type' => $captcha_point
          ->getCaptchaType(),
      ];

      // Add a CAPTCHA description if required.
      if ($config
        ->get('add_captcha_description')) {
        $captcha_element['#description'] = _captcha_get_description();
      }

      // Get placement in form and insert in form.
      $captcha_placement = _captcha_get_captcha_placement($form_id, $form);
      $captchaService
        ->insertCaptchaElement($form, $captcha_placement, $captcha_element);
    }
  }
  elseif ($config
    ->get('administration_mode') && $account
    ->hasPermission('administer CAPTCHA settings') && (!\Drupal::service('router.admin_context')
    ->isAdminRoute() || $config
    ->get('allow_on_admin_pages'))) {

    // Add CAPTCHA administration tools.

    /* @var \Drupal\captcha\Entity\CaptchaPoint $captcha_point */
    $captcha_point = CaptchaPoint::load($form_id);

    // For administrators: show CAPTCHA info and offer link to configure it.
    $captcha_element = [
      '#type' => 'details',
      '#title' => t('CAPTCHA'),
      '#attributes' => [
        'class' => [
          'captcha-admin-links',
        ],
      ],
      '#open' => TRUE,
    ];
    if ($captcha_point !== NULL && $captcha_point
      ->getCaptchaType()) {
      $captcha_element['#title'] = $captcha_point
        ->status() ? t('CAPTCHA: challenge "@type" enabled', [
        '@type' => $captcha_point
          ->getCaptchaType(),
      ]) : t('CAPTCHA: challenge "@type" disabled', [
        '@type' => $captcha_point
          ->getCaptchaType(),
      ]);
      $captcha_point
        ->status() ? $captcha_element['#description'] = t('Untrusted users will see a CAPTCHA here (<a href="@settings">general CAPTCHA settings</a>).', [
        '@settings' => Url::fromRoute('captcha_settings')
          ->toString(),
      ]) : ($captcha_element['#description'] = t('CAPTCHA disabled, Untrusted users won\'t see the captcha (<a href="@settings">general CAPTCHA settings</a>).', [
        '@settings' => Url::fromRoute('captcha_settings')
          ->toString(),
      ]));
      $captcha_element['challenge'] = [
        '#type' => 'item',
        '#title' => t('Enabled challenge'),
        '#markup' => $captcha_point
          ->toLink(t('change'), 'edit-form', [
          'query' => \Drupal::destination()
            ->getAsArray(),
        ])
          ->toString(),
      ];
    }
    else {
      $captcha_element['#title'] = t('CAPTCHA: no challenge enabled');
      $captcha_element['add_captcha'] = [
        '#markup' => Link::fromTextAndUrl(t('Place a CAPTCHA here for untrusted users.'), Url::fromRoute('captcha_point.add', [], [
          'query' => \Drupal::destination()
            ->getAsArray() + [
            'form_id' => $form_id,
          ],
        ]))
          ->toString(),
      ];
    }

    // Get placement in form and insert in form.
    if ($captcha_placement = _captcha_get_captcha_placement($form_id, $form)) {
      $captchaService
        ->insertCaptchaElement($form, $captcha_placement, $captcha_element);
    }
  }

  // Add a warning about caching on the Performance settings page.
  if ($form_id == 'system_performance_settings') {
    $form['caching']['captcha'] = [
      '#type' => 'item',
      '#title' => t('CAPTCHA'),
      '#markup' => '<div class="messages messages--warning">' . t('Most CAPTCHA methods will disable the caching of pages that contain a CAPTCHA element. Check the different implementations to know more about how it affects caching.') . '</div>',
    ];
  }

  // Disable captcha if override is set.
  if (Settings::get('disable_captcha', FALSE) === TRUE) {
    $override_notice = [
      '#type' => 'html_tag',
      '#tag' => 'strong',
      '#value' => t('Captcha is currently disabled via settings.php.'),
    ];
    if (isset($form['elements']['captcha'])) {
      $form['elements']['captcha'] = $override_notice;
    }
    if (isset($form['captcha'])) {
      $form['captcha'] = $override_notice;
    }
  }
}