diff --git a/.gitignore b/.gitignore
index 5e399d91532..e9beba66d19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ tests/php/coverage-html
tests/php/clover.xml
tests/integration/vendor
tests/integration/output
+
+\.idea/
diff --git a/appinfo/info.xml b/appinfo/info.xml
index cd9b0dd1e12..e63017954e9 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -99,4 +99,9 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
OCA\Spreed\Collaboration\Collaborators\RoomPlugin
+
+
+ OCA\Spreed\FullTextSearch\TalkProvider
+
+
diff --git a/css/fulltextsearch.css b/css/fulltextsearch.css
new file mode 100644
index 00000000000..ad2efd3e344
--- /dev/null
+++ b/css/fulltextsearch.css
@@ -0,0 +1,3 @@
+.icon-fts-talk {
+ background-image: url('/apps/spreed/img/app-dark.svg');
+}
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index d75233a14bf..882a1dc6bf8 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -30,6 +30,7 @@
use OCA\Spreed\Config;
use OCA\Spreed\Files\Listener as FilesListener;
use OCA\Spreed\Files\TemplateLoader as FilesTemplateLoader;
+use OCA\Spreed\FullTextSearch\FullTextSearchService;
use OCA\Spreed\Listener;
use OCA\Spreed\Notification\Listener as NotificationListener;
use OCA\Spreed\Notification\Notifier;
@@ -136,4 +137,17 @@ protected function extendDefaultContentSecurityPolicy(): void {
$cspManager = $this->getContainer()->getServer()->getContentSecurityPolicyManager();
$cspManager->addDefaultPolicy($csp);
}
+
+ /**
+ * @param EventDispatcherInterface $dispatcher
+ */
+ protected function registerFullTextSearch(EventDispatcherInterface $dispatcher) {
+ $dispatcher->addListener(
+ ChatManager::class . '::sendMessage', function(GenericEvent $e) {
+ $fullTextSearchService = $this->getContainer()
+ ->query(FullTextSearchService::class);
+ $fullTextSearchService->onSendMessage($e);
+ }
+ );
+ }
}
diff --git a/lib/FullTextSearch/FullTextSearchService.php b/lib/FullTextSearch/FullTextSearchService.php
new file mode 100644
index 00000000000..9e1851f7c11
--- /dev/null
+++ b/lib/FullTextSearch/FullTextSearchService.php
@@ -0,0 +1,208 @@
+
+ * @copyright 2018
+ * @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\Spreed\FullTextSearch;
+
+
+use OC\FullTextSearch\Model\DocumentAccess;
+use OC\FullTextSearch\Model\IndexDocument;
+use OCA\Spreed\Chat\ChatManager;
+use OCA\Spreed\Exceptions\RoomNotFoundException;
+use OCA\Spreed\Manager;
+use OCA\Spreed\Participant;
+use OCP\Comments\IComment;
+use OCP\FullTextSearch\IFullTextSearchManager;
+use OCP\FullTextSearch\Model\IDocumentAccess;
+use OCP\FullTextSearch\Model\IIndex;
+use OCP\FullTextSearch\Model\IIndexDocument;
+use OCP\FullTextSearch\Model\ISearchResult;
+use OCP\IURLGenerator;
+use Symfony\Component\EventDispatcher\GenericEvent;
+
+
+/**
+ * Class FullTextSearchService
+ *
+ * @package OCA\Spreed\FullTextSearch
+ */
+class FullTextSearchService {
+
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var Manager */
+ private $roomManager;
+
+ /** @var ChatManager */
+ private $chatManager;
+
+ /** @var IFullTextSearchManager */
+ private $fullTextSearchManager;
+
+
+ /**
+ * FullTextSearchService constructor.
+ *
+ * @param IURLGenerator $urlGenerator
+ * @param Manager $roomManager
+ * @param ChatManager $chatManager
+ * @param IFullTextSearchManager $fullTextSearchManager
+ */
+ public function __construct(
+ IUrlGenerator $urlGenerator, Manager $roomManager, ChatManager $chatManager,
+ IFullTextSearchManager $fullTextSearchManager
+ ) {
+ $this->urlGenerator = $urlGenerator;
+ $this->roomManager = $roomManager;
+ $this->chatManager = $chatManager;
+ $this->fullTextSearchManager = $fullTextSearchManager;
+ }
+
+
+ public function onSendMessage(GenericEvent $e) {
+ /** @var IComment $comment */
+ $comment = $e->getArgument('comment');
+ if ($comment->getObjectType() !== 'chat') {
+ return;
+ }
+
+ $this->fullTextSearchManager->createIndex(
+ TalkProvider::SPREED_PROVIDER_ID, $comment->getObjectId(), $comment->getActorId(),
+ IIndex::INDEX_FULL
+ );
+ }
+
+
+ /**
+ * @param IIndexDocument $document
+ */
+ public function generateDocument(IIndexDocument $document) {
+ $document->setAccess($this->generateDocumentAccessForRoom($document->getId()));
+
+ $this->fillContent($document);
+ }
+
+
+ /**
+ * @param IIndex $index
+ *
+ * @return IIndexDocument
+ */
+ public function updateDocument(IIndex $index): IIndexDocument {
+ $document = new IndexDocument(TalkProvider::SPREED_PROVIDER_ID, $index->getDocumentId());
+
+ $this->generateDocument($document);
+ $document->setIndex($index);
+
+ return $document;
+ }
+
+
+ /**
+ * @param ISearchResult $searchResult
+ */
+ public function improveSearchResult(ISearchResult $searchResult) {
+ foreach ($searchResult->getDocuments() as $document) {
+ try {
+ $board =
+ $this->roomManager->getRoomById((int)$document->getId());
+ $document->setLink(
+ $this->urlGenerator->linkToRoute(
+ 'spreed.pagecontroller.showCall', ['token' => $board->getToken()]
+ )
+ );
+ } catch (RoomNotFoundException $e) {
+ }
+ }
+ }
+
+
+ /**
+ * @param IIndexDocument $document
+ */
+ private function fillContent(IIndexDocument $document) {
+ $room = $this->roomManager->getRoomById((int)$document->getId());
+ $document->setTitle($room->getName());
+
+ $all = $this->chatManager->getHistory($room, 0, 100);
+
+ $comments = [];
+ foreach ($all as $comment) {
+ if ($comment->getVerb() !== 'comment') {
+ continue;
+ }
+
+ $dTime = $comment->getCreationDateTime();
+ $date = $dTime->format('ymd');
+ if (!array_key_exists($date, $comments)) {
+ $comments[$date] = [];
+ }
+
+ $comments[$date][] = '<' . $comment->getActorId() . '> ' . $comment->getMessage();
+ }
+
+ foreach (array_keys($comments) as $day) {
+ $document->addPart((string)$day, implode(" \n ", $comments[$day]));
+ }
+ }
+
+
+ /**
+ * @param string $roomId
+ *
+ * @return IDocumentAccess
+ */
+ private function generateDocumentAccessForRoom(string $roomId): IDocumentAccess {
+ $room = $this->roomManager->getRoomById((int)$roomId);
+
+ $ownerId = '';
+ $users = [];
+ $participants = $room->getParticipants();
+ foreach ($participants as $participant) {
+ switch ($participant->getParticipantType()) {
+ case Participant::OWNER:
+ $ownerId = $participant->getUser();
+ break;
+
+ case Participant::USER:
+ case Participant::MODERATOR:
+ case Participant::USER_SELF_JOINED:
+ $users[] = $participant->getUser();
+ break;
+ }
+ }
+
+ $access = new DocumentAccess($ownerId);
+ $access->addUsers($users);
+
+ return $access;
+ }
+
+}
+
diff --git a/lib/FullTextSearch/TalkProvider.php b/lib/FullTextSearch/TalkProvider.php
new file mode 100644
index 00000000000..471ddc6e6ff
--- /dev/null
+++ b/lib/FullTextSearch/TalkProvider.php
@@ -0,0 +1,271 @@
+
+ * @copyright 2019
+ * @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\Spreed\FullTextSearch;
+
+
+use OC\FullTextSearch\Model\IndexDocument;
+use OC\FullTextSearch\Model\SearchTemplate;
+use OCA\Spreed\Manager;
+use OCP\FullTextSearch\IFullTextSearchPlatform;
+use OCP\FullTextSearch\IFullTextSearchProvider;
+use OCP\FullTextSearch\Model\IIndex;
+use OCP\FullTextSearch\Model\IIndexDocument;
+use OCP\FullTextSearch\Model\IIndexOptions;
+use OCP\FullTextSearch\Model\IRunner;
+use OCP\FullTextSearch\Model\ISearchRequest;
+use OCP\FullTextSearch\Model\ISearchResult;
+use OCP\FullTextSearch\Model\ISearchTemplate;
+use OCP\IL10N;
+
+
+class TalkProvider implements IFullTextSearchProvider {
+
+
+ const SPREED_PROVIDER_ID = 'spreed';
+
+
+ /** @var IL10N */
+ private $l10n;
+
+ /** @var Manager */
+ private $roomManager;
+
+ /** @var FullTextSearchService */
+ private $fullTextSearchService;
+
+
+ /** @var IRunner */
+ private $runner;
+
+ /** @var IIndexOptions */
+ private $indexOptions = [];
+
+
+ public function __construct(
+ IL10N $l10n, Manager $roomManager, FullTextSearchService $fullTextSearchService
+ ) {
+ $this->l10n = $l10n;
+ $this->roomManager = $roomManager;
+ $this->fullTextSearchService = $fullTextSearchService;
+ }
+
+
+ /**
+ * return unique id of the provider
+ */
+ public function getId(): string {
+ return self::SPREED_PROVIDER_ID;
+ }
+
+
+ /**
+ * return name of the provider
+ */
+ public function getName(): string {
+ return 'Talk';
+ }
+
+
+ /**
+ * @return array
+ */
+ public function getConfiguration(): array {
+ return [];
+ }
+
+
+ /**
+ * @param IRunner $runner
+ */
+ public function setRunner(IRunner $runner) {
+ $this->runner = $runner;
+ }
+
+
+ /**
+ * @param IIndexOptions $options
+ */
+ public function setIndexOptions(IIndexOptions $options) {
+ $this->indexOptions = $options;
+ }
+
+
+ /**
+ * @return ISearchTemplate
+ */
+ public function getSearchTemplate(): ISearchTemplate {
+ $template = new SearchTemplate('icon-fts-talk', 'fulltextsearch');
+
+ return $template;
+ }
+
+
+ /**
+ *
+ */
+ public function loadProvider() {
+ }
+
+
+ /**
+ * @param string $userId
+ *
+ * @return string[]
+ */
+ public function generateChunks(string $userId): array {
+ return [];
+ }
+
+
+ /**
+ * @param string $userId
+ *
+ * @param string $chunk
+ *
+ * @return IIndexDocument[]
+ */
+ public function generateIndexableDocuments(string $userId, string $chunk): array {
+ $documents = [];
+ $rooms = $this->roomManager->getRoomsForParticipant($userId);
+ foreach ($rooms as $room) {
+ $document = new IndexDocument(self::SPREED_PROVIDER_ID, (string)$room->getId());
+ $document->setTitle($room->getName());
+
+ $documents[] = $document;
+ }
+
+ return $documents;
+ }
+
+
+ /**
+ * @param IIndexDocument $document
+ */
+ public function fillIndexDocument(IIndexDocument $document) {
+ $this->updateRunnerInfoArray(
+ [
+ 'info' => $document->getId(),
+ 'title' => $document->getTitle()
+ ]
+ );
+
+ $this->fullTextSearchService->generateDocument($document);
+ }
+
+
+ /**
+ * @param IIndexDocument $document
+ *
+ * @return bool
+ */
+ public function isDocumentUpToDate(IIndexDocument $document): bool {
+ return false;
+// return $this->filesService->isDocumentUpToDate($document);
+ }
+
+
+ /**
+ * @param IIndex $index
+ *
+ * @return IIndexDocument
+ */
+ public function updateDocument(IIndex $index): IIndexDocument {
+ $document = $this->fullTextSearchService->updateDocument($index);
+ $this->updateRunnerInfo('info', $document->getId());
+
+ return $document;
+ }
+
+
+ /**
+ * @param IFullTextSearchPlatform $platform
+ */
+ public function onInitializingIndex(IFullTextSearchPlatform $platform) {
+ }
+
+
+ /**
+ * @param IFullTextSearchPlatform $platform
+ */
+ public function onResettingIndex(IFullTextSearchPlatform $platform) {
+ }
+
+
+ /**
+ * not used yet
+ */
+ public function unloadProvider() {
+ }
+
+
+ /**
+ * before a search, improve the request
+ *
+ * @param ISearchRequest $request
+ */
+ public function improveSearchRequest(ISearchRequest $request) {
+ $request->addPart('*');
+ }
+
+
+ /**
+ * after a search, improve results
+ *
+ * @param ISearchResult $searchResult
+ */
+ public function improveSearchResult(ISearchResult $searchResult) {
+ $this->fullTextSearchService->improveSearchResult($searchResult);
+ }
+
+
+ /**
+ * @param string $info
+ * @param string $value
+ */
+ private function updateRunnerInfo(string $info, string $value) {
+ if ($this->runner === null) {
+ return;
+ }
+
+ $this->runner->setInfo($info, $value);
+ }
+
+ /**
+ * @param array $info
+ */
+ private function updateRunnerInfoArray(array $info) {
+ if ($this->runner === null) {
+ return;
+ }
+
+ $this->runner->setInfoArray($info);
+ }
+
+
+}