Skip to content
Merged
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
67 changes: 62 additions & 5 deletions src/CoreBundle/Command/SendEventRemindersCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
continue;
}

$eventDetails = $this->generateEventDetails($event);
// NOTE: keep this call (without user) if you rely on it elsewhere; it does not change behavior.
// We now format per-user inside sendReminderMessage().
$eventDetails = $this->generateEventDetails($event, null);

$initialSentRemindersCount = $sentRemindersCount;

Expand Down Expand Up @@ -193,6 +195,47 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::SUCCESS;
}

/**
* Resolve the DateTimeZone to use for a given user (CLI-safe, no legacy api_* calls).
* Priority: user's timezone -> platform timezone setting -> UTC.
*/
private function resolveTimezoneForUser(?User $user): DateTimeZone
{
// User explicit timezone (if present and valid)
$tzId = $user?->getTimezone();
if (\is_string($tzId) && $tzId !== '') {
try {
return new DateTimeZone($tzId);
} catch (\Throwable) {
// keep going
}
}

// Platform timezone setting (equivalent to api_get_setting('platform.timezone', false, 'timezones'))
$platformTz = (string) ($this->settingsManager->getSetting('platform.timezone', false, 'timezones') ?? '');
if ($platformTz !== '') {
try {
return new DateTimeZone($platformTz);
} catch (\Throwable) {
// keep going
}
}

return new DateTimeZone('UTC');
}

/**
* Format a UTC DateTime into the user's local timezone, CLI-safe.
*/
private function formatForUser(DateTime $utc, ?User $user): string
{
$dt = (clone $utc);
$dt->setTimezone($this->resolveTimezoneForUser($user));

// Keep the existing format as used previously.
return $dt->format('Y-m-d H:i:s');
}

private function sendReminderMessage(User $user, CCalendarEvent $event, int $senderId, bool $debug, SymfonyStyle $io, int &$sentRemindersCount): void
{
$locale = $user->getLocale() ?: 'en';
Expand All @@ -202,7 +245,9 @@ private function sendReminderMessage(User $user, CCalendarEvent $event, int $sen
$this->translator->trans('Reminder for event : %s'),
$event->getTitle()
);
$messageContent = implode(PHP_EOL, $this->generateEventDetails($event));

// IMPORTANT: build details with user's timezone applied
$messageContent = implode(PHP_EOL, $this->generateEventDetails($event, $user));

$this->messageHelper->sendMessage(
$user->getId(),
Expand Down Expand Up @@ -237,23 +282,35 @@ private function getFirstAdminId(): int
: 1;
}

private function generateEventDetails(CCalendarEvent $event): array
/**
* Build event details text. If $user is provided, dates are converted to user's local timezone.
* Otherwise, keep UTC (backward compatible path).
*/
private function generateEventDetails(CCalendarEvent $event, ?User $user = null): array
{
$details = [];
$details[] = \sprintf('<p><strong>%s</strong></p>', $event->getTitle());

if ($event->isAllDay()) {
$details[] = \sprintf('<p class="small">%s</p>', $this->translator->trans('All day'));
} else {
$fromStr = $user
? $this->formatForUser($event->getStartDate(), $user)
: $event->getStartDate()->format('Y-m-d H:i:s');

$details[] = \sprintf(
'<p class="small">%s</p>',
$this->translator->trans('From %s', ['%s' => $event->getStartDate()->format('Y-m-d H:i:s')])
$this->translator->trans('From %s', ['%s' => $fromStr])
);

if ($event->getEndDate()) {
$untilStr = $user
? $this->formatForUser($event->getEndDate(), $user)
: $event->getEndDate()->format('Y-m-d H:i:s');

$details[] = \sprintf(
'<p class="small">%s</p>',
$this->translator->trans('Until %s', ['%s' => $event->getEndDate()->format('Y-m-d H:i:s')])
$this->translator->trans('Until %s', ['%s' => $untilStr])
);
}
}
Expand Down
Loading