fix: imip set language per user

Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
pull/56665/head
SebastianKrupinski 2025-10-01 09:26:04 +07:00
parent 366652477c
commit 3d44ec453b
3 changed files with 42 additions and 11 deletions

@ -165,7 +165,7 @@ class IMipPlugin extends SabreIMipPlugin {
$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

@ -14,6 +14,7 @@ use OCP\AppFramework\Utility\ITimeFactory;
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 @@ class IMipService {
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 @@ class IMipService {
}
/**
* @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);
}
/**

@ -16,6 +16,7 @@ use OCA\DAV\CalDAV\Schedule\IMipService;
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 @@ class IMipServiceTest extends TestCase {
$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 @@ class IMipServiceTest extends TestCase {
$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 @@ class IMipServiceTest extends TestCase {
// 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 @@ class IMipServiceTest extends TestCase {
// 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 @@ class IMipServiceTest extends TestCase {
// 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');