From 3d44ec453bd1ce4cdc893d9e585025e8255aeef0 Mon Sep 17 00:00:00 2001 From: SebastianKrupinski Date: Wed, 1 Oct 2025 09:26:04 -0400 Subject: [PATCH] fix: imip set language per user Signed-off-by: SebastianKrupinski --- apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 2 +- apps/dav/lib/CalDAV/Schedule/IMipService.php | 37 ++++++++++++++----- .../unit/CalDAV/Schedule/IMipServiceTest.php | 14 ++++++- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 41190c7100d6c..4d916e43dec14 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -165,7 +165,7 @@ public function schedule(Message $iTipMessage) { $iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email'; return; } - $this->imipService->setL10n($attendee); + $this->imipService->setL10nFromAttendee($attendee); // Build the sender name. // Due to a bug in sabre, the senderName property for an iTIP message can actually also be a VObject Property diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php index 531847175a1b7..a31daaa6779c6 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipService.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php @@ -14,6 +14,7 @@ use OCP\IConfig; use OCP\IDBConnection; use OCP\IL10N; +use OCP\IUserManager; use OCP\L10N\IFactory as L10NFactory; use OCP\Mail\IEMailTemplate; use OCP\Security\ISecureRandom; @@ -44,6 +45,7 @@ public function __construct( private ISecureRandom $random, private L10NFactory $l10nFactory, private ITimeFactory $timeFactory, + private readonly IUserManager $userManager, ) { $language = $this->l10nFactory->findGenericLanguage(); $locale = $this->l10nFactory->findLocale($language); @@ -870,18 +872,35 @@ public function getLastOccurrence(VCalendar $vObject) { } /** - * @param Property|null $attendee + * @param Property $attendee */ - public function setL10n(?Property $attendee = null) { - if ($attendee === null) { - return; + public function setL10nFromAttendee(Property $attendee) { + $language = null; + $locale = null; + // check if the attendee is a system user + $userAddress = $attendee->getValue(); + if (str_starts_with($userAddress, 'mailto:')) { + $userAddress = substr($userAddress, 7); } - - $lang = $attendee->offsetGet('LANGUAGE'); - if ($lang instanceof Parameter) { - $lang = $lang->getValue(); - $this->l10n = $this->l10nFactory->get('dav', $lang); + $users = $this->userManager->getByEmail($userAddress); + if ($users !== []) { + $user = array_shift($users); + $language = $this->config->getUserValue($user->getUID(), 'core', 'lang', null); + $locale = $this->config->getUserValue($user->getUID(), 'core', 'locale', null); } + // fallback to attendee LANGUAGE parameter if language not set + if ($language === null && isset($attendee['LANGUAGE']) && $attendee['LANGUAGE'] instanceof Parameter) { + $language = $attendee['LANGUAGE']->getValue(); + } + // fallback to system language if language not set + if ($language === null) { + $language = $this->l10nFactory->findGenericLanguage(); + } + // fallback to system locale if locale not set + if ($locale === null) { + $locale = $this->l10nFactory->findLocale($language); + } + $this->l10n = $this->l10nFactory->get('dav', $language, $locale); } /** diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php index abf8cfe3177f6..141a722f30a52 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php @@ -16,6 +16,7 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\IDBConnection; +use OCP\IUserManager; use OCP\L10N\IFactory as L10NFactory; use OCP\Security\ISecureRandom; use PHPUnit\Framework\MockObject\MockObject; @@ -48,6 +49,9 @@ class IMipServiceTest extends TestCase { /** @var IMipService */ private $service; + /** @var IUserManager|MockObject */ + private $userManager; + /** @var VCalendar */ private $vCalendar1a; /** @var VCalendar */ @@ -67,6 +71,7 @@ protected function setUp(): void { $this->l10nFactory = $this->createMock(L10NFactory::class); $this->l10n = $this->createMock(LazyL10N::class); $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->userManager = $this->createMock(IUserManager::class); $this->l10nFactory->expects(self::once()) ->method('findGenericLanguage') ->willReturn('en'); @@ -80,11 +85,13 @@ protected function setUp(): void { $this->db, $this->random, $this->l10nFactory, - $this->timeFactory + $this->timeFactory, + $this->userManager ); // construct calendar with a 1 hour event and same start/end time zones $this->vCalendar1a = new VCalendar(); + /** @var \Sabre\VObject\Component\VEvent $vEvent */ $vEvent = $this->vCalendar1a->add('VEVENT', []); $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); @@ -101,6 +108,7 @@ protected function setUp(): void { // construct calendar with a 1 hour event and different start/end time zones $this->vCalendar1b = new VCalendar(); + /** @var \Sabre\VObject\Component\VEvent $vEvent */ $vEvent = $this->vCalendar1b->add('VEVENT', []); $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); @@ -118,9 +126,11 @@ protected function setUp(): void { // construct calendar with a full day event $this->vCalendar2 = new VCalendar(); // time zone component + /** @var \Sabre\VObject\Component\VTimeZone $vTimeZone */ $vTimeZone = $this->vCalendar2->add('VTIMEZONE'); $vTimeZone->add('TZID', 'America/Toronto'); // event component + /** @var \Sabre\VObject\Component\VEvent $vEvent */ $vEvent = $this->vCalendar2->add('VEVENT', []); $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); $vEvent->add('DTSTART', '20240701'); @@ -138,9 +148,11 @@ protected function setUp(): void { // construct calendar with a multi day event $this->vCalendar3 = new VCalendar(); // time zone component + /** @var \Sabre\VObject\Component\VTimeZone $vTimeZone */ $vTimeZone = $this->vCalendar3->add('VTIMEZONE'); $vTimeZone->add('TZID', 'America/Toronto'); // event component + /** @var \Sabre\VObject\Component\VEvent $vEvent */ $vEvent = $this->vCalendar3->add('VEVENT', []); $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); $vEvent->add('DTSTART', '20240701');