You are here

protected function FileWidget::formMultipleElements in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php \Drupal\file\Plugin\Field\FieldWidget\FileWidget::formMultipleElements()
  2. 9 core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php \Drupal\file\Plugin\Field\FieldWidget\FileWidget::formMultipleElements()

Overrides \Drupal\Core\Field\WidgetBase::formMultipleElements().

Special handling for draggable multiple widgets and 'add more' button.

Overrides WidgetBase::formMultipleElements

File

core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php, line 88

Class

FileWidget
Plugin implementation of the 'file_generic' widget.

Namespace

Drupal\file\Plugin\Field\FieldWidget

Code

protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
  $field_name = $this->fieldDefinition
    ->getName();
  $parents = $form['#parents'];

  // Load the items for form rebuilds from the field state as they might not
  // be in $form_state->getValues() because of validation limitations. Also,
  // they are only passed in as $items when editing existing entities.
  $field_state = static::getWidgetState($parents, $field_name, $form_state);
  if (isset($field_state['items'])) {
    $items
      ->setValue($field_state['items']);
  }

  // Determine the number of widgets to display.
  $cardinality = $this->fieldDefinition
    ->getFieldStorageDefinition()
    ->getCardinality();
  switch ($cardinality) {
    case FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED:
      $max = count($items);
      $is_multiple = TRUE;
      break;
    default:
      $max = $cardinality - 1;
      $is_multiple = $cardinality > 1;
      break;
  }
  $title = $this->fieldDefinition
    ->getLabel();
  $description = $this
    ->getFilteredDescription();
  $elements = [];
  $delta = 0;

  // Add an element for every existing item.
  foreach ($items as $item) {
    $element = [
      '#title' => $title,
      '#description' => $description,
    ];
    $element = $this
      ->formSingleElement($items, $delta, $element, $form, $form_state);
    if ($element) {

      // Input field for the delta (drag-n-drop reordering).
      if ($is_multiple) {

        // We name the element '_weight' to avoid clashing with elements
        // defined by widget.
        $element['_weight'] = [
          '#type' => 'weight',
          '#title' => t('Weight for row @number', [
            '@number' => $delta + 1,
          ]),
          '#title_display' => 'invisible',
          // Note: this 'delta' is the FAPI #type 'weight' element's property.
          '#delta' => $max,
          '#default_value' => $item->_weight ?: $delta,
          '#weight' => 100,
        ];
      }
      $elements[$delta] = $element;
      $delta++;
    }
  }
  $empty_single_allowed = $cardinality == 1 && $delta == 0;
  $empty_multiple_allowed = ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $delta < $cardinality) && !$form_state
    ->isProgrammed();

  // Add one more empty row for new uploads except when this is a programmed
  // multiple form as it is not necessary.
  if ($empty_single_allowed || $empty_multiple_allowed) {

    // Create a new empty item.
    $items
      ->appendItem();
    $element = [
      '#title' => $title,
      '#description' => $description,
    ];
    $element = $this
      ->formSingleElement($items, $delta, $element, $form, $form_state);
    if ($element) {
      $element['#required'] = $element['#required'] && $delta == 0;
      $elements[$delta] = $element;
    }
  }
  if ($is_multiple) {

    // The group of elements all-together need some extra functionality after
    // building up the full list (like draggable table rows).
    $elements['#file_upload_delta'] = $delta;
    $elements['#type'] = 'details';
    $elements['#open'] = TRUE;
    $elements['#theme'] = 'file_widget_multiple';
    $elements['#theme_wrappers'] = [
      'details',
    ];
    $elements['#process'] = [
      [
        static::class,
        'processMultiple',
      ],
    ];
    $elements['#title'] = $title;
    $elements['#description'] = $description;
    $elements['#field_name'] = $field_name;
    $elements['#language'] = $items
      ->getLangcode();

    // The field settings include defaults for the field type. However, this
    // widget is a base class for other widgets (e.g., ImageWidget) that may
    // act on field types without these expected settings.
    $field_settings = $this
      ->getFieldSettings() + [
      'display_field' => NULL,
    ];
    $elements['#display_field'] = (bool) $field_settings['display_field'];

    // Add some properties that will eventually be added to the file upload
    // field. These are added here so that they may be referenced easily
    // through a hook_form_alter().
    $elements['#file_upload_title'] = t('Add a new file');
    $elements['#file_upload_description'] = [
      '#theme' => 'file_upload_help',
      '#description' => '',
      '#upload_validators' => $elements[0]['#upload_validators'],
      '#cardinality' => $cardinality,
    ];
  }
  return $elements;
}