You are here

class ShsTermSelect in Webform Simple Hierarchical Select 8

Same name in this branch
  1. 8 src/Element/ShsTermSelect.php \Drupal\webform_shs\Element\ShsTermSelect
  2. 8 src/Plugin/WebformElement/ShsTermSelect.php \Drupal\webform_shs\Plugin\WebformElement\ShsTermSelect

Provides a webform element for an shs term select menu.

Plugin annotation

@FormElement("webform_shs_term_select");

Hierarchy

Expanded class hierarchy of ShsTermSelect

2 files declare their use of ShsTermSelect
ShsTermSelect.php in src/Plugin/WebformElement/ShsTermSelect.php
webform_shs.module in ./webform_shs.module
Webform component which renders a "shs" field.

File

src/Element/ShsTermSelect.php, line 14

Namespace

Drupal\webform_shs\Element
View source
class ShsTermSelect extends Select {

  /**
   * The list of term options.
   *
   * @var null|array
   */
  protected static $options = NULL;

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    return [
      '#vocabulary' => '',
      '#force_deepest' => FALSE,
      '#force_deepest_error' => '',
      '#cache_options' => FALSE,
      '#depth_labels' => [],
      '#addNewLabel' => '',
    ] + parent::getInfo();
  }

  /**
   * {@inheritdoc}
   */
  public static function processSelect(&$element, FormStateInterface $form_state, &$complete_form) {
    self::setOptions($element);
    $element = parent::processSelect($element, $form_state, $complete_form);

    // Must convert this element['#type'] to a 'select' to prevent
    // "Illegal choice %choice in %name element" validation error.
    // @see \Drupal\Core\Form\FormValidator::performRequiredValidation
    $element['#type'] = 'select';

    // AJAX errors occur when submitting the element config on the webform ui
    // path. \Drupal\shs\Plugin\Field\FieldWidget\OptionsShsWidget also stops
    // rendering on the field ui pages.
    $route = \Drupal::routeMatch()
      ->getRouteObject();
    if (\Drupal::service('router.admin_context')
      ->isAdminRoute($route)) {
      return $element;
    }
    $settings = [
      'required' => $element['#required'],
      'multiple' => $element['#webform_multiple'],
      'anyLabel' => $element['#empty_option'] ?? t('- None -'),
      'anyValue' => '_none',
      'force_deepest' => $element['#force_deepest'],
      'cache_options' => $element['#cache_options'],
      '#depth_labels' => [],
      'addNewLabel' => $element['#addNewLabel'] ?: t('Add another item'),
    ];

    /** @var \Drupal\shs\WidgetDefaults $widget_defaults */
    $widget_defaults = \Drupal::service('shs.widget_defaults');
    $bundle = $element['#vocabulary'];
    $cardinality = $element['#multiple'] ? -1 : 1;

    // Define default parents for the widget.
    $parents = $widget_defaults
      ->getInitialParentDefaults($settings['anyValue'], $cardinality);
    if (!is_null($element['#value'])) {
      $parents = $widget_defaults
        ->getParentDefaults($element['#value'], $settings['anyValue'], 'taxonomy_term', $cardinality);
    }
    $settings_shs = [
      'settings' => $settings,
      'labels' => $element['#depth_labels'],
      'bundle' => $bundle,
      'baseUrl' => 'shs-term-data',
      'cardinality' => $cardinality,
      'parents' => $parents,
      'defaultValue' => $element['#value'] ?? NULL,
    ];
    $hooks = [
      'shs_js_settings',
      sprintf('shs_%s_js_settings', $element['#webform_key']),
    ];

    // Allow other modules to override the settings.
    \Drupal::moduleHandler()
      ->alter($hooks, $settings_shs, $bundle, $element['#webform_key']);
    $element['#shs'] = $settings_shs;
    $element['#shs']['classes'] = shs_get_class_definitions($element['#webform_key']);
    $element['#attributes']['class'][] = 'shs-enabled';
    $element['#attributes']['data-shs-selector'] = $element['#webform_key'];
    $element['#attached']['library'][] = 'shs/shs.form';
    $element['#attached']['drupalSettings']['shs'] = [
      $element['#webform_key'] => $element['#shs'],
    ];
    $element['#element_validate'][] = [
      self::class,
      'validateForceDeepest',
    ];
    return $element;
  }

  /**
   * Form API callback. Validate the force deepest option.
   *
   * @param array $element
   *   The element.
   * @param FormStateInterface $form_state
   *   The form state.
   */
  public static function validateForceDeepest(array &$element, FormStateInterface $form_state) {
    if (empty($element['#force_deepest'])) {
      return;
    }
    if (!empty($element['#force_deepest_error'])) {
      $message = $element['#force_deepest_error'];
    }
    else {
      $message = t('You need to select a term from the deepest level in field @name.', [
        '@name' => $element['#title'],
      ]);
    }
    $value = $form_state
      ->getValue($element['#name']);
    if (!is_array($value)) {
      $value = [
        $value,
      ];
    }
    foreach ($value as $element_value) {

      // If nothing was selected.
      if ($element['#shs']['settings']['anyValue'] === $element_value) {

        // Skip this value row and check the next one.
        if (!$element['#required']) {
          continue;
        }
        elseif (count($element['#options']) > 1) {
          $form_state
            ->setError($element, $message);
          return;
        }
      }
      elseif (shs_term_has_children($element_value)) {
        $form_state
          ->setError($element, $message);
        return;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function setOptions(array &$element) {
    if (!empty($element['#options'])) {
      return;
    }
    if (!\Drupal::moduleHandler()
      ->moduleExists('taxonomy') || empty($element['#vocabulary'])) {
      $element['#options'] = [];
      return;
    }
    $element['#options'] = static::getOptions($element);
  }

  /**
   * Get options of all terms in given vocabulary.
   *
   * @param array $element
   *   The element.
   *
   * @return array
   *   An associative array of term options.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  protected static function getOptions(array $element) {
    return self::buildOptions($element['#vocabulary'], !empty($element['#cache_options']));
  }

  /**
   * Return an option cache ID for provided vocabulary.
   *
   * @param string $vid
   *   Vocabulary id.
   *
   * @return string
   *   Cache ID.
   */
  public static function getOptionsCacheId($vid) {
    return 'webform_shs:options:' . $vid;
  }

  /**
   * Invalidate options cache for provided vocabulary.
   *
   * @param string $vid
   *   Vocabulary id.
   */
  public static function invalidateOptionsCache($vid) {
    $cid = self::getOptionsCacheId($vid);
    \Drupal::cache()
      ->invalidate($cid);
  }

  /**
   * Build a list of term options for provided vocabulary.
   *
   * @param string $vid
   *   Vocabulary id.
   * @param bool $cache_options
   *   Should we use cache?
   *
   * @return array
   *   An associative array of terms, where keys are tid and values are
   *   term name.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  public static function buildOptions($vid, $cache_options = FALSE) {
    if ($cache_options) {
      $options = self::buildCachedTermOptions($vid);
    }
    else {
      $options = self::buildTermOptions($vid);
    }
    return $options;
  }

  /**
   * Build a cached list of term options for provided vocabulary.
   *
   * @param string $vid
   *   Vocabulary id.
   *
   * @return array
   *   Cached list of term options.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  protected static function buildCachedTermOptions($vid) {
    $cid = self::getOptionsCacheId($vid);
    if ($cache = \Drupal::cache()
      ->get($cid)) {
      $options = $cache->data;
    }
    else {
      $options = self::buildTermOptions($vid);
      \Drupal::cache()
        ->set($cid, $options, Cache::PERMANENT);
    }
    return $options;
  }

  /**
   * Build a list of term options for provided vocabulary.
   *
   * @param string $vid
   *   Vocabulary id.
   *
   * @return array
   *   List of term options.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   */
  protected static function buildTermOptions($vid) {
    $options = [];

    /** @var \Drupal\taxonomy\TermStorageInterface $taxonomy_storage */
    $taxonomy_storage = \Drupal::entityTypeManager()
      ->getStorage('taxonomy_term');
    $terms = $taxonomy_storage
      ->loadTree($vid);
    foreach ($terms as $item) {
      $options[$item->tid] = $item->name;
    }
    return $options;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
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::valueCallback public static function Determines how user input is mapped to an element's #value property. Overrides FormElement::valueCallback
ShsTermSelect::$options protected static property The list of term options.
ShsTermSelect::buildCachedTermOptions protected static function Build a cached list of term options for provided vocabulary.
ShsTermSelect::buildOptions public static function Build a list of term options for provided vocabulary.
ShsTermSelect::buildTermOptions protected static function Build a list of term options for provided vocabulary.
ShsTermSelect::getInfo public function Returns the element properties for this element. Overrides Select::getInfo
ShsTermSelect::getOptions protected static function Get options of all terms in given vocabulary.
ShsTermSelect::getOptionsCacheId public static function Return an option cache ID for provided vocabulary.
ShsTermSelect::invalidateOptionsCache public static function Invalidate options cache for provided vocabulary.
ShsTermSelect::processSelect public static function Processes a select list form element. Overrides Select::processSelect
ShsTermSelect::setOptions public static function
ShsTermSelect::validateForceDeepest public static function Form API callback. Validate the force deepest option.
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.