Same name and namespace in other branches
  1. 8.9.x core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::form()
  2. 9 core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::form()

Creates a form element for a field.

If the entity associated with the form is new (i.e., $entity->isNew() is TRUE), the 'default value', if any, is pre-populated. Also allows other modules to alter the form element by implementing their own hooks.

Parameters

\Drupal\Core\Field\FieldItemListInterface $items: An array of the field values. When creating a new entity this may be NULL or an empty array to use default values.

array $form: An array representing the form that the editing element will be attached to.

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

int $get_delta: Used to get only a specific delta value of a multiple value field.

Return value

array The form element array created for this field.

Overrides WidgetBaseInterface::form

File

core/lib/Drupal/Core/Field/WidgetBase.php, line 70

Class

WidgetBase
Base class for 'Field widget' plugin implementations.

Namespace

Drupal\Core\Field

Code

public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
  $field_name = $this->fieldDefinition
    ->getName();
  $parents = $form['#parents'];
  if (!($field_state = static::getWidgetState($parents, $field_name, $form_state))) {
    $field_state = [
      'items_count' => count($items),
      'array_parents' => [],
    ];
    static::setWidgetState($parents, $field_name, $form_state, $field_state);
  }

  // Remove deleted items from the field item list.
  if (isset($field_state['deleted_item']) && $items
    ->get($field_state['deleted_item'])) {
    $items
      ->removeItem($field_state['deleted_item']);
    unset($field_state['deleted_item']);
    static::setWidgetState($parents, $field_name, $form_state, $field_state);
  }

  // Collect widget elements.
  $elements = [];

  // If the widget is handling multiple values (e.g Options), or if we are
  // displaying an individual element, just get a single form element and make
  // it the $delta value.
  if ($this
    ->handlesMultipleValues() || isset($get_delta)) {
    $delta = $get_delta ?? 0;
    $element = [
      '#title' => $this->fieldDefinition
        ->getLabel(),
      '#description' => $this
        ->getFilteredDescription(),
    ];
    $element = $this
      ->formSingleElement($items, $delta, $element, $form, $form_state);
    if ($element) {
      if (isset($get_delta)) {

        // If we are processing a specific delta value for a field where the
        // field module handles multiples, set the delta in the result.
        $elements[$delta] = $element;
      }
      else {

        // For fields that handle their own processing, we cannot make
        // assumptions about how the field is structured, just merge in the
        // returned element.
        $elements = $element;
      }
    }
  }
  else {
    $elements = $this
      ->formMultipleElements($items, $form, $form_state);
  }

  // Populate the 'array_parents' information in $form_state->get('field')
  // after the form is built, so that we catch changes in the form structure
  // performed in alter() hooks.
  $elements['#after_build'][] = [
    static::class,
    'afterBuild',
  ];
  $elements['#field_name'] = $field_name;
  $elements['#field_parents'] = $parents;

  // Enforce the structure of submitted values.
  $elements['#parents'] = array_merge($parents, [
    $field_name,
  ]);

  // Most widgets need their internal structure preserved in submitted values.
  $elements += [
    '#tree' => TRUE,
  ];
  $field_widget_complete_form = [
    // Aid in theming of widgets by rendering a classified container.
    '#type' => 'container',
    // Assign a different parent, to keep the main id for the widget itself.
    '#parents' => array_merge($parents, [
      $field_name . '_wrapper',
    ]),
    '#attributes' => [
      'class' => [
        'field--type-' . Html::getClass($this->fieldDefinition
          ->getType()),
        'field--name-' . Html::getClass($field_name),
        'field--widget-' . Html::getClass($this
          ->getPluginId()),
      ],
    ],
    'widget' => $elements,
  ];

  // Allow modules to alter the field widget form element.
  $context = [
    'form' => $form,
    'widget' => $this,
    'items' => $items,
    'default' => $this
      ->isDefaultValueWidget($form_state),
  ];
  \Drupal::moduleHandler()
    ->alter([
    'field_widget_complete_form',
    'field_widget_complete_' . $this
      ->getPluginId() . '_form',
  ], $field_widget_complete_form, $form_state, $context);
  return $field_widget_complete_form;
}