You are here

abstract class JsCallbackBase in JS Callback Handler 8.3

Base JsCallback class.

Hierarchy

Expanded class hierarchy of JsCallbackBase

1 file declares its use of JsCallbackBase
Email.php in js_callback_examples/src/Plugin/Js/Email.php

File

src/Plugin/Js/JsCallbackBase.php, line 14

Namespace

Drupal\js\Plugin\Js
View source
abstract class JsCallbackBase extends PluginBase implements JsCallbackInterface {

  /**
   * @var \Drupal\Core\DependencyInjection\ClassResolver
   */
  protected $classResolver;

  /**
   * @var \Drupal\js\Js
   */
  protected $js;

  /**
   * @var \Drupal\js\JsResponse
   */
  protected $response;

  /**
   * @var array
   */
  protected $parameters;

  /**
   * @var \Drupal\Core\Routing\Enhancer\ParamConversionEnhancer
   */
  protected $paramConversion;

  /**
   * @var \Drupal\Core\StringTranslation\TranslatableMarkup|string
   */
  protected $title;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->classResolver = \Drupal::service('class_resolver');
    $this->js = \Drupal::service('js.callback');
    $this->paramConversion = \Drupal::service('route_enhancer.param_conversion');
    $this->title = isset($this->pluginDefinition['title']) ? $this->pluginDefinition['title'] : '';
    try {
      $this->response = $this->classResolver
        ->getInstanceFromDefinition($this->pluginDefinition['response']);
    } catch (\Exception $e) {

      // Intentionally left empty since this is checked below.
    }
    if (!$this->response instanceof JsResponse) {
      throw new \InvalidArgumentException('JS Callback requires that the "response" option be either a service identifier or a class name creating an instance that is or inherits from \\Drupal\\js\\JsResponse.');
    }
    $this->parameters = $this
      ->convertParameters();
  }

  /**
   * {@inheritdoc}
   */
  public function access() {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function accessDeniedMessage() {
    return $this
      ->t('Unauthorized access. If you feel this is in error, please contact the site administrator.');
  }

  /**
   * {@inheritdoc}
   */
  public function anonymousUserMessage() {
    return $this
      ->t('Cannot complete request: requires authentication. Try refreshing this page or logging out and back in again.');
  }

  /**
   * {@inheritdoc}
   */
  public function call($method) {
    return call_user_func_array([
      $this,
      $method,
    ], $this
      ->mapMethodParameters($method));
  }

  /**
   * {@inheritdoc}
   */
  public function captureOutput() {
    return !!$this->pluginDefinition['capture_output'];
  }

  /**
   * Convert callback parameters into fully loaded objects.
   *
   * @return array
   *   An associative array of converted parameters.
   */
  protected function convertParameters() {
    if (!$this->js
      ->isExecuting()) {
      return [];
    }

    // Create a standalone "Request" object.
    $request = $this->js
      ->getRequest();
    $parameters = $request->query
      ->all() + $request->request
      ->all();
    if ($this->pluginDefinition['parameters']) {
      $options = [
        'parameters' => $this->pluginDefinition['parameters'],
      ];
      $route = new Route('/{' . implode('}/{', array_keys($parameters)) . '}', $parameters, [], $options);
      $parameters = $this->paramConversion
        ->enhance([
        '_route_object' => $route,
      ] + $parameters, Request::create(''));
      unset($parameters['_route_object']);
      unset($parameters['_raw_variables']);

      // Handle JSON data.
      $boolean_values = [
        'true',
        'false',
        '1',
        '0',
        'yes',
        'no',
      ];
      foreach ($parameters as $key => $value) {

        // Convert possible JSON strings into arrays.
        if (is_string($value) && $value !== '' && ($value[0] === '[' || $value[0] === '{') && ($json = Json::decode($value))) {
          $parameters[$key] = $json;
        }
        elseif (is_string($value) && in_array($value, $boolean_values)) {
          $parameters[$key] = (bool) $value;
        }
      }
    }
    return $parameters;
  }

  /**
   * {@inheritdoc}
   */
  public function csrfToken() {
    return !!$this->pluginDefinition['csrf_token'];
  }

  /**
   * {@inheritdoc}
   */
  public function getAllowedMethods() {
    return $this->pluginDefinition['allowed_methods'];
  }

  /**
   * {@inheritdoc}
   */
  public function invalidTokenMessage() {
    return $this
      ->t('Cannot complete request: invalid CSRF token. Try refreshing this page or logging out and back in again.');
  }

  /**
   * {@inheritdoc}
   */
  public function mapMethodParameters($method) {
    $args = [];
    $parameters = $this
      ->getParameters();
    $reflection = new \ReflectionClass($this);
    $function = $reflection
      ->getMethod($method);
    foreach ($function
      ->getParameters() as $param) {
      $default_value = $param
        ->isDefaultValueAvailable() ? $param
        ->getDefaultValue() : NULL;
      $value = isset($parameters[$param->name]) ? $parameters[$param->name] : $default_value;

      // Type case values if not an object.
      if (isset($value) && !is_object($value) && ($type = gettype($default_value))) {
        settype($value, $type);
      }
      $args[$param->name] = $value;
    }
    return $args;
  }

  /**
   * {@inheritdoc}
   */
  public function getParameters() {
    return $this->parameters;
  }

  /**
   * {@inheritdoc}
   */
  public function getResponse() {
    return $this->response;
  }

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    return $this->title;
  }

  /**
   * {@inheritdoc}
   */
  public function setTitle($title = '') {
    $this->title = $title;
  }

  /**
   * {@inheritdoc}
   */
  public function methodNotAllowedMessage() {
    $allowed = $this
      ->getAllowedMethods();
    return $this
      ->formatPlural(count($allowed), 'Method not allowed: %method. Only the %allowed_methods method is allowed. Please contact the site administrator if this problem persists.', 'Method not allowed: %method. Only the %allowed_methods methods are allowed. Please contact the site administrator if this problem persists.', [
      '%method' => $this->js
        ->getRequest()
        ->getMethod(),
      '%allowed_methods' => implode(', ', $allowed),
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function validate() {
    return TRUE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
JsCallbackBase::$classResolver protected property
JsCallbackBase::$js protected property
JsCallbackBase::$paramConversion protected property
JsCallbackBase::$parameters protected property
JsCallbackBase::$response protected property
JsCallbackBase::$title protected property
JsCallbackBase::access public function Access callback. Overrides JsCallbackInterface::access 1
JsCallbackBase::accessDeniedMessage public function Message to show when access to the callback has been denied. Overrides JsCallbackInterface::accessDeniedMessage
JsCallbackBase::anonymousUserMessage public function Message to show when user is anonymous and callback requires CSRF token. Overrides JsCallbackInterface::anonymousUserMessage
JsCallbackBase::call public function Calls a method on the callback, providing necessary converted parameters. Overrides JsCallbackInterface::call
JsCallbackBase::captureOutput public function Flag indicating whether or not the callback should capture printed output. Overrides JsCallbackInterface::captureOutput
JsCallbackBase::convertParameters protected function Convert callback parameters into fully loaded objects.
JsCallbackBase::csrfToken public function Flag indicating whether callback should validate a CSRF token. Overrides JsCallbackInterface::csrfToken
JsCallbackBase::getAllowedMethods public function An indexed array of allowed HTTP methods. Overrides JsCallbackInterface::getAllowedMethods
JsCallbackBase::getParameters public function An associative array of parameters. Overrides JsCallbackInterface::getParameters
JsCallbackBase::getResponse public function Retrieves the callback's response handler. Overrides JsCallbackInterface::getResponse
JsCallbackBase::getTitle public function The human readable title of the callback, if set. Overrides JsCallbackInterface::getTitle
JsCallbackBase::invalidTokenMessage public function Message to show when an invalid CSRF token was provided. Overrides JsCallbackInterface::invalidTokenMessage
JsCallbackBase::mapMethodParameters public function
JsCallbackBase::methodNotAllowedMessage public function Message to show when a callback was requested with an invalid HTTP method. Overrides JsCallbackInterface::methodNotAllowedMessage
JsCallbackBase::setTitle public function Sets the title for the callback. Overrides JsCallbackInterface::setTitle
JsCallbackBase::validate public function Validates the callback. Overrides JsCallbackInterface::validate 1
JsCallbackBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase::__construct 1
JsCallbackInterface::execute public function Executes the callback. 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.