You are here

class AutocompleteDeluxeWidget in Autocomplete Deluxe 2.0.x

Same name and namespace in other branches
  1. 8 src/Plugin/Field/FieldWidget/AutocompleteDeluxeWidget.php \Drupal\autocomplete_deluxe\Plugin\Field\FieldWidget\AutocompleteDeluxeWidget

Plugin implementation of the 'options_buttons' widget.

Plugin annotation


@FieldWidget(
  id = "autocomplete_deluxe",
  label = @Translation("Autocomplete Deluxe"),
  field_types = {
    "entity_reference"
  },
  multiple_values = TRUE
)

Hierarchy

Expanded class hierarchy of AutocompleteDeluxeWidget

File

src/Plugin/Field/FieldWidget/AutocompleteDeluxeWidget.php, line 33

Namespace

Drupal\autocomplete_deluxe\Plugin\Field\FieldWidget
View source
class AutocompleteDeluxeWidget extends WidgetBase implements ContainerFactoryPluginInterface {
  use StringTranslationTrait;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Current Account Interface.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;

  /**
   * Key value service.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface
   */
  protected $keyValue;

  /**
   * {@inheritdoc}
   *
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The field definition for the operation.
   * @param array $settings
   *   The formatter settings.
   * @param array $third_party_settings
   *   Any third party settings.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Current account.
   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value
   *   Key value storage.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ModuleHandlerInterface $module_handler, AccountInterface $account, KeyValueFactoryInterface $key_value) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
    $this->moduleHandler = $module_handler;
    $this->account = $account;
    $this->keyValue = $key_value;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
      ->get('module_handler'), $container
      ->get('current_user'), $container
      ->get('keyvalue'));
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'match_operator' => 'CONTAINS',
      'autocomplete_route_name' => 'autocomplete_deluxe.autocomplete',
      'size' => 60,
      'selection_handler' => 'default',
      'limit' => 10,
      'min_length' => 0,
      'delimiter' => '',
      'not_found_message_allow' => FALSE,
      'not_found_message' => "The term '@term' will be added",
      'new_terms' => FALSE,
      'no_empty_message' => 'No terms could be found. Please type in order to add a new term.',
    ] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $element['match_operator'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Match operator'),
      '#description' => $this
        ->t('Specify the matcting operator.'),
      '#default_value' => $this
        ->getSetting('match_operator'),
      '#options' => $this
        ->getMatchOperatorOptions(),
    ];
    $element['limit'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Limit of the output.'),
      '#description' => $this
        ->t('If set to zero no limit will be used'),
      '#default_value' => $this
        ->getSetting('limit'),
      '#element_validate' => [
        [
          get_class($this),
          'validateInteger',
        ],
      ],
    ];
    $element['min_length'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Minimum length.'),
      '#description' => $this
        ->t('The minimum length of characters to enter to open the suggestion list.'),
      '#default_value' => $this
        ->getSetting('min_length'),
      '#element_validate' => [
        [
          get_class($this),
          'validateInteger',
        ],
      ],
    ];
    $element['delimiter'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Delimiter.'),
      '#description' => $this
        ->t('A character which should be used beside the enter key, to separate terms.'),
      '#default_value' => $this
        ->getSetting('delimiter'),
      '#size' => 1,
    ];
    $element['not_found_message_allow'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Show Term not found message'),
      '#description' => $this
        ->t('If this is enabled, a message will be displayed when the term is not found.'),
      '#default_value' => $this
        ->getSetting('not_found_message_allow'),
    ];
    $element['not_found_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Term not found message.'),
      '#description' => $this
        ->t('A message text which will be displayed, if the entered term was not found.'),
      '#default_value' => $this
        ->getSetting('not_found_message'),
    ];
    $element['new_terms'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Allow new terms'),
      '#description' => $this
        ->t('Should it be allowed, that user enter new terms?'),
      '#default_value' => $this
        ->getSetting('new_terms'),
    ];
    $element['no_empty_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Empty value message.'),
      '#description' => $this
        ->t('A text message that will be displayed when the field is focused and it does not contain values.'),
      '#default_value' => $this
        ->getSetting('no_empty_message'),
    ];
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];
    $summary[] = $this
      ->t('Match operator: @match_operator', [
      '@match_operator' => $this
        ->getSetting('match_operator'),
    ]);
    $summary[] = $this
      ->t('Limit: @limit', [
      '@limit' => $this
        ->getSetting('limit'),
    ]);
    $summary[] = $this
      ->t('Min length: @min_length', [
      '@min_length' => $this
        ->getSetting('min_length'),
    ]);
    $summary[] = $this
      ->t('Delimiter: @delimiter', [
      '@delimiter' => $this
        ->getSetting('delimiter'),
    ]);
    $summary[] = $this
      ->t('Allow Not Found message: @not_found_message_allow', [
      '@not_found_message_allow' => $this
        ->getSetting('not_found_message_allow') ? 'Yes' : 'No',
    ]);
    $summary[] = $this
      ->t('Not Found message: @not_found_message', [
      '@not_found_message' => $this
        ->getSetting('not_found_message'),
    ]);
    $summary[] = $this
      ->t('Allow new terms: @new_terms', [
      '@new_terms' => $this
        ->getSetting('new_terms') ? 'Yes' : 'No',
    ]);
    $summary[] = $this
      ->t('Empty value message: @no_empty_message', [
      '@no_empty_message' => $this
        ->getSetting('no_empty_message'),
    ]);
    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $entity = $items
      ->getEntity();
    $instance = $this->fieldDefinition;
    $cardinality = $instance
      ->getFieldStorageDefinition()
      ->getCardinality();
    $target_type = $instance
      ->getFieldStorageDefinition()
      ->getSetting('target_type');
    $settings = $this
      ->getSettings();
    $referenced_entities = $items
      ->referencedEntities();
    $selection_settings = $this
      ->getFieldSetting('handler_settings') + [
      'match_operator' => $this
        ->getSetting('match_operator'),
    ];
    $allow_message = $settings['not_found_message_allow'] ?? FALSE;
    $not_found_message = $settings['not_found_message'] ?? "";
    $element += [
      '#type' => 'autocomplete_deluxe',
      '#title' => $this->fieldDefinition
        ->getLabel(),
      '#target_type' => $target_type,
      '#selection_handler' => $this
        ->getFieldSetting('handler'),
      '#selection_settings' => $selection_settings,
      '#size' => 60,
      '#limit' => $settings['limit'] ?? 10,
      '#min_length' => $settings['min_length'] ?? 0,
      '#delimiter' => $settings['delimiter'] ?? '',
      '#not_found_message_allow' => $allow_message,
      '#not_found_message' => $this
        ->t('@not_found_message', [
        '@not_found_message' => $not_found_message,
      ]),
      '#new_terms' => $settings['new_terms'] ?? FALSE,
      '#no_empty_message' => isset($settings['no_empty_message']) ? $this
        ->t('@no_empty_message', [
        '@no_empty_message' => $settings['no_empty_message'],
      ]) : '',
    ];
    $multiple = $cardinality > 1 || $cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;

    // If new terms are allowed to be created, set the bundle and the uid of the
    // term.
    if ($this
      ->getSetting('new_terms') && $this
      ->getSelectionHandlerSetting('auto_create') && ($bundle = $this
      ->getAutocreateBundle())) {
      $element['#autocreate'] = [
        'bundle' => $bundle,
        'uid' => $entity instanceof EntityOwnerInterface ? $entity
          ->getOwnerId() : $this->account
          ->id(),
      ];
    }
    $entities = [];
    foreach ($referenced_entities as $item) {
      $entities[$item
        ->id()] = $item;
    }
    $selection_settings = isset($element['#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 = $this->keyValue
      ->get('entity_autocomplete');
    if (!$key_value_storage
      ->has($selection_settings_key)) {
      $key_value_storage
        ->set($selection_settings_key, $selection_settings);
    }
    $route_parameters = [
      'target_type' => $target_type,
      'selection_handler' => $element['#selection_handler'],
      'selection_settings_key' => $selection_settings_key,
    ];
    $element += [
      '#multiple' => $multiple,
      '#autocomplete_deluxe_path' => Url::fromRoute('autocomplete_deluxe.autocomplete', $route_parameters, [
        'absolute' => TRUE,
      ])
        ->getInternalPath(),
      '#default_value' => self::implodeEntities($entities),
    ];
    return [
      'target_id' => $element,
    ];
  }

  /**
   * Implodes the tags from the taxonomy module.
   *
   * @param \Drupal\Core\Entity\EntityInterface[] $entities
   *   List of entities.
   * @param string $bundle
   *   Bundle name.
   *
   * @return array
   *   Imploded list of entity labels.
   */
  public static function implodeEntities(array $entities, $bundle = NULL) {
    $typed_entities = [];
    foreach ($entities as $entity) {
      $label = $entity
        ->label();

      // Extract entities belonging to the bundle in question.
      if (!isset($bundle) || $entity
        ->bundle() == $bundle) {

        // Make sure we have a completed loaded entity.
        if ($entity && $label) {

          // Commas and quotes in tag names are special cases, so encode 'em.
          if (strpos($label, ',') !== FALSE || strpos($label, '"') !== FALSE) {
            $label = '"' . str_replace('"', '""', $label) . '"';
          }
          $typed_entities[] = $label;
        }
      }
    }
    return implode(',', $typed_entities);
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    return $values['target_id'];
  }

  /**
   * Form element validation handler for integer textfields.
   */
  public static function validateInteger(&$element, FormStateInterface $form_state, &$complete_form) {
    $value = $element['#value'];
    if ($value !== '' && (!is_numeric($value) || intval($value) != $value)) {
      $form_state
        ->setError($element, \Drupal::translation()
        ->translate('%name must be an integer.', [
        '%name' => $element['#title'],
      ]));
    }
  }

  /**
   * Form element validation handler for positive integer textfields.
   */
  public static function validateIntegerPositive(&$element, FormStateInterface $form_state, &$complete_form) {
    $value = $element['#value'];
    if ($value !== '' && (!is_numeric($value) || intval($value) != $value || $value <= 0)) {
      $form_state
        ->setError($element, \Drupal::translation()
        ->translate('%name must be a positive integer.', [
        '%name' => $element['#title'],
      ]));
    }
  }

  /**
   * Returns the name of the bundle which will be used for autocreated entities.
   *
   * @return string
   *   The bundle name.
   */
  protected function getAutocreateBundle() {
    $bundle = NULL;
    if ($this
      ->getSelectionHandlerSetting('auto_create') && ($target_bundles = $this
      ->getSelectionHandlerSetting('target_bundles'))) {

      // If there's only one target bundle, use it.
      if (count($target_bundles) == 1) {
        $bundle = reset($target_bundles);
      }
      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;
  }

  /**
   * Returns the options for the match operator.
   *
   * @return array
   *   List of options.
   */
  protected function getMatchOperatorOptions() {
    return [
      'STARTS_WITH' => $this
        ->t('Starts with'),
      'CONTAINS' => $this
        ->t('Contains'),
    ];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AutocompleteDeluxeWidget::$account protected property Current Account Interface.
AutocompleteDeluxeWidget::$keyValue protected property Key value service.
AutocompleteDeluxeWidget::$moduleHandler protected property The module handler.
AutocompleteDeluxeWidget::create public static function Creates an instance of the plugin. Overrides WidgetBase::create
AutocompleteDeluxeWidget::defaultSettings public static function Defines the default settings for this plugin. Overrides PluginSettingsBase::defaultSettings
AutocompleteDeluxeWidget::formElement public function Returns the form for a single field widget. Overrides WidgetInterface::formElement
AutocompleteDeluxeWidget::getAutocreateBundle protected function Returns the name of the bundle which will be used for autocreated entities.
AutocompleteDeluxeWidget::getMatchOperatorOptions protected function Returns the options for the match operator.
AutocompleteDeluxeWidget::getSelectionHandlerSetting protected function Returns the value of a setting for the entity reference selection handler.
AutocompleteDeluxeWidget::implodeEntities public static function Implodes the tags from the taxonomy module.
AutocompleteDeluxeWidget::massageFormValues public function Massages the form values into the format expected for field values. Overrides WidgetBase::massageFormValues
AutocompleteDeluxeWidget::settingsForm public function Returns a form to configure settings for the widget. Overrides WidgetBase::settingsForm
AutocompleteDeluxeWidget::settingsSummary public function Returns a short summary for the current widget settings. Overrides WidgetBase::settingsSummary
AutocompleteDeluxeWidget::validateInteger public static function Form element validation handler for integer textfields.
AutocompleteDeluxeWidget::validateIntegerPositive public static function Form element validation handler for positive integer textfields.
AutocompleteDeluxeWidget::__construct public function Overrides WidgetBase::__construct
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 2
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 27
MessengerTrait::messenger public function Gets the messenger. 27
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 2
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.
PluginSettingsBase::$defaultSettingsMerged protected property Whether default settings have been merged into the current $settings.
PluginSettingsBase::$thirdPartySettings protected property The plugin settings injected by third party modules.
PluginSettingsBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies 6
PluginSettingsBase::getSetting public function Returns the value of a setting, or its default value if absent. Overrides PluginSettingsInterface::getSetting
PluginSettingsBase::getSettings public function Returns the array of settings, including defaults for missing settings. Overrides PluginSettingsInterface::getSettings
PluginSettingsBase::getThirdPartyProviders public function Gets the list of third parties that store information. Overrides ThirdPartySettingsInterface::getThirdPartyProviders
PluginSettingsBase::getThirdPartySetting public function Gets the value of a third-party setting. Overrides ThirdPartySettingsInterface::getThirdPartySetting
PluginSettingsBase::getThirdPartySettings public function Gets all third-party settings of a given module. Overrides ThirdPartySettingsInterface::getThirdPartySettings
PluginSettingsBase::mergeDefaults protected function Merges default settings values into $settings.
PluginSettingsBase::onDependencyRemoval public function Informs the plugin that some configuration it depends on will be deleted. Overrides PluginSettingsInterface::onDependencyRemoval 3
PluginSettingsBase::setSetting public function Sets the value of a setting for the plugin. Overrides PluginSettingsInterface::setSetting
PluginSettingsBase::setSettings public function Sets the settings for the plugin. Overrides PluginSettingsInterface::setSettings
PluginSettingsBase::setThirdPartySetting public function Sets the value of a third-party setting. Overrides ThirdPartySettingsInterface::setThirdPartySetting
PluginSettingsBase::unsetThirdPartySetting public function Unsets a third-party setting. Overrides ThirdPartySettingsInterface::unsetThirdPartySetting
StringTranslationTrait::$stringTranslation protected property The string translation service. 4
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.
WidgetBase::$fieldDefinition protected property The field definition.
WidgetBase::$settings protected property The widget settings. Overrides PluginSettingsBase::$settings
WidgetBase::addMoreAjax public static function Ajax callback for the "Add another item" button.
WidgetBase::addMoreSubmit public static function Submission handler for the "Add another item" button.
WidgetBase::afterBuild public static function After-build handler for field elements in a form.
WidgetBase::errorElement public function Assigns a field-level validation error to the right widget sub-element. Overrides WidgetInterface::errorElement 8
WidgetBase::extractFormValues public function Extracts field values from submitted form values. Overrides WidgetBaseInterface::extractFormValues 2
WidgetBase::flagErrors public function Reports field-level validation errors against actual form elements. Overrides WidgetBaseInterface::flagErrors 2
WidgetBase::form public function Creates a form element for a field. Overrides WidgetBaseInterface::form 3
WidgetBase::formMultipleElements protected function Special handling to create form elements for multiple values. 1
WidgetBase::formSingleElement protected function Generates the form element for a single copy of the widget.
WidgetBase::getFieldSetting protected function Returns the value of a field setting.
WidgetBase::getFieldSettings protected function Returns the array of field settings.
WidgetBase::getFilteredDescription protected function Returns the filtered field description.
WidgetBase::getWidgetState public static function Retrieves processing information about the widget from $form_state. Overrides WidgetBaseInterface::getWidgetState
WidgetBase::getWidgetStateParents protected static function Returns the location of processing information within $form_state.
WidgetBase::handlesMultipleValues protected function Returns whether the widget handles multiple values.
WidgetBase::isApplicable public static function Returns if the widget can be used for the provided field. Overrides WidgetInterface::isApplicable 4
WidgetBase::isDefaultValueWidget protected function Returns whether the widget used for default value form.
WidgetBase::setWidgetState public static function Stores processing information about the widget in $form_state. Overrides WidgetBaseInterface::setWidgetState