select2_widget-8.x-1.x-dev/src/Plugin/Field/FieldWidget/Select2AutocompleteWidget.php

src/Plugin/Field/FieldWidget/Select2AutocompleteWidget.php
<?php

namespace Drupal\select2_widget\Plugin\Field\FieldWidget;

use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Field\FieldItemListInterface;
use function is_array;
use function str_replace;
use function strpos;

/**
 * Plugin implementation of the 'select2_autocomplete_widget' widget.
 *
 * @FieldWidget(
 *   id = "select2_autocomplete_widget",
 *   label = @Translation("Select2 Autocomplete"),
 *   field_types = {
 *     "entity_reference"
 *   },
 *   multiple_values = TRUE
 * )
 */
class Select2AutocompleteWidget extends OptionsSelectWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    $entity = $items->getEntity();
    $target_type = $this->getFieldSetting('target_type');
    $field_name = $this->fieldDefinition->getFieldStorageDefinition()->getName();
    $selected_options = $this->getSelectedOptions($items);
    $selection_settings = $this->getFieldSetting('handler_settings');

    // If the form is submited add the newly added options to the allowed
    // options to prevent 'An illegal choice has been detected.' validation
    // error.
    $input = $form_state->getUserInput();
    if(!empty($input) && isset($input[$field_name]) && is_array($input[$field_name])){
      $field_input = array_flip($input[$field_name]);

      foreach ($field_input as $entity_id => $label) {
        if(!isset($selected_options[$entity_id])){
          if(is_numeric($entity_id)){
            $entity = \Drupal::entityTypeManager()->getStorage($target_type)->load($entity_id);
            if(isset($entity)) {
              $selected_options[$entity_id] = $entity->label();
            }
          }

          if(!isset($selected_options[$entity_id])) {
            $selected_options[$entity_id] = $entity_id;
          }
        }
      }

    }

    $element = [
      '#type' => 'select2_entity_autocomplete',
      '#target_type' => $target_type,
      '#selection_handler' => $this->getFieldSetting('handler'),
      '#selection_settings' => $selection_settings,
      // Entity reference field items are handling validation themselves via
      // the 'ValidReference' constraint.
      '#validate_reference' => FALSE,
      '#options' => $selected_options,
      '#default_value' => array_keys($selected_options),
      '#size' => $this->getSetting('size'),
      '#placeholder' => $this->getSetting('placeholder'),
      '#multiple' => $this->multiple,
    ] + $element;


    if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) {
      $element['#autocreate'] = array(
        'bundle' => $bundle,
        'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id()
      );
    }

    $class = 'select2-' . hash('md5', Html::getUniqueId('select2-' . $field_name));

    $select2_settings = [
      'selector' => '.' . $class,
      'field_name' => $field_name,
      'settings' => $this->getSettings(),
      'items' => []
    ];

    foreach ($selected_options as $entity_id => $label) {
      $entity = \Drupal::entityTypeManager()->getStorage($target_type)->load($entity_id);
      if(isset($entity)){
        $select2_settings['items'][$entity_id] = [
          'id' => $entity_id,
          'label' => $label,
          'status' => $entity->get('status')->value,
        ];
      }
    }

    $element['#attached']['drupalSettings']['select2'][$class] = $select2_settings;
    $element['#attributes']['class'][] = $class;
    $element['#attached']['library'][] = 'select2_widget/select2.widget';

    return $element;
  }

  public static function validateElement(array $element, FormStateInterface $form_state) {
    $target_type = $element['#target_type'];

    $element_value = array_reduce($element['#value'], function ($return, $item) use ($target_type) {
      if (is_numeric($item)) {
        $entity = \Drupal::entityTypeManager()->getStorage($target_type)->load($item);
        if(isset($entity)){
          $item = 'dummy term name (' . $item . ')';
        }
      }

      if(strpos($item, 'create:') === 0) {
        $item = str_replace('create:', '', $item);
      }

      $return[] = $item;

      return $return;
    });

    if(is_array($element_value)){
      $element['#value'] = Tags::implode($element_value);
      $complete_form = &$form_state->getCompleteForm();
      EntityAutocomplete::validateEntityAutocomplete($element, $form_state, $complete_form);
    }

  }

  protected function getOptions(FieldableEntityInterface $entity) {
    if (!isset($this->options)) {
      $this->options = [];
    }
    return $this->options;
  }

  protected function getSelectedOptions(FieldItemListInterface $items) {
    $selected_options = array();
    $referenced_entities = $items->referencedEntities();

    foreach ($referenced_entities as $delta => $referenced_entity) {
      $id = $referenced_entity->id();
      $label = $referenced_entity->label();
      $selected_options[$id] = $label;
    }

    return $selected_options;
  }

  /**
   * Returns the name of the bundle which will be used for autocreated entities.
   *
   * @return string
   *   The bundle name.
   */
  protected function getAutocreateBundle() {
    $bundle = NULL;
    $target_bundles = $this->getSelectionHandlerSetting('target_bundles');
    if ($this->getSelectionHandlerSetting('auto_create')) {
      // If there's only one target bundle, use it.
      if (is_array($target_bundles) && count($target_bundles) == 1) {
        $bundle = reset($target_bundles);
      }
      // Otherwise use the target bundle stored in selection handler settings.
      elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) {
        // If no bundle has been set as auto create target means that there is
        // an inconsistency in entity reference field settings.
        trigger_error(sprintf(
          "The 'Create referenced entities if they don't already exist' option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
          $this->fieldDefinition->getLabel(),
          $this->fieldDefinition->getName()
        ), E_USER_WARNING);
      }
    }

    return $bundle;
  }

  /**
   * Returns the value of a setting for the entity reference selection handler.
   *
   * @param string $setting_name
   *   The setting name.
   *
   * @return mixed
   *   The setting value.
   */
  protected function getSelectionHandlerSetting($setting_name) {
    $settings = $this->getFieldSetting('handler_settings');
    return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL;
  }

}

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

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