yandex_smartcaptcha-1.0.2/src/Element/YandexSmartCaptchaElement.php
src/Element/YandexSmartCaptchaElement.php
<?php
namespace Drupal\yandex_smartcaptcha\Element;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Hidden;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* The class implements the Yandex SmartCaptcha form element.
*
* @FormElement("smartcaptcha_element")
*/
class YandexSmartCaptchaElement extends Hidden {
/**
* {@inheritdoc}
*/
public function getInfo() {
return [
'#input' => TRUE,
'#process' => [
[static::class, 'processCaptcha'],
],
'#element_validate' => [
[static::class, 'validateCaptcha'],
],
'#pre_render' => [
[static::class, 'preRenderHidden'],
],
'#theme' => 'input__hidden',
'#smartcaptcha' => [],
];
}
/**
* Process callback for captcha elements.
*/
public static function processCaptcha(&$element) {
$config = \Drupal::config('yandex_smartcaptcha.settings');
/** @var \Drupal\yandex_smartcaptcha\YandexSmartCaptcha $smart_captcha */
$smart_captcha = \Drupal::service('yandex_smartcaptcha.service');
// Hide SmartCaptcha element if disabled.
if (!$smart_captcha->isEnabled()) {
$element['#access'] = FALSE;
return $element;
}
$element['#attributes']['data-smartcaptcha-element'] = '';
$element['#attributes']['id'] = 'smartcaptcha-element-id';
$language = \Drupal::languageManager()->getDefaultLanguage()->getId();
$div = [
'#type' => 'html_tag',
'#tag' => 'div',
'#attributes' => [
'id' => 'container-smartcaptcha',
'data-sitekey' => $smart_captcha->getSiteKey(),
'data-hl' => $language,
'class' => ["smart-captcha"],
],
];
// If SmartCaptcha settings was overriden.
if (!empty($element["#smartcaptcha"])) {
// Add attribute for invisible mode.
$div['#attributes']['data-invisible'] = !empty($element['#smartcaptcha']['invisible']);
// Add attribute for test mode.
$div['#attributes']['data-test'] = !empty($element['#smartcaptcha']['test']);
// Add attribute for button hide mode mode.
$div['#attributes']['data-button_hide_mode'] = $element['#smartcaptcha']['button_hide_mode'];
}
else {
// Add attribute for invisible mode.
$div['#attributes']['data-invisible'] = $config->get('invisible');
// Add attribute for test mode.
$div['#attributes']['data-test'] = $config->get('test');
// Add attribute for button hide mode mode.
$div['#attributes']['data-button_hide_mode'] = $config->get('button_hide_mode');
}
// Render SmartCaptcha div element.
$element['#suffix'] = \Drupal::service('renderer')->render($div);
// Attach Yandex SmartCaptcha library script.
$element['#attached']['library'][] = 'yandex_smartcaptcha/smartcaptcha.element';
$element['#attached']['drupalSettings']['SmartCaptcha'] = [
'invisible' => $div['#attributes']['data-invisible'],
'test' => $div['#attributes']['data-test'],
'button_hide_mode' => $div['#attributes']['data-button_hide_mode'],
];
return $element;
}
/**
* {@inheritDoc}
*/
public static function validateCaptcha(&$element, FormStateInterface $form_state) {
/** @var \Drupal\yandex_smartcaptcha\YandexSmartCaptcha $smart_captcha */
$smart_captcha = \Drupal::service('yandex_smartcaptcha.service');
// Do not verify if smartcaptcha was disabled
// or clicked not primary submit button.
if (!$smart_captcha->isEnabled() || !self::isPrimarySubmit($form_state)) {
return;
}
$isSuccess = $smart_captcha->verify($element['#value']);
if (!$isSuccess) {
$message = new TranslatableMarkup('The SmartCaptcha verification was failed! Check the logs for more details');
$form_state->setError($element, Markup::create(Xss::filterAdmin($message)));
return;
}
if ($smart_captcha->isLog()) {
\Drupal::logger('smartcaptcha')->info('Sucessfully verified for @form_id',
['@form_id' => $form_state->getValue('form_id')]);
}
}
/**
* Check if was clicked primary submit button or no.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The $form_state object.
*
* @return bool
* Return is button primary.
*/
public static function isPrimarySubmit(FormStateInterface $form_state) {
$triggered = $form_state->getTriggeringElement();
// Check in ajax posted data.
$is_primary_ajax_submit = isset($triggered['#button_type']) ? $triggered['#button_type'] == 'primary' : FALSE;
// Check in regular submitted data.
$is_primary_submit = isset($triggered['#name']) ? $triggered['#name'] == 'op' : FALSE;
return $is_primary_ajax_submit || $is_primary_submit;
}
/**
* Builds a configuration form for the settings of a smartcaptcha elements.
*
* @param array $form
* The form array to which to attach the configuration form elements.
* @param array|null $configuration
* The configuration defaults used to populate the form elements.
*
* @return array
* The configuration form.
*/
public static function buildConfigurationForm(array $form = [], array $configuration = NULL) {
$form['invisible'] = [
'#type' => 'checkbox',
'#title' => t('Enable invisible mode'),
'#default_value' => $configuration['invisible'] ?? NULL,
'#description' => t('Enable invisible mode of Yandex SmartCaptcha'),
];
$form['test'] = [
'#type' => 'checkbox',
'#title' => t('Enable test mode'),
'#default_value' => $configuration['test'] ?? NULL,
'#description' => t('Enable test mode of Yandex SmartCaptcha'),
];
$form['button_hide_mode'] = [
'#type' => 'select',
'#title' => t('Submit button hide mode'),
'#description' => t('Choose the type of submit button hiding.'),
'#options' => ['hide' => t('Hide'), 'disable' => t('Disable')],
'#default_value' => $configuration['button_hide_mode'] ?? 'hide',
];
/** @var \Drupal\yandex_smartcaptcha\YandexSmartCaptcha $smart_captcha */
$smart_captcha = \Drupal::service('yandex_smartcaptcha.service');
$pages = $smart_captcha->getCurrentWebformPages();
$default = $pages ? key($pages) : '';
$form['display_page'] = [
'#type' => 'select',
'#title' => t('Captcha display page'),
'#description' => t('For multi-step webforms choose the step where captcha display.'),
'#options' => $pages,
'#default_value' => $configuration['display_page'] ?? $default,
];
return $form;
}
}
