From 285f6387116b7e043f4fbbfbc4e505645a48d353 Mon Sep 17 00:00:00 2001 From: Jan Pintr Date: Sat, 10 Feb 2024 14:23:32 +0100 Subject: [PATCH 1/3] Add calendar DateType option --- .../DateTimeToLocalizedStringTransformer.php | 2 +- .../Form/Extension/Core/Type/DateType.php | 4 +- ...teTimeToLocalizedStringTransformerTest.php | 77 ++++++++++++++++ .../Extension/Core/Type/DateTypeTest.php | 87 +++++++++++++++++++ 4 files changed, 168 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 b7ea092591d51..bd3feb0bbccfe 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -44,7 +44,7 @@ public function __construct( ?string $outputTimezone = null, ?int $dateFormat = null, ?int $timeFormat = null, - private int $calendar = \IntlDateFormatter::GREGORIAN, + private int|\IntlCalendar $calendar = \IntlDateFormatter::GREGORIAN, private ?string $pattern = null, ) { parent::__construct($inputTimezone, $outputTimezone); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index cfbbaf4c0dba7..3c7b6c22f2849 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -49,7 +49,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void { $dateFormat = \is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; $timeFormat = \IntlDateFormatter::NONE; - $calendar = \IntlDateFormatter::GREGORIAN; + $calendar = $options['calendar'] !== null ? $options['calendar'] : \IntlDateFormatter::GREGORIAN; $pattern = \is_string($options['format']) ? $options['format'] : ''; if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) { @@ -281,6 +281,7 @@ public function configureOptions(OptionsResolver $resolver): void 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, + 'calendar' => null, 'placeholder' => $placeholderDefault, 'html5' => true, // Don't modify \DateTime classes by reference, we treat @@ -320,6 +321,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedTypes('months', 'array'); $resolver->setAllowedTypes('days', 'array'); $resolver->setAllowedTypes('input_format', 'string'); + $resolver->setAllowedTypes('calendar', ['null', \IntlCalendar::class]); $resolver->setNormalizer('html5', static function (Options $options, $html5) { if ($html5 && 'single_text' === $options['widget'] && self::HTML5_FORMAT !== $options['format']) { 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 47f21203251d6..e1029c4e66d32 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -180,6 +180,44 @@ public function testTransformDateTimeImmutableTimezones() $this->assertEquals($dateTime->format('d.m.Y, H:i'), $transformer->transform($input)); } + public function testTransformDateTimeWithCalendar() + { + $locale = \Locale::getDefault(); + \Locale::setDefault('en_US'); + + $pattern = "y-MM-dd Y'w'w"; + $dateTime = new \DateTimeImmutable('2024-03-31'); + + $transformer = new DateTimeToLocalizedStringTransformer( + null, + null, + null, + null, + \IntlDateFormatter::GREGORIAN, + $pattern, + ); + + $this->assertEquals('2024-03-31 2024w14', $transformer->transform($dateTime)); + + // ISO 8601 + $calendar = \IntlCalendar::createInstance(null); + $calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY); + $calendar->setMinimalDaysInFirstWeek(4); + + $transformer = new DateTimeToLocalizedStringTransformer( + null, + null, + null, + null, + $calendar, + $pattern, + ); + + $this->assertEquals('2024-03-31 2024w13', $transformer->transform($dateTime)); + + \Locale::setDefault($locale); + } + public function testTransformRequiresValidDateTime() { $this->expectException(TransformationFailedException::class); @@ -254,6 +292,45 @@ public function testReverseTransformOnlyDateWithDifferentTimezones() $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2017-01-10')); } + public function testReverseTransformDateTimeWithCalendar() + { + $locale = \Locale::getDefault(); + \Locale::setDefault('en_US'); + + $pattern = "y-MM-dd Y'w'w"; + + $transformer = new DateTimeToLocalizedStringTransformer( + null, + null, + null, + null, + \IntlDateFormatter::GREGORIAN, + $pattern, + ); + + $dateTime = new \DateTime('2024-03-31'); + $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2024-03-31 2024w14')); + + // ISO 8601 + $calendar = \IntlCalendar::createInstance(null); + $calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY); + $calendar->setMinimalDaysInFirstWeek(4); + + $transformer = new DateTimeToLocalizedStringTransformer( + null, + null, + null, + null, + $calendar, + $pattern, + ); + + $dateTime = new \DateTime('2024-03-31'); + $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2024-03-31 2024w13')); + + \Locale::setDefault($locale); + } + public function testReverseTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index dfbae933092da..5255e88a47e52 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -395,6 +395,54 @@ public function testSubmitFromInputRawDifferentPattern() $this->assertEquals('06*2010*02', $form->getViewData()); } + public function testSubmitWithCalendarOption() + { + // we test against "en_US", so we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('en_US'); + + $format = "y-MM-dd y'w'w"; + + $output = [ + 'day' => '31', + 'month' => '3', + 'year' => '2024', + ]; + + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'format' => $format, + 'html5' => false, + 'widget' => 'single_text', + 'input' => 'array', + ]); + + $form->submit('2024-03-31 2024w14'); + + $this->assertEquals($output, $form->getData()); + $this->assertEquals('2024-03-31 2024w14', $form->getViewData()); + + // ISO 8601 + $calendar = \IntlCalendar::createInstance(); + $calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY); + $calendar->setMinimalDaysInFirstWeek(4); + + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'format' => $format, + 'html5' => false, + 'widget' => 'single_text', + 'input' => 'array', + 'calendar' => $calendar, + ]); + + $form->submit('2024-03-31 2024w13'); + + $this->assertEquals($output, $form->getData()); + $this->assertEquals('2024-03-31 2024w13', $form->getViewData()); + } + /** * @dataProvider provideDateFormats */ @@ -523,6 +571,45 @@ public function testSetDataWithNegativeTimezoneOffsetStringInput() $this->assertEquals('01.06.2010', $form->getViewData()); } + public function testSetDataWithCalendarInput() + { + // we test against "en_US", so we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('en_US'); + + $format = "y-MM-dd Y'w'w"; + $date = '2024-03-31'; + + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'format' => $format, + 'html5' => false, + 'input' => 'string', + 'widget' => 'single_text', + ]); + + $form->setData($date); + + $this->assertEquals('2024-03-31 2024w14', $form->getViewData()); + + // ISO 8601 + $calendar = \IntlCalendar::createInstance(null); + $calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY); + $calendar->setMinimalDaysInFirstWeek(4); + + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'format' => $format, + 'html5' => false, + 'input' => 'string', + 'widget' => 'single_text', + 'calendar' => $calendar, + ]); + + $form->setData($date); + + $this->assertEquals('2024-03-31 2024w13', $form->getViewData()); + } + public function testSetDataWithNegativeTimezoneOffsetDateTimeInput() { // we test against "de_DE", so we need the full implementation From 252a4afe32a651fce750c30311f7700212415d45 Mon Sep 17 00:00:00 2001 From: Jan Pintr Date: Sat, 10 Feb 2024 15:48:11 +0100 Subject: [PATCH 2/3] fix coding style --- src/Symfony/Component/Form/Extension/Core/Type/DateType.php | 2 +- .../Component/Form/Tests/Extension/Core/Type/DateTypeTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index 3c7b6c22f2849..d449c1b40b7a4 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -49,7 +49,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void { $dateFormat = \is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; $timeFormat = \IntlDateFormatter::NONE; - $calendar = $options['calendar'] !== null ? $options['calendar'] : \IntlDateFormatter::GREGORIAN; + $calendar = null !== $options['calendar'] ? $options['calendar'] : \IntlDateFormatter::GREGORIAN; $pattern = \is_string($options['format']) ? $options['format'] : ''; if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index 5255e88a47e52..2ff43df37dae5 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -401,7 +401,7 @@ public function testSubmitWithCalendarOption() IntlTestHelper::requireFullIntl($this, false); \Locale::setDefault('en_US'); - + $format = "y-MM-dd y'w'w"; $output = [ @@ -423,7 +423,7 @@ public function testSubmitWithCalendarOption() $this->assertEquals($output, $form->getData()); $this->assertEquals('2024-03-31 2024w14', $form->getViewData()); - + // ISO 8601 $calendar = \IntlCalendar::createInstance(); $calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY); From 6daff1cffdfa1b2d354262a6949c0c64ab3306ce Mon Sep 17 00:00:00 2001 From: Jan Pintr Date: Sat, 10 Feb 2024 15:56:02 +0100 Subject: [PATCH 3/3] fix transformer test --- .../DateTimeToLocalizedStringTransformerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 e1029c4e66d32..ed3a08e1aa8d8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -185,7 +185,7 @@ public function testTransformDateTimeWithCalendar() $locale = \Locale::getDefault(); \Locale::setDefault('en_US'); - $pattern = "y-MM-dd Y'w'w"; + $pattern = "y-MM-dd y'w'w"; $dateTime = new \DateTimeImmutable('2024-03-31'); $transformer = new DateTimeToLocalizedStringTransformer( @@ -297,7 +297,7 @@ public function testReverseTransformDateTimeWithCalendar() $locale = \Locale::getDefault(); \Locale::setDefault('en_US'); - $pattern = "y-MM-dd Y'w'w"; + $pattern = "y-MM-dd y'w'w"; $transformer = new DateTimeToLocalizedStringTransformer( null,