diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index d0f9c282f5..2c671b6f06 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -27,6 +27,7 @@ use OCA\Libresign\Middleware\GlobalInjectionMiddleware; use OCA\Libresign\Middleware\InjectionMiddleware; use OCA\Libresign\Notification\Notifier; +use OCA\Libresign\Search\FileSearchProvider; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; @@ -64,6 +65,8 @@ public function register(IRegistrationContext $context): void { $context->registerNotifierService(Notifier::class); + $context->registerSearchProvider(FileSearchProvider::class); + $context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class); $context->registerEventListener(BeforeNodeDeletedEvent::class, BeforeNodeDeletedListener::class); $context->registerEventListener(CacheEntryRemovedEvent::class, BeforeNodeDeletedListener::class); diff --git a/lib/Db/SignRequestMapper.php b/lib/Db/SignRequestMapper.php index 9380c2380c..0e4b598290 100644 --- a/lib/Db/SignRequestMapper.php +++ b/lib/Db/SignRequestMapper.php @@ -457,6 +457,41 @@ public function getFilesAssociatedFilesWithMe( ]; } + public function getFilesToSearchProvider(IUser $user, string $fileName, int $limit, int $offset): array { + $filter = [ + 'page' => ($offset / $limit) + 1, + 'length' => $limit, + 'fileName' => $fileName, + ]; + + $sort = [ + 'sortBy' => 'created_at', + 'sortDirection' => 'desc', + ]; + + $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($user->getUID(), $filter, false, $sort); + + + $qb->orderBy('f.created_at', 'DESC'); + + $result = $qb->executeQuery(); + $files = []; + + while ($row = $result->fetch()) { + try { + $file = File::fromRow($row); + + $files[] = $file; + } catch (\Exception $e) { + continue; + } + } + + $result->closeCursor(); + + return $files; + } + /** * @param array $signRequests * @return FileElement[][] @@ -530,7 +565,7 @@ public function getMyLibresignFile(string $userId, ?array $filter = []): File { return $file->fromRow($row); } - private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array $filter = [], bool $count = false): IQueryBuilder { + private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array $filter = [], bool $count = false, array $sort = []): IQueryBuilder { $qb = $this->db->getQueryBuilder(); $qb->from('libresign_file', 'f') ->leftJoin('f', 'libresign_sign_request', 'sr', 'sr.file_id = f.id') @@ -633,6 +668,11 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array $qb->expr()->lte('f.created_at', $qb->createNamedParameter($end, IQueryBuilder::PARAM_STR)) ); } + if (!empty($filter['fileName'])) { + $qb->andWhere( + $qb->expr()->like('f.name', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($filter['fileName']) . '%')) + ); + } if (!empty($filter['parentFileId'])) { $qb->andWhere( $qb->expr()->eq('f.parent_file_id', $qb->createNamedParameter($filter['parentFileId'], IQueryBuilder::PARAM_INT)) @@ -640,19 +680,9 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array } else { $qb->andWhere($qb->expr()->isNull('f.parent_file_id')); } - } else { - $qb->andWhere($qb->expr()->isNull('f.parent_file_id')); } - return $qb; - } - private function getFilesAssociatedFilesWithMeStmt( - string $userId, - ?array $filter = [], - ?array $sort = [], - ): Pagination { - $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($userId, $filter); - if (!empty($sort['sortBy'])) { + if (!empty($sort['sortBy']) && !empty($sort['sortDirection'])) { switch ($sort['sortBy']) { case 'name': case 'status': @@ -669,6 +699,16 @@ private function getFilesAssociatedFilesWithMeStmt( } } + return $qb; + } + + private function getFilesAssociatedFilesWithMeStmt( + string $userId, + ?array $filter = [], + ?array $sort = [], + ): Pagination { + $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($userId, $filter, false, $sort); + $countQb = $this->getFilesAssociatedFilesWithMeQueryBuilder( userId: $userId, filter: $filter, diff --git a/lib/Search/FileSearchProvider.php b/lib/Search/FileSearchProvider.php new file mode 100644 index 0000000000..3f010ad822 --- /dev/null +++ b/lib/Search/FileSearchProvider.php @@ -0,0 +1,139 @@ +l10n->t('LibreSign documents'); + } + + #[\Override] + public function getOrder(string $route, array $routeParameters): int { + if (strpos($route, Application::APP_ID . '.') === 0) { + return 0; + } + return 10; + } + + #[\Override] + public function search(IUser $user, ISearchQuery $query): SearchResult { + if (!$this->appManager->isEnabledForUser(Application::APP_ID, $user)) { + return SearchResult::complete($this->l10n->t('LibreSign documents'), []); + } + + $term = $query->getTerm(); + $limit = $query->getLimit(); + $offset = $query->getCursor(); + + try { + $files = $this->fileMapper->getFilesToSearchProvider($user, $term, $limit, (int)$offset); + } catch (\Exception $e) { + return SearchResult::complete($this->l10n->t('LibreSign documents'), []); + } + + $results = array_map(function (File $file) use ($user) { + return $this->formatResult($file, $user); + }, $files); + + return SearchResult::paginated( + $this->l10n->t('LibreSign documents'), + $results, + $offset + $limit + ); + } + + private function formatResult(File $file, IUser $user): SearchResultEntry { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $thumbnailUrl = ''; + $subline = ''; + $icon = ''; + $path = ''; + + try { + $nodes = $userFolder->getById($file->getNodeId()); + if (!empty($nodes)) { + $node = array_shift($nodes); + + $icon = $this->mimeTypeDetector->mimeTypeIcon($node->getMimetype()); + + $thumbnailUrl = $this->urlGenerator->linkToRouteAbsolute( + 'core.Preview.getPreviewByFileId', + [ + 'x' => 32, + 'y' => 32, + 'fileId' => $node->getId() + ] + ); + + $path = $userFolder->getRelativePath($node->getPath()); + $subline = $this->formatSubline($path); + } + } catch (\Exception $e) { + } + + $link = $this->urlGenerator->linkToRoute( + 'files.View.showFile', + ['fileid' => $file->getNodeId()] + ); + + $searchResultEntry = new SearchResultEntry( + $thumbnailUrl, + $file->getName() ?? $this->l10n->t('Unnamed document'), + $subline, + $this->urlGenerator->getAbsoluteURL($link), + $icon, + ); + + $searchResultEntry->addAttribute('fileId', (string)$file->getNodeId()); + $searchResultEntry->addAttribute('path', $path); + + return $searchResultEntry; + } + + private function formatSubline(string $path): string { + if (strrpos($path, '/') > 0) { + $path = ltrim(dirname($path), '/'); + return $this->l10n->t('in %s', [$path]); + } else { + return ''; + } + } + +}