diff --git a/lib/Consumer.php b/lib/Consumer.php index d85990718..801d2cd1a 100644 --- a/lib/Consumer.php +++ b/lib/Consumer.php @@ -7,11 +7,15 @@ */ namespace OCA\Activity; +use OCP\Activity\ActivitySettings; +use OCP\Activity\IBulkConsumer; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; use OCP\Activity\IManager; +use OCP\Activity\ISetting; +use Throwable; -class Consumer implements IConsumer { +class Consumer implements IConsumer, IBulkConsumer { public function __construct( protected Data $data, @@ -29,7 +33,7 @@ public function __construct( * @return void */ #[\Override] - public function receive(IEvent $event) { + public function receive(IEvent $event): void { $selfAction = $event->getAffectedUser() === $event->getAuthor(); $notificationSetting = $this->userSettings->getUserSetting($event->getAffectedUser(), 'notification', $event->getType()); $emailSetting = $this->userSettings->getUserSetting($event->getAffectedUser(), 'email', $event->getType()); @@ -47,4 +51,58 @@ public function receive(IEvent $event) { $this->data->storeMail($event, $latestSend); } } + + /** + * Send an event to the notifications of a user + * + * @param IEvent $event + * @throws Throwable + * + * @return void + */ + #[\Override] + public function bulkReceive(IEvent $event, array $affectedUserIds, ISetting $setting): void { + if (empty($affectedUserIds)) { + return; + } + $activityIds = $this->data->bulkSend($event, $affectedUserIds); + + if (empty($activityIds)) { + return; + } + + $canChangeMail = $setting->canChangeMail(); + $canChangePush = false; + if ($setting instanceof ActivitySettings && $setting->canChangeNotification() === true) { + $canChangePush = true; + } + + if ($canChangePush === false && $canChangeMail === false) { + return; + } + + foreach ($activityIds as $activityId => $affectedUser) { + if ($event->getAuthor() === $affectedUser) { + continue; + } + $event->setAffectedUser($affectedUser); + if ($canChangePush === true) { + $notificationSetting = $this->userSettings->getUserSetting($affectedUser, 'notification', $event->getType()); + } + + if ($canChangeMail === true) { + $emailSetting = $this->userSettings->getUserSetting($event->getAffectedUser(), 'email', $event->getType()); + $emailSetting = ($emailSetting) ? $this->userSettings->getUserSetting($event->getAffectedUser(), 'setting', 'batchtime') : false; + } + + if (isset($notificationSetting) && $notificationSetting === true) { + $this->notificationGenerator->sendNotificationForEvent($event, $activityId, $notificationSetting); + } + + if (isset($emailSetting) && $emailSetting !== false) { + $latestSend = $event->getTimestamp() + $emailSetting; + $this->data->storeMail($event, $latestSend); + } + } + } } diff --git a/lib/Data.php b/lib/Data.php index cf7383d1c..e09774385 100644 --- a/lib/Data.php +++ b/lib/Data.php @@ -15,10 +15,12 @@ use OCP\Activity\IExtension; use OCP\Activity\IFilter; use OCP\Activity\IManager; +use OCP\DB\Exception; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; use Psr\Log\LoggerInterface; +use Throwable; /** * @brief Class for managing the data in the activities @@ -91,6 +93,72 @@ public function send(IEvent $event): int { return $this->insertActivity->getLastInsertId(); } + /** + * Bulk sends an event into the activity stream + * for a batch of users that are affected by the same event + * (ex. Call Started, Call ended) + * + * @param IEvent $event + * @param array $affectedUsers + * @return array + * @throws Exception + */ + public function bulkSend(IEvent $event, array $affectedUsers): array { + $this->connection->beginTransaction(); + + $activityIds = []; + try { + $qb = $this->connection->getQueryBuilder(); + $qb->insert('activity') + ->values([ + 'app' => $this->insertActivity->createParameter('app'), + 'subject' => $this->insertActivity->createParameter('subject'), + 'subjectparams' => $this->insertActivity->createParameter('subjectparams'), + 'message' => $this->insertActivity->createParameter('message'), + 'messageparams' => $this->insertActivity->createParameter('messageparams'), + 'file' => $this->insertActivity->createParameter('object_name'), + 'link' => $this->insertActivity->createParameter('link'), + 'user' => $this->insertActivity->createParameter('user'), + 'affecteduser' => $this->insertActivity->createParameter('affecteduser'), + 'timestamp' => $this->insertActivity->createParameter('timestamp'), + 'priority' => $this->insertActivity->createParameter('priority'), + 'type' => $this->insertActivity->createParameter('type'), + 'object_type' => $this->insertActivity->createParameter('object_type'), + 'object_id' => $this->insertActivity->createParameter('object_id'), + ]); + + $qb->setParameters([ + 'app' => $event->getApp(), + 'type' => $event->getType(), + 'user' => $event->getAuthor(), + 'timestamp' => $event->getTimestamp(), + 'subject' => $event->getSubject(), + 'subjectparams' => json_encode($event->getSubjectParameters()), + 'message' => $event->getMessage(), + 'messageparams' => json_encode($event->getMessageParameters()), + 'priority' => IExtension::PRIORITY_MEDIUM, + 'object_type' => $event->getObjectType(), + 'object_id' => $event->getObjectId(), + 'object_name' => $event->getObjectName(), + 'link' => $event->getLink(), + ]); + + foreach ($affectedUsers as $affectedUser) { + $qb->setParameter('affecteduser', $affectedUser); + $qb->executeStatement(); + $activityIds[$qb->getLastInsertId()] = (string)$affectedUser; + } + + $this->connection->commit(); + } catch (Throwable) { + // Make sure to always roll back, otherwise the outer code runs in a failed transaction + $this->connection->rollBack(); + return []; + } + + return $activityIds; + } + /** * Send an event as email *