abstract class OptionsWidgetBase

Base class for the 'options_*' widgets.

Hierarchy

Expanded class hierarchy of OptionsWidgetBase

1 file declares its use of OptionsWidgetBase
options.module in drupal/core/modules/options/options.module
Defines selection, check box and radio button widgets for text and numeric fields.

File

drupal/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php, line 16
Contains \Drupal\options\Plugin\field\widget\OptionsWidgetBase.

Namespace

Drupal\options\Plugin\field\widget
View source
abstract class OptionsWidgetBase extends WidgetBase {

  /**
   * Identifies a 'None' option.
   */
  const OPTIONS_EMPTY_NONE = 'option_none';

  /**
   * Identifies a 'Select a value' option.
   */
  const OPTIONS_EMPTY_SELECT = 'option_select';

  /**
   * Abstract over the actual field columns, to allow different field types to
   * reuse those widgets.
   *
   * @var string
   */
  protected $column;

  /**
   * {@inheritdoc}
   */
  public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) {
    parent::__construct($plugin_id, $plugin_definition, $instance, $settings);

    // Reset internal pointer since we're dealing with objects now.
    reset($this->field['columns']);
    $this->column = key($this->field['columns']);
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {

    // Prepare some properties for the child methods to build the actual form
    // element.
    $this->entity = $element['#entity'];
    $this->required = $element['#required'];
    $this->multiple = $this->field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $this->field['cardinality'] > 1;
    $this->has_value = isset($items[0][$this->column]);

    // Add our custom validator.
    $element['#element_validate'][] = array(
      get_class($this),
      'validateElement',
    );
    $element['#key_column'] = $this->column;

    // The rest of the $element is built by child method implementations.
    return $element;
  }

  /**
   * Form validation handler for widget elements.
   *
   * @param array $element
   *   The form element.
   * @param array $form_state
   *   The form state.
   */
  public static function validateElement(array $element, array &$form_state) {
    if ($element['#required'] && $element['#value'] == '_none') {
      form_error($element, t('!name field is required.', array(
        '!name' => $element['#title'],
      )));
    }

    // Massage submitted form values.
    // Drupal\field\Plugin\Type\Widget\WidgetBase::submit() expects values as
    // an array of values keyed by delta first, then by column, while our
    // widgets return the opposite.
    if (is_array($element['#value'])) {
      $values = array_values($element['#value']);
    }
    else {
      $values = array(
        $element['#value'],
      );
    }

    // Filter out the 'none' option. Use a strict comparison, because
    // 0 == 'any string'.
    $index = array_search('_none', $values, TRUE);
    if ($index !== FALSE) {
      unset($values[$index]);
    }

    // Transpose selections from field => delta to delta => field.
    $items = array();
    foreach ($values as $value) {
      $items[] = array(
        $element['#key_column'] => $value,
      );
    }
    form_set_value($element, $items, $form_state);
  }

  /**
   * Returns the array of options for the widget.
   *
   * @return array
   *   The array of options for the widget.
   */
  protected function getOptions() {
    if (!isset($this->options)) {
      $module_handler = \Drupal::moduleHandler();

      // Get the list of options from the field type module, and sanitize them.
      $options = (array) $module_handler
        ->invoke($this->field['module'], 'options_list', array(
        $this->field,
        $this->instance,
        $this->entity,
      ));

      // Add an empty option if the widget needs one.
      if ($empty_option = $this
        ->getEmptyOption()) {
        switch ($this
          ->getPluginId()) {
          case 'options_buttons':
            $label = t('N/A');
            break;
          case 'options_select':
            $label = $empty_option == static::OPTIONS_EMPTY_NONE ? t('- None -') : t('- Select a value -');
            break;
        }
        $options = array(
          '_none' => $label,
        ) + $options;
      }
      $context = array(
        'field' => $this->field,
        'instance' => $this->instance,
        'entity' => $this->entity,
      );
      $module_handler
        ->alter('options_list', $options, $context);
      array_walk_recursive($options, array(
        $this,
        'sanitizeLabel',
      ));

      // Options might be nested ("optgroups"). If the widget does not support
      // nested options, flatten the list.
      if (!$this
        ->supportsGroups()) {
        $options = $this
          ->flattenOptions($options);
      }
      $this->options = $options;
    }
    return $this->options;
  }

  /**
   * Determines selected options from the incoming field values.
   *
   * @param array $items
   *   The field values.
   *
   * @return array
   *   The array of corresponding selected options.
   */
  protected function getSelectedOptions(array $items) {

    // We need to check against a flat list of options.
    $flat_options = $this
      ->flattenOptions($this
      ->getOptions());
    $selected_options = array();
    foreach ($items as $item) {
      $value = $item[$this->column];

      // Keep the value if it actually is in the list of options (needs to be
      // checked against the flat list).
      if (isset($flat_options[$value])) {
        $selected_options[] = $value;
      }
    }
    return $selected_options;
  }

  /**
   * Flattens an array of allowed values.
   *
   * @param array $array
   *   A single or multidimensional array.
   *
   * @return array
   *   The flattened array.
   */
  protected function flattenOptions(array $array) {
    $result = array();
    array_walk_recursive($array, function ($a, $b) use (&$result) {
      $result[$b] = $a;
    });
    return $result;
  }

  /**
   * Indicates whether the widgets support optgroups.
   *
   * @return bool
   *   TRUE if the widget supports optgroups, FALSE otherwise.
   */
  protected function supportsGroups() {
    return FALSE;
  }

  /**
   * Sanitizes a string label to display as an option.
   *
   * @param string $label
   *   The label to sanitize.
   */
  protected static function sanitizeLabel(&$label) {

    // Allow a limited set of HTML tags.
    $label = field_filter_xss($label);
  }

  /**
   * Returns the empty option to add to the list of options, if any.
   *
   * @return string|null
   *   Either static::OPTIONS_EMPTY_NONE, static::OPTIONS_EMPTY_SELECT, or NULL.
   */
  protected function getEmptyOption() {
  }

}

Members

Namesort descending Modifiers Type Description Overrides
OptionsWidgetBase::$column protected property Abstract over the actual field columns, to allow different field types to reuse those widgets.
OptionsWidgetBase::flattenOptions protected function Flattens an array of allowed values.
OptionsWidgetBase::formElement public function Returns the form for a single field widget. Overrides WidgetInterface::formElement 3
OptionsWidgetBase::getEmptyOption protected function Returns the empty option to add to the list of options, if any. 2
OptionsWidgetBase::getOptions protected function Returns the array of options for the widget.
OptionsWidgetBase::getSelectedOptions protected function Determines selected options from the incoming field values.
OptionsWidgetBase::OPTIONS_EMPTY_NONE constant Identifies a 'None' option.
OptionsWidgetBase::OPTIONS_EMPTY_SELECT constant Identifies a 'Select a value' option.
OptionsWidgetBase::sanitizeLabel protected static function Sanitizes a string label to display as an option. 1
OptionsWidgetBase::supportsGroups protected function Indicates whether the widgets support optgroups. 1
OptionsWidgetBase::validateElement public static function Form validation handler for widget elements.
OptionsWidgetBase::__construct public function Constructs a WidgetBase object. Overrides WidgetBase::__construct
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition.
PluginBase::$pluginId protected property The plugin_id.
PluginBase::getPluginDefinition public function Returns the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition
PluginBase::getPluginId public function Returns the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginSettingsBase::$defaultSettingsMerged protected property Whether default settings have been merged into the current $settings.
PluginSettingsBase::getDefaultSettings public function Implements Drupal\field\Plugin\PluginSettingsInterface::getDefaultSettings(). Overrides PluginSettingsInterface::getDefaultSettings
PluginSettingsBase::getSetting public function Implements Drupal\field\Plugin\PluginSettingsInterface::getSetting(). Overrides PluginSettingsInterface::getSetting
PluginSettingsBase::getSettings public function Implements Drupal\field\Plugin\PluginSettingsInterface::getSettings(). Overrides PluginSettingsInterface::getSettings
PluginSettingsBase::mergeDefaults protected function Merges default settings values into $settings.
PluginSettingsBase::setSetting public function Implements Drupal\field\Plugin\PluginSettingsInterface::setSetting(). Overrides PluginSettingsInterface::setSetting
PluginSettingsBase::setSettings public function Implements Drupal\field\Plugin\PluginSettingsInterface::setSettings(). Overrides PluginSettingsInterface::setSettings
WidgetBase::$field protected property The field definition.
WidgetBase::$instance protected property The field instance definition.
WidgetBase::$settings protected property The widget settings. Overrides PluginSettingsBase::$settings
WidgetBase::errorElement public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement(). Overrides WidgetInterface::errorElement 5
WidgetBase::extractFormValues public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::extractFormValues(). Overrides WidgetBaseInterface::extractFormValues
WidgetBase::flagErrors public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::flagErrors(). Overrides WidgetBaseInterface::flagErrors
WidgetBase::form public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::form(). Overrides WidgetBaseInterface::form
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::massageFormValues public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::massageFormValues() Overrides WidgetInterface::massageFormValues 2
WidgetBase::settingsForm public function Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). Overrides WidgetInterface::settingsForm 13
WidgetBase::sortItems protected function Sorts submitted field values according to drag-n-drop reordering.