active_form-8.x-1.x-dev/src/Plugin/ActiveForm/BaseForm.php

src/Plugin/ActiveForm/BaseForm.php
<?php

namespace Drupal\active_form\Plugin\ActiveForm;

use Drupal\active_form\BaseException;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\UnchangingCacheableDependencyTrait;
use Drupal\Core\Render\RenderableInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

abstract class BaseForm extends PluginBase implements RenderableInterface, CacheableDependencyInterface, ActiveFormInterface {

  use UnchangingCacheableDependencyTrait;

  protected $permission = '';

  /**
   * @param $plugin_id
   * @param string $configuration
   *
   * @return array
   */
  static public function lazyBuild($plugin_id, $configuration = NULL): array {
    /** @var BaseForm $form */
    $form = \Drupal::service('plugin.manager.active_form')
      ->createInstance($plugin_id, \GuzzleHttp\json_decode($configuration ?? '[]', TRUE));

    return $form->buildLazyProps();
  }

  /**
   * @return array
   */
  protected function buildLazyProps(): array {
    return [
      [
        '#type'       => 'html_tag',
        '#tag'        => 'script',
        '#attributes' => ['type' => 'application/json'],
        '#value'      => json_encode($this->getLazyProps()),
      ],
    ];
  }


  /**
   * @return string
   */
  protected function getCsrfToken(): string {
    return \Drupal::csrfToken()->get();
  }

  /**
   * @return array
   */
  protected function build(): array {
    $json = \GuzzleHttp\json_encode($this->configuration);
    $placeholder = $this->getPluginId() . '--' . $json;
    $output = [
      '#type'       => 'html_tag',
      '#tag'        => 'form',
      '#value'      => $placeholder,
      '#attributes' => $this->getHtmlAttributes(),
      '#attached'   => ['library' => [$this->getLibraryName()]],
    ];
    $output['#attached']['placeholders'][$placeholder] = [
      '#lazy_builder' => [
        static::class . '::lazyBuild',
        [
          $this->getPluginId(),
          $json,
        ],
      ],
    ];

    return $output;
  }

  /**
   * @return string|null
   */
  protected function getType(): ?string {
    return NULL;
  }

  /**
   * @return array
   */
  protected function getHtmlAttributes(): array {
    $attributes = ['class' => ['active-form--' . $this->pluginId], 'is' => $this->getComponentName()];
    if ($type = $this->getType()) {
      $attributes['class'][] = 'active-form--' . $this->pluginId . '--' . $type;
    }

    return $attributes + $this->propsToAttrs($this->getProps());
  }

  /**
   * @param array $props
   *
   * @return array
   */
  public function propsToAttrs(array $props): array {
    foreach ($props as $key => $value) {
      if (!is_scalar($value)) {
        $props[$key] = json_encode($value);
      }
    }

    return $props;
  }

  /**
   * @return array
   */
  protected function getProps(): array {
    $storage_json = \GuzzleHttp\json_encode($this->configuration);
    return [
      'action'        => Url::fromRoute('activeform')->toString(),
      'method'        => 'POST',
      'storage_json'  => $storage_json,
      'storage_token' => $this->getStorageToken($storage_json),
    ];
  }

  /**
   * @return array
   */
  protected function getLazyProps(): array {
    return [
      'csrf_token' => $this->getCsrfToken(),
    ];
  }

  /**
   * @return string
   */
  protected function getComponentName(): string {
    return 'active-form--' . $this->pluginId . ($this->getType() ? "--{$this->getType()}" : '');
  }

  /**
   * @return string
   */
  protected function getLibraryName(): string {
    return $this->pluginDefinition['provider'] . '/' . $this->pluginId . ($this->getType() ? "--{$this->getType()}" : '');
  }

  /**
   * @return array
   */
  public function toRenderable(): array {
    return $this->build() +
      [
        '#cache' => [
          'contexts' => $this->getCacheContexts(),
          'tags'     => $this->getCacheTags(),
          'max-age'  => $this->getCacheMaxAge(),
        ],
      ];
  }

  /**
   * @param string $storage_json
   *
   * @return string
   */
  protected function getStorageToken(string $storage_json): string {
    $data = $this->pluginId . ':' . $storage_json;
    return Crypt::hmacBase64($data, Settings::getHashSalt());
  }

  /**
   * @param \Symfony\Component\HttpFoundation\Request $request
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  final public function handle(Request $request): JsonResponse {
    try {
      $method = $request->request->get('op');
      $this->validate($request, $method);
      return new JsonResponse($this->$method($request));
    } catch (BaseException $e) {
      return new JsonResponse([
        'status'  => 'error',
        'message' => $e->getMessage(),
        'error'   => $e->getData(),
      ], $e->getCode());
    }
  }

  /**
   * @param string|null $csrf_token
   *
   * @throws \Drupal\active_form\BaseException
   */
  protected function checkCsrfToken(?string $csrf_token) {
    if ($csrf_token !== $this->getCsrfToken()) {
      throw new BaseException('invalid csrf token', 403);
    }
  }

  /**
   * @param string $storage_token
   * @param string $storage_json
   *
   * @throws BaseException
   */
  protected function checkStorageToken(string $storage_token, string $storage_json) {
    if ($storage_token !== $this->getStorageToken($storage_json)) {
      throw new BaseException('invalid storage token', 403);
    }
  }

  /**
   * @throws BaseException
   */
  protected function checkPermission() {
    if ($this->permission && !\Drupal::currentUser()
        ->hasPermission($this->permission)) {
      throw new BaseException('has not permission', 403);
    }
  }

  /**
   * @param string $method
   *
   * @throws \Drupal\active_form\BaseException
   */
  protected function checkMethod(string $method) {
    if (!method_exists($this, $method)) {
      throw (new BaseException('method not exist', 501))->addValue('method', $method);
    }
  }

  /**
   * @param \Symfony\Component\HttpFoundation\Request $request
   * @param string|null $method
   *
   * @throws \Drupal\active_form\BaseException
   */
  function validate(Request $request, ?string $method = NULL) {
    $this->checkCsrfToken($request->request->get('csrf_token'));
    $this->checkPermission();
    $this->checkMethod($method);
    $this->checkStorageToken($request->request->get('storage_token', ''), $request->request->get('storage_json', ''));
  }

}

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

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