yandex_smartcaptcha-1.0.2/src/YandexSmartCaptcha.php

src/YandexSmartCaptcha.php
<?php

namespace Drupal\yandex_smartcaptcha;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\Error;
use Exception\RuntimeException;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * The class implements integration with the Yandex SmartCaptcha service.
 */
class YandexSmartCaptcha {

  /**
   * The Yandex SmartCaptcha generated token.
   *
   * @var string
   */
  private $token;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  public $configFactory;

  /**
   * The HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $client;

  /**
   * The update settings.
   *
   * @var \Drupal\Core\Config\Config
   */
  public $settings;

  /**
   * The attached_forms settings.
   *
   * @var \Drupal\Core\Config\Config
   */
  public $attachedFormsSettings;

  /**
   * The file_mdm logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The Request Stack Service.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  private RequestStack $requestStack;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Constructs a YandexSmartCaptchaService object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \GuzzleHttp\ClientInterface $client
   *   The HTTP client.
   * @param \Psr\Log\LoggerInterface $logger
   *   The yandex_smartcaptcha logger.
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   Request stack.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   */
  public function __construct(ConfigFactoryInterface $config_factory,
  ClientInterface $client,
  LoggerInterface $logger,
  RequestStack $requestStack,
  MessengerInterface $messenger) {
    $this->settings = $config_factory->get('yandex_smartcaptcha.settings');
    $this->attachedFormsSettings = $config_factory->get('yandex_smartcaptcha.attached_forms');
    $this->client = $client;
    $this->logger = $logger;
    $this->requestStack = $requestStack;
    $this->messenger = $messenger;
  }

  /**
   * Verify Yandex SmartCaptcha token request.
   *
   * @param string $token
   *   The Yandex SmartCaptcha token value.
   *
   * @return bool
   *   Return TRUE if the token has been successfully verified, FALSE otherwise.
   */
  public function verify(string $token) {
    if (!$token) {
      $this->logger->error('The Yandex SmartCaptcha token is empty');
      return FALSE;
    }
    $this->token = $token;

    $query = $this->getQuery($token);
    $url = $this->settings->get('api_url') . '?' . $query;
    try {
      $response = $this->client->get($url, $this->getOptions());
    }
    catch (GuzzleException $e) {
      throw new RuntimeException(Error::decodeException($e));
    }

    return $this->validateResponse($response);
  }

  /**
   * SmartCaptcha response validation.
   *
   * @param \Psr\Http\Message\ResponseInterface $response
   *   The response.
   *
   * @return bool
   *   TRUE if response valid, FALSE otherwise.
   */
  private function validateResponse(ResponseInterface $response) {
    $status = $response->getStatusCode();
    if ($status != 200) {
      $this->logger->warning('HTTP error @errorcode occurred when trying to fetch @remote.', [
        '@errorcode' => $status,
      ]);
      return FALSE;
    }

    $data = Json::decode($response->getBody());
    if ($data['status'] !== 'ok') {
      $this->logger->warning('Request return error message @message', [
        '@message' => $data['message'],
      ]);
      return FALSE;
    }

    return TRUE;
  }

  /**
   * Return verification query parameters.
   *
   * @param string|null $token
   *   The token value.
   *
   * @return string
   *   Url encoded string.
   */
  private function getQuery(string $token = NULL) {
    return http_build_query([
      "secret" => $this->getSecretKey(),
      "token" => $this->token,
      "ip" => $this->getClientIp(),
    ]);
  }

  /**
   * Return client request IP.
   */
  private function getClientIp() {
    return $this->requestStack->getCurrentRequest()->getClientIp();
  }

  /**
   * Return SmartCaptcha site key.
   */
  public function getSiteKey() {
    $key = $this->isEnvVarsExists() ? getenv('YA_CAPTCHA_SITE_KEY') : $this->settings->get('site_key');
    if (!$key) {
      $this->logger->error('The site key is not provided');
      $this->messenger->addError('The site key is not provided');
    }

    return $key;
  }

  /**
   * Return SmartCaptcha secret key.
   */
  public function getSecretKey() {
    $key = $this->isEnvVarsExists() ? getenv('YA_CAPTCHA_SECRET_KEY') : $this->settings->get('secret_key');
    if (!$key) {
      $this->logger->error('The secret key is not provided');
      $this->messenger->addError('The secret key is not provided');
    }

    return $key;
  }

  /**
   * {@inheritdoc}
   */
  private function getOptions() {
    return [
      'headers' => [
        'Accept' => 'application/json',
        'Content-Type' => 'application/x-www-form-urlencoded',
      ],
    ];
  }

  /**
   * Check if SmartCaptcha enabled or not.
   */
  public function isEnabled() {
    return $this->settings->get('enabled') || $this->isTestForm();
  }

  /**
   * Check if SmartCaptcha logging enabled or not.
   */
  public function isLog() {
    return (bool) $this->settings->get('log');
  }

  /**
   * Check if SmartCaptcha logging enabled or not.
   */
  public function isTestForm() {
    return $this->requestStack->getCurrentRequest()
      ->getRequestUri() == Url::fromRoute('yandex_smartcaptcha.test_form')
      ->toString();
  }

  /**
   * Check if environment variables exists.
   */
  public function isEnvVarsExists() {
    return getenv('YA_CAPTCHA_SITE_KEY') && getenv('YA_CAPTCHA_SECRET_KEY');
  }

  /**
   * Returns the Captcha attached forms array.
   */
  public function getAttachedFormsIds() {
    $form_ids = [];
    foreach ($this->attachedFormsSettings->getRawData() as $k => $v) {
      if ($k && isset($v['enabled'])) {
        $form_ids[$k] = $v;
      }
    };
    return $form_ids;
  }

  /**
   * Return the webform page step where SmartCaptcha should be displayed.
   */
  public function getCurrentWebformDisplayPage() {
    /** @var \Drupal\webform\WebformRequestInterface $request_handler */
    $request_handler = \Drupal::service('webform.request');
    $webform = $request_handler->getCurrentWebform();
    $webform_settings = $webform->getHandler('smartcaptcha_element')
      ->getSettings();

    $pages = $this->getCurrentWebformPages();
    $first_page = key($pages);
    // Get the page where captcha should be displayed.
    return $webform_settings['smartcaptcha']['display_page'] ?? $first_page;
  }

  /**
   * Return SmartCaptcha form element.
   */
  public function getCaptchaFormElement(array $settings = []) {
    return [
      '#type' => 'smartcaptcha_element',
      '#smartcaptcha' => [
        'invisible' => boolval($settings['invisible']),
        'test' => boolval($settings['test']),
        'button_hide_mode' => $settings['button_hide_mode'] ?? 'hide',
      ],
    ];
  }

  /**
   * Return webform pages array.
   */
  public function getCurrentWebformPages() {
    /** @var \Drupal\webform\WebformRequestInterface $request_handler */
    $request_handler = \Drupal::service('webform.request');
    $webform = $request_handler->getCurrentWebform();
    $options = $webform->getPages();
    array_walk($options, function ($v, $k) use (&$options) {
      $options[$k] = $v['#title'];
    });
    $options = array_diff_key($options, ['webform_confirmation' => '']);
    return $options;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc