From e9d1e28b2fd53f504949751d38535d7226a26c57 Mon Sep 17 00:00:00 2001 From: adev Date: Mon, 17 Apr 2017 20:52:26 +0200 Subject: [PATCH 1/2] [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible --- src/Symfony/Component/Form/CHANGELOG.md | 1 + .../PercentToLocalizedStringTransformer.php | 12 ++ ...ercentToLocalizedStringTransformerTest.php | 111 ++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 58b0f3862b23f..3981ed42b7c16 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -25,6 +25,7 @@ CHANGELOG * "choice_value" * "choice_attr" * "group_by" + * added PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible 2.6.2 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 7fc191a054ff4..6d209c9d60232 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -119,6 +119,18 @@ public function reverseTransform($value) } $formatter = $this->getNumberFormatter(); + $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + $grouping = $formatter->getAttribute(\NumberFormatter::GROUPING_USED); + + if ('.' !== $decSep && (!$grouping || '.' !== $groupSep)) { + $value = str_replace('.', $decSep, $value); + } + + if (',' !== $decSep && (!$grouping || ',' !== $groupSep)) { + $value = str_replace(',', $decSep, $value); + } + // replace normal spaces so that the formatter can read them $value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value)); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index abcc72e2315f8..8de480f8ec7f2 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -119,4 +119,115 @@ public function testReverseTransformExpectsString() $transformer->reverseTransform(1); } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() + { + \Locale::setDefault('fr'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // accept dots + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() + { + // Since we test against "de_DE", we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('de_DE'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1.234.5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() + { + // Since we test against "de_DE", we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('de_DE'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1234.5'); + } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('fr'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('bg'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // accept commas + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() + { + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1,234,5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() + { + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1234,5'); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed() + { + $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); + $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, 1); + $formatter->setAttribute(\NumberFormatter::GROUPING_USED, false); + + $transformer = $this->getMockBuilder('Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer') + ->setMethods(array('getNumberFormatter')) + ->setConstructorArgs(array(1, 'integer')) + ->getMock(); + $transformer->expects($this->any()) + ->method('getNumberFormatter') + ->willReturn($formatter); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } } From a42fa981a0448d80780d9e58f14ad31af9ee5f45 Mon Sep 17 00:00:00 2001 From: adev Date: Sat, 29 Jul 2017 10:17:07 +0200 Subject: [PATCH 2/2] Fix failing tests --- src/Symfony/Component/Form/CHANGELOG.md | 1 - .../PercentToLocalizedStringTransformerTest.php | 16 +++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 3981ed42b7c16..58b0f3862b23f 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -25,7 +25,6 @@ CHANGELOG * "choice_value" * "choice_attr" * "group_by" - * added PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible 2.6.2 ----- diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index 8de480f8ec7f2..24cef424d1c3e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -122,6 +122,8 @@ public function testReverseTransformExpectsString() public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + \Locale::setDefault('fr'); $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); @@ -139,10 +141,10 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { - // Since we test against "de_DE", we need the full implementation - IntlTestHelper::requireFullIntl($this, false); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); - \Locale::setDefault('de_DE'); + \Locale::setDefault('de_AT'); $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); @@ -155,7 +157,7 @@ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() { // Since we test against "de_DE", we need the full implementation - IntlTestHelper::requireFullIntl($this, false); + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); \Locale::setDefault('de_DE'); @@ -179,7 +181,7 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupin public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() { // Since we test against other locales, we need the full implementation - IntlTestHelper::requireFullIntl($this, false); + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); \Locale::setDefault('bg'); $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); @@ -198,6 +200,8 @@ public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); $transformer->reverseTransform('1,234,5'); @@ -208,6 +212,8 @@ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); $transformer->reverseTransform('1234,5');