From 82b5bc08b076eb0d8a0dd01cbe70d2c259581f05 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Thu, 19 Oct 2023 11:46:37 +0200 Subject: [PATCH] Issue #3376692 by lauriii, mstrelan, quietone, acbramley, larowlan, smustgrave: Removed values in multi-value fields reappear --- core/lib/Drupal/Core/Field/WidgetBase.php | 12 ++++++++-- .../MultipleValueWidgetTest.php | 15 +++++++++++++ ...erInputMappingOnFieldDeltaElementsTest.php | 22 +++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index 7b0fa5496153..9e4de97ff602 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -68,8 +68,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter $field_name = $this->fieldDefinition->getName(); $parents = $form['#parents']; - // Store field information in $form_state. - if (!static::getWidgetState($parents, $field_name, $form_state)) { + if (!$field_state = static::getWidgetState($parents, $field_name, $form_state)) { $field_state = [ 'items_count' => count($items), 'array_parents' => [], @@ -77,6 +76,13 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter 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 = []; @@ -384,6 +390,8 @@ public static function deleteSubmit(&$form, FormStateInterface $form_state) { $form_state->setUserInput($user_input); } + $field_state['deleted_item'] = $delta; + unset($parent_element[$delta]); NestedArray::setValue($form, $array_parents, $parent_element); diff --git a/core/modules/field/tests/src/FunctionalJavascript/MultipleValueWidgetTest.php b/core/modules/field/tests/src/FunctionalJavascript/MultipleValueWidgetTest.php index b4bce7b3d225..730d0c8b44fa 100644 --- a/core/modules/field/tests/src/FunctionalJavascript/MultipleValueWidgetTest.php +++ b/core/modules/field/tests/src/FunctionalJavascript/MultipleValueWidgetTest.php @@ -150,6 +150,21 @@ public function testFieldMultipleValueWidget() { // Assert that the wrapper exists and isn't nested. $this->assertSession()->elementsCount('css', '[data-drupal-selector="edit-field-unlimited-wrapper"]', 1); + + // Test removing items/values on saved entities resets to initial value. + $this->submitForm([], 'Save'); + $field_2_remove_button->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $field_1_remove_button->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $field_0_remove_button->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $add_more_button->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->assertSame('', $field_0->getValue()); + $add_more_button->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->assertSame('', $field_1->getValue()); } } diff --git a/core/tests/Drupal/FunctionalTests/Entity/ContentEntityFormCorrectUserInputMappingOnFieldDeltaElementsTest.php b/core/tests/Drupal/FunctionalTests/Entity/ContentEntityFormCorrectUserInputMappingOnFieldDeltaElementsTest.php index 1cd176328f5b..bd4cb68c126d 100644 --- a/core/tests/Drupal/FunctionalTests/Entity/ContentEntityFormCorrectUserInputMappingOnFieldDeltaElementsTest.php +++ b/core/tests/Drupal/FunctionalTests/Entity/ContentEntityFormCorrectUserInputMappingOnFieldDeltaElementsTest.php @@ -77,10 +77,10 @@ protected function setUp(): void { * Tests the correct user input mapping on complex fields. */ public function testCorrectUserInputMappingOnComplexFields() { - /** @var ContentEntityStorageInterface $storage */ + /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ $storage = $this->container->get('entity_type.manager')->getStorage($this->entityTypeId); - /** @var ContentEntityInterface $entity */ + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ $entity = $storage->create([ $this->fieldName => [ ['shape' => 'rectangle', 'color' => 'green'], @@ -118,6 +118,24 @@ public function testCorrectUserInputMappingOnComplexFields() { ['shape' => 'circle', 'color' => 'blue'], ['shape' => 'rectangle', 'color' => 'green'], ], $entity->get($this->fieldName)->getValue()); + + $this->drupalGet($this->entityTypeId . '/manage/' . $entity->id() . '/edit'); + + // Delete one of the field items and ensure that the user input is mapped on + // the correct delta field items. + $edit = [ + "$this->fieldName[0][_weight]" => 0, + "$this->fieldName[1][_weight]" => -1, + ]; + $this->submitForm($edit, "{$this->fieldName}_0_remove_button"); + $this->submitForm([], 'Save'); + + $storage->resetCache([$entity->id()]); + $entity = $storage->load($entity->id()); + $this->assertEquals([ + ['shape' => 'rectangle', 'color' => 'green'], + ], $entity->get($this->fieldName)->getValue()); + } } -- GitLab