10000 [Form] Add support for the `calendar` option in `DateType` · symfony/symfony@75dc4db · GitHub
[go: up one dir, main page]

Skip to content

Commit 75dc4db

Browse files
[Form] Add support for the calendar option in DateType
1 parent 031dde7 commit 75dc4db

File tree

5 files changed

+131
-8
lines changed

5 files changed

+131
-8
lines changed

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Deprecate the `VersionAwareTest` trait, use feature detection instead
8+
* Add support for the `calendar` option in `DateType`
89

910
7.1
1011
---

src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
3030
/**
3131
* @see BaseDateTimeTransformer::formats for available format options
3232
*
33-
* @param string|null $inputTimezone The name of the input timezone
34-
* @param string|null $outputTimezone The name of the output timezone
35-
* @param int|null $dateFormat The date format
36-
* @param int|null $timeFormat The time format
37-
* @param int $calendar One of the \IntlDateFormatter calendar constants
38-
* @param string|null $pattern A pattern to pass to \IntlDateFormatter
33+
* @param string|null $inputTimezone The name of the input timezone
34+
* @param string|null $outputTimezone The name of the output timezone
35+
* @param int|null $dateFormat The date format
36+
* @param int|null $timeFormat The time format
37+
* @param int|\IntlCalendar $calendar One of the \IntlDateFormatter calendar constants or an \IntlCalendar instance
38+
* @param string|null $pattern A pattern to pass to \IntlDateFormatter
3939
*
4040
* @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string
4141
*/
@@ -44,7 +44,7 @@ public function __construct(
4444
?string $outputTimezone = null,
4545
?int $dateFormat = null,
4646
?int $timeFormat = null,
47-
private int $calendar = \IntlDateFormatter::GREGORIAN,
47+
private int|\IntlCalendar $calendar = \IntlDateFormatter::GREGORIAN,
4848
private ?string $pattern = null,
4949
) {
5050
parent::__construct($inputTimezone, $outputTimezone);

src/Symfony/Component/Form/Extension/Core/Type/DateType.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
4949
{
5050
$dateFormat = \is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT;
5151
$timeFormat = \IntlDateFormatter::NONE;
52-
$calendar = \IntlDateFormatter::GREGORIAN;
52+
$calendar = $options['calendar'] ?? \IntlDateFormatter::GREGORIAN;
5353
$pattern = \is_string($options['format']) ? $options['format'] : '';
5454

5555
if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) {
@@ -281,6 +281,7 @@ public function configureOptions(OptionsResolver $resolver): void
281281
'format' => $format,
282282
'model_timezone' => null,
283283
'view_timezone' => null,
284+
'calendar' => null,
284285
'placeholder' => $placeholderDefault,
285286
'html5' => true,
286287
// Don't modify \DateTime classes by reference, we treat
@@ -320,6 +321,7 @@ public function configureOptions(OptionsResolver $resolver): void
320321
$resolver->setAllowedTypes('months', 'array');
321322
$resolver->setAllowedTypes('days', 'array');
322323
$resolver->setAllowedTypes('input_format', 'string');
324+
$resolver->setAllowedTypes('calendar', ['null', \IntlCalendar::class]);
323325

324326
$resolver->setNormalizer('html5', static function (Options $options, $html5) {
325327
if ($html5 && 'single_text' === $options['widget'] && self::HTML5_FORMAT !== $options['format']) {

src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,60 @@ public function testReverseTransformWrapsIntlErrorsWithExceptionsAndErrorLevel()
392392
}
393393
}
394394

395+
public function testTransformDateTimeWithCustomCalendar()
396+
{
397+
$dateTime = new \DateTimeImmutable('2024-03-31');
398+
399+
$weekBeginsOnSunday = \IntlCalendar::createInstance();
400+
$weekBeginsOnSunday->setFirstDayOfWeek(\IntlCalendar::DOW_SUNDAY);
401+
402+
$this->assertSame(
403+
'2024-03-31 2024w14',
404+
(new DateTimeToLocalizedStringTransformer(calendar: $weekBeginsOnSunday, pattern: "y-MM-dd y'w'w"))->transform($dateTime),
405+
);
406+
407+
$weekBeginsOnMonday = \IntlCalendar::createInstance();
408+
$weekBeginsOnMonday->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY);
409+
410+
$this->assertSame(
411+
'2024-03-31 2024w13',
412+
(new DateTimeToLocalizedStringTransformer(calendar: $weekBeginsOnMonday, pattern: "y-MM-dd y'w'w"))->transform($dateTime),
413+
);
414+
}
415+
416+
public function testReverseTransformDateTimeWithCustomCalendar()
417+
{
418+
$weekBeginsOnSunday = \IntlCalendar::createInstance();
419+
$weekBeginsOnSunday->setFirstDayOfWeek(\IntlCalendar::DOW_SUNDAY);
420+
421+
$this->assertSame(
422+
'2024-03-31',
423+
(new DateTimeToLocalizedStringTransformer(calendar: $weekBeginsOnSunday, pattern: "y-MM-dd"))
424+
->reverseTransform('2024-03-31 2024w14')
425+
->format('Y-m-d'),
426+
);
427+
428+
$weekBeginsOnMonday = \IntlCalendar::createInstance();
429+
$weekBeginsOnMonday->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY);
430+
431+
$this->assertSame(
432+
'2024-03-31',
433+
(new DateTimeToLocalizedStringTransformer(calendar: $weekBeginsOnMonday, pattern: "y-MM-dd"))
434+
->reverseTransform('2024-03-31 2024w13')
435+
->format('Y-m-d'),
436+
);
437+
}
438+
439+
public function testDefaultCalendarIsGregorian()
440+
{
441+
$now = new \DateTimeImmutable();
442+
443+
$this->assertSame(
444+
(new DateTimeToLocalizedStringTransformer(calendar: \IntlDateFormatter::GREGORIAN, pattern: "y-MM-dd y'w'w& 10000 quot;))->transform($now),
445+
(new DateTimeToLocalizedStringTransformer(pattern: "y-MM-dd y'w'w"))->transform($now),
446+
);
447+
}
448+
395449
protected function createDateTimeTransformer(?string $inputTimezone = null, ?string $outputTimezone = null): BaseDateTimeTransformer
396450
{
397451
return new DateTimeToLocalizedStringTransformer($inputTimezone, $outputTimezone);

src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,72 @@ public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone()
11561156
]);
11571157
}
11581158

1159+
public function testSubmitWithCustomCalendarOption()
1160+
{
1161+
$calendar = \IntlCalendar::createInstance();
1162+
$calendar->setFirstDayOfWeek(\IntlCalendar::DOW_SUNDAY);
1163+
1164+
$form = $this->factory->create(static::TESTED_TYPE, options: [
1165+
'format' => "y-MM-dd y'w'w",
1166+
'html5' => false,
1167+
'input' => 'array',
1168+
'calendar' => $calendar,
1169+
]);
1170+
$form->submit('2024-03-31 2024w14');
1171+
1172+
$this->assertSame('2024', $form->getData()['year']);
1173+
$this->assertSame('31', $form->getData()['day']);
1174+
$this->assertSame('3', $form->getData()['month']);
1175+
1176+
$this->assertSame('2024-03-31 2024w14', $form->getViewData());
1177+
1178+
$calendar = \IntlCalendar::createInstance();
1179+
$calendar->setFi F42D rstDayOfWeek(\IntlCalendar::DOW_MONDAY);
1180+
1181+
$form = $this->factory->create(static::TESTED_TYPE, options: [
1182+
'format' => "y-MM-dd y'w'w",
1183+
'html5' => false,
1184+
'input' => 'array',
1185+
'calendar' => $calendar,
1186+
]);
1187+
$form->submit('2024-03-31 2024w13');
1188+
1189+
$this->assertSame('2024', $form->getData()['year']);
1190+
$this->assertSame('31', $form->getData()['day']);
1191+
$this->assertSame('3', $form->getData()['month']);
1192+
1193+
$this->assertSame('2024-03-31 2024w13', $form->getViewData());
1194+
}
1195+
1196+
public function testSetDataWithCustomCalendarOption()
1197+
{
1198+
$calendar = \IntlCalendar::createInstance();
1199+
$calendar->setFirstDayOfWeek(\IntlCalendar::DOW_SUNDAY);
1200+
1201+
$form = $this->factory->create(static::TESTED_TYPE, options: [
1202+
'format' => "y-MM-dd y'w'w",
1203+
'html5' => false,
1204+
'input' => 'array',
1205+
'calendar' => $calendar,
1206+
]);
1207+
$form->setData(['year' => '2024', 'month' => '3', 'day' => '31']);
1208+
1209+
$this->assertSame('2024-03-31 2024w14', $form->getViewData());
1210+
1211+
$calendar = \IntlCalendar::createInstance();
1212+
$calendar->setFirstDayOfWeek(\IntlCalendar::DOW_MONDAY);
1213+
1214+
$form = $this->factory->create(static::TESTED_TYPE, options: [
1215+
'format' => "y-MM-dd y'w'w",
1216+
'html5' => false,
1217+
'input' => 'array',
1218+
'calendar' => $calendar,
1219+
]);
1220+
$form->setData(['year' => '2024', 'month' => '3', 'day' => '31']);
1221+
1222+
$this->assertSame('2024-03-31 2024w13', $form->getViewData());
1223+
}
1224+
11591225
protected function getTestOptions(): array
11601226
{
11611227
return ['widget' => 'choice'];

0 commit comments

Comments
 (0)
0