You are here

class CshsElement in Client-side Hierarchical Select 8

Same name and namespace in other branches
  1. 8.3 src/Element/CshsElement.php \Drupal\cshs\Element\CshsElement
  2. 8.2 src/Element/CshsElement.php \Drupal\cshs\Element\CshsElement

Defines the CSHS element.

Plugin annotation

@FormElement("cshs");

Hierarchy

Expanded class hierarchy of CshsElement

3 files declare their use of CshsElement
cshs.module in ./cshs.module
Client-side Hierarchical Select.
CshsOptionsFromHelper.php in src/CshsOptionsFromHelper.php
CshsTaxonomyIndex.php in src/Plugin/views/filter/CshsTaxonomyIndex.php

File

src/Element/CshsElement.php, line 16

Namespace

Drupal\cshs\Element
View source
class CshsElement extends Select {
  public const ID = 'cshs';
  public const NONE_VALUE = 'All';
  public const NONE_LABEL = '- Please select -';

  /**
   * {@inheritdoc}
   */
  public function getInfo() : array {
    $info = parent::getInfo();
    $info['#label'] = '';
    $info['#labels'] = [];
    $info['#parent'] = 0;
    $info['#force_deepest'] = FALSE;
    $info['#required_depth'] = 0;
    $info['#none_value'] = static::NONE_VALUE;

    // phpcs:ignore Drupal.Semantics.FunctionT.NotLiteralString
    $info['#none_label'] = $this
      ->t(static::NONE_LABEL);
    $info['#theme'] = static::ID;
    $info['#process'][] = [
      static::class,
      'processElement',
    ];
    $info['#pre_render'][] = [
      static::class,
      'preRender',
    ];
    $info['#element_validate'][] = [
      static::class,
      'validateElement',
    ];
    return $info;
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    return FALSE !== $input && NULL !== $input ? $input : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public static function processElement(array $element) : array {
    \assert(Inspector::assertAllStringable($element['#labels']));
    $element['#attached']['library'][] = 'cshs/cshs.base';
    $element['#attached']['drupalSettings'][static::ID][$element['#id']] = [
      'labels' => $element['#labels'],
      'noneLabel' => $element['#none_label'],
      'noneValue' => $element['#none_value'],
    ];
    static::setAttributes($element, [
      'simpler-select-root',
      'form-element',
      'form-element--type-select',
    ]);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function preRender(array $element) : array {
    $element['#options'] = static::formatOptions($element);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function validateElement(array &$element, FormStateInterface $form_state) : void {
    $term_id = $element['#value'];
    if (\is_array($term_id)) {
      $term_id = \end($term_id);
    }

    // The value is not selected.
    if (empty($term_id) || $term_id == $element['#none_value']) {

      // Element must have its "none" value when nothing selected. This will
      // let it function correctly, for instance with views. Otherwise it could
      // lead to illegal choice selection error.

      /* @link https://www.drupal.org/node/2882790 */
      $form_state
        ->setValueForElement($element, \is_a($form_state
        ->getFormObject(), ViewsExposedForm::class) ? $element['#none_value'] : NULL);

      // Set an error if user doesn't select anything and field is required.
      if ($element['#required']) {
        $form_state
          ->setError($element, \t('@label field is required.', [
          '@label' => $element['#label'],
        ]));
      }
    }
    elseif ($element['#force_deepest']) {
      $storage = static::getTermStorage();
      if (!$storage
        ->load($term_id)) {
        $form_state
          ->setError($element, \t('Unable to load a term (ID: @id) for the @label field.', [
          '@id' => $element['#value'],
          '@label' => $element['#label'],
        ]));
      }
      elseif (!empty($storage
        ->loadChildren($term_id))) {
        $form_state
          ->setError($element, \t('You need to select a term from the deepest level in @label field.', [
          '@label' => $element['#label'],
        ]));
      }
    }
    elseif ($element['#required_depth'] > 0) {
      $storage = static::getTermStorage();
      if (\count($storage
        ->loadAllParents($term_id)) < $element['#required_depth']) {
        $form_state
          ->setError($element, \t('The field @label requires you to select at least @level levels of hierarchy.', [
          '@label' => $element['#label'],
          '@level' => $element['#required_depth'],
        ]));
      }
    }
  }

  /**
   * {@inheritdoc}
   *
   * @see \form_select_options()
   */
  protected static function formatOptions(array $element) : array {
    $options = [];
    if (!empty($element['#options'])) {
      $parent = isset($element['#parent']) ? (string) $element['#parent'] : NULL;
      $is_value_valid = \array_key_exists('#value', $element);
      $is_value_array = $is_value_valid && \is_array($element['#value']);
      foreach ($element['#options'] as $value => $data) {
        $value = (string) $value;
        if ($is_value_valid) {
          $selected = $is_value_array ? \in_array($value, $element['#value']) : $value === (string) $element['#value'];
        }
        else {
          $selected = FALSE;
        }

        // The default `All` option coming from Views has `$data` as a string.
        if (\is_string($data)) {
          $data = [
            'name' => $data,
            'parent_tid' => 0,
          ];
        }
        $options[] = [
          'value' => $value,
          'label' => $data['name'],
          'parent' => (string) $data['parent_tid'] === $parent ? 0 : $data['parent_tid'],
          'selected' => $selected,
        ];
      }
    }
    return $options;
  }

  /**
   * Returns the "taxonomy_term" entities storage.
   *
   * @return \Drupal\taxonomy\TermStorageInterface
   *   The storage.
   */
  protected static function getTermStorage() : TermStorageInterface {
    return \Drupal::entityTypeManager()
      ->getStorage('taxonomy_term');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CshsElement::formatOptions protected static function
CshsElement::getInfo public function Returns the element properties for this element. Overrides Select::getInfo
CshsElement::getTermStorage protected static function Returns the "taxonomy_term" entities storage.
CshsElement::ID public constant
CshsElement::NONE_LABEL public constant
CshsElement::NONE_VALUE public constant
CshsElement::preRender public static function
CshsElement::processElement public static function
CshsElement::validateElement public static function
CshsElement::valueCallback public static function Determines how user input is mapped to an element's #value property. Overrides Select::valueCallback
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormElement::processAutocomplete public static function Adds autocomplete functionality to elements.
FormElement::processPattern public static function #process callback for #pattern form element property.
FormElement::validatePattern public static function #element_validate callback for #pattern form element property.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
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 3
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.
PluginBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. 92
RenderElement::preRenderAjaxForm public static function Adds Ajax information about an element to communicate with JavaScript.
RenderElement::preRenderGroup public static function Adds members of this group as actual elements for rendering.
RenderElement::processAjaxForm public static function Form element processing handler for the #ajax form property. 1
RenderElement::processGroup public static function Arranges elements into groups.
RenderElement::setAttributes public static function Sets a form element's class attribute. Overrides ElementInterface::setAttributes
Select::preRenderSelect public static function Prepares a select render element.
Select::processSelect public static function Processes a select list form element.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
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.