Reject normalized datetime-local inputs

createFromFormat() only returns false on hard parse failures.
Impossible dates such as 2026-02-31 were silently normalized
into March, so a confirmed event could land on a different day
than the booking link supplied. Non-padded values like
2026-2-3T10:00 were also accepted and reformatted.

Parse with a leading "!" so no current-date fields leak in,
require zero warnings and errors from getLastErrors(), and
round-trip the value through the format. Impossible dates,
out-of-range components and non-padded values now throw in
both the confirmation and the creation stage.
This commit is contained in:
stefan.tollkuehn committed 2026-10-26 13:39:07 +01:00
1 parent a9b7fd11af
commit 2b3e96e50a
2 files changed
+53 -15

No files matched your search

+29
View File
@@ -218,6 +218,35 @@ class CalendarControllerTest extends TestCase
$this->invoke($c, 'parseLocalDateTime', ['tomorrow']);
}
public function testParseLocalDateTimeAcceptsLeapDay(): void
{
$c = $this->newController();
$date = $this->invoke($c, 'parseLocalDateTime', ['2028-02-29T10:00']);
$this->assertSame('2028-02-29 10:00:00 UTC', $date->format('Y-m-d H:i:s T'));
}
public static function provideInvalidLocalDateTimes(): iterable
{
return [
'impossible day rolls into next month' => ['2026-02-31T10:00'],
'leap day in a non-leap year' => ['2027-02-29T10:00'],
'month out of range' => ['2026-13-01T10:00'],
'day out of range' => ['2026-00-15T10:00'],
'hour out of range' => ['2026-02-03T25:00'],
'non-padded components' => ['2026-2-3T10:00'],
];
}
#[DataProvider('provideInvalidLocalDateTimes')]
public function testParseLocalDateTimeRejectsInvalidValues(string $value): void
{
$c = $this->newController();
$this->expectException(\InvalidArgumentException::class);
$this->invoke($c, 'parseLocalDateTime', [$value]);
}
/*
* validateEventData
*/