From 61025d1d1b7fa1675b15e20129ea9c7fa86981d7 Mon Sep 17 00:00:00 2001 From: Jorrit Schippers Date: Fri, 20 Mar 2020 13:10:52 +0100 Subject: [PATCH] [Form] Support customized intl php.ini settings `IntlDateParser->parse()` behaves differently when `intl.error_level` and/or `intl.use_exceptions` are not 0. This change makes sure `\IntlException` is caught when `intl.use_exceptions` is 1 and warnings thrown when `intl.error_level` is not 0 are ignored. --- .../DateTimeToLocalizedStringTransformer.php | 9 +++- ...teTimeToLocalizedStringTransformerTest.php | 46 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index af2dad7c9e32..e47b03d32d4a 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -117,11 +117,16 @@ public function reverseTransform($value) // date-only patterns require parsing to be done in UTC, as midnight might not exist in the local timezone due // to DST changes $dateOnly = $this->isPatternDateOnly(); + $dateFormatter = $this->getIntlDateFormatter($dateOnly); - $timestamp = $this->getIntlDateFormatter($dateOnly)->parse($value); + try { + $timestamp = @$dateFormatter->parse($value); + } catch (\IntlException $e) { + throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); + } if (0 != intl_get_error_code()) { - throw new TransformationFailedException(intl_get_error_message()); + throw new TransformationFailedException(intl_get_error_message(), intl_get_error_code()); } elseif ($timestamp > 253402214400) { // This timestamp represents UTC midnight of 9999-12-31 to prevent 5+ digit years throw new TransformationFailedException('Years beyond 9999 are not supported.'); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index ce91d05ff4b6..ad9e09990912 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -27,6 +27,12 @@ protected function setUp() { parent::setUp(); + // Normalize intl. configuration settings. + if (\extension_loaded('intl')) { + $this->iniSet('intl.use_exceptions', 0); + $this->iniSet('intl.error_level', 0); + } + // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this, '57.1'); @@ -334,4 +340,44 @@ public function testReverseTransformFiveDigitYearsWithTimestamp() $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, null, \IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd HH:mm:ss'); $transformer->reverseTransform('20107-03-21 12:34:56'); } + + public function testReverseTransformWrapsIntlErrorsWithErrorLevel() + { + if (!\extension_loaded('intl')) { + $this->markTestSkipped('intl extension is not loaded'); + } + + $this->iniSet('intl.error_level', E_WARNING); + + $this->expectException('Symfony\Component\Form\Exception\TransformationFailedException'); + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->reverseTransform('12345'); + } + + public function testReverseTransformWrapsIntlErrorsWithExceptions() + { + if (!\extension_loaded('intl')) { + $this->markTestSkipped('intl extension is not loaded'); + } + + $this->iniSet('intl.use_exceptions', 1); + + $this->expectException('Symfony\Component\Form\Exception\TransformationFailedException'); + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->reverseTransform('12345'); + } + + public function testReverseTransformWrapsIntlErrorsWithExceptionsAndErrorLevel() + { + if (!\extension_loaded('intl')) { + $this->markTestSkipped('intl extension is not loaded'); + } + + $this->iniSet('intl.use_exceptions', 1); + $this->iniSet('intl.error_level', E_WARNING); + + $this->expectException('Symfony\Component\Form\Exception\TransformationFailedException'); + $transformer = new DateTimeToLocalizedStringTransformer(); + $transformer->reverseTransform('12345'); + } }