diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index c2412f0152e..f91dddca7dc 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -49,6 +49,7 @@ return array( 'OCP\\Activity\\Exceptions\\InvalidValueException' => $baseDir . '/lib/public/Activity/Exceptions/InvalidValueException.php', 'OCP\\Activity\\Exceptions\\SettingNotFoundException' => $baseDir . '/lib/public/Activity/Exceptions/SettingNotFoundException.php', 'OCP\\Activity\\Exceptions\\UnknownActivityException' => $baseDir . '/lib/public/Activity/Exceptions/UnknownActivityException.php', + 'OCP\\Activity\\IBulkConsumer' => $baseDir . '/lib/public/Activity/IBulkConsumer.php', 'OCP\\Activity\\IConsumer' => $baseDir . '/lib/public/Activity/IConsumer.php', 'OCP\\Activity\\IEvent' => $baseDir . '/lib/public/Activity/IEvent.php', 'OCP\\Activity\\IEventMerger' => $baseDir . '/lib/public/Activity/IEventMerger.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 9c0cf7fb9be..a93f079ee7e 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -90,6 +90,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Activity\\Exceptions\\InvalidValueException' => __DIR__ . '/../../..' . '/lib/public/Activity/Exceptions/InvalidValueException.php', 'OCP\\Activity\\Exceptions\\SettingNotFoundException' => __DIR__ . '/../../..' . '/lib/public/Activity/Exceptions/SettingNotFoundException.php', 'OCP\\Activity\\Exceptions\\UnknownActivityException' => __DIR__ . '/../../..' . '/lib/public/Activity/Exceptions/UnknownActivityException.php', + 'OCP\\Activity\\IBulkConsumer' => __DIR__ . '/../../..' . '/lib/public/Activity/IBulkConsumer.php', 'OCP\\Activity\\IConsumer' => __DIR__ . '/../../..' . '/lib/public/Activity/IConsumer.php', 'OCP\\Activity\\IEvent' => __DIR__ . '/../../..' . '/lib/public/Activity/IEvent.php', 'OCP\\Activity\\IEventMerger' => __DIR__ . '/../../..' . '/lib/public/Activity/IEventMerger.php', diff --git a/lib/private/Activity/Event.php b/lib/private/Activity/Event.php index 39cdc12b3fb..0ccad1d0a4e 100644 --- a/lib/private/Activity/Event.php +++ b/lib/private/Activity/Event.php @@ -450,7 +450,6 @@ class Event implements IEvent { return $this->getApp() !== '' && $this->getType() !== '' - && $this->getAffectedUser() !== '' && $this->getTimestamp() !== 0 /** * Disabled for BC with old activities diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php index 4e10f8a0c1a..7471b7d708a 100644 --- a/lib/private/Activity/Manager.php +++ b/lib/private/Activity/Manager.php @@ -11,12 +11,14 @@ use OCP\Activity\ActivitySettings; use OCP\Activity\Exceptions\FilterNotFoundException; use OCP\Activity\Exceptions\IncompleteActivityException; use OCP\Activity\Exceptions\SettingNotFoundException; +use OCP\Activity\IBulkConsumer; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; use OCP\Activity\IFilter; use OCP\Activity\IManager; use OCP\Activity\IProvider; use OCP\Activity\ISetting; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -46,6 +48,7 @@ class Manager implements IManager { protected IValidator $validator, protected IRichTextFormatter $richTextFormatter, protected IL10N $l10n, + protected ITimeFactory $timeFactory, ) { } @@ -96,6 +99,31 @@ class Manager implements IManager { * {@inheritDoc} */ public function publish(IEvent $event): void { + if ($event->getAuthor() === '' && $this->session->getUser() instanceof IUser) { + $event->setAuthor($this->session->getUser()->getUID()); + } + + if (!$event->getTimestamp()) { + $event->setTimestamp($this->timeFactory->getTime()); + } + + if ($event->getAffectedUser() === '' || !$event->isValid()) { + throw new IncompleteActivityException('The given event is invalid'); + } + + foreach ($this->getConsumers() as $c) { + $c->receive($event); + } + } + + /** + * {@inheritDoc} + */ + public function bulkPublish(IEvent $event, array $affectedUserIds, ISetting $setting): void { + if (empty($affectedUserIds)) { + throw new IncompleteActivityException('The given event is invalid'); + } + if ($event->getAuthor() === '') { if ($this->session->getUser() instanceof IUser) { $event->setAuthor($this->session->getUser()->getUID()); @@ -103,7 +131,7 @@ class Manager implements IManager { } if (!$event->getTimestamp()) { - $event->setTimestamp(time()); + $event->setTimestamp($this->timeFactory->getTime()); } if (!$event->isValid()) { @@ -111,10 +139,17 @@ class Manager implements IManager { } foreach ($this->getConsumers() as $c) { - $c->receive($event); + if ($c instanceof IBulkConsumer) { + $c->bulkReceive($event, $affectedUserIds, $setting); + } + foreach ($affectedUserIds as $affectedUserId) { + $event->setAffectedUser($affectedUserId); + $c->receive($event); + } } } + /** * In order to improve lazy loading a closure can be registered which will be called in case * activity consumers are actually requested diff --git a/lib/private/Server.php b/lib/private/Server.php index 171fee2afa1..22cd13438b8 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -657,7 +657,8 @@ class Server extends ServerContainer implements IServerContainer { $c->get(\OCP\IConfig::class), $c->get(IValidator::class), $c->get(IRichTextFormatter::class), - $l10n + $l10n, + $c->get(ITimeFactory::class), ); }); diff --git a/lib/public/Activity/IBulkConsumer.php b/lib/public/Activity/IBulkConsumer.php new file mode 100644 index 00000000000..9fdf3516b9a --- /dev/null +++ b/lib/public/Activity/IBulkConsumer.php @@ -0,0 +1,24 @@ +config = $this->createMock(IConfig::class); $this->validator = $this->createMock(IValidator::class); $this->richTextFormatter = $this->createMock(IRichTextFormatter::class); + $this->time = $this->createMock(ITimeFactory::class); $this->activityManager = new \OC\Activity\Manager( $this->request, @@ -46,7 +49,8 @@ class ManagerTest extends TestCase { $this->config, $this->validator, $this->richTextFormatter, - $this->createMock(IL10N::class) + $this->createMock(IL10N::class), + $this->time, ); $this->assertSame([], self::invokePrivate($this->activityManager, 'getConsumers')); @@ -217,6 +221,11 @@ class ManagerTest extends TestCase { ->willReturn($authorObject); } + $time = time(); + $this->time + ->method('getTime') + ->willReturn($time); + $event = $this->activityManager->generateEvent(); $event->setApp('test') ->setType('test_type') @@ -230,9 +239,8 @@ class ManagerTest extends TestCase { $consumer->expects($this->once()) ->method('receive') ->with($event) - ->willReturnCallback(function (IEvent $event) use ($expected): void { - $this->assertLessThanOrEqual(time() + 2, $event->getTimestamp(), 'Timestamp not set correctly'); - $this->assertGreaterThanOrEqual(time() - 2, $event->getTimestamp(), 'Timestamp not set correctly'); + ->willReturnCallback(function (IEvent $event) use ($expected, $time): void { + $this->assertEquals($time, $event->getTimestamp(), 'Timestamp not set correctly'); $this->assertSame($expected, $event->getAuthor(), 'Author name not set correctly'); }); $this->activityManager->registerConsumer(function () use ($consumer) {