[Form] fix parsing invalid floating point numbers
This commit is contained in:
parent
dd490af864
commit
042eac4624
|
@ -116,6 +116,7 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface
|
|||
return;
|
||||
}
|
||||
|
||||
$position = 0;
|
||||
$formatter = $this->getNumberFormatter();
|
||||
$groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
|
||||
$decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
|
||||
|
@ -129,18 +130,44 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface
|
|||
$value = str_replace(',', $decSep, $value);
|
||||
}
|
||||
|
||||
if (false !== strpos($value, $decSep)) {
|
||||
$type = \NumberFormatter::TYPE_DOUBLE;
|
||||
} else {
|
||||
$type = \PHP_INT_SIZE === 8 ? \NumberFormatter::TYPE_INT64 : \NumberFormatter::TYPE_INT32;
|
||||
}
|
||||
|
||||
// replace normal spaces so that the formatter can read them
|
||||
$value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value));
|
||||
$result = $formatter->parse(str_replace(' ', "\xc2\xa0", $value), $type, $position);
|
||||
|
||||
if (intl_is_failure($formatter->getErrorCode())) {
|
||||
throw new TransformationFailedException($formatter->getErrorMessage());
|
||||
}
|
||||
|
||||
if (self::FRACTIONAL == $this->type) {
|
||||
$value /= 100;
|
||||
$result /= 100;
|
||||
}
|
||||
|
||||
return $value;
|
||||
if (\function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value, null, true)) {
|
||||
$length = mb_strlen($value, $encoding);
|
||||
$remainder = mb_substr($value, $position, $length, $encoding);
|
||||
} else {
|
||||
$length = \strlen($value);
|
||||
$remainder = substr($value, $position, $length);
|
||||
}
|
||||
|
||||
// After parsing, position holds the index of the character where the
|
||||
// parsing stopped
|
||||
if ($position < $length) {
|
||||
// Check if there are unrecognized characters at the end of the
|
||||
// number (excluding whitespace characters)
|
||||
$remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0");
|
||||
|
||||
if ('' !== $remainder) {
|
||||
throw new TransformationFailedException(sprintf('The number contains unrecognized characters: "%s"', $remainder));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -141,10 +141,10 @@ class PercentToLocalizedStringTransformerTest extends TestCase
|
|||
*/
|
||||
public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot()
|
||||
{
|
||||
// Since we test against "de_AT", we need the full implementation
|
||||
// Since we test against "de_DE", we need the full implementation
|
||||
IntlTestHelper::requireFullIntl($this, '4.8.1.1');
|
||||
|
||||
\Locale::setDefault('de_AT');
|
||||
\Locale::setDefault('de_DE');
|
||||
|
||||
$transformer = new PercentToLocalizedStringTransformer(1, 'integer');
|
||||
|
||||
|
@ -236,4 +236,70 @@ class PercentToLocalizedStringTransformerTest extends TestCase
|
|||
$this->assertEquals(1234.5, $transformer->reverseTransform('1234,5'));
|
||||
$this->assertEquals(1234.5, $transformer->reverseTransform('1234.5'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
public function testReverseTransformDisallowsLeadingExtraCharacters()
|
||||
{
|
||||
$transformer = new PercentToLocalizedStringTransformer();
|
||||
|
||||
$transformer->reverseTransform('foo123');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo3"
|
||||
*/
|
||||
public function testReverseTransformDisallowsCenteredExtraCharacters()
|
||||
{
|
||||
$transformer = new PercentToLocalizedStringTransformer();
|
||||
|
||||
$transformer->reverseTransform('12foo3');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo8"
|
||||
* @requires extension mbstring
|
||||
*/
|
||||
public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte()
|
||||
{
|
||||
// Since we test against other locales, we need the full implementation
|
||||
IntlTestHelper::requireFullIntl($this, false);
|
||||
|
||||
\Locale::setDefault('ru');
|
||||
|
||||
$transformer = new PercentToLocalizedStringTransformer();
|
||||
|
||||
$transformer->reverseTransform("12\xc2\xa0345,67foo8");
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
|
||||
*/
|
||||
public function testReverseTransformDisallowsTrailingExtraCharacters()
|
||||
{
|
||||
$transformer = new PercentToLocalizedStringTransformer();
|
||||
|
||||
$transformer->reverseTransform('123foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
* @expectedExceptionMessage The number contains unrecognized characters: "foo"
|
||||
* @requires extension mbstring
|
||||
*/
|
||||
public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
|
||||
{
|
||||
// Since we test against other locales, we need the full implementation
|
||||
IntlTestHelper::requireFullIntl($this, false);
|
||||
|
||||
\Locale::setDefault('ru');
|
||||
|
||||
$transformer = new PercentToLocalizedStringTransformer();
|
||||
|
||||
$transformer->reverseTransform("12\xc2\xa0345,678foo");
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue