Skip to content

[Form] Add calendar DateType option #53895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = null !== $options['calendar'] ? $options['calendar'] : \IntlDateFormatter::GREGORIAN;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$calendar = null !== $options['calendar'] ? $options['calendar'] : \IntlDateFormatter::GREGORIAN;
$calendar = $options['calendar'] ?? \IntlDateFormatter::GREGORIAN;

$pattern = \is_string($options['format']) ? $options['format'] : '';

if (!\in_array($dateFormat, self::ACCEPTED_FORMATS, true)) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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']) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we prefer long lines, maybe using named args could help? our put this on one line otherwise


$this->assertEquals('2024-03-31 2024w13', $transformer->transform($dateTime));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertSame everywhere please


\Locale::setDefault($locale);
}

public function testTransformRequiresValidDateTime()
{
$this->expectException(TransformationFailedException::class);
Expand Down Expand Up @@ -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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oneliners FTW

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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oneliner

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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use asserSame ?

Same for the other tests

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the change ready on local, but I'm not a big fan of it as other tests in changed files use assertEquals. Could somebody else give us an opinion?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opinion: never rely on assertEquals, same as never rely on == instead of ===

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can change it to assertSame across the whole file 👍

}

/**
* @dataProvider provideDateFormats
*/
Expand Down Expand Up @@ -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
Expand Down