View source
<?php
namespace Drupal\webform\Plugin\WebformElement;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Element\WebformMessage as WebformMessageElement;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\WebformSubmissionForm;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\Core\Link;
use Drupal\Core\Url as CoreUrl;
class Captcha extends WebformElementBase {
protected function defineDefaultProperties() {
return [
'captcha_type' => 'default',
'captcha_admin_mode' => FALSE,
'captcha_title' => '',
'captcha_description' => '',
'flex' => 1,
];
}
public function isInput(array $element) {
return FALSE;
}
public function isContainer(array $element) {
return FALSE;
}
public function getItemDefaultFormat() {
return NULL;
}
public function getItemFormats() {
return [];
}
public function prepare(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
$is_admin = \Drupal::currentUser()
->hasPermission('skip CAPTCHA');
if ($is_admin && empty($element['#captcha_admin_mode'])) {
$element['#access'] = FALSE;
$element['#captcha_admin_mode'] = TRUE;
}
$is_test = strpos(\Drupal::routeMatch()
->getRouteName(), '.webform.test_form') !== FALSE ? TRUE : FALSE;
if ($is_test) {
$element['#captcha_admin_mode'] = TRUE;
}
parent::prepare($element, $webform_submission);
$element['#after_build'][] = [
get_class($this),
'afterBuildCaptcha',
];
}
public function preview() {
$element = parent::preview() + [
'#captcha_admin_mode' => TRUE,
'#captcha_info' => [
'form_id' => '',
],
];
if (\Drupal::moduleHandler()
->moduleExists('image_captcha')) {
$element['#captcha_type'] = 'image_captcha/Image';
}
return $element;
}
public function preSave(array &$element, WebformSubmissionInterface $webform_submission) {
$key = $element['#webform_key'];
$data = $webform_submission
->getData();
unset($data[$key]);
$sub_keys = [
'sid',
'token',
'response',
];
foreach ($sub_keys as $sub_key) {
unset($data[$key . '_' . $sub_key]);
}
$webform_submission
->setData($data);
}
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$captcha_types = [];
$captcha_types['default'] = $this
->t('Default challenge type');
foreach (\Drupal::moduleHandler()
->getImplementations('captcha') as $module) {
$result = call_user_func_array($module . '_captcha', [
'list',
]);
if (is_array($result)) {
foreach ($result as $type) {
$captcha_types["{$module}/{$type}"] = $this
->t('@type (from module @module)', [
'@type' => $type,
'@module' => $module,
]);
}
}
}
$form['captcha'] = [
'#type' => 'fieldset',
'#title' => $this
->t('CAPTCHA settings'),
];
$form['captcha']['message'] = [
'#type' => 'webform_message',
'#message_type' => 'warning',
'#message_message' => $this
->t('Note that the CAPTCHA module disables page caching of pages that include a CAPTCHA challenge.'),
'#message_close' => TRUE,
'#message_storage' => WebformMessageElement::STORAGE_SESSION,
'#access' => TRUE,
];
$form['captcha']['captcha_type'] = [
'#type' => 'select',
'#title' => $this
->t('Challenge type'),
'#required' => TRUE,
'#options' => $captcha_types,
];
$form['captcha']['captcha_container'] = [
'#type' => 'container',
'#states' => [
'invisible' => [
[
':input[name="properties[captcha_type]"]' => [
'value' => 'recaptcha/reCAPTCHA',
],
],
],
],
];
$form['captcha']['captcha_container']['captcha_title'] = [
'#type' => 'textfield',
'#title' => $this
->t('Question title'),
];
$form['captcha']['captcha_container']['captcha_description'] = [
'#type' => 'textarea',
'#title' => $this
->t('Question description'),
];
$form['captcha']['captcha_admin_mode'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Admin mode'),
'#description' => $this
->t('Presolve the CAPTCHA and always shows it. This is useful for debugging and preview CAPTCHA integration.'),
'#return_value' => TRUE,
];
return $form;
}
public static function afterBuildCaptcha(array $element, FormStateInterface $form_state) {
if (isset($element['captcha_widgets']) && isset($element['captcha_widgets']['captcha_response']) && isset($element['captcha_widgets']['captcha_response']['#title'])) {
if (!empty($element['#captcha_title'])) {
$element['captcha_widgets']['captcha_response']['#title'] = $element['#captcha_title'];
}
if (!empty($element['#captcha_description'])) {
$element['captcha_widgets']['captcha_response']['#description'] = $element['#captcha_description'];
}
}
if ($form_state
->getFormObject() instanceof WebformSubmissionForm) {
$is_image_captcha = FALSE;
if ($element['#captcha_type'] === 'image_captcha/Image') {
$is_image_captcha = TRUE;
}
elseif ($element['#captcha_type'] === 'default') {
$default_challenge = \Drupal::service('config.manager')
->getConfigFactory()
->get('captcha.settings')
->get('default_challenge');
if ($default_challenge === 'image_captcha/Image') {
$is_image_captcha = TRUE;
}
}
if ($is_image_captcha && isset($element['#captcha_info']['form_id'])) {
$form_id = $element['#captcha_info']['form_id'];
$uri = Link::fromTextAndUrl(t('Get new captcha!'), new CoreUrl('image_captcha.refresh', [
'form_id' => $form_id,
], [
'attributes' => [
'class' => [
'reload-captcha',
],
],
]));
$element['captcha_widgets']['captcha_refresh'] = [
'#theme' => 'image_captcha_refresh',
'#captcha_refresh_link' => $uri,
'#parents' => array_merge($element['#parents'], [
'captcha_widgets',
]),
];
}
}
return $element;
}
}