From d41ae242f9fbe5b48499bfbf0286385d983a44ba Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 28 Jul 2026 14:56:44 +0200 Subject: [PATCH 1/2] fix(activity): Stop deprecation spam from activity provider Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Joas Schilling --- lib/Activity/Provider.php | 5 +- tests/Unit/Activity/ProviderTest.php | 91 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 tests/Unit/Activity/ProviderTest.php diff --git a/lib/Activity/Provider.php b/lib/Activity/Provider.php index a0ea968..454c05c 100644 --- a/lib/Activity/Provider.php +++ b/lib/Activity/Provider.php @@ -10,6 +10,7 @@ use OCA\Absence\Service\ActivityPublisher; use OCA\Absence\Service\ConfigService; +use OCP\Activity\Exceptions\UnknownActivityException; use OCP\Activity\IEvent; use OCP\Activity\IProvider; use OCP\IURLGenerator; @@ -27,7 +28,7 @@ public function __construct( #[\Override] public function parse($language, IEvent $event, ?IEvent $previousEvent = null): IEvent { if ($event->getApp() !== ConfigService::APP_ID) { - throw new \InvalidArgumentException('Not an Absence event'); + throw new UnknownActivityException('Not an Absence event'); } $l = $this->l10nFactory->get(ConfigService::APP_ID, $language); $params = $event->getSubjectParameters(); @@ -42,7 +43,7 @@ public function parse($language, IEvent $event, ?IEvent $previousEvent = null): ActivityPublisher::SUBJECT_ESCALATED => $l->t('Leave for %1$s (%2$s) was escalated to HR', [$employee, $range]), ActivityPublisher::SUBJECT_WITHDRAWAL => $l->t('%1$s requested to withdraw leave for %2$s', [$employee, $range]), ActivityPublisher::SUBJECT_BALANCE_ADJUSTED => $l->t('Leave balance of %s was adjusted', [$employee]), - default => throw new \InvalidArgumentException('Unknown subject'), + default => throw new UnknownActivityException('Unknown subject'), }; $event->setParsedSubject($subject); diff --git a/tests/Unit/Activity/ProviderTest.php b/tests/Unit/Activity/ProviderTest.php new file mode 100644 index 0000000..3c16ce3 --- /dev/null +++ b/tests/Unit/Activity/ProviderTest.php @@ -0,0 +1,91 @@ +createMock(IL10N::class); + $l10n->method('t')->willReturnCallback( + static fn (string $text, array $parameters = []): string => vsprintf($text, $parameters) + ); + $l10nFactory = $this->createMock(IFactory::class); + $l10nFactory->method('get')->willReturn($l10n); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->provider = new Provider($l10nFactory, $this->urlGenerator, $this->userManager); + } + + public function testParseThrowsUnknownActivityForForeignApp(): void { + $event = $this->createMock(IEvent::class); + $event->method('getApp')->willReturn('files'); + + $this->expectException(UnknownActivityException::class); + $this->provider->parse('en', $event); + } + + public function testParseThrowsUnknownActivityForUnknownSubject(): void { + $event = $this->createMock(IEvent::class); + $event->method('getApp')->willReturn(ConfigService::APP_ID); + $event->method('getSubject')->willReturn('something_else'); + $event->method('getSubjectParameters')->willReturn([]); + + $this->expectException(UnknownActivityException::class); + $this->provider->parse('en', $event); + } + + public function testParseSetsSubjectIconAndLink(): void { + $user = $this->createMock(IUser::class); + $user->method('getDisplayName')->willReturn('Alice Doe'); + $this->userManager->method('get')->with('alice')->willReturn($user); + + $this->urlGenerator->method('imagePath')->willReturn('/img/app-dark.svg'); + $this->urlGenerator->method('getAbsoluteURL')->willReturn('https://cloud.example.com/img/app-dark.svg'); + $this->urlGenerator->method('linkToRouteAbsolute')->willReturn('https://cloud.example.com/apps/absence/'); + + $event = $this->createMock(IEvent::class); + $event->method('getApp')->willReturn(ConfigService::APP_ID); + $event->method('getSubject')->willReturn(ActivityPublisher::SUBJECT_APPROVED); + $event->method('getSubjectParameters')->willReturn([ + 'employee' => 'alice', + 'start' => '2026-08-03', + 'end' => '2026-08-07', + ]); + $event->method('getObjectId')->willReturn(42); + + $event->expects($this->once()) + ->method('setParsedSubject') + ->with('Leave for Alice Doe (2026-08-03 – 2026-08-07) was approved'); + $event->expects($this->once()) + ->method('setIcon') + ->with('https://cloud.example.com/img/app-dark.svg'); + $event->expects($this->once()) + ->method('setLink') + ->with('https://cloud.example.com/apps/absence/#/requests/42'); + + $this->assertSame($event, $this->provider->parse('en', $event)); + } +} From f56587686b89041d9963b2b6afc0af177764d245 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 28 Jul 2026 22:20:59 +0200 Subject: [PATCH 2/2] chore(IUserConfig): Migrate to new IUserConfig class Signed-off-by: Joas Schilling --- lib/Service/PersonalDefaultsService.php | 6 +- .../Service/PersonalDefaultsServiceTest.php | 63 +++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/Unit/Service/PersonalDefaultsServiceTest.php diff --git a/lib/Service/PersonalDefaultsService.php b/lib/Service/PersonalDefaultsService.php index f0343d2..7d53cb3 100644 --- a/lib/Service/PersonalDefaultsService.php +++ b/lib/Service/PersonalDefaultsService.php @@ -12,7 +12,7 @@ use OCA\DAV\CalDAV\Schedule\Plugin; use OCA\DAV\Db\PropertyMapper; use OCP\Accounts\IAccountManager; -use OCP\IConfig; +use OCP\Config\IUserConfig; use OCP\IUserManager; use Psr\Log\LoggerInterface; use Sabre\VObject\Reader; @@ -49,7 +49,7 @@ class PersonalDefaultsService { ]; public function __construct( - private IConfig $config, + private IUserConfig $userConfig, private ConfigService $appConfig, private IAccountManager $accountManager, private IUserManager $userManager, @@ -139,7 +139,7 @@ public function detectWorkingWeekdays(string $uid): ?array { /** Suggested ISO country code from the user's locale, then phone; null if unknown. */ public function detectCountry(string $uid): ?string { - $locale = $this->config->getUserValue($uid, 'core', 'locale', ''); + $locale = $this->userConfig->getValueString($uid, 'core', 'locale'); if (str_contains($locale, '_')) { $region = strtoupper(substr($locale, strpos($locale, '_') + 1)); if (preg_match('/^[A-Z]{2}$/', $region)) { diff --git a/tests/Unit/Service/PersonalDefaultsServiceTest.php b/tests/Unit/Service/PersonalDefaultsServiceTest.php new file mode 100644 index 0000000..d6a2b58 --- /dev/null +++ b/tests/Unit/Service/PersonalDefaultsServiceTest.php @@ -0,0 +1,63 @@ +userConfig = $this->createMock(IUserConfig::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->service = new PersonalDefaultsService( + $this->userConfig, + $this->createMock(ConfigService::class), + $this->createMock(IAccountManager::class), + $this->userManager, + $this->createMock(PropertyMapper::class), + $this->createMock(LoggerInterface::class), + ); + } + + public function testDetectCountryReadsLocaleFromUserConfig(): void { + $this->userConfig->expects($this->once()) + ->method('getValueString') + ->with('alice', 'core', 'locale') + ->willReturn('de_AT'); + + $this->assertSame('AT', $this->service->detectCountry('alice')); + } + + public function testDetectCountryFallsBackToPhoneWhenLocaleHasNoRegion(): void { + $this->userConfig->method('getValueString')->willReturn('de'); + // No user -> phone lookup yields nothing, so the result is null rather than a guess. + $this->userManager->method('get')->with('alice')->willReturn(null); + + $this->assertNull($this->service->detectCountry('alice')); + } + + public function testDetectCountryFallsBackToPhoneWhenLocaleUnset(): void { + $this->userConfig->method('getValueString')->willReturn(''); + $this->userManager->method('get')->with('alice')->willReturn(null); + + $this->assertNull($this->service->detectCountry('alice')); + } +}