toolshed-8.x-1.x-dev/src/Element/Autocomplete.php

src/Element/Autocomplete.php
<?php

namespace Drupal\toolshed\Element;

use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\Element\Textfield;
use Drupal\Core\Url;

/**
 * Create an autocomplete element, which uses the Toolshed autocomplete widget.
 *
 * The autocomplete widget from Toolshed handles the situation where the
 * display and the value differs. Allows passing key and value as autocomplete
 * results, and some additional flexibility with separating the autocomplete
 * display of suggestions from the input value.
 *
 * @FormElement("toolshed_autocomplete")
 *
 * @see /assets/widgets/Autocomplete.es6.js
 */
class Autocomplete extends Textfield {

  /**
   * {@inheritdoc}
   */
  public static function processAutocomplete(&$element, FormStateInterface $form_state, &$complete_form): array {
    $url = NULL;
    $access = FALSE;

    if (!empty($element['#autocomplete_route_name'])) {
      $params = @$element['#autocomplete_route_parameters'] ?: [];
      $url = Url::fromRoute($element['#autocomplete_route_name'], $params)->toString(TRUE);

      /** @var \Drupal\Core\Access\AccessManagerInterface $access_manager */
      $access_manager = \Drupal::service('access_manager');
      $access = $access_manager->checkNamedRoute(
        $element['#autocomplete_route_name'],
        $params,
        \Drupal::currentUser(),
        TRUE
      );
    }

    if ($access) {
      $metadata = BubbleableMetadata::createFromRenderArray($element);

      if (TRUE === $access || $access->isAllowed()) {
        $metadata->addAttachments(['library' => ['toolshed/autocomplete']]);

        $element['#attributes']['class'][] = 'toolshed-autocomplete';

        $settings = $element['#autocomplete_settings'] ?? [];
        $settings['uri'] = $url->getGeneratedUrl();

        if (!empty($element['#autocomplete_min_length'])) {
          $settings['minLength'] = intval($element['#autocomplete_min_length']);
        }
        if (!empty($element['#autocomplete_delay'])) {
          $settings['delay'] = intval($element['#autocomplete_delay']);
        }

        // Provide a data attribute for the JavaScript behavior to bind to.
        $element['#attributes']['data-autocomplete'] = json_encode($settings);

        if (!empty($element['#autocomplete_params'])) {
          $formattedParams = static::formatAutocompleteParams($element['#autocomplete_params'], $complete_form);
          $element['#attributes']['data-params'] = json_encode($formattedParams);
        }

        $metadata = $metadata->merge($url);
      }

      $metadata->merge(BubbleableMetadata::createFromObject($access))->applyTo($element);
    }

    // Apply display text for the separate value display.
    if (!empty($element['#text'])) {
      $element['#attributes']['data-text'] = Html::escape($element['#text']);
    }

    return $element;
  }

  /**
   * Transform the passed autocomplete parameters into a format for the JS data.
   *
   * @return array
   *   Convert autocomplete routing parameters into a format, that can be
   *   JSON encoded for inclusion to the element attributes.
   */
  protected static function formatAutocompleteParams(array $params, $form): array {
    $formatted = [];

    foreach ($params as $key => $target) {
      $hasKey = FALSE;
      $source = NestedArray::getValue($form, $target, $hasKey);

      if ($hasKey && !empty($source['#id'])) {
        $formatted[$key] = $source['#id'];
      }
    }

    return $formatted;
  }

}

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

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