From 89189a9a071ad569bcbfab021b3fbe8ea00b131b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 20 Aug 2020 17:38:33 +0200 Subject: [PATCH] Keep 18 compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/AppInfo/Application.php | 224 +--------------------- lib/AppInfo/Application20.php | 249 ++++++++++++++++++++++++ lib/AppInfo/ApplicationLegacy.php | 264 ++++++++++++++++++++++++++ lib/Db/CardMapper.php | 5 +- lib/Db/StackMapper.php | 2 +- lib/Search/BoardSearchResultEntry.php | 2 - lib/Search/CardSearchResultEntry.php | 2 - lib/Search/DeckProvider.php | 24 +-- lib/Service/BoardService.php | 62 +++--- 9 files changed, 566 insertions(+), 268 deletions(-) create mode 100644 lib/AppInfo/Application20.php create mode 100644 lib/AppInfo/ApplicationLegacy.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index eddd437fe..048dc5b3c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -23,225 +23,11 @@ namespace OCA\Deck\AppInfo; -use Exception; -use OC_Util; -use OCA\Deck\Activity\CommentEventHandler; -use OCA\Deck\Capabilities; -use OCA\Deck\Collaboration\Resources\ResourceProvider; -use OCA\Deck\Collaboration\Resources\ResourceProviderCard; -use OCA\Deck\Db\Acl; -use OCA\Deck\Db\AclMapper; -use OCA\Deck\Db\AssignedUsersMapper; -use OCA\Deck\Db\BoardMapper; -use OCA\Deck\Db\CardMapper; -use OCA\Deck\Middleware\DefaultBoardMiddleware; -use OCA\Deck\Middleware\ExceptionMiddleware; -use OCA\Deck\Notification\Notifier; -use OCA\Deck\Search\DeckProvider; -use OCA\Deck\Service\FullTextSearchService; -use OCA\Deck\Service\PermissionService; -use OCP\AppFramework\App; -use OCP\AppFramework\Bootstrap\IBootContext; -use OCP\AppFramework\Bootstrap\IBootstrap; -use OCP\AppFramework\Bootstrap\IRegistrationContext; -use OCP\Collaboration\Resources\IManager; -use OCP\Collaboration\Resources\IProviderManager; -use OCP\Comments\CommentsEntityEvent; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventDispatcher; -use OCP\FullTextSearch\IFullTextSearchManager; -use OCP\IConfig; -use OCP\IContainer; -use OCP\IDBConnection; -use OCP\IGroup; -use OCP\IServerContainer; -use OCP\IUser; -use OCP\IUserManager; -use OCP\IURLGenerator; -use OCP\Util; - -class Application extends App implements IBootstrap { - public const APP_ID = 'deck'; - - public const COMMENT_ENTITY_TYPE = 'deckCard'; - - /** @var IServerContainer */ - private $server; - - /** @var FullTextSearchService */ - private $fullTextSearchService; - - /** @var IFullTextSearchManager */ - private $fullTextSearchManager; - - public function __construct(array $urlParams = []) { - parent::__construct(self::APP_ID, $urlParams); - - $this->server = \OC::$server; - } - - public function boot(IBootContext $context): void { - $notificationManager = $context->getServerContainer()->get(\OCP\Notification\IManager::class); - $notificationManager->registerNotifierService(Notifier::class); - \OCP\Util::addStyle('deck', 'deck'); - } - - public function register(IRegistrationContext $context): void { - - $context->registerCapability(Capabilities::class); - $context->registerMiddleWare(ExceptionMiddleware::class); - $context->registerMiddleWare(DefaultBoardMiddleware::class); - - $context->registerService('databaseType', static function (IContainer $c) { - return $c->get(IConfig::class)->getSystemValue('dbtype', 'sqlite'); - }); - $context->registerService('database4ByteSupport', static function (IContainer $c) { - return $c->get(IDBConnection::class)->supports4ByteText(); - }); - - $context->registerSearchProvider(DeckProvider::class); - - $this->registerUserGroupHooks(); - - $this->registerCommentsEntity(); - $this->registerFullTextSearch(); - $this->registerCollaborationResources(); +$version = \OC_Util::getVersion()[0]; +if ($version >= 20) { + class Application extends Application20 { } - - private function registerUserGroupHooks(): void { - $container = $this->getContainer(); - // Delete user/group acl entries when they get deleted - /** @var IUserManager $userManager */ - $userManager = $this->server->getUserManager(); - $userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) { - // delete existing acl entries for deleted user - /** @var AclMapper $aclMapper */ - $aclMapper = $container->query(AclMapper::class); - $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID()); - foreach ($acls as $acl) { - $aclMapper->delete($acl); - } - // delete existing user assignments - $assignmentMapper = $container->query(AssignedUsersMapper::class); - $assignments = $assignmentMapper->findByUserId($user->getUID()); - foreach ($assignments as $assignment) { - $assignmentMapper->delete($assignment); - } - - /** @var BoardMapper $boardMapper */ - $boardMapper = $container->query(BoardMapper::class); - $boards = $boardMapper->findAllByOwner($user->getUID()); - foreach ($boards as $board) { - $boardMapper->delete($board); - } - }); - - /** @var IUserManager $userManager */ - $groupManager = $this->server->getGroupManager(); - $groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) { - /** @var AclMapper $aclMapper */ - $aclMapper = $container->query(AclMapper::class); - $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); - $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); - foreach ($acls as $acl) { - $aclMapper->delete($acl); - } - }); - } - - public function registerCommentsEntity(): void { - $this->server->getEventDispatcher()->addListener(CommentsEntityEvent::EVENT_ENTITY, function (CommentsEntityEvent $event) { - $event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) { - /** @var CardMapper */ - $cardMapper = $this->getContainer()->query(CardMapper::class); - $permissionService = $this->getContainer()->query(PermissionService::class); - - try { - return $permissionService->checkPermission($cardMapper, (int) $name, Acl::PERMISSION_READ); - } catch (\Exception $e) { - return false; - } - }); - }); - $this->registerCommentsEventHandler(); - } - - protected function registerCommentsEventHandler(): void { - $this->server->getCommentsManager()->registerEventHandler(function () { - return $this->getContainer()->query(CommentEventHandler::class); - }); - } - - protected function registerCollaborationResources(): void { - $version = OC_Util::getVersion()[0]; - /** - * Register Collaboration ResourceProvider - * - * @Todo: Remove if min-version is 18 - */ - if ($version < 18) { - /** @var IManager $resourceManager */ - $resourceManager = $this->getContainer()->query(IManager::class); - } else { - /** @var IProviderManager $resourceManager */ - $resourceManager = $this->getContainer()->query(IProviderManager::class); - } - $resourceManager->registerResourceProvider(ResourceProvider::class); - $resourceManager->registerResourceProvider(ResourceProviderCard::class); - - $this->server->getEventDispatcher()->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () { - Util::addScript('deck', 'collections'); - }); - } - - public function registerFullTextSearch(): void { - if (Util::getVersion()[0] < 16) { - return; - } - - $c = $this->getContainer(); - try { - $this->fullTextSearchService = $c->query(FullTextSearchService::class); - $this->fullTextSearchManager = $c->query(IFullTextSearchManager::class); - } catch (Exception $e) { - return; - } - - if (!$this->fullTextSearchManager->isAvailable()) { - return; - } - - /** @var IEventDispatcher $eventDispatcher */ - $eventDispatcher = $this->server->query(IEventDispatcher::class); - $eventDispatcher->addListener( - '\OCA\Deck\Card::onCreate', function (Event $e) { - $this->fullTextSearchService->onCardCreated($e); - } - ); - $eventDispatcher->addListener( - '\OCA\Deck\Card::onUpdate', function (Event $e) { - $this->fullTextSearchService->onCardUpdated($e); - } - ); - $eventDispatcher->addListener( - '\OCA\Deck\Card::onDelete', function (Event $e) { - $this->fullTextSearchService->onCardDeleted($e); - } - ); - $eventDispatcher->addListener( - '\OCA\Deck\Board::onShareNew', function (Event $e) { - $this->fullTextSearchService->onBoardShares($e); - } - ); - $eventDispatcher->addListener( - '\OCA\Deck\Board::onShareEdit', function (Event $e) { - $this->fullTextSearchService->onBoardShares($e); - } - ); - $eventDispatcher->addListener( - '\OCA\Deck\Board::onShareDelete', function (Event $e) { - $this->fullTextSearchService->onBoardShares($e); - } - ); +} else { + class Application extends ApplicationLegacy { } } diff --git a/lib/AppInfo/Application20.php b/lib/AppInfo/Application20.php new file mode 100644 index 000000000..7e672b944 --- /dev/null +++ b/lib/AppInfo/Application20.php @@ -0,0 +1,249 @@ + + * + * @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 . + * + */ + +namespace OCA\Deck\AppInfo; + +use Exception; +use OC_Util; +use OCA\Deck\Activity\CommentEventHandler; +use OCA\Deck\Capabilities; +use OCA\Deck\Collaboration\Resources\ResourceProvider; +use OCA\Deck\Collaboration\Resources\ResourceProviderCard; +use OCA\Deck\Db\Acl; +use OCA\Deck\Db\AclMapper; +use OCA\Deck\Db\AssignedUsersMapper; +use OCA\Deck\Db\BoardMapper; +use OCA\Deck\Db\CardMapper; +use OCA\Deck\Middleware\DefaultBoardMiddleware; +use OCA\Deck\Middleware\ExceptionMiddleware; +use OCA\Deck\Notification\Notifier; +use OCA\Deck\Search\DeckProvider; +use OCA\Deck\Service\FullTextSearchService; +use OCA\Deck\Service\PermissionService; +use OCP\AppFramework\App; +use OCP\AppFramework\Bootstrap\IBootContext; +use OCP\AppFramework\Bootstrap\IBootstrap; +use OCP\AppFramework\Bootstrap\IRegistrationContext; +use OCP\Collaboration\Resources\IManager; +use OCP\Collaboration\Resources\IProviderManager; +use OCP\Comments\CommentsEntityEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\FullTextSearch\IFullTextSearchManager; +use OCP\IConfig; +use OCP\IContainer; +use OCP\IDBConnection; +use OCP\IGroup; +use OCP\IServerContainer; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Util; + +class Application20 extends App implements IBootstrap { + public const APP_ID = 'deck'; + + public const COMMENT_ENTITY_TYPE = 'deckCard'; + + /** @var IServerContainer */ + private $server; + + /** @var FullTextSearchService */ + private $fullTextSearchService; + + /** @var IFullTextSearchManager */ + private $fullTextSearchManager; + + public function __construct(array $urlParams = []) { + parent::__construct(self::APP_ID, $urlParams); + + $this->server = \OC::$server; + } + + public function boot(IBootContext $context): void { + $notificationManager = $context->getServerContainer()->get(\OCP\Notification\IManager::class); + $notificationManager->registerNotifierService(Notifier::class); + \OCP\Util::addStyle('deck', 'deck'); + } + + public function register(IRegistrationContext $context): void { + if ((@include_once __DIR__ . '/../../vendor/autoload.php') === false) { + throw new Exception('Cannot include autoload. Did you run install dependencies using composer?'); + } + + $context->registerCapability(Capabilities::class); + $context->registerMiddleWare(ExceptionMiddleware::class); + $context->registerMiddleWare(DefaultBoardMiddleware::class); + + $context->registerService('databaseType', static function (IContainer $c) { + return $c->get(IConfig::class)->getSystemValue('dbtype', 'sqlite'); + }); + $context->registerService('database4ByteSupport', static function (IContainer $c) { + return $c->get(IDBConnection::class)->supports4ByteText(); + }); + + $context->registerSearchProvider(DeckProvider::class); + + $this->registerUserGroupHooks(); + + $this->registerCommentsEntity(); + $this->registerFullTextSearch(); + $this->registerCollaborationResources(); + } + + private function registerUserGroupHooks(): void { + $container = $this->getContainer(); + // Delete user/group acl entries when they get deleted + /** @var IUserManager $userManager */ + $userManager = $this->server->getUserManager(); + $userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) { + // delete existing acl entries for deleted user + /** @var AclMapper $aclMapper */ + $aclMapper = $container->query(AclMapper::class); + $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID()); + foreach ($acls as $acl) { + $aclMapper->delete($acl); + } + // delete existing user assignments + $assignmentMapper = $container->query(AssignedUsersMapper::class); + $assignments = $assignmentMapper->findByUserId($user->getUID()); + foreach ($assignments as $assignment) { + $assignmentMapper->delete($assignment); + } + + /** @var BoardMapper $boardMapper */ + $boardMapper = $container->query(BoardMapper::class); + $boards = $boardMapper->findAllByOwner($user->getUID()); + foreach ($boards as $board) { + $boardMapper->delete($board); + } + }); + + /** @var IUserManager $userManager */ + $groupManager = $this->server->getGroupManager(); + $groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) { + /** @var AclMapper $aclMapper */ + $aclMapper = $container->query(AclMapper::class); + $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); + $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); + foreach ($acls as $acl) { + $aclMapper->delete($acl); + } + }); + } + + public function registerCommentsEntity(): void { + $this->server->getEventDispatcher()->addListener(CommentsEntityEvent::EVENT_ENTITY, function (CommentsEntityEvent $event) { + $event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) { + /** @var CardMapper */ + $cardMapper = $this->getContainer()->query(CardMapper::class); + $permissionService = $this->getContainer()->query(PermissionService::class); + + try { + return $permissionService->checkPermission($cardMapper, (int) $name, Acl::PERMISSION_READ); + } catch (\Exception $e) { + return false; + } + }); + }); + $this->registerCommentsEventHandler(); + } + + protected function registerCommentsEventHandler(): void { + $this->server->getCommentsManager()->registerEventHandler(function () { + return $this->getContainer()->query(CommentEventHandler::class); + }); + } + + protected function registerCollaborationResources(): void { + $version = OC_Util::getVersion()[0]; + /** + * Register Collaboration ResourceProvider + * + * @Todo: Remove if min-version is 18 + */ + if ($version < 18) { + /** @var IManager $resourceManager */ + $resourceManager = $this->getContainer()->query(IManager::class); + } else { + /** @var IProviderManager $resourceManager */ + $resourceManager = $this->getContainer()->query(IProviderManager::class); + } + $resourceManager->registerResourceProvider(ResourceProvider::class); + $resourceManager->registerResourceProvider(ResourceProviderCard::class); + + $this->server->getEventDispatcher()->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () { + Util::addScript('deck', 'collections'); + }); + } + + public function registerFullTextSearch(): void { + if (Util::getVersion()[0] < 16) { + return; + } + + $c = $this->getContainer(); + try { + $this->fullTextSearchService = $c->query(FullTextSearchService::class); + $this->fullTextSearchManager = $c->query(IFullTextSearchManager::class); + } catch (Exception $e) { + return; + } + + if (!$this->fullTextSearchManager->isAvailable()) { + return; + } + + /** @var IEventDispatcher $eventDispatcher */ + $eventDispatcher = $this->server->query(IEventDispatcher::class); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onCreate', function (Event $e) { + $this->fullTextSearchService->onCardCreated($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onUpdate', function (Event $e) { + $this->fullTextSearchService->onCardUpdated($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onDelete', function (Event $e) { + $this->fullTextSearchService->onCardDeleted($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareNew', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareEdit', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareDelete', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + } +} diff --git a/lib/AppInfo/ApplicationLegacy.php b/lib/AppInfo/ApplicationLegacy.php new file mode 100644 index 000000000..4a299c429 --- /dev/null +++ b/lib/AppInfo/ApplicationLegacy.php @@ -0,0 +1,264 @@ + + * + * @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 . + * + */ + +namespace OCA\Deck\AppInfo; + +use Exception; +use OC_Util; +use OCA\Deck\Activity\CommentEventHandler; +use OCA\Deck\Capabilities; +use OCA\Deck\Collaboration\Resources\ResourceProvider; +use OCA\Deck\Collaboration\Resources\ResourceProviderCard; +use OCA\Deck\Db\Acl; +use OCA\Deck\Db\AclMapper; +use OCA\Deck\Db\AssignedUsersMapper; +use OCA\Deck\Db\BoardMapper; +use OCA\Deck\Db\CardMapper; +use OCA\Deck\Middleware\DefaultBoardMiddleware; +use OCA\Deck\Middleware\ExceptionMiddleware; +use OCA\Deck\Notification\Notifier; +use OCA\Deck\Service\FullTextSearchService; +use OCA\Deck\Service\PermissionService; +use OCP\AppFramework\App; +use OCP\Collaboration\Resources\IManager; +use OCP\Collaboration\Resources\IProviderManager; +use OCP\Comments\CommentsEntityEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\FullTextSearch\IFullTextSearchManager; +use OCP\IGroup; +use OCP\IServerContainer; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IURLGenerator; +use OCP\Util; + +if ((@include_once __DIR__ . '/../../vendor/autoload.php') === false) { + throw new Exception('Cannot include autoload. Did you run install dependencies using composer?'); +} + +class ApplicationLegacy extends App { + public const APP_ID = 'deck'; + + public const COMMENT_ENTITY_TYPE = 'deckCard'; + + /** @var IServerContainer */ + private $server; + + /** @var FullTextSearchService */ + private $fullTextSearchService; + + /** @var IFullTextSearchManager */ + private $fullTextSearchManager; + + public function __construct(array $urlParams = []) { + parent::__construct('deck', $urlParams); + + $container = $this->getContainer(); + $server = $this->getContainer()->getServer(); + + $this->server = $server; + + $container->registerCapability(Capabilities::class); + $container->registerMiddleWare(ExceptionMiddleware::class); + $container->registerMiddleWare(DefaultBoardMiddleware::class); + + $container->registerService('databaseType', static function () use ($server) { + return $server->getConfig()->getSystemValue('dbtype', 'sqlite'); + }); + $container->registerService('database4ByteSupport', static function () use ($server) { + return $server->getDatabaseConnection()->supports4ByteText(); + }); + } + + public function register(): void { + $this->registerNavigationEntry(); + $this->registerUserGroupHooks(); + $this->registerNotifications(); + $this->registerCommentsEntity(); + $this->registerFullTextSearch(); + $this->registerCollaborationResources(); + } + + public function registerNavigationEntry(): void { + $container = $this->getContainer(); + $this->server->getNavigationManager()->add(static function () use ($container) { + $urlGenerator = $container->query(IURLGenerator::class); + return [ + 'id' => 'deck', + 'order' => 10, + 'href' => $urlGenerator->linkToRoute('deck.page.index'), + 'icon' => $urlGenerator->imagePath('deck', 'deck.svg'), + 'name' => 'Deck', + ]; + }); + } + + private function registerUserGroupHooks(): void { + $container = $this->getContainer(); + // Delete user/group acl entries when they get deleted + /** @var IUserManager $userManager */ + $userManager = $this->server->getUserManager(); + $userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) { + // delete existing acl entries for deleted user + /** @var AclMapper $aclMapper */ + $aclMapper = $container->query(AclMapper::class); + $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID()); + foreach ($acls as $acl) { + $aclMapper->delete($acl); + } + // delete existing user assignments + $assignmentMapper = $container->query(AssignedUsersMapper::class); + $assignments = $assignmentMapper->findByUserId($user->getUID()); + foreach ($assignments as $assignment) { + $assignmentMapper->delete($assignment); + } + + /** @var BoardMapper $boardMapper */ + $boardMapper = $container->query(BoardMapper::class); + $boards = $boardMapper->findAllByOwner($user->getUID()); + foreach ($boards as $board) { + $boardMapper->delete($board); + } + }); + + /** @var IUserManager $userManager */ + $groupManager = $this->server->getGroupManager(); + $groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) { + /** @var AclMapper $aclMapper */ + $aclMapper = $container->query(AclMapper::class); + $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); + $acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID()); + foreach ($acls as $acl) { + $aclMapper->delete($acl); + } + }); + } + + public function registerNotifications(): void { + $notificationManager = $this->server->getNotificationManager(); + $notificationManager->registerNotifierService(Notifier::class); + } + + public function registerCommentsEntity(): void { + $this->server->getEventDispatcher()->addListener(CommentsEntityEvent::EVENT_ENTITY, function (CommentsEntityEvent $event) { + $event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) { + /** @var CardMapper */ + $cardMapper = $this->getContainer()->query(CardMapper::class); + $permissionService = $this->getContainer()->query(PermissionService::class); + + try { + return $permissionService->checkPermission($cardMapper, (int) $name, Acl::PERMISSION_READ); + } catch (\Exception $e) { + return false; + } + }); + }); + $this->registerCommentsEventHandler(); + } + + /** + */ + protected function registerCommentsEventHandler(): void { + $this->server->getCommentsManager()->registerEventHandler(function () { + return $this->getContainer()->query(CommentEventHandler::class); + }); + } + + protected function registerCollaborationResources(): void { + $version = OC_Util::getVersion()[0]; + if ($version < 16) { + return; + } + + /** + * Register Collaboration ResourceProvider + * + * @Todo: Remove if min-version is 18 + */ + if ($version < 18) { + /** @var IManager $resourceManager */ + $resourceManager = $this->getContainer()->query(IManager::class); + } else { + /** @var IProviderManager $resourceManager */ + $resourceManager = $this->getContainer()->query(IProviderManager::class); + } + $resourceManager->registerResourceProvider(ResourceProvider::class); + $resourceManager->registerResourceProvider(ResourceProviderCard::class); + + $this->server->getEventDispatcher()->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () { + Util::addScript('deck', 'collections'); + }); + } + + public function registerFullTextSearch(): void { + if (Util::getVersion()[0] < 16) { + return; + } + + $c = $this->getContainer(); + try { + $this->fullTextSearchService = $c->query(FullTextSearchService::class); + $this->fullTextSearchManager = $c->query(IFullTextSearchManager::class); + } catch (Exception $e) { + return; + } + + if (!$this->fullTextSearchManager->isAvailable()) { + return; + } + + /** @var IEventDispatcher $eventDispatcher */ + $eventDispatcher = $this->server->query(IEventDispatcher::class); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onCreate', function (Event $e) { + $this->fullTextSearchService->onCardCreated($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onUpdate', function (Event $e) { + $this->fullTextSearchService->onCardUpdated($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Card::onDelete', function (Event $e) { + $this->fullTextSearchService->onCardDeleted($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareNew', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareEdit', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + $eventDispatcher->addListener( + '\OCA\Deck\Board::onShareDelete', function (Event $e) { + $this->fullTextSearchService->onBoardShares($e); + } + ); + } +} diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index 502dafe48..683a4fe30 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -26,7 +26,6 @@ use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\QBMapper; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\Diagnostics\IQuery; use OCP\IDBConnection; use OCP\IUserManager; use OCP\Notification\IManager; @@ -216,8 +215,8 @@ public function findOverdue() { $qb->select('id,title,duedate,notified') ->from('deck_cards') ->where($qb->expr()->lt('duedate', $qb->createFunction('NOW()'))) - ->andWhere($qb->expr()->eq('archived', false)) - ->andWhere($qb->expr()->eq('deleted_at', 0)); + ->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))) + ->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))); return $this->findEntities($qb); } diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 40d01929b..58b343929 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -41,7 +41,7 @@ public function __construct(IDBConnection $db, CardMapper $cardMapper) { * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException * @throws \OCP\AppFramework\Db\DoesNotExistException */ - public function find($id) { + public function find($id): Stack { $sql = 'SELECT * FROM `*PREFIX*deck_stacks` ' . 'WHERE `id` = ?'; return $this->findEntity($sql, [$id]); diff --git a/lib/Search/BoardSearchResultEntry.php b/lib/Search/BoardSearchResultEntry.php index 7d9ffb3f6..f66b7377d 100644 --- a/lib/Search/BoardSearchResultEntry.php +++ b/lib/Search/BoardSearchResultEntry.php @@ -26,12 +26,10 @@ namespace OCA\Deck\Search; - use OCA\Deck\Db\Board; use OCP\Search\SearchResultEntry; class BoardSearchResultEntry extends SearchResultEntry { - public function __construct(Board $board, $urlGenerator) { parent::__construct( '', diff --git a/lib/Search/CardSearchResultEntry.php b/lib/Search/CardSearchResultEntry.php index c3fbfede0..72b9c5f3a 100644 --- a/lib/Search/CardSearchResultEntry.php +++ b/lib/Search/CardSearchResultEntry.php @@ -26,14 +26,12 @@ namespace OCA\Deck\Search; - use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\Stack; use OCP\Search\SearchResultEntry; class CardSearchResultEntry extends SearchResultEntry { - public function __construct(Board $board, Stack $stack, Card $card, $urlGenerator) { parent::__construct('', $card->getTitle(), $board->getTitle() . ' » ' . $stack->getTitle() , $urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $board->getId() . '/card/' . $card->getId(), 'icon-deck'); } diff --git a/lib/Search/DeckProvider.php b/lib/Search/DeckProvider.php index 676b1e8c5..84015e90d 100644 --- a/lib/Search/DeckProvider.php +++ b/lib/Search/DeckProvider.php @@ -26,7 +26,6 @@ namespace OCA\Deck\Search; - use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\CardMapper; @@ -69,9 +68,6 @@ public function __construct( $this->urlGenerator = $urlGenerator; } - /** - * @inheritDoc - */ public function getId(): string { return 'deck'; } @@ -80,12 +76,14 @@ public function getName(): string { return 'Deck'; } - /** - * @inheritDoc - */ public function search(IUser $user, ISearchQuery $query): SearchResult { - $boards = $this->boardService->findAll(); - $cards = $this->cardMapper->search(array_map(function (Board $board) { + $boards = $this->boardService->getUserBoards(); + + $matchedBoards = array_filter($this->getUserBoards(-1), static function (Board $board) use ($query) { + return mb_stripos($board->getTitle(), $query->getTerm()) > -1; + }); + + $matchedCards = $this->cardMapper->search(array_map(static function (Board $board) { return $board->getId(); }, $boards), $query->getTerm(), $query->getLimit(), $query->getCursor()); @@ -93,14 +91,13 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { $results = array_merge( array_map(function (Board $board) { return new BoardSearchResultEntry($board, $this->urlGenerator); - }, array_filter($boards, function($board) use ($query) { - return mb_strpos($board->getTitle(), $query->getTerm()) !== -1; - })), + }, $matchedBoards), + array_map(function (Card $card) use ($self) { $board = $self->boardService->find($self->cardMapper->findBoardId($card->getId())); $stack = $self->stackMapper->find($card->getStackId()); return new CardSearchResultEntry($board, $stack, $card, $this->urlGenerator); - }, $cards) + }, $matchedCards) ); return SearchResult::complete( @@ -111,7 +108,6 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { public function getOrder(string $route, array $routeParameters): int { if ($route === 'deck.page.index') { - // Before comments return -5; } return 10; diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index c037540ac..420d706e6 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -107,6 +107,21 @@ public function setUserId(string $userId): void { $this->userId = $userId; } + public function getUserBoards(int $since = -1): array { + $userInfo = $this->getBoardPrerequisites(); + $userBoards = $this->boardMapper->findAllByUser($userInfo['user'], null, null, $since); + $groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups'],null, null, $since); + $circleBoards = $this->boardMapper->findAllByCircles($userInfo['user'], null, null, $since); + $mergedBoards = array_merge($userBoards, $groupBoards, $circleBoards); + $result = []; + /** @var Board $item */ + foreach ($mergedBoards as &$item) { + if (!array_key_exists($item->getId(), $result)) { + $result[$item->getId()] = $item; + } + } + return array_values($result); + } /** * @return array */ @@ -114,37 +129,30 @@ public function findAll($since = -1, $details = null) { if ($this->boardsCache) { return $this->boardsCache; } - $userInfo = $this->getBoardPrerequisites(); - $userBoards = $this->boardMapper->findAllByUser($userInfo['user'], null, null, $since); - $groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups'],null, null, $since); - $circleBoards = $this->boardMapper->findAllByCircles($userInfo['user'], null, null, $since); - $complete = array_merge($userBoards, $groupBoards, $circleBoards); - $result = []; + $complete = $this->getUserBoards($since); /** @var Board $item */ foreach ($complete as &$item) { - if (!array_key_exists($item->getId(), $result)) { - $this->boardMapper->mapOwner($item); - if ($item->getAcl() !== null) { - foreach ($item->getAcl() as &$acl) { - $this->boardMapper->mapAcl($acl); - } - } - if ($details !== null) { - $this->enrichWithStacks($item); - $this->enrichWithLabels($item); - $this->enrichWithUsers($item); + $this->boardMapper->mapOwner($item); + if ($item->getAcl() !== null) { + foreach ($item->getAcl() as &$acl) { + $this->boardMapper->mapAcl($acl); } - $permissions = $this->permissionService->matchPermissions($item); - $item->setPermissions([ - 'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ] ?? false, - 'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT] ?? false, - 'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE] ?? false, - 'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE] ?? false - ]); - $result[$item->getId()] = $item; } - } - $this->boardsCache = $result; + if ($details !== null) { + $this->enrichWithStacks($item); + $this->enrichWithLabels($item); + $this->enrichWithUsers($item); + } + $permissions = $this->permissionService->matchPermissions($item); + $item->setPermissions([ + 'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ] ?? false, + 'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT] ?? false, + 'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE] ?? false, + 'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE] ?? false + ]); + $result[$item->getId()] = $item; + } + $this->boardsCache = $complete; return array_values($result); }