Skip to content

Commit 88a5e42

Browse files
authored
Merge pull request #2933 from nextcloud/enh/fts-events
2 parents be5c4a1 + 174d74c commit 88a5e42

20 files changed

+541
-731
lines changed

lib/AppInfo/Application.php

Lines changed: 185 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,191 @@
2323

2424
namespace OCA\Deck\AppInfo;
2525

26-
$version = \OCP\Util::getVersion()[0];
27-
if ($version >= 20) {
28-
class Application extends Application20 {
26+
use Closure;
27+
use Exception;
28+
use OC\EventDispatcher\SymfonyAdapter;
29+
use OCA\Deck\Activity\CommentEventHandler;
30+
use OCA\Deck\Capabilities;
31+
use OCA\Deck\Collaboration\Resources\ResourceProvider;
32+
use OCA\Deck\Collaboration\Resources\ResourceProviderCard;
33+
use OCA\Deck\Dashboard\DeckWidget;
34+
use OCA\Deck\Db\Acl;
35+
use OCA\Deck\Db\AclMapper;
36+
use OCA\Deck\Db\AssignmentMapper;
37+
use OCA\Deck\Db\BoardMapper;
38+
use OCA\Deck\Db\CardMapper;
39+
use OCA\Deck\Event\AclCreatedEvent;
40+
use OCA\Deck\Event\AclDeletedEvent;
41+
use OCA\Deck\Event\AclUpdatedEvent;
42+
use OCA\Deck\Event\CardCreatedEvent;
43+
use OCA\Deck\Event\CardDeletedEvent;
44+
use OCA\Deck\Event\CardUpdatedEvent;
45+
use OCA\Deck\Listeners\BeforeTemplateRenderedListener;
46+
use OCA\Deck\Listeners\FullTextSearchEventListener;
47+
use OCA\Deck\Middleware\DefaultBoardMiddleware;
48+
use OCA\Deck\Middleware\ExceptionMiddleware;
49+
use OCA\Deck\Notification\Notifier;
50+
use OCA\Deck\Search\DeckProvider;
51+
use OCA\Deck\Service\PermissionService;
52+
use OCA\Deck\Sharing\DeckShareProvider;
53+
use OCA\Deck\Sharing\Listener;
54+
use OCP\AppFramework\App;
55+
use OCP\AppFramework\Bootstrap\IBootContext;
56+
use OCP\AppFramework\Bootstrap\IBootstrap;
57+
use OCP\AppFramework\Bootstrap\IRegistrationContext;
58+
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
59+
use OCP\Collaboration\Resources\IProviderManager;
60+
use OCP\Comments\CommentsEntityEvent;
61+
use OCP\Comments\ICommentsManager;
62+
use OCP\EventDispatcher\Event;
63+
use OCP\EventDispatcher\IEventDispatcher;
64+
use OCP\IConfig;
65+
use OCP\IDBConnection;
66+
use OCP\IGroup;
67+
use OCP\IGroupManager;
68+
use OCP\IServerContainer;
69+
use OCP\IUser;
70+
use OCP\IUserManager;
71+
use OCP\Notification\IManager as NotificationManager;
72+
use OCP\Share\IManager;
73+
use OCP\Util;
74+
use Psr\Container\ContainerInterface;
75+
76+
class Application extends App implements IBootstrap {
77+
public const APP_ID = 'deck';
78+
79+
public const COMMENT_ENTITY_TYPE = 'deckCard';
80+
81+
/** @var IServerContainer */
82+
private $server;
83+
84+
public function __construct(array $urlParams = []) {
85+
parent::__construct(self::APP_ID, $urlParams);
86+
87+
$this->server = \OC::$server;
88+
}
89+
90+
public function boot(IBootContext $context): void {
91+
$context->injectFn(Closure::fromCallable([$this, 'registerUserGroupHooks']));
92+
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEntity']));
93+
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEventHandler']));
94+
$context->injectFn(Closure::fromCallable([$this, 'registerNotifications']));
95+
$context->injectFn(Closure::fromCallable([$this, 'registerCollaborationResources']));
96+
97+
$context->injectFn(function (IManager $shareManager) {
98+
if (method_exists($shareManager, 'registerShareProvider')) {
99+
$shareManager->registerShareProvider(DeckShareProvider::class);
100+
}
101+
});
102+
103+
$context->injectFn(function (Listener $listener, IEventDispatcher $eventDispatcher) {
104+
$listener->register($eventDispatcher);
105+
});
106+
}
107+
108+
public function register(IRegistrationContext $context): void {
109+
if ((@include_once __DIR__ . '/../../vendor/autoload.php') === false) {
110+
throw new Exception('Cannot include autoload. Did you run install dependencies using composer?');
111+
}
112+
113+
$context->registerCapability(Capabilities::class);
114+
$context->registerMiddleWare(ExceptionMiddleware::class);
115+
$context->registerMiddleWare(DefaultBoardMiddleware::class);
116+
117+
$context->registerService('databaseType', static function (ContainerInterface $c) {
118+
return $c->get(IConfig::class)->getSystemValue('dbtype', 'sqlite');
119+
});
120+
$context->registerService('database4ByteSupport', static function (ContainerInterface $c) {
121+
return $c->get(IDBConnection::class)->supports4ByteText();
122+
});
123+
124+
$context->registerSearchProvider(DeckProvider::class);
125+
$context->registerDashboardWidget(DeckWidget::class);
126+
127+
$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
128+
129+
// Event listening for full text search indexing
130+
$context->registerEventListener(CardCreatedEvent::class, FullTextSearchEventListener::class);
131+
$context->registerEventListener(CardUpdatedEvent::class, FullTextSearchEventListener::class);
132+
$context->registerEventListener(CardDeletedEvent::class, FullTextSearchEventListener::class);
133+
$context->registerEventListener(AclCreatedEvent::class, FullTextSearchEventListener::class);
134+
$context->registerEventListener(AclUpdatedEvent::class, FullTextSearchEventListener::class);
135+
$context->registerEventListener(AclDeletedEvent::class, FullTextSearchEventListener::class);
136+
}
137+
138+
public function registerNotifications(NotificationManager $notificationManager): void {
139+
$notificationManager->registerNotifierService(Notifier::class);
140+
}
141+
142+
private function registerUserGroupHooks(IUserManager $userManager, IGroupManager $groupManager): void {
143+
$container = $this->getContainer();
144+
// Delete user/group acl entries when they get deleted
145+
$userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) {
146+
// delete existing acl entries for deleted user
147+
/** @var AclMapper $aclMapper */
148+
$aclMapper = $container->query(AclMapper::class);
149+
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID());
150+
foreach ($acls as $acl) {
151+
$aclMapper->delete($acl);
152+
}
153+
// delete existing user assignments
154+
$assignmentMapper = $container->query(AssignmentMapper::class);
155+
$assignments = $assignmentMapper->findByParticipant($user->getUID());
156+
foreach ($assignments as $assignment) {
157+
$assignmentMapper->delete($assignment);
158+
}
159+
160+
/** @var BoardMapper $boardMapper */
161+
$boardMapper = $container->query(BoardMapper::class);
162+
$boards = $boardMapper->findAllByOwner($user->getUID());
163+
foreach ($boards as $board) {
164+
$boardMapper->delete($board);
165+
}
166+
});
167+
168+
$groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) {
169+
/** @var AclMapper $aclMapper */
170+
$aclMapper = $container->query(AclMapper::class);
171+
$aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
172+
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
173+
foreach ($acls as $acl) {
174+
$aclMapper->delete($acl);
175+
}
176+
});
29177
}
30-
} else {
31-
class Application extends ApplicationLegacy {
178+
179+
public function registerCommentsEntity(IEventDispatcher $eventDispatcher): void {
180+
$eventDispatcher->addListener(CommentsEntityEvent::EVENT_ENTITY, function (CommentsEntityEvent $event) {
181+
$event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) {
182+
/** @var CardMapper */
183+
$cardMapper = $this->getContainer()->get(CardMapper::class);
184+
$permissionService = $this->getContainer()->get(PermissionService::class);
185+
186+
try {
187+
return $permissionService->checkPermission($cardMapper, (int) $name, Acl::PERMISSION_READ);
188+
} catch (\Exception $e) {
189+
return false;
190+
}
191+
});
192+
});
193+
}
194+
195+
protected function registerCommentsEventHandler(ICommentsManager $commentsManager): void {
196+
$commentsManager->registerEventHandler(function () {
197+
return $this->getContainer()->query(CommentEventHandler::class);
198+
});
199+
}
200+
201+
protected function registerCollaborationResources(IProviderManager $resourceManager, SymfonyAdapter $symfonyAdapter): void {
202+
$resourceManager->registerResourceProvider(ResourceProvider::class);
203+
$resourceManager->registerResourceProvider(ResourceProviderCard::class);
204+
205+
$symfonyAdapter->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () {
206+
if (strpos(\OC::$server->getRequest()->getPathInfo(), '/call/') === 0) {
207+
// Talk integration has its own entrypoint which already includes collections handling
208+
return;
209+
}
210+
Util::addScript('deck', 'collections');
211+
});
32212
}
33213
}

0 commit comments

Comments
 (0)