route_ui-1.0.0-alpha2/src/Element/Route.php

src/Element/Route.php
<?php

namespace Drupal\route_ui\Element;

use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
use Drupal\Core\ParamConverter\ParamNotConvertedException;
use Drupal\Core\Render\Element\Details;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Routing\RouteObjectInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\Routing\Exception\RouteNotFoundException;

/**
 * Provides an route element.
 *
 * Properties:
 * - #route: Sets the value of the inner form elements. An array with the
 *   following keys:
 *   - 'route_name': A string for the route name.
 *   - 'route_parameters': An array of route parameters.
 *   - 'link_title': A string used as the link text.
 * - #route_access_check: Determines if the route should be access checked.
 *   Defaults to TRUE.
 * - #title: The title of the details container. Defaults to "Details".
 * - #open: Indicates whether the container should be open by default.
 *   Defaults to FALSE.
 * - #summary_attributes: An array of attributes to apply to the <summary>
 *   element.
 *
 * @RenderElement("route_ui")
 */
class Route extends Details {

  /**
   * {@inheritdoc}
   */
  public function getInfo(): array {
    $class = static::class;
    $info = parent::getInfo();

    $info['#input'] = TRUE;
    $info['#route_access_check'] = TRUE;
    array_unshift($info['#process'], [$class, 'processRoute']);
    $info['#element_validate'][] = [$class, 'validateRoute'];
    $info['#value_callback'] = [$class, 'valueCallback'];
    unset($info['#value']);

    return $info;
  }

  /**
   * Expands a route_ui element type into input elements.
   *
   * @param array $element
   *   The form element whose value is being processed.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param array $complete_form
   *   The complete form structure.
   *
   * @return array
   *   The form element whose value has been processed.
   */
  public static function processRoute(array &$element, FormStateInterface $form_state, array &$complete_form): array {
    // The value callback has populated the #value array.
    $values = $element['#value'];
    unset($element['#value']);

    $user_token = Crypt::hmacBase64(self::getCurrentUser()->id(), Settings::getHashSalt() . self::getPrivateKey());
    $element['route_name'] = [
      '#type' => 'textfield',
      '#title' => new TranslatableMarkup('Route name'),
      '#default_value' => $values['route_name'],
      '#description' => new TranslatableMarkup('The route name. For example: "node.add". To remove the route delete the value.'),
      '#autocomplete_route_name' => 'route_ui.route_names.autocomplete',
      '#autocomplete_route_parameters' => ['user_token' => $user_token],
    ];

    $element['route_parameters'] = [
      '#type' => 'textfield',
      '#title' => new TranslatableMarkup('The route parameters'),
      '#default_value' => self::paramArrayToString($values['route_parameters']),
      '#description' => new TranslatableMarkup('The route parameter values separate by a comma. For example, "node_type=page".'),
    ];

    $element['link_title'] = [
      '#type' => 'textfield',
      '#title' => new TranslatableMarkup('The text for link'),
      '#default_value' => $values['link_title'],
    ];

    $element['add_destination'] = [
      '#type' => 'checkbox',
      '#title' => new TranslatableMarkup('Adds the destination to the query string. If this is not already set it will use the current page.'),
      '#default_value' => $values['add_destination'] ?? FALSE,
    ];

    return $element;
  }

  /**
   * Validation callback for a route_ui element.
   *
   * @param array $element
   *   The form element whose value is being validated.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param array $complete_form
   *   The complete form structure.
   */
  public static function validateRoute(array &$element, FormStateInterface $form_state, array &$complete_form) {
    $input_exists = FALSE;
    $values = $form_state->getValues();
    $input = NestedArray::getValue($values, $element['#parents'], $input_exists);

    if ($input_exists && !empty($input['route_name'])) {
      if (empty($input['link_title'])) {
        $form_state->setError($element['link_title'], new TranslatableMarkup('The text for link is required.'));
      }

      try {
        $route = self::getRouteProvider()->getRouteByName($input['route_name']);
        // ParamConverterManager relies on the route name and object being
        // available from the parameters array.
        $input['route_parameters'][RouteObjectInterface::ROUTE_NAME] = $input['route_name'];
        $input['route_parameters'][RouteObjectInterface::ROUTE_OBJECT] = $route;
        $upcasted_parameters = self::getParamConverter()->convert($input['route_parameters'] + $route->getDefaults());
        $route_match = new RouteMatch($input['route_name'], $route, $upcasted_parameters, $input['route_parameters']);
        if ($element['#route_access_check'] && !self::getAccessManager()->check($route_match)) {
          $form_state->setError($element['route_name'], new TranslatableMarkup('Access to the route is denied.'));
        }
      }
      catch (RouteNotFoundException $e) {
        $form_state->setError($element['route_name'], new TranslatableMarkup('The route does not exist.'));
      }
      catch (ParamNotConvertedException $e) {
        $form_state->setError($element['route_parameters'], new TranslatableMarkup('The route parameters are incorrect: %message', ['%message' => $e->getMessage()]));
      }
    }
  }

  /**
   * Determines how user input is mapped to an element's #value property.
   *
   * @param array $element
   *   An associative array containing the properties of the element.
   * @param mixed $input
   *   The incoming input to populate the form element. If this is FALSE,
   *   the element's default value should be returned.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The value to assign to the element.
   *
   * @see \Drupal\Core\Render\Element\FormElementInterface::valueCallback()
   */
  public static function valueCallback(array &$element, $input, FormStateInterface $form_state): array {
    if ($input) {
      $input['route_parameters'] = self::paramStringToArray($input['route_parameters']);
    }
    else {
      $input = $element['#route'] ?? [
        'route_name' => '',
        'route_parameters' => [],
        'link_title' => '',
        'add_destination' => FALSE,
      ];
    }
    return $input;
  }

  /**
   * Converts a route parameter string into an array.
   *
   * @param string|null $param_string
   *   The route parameter string.
   *
   * @return array
   *   The array representation.
   */
  private static function paramStringToArray(string $param_string = NULL) : array {
    $params = [];
    $params_to_process = !empty($param_string) ? explode(',', $param_string) : [];
    foreach ($params_to_process as $param) {
      [$value1, $value2] = explode('=', $param, 2);
      if (!empty($value2)) {
        $params[$value1] = $value2;
      }
      else {
        $params[] = $value1;
      }
    }
    return $params;
  }

  /**
   * Converts an array of route parameters into a string.
   *
   * @param array $params
   *   The array of route parameters.
   *
   * @return string
   *   The string representation.
   */
  private static function paramArrayToString(array $params = []) : string {
    $strings = [];
    foreach ($params as $key => $param) {
      $strings[] = "$key=$param";
    }
    return implode(', ', $strings);
  }

  /**
   * Gets the access manager for route checking.
   *
   * @return \Drupal\Core\Access\AccessManagerInterface
   */
  private static function getAccessManager(): AccessManagerInterface {
    return \Drupal::service('access_manager');
  }

  /**
   * Gets the route provider.
   *
   * @return \Drupal\Core\Routing\RouteProviderInterface
   */
  private static function getRouteProvider(): RouteProviderInterface {
    return \Drupal::service('router.route_provider');
  }

  /**
   * Gets the param convertor.
   *
   * @return \Drupal\Core\ParamConverter\ParamConverterManagerInterface
   */
  private static function getParamConverter(): ParamConverterManagerInterface {
    return \Drupal::service('paramconverter_manager');
  }

  /**
   * The current user.
   *
   * @return \Drupal\Core\Session\AccountProxyInterface
   */
  private static function getCurrentUser(): AccountProxyInterface {
    return \Drupal::currentUser();
  }

  /**
   * Gets the private key.
   *
   * @return string
   *   The private key.
   */
  private static function getPrivateKey(): string {
    return \Drupal::service('private_key')->get();
  }

}

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

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