From cafc9d2543fb1258d9e32996edbf0ce19ef43694 Mon Sep 17 00:00:00 2001 From: catch <6915-catch@users.noreply.drupalcode.org> Date: Fri, 14 Mar 2025 20:20:51 +0000 Subject: [PATCH] Issue #3416819 by efpapado, godotislate, shoroshanska, tawellman, heikkiy, smustgrave: Not able to add option with key and label '0' to List string field --- .../Plugin/Field/FieldType/ListItemBase.php | 14 +++++++---- .../Plugin/Field/FieldType/ListStringItem.php | 3 +++ .../OptionsFieldUIAllowedValuesTest.php | 25 +++++++++++++------ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php index 2a87d03fa9a8..e7209f1f33fe 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php @@ -351,13 +351,17 @@ abstract protected function allowedValuesDescription(); public static function validateAllowedValues($element, FormStateInterface $form_state) { $items = array_filter(array_map(function ($item) use ($element) { $current_element = $element['table'][$item]; - if ($current_element['item']['key']['#value'] !== NULL && $current_element['item']['label']['#value']) { - return $current_element['item']['key']['#value'] . '|' . $current_element['item']['label']['#value']; - } - elseif ($current_element['item']['key']['#value']) { + $key_has_input = isset($current_element['item']['key']['#value']) && $current_element['item']['key']['#value'] !== ''; + $label_has_input = isset($current_element['item']['label']['#value']) && $current_element['item']['label']['#value'] !== ''; + if ($key_has_input) { + if ($label_has_input) { + return $current_element['item']['key']['#value'] . '|' . $current_element['item']['label']['#value']; + } + return $current_element['item']['key']['#value']; } - elseif ($current_element['item']['label']['#value']) { + + if ($label_has_input) { return $current_element['item']['label']['#value']; } diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php index c31f1bc13768..4e6ce2b9dcf2 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php @@ -93,6 +93,9 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state // Improve user experience by using an automatically generated machine name. foreach (Element::children($element['allowed_values']['table']) as $delta => $row) { $element['allowed_values']['table'][$delta]['item']['key']['#type'] = 'machine_name'; + // ListItemBase::storageSettingsForm() will set the default value to an + // integer if the key is a decimal integer string, so cast it back here. + $element['allowed_values']['table'][$delta]['item']['key']['#default_value'] = (string) $element['allowed_values']['table'][$delta]['item']['key']['#default_value']; $element['allowed_values']['table'][$delta]['item']['key']['#machine_name'] = [ 'exists' => [static::class, 'exists'], ]; diff --git a/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php b/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php index fec03135703f..5266f1c950aa 100644 --- a/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php +++ b/core/modules/options/tests/src/FunctionalJavascript/OptionsFieldUIAllowedValuesTest.php @@ -172,42 +172,45 @@ public function testOptionsAllowedValues($option_type, $options, $is_string_opti } $page->pressButton('Save'); + $option_labels = array_values($options); + $this->assertCount(3, $option_labels); + // Test the order of the option list on node form. $this->drupalGet($this->nodeFormPath); - $this->assertNodeFormOrder(['- None -', 'First', 'Second', 'Third']); + $this->assertNodeFormOrder(['- None -', $option_labels[0], $option_labels[1], $option_labels[2]]); // Test the order of the option list on admin path. $this->drupalGet($this->adminPath); - $this->assertOrder(['First', 'Second', 'Third', ''], $is_string_option); + $this->assertOrder([$option_labels[0], $option_labels[1], $option_labels[2], ''], $is_string_option); $drag_handle = $page->find('css', '[data-drupal-selector="edit-field-storage-subform-settings-allowed-values-table-0"] .tabledrag-handle'); $target = $page->find('css', '[data-drupal-selector="edit-field-storage-subform-settings-allowed-values-table-2"]'); // Change the order the items appear. $drag_handle->dragTo($target); - $this->assertOrder(['Second', 'Third', 'First', ''], $is_string_option); + $this->assertOrder([$option_labels[1], $option_labels[2], $option_labels[0], ''], $is_string_option); $page->pressButton('Save'); $this->drupalGet($this->nodeFormPath); - $this->assertNodeFormOrder(['- None -', 'Second', 'Third', 'First']); + $this->assertNodeFormOrder(['- None -', $option_labels[1], $option_labels[2], $option_labels[0]]); $this->drupalGet($this->adminPath); // Confirm the change in order was saved. - $this->assertOrder(['Second', 'Third', 'First', ''], $is_string_option); + $this->assertOrder([$option_labels[1], $option_labels[2], $option_labels[0], ''], $is_string_option); // Delete an item. $page->pressButton('remove_row_button__1'); $this->assertSession()->assertWaitOnAjaxRequest(); - $this->assertOrder(['Second', 'First', ''], $is_string_option); + $this->assertOrder([$option_labels[1], $option_labels[0], ''], $is_string_option); $page->pressButton('Save'); $this->drupalGet($this->nodeFormPath); - $this->assertNodeFormOrder(['- None -', 'Second', 'First']); + $this->assertNodeFormOrder(['- None -', $option_labels[1], $option_labels[0]]); $this->drupalGet($this->adminPath); // Confirm the item removal was saved. - $this->assertOrder(['Second', 'First', ''], $is_string_option); + $this->assertOrder([$option_labels[1], $option_labels[0], ''], $is_string_option); } /** @@ -316,6 +319,12 @@ public static function providerTestOptionsAllowedValues() { ['first' => 'First', 'second' => 'Second', 'third' => 'Third'], TRUE, ], + // Example with empty key and label values like string '0'. + 'List string with 0 value' => [ + 'list_string', + ['0' => '0', '1' => '1', '2' => '2'], + TRUE, + ], ]; // Test adding options for each option field type using several possible // methods that could be used for navigating the options list: -- GitLab