You are here

css_captcha.module in CAPTCHA Pack 8

Load css captcha file to use some helper functions.

File

css_captcha/css_captcha.module
View source
<?php

/**
 * @file
 * Load css captcha file to use some helper functions.
 */

/**
 * Implements hook_help().
 */
function css_captcha_help($path, $arg) {
  switch ($path) {
    case 'admin/user/captcha/css_captcha':
      return '<p>' . t('The CSS CAPTCHA uses CSS tricks to obfuscate a random text code for spam bots. The characters of the code are scrambled in the HTML markup but are displayed in the correct order when rendered with a CSS capable browser.') . '</p>';
  }
}

/**
 * Implements hook_captcha().
 */
function css_captcha_captcha($op, $captcha_type = '') {
  $config = \Drupal::config('css_captcha.settings');
  switch ($op) {
    case 'list':
      return [
        "CSS CAPTCHA",
      ];
    case 'generate':
      if ($captcha_type == "CSS CAPTCHA") {

        // Get settings.
        $allowed_chars = _text_captcha_utf8_split($config
          ->get('css_captcha_allowed_characters'));
        $code_length = $config
          ->get('css_captcha_code_length');

        // Build $code_struct and solution.
        $code_struct = [];
        $solution = '';
        for ($i = 0; $i < $code_length; $i++) {
          $character = $allowed_chars[array_rand($allowed_chars)];
          $code_struct[$i] = [
            'content' => $character,
            'size' => 1.25,
          ];
          $solution .= $character;
        }

        // Generate css scrambling.
        while (count($code_struct) > 1) {

          // Pick random neighbouring items from $code_struct.
          $i = mt_rand(0, count($code_struct) - 2);
          $item_left = $code_struct[$i];
          $item_right = $code_struct[$i + 1];

          // Merge.
          $merged_size = $item_left['size'] + $item_right['size'] + 0.25;
          if (mt_rand(0, 1)) {

            // Normal merge: $item_left first and $item_right second.
            $merged_content = "<div style=\"width:{$item_left['size']}em;float:left;\">{$item_left['content']}</div>" . "<div style=\"width:{$item_right['size']}em;float:left;\">{$item_right['content']}</div>";
          }
          else {

            // Mirror merge: $item_right first and $item_left second.
            $merged_content = "<div style=\"width:{$item_right['size']}em;float:right;\">{$item_right['content']}</div>" . "<div style=\"width:{$item_left['size']}em;float:left;\">{$item_left['content']}</div>";
          }

          // Build merged item.
          $item_merged = [
            'content' => '<div style="width: ' . $merged_size . 'em;height:1.5em;">' . $merged_content . '</div>',
            'size' => $merged_size,
          ];

          // Replace the two items with the merged one.
          array_splice($code_struct, $i, 2, [
            $item_merged,
          ]);

          // Make array indices contiguous again.
          $code_struct = array_values($code_struct);
        }

        // Build CAPTCHA.
        $captcha = [];
        $captcha['solution'] = $solution;
        $captcha['form']['captcha_code'] = [
          '#type' => 'inline_template',
          '#template' => '<div class="css-captcha-code">' . $code_struct[0]['content'] . '</div>',
          '#cache' => [
            'max-age' => 0,
          ],
        ];
        $captcha['form']['captcha_response'] = [
          '#type' => 'textfield',
          '#title' => t('Enter the code above'),
          '#size' => 10,
          '#maxlength' => 10,
          '#required' => TRUE,
          '#description' => t('Enter the code without spaces.'),
          '#cache' => [
            'max-age' => 0,
          ],
        ];
        \Drupal::service('page_cache_kill_switch')
          ->trigger();
        return $captcha;
      }
      break;
  }
}

Functions

Namesort descending Description
css_captcha_captcha Implements hook_captcha().
css_captcha_help Implements hook_help().