From b7f1ba4376f6ef4686464a88233378e00290f566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Wed, 8 Jan 2025 03:04:47 +0100 Subject: [PATCH] [LiveComponent] Fix `ComponentWithFormTrait::extractFormValues()` with edge cases --- .../src/ComponentWithFormTrait.php | 41 +++++++++++++------ .../Form/FormWithManyDifferentFieldsType.php | 9 ++++ .../Functional/Form/ComponentWithFormTest.php | 1 + .../tests/Unit/Form/ComponentWithFormTest.php | 1 + 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/LiveComponent/src/ComponentWithFormTrait.php b/src/LiveComponent/src/ComponentWithFormTrait.php index c8ab525d495..8f2aceab2cb 100644 --- a/src/LiveComponent/src/ComponentWithFormTrait.php +++ b/src/LiveComponent/src/ComponentWithFormTrait.php @@ -11,6 +11,7 @@ namespace Symfony\UX\LiveComponent; +use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; use Symfony\Component\Form\ClearableErrorsInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; @@ -255,25 +256,39 @@ private function extractFormValues(FormView $formView): array continue; } + // if (\array_key_exists('checked', $child->vars)) { - // special handling for check boxes $values[$name] = $child->vars['checked'] ? $child->vars['value'] : null; continue; } - if (\array_key_exists('choices', $child->vars) - && $child->vars['required'] - && !$child->vars['disabled'] - && !$child->vars['value'] - && (false === $child->vars['placeholder'] || null === $child->vars['placeholder']) - && !$child->vars['multiple'] - && !$child->vars['expanded'] - && $child->vars['choices'] + // (not a radio/checkbox) + && !$child->vars['multiple'] // is not multiple + && !\is_string($child->vars['placeholder']) // has no placeholder (empty string is valid) ) { - if (null !== $firstKey = array_key_first($child->vars['choices'])) { - $values[$name] = $child->vars['choices'][$firstKey]->value ?? null; - } - + $choices = $child->vars['choices']; + do { + $choice = $choices[array_key_first($choices)]; + if (!$choice instanceof ChoiceGroupView) { + break; + } + } while ($choices = $choice->choices); + + $values[$name] = $choice?->value; continue; } diff --git a/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php b/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php index f2a0e322104..59537991d57 100644 --- a/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php +++ b/src/LiveComponent/tests/Fixtures/Form/FormWithManyDifferentFieldsType.php @@ -65,6 +65,15 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'foo' => 1, ], ]) + ->add('choice_required_without_placeholder_and_choice_group', ChoiceType::class, [ + 'choices' => [ + 'Bar Group' => [ + 'Bar Label' => 'ok', + 'Foo Label' => 'foo_value', + ], + 'foo' => 1, + ], + ]) ->add('choice_expanded', ChoiceType::class, [ 'choices' => [ 'foo' => 1, diff --git a/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php b/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php index a3ed0f7c5e4..bfbe477c948 100644 --- a/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php +++ b/src/LiveComponent/tests/Functional/Form/ComponentWithFormTest.php @@ -181,6 +181,7 @@ public function testHandleCheckboxChanges(): void 'choice_required_with_placeholder' => '', 'choice_required_with_empty_placeholder' => '', 'choice_required_without_placeholder' => '2', + 'choice_required_without_placeholder_and_choice_group' => 'ok', 'choice_expanded' => '', 'choice_multiple' => ['2'], 'select_multiple' => ['2'], diff --git a/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php b/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php index 931430d8b0a..a7062605e48 100644 --- a/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php +++ b/src/LiveComponent/tests/Unit/Form/ComponentWithFormTest.php @@ -46,6 +46,7 @@ public function testFormValues(): void 'choice_required_with_placeholder' => '', 'choice_required_with_empty_placeholder' => '', 'choice_required_without_placeholder' => '2', + 'choice_required_without_placeholder_and_choice_group' => 'ok', 'choice_expanded' => '', 'choice_multiple' => ['2'], 'select_multiple' => ['2'],