pluginreference-2.0.0/src/Element/PluginAutocomplete.php

src/Element/PluginAutocomplete.php
<?php

namespace Drupal\pluginreference\Element;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Render\Element\Textfield;
use Drupal\Core\Site\Settings;

/**
 * Provides a plugin autocomplete form element.
 *
 * The #default_value accepted by this element is a plugin definition array.
 *
 * @FormElement("plugin_autocomplete")
 */
class PluginAutocomplete extends Textfield {

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

    // Apply default form element properties.
    $info['#target_type'] = NULL;
    $info['#selection_handler'] = 'default';
    $info['#selection_settings'] = [];
    $info['#validate_reference'] = TRUE;

    $info['#element_validate'] = [
      [
        $class,
        'validatePluginAutocomplete',
      ],
    ];
    array_unshift($info['#process'], [
      $class,
      'processPluginAutocomplete',
    ]);

    return $info;
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    // Process the #default_value property.
    if ($input === FALSE && isset($element['#default_value'])) {
      if (is_array($element['#default_value']) && isset($element['#default_value']['label'])) {
        $name = $element['#default_value']['label'] ?? $element['#default_value']['admin_label'] ?? $element['#default_value']['id'];
        return $name . ' (' . $element['#default_value']['id'] . ')';
      }
      elseif ($element['#default_value'] instanceof PluginBase) {
        $plugin_definition = $element['#default_value']->getPluginDefinition();
        $name = $plugin_definition['label'] ?? $plugin_definition['admin_label'] ?? $element['#default_value']->getPluginId();
        return $name . ' (' . $element['#default_value']->getPluginId() . ')';
      }
      elseif (is_string($element['#default_value'])) {
        $plugin_manager = \Drupal::service('plugin_reference.plugin_type_helper')->getPluginManager($element['#target_type']);
        if ($plugin_manager instanceof PluginManagerInterface && $plugin_manager->hasDefinition($element['#default_value'])) {
          $plugin_definition = $plugin_manager->getDefinition($element['#default_value']);
          $name = $plugin_definition['label'] ?? $plugin_definition['admin_label'] ?? $plugin_definition['id'];
          return $name . ' (' . $plugin_definition['id'] . ')';
        }
      }
    }

    return NULL;
  }

  /**
   * Adds plugin autocomplete functionality to a form element.
   *
   * @param array $element
   *   The form element to process. Properties used:
   *   - #target_type: The ID of the target entity type.
   * @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.
   *
   * @throws \InvalidArgumentException
   *   Exception thrown when the #target_type is missing.
   */
  public static function processPluginAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
    // Nothing to do if there is no target entity type.
    if (empty($element['#target_type'])) {
      throw new \InvalidArgumentException('Missing required #target_type parameter.');
    }

    // Store the selection settings in the key/value store and pass a hashed key
    // in the route parameters.
    $selection_settings = $element['#selection_settings'] ?? [];
    $data = serialize($selection_settings) . $element['#target_type'] . $element['#selection_handler'];
    $selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt());

    $key_value_storage = \Drupal::keyValue('plugin_autocomplete');
    if (!$key_value_storage->has($selection_settings_key)) {
      $key_value_storage->set($selection_settings_key, $selection_settings);
    }

    $element['#autocomplete_route_name'] = 'pluginreference.plugin_autocomplete';
    $element['#autocomplete_route_parameters'] = [
      'target_type' => $element['#target_type'],
      'selection_handler' => $element['#selection_handler'],
      'selection_settings_key' => $selection_settings_key,
    ];

    return $element;
  }

  /**
   * Form element validation handler for plugin_autocomplete elements.
   */
  public static function validatePluginAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form): void {
    $value = NULL;

    if (!empty($element['#value']) && $match = static::extractPluginIdFromAutocompleteInput($element['#value'])) {
      $options = $element['#selection_settings'] + [
        'target_type' => $element['#target_type'],
        'handler' => $element['#selection_handler'],
      ];

      $handler = \Drupal::service('plugin.manager.plugin_reference_selection')->getInstance($options);
      if ($element['#validate_reference'] === TRUE && $handler->validateReferenceablePlugins([$match])) {
        $value = $match;
      }
      elseif ($element['#validate_reference'] === FALSE) {
        $value = $match;
      }
    }

    $form_state->setValueForElement($element, $value);
  }

  /**
   * Helper function to retrieve the plugin ID from the element value.
   */
  public static function extractPluginIdFromAutocompleteInput(string $input): ?string {
    $match = NULL;

    // Take "label (plugin id)', match the ID from parenthesis when it's a
    // number.
    if (preg_match("/.+\s\((\d+)\)/", $input, $matches)) {
      $match = $matches[1];
    }
    // Match the ID when it's a string .
    elseif (preg_match("/.+\s\(([\w.]+)\)/", $input, $matches)) {
      $match = $matches[1];
    }

    return $match;
  }

}

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

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