You are here

public function FieldStateManager::apply in Field States UI 8.2

Apply the field states to a form element.

Due to various form elements having different array structure, the states array has to be put in a different spot for different widgets. Most common locations are `value` and `target_id` or for multiple value forms, on the wrapper.

Parameters

array $element: The field widget form elements as constructed by \Drupal\Core\Field\WidgetBase::formMultipleElements().

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

array $context: An associative array containing the following key-value pairs:

  • form: The form structure to which widgets are being attached. This may be a full form structure, or a sub-element of a larger form.
  • widget: The widget plugin instance.
  • items: The field values, as a \Drupal\Core\Field\FieldItemListInterface object.
  • default: A boolean indicating whether the form is being shown as a dummy form to set default values.

See also

hook_field_widget_multivalue_form_alter().

File

src/FieldStateManager.php, line 81

Class

FieldStateManager
Manages field state plugins.

Namespace

Drupal\field_states_ui

Code

public function apply(&$element, FormStateInterface $form_state, $context) {

  /** @var \Drupal\Core\Field\PluginSettingsInterface $plugin */
  $plugin = $context['widget'];

  // Check that it is enabled for this field.
  if (empty($plugin
    ->getThirdPartySettings('field_states_ui')['field_states'])) {
    return;
  }
  $states = $plugin
    ->getThirdPartySettings('field_states_ui')['field_states'];

  /** @var \Drupal\Core\Field\FieldItemListInterface $field_item */
  $field_item = $context['items'];
  $field_definition = $field_item
    ->getFieldDefinition();
  $type = $field_definition
    ->getType();
  $plugin_id = $plugin
    ->getPluginId();

  // Handle the type of field appropriately.
  switch ($type) {
    case 'entity_reference':
      switch ($plugin_id) {
        case 'chosen_select':
        case 'options_select':
        case 'options_buttons':
        case 'media_library_widget':
          $target =& $element;
          break;
        case 'entity_browser_entity_reference':
          if (!isset($element[0])) {
            $target =& $element;
          }
          else {
            $target =& $element[0];
          }
          break;
        case 'entity_reference_autocomplete':
        case 'entity_reference_autocomplete_tags':
          if (!isset($element[0])) {
            $target =& $element['target_id'];
          }
          else {
            $target =& $element[0]['target_id'];
          }
          break;
        default:

          // Log a notice so that user(s) can report unrecognized field
          // plugin_id.
          $this->logger
            ->notice(t('Field type: "@type" with plugin_id "@id" was unrecognized. Please report on the @link. For quickest resolution, please include what module it comes from.', [
            '@type' => $type,
            '@id' => $plugin_id,
            '@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))
              ->toString(),
          ]));
          if (isset($element[0]['target_id'])) {
            $target =& $element[0]['target_id'];
          }
          elseif (isset($element['target_id'])) {
            $target =& $element['target_id'];
          }
          else {
            $target =& $element;
          }
          break;
      }
      break;
    case 'boolean':
      switch ($plugin_id) {
        case 'options_buttons':
          $target =& $element[0];
          break;
        case 'boolean_checkbox':
          $target =& $element['value'];
          break;
        default:
          $target =& $element[0]['value'];
          break;
      }
      break;
    case 'address_country':
    case 'decimal':
    case 'float':
    case 'integer':
    case 'string':
    case 'string_long':
      $target =& $element[0]['value'];
      break;
    case 'text_with_summary':
    case 'text_long':
    case 'list_float':
    case 'list_integer':
    case 'list_string':
    case 'link':
    case 'entity_reference_revisions':
    case 'datetime':
    case 'color_field_type':
    case 'address_zone':
    case 'address':
      if (!isset($element[0])) {
        $target =& $element;
      }
      else {
        $target =& $element[0];
      }
      break;
    case 'name':
      $target =& $element[0];
      $container = TRUE;
      break;
    default:

      // Log a notice so that user(s) can report unrecognized field types.
      $this->logger
        ->notice(t('Field type: "@type" was unrecognized. Please report on the @link. For quickest resolution, please include the element details: @details', [
        '@type' => $type,
        '@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))
          ->toString(),
        '@details' => var_export(array_keys($element[0]), TRUE),
      ]));
      $target =& $element[0];
      $container = TRUE;
      break;
  }
  if (!isset($target['#field_parents'])) {
    $parents = [];
    $this->logger
      ->notice(t('#field_parents key not found. This will may cause problems. If so, please report on the @link. For quickest resolution, please include the element details: @details', [
      '@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))
        ->toString(),
      '@details' => var_export(array_keys($element[0]), TRUE),
    ]));
  }
  else {
    $parents = $target['#field_parents'];
  }
  if (isset($element['#cardinality_multiple']) && $element['#cardinality_multiple']) {

    // Multiple widget field. Put states on the wrapper.
    $element = [
      'element' => $element,
      '#type' => 'container',
      '#states' => $this
        ->getStates($states, $form_state, $context, $element, $parents),
    ];
  }
  elseif (isset($container)) {

    // Add a container element and set states on that to ensure it works.
    // This increases divitis which is already common on Drupal forms so
    // it is better to handle the element properly. There are elements that it
    // does make sense to do this to (ie name) but avoid if possible.
    $element = [
      'element' => $element,
      '#type' => 'container',
      '#states' => $this
        ->getStates($states, $form_state, $context, $element, $parents),
    ];
  }
  else {
    $target['#states'] = $this
      ->getStates($states, $form_state, $context, $element, $parents);
  }
}