diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index 39daf849aa..53afc4e106 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -111,15 +111,6 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter $elements = $this->formMultipleElements($items, $form, $form_state); } - // Allow modules to alter the field multi-value widget form element. - // This hook can also be used for single-value fields. - $context = [ - 'form' => $form, - 'widget' => $this, - 'items' => $items, - 'default' => $this->isDefaultValueWidget($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. @@ -267,6 +258,31 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f 'effect' => 'fade', ], ]; + + // By default, the limit quantity is defined by quantity of items. + $optionsAvailable = $items->count(); + $emptyValues = $items->count() - count(array_filter($items->getValue())); + if (!$items->getEntity()->isNew()) { + // None options available when editing a field to avoid empty input field. + $optionsAvailable = 0; + $userInput = $form_state->getUserInput(); + $isAddingMore = isset($userInput["_triggering_element_name"]) + && $userInput["_triggering_element_name"] == $field_name . '_add_more'; + // On add more action only one option must appear to the user. + if ($isAddingMore) { + $optionsAvailable = 1; + } + } + elseif ($items->count() > $emptyValues) { + $optionsAvailable = 0; + } + + // Remove leftover option. + if ($emptyValues > $optionsAvailable) { + unset($elements[$max]); + $items->removeItem($max); + $elements["#max_delta"] = $items->count() - 1; + } } } diff --git a/core/modules/field/tests/src/Functional/FormTest.php b/core/modules/field/tests/src/Functional/FormTest.php index 3fbe668953..807afcf14b 100644 --- a/core/modules/field/tests/src/Functional/FormTest.php +++ b/core/modules/field/tests/src/Functional/FormTest.php @@ -686,7 +686,8 @@ public function testLabelOnMultiValueFields() { $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('A field with multiple values'); // Test if labels were XSS filtered. - $this->assertSession()->assertEscaped(""); + $this->assertSession()->pageTextContains("alert('a configurable field');"); + $this->assertSession()->pageTextNotContains(""); } /** diff --git a/core/modules/field/tests/src/Functional/NestedFormTest.php b/core/modules/field/tests/src/Functional/NestedFormTest.php index 4bd2f97c6b..5b67b003ab 100644 --- a/core/modules/field/tests/src/Functional/NestedFormTest.php +++ b/core/modules/field/tests/src/Functional/NestedFormTest.php @@ -124,6 +124,8 @@ public function testNestedFieldForm() { $this->assertSession()->fieldValueEquals('entity_2[field_unlimited][0][value]', 11); // Submit the form and check that the entities are updated accordingly. + $this->submitForm([], 'field_unlimited_add_more'); + $this->submitForm([], 'entity_2_field_unlimited_add_more'); $edit = [ 'field_single[0][value]' => 1, 'field_unlimited[0][value]' => 2, @@ -177,6 +179,7 @@ public function testNestedFieldForm() { // 'Add more' button in the first entity: $this->drupalGet('test-entity/nested/1/2'); $this->submitForm([], 'field_unlimited_add_more'); + $this->submitForm([], 'field_unlimited_add_more'); $this->assertSession()->fieldValueEquals('field_unlimited[0][value]', 3); $this->assertSession()->fieldValueEquals('field_unlimited[1][value]', 2); $this->assertSession()->fieldValueEquals('field_unlimited[2][value]', ''); @@ -187,6 +190,7 @@ public function testNestedFieldForm() { 'entity_2[field_unlimited][1][value]' => 14, 'entity_2[field_unlimited][2][value]' => 15, ]; + $this->submitForm([], 'entity_2_field_unlimited_add_more'); $this->submitForm($edit, 'entity_2_field_unlimited_add_more'); $this->assertSession()->fieldValueEquals('entity_2[field_unlimited][0][value]', 13); $this->assertSession()->fieldValueEquals('entity_2[field_unlimited][1][value]', 14);