diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index e15e111ce..b3695e1eb 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -46,6 +46,7 @@ use OCA\Deck\Listeners\BeforeTemplateRenderedListener; use OCA\Deck\Listeners\ParticipantCleanupListener; use OCA\Deck\Listeners\FullTextSearchEventListener; use OCA\Deck\Listeners\ResourceListener; +use OCA\Deck\Listeners\LiveUpdateListener; use OCA\Deck\Middleware\DefaultBoardMiddleware; use OCA\Deck\Middleware\ExceptionMiddleware; use OCA\Deck\Notification\Notifier; @@ -53,10 +54,8 @@ use OCA\Deck\Reference\CardReferenceProvider; use OCA\Deck\Search\CardCommentProvider; use OCA\Deck\Search\DeckProvider; use OCA\Deck\Service\PermissionService; -use OCA\Deck\Service\SessionService; use OCA\Deck\Sharing\DeckShareProvider; use OCA\Deck\Sharing\Listener; -use OCA\NotifyPush\Queue\IQueue; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; @@ -100,7 +99,6 @@ class Application extends App implements IBootstrap { $context->injectFn(Closure::fromCallable([$this, 'registerCommentsEventHandler'])); $context->injectFn(Closure::fromCallable([$this, 'registerNotifications'])); $context->injectFn(Closure::fromCallable([$this, 'registerCollaborationResources'])); - $context->injectFn(Closure::fromCallable([$this, 'registerSessionListener'])); $context->injectFn(function (IManager $shareManager) { $shareManager->registerShareProvider(DeckShareProvider::class); @@ -152,6 +150,10 @@ class Application extends App implements IBootstrap { $context->registerEventListener(UserDeletedEvent::class, ParticipantCleanupListener::class); $context->registerEventListener(GroupDeletedEvent::class, ParticipantCleanupListener::class); $context->registerEventListener(CircleDestroyedEvent::class, ParticipantCleanupListener::class); + + // Event listening for realtime updates via notify_push + $context->registerEventListener(SessionCreatedEvent::class, LiveUpdateListener::class); + $context->registerEventListener(SessionClosedEvent::class, LiveUpdateListener::class); } public function registerNotifications(NotificationManager $notificationManager): void { @@ -193,33 +195,4 @@ class Application extends App implements IBootstrap { Util::addScript('deck', 'deck-collections'); }); } - - protected function registerSessionListener(IEventDispatcher $eventDispatcher): void { - $container = $this->getContainer(); - - try { - $queue = $container->get(IQueue::class); - } catch (\Exception $e) { - // most likely notify_push is not installed. - return; - } - - // if SessionService is injected via function parameters, tests throw following error: - // "OCA\Deck\NoPermissionException: Creating boards has been disabled for your account." - // doing it this way it somehow works - $sessionService = $container->get(SessionService::class); - - - $eventDispatcher->addListener(SessionCreatedEvent::class, function (SessionCreatedEvent $event) use ($sessionService, $queue) { - $sessionService->notifyAllSessions($queue, $event->getBoardId(), "DeckBoardUpdate", $event->getUserId(), [ - "id" => $event->getBoardId() - ]); - }); - - $eventDispatcher->addListener(SessionClosedEvent::class, function (SessionClosedEvent $event) use ($sessionService, $queue) { - $sessionService->notifyAllSessions($queue, $event->getBoardId(), "DeckBoardUpdate", $event->getUserId(), [ - "id" => $event->getBoardId() - ]); - }); - } } diff --git a/lib/Listeners/LiveUpdateListener.php b/lib/Listeners/LiveUpdateListener.php new file mode 100644 index 000000000..06eecfe4f --- /dev/null +++ b/lib/Listeners/LiveUpdateListener.php @@ -0,0 +1,73 @@ + + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +declare(strict_types=1); + + +namespace OCA\Deck\Listeners; + +use OCA\Deck\NotifyPushEvents; +use OCA\Deck\Event\SessionClosedEvent; +use OCA\Deck\Event\SessionCreatedEvent; +use OCA\Deck\Service\SessionService; +use OCA\NotifyPush\Queue\IQueue; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; + +class LiveUpdateListener implements IEventListener { + private string $userId; + private LoggerInterface $logger; + private SessionService $sessionService; + private $queue; + + public function __construct(ContainerInterface $container, SessionService $sessionService, $userId) { + try { + $this->queue = $container->get(IQueue::class); + } catch (\Exception $e) { + // most likely notify_push is not installed. + return; + } + $this->userId = $userId; + $this->logger = $container->get(LoggerInterface::class); + $this->sessionService = $sessionService; + } + + public function handle(Event $event): void { + if (!$this->queue) { + // notify_push is not active + return; + } + + try { + if ($event instanceof SessionCreatedEvent || $event instanceof SessionClosedEvent) { + $this->sessionService->notifyAllSessions($this->queue, $event->getBoardId(), NotifyPushEvents::DeckBoardUpdate, $event->getUserId(), [ + 'id' => $event->getBoardId() + ]); + } + } catch (\Exception $e) { + $this->logger->error('Error when handling live update event', ['exception' => $e]); + } + } +} diff --git a/lib/NotifyPushEvents.php b/lib/NotifyPushEvents.php new file mode 100644 index 000000000..3fed8d11d --- /dev/null +++ b/lib/NotifyPushEvents.php @@ -0,0 +1,26 @@ +. + * + */ + +namespace OCA\Deck; + +class NotifyPushEvents { + public const DeckBoardUpdate = 'deck_board_update'; +} diff --git a/lib/Service/SessionService.php b/lib/Service/SessionService.php index 28f0fc91e..bd8ab34cc 100644 --- a/lib/Service/SessionService.php +++ b/lib/Service/SessionService.php @@ -66,6 +66,9 @@ class SessionService { return $session; } + /** + * @throws DoesNotExistException + */ public function syncSession(int $boardId, string $token) { $session = $this->sessionMapper->find($boardId, $this->userId, $token); $session->setLastContact($this->timeFactory->getTime());