From 881174157bc4a57863280d9033b416101725acb2 Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Sat, 7 Oct 2023 18:48:28 +0200 Subject: [PATCH] [Form] add "model_type" option to MoneyType --- src/Symfony/Component/Form/CHANGELOG.md | 1 + .../MoneyToLocalizedStringTransformer.php | 7 ++++-- .../Form/Extension/Core/Type/MoneyType.php | 14 ++++++++++- .../Extension/Core/Type/MoneyTypeTest.php | 24 +++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 2035e8f805a53..d78622d9fd56e 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Deprecate not configuring the `default_protocol` option of the `UrlType`, it will default to `null` in 8.0 * Add a `keep_as_list` option to `CollectionType` + * Add a new `model_type` option to `MoneyType`, to be able to cast the transformed value to `integer` 7.0 --- diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index fd943cc820f49..9a768e8979149 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -22,12 +22,14 @@ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { private int $divisor; + private string $modelType; - public function __construct(?int $scale = 2, ?bool $grouping = true, ?int $roundingMode = \NumberFormatter::ROUND_HALFUP, ?int $divisor = 1, string $locale = null) + public function __construct(?int $scale = 2, ?bool $grouping = true, ?int $roundingMode = \NumberFormatter::ROUND_HALFUP, ?int $divisor = 1, string $locale = null, string $modelType = 'float') { parent::__construct($scale ?? 2, $grouping ?? true, $roundingMode, $locale); $this->divisor = $divisor ?? 1; + $this->modelType = $modelType; } /** @@ -62,7 +64,8 @@ public function reverseTransform(mixed $value): int|float|null { $value = parent::reverseTransform($value); if (null !== $value && 1 !== $this->divisor) { - $value = (float) (string) ($value * $this->divisor); + $value = (string) ($value * $this->divisor); + $value = 'integer' === $this->modelType ? (int) $value : (float) $value; } return $value; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php b/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php index c82911a2163bb..e4d402d8d0379 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/MoneyType.php @@ -34,7 +34,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $options['grouping'], $options['rounding_mode'], $options['divisor'], - $options['html5'] ? 'en' : null + $options['html5'] ? 'en' : null, + $options['model_type'], )) ; } @@ -59,6 +60,7 @@ public function configureOptions(OptionsResolver $resolver): void 'compound' => false, 'html5' => false, 'invalid_message' => 'Please enter a valid money amount.', + 'model_type' => 'float', ]); $resolver->setAllowedValues('rounding_mode', [ @@ -75,6 +77,8 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedTypes('html5', 'bool'); + $resolver->setAllowedValues('model_type', ['float', 'integer']); + $resolver->setNormalizer('grouping', static function (Options $options, $value) { if ($value && $options['html5']) { throw new LogicException('Cannot use the "grouping" option when the "html5" option is enabled.'); @@ -82,6 +86,14 @@ public function configureOptions(OptionsResolver $resolver): void return $value; }); + + $resolver->setNormalizer('model_type', static function (Options $options, $value) { + if ('integer' === $value && 1 === $options['divisor']) { + throw new LogicException('When the "model_type" option is set to "integer", the "divisor" option should not be set to "1".'); + } + + return $value; + }); } public function getBlockPrefix(): string diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php index b00439b574153..75d07294381fe 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Intl\Util\IntlTestHelper; class MoneyTypeTest extends BaseTypeTestCase @@ -123,4 +124,27 @@ public function testHtml5EnablesSpecificFormatting() $this->assertSame('12345.60', $form->createView()->vars['value']); $this->assertSame('number', $form->createView()->vars['type']); } + + public function testDefaultModelType() + { + $form = $this->factory->create(static::TESTED_TYPE, null, ['divisor' => 100]); + $form->submit('12345.67'); + + $this->assertSame(1234567.0, $form->getData()); + } + + public function testIntegerModelType() + { + $form = $this->factory->create(static::TESTED_TYPE, null, ['divisor' => 100, 'model_type' => 'integer']); + $form->submit('12345.67'); + + $this->assertSame(1234567, $form->getData()); + } + + public function testIntegerModelTypeExpectsDivisorNotEqualToOne() + { + $this->expectException(LogicException::class); + + $form = $this->factory->create(static::TESTED_TYPE, null, ['divisor' => 1, 'model_type' => 'integer']); + } }