Skip to content
Merged
Show file tree
Hide file tree
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
20 changes: 14 additions & 6 deletions lib/Consumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCP\Config\IUserConfig;
use OCP\Config\ValueType;
use OCP\DB\Exception;
use OCP\IAppConfig;

class Consumer implements IConsumer, IBulkConsumer {

Expand All @@ -25,6 +26,7 @@ public function __construct(
protected UserSettings $userSettings,
protected NotificationGenerator $notificationGenerator,
protected IUserConfig $userConfig,
protected IAppConfig $appConfig,
) {
}

Expand Down Expand Up @@ -78,13 +80,16 @@ public function bulkReceive(IEvent $event, array $affectedUserIds, ISetting $set

$canChangeMail = $setting->canChangeMail();
$canChangePush = $setting instanceof ActivitySettings && $setting->canChangeNotification() === true;
$defaultPushEnabled = $setting instanceof ActivitySettings && $setting->isDefaultEnabledNotification();

$userPushSettings = $userEmailSettings = $batchTimeSettings = null;
$userPushSettings = null;
if ($canChangePush === true) {
$userPushSettings = $this->userConfig->getValuesByUsers('activity', 'notify_notification_' . $event->getType(), ValueType::BOOL, $affectedUserIds);
}

if ($canChangeMail === true || $setting->isDefaultEnabledMail() === true) {
$userEmailSettings = $batchTimeSettings = null;
$emailEnabled = $this->appConfig->getValueString('activity', 'enable_email', 'yes') !== 'no';
if ($emailEnabled && ($canChangeMail === true || $setting->isDefaultEnabledMail() === true)) {
$userEmailSettings = $this->userConfig->getValuesByUsers('activity', 'notify_email_' . $event->getType(), ValueType::BOOL, $affectedUserIds);
$batchTimeSettings = $this->userConfig->getValuesByUsers('activity', 'notify_setting_batchtime', ValueType::INT, $affectedUserIds);
}
Expand All @@ -95,14 +100,17 @@ public function bulkReceive(IEvent $event, array $affectedUserIds, ISetting $set
continue;
}
$event->setAffectedUser($affectedUser);
$notificationSetting = $userPushSettings[$affectedUser] ?? null;
if ($notificationSetting !== null) {
$notificationSetting = (bool)$notificationSetting;

if ($canChangePush === true) {
$notificationSetting = isset($userPushSettings[$affectedUser]) ? (bool)$userPushSettings[$affectedUser] : $defaultPushEnabled;
} else {
$notificationSetting = $defaultPushEnabled;
}

$emailSetting = $userEmailSettings[$affectedUser] ?? false;
$emailSetting = ($emailSetting) ? ($batchTimeSettings[$affectedUser] ?? false) : false;

if ($notificationSetting !== false) {
if ($notificationSetting === true) {
$this->notificationGenerator->sendNotificationForEvent($event, $activityId, $notificationSetting);
}

Expand Down
260 changes: 259 additions & 1 deletion tests/ConsumerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
use OCP\Activity\ActivitySettings;
use OCP\Activity\IEvent;
use OCP\Activity\IManager;
use OCP\Activity\ISetting;
use OCP\Config\IUserConfig;
use OCP\IAppConfig;
use OCP\IDBConnection;
use OCP\IL10N;
use OCP\L10N\IFactory;
Expand All @@ -52,6 +54,7 @@ class ConsumerTest extends TestCase {
protected NotificationGenerator&MockObject $notificationGenerator;
protected UserSettings $userSettings;
private IUserConfig&MockObject $userConfig;
private IAppConfig&MockObject $appConfig;
private IEvent $event;
private Consumer $consumer;

Expand All @@ -69,7 +72,10 @@ protected function setUp(): void {
$this->notificationGenerator = $this->createMock(NotificationGenerator::class);
$this->l10nFactory = $this->createMock(IFactory::class);
$this->userConfig = $this->createMock(IUserConfig::class);

$this->appConfig = $this->createMock(IAppConfig::class);
$this->appConfig->method('getValueString')
->with('activity', 'enable_email', 'yes')
->willReturn('yes');
$this->data->method('send')
->willReturn(1);
$this->l10nFactory
Expand All @@ -94,6 +100,7 @@ protected function setUp(): void {
$this->userSettings,
$this->notificationGenerator,
$this->userConfig,
$this->appConfig,
);

$this->event = Server::get(IManager::class)->generateEvent();
Expand Down Expand Up @@ -142,6 +149,7 @@ public function testReceiveStream(string $type, string $author, string $affected
$this->userSettings,
$this->notificationGenerator,
$this->userConfig,
$this->appConfig,
);
$event = Server::get(IManager::class)->generateEvent();
$event->setApp('test')
Expand Down Expand Up @@ -263,4 +271,254 @@ public function testBulkReceiveNotification(string $type, string $author, string
$this->consumer->bulkReceive($this->event, $affectedUsers, $settings);
}

public function testBulkReceiveEmail(): void {
$time = time();
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp($time)
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(true);
$settings->method('isDefaultEnabledMail')->willReturn(true);
$settings->method('canChangeNotification')->willReturn(false);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser', 2 => 'affectedUser2']);

$this->userConfig->method('getValuesByUsers')
->willReturnCallback(function (string $app, string $key, mixed $type, array $users): array {
if (str_contains($key, 'email')) {
return array_fill_keys($users, true);
}
if (str_contains($key, 'batchtime')) {
return array_fill_keys($users, 10);
}
return [];
});

$this->data->expects($this->exactly(2))
->method('storeMail');

$this->consumer->bulkReceive($this->event, ['affectedUser', 'affectedUser2'], $settings);
}

public function testBulkReceiveNoMailWhenSettingDisabled(): void {
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp(time())
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(false);
$settings->method('isDefaultEnabledMail')->willReturn(false);
$settings->method('canChangeNotification')->willReturn(false);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser']);

$this->data->expects($this->never())
->method('storeMail');
$this->notificationGenerator->expects($this->never())
->method('sendNotificationForEvent');

$this->consumer->bulkReceive($this->event, ['affectedUser'], $settings);
}

public function testBulkReceiveDeferAndFlushNotifications(): void {
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp(time())
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(false);
$settings->method('isDefaultEnabledMail')->willReturn(false);
$settings->method('canChangeNotification')->willReturn(true);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser']);

$this->userConfig->method('getValuesByUsers')
->willReturnCallback(function (string $app, string $key, mixed $type, array $users): array {
return array_fill_keys($users, true);
});

$this->notificationGenerator->expects($this->once())
->method('deferNotifications')
->willReturn(true);
$this->notificationGenerator->expects($this->once())
->method('flushNotifications');
$this->notificationGenerator->expects($this->once())
->method('sendNotificationForEvent');

$this->consumer->bulkReceive($this->event, ['affectedUser'], $settings);
}

public function testBulkReceiveNoFlushWhenDeferReturnsFalse(): void {
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp(time())
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(false);
$settings->method('isDefaultEnabledMail')->willReturn(false);
$settings->method('canChangeNotification')->willReturn(true);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser']);

$this->userConfig->method('getValuesByUsers')
->willReturnCallback(function (string $app, string $key, mixed $type, array $users): array {
return array_fill_keys($users, true);
});

$this->notificationGenerator->expects($this->once())
->method('deferNotifications')
->willReturn(false);
$this->notificationGenerator->expects($this->never())
->method('flushNotifications');

$this->consumer->bulkReceive($this->event, ['affectedUser'], $settings);
}

public function testBulkReceiveMultipleUsersWithMixedSettings(): void {
$time = time();
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp($time)
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(true);
$settings->method('isDefaultEnabledMail')->willReturn(true);
$settings->method('canChangeNotification')->willReturn(true);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'user1', 2 => 'user2', 3 => 'author']);

$this->userConfig->method('getValuesByUsers')
->willReturnCallback(function (string $app, string $key, mixed $type, array $users): array {
if (str_contains($key, 'notification')) {
// Only user1 has notifications enabled
return ['user1' => true];
}
if (str_contains($key, 'email')) {
// Only user2 has email enabled
return ['user2' => true];
}
if (str_contains($key, 'batchtime')) {
return ['user2' => 15];
}
return [];
});

// only user1 has an explicit notification=true in DB; user2 has no entry so falls back to isDefaultEnabledNotification()=false
$this->notificationGenerator->expects($this->once())
->method('sendNotificationForEvent');
// user2 gets email, author is skipped
$this->data->expects($this->once())
->method('storeMail')
->with($this->event, $time + 15);

$this->consumer->bulkReceive($this->event, ['user1', 'user2', 'author'], $settings);
}

public function testBulkReceiveNoMailWhenAdminEmailDisabled(): void {
$time = time();
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp($time)
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

$appConfig = $this->createMock(IAppConfig::class);
$appConfig->method('getValueString')
->with('activity', 'enable_email', 'yes')
->willReturn('no');

$consumer = new Consumer(
$this->data,
$this->activityManager,
$this->userSettings,
$this->notificationGenerator,
$this->userConfig,
$appConfig,
);

$settings = $this->createMock(ActivitySettings::class);
$settings->method('canChangeMail')->willReturn(true);
$settings->method('isDefaultEnabledMail')->willReturn(true);
$settings->method('canChangeNotification')->willReturn(false);
$settings->method('isDefaultEnabledNotification')->willReturn(false);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser']);

$this->userConfig->expects($this->never())
->method('getValuesByUsers');

$this->data->expects($this->never())
->method('storeMail');

$consumer->bulkReceive($this->event, ['affectedUser'], $settings);
}

public function testBulkReceiveWithISetting(): void {
$this->event->setApp('activity')
->setType('type')
->setAuthor('author')
->setTimestamp(time())
->setSubject('subject', ['subjectParam1'])
->setMessage('message', ['messageParam1'])
->setObject('', 0, 'file')
->setLink('link');

// ISetting (not ActivitySettings) — canChangeNotification is not available
$settings = $this->createMock(ISetting::class);
$settings->method('canChangeMail')->willReturn(false);

$this->data->expects($this->once())
->method('bulkSend')
->willReturn([1 => 'affectedUser']);

// ISetting is not ActivitySettings so $defaultPushEnabled is false — no notification sent
$this->notificationGenerator->expects($this->never())
->method('sendNotificationForEvent');
$this->data->expects($this->never())
->method('storeMail');

$this->consumer->bulkReceive($this->event, ['affectedUser'], $settings);
}

}
Loading