Commit 1153746d authored by Jacob Rockowitz's avatar Jacob Rockowitz Committed by Jacob Rockowitz
Browse files

Issue #2984983 by jrockowitz: Required fields inside a composite are validated...

Issue #2984983 by jrockowitz: Required fields inside a composite are validated for empty rows when "Allowed number of values" is limited to a specific number
parent 3af61a05
Loading
Loading
Loading
Loading
+31 −14
Changes for src/Element/WebformMultiple.php: 31 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -94,9 +94,14 @@ class WebformMultiple extends FormElement {
      $element['#min_items'] = (empty($element['#required'])) ? 0 : 1;
    }

    // Disable operation when #cardinality is set.
    if (!empty($element['#cardinality'])) {
      $element['#operations'] = FALSE;
    // 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'];
    }

    // Add validate callback that extracts the array of items.
@@ -106,11 +111,6 @@ class WebformMultiple extends FormElement {
    // Wrap this $element in a <div> that handle #states.
    WebformElementHelper::fixStatesWrapper($element);

    if ($element['#cardinality']) {
      // If the cardinality is set limit number of items to this value.
      $number_of_items = $element['#cardinality'];
    }
    else {
    // Get unique key used to store the current number of items.
    $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items');

@@ -126,17 +126,33 @@ class WebformMultiple extends FormElement {
      $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.
    if (!empty($element['#cardinality']) && $number_of_items >= $element['#cardinality']) {
      $element['#add'] = FALSE;
    }

    // Add wrapper to the element
    $element += [
      '#prefix' => '<div id="' . $table_id .'">',
      '#suffix' => '</div>',
    ];

    // DEBUG:
    // Disable Ajax callback by commenting out the below callback and wrapper.
    $ajax_settings = [
@@ -188,7 +204,7 @@ class WebformMultiple extends FormElement {
    }

    // Build table.
    $attributes = ['id' => $table_id, 'class' => ['webform-multiple-table']];
    $attributes = ['class' => ['webform-multiple-table']];
    if (count($element['#element']) > 1) {
      $attributes['class'][] = 'webform-multiple-table-responsive';
    }
@@ -225,7 +241,7 @@ class WebformMultiple extends FormElement {
    }

    // Build add items actions.
    if (empty($element['#cardinality'])) {
    if (empty($element['#cardinality']) || ($number_of_items < $element['#cardinality'])) {
      $element['add'] = [
        '#prefix' => '<div class="webform-multiple-add js-webform-multiple-add container-inline">',
        '#suffix' => '</div>',
@@ -238,12 +254,13 @@ class WebformMultiple extends FormElement {
        '#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' => 100,
        '#max' => $max,
        '#default_value' => $element['#add_more'],
        '#field_suffix' => $element['#add_more_input_label'],
        '#error_no_message' => TRUE,
@@ -837,7 +854,7 @@ class WebformMultiple extends FormElement {
    $button = $form_state->getTriggeringElement();
    $parent_length = (isset($button['#row_index'])) ? -4 : -2;
    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, $parent_length));
    return $element['items'];
    return $element;
  }

  /**
@@ -852,7 +869,7 @@ class WebformMultiple extends FormElement {

    $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items');
    $number_of_items = $form_state->get($number_of_items_storage_key);
    if ($number_of_items || $element['#cardinality']) {
    if (!empty($values['items']) && ($number_of_items || $element['#cardinality'])) {
      $items = $values['items'];

      // Validate unique keys.
+2 −1
Changes for src/Tests/Composite/WebformCompositeCustomTest.php: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ class WebformCompositeCustomTest extends WebformTestBase {

    // Check basic custom composite.
    $this->assertRaw('<label for="edit-webform-custom-composite-basic">webform_custom_composite_basic</label>');
    $this->assertRaw('<div id="webform_custom_composite_basic_table" class="webform-multiple-table webform-multiple-table-responsive">');
    $this->assertRaw('<div id="webform_custom_composite_basic_table">');
    $this->assertRaw('<div class="webform-multiple-table webform-multiple-table-responsive">');
    $this->assertRaw('<th class="webform_custom_composite_basic-table--handle webform-multiple-table--handle"><span class="visually-hidden">Re-order</span></th>');
    $this->assertRaw('<th class="webform_custom_composite_basic-table--first_name webform-multiple-table--first_name">First name</th>');
    $this->assertRaw('<th class="webform_custom_composite_basic-table--last_name webform-multiple-table--last_name">Last name</th>');
+11 −0
Changes for src/Tests/Element/WebformElementValidateMultipleTest.php: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -24,6 +24,17 @@ class WebformElementValidateMultipleTest extends WebformElementTestBase {

    // Check that only three textfields are displayed.
    $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]');
    $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][1][_item_]');
    $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][2][_item_]');
    $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]');
    $this->assertNoFieldByName('webform_element_multiple_textfield_three_table_add');

    // Add 2 more items.
    $edit = [
      'webform_element_multiple_textfield_three[add][more_items]' => 2
    ];
    $this->drupalPostAjaxForm(NULL, $edit, 'webform_element_multiple_textfield_three_table_add');
    $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]');
    $this->assertFieldByName('webform_element_multiple_textfield_three[items][1][_item_]');
    $this->assertFieldByName('webform_element_multiple_textfield_three[items][2][_item_]');
    $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]');
+8 −1
Changes for src/Tests/Element/WebformElementValidateUniqueTest.php: 8 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -62,13 +62,20 @@ class WebformElementValidateUniqueTest extends WebformElementTestBase {
    $this->assertNoRaw('unique_error error message.');
    $this->assertNoRaw('unique_ignored error message.');


    // Check #unique multiple validation within the same element.
    // @see \Drupal\webform\Plugin\WebformElementBase::validateUniqueMultiple
    // Add 2 more items.
    $edit = [
      'unique_textfield_multiple[add][more_items]' => 2
    ];
    $this->drupalPostAjaxForm('webform/test_element_validate_unique', $edit, 'unique_textfield_multiple_table_add');

    $edit = [
      'unique_textfield_multiple[items][0][_item_]' => '{same}',
      'unique_textfield_multiple[items][2][_item_]' => '{same}',
    ];
    $this->postSubmission($webform, $edit);
    $this->drupalPostForm(NULL, $edit, t('Submit'));
    $this->assertRaw('unique_textfield_multiple error message.');;

    // Purge existing submissions.