From 6f60a2a9031c49fe92b8703764defa46481db155 Mon Sep 17 00:00:00 2001 From: "Nathanael d. Noblet" Date: Tue, 3 Jun 2025 14:24:16 -0600 Subject: [PATCH 1/3] Allow NumberToLocalizedStringTransformer empty values --- .../DataTransformer/MoneyToLocalizedStringTransformer.php | 4 ++-- .../DataTransformer/NumberToLocalizedStringTransformer.php | 4 ++-- .../MoneyToLocalizedStringTransformerTest.php | 7 +++++++ .../NumberToLocalizedStringTransformerTest.php | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 7a8aacac6..d862b885d 100644 --- a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -33,14 +33,14 @@ public function __construct(?int $scale = 2, ?bool $grouping = true, ?int $round /** * Transforms a normalized format into a localized money string. * - * @param int|float|null $value Normalized number + * @param int|float|string|null $value Normalized number * * @throws TransformationFailedException if the given value is not numeric or * if the value cannot be transformed */ public function transform(mixed $value): string { - if (null !== $value && 1 !== $this->divisor) { + if (null !== $value && '' !== $value && 1 !== $this->divisor) { if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 71d225e58..2bff37ad3 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -43,14 +43,14 @@ public function __construct(?int $scale = null, ?bool $grouping = false, ?int $r /** * Transforms a number type into localized number. * - * @param int|float|null $value Number value + * @param int|float|string|null $value Number value * * @throws TransformationFailedException if the given value is not numeric * or if the value cannot be transformed */ public function transform(mixed $value): string { - if (null === $value) { + if (null === $value || '' === $value) { return ''; } diff --git a/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php index 2d43e9533..f25d49981 100644 --- a/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php @@ -54,6 +54,13 @@ public function testTransformExpectsNumeric() $transformer->transform('abcd'); } + public function testTransformEmptyString() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + + $this->assertSame('', $transformer->transform('')); + } + public function testTransformEmpty() { $transformer = new MoneyToLocalizedStringTransformer(); diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 37448db51..c0344b9f2 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -49,6 +49,7 @@ public static function provideTransformations() { return [ [null, '', 'de_AT'], + ['', '', 'de_AT'], [1, '1', 'de_AT'], [1.5, '1,5', 'de_AT'], [1234.5, '1234,5', 'de_AT'], From e4718144d2d1b3f7a1ecd93c50b634eba22be59a Mon Sep 17 00:00:00 2001 From: matlec Date: Mon, 2 Jun 2025 17:39:25 +0200 Subject: [PATCH 2/3] [Form] Fix `keep_as_list` when data is not an array --- .../Core/EventListener/ResizeFormListener.php | 10 ++++++++-- .../Core/EventListener/ResizeFormListenerTest.php | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 299f91937..a9e521300 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -199,7 +199,13 @@ public function onSubmit(FormEvent $event): void } if ($this->keepAsList) { - $formReindex = []; + $formReindex = $dataKeys = []; + foreach ($data as $key => $value) { + $dataKeys[] = $key; + } + foreach ($dataKeys as $key) { + unset($data[$key]); + } foreach ($form as $name => $child) { $formReindex[] = $child; $form->remove($name); @@ -208,8 +214,8 @@ public function onSubmit(FormEvent $event): void $form->add($index, $this->type, array_replace([ 'property_path' => '['.$index.']', ], $this->options)); + $data[$index] = $child->getData(); } - $data = array_values($data); } $event->setData($data); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 934460c8f..390f6b04a 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -310,7 +310,7 @@ public function testOnSubmitDealsWithObjectBackedIteratorAggregate() $this->assertArrayNotHasKey(2, $event->getData()); } - public function testOnSubmitDealsWithArrayBackedIteratorAggregate() + public function testOnSubmitDealsWithDoctrineCollection() { $this->builder->add($this->getBuilder('1')); @@ -323,6 +323,19 @@ public function testOnSubmitDealsWithArrayBackedIteratorAggregate() $this->assertArrayNotHasKey(2, $event->getData()); } + public function testKeepAsListWorksWithTraversableArrayAccess() + { + $this->builder->add($this->getBuilder('1')); + + $data = new \ArrayIterator([0 => 'first', 1 => 'second', 2 => 'third']); + $event = new FormEvent($this->builder->getForm(), $data); + $listener = new ResizeFormListener(TextType::class, keepAsList: true); + $listener->onSubmit($event); + + $this->assertCount(1, $event->getData()); + $this->assertArrayHasKey(0, $event->getData()); + } + public function testOnSubmitDeleteEmptyNotCompoundEntriesIfAllowDelete() { $this->builder->setData(['0' => 'first', '1' => 'second']); From 4798286b41df22482cd37b95e753ae45c9ed738c Mon Sep 17 00:00:00 2001 From: kells Date: Tue, 4 Mar 2025 19:08:49 +0100 Subject: [PATCH 3/3] [Form] Keep submitted values when keep_as_list option of collection type is enabled Co-authored-by: mariecharles marie.charles@hetic.net --- Extension/Core/EventListener/ResizeFormListener.php | 2 +- .../Type/FormTypeValidatorExtensionTest.php | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index a9e521300..a7da65bdb 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -213,7 +213,7 @@ public function onSubmit(FormEvent $event): void foreach ($formReindex as $index => $child) { $form->add($index, $this->type, array_replace([ 'property_path' => '['.$index.']', - ], $this->options)); + ], $this->options, ['data' => $child->getData()])); $data[$index] = $child->getData(); } } diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index a1d1a3840..1661519b7 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -257,7 +257,7 @@ public function testCollectionTypeKeepAsListOptionTrue() { $formMetadata = new ClassMetadata(Form::class); $authorMetadata = (new ClassMetadata(Author::class)) - ->addPropertyConstraint('firstName', new NotBlank()); + ->addPropertyConstraint('firstName', new Length(1)); $organizationMetadata = (new ClassMetadata(Organization::class)) ->addPropertyConstraint('authors', new Valid()); $metadataFactory = $this->createMock(MetadataFactoryInterface::class); @@ -301,22 +301,22 @@ public function testCollectionTypeKeepAsListOptionTrue() $form->submit([ 'authors' => [ 0 => [ - 'firstName' => '', // Fires a Not Blank Error + 'firstName' => 'foobar', // Fires a Length Error 'lastName' => 'lastName1', ], // key "1" could be missing if we add 4 blank form entries and then remove it. 2 => [ - 'firstName' => '', // Fires a Not Blank Error + 'firstName' => 'barfoo', // Fires a Length Error 'lastName' => 'lastName3', ], 3 => [ - 'firstName' => '', // Fires a Not Blank Error + 'firstName' => 'barbaz', // Fires a Length Error 'lastName' => 'lastName3', ], ], ]); - // Form does have 3 not blank errors + // Form does have 3 length errors $errors = $form->getErrors(true); $this->assertCount(3, $errors); @@ -328,12 +328,15 @@ public function testCollectionTypeKeepAsListOptionTrue() ]; $this->assertTrue($form->get('authors')->has('0')); + $this->assertSame('foobar', $form->get('authors')->get('0')->getData()->firstName); $this->assertContains('data.authors[0].firstName', $errorPaths); $this->assertTrue($form->get('authors')->has('1')); + $this->assertSame('barfoo', $form->get('authors')->get('1')->getData()->firstName); $this->assertContains('data.authors[1].firstName', $errorPaths); $this->assertTrue($form->get('authors')->has('2')); + $this->assertSame('barbaz', $form->get('authors')->get('2')->getData()->firstName); $this->assertContains('data.authors[2].firstName', $errorPaths); $this->assertFalse($form->get('authors')->has('3'));