Skip to content

Commit 99e2e5f

Browse files
authored
Merge pull request #26258 from nextcloud/backport/26198/stable20
[stable20] Handle limit offset and sorting in files search
2 parents f1cde6b + 4b65a1d commit 99e2e5f

File tree

11 files changed

+455
-228
lines changed

11 files changed

+455
-228
lines changed

apps/files/lib/Search/FilesSearchProvider.php

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@
2828

2929
namespace OCA\Files\Search;
3030

31-
use OC\Search\Provider\File;
32-
use OC\Search\Result\File as FileResult;
31+
use OC\Files\Search\SearchComparison;
32+
use OC\Files\Search\SearchOrder;
33+
use OC\Files\Search\SearchQuery;
34+
use OCP\Files\FileInfo;
3335
use OCP\Files\IMimeTypeDetector;
3436
use OCP\Files\IRootFolder;
37+
use OCP\Files\Search\ISearchComparison;
38+
use OCP\Files\Node;
39+
use OCP\Files\Search\ISearchOrder;
3540
use OCP\IL10N;
3641
use OCP\IURLGenerator;
3742
use OCP\IUser;
@@ -42,9 +47,6 @@
4247

4348
class FilesSearchProvider implements IProvider {
4449

45-
/** @var File */
46-
private $fileSearch;
47-
4850
/** @var IL10N */
4951
private $l10n;
5052

@@ -57,13 +59,13 @@ class FilesSearchProvider implements IProvider {
5759
/** @var IRootFolder */
5860
private $rootFolder;
5961

60-
public function __construct(File $fileSearch,
61-
IL10N $l10n,
62-
IURLGenerator $urlGenerator,
63-
IMimeTypeDetector $mimeTypeDetector,
64-
IRootFolder $rootFolder) {
62+
public function __construct(
63+
IL10N $l10n,
64+
IURLGenerator $urlGenerator,
65+
IMimeTypeDetector $mimeTypeDetector,
66+
IRootFolder $rootFolder
67+
) {
6568
$this->l10n = $l10n;
66-
$this->fileSearch = $fileSearch;
6769
$this->urlGenerator = $urlGenerator;
6870
$this->mimeTypeDetector = $mimeTypeDetector;
6971
$this->rootFolder = $rootFolder;
@@ -98,43 +100,56 @@ public function getOrder(string $route, array $routeParameters): int {
98100
* @inheritDoc
99101
*/
100102
public function search(IUser $user, ISearchQuery $query): SearchResult {
101-
102-
// Make sure we setup the users filesystem
103-
$this->rootFolder->getUserFolder($user->getUID());
103+
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
104+
$fileQuery = new SearchQuery(
105+
new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query->getTerm() . '%'),
106+
$query->getLimit(),
107+
(int)$query->getCursor(),
108+
$query->getSortOrder() === ISearchQuery::SORT_DATE_DESC ? [
109+
new SearchOrder(ISearchOrder::DIRECTION_DESCENDING, 'mtime'),
110+
] : [],
111+
$user
112+
);
104113

105114
return SearchResult::paginated(
106115
$this->l10n->t('Files'),
107-
array_map(function (FileResult $result) {
116+
array_map(function (Node $result) use ($userFolder) {
108117
// Generate thumbnail url
109-
$thumbnailUrl = $result->has_preview
110-
? $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 32, 'y' => 32, 'fileId' => $result->id])
111-
: '';
118+
$thumbnailUrl = $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 32, 'y' => 32, 'fileId' => $result->getId()]);
119+
$path = $userFolder->getRelativePath($result->getPath());
120+
$link = $this->urlGenerator->linkToRoute(
121+
'files.view.index',
122+
[
123+
'dir' => dirname($path),
124+
'scrollto' => $result->getName(),
125+
]
126+
);
112127

113128
return new SearchResultEntry(
114129
$thumbnailUrl,
115-
$result->name,
116-
$this->formatSubline($result),
117-
$this->urlGenerator->getAbsoluteURL($result->link),
118-
$result->type === 'folder' ? 'icon-folder' : $this->mimeTypeDetector->mimeTypeIcon($result->mime_type)
130+
$result->getName(),
131+
$this->formatSubline($path),
132+
$this->urlGenerator->getAbsoluteURL($link),
133+
$result->getMimetype() === FileInfo::MIMETYPE_FOLDER ? 'icon-folder' : $this->mimeTypeDetector->mimeTypeIcon($result->getMimetype())
119134
);
120-
}, $this->fileSearch->search($query->getTerm(), $query->getLimit(), (int)$query->getCursor())),
135+
}, $userFolder->search($fileQuery)),
121136
$query->getCursor() + $query->getLimit()
122137
);
123138
}
124139

125140
/**
126141
* Format subline for files
127142
*
128-
* @param FileResult $result
143+
* @param string $path
129144
* @return string
130145
*/
131-
private function formatSubline($result): string {
146+
private function formatSubline(string $path): string {
132147
// Do not show the location if the file is in root
133-
if ($result->path === '/' . $result->name) {
148+
if (strrpos($path, '/') > 0) {
149+
$path = ltrim(dirname($path), '/');
150+
return $this->l10n->t('in %s', [$path]);
151+
} else {
134152
return '';
135153
}
136-
137-
$path = ltrim(dirname($result->path), '/');
138-
return $this->l10n->t('in %s', [$path]);
139154
}
140155
}

core/Controller/SearchController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public function __construct(
5555

5656
/**
5757
* @NoAdminRequired
58+
* @NoCSRFRequired
5859
*/
5960
public function search(string $query, array $inApps = [], int $page = 1, int $size = 30): JSONResponse {
6061
$results = $this->searcher->searchPaged($query, $inApps, $page, $size);

lib/private/Files/Cache/Cache.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@ public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader
190190
}
191191
$data['permissions'] = (int)$data['permissions'];
192192
if (isset($data['creation_time'])) {
193-
$data['creation_time'] = (int) $data['creation_time'];
193+
$data['creation_time'] = (int)$data['creation_time'];
194194
}
195195
if (isset($data['upload_time'])) {
196-
$data['upload_time'] = (int) $data['upload_time'];
196+
$data['upload_time'] = (int)$data['upload_time'];
197197
}
198198
return new CacheEntry($data);
199199
}
@@ -811,6 +811,10 @@ public function searchByMime($mimetype) {
811811
}, $files);
812812
}
813813

814+
/**
815+
* @param ISearchQuery $searchQuery
816+
* @return CacheEntry[]
817+
*/
814818
public function searchQuery(ISearchQuery $searchQuery) {
815819
$builder = $this->getQueryBuilder();
816820

@@ -819,14 +823,18 @@ public function searchQuery(ISearchQuery $searchQuery) {
819823
$query->whereStorageId();
820824

821825
if ($this->querySearchHelper->shouldJoinTags($searchQuery->getSearchOperation())) {
826+
$user = $searchQuery->getUser();
827+
if ($user === null) {
828+
throw new \InvalidArgumentException("Searching by tag requires the user to be set in the query");
829+
}
822830
$query
823831
->innerJoin('file', 'vcategory_to_object', 'tagmap', $builder->expr()->eq('file.fileid', 'tagmap.objid'))
824832
->innerJoin('tagmap', 'vcategory', 'tag', $builder->expr()->andX(
825833
$builder->expr()->eq('tagmap.type', 'tag.type'),
826834
$builder->expr()->eq('tagmap.categoryid', 'tag.id')
827835
))
828836
->andWhere($builder->expr()->eq('tag.type', $builder->createNamedParameter('files')))
829-
->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($searchQuery->getUser()->getUID())));
837+
->andWhere($builder->expr()->eq('tag.uid', $builder->createNamedParameter($user->getUID())));
830838
}
831839

832840
$searchExpr = $this->querySearchHelper->searchOperatorToDBExpr($builder, $searchQuery->getSearchOperation());
@@ -1007,7 +1015,7 @@ public function getPathById($id) {
10071015
return null;
10081016
}
10091017

1010-
return (string) $path;
1018+
return (string)$path;
10111019
}
10121020

10131021
/**

0 commit comments

Comments
 (0)