Component: CalendarLink
Version: v3.4.0
Problem
IcsBuilder::build() reads the wall clock directly:
'DTSTAMP:'.$this->formatUtc(new \DateTimeImmutable('now', new \DateTimeZone('UTC'))),
The builder already takes an injectable UuidFactory so that UID generation
can be controlled in tests (MockUuidFactory in IcsBuilderTest), but
DTSTAMP has no equivalent seam. The consequence is that no test — upstream or
downstream — can assert on a complete .ics payload or on the generated
data: URI, since one line changes every second.
Symfony ships symfony/clock precisely for this, and the component already
depends on the framework.
Suggested fix
Accept an optional ClockInterface, mirroring the existing UuidFactory
parameter:
public function __construct(
?UuidFactory $uuidFactory = null,
private readonly ClockInterface $clock = new NativeClock(),
) {
$this->uuidFactory = $uuidFactory ?? new UuidFactory();
}
and use $this->clock->now() for DTSTAMP. Backward compatible, and it would
let IcsBuilderTest assert on whole payloads. Happy to open a PR.
Component: CalendarLink
Version: v3.4.0
Problem
IcsBuilder::build()reads the wall clock directly:The builder already takes an injectable
UuidFactoryso that UID generationcan be controlled in tests (
MockUuidFactoryinIcsBuilderTest), butDTSTAMPhas no equivalent seam. The consequence is that no test — upstream ordownstream — can assert on a complete
.icspayload or on the generateddata:URI, since one line changes every second.Symfony ships
symfony/clockprecisely for this, and the component alreadydepends on the framework.
Suggested fix
Accept an optional
ClockInterface, mirroring the existingUuidFactoryparameter:
and use
$this->clock->now()forDTSTAMP. Backward compatible, and it wouldlet
IcsBuilderTestassert on whole payloads. Happy to open a PR.