You are here

public static function WebformMultiple::processWebformMultiple in Webform 8.5

Same name and namespace in other branches
  1. 6.x src/Element/WebformMultiple.php \Drupal\webform\Element\WebformMultiple::processWebformMultiple()

Process items and build multiple elements widget.

1 call to WebformMultiple::processWebformMultiple()
WebformSubmissionViews::processWebformMultiple in src/Element/WebformSubmissionViews.php
Process items and build multiple elements widget.
1 method overrides WebformMultiple::processWebformMultiple()
WebformSubmissionViews::processWebformMultiple in src/Element/WebformSubmissionViews.php
Process items and build multiple elements widget.

File

src/Element/WebformMultiple.php, line 94

Class

WebformMultiple
Provides a webform element to assist in creation of multiple elements.

Namespace

Drupal\webform\Element

Code

public static function processWebformMultiple(&$element, FormStateInterface $form_state, &$complete_form) {

  // Set tree.
  $element['#tree'] = TRUE;

  // Remove 'for' from the element's label.
  $element['#label_attributes']['webform-remove-for-attribute'] = TRUE;

  // Set min items based on when the element is required.
  if (!isset($element['#min_items']) || $element['#min_items'] === '') {
    $element['#min_items'] = empty($element['#required']) ? 0 : 1;
  }

  // Make sure min items does not exceed cardinality.
  if (!empty($element['#cardinality']) && $element['#min_items'] > $element['#cardinality']) {
    $element['#min_items'] = $element['#cardinality'];
  }

  // Make sure empty items does not exceed cardinality.
  if (!empty($element['#cardinality']) && $element['#empty_items'] > $element['#cardinality']) {
    $element['#empty_items'] = $element['#cardinality'];
  }

  // If the number of default values exceeds the min items and has required
  // sub-elements, set empty items to 0.
  if (isset($element['#default_value']) && is_array($element['#default_value']) && count($element['#default_value']) >= $element['#min_items'] && static::hasRequireElement($element['#element'])) {
    $element['#empty_items'] = 0;
  }

  // Add validate callback that extracts the array of items.
  $element += [
    '#element_validate' => [],
  ];
  array_unshift($element['#element_validate'], [
    get_called_class(),
    'validateWebformMultiple',
  ]);

  // Wrap this $element in a <div> that handle #states.
  WebformElementHelper::fixStatesWrapper($element);

  // Get unique key used to store the current number of items.
  $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items');

  // Store the number of items which is the number of
  // #default_values + number of empty_items.
  if ($form_state
    ->get($number_of_items_storage_key) === NULL) {
    if (empty($element['#default_value']) || !is_array($element['#default_value'])) {
      $number_of_default_values = 0;
    }
    else {
      $number_of_default_values = count($element['#default_value']);
    }
    $number_of_empty_items = (int) $element['#empty_items'];
    $number_of_items = $number_of_default_values + $number_of_empty_items;

    // Make sure number of items is greated than min items.
    $min_items = (int) $element['#min_items'];
    $number_of_items = $number_of_items < $min_items ? $min_items : $number_of_items;

    // Make sure number of (default) items does not exceed cardinality.
    if (!empty($element['#cardinality']) && $number_of_items > $element['#cardinality']) {
      $number_of_items = $element['#cardinality'];
    }
    $form_state
      ->set($number_of_items_storage_key, $number_of_items);
  }
  $number_of_items = $form_state
    ->get($number_of_items_storage_key);
  $table_id = implode('_', $element['#parents']) . '_table';

  // Disable add operation when #cardinality is met
  // and make sure to limit the number of items.
  if (!empty($element['#cardinality']) && $number_of_items >= $element['#cardinality']) {
    $element['#add'] = FALSE;
    $number_of_items = $element['#cardinality'];
    $form_state
      ->set($number_of_items_storage_key, $number_of_items);
  }

  // Add wrapper to the element.
  $ajax_attributes = $element['#ajax_attributes'];
  $ajax_attributes['id'] = $table_id;
  $element += [
    '#prefix' => '',
    '#suffix' => '',
  ];
  $element['#ajax_prefix'] = '<div' . new Attribute($ajax_attributes) . '>';
  $element['#ajax_suffix'] = '</div>';
  $element['#prefix'] = $element['#prefix'] . $element['#ajax_prefix'];
  $element['#suffix'] = $element['#ajax_suffix'] . $element['#suffix'];

  // DEBUG:
  // Disable Ajax callback by commenting out the below callback and wrapper.
  $ajax_settings = [
    'callback' => [
      get_called_class(),
      'ajaxCallback',
    ],
    'wrapper' => $table_id,
    'progress' => [
      'type' => 'none',
    ],
  ];

  // Initialize, prepare, and finalize sub-elements.
  static::initializeElement($element, $form_state, $complete_form);

  // Build (single) element header.
  $header = static::buildElementHeader($element);

  // Build (single) element rows.
  $row_index = 0;
  $weight = 0;
  $rows = [];
  if (!$form_state
    ->isProcessingInput() && isset($element['#default_value']) && is_array($element['#default_value'])) {
    $default_values = $element['#default_value'];
  }
  elseif ($form_state
    ->isProcessingInput() && isset($element['#value']) && is_array($element['#value'])) {
    $default_values = $element['#value'];
  }
  else {
    $default_values = [];
  }

  // When adding/removing elements we don't need to set any default values.
  $action_key = static::getStorageKey($element, 'action');
  if ($form_state
    ->get($action_key)) {
    $form_state
      ->set($action_key, FALSE);
    $default_values = [];
  }
  foreach ($default_values as $key => $default_value) {

    // If #key is defined make sure to set default value's key item.
    if (!empty($element['#key']) && !isset($default_value[$element['#key']])) {
      $default_value[$element['#key']] = $key;
    }
    $rows[$row_index] = static::buildElementRow($table_id, $row_index, $element, $default_value, $weight++, $ajax_settings);
    $row_index++;
  }
  while ($row_index < $number_of_items) {
    $rows[$row_index] = static::buildElementRow($table_id, $row_index, $element, NULL, $weight++, $ajax_settings);
    $row_index++;
  }

  // Build table.
  $table_wrapper_attributes = $element['#table_wrapper_attributes'];
  $table_wrapper_attributes['class'][] = 'webform-multiple-table';
  if (count($element['#element']) > 1) {
    $table_wrapper_attributes['class'][] = 'webform-multiple-table-responsive';
  }
  $element['items'] = [
    '#prefix' => '<div' . new Attribute($table_wrapper_attributes) . '>',
    '#suffix' => '</div>',
  ] + $rows;

  // Display table if there are any rows.
  if ($rows) {
    $element['items'] += [
      '#type' => 'table',
      '#header' => $header,
      '#attributes' => $element['#table_attributes'],
    ] + $rows;

    // Add sorting to table.
    if ($element['#sorting']) {
      $element['items']['#tabledrag'] = [
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'webform-multiple-sort-weight',
        ],
      ];
    }
  }
  elseif (!empty($element['#no_items_message'])) {
    $element['items'] += [
      '#type' => 'webform_message',
      '#message_message' => $element['#no_items_message'],
      '#message_type' => 'info',
      '#attributes' => [
        'class' => [
          'webform-multiple-table--no-items-message',
        ],
      ],
    ];
  }

  // Build add more actions.
  if ($element['#add_more'] && (empty($element['#cardinality']) || $number_of_items < $element['#cardinality'])) {
    $element['add'] = [
      '#prefix' => '<div class="webform-multiple-add js-webform-multiple-add container-inline">',
      '#suffix' => '</div>',
    ];
    $element['add']['submit'] = [
      '#type' => 'submit',
      '#value' => $element['#add_more_button_label'],
      '#limit_validation_errors' => [],
      '#submit' => [
        [
          get_called_class(),
          'addItemsSubmit',
        ],
      ],
      '#ajax' => $ajax_settings,
      '#name' => $table_id . '_add',
    ];
    $max = $element['#cardinality'] ? $element['#cardinality'] - $number_of_items : 100;
    $element['add']['more_items'] = [
      '#type' => 'number',
      '#title' => $element['#add_more_button_label'] . ' ' . $element['#add_more_input_label'],
      '#title_display' => 'invisible',
      '#min' => 1,
      '#max' => $max,
      '#default_value' => $element['#add_more_items'],
      '#field_suffix' => $element['#add_more_input_label'],
      '#error_no_message' => TRUE,
      '#access' => $element['#add_more_input'],
    ];
  }
  $element['#attached']['library'][] = 'webform/webform.element.multiple';
  return $element;
}