From 5ea9aaf96c054a4af874d433167b6c2c5d2410a4 Mon Sep 17 00:00:00 2001 From: Benjamin Gaussorgues Date: Mon, 25 Sep 2023 15:07:29 +0200 Subject: [PATCH] feat(files): Allow advanced search for files Signed-off-by: Benjamin Gaussorgues --- apps/files/lib/Search/FilesSearchProvider.php | 75 ++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/apps/files/lib/Search/FilesSearchProvider.php b/apps/files/lib/Search/FilesSearchProvider.php index ba2d4bafa3062..bbe0d9b6aa62b 100644 --- a/apps/files/lib/Search/FilesSearchProvider.php +++ b/apps/files/lib/Search/FilesSearchProvider.php @@ -29,25 +29,26 @@ */ namespace OCA\Files\Search; +use OC\Files\Search\SearchBinaryOperator; use OC\Files\Search\SearchComparison; use OC\Files\Search\SearchOrder; use OC\Files\Search\SearchQuery; +use OC\Search\Filter; use OCP\Files\FileInfo; use OCP\Files\IMimeTypeDetector; use OCP\Files\IRootFolder; -use OCP\Files\Search\ISearchComparison; use OCP\Files\Node; +use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOrder; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; -use OCP\Search\IProvider; +use OCP\Search\IProviderV2; use OCP\Search\ISearchQuery; use OCP\Search\SearchResult; use OCP\Search\SearchResultEntry; -class FilesSearchProvider implements IProvider { - +class FilesSearchProvider implements IProviderV2 { /** @var IL10N */ private $l10n; @@ -97,21 +98,36 @@ public function getOrder(string $route, array $routeParameters): int { return 5; } - /** - * @inheritDoc - */ + public function getSupportedFilters(): array { + return [ + 'term', + 'since', + 'until', + 'min-size', + 'max-size', + 'mime', + 'type', + 'is-favorite', + ]; + } + + public function getAlternateIds(): array { + return []; + } + + public function registerCustomFilters(): array { + return [ + 'min-size' => Filter\IntFilter::class, + 'max-size' => Filter\IntFilter::class, + 'mime' => Filter\StringFilter::class, + 'type' => Filter\StringFilter::class, + 'is-favorite' => Filter\BoolFilter::class, + ]; + } + public function search(IUser $user, ISearchQuery $query): SearchResult { $userFolder = $this->rootFolder->getUserFolder($user->getUID()); - $fileQuery = new SearchQuery( - new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query->getTerm() . '%'), - $query->getLimit(), - (int)$query->getCursor(), - $query->getSortOrder() === ISearchQuery::SORT_DATE_DESC ? [ - new SearchOrder(ISearchOrder::DIRECTION_DESCENDING, 'mtime'), - ] : [], - $user - ); - + $fileQuery = $this->buildSearchQuery($query, $user); return SearchResult::paginated( $this->l10n->t('Files'), array_map(function (Node $result) use ($userFolder) { @@ -141,6 +157,31 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { ); } + private function buildSearchQuery(ISearchQuery $query, IUser $user): SearchQuery { + $comparisons = []; + foreach ($query->getFilters() as $name => $filter) { + $comparisons[] = match ($name) { + 'term' => new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $filter->get() . '%'), + 'since' => new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN_EQUAL, 'mtime', $filter->get()->getTimestamp()), + 'until' => new SearchComparison(ISearchComparison::COMPARE_LESS_THAN_EQUAL, 'mtime', $filter->get()->getTimestamp()), + 'min-size' => new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN_EQUAL, 'size', $filter->get()), + 'max-size' => new SearchComparison(ISearchComparison::COMPARE_LESS_THAN_EQUAL, 'size', $filter->get()), + 'mime' => new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $filter->get()), + 'type' => new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $filter->get() . '/%'), + }; + } + + return new SearchQuery( + new SearchBinaryOperator(SearchBinaryOperator::OPERATOR_AND, $comparisons), + $query->getLimit(), + (int) $query->getCursor(), + $query->getSortOrder() === ISearchQuery::SORT_DATE_DESC + ? [new SearchOrder(ISearchOrder::DIRECTION_DESCENDING, 'mtime')] + : [], + $user + ); + } + /** * Format subline for files *