Skip to content

Commit ab3bba2

Browse files
committed
refactor: remove SystemTag logic from Folder into QuerySearchHelper
- adds OC\SystemTag\SystemTagsInFilesDetector where the search logic is moved to Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
1 parent 97706da commit ab3bba2

6 files changed

Lines changed: 117 additions & 55 deletions

File tree

apps/dav/lib/SystemTag/SystemTagsInUseCollection.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
namespace OCA\DAV\SystemTag;
2828

2929
use OC\SystemTag\SystemTag;
30+
use OC\SystemTag\SystemTagsInFilesDetector;
3031
use OC\User\NoUserException;
3132
use OCP\Files\IRootFolder;
3233
use OCP\Files\NotPermittedException;
@@ -40,19 +41,22 @@ class SystemTagsInUseCollection extends SimpleCollection {
4041
protected IUserSession $userSession;
4142
protected IRootFolder $rootFolder;
4243
protected string $mediaType;
43-
private ISystemTagManager $systemTagManager;
44+
protected ISystemTagManager $systemTagManager;
45+
protected SystemTagsInFilesDetector $systemTagsInFilesDetector;
4446

4547
/** @noinspection PhpMissingParentConstructorInspection */
4648
public function __construct(
4749
IUserSession $userSession,
4850
IRootFolder $rootFolder,
4951
ISystemTagManager $systemTagManager,
52+
SystemTagsInFilesDetector $systemTagsInFilesDetector,
5053
string $mediaType = ''
5154
) {
5255
$this->userSession = $userSession;
5356
$this->rootFolder = $rootFolder;
5457
$this->systemTagManager = $systemTagManager;
5558
$this->mediaType = $mediaType;
59+
$this->systemTagsInFilesDetector = $systemTagsInFilesDetector;
5660
$this->name = 'systemtags-assigned';
5761
if ($this->mediaType != '') {
5862
$this->name .= '/' . $this->mediaType;
@@ -67,7 +71,7 @@ public function getChild($name): self {
6771
if ($this->mediaType !== '') {
6872
throw new NotFound('Invalid media type');
6973
}
70-
return new self($this->userSession, $this->rootFolder, $this->systemTagManager, $name);
74+
return new self($this->userSession, $this->rootFolder, $this->systemTagManager, $this->systemTagsInFilesDetector, $name);
7175
}
7276

7377
/**
@@ -89,7 +93,7 @@ public function getChildren(): array {
8993
throw new Forbidden('Permission denied to read this collection');
9094
}
9195

92-
$result = $userFolder->getSystemTags($this->mediaType);
96+
$result = $this->systemTagsInFilesDetector->detectAssignedSystemTagsIn($userFolder, $this->mediaType);
9397
$children = [];
9498
foreach ($result as $tagData) {
9599
$tag = new SystemTag((string)$tagData['id'], $tagData['name'], (bool)$tagData['visibility'], (bool)$tagData['editable']);

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,7 @@
16201620
'OC\\SystemTag\\SystemTag' => $baseDir . '/lib/private/SystemTag/SystemTag.php',
16211621
'OC\\SystemTag\\SystemTagManager' => $baseDir . '/lib/private/SystemTag/SystemTagManager.php',
16221622
'OC\\SystemTag\\SystemTagObjectMapper' => $baseDir . '/lib/private/SystemTag/SystemTagObjectMapper.php',
1623+
'OC\\SystemTag\\SystemTagsInFilesDetector' => $baseDir . '/lib/private/SystemTag/SystemTagsInFilesDetector.php',
16231624
'OC\\TagManager' => $baseDir . '/lib/private/TagManager.php',
16241625
'OC\\Tagging\\Tag' => $baseDir . '/lib/private/Tagging/Tag.php',
16251626
'OC\\Tagging\\TagMapper' => $baseDir . '/lib/private/Tagging/TagMapper.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
16531653
'OC\\SystemTag\\SystemTag' => __DIR__ . '/../../..' . '/lib/private/SystemTag/SystemTag.php',
16541654
'OC\\SystemTag\\SystemTagManager' => __DIR__ . '/../../..' . '/lib/private/SystemTag/SystemTagManager.php',
16551655
'OC\\SystemTag\\SystemTagObjectMapper' => __DIR__ . '/../../..' . '/lib/private/SystemTag/SystemTagObjectMapper.php',
1656+
'OC\\SystemTag\\SystemTagsInFilesDetector' => __DIR__ . '/../../..' . '/lib/private/SystemTag/SystemTagsInFilesDetector.php',
16561657
'OC\\TagManager' => __DIR__ . '/../../..' . '/lib/private/TagManager.php',
16571658
'OC\\Tagging\\Tag' => __DIR__ . '/../../..' . '/lib/private/Tagging/Tag.php',
16581659
'OC\\Tagging\\TagMapper' => __DIR__ . '/../../..' . '/lib/private/Tagging/TagMapper.php',

lib/private/Files/Cache/QuerySearchHelper.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@
2525
*/
2626
namespace OC\Files\Cache;
2727

28+
use OC\Files\Cache\Wrapper\CacheJail;
29+
use OC\Files\Node\Root;
2830
use OC\Files\Search\QueryOptimizer\QueryOptimizer;
2931
use OC\Files\Search\SearchBinaryOperator;
3032
use OC\SystemConfig;
3133
use OCP\DB\QueryBuilder\IQueryBuilder;
3234
use OCP\Files\Cache\ICache;
3335
use OCP\Files\Cache\ICacheEntry;
36+
use OCP\Files\Folder;
3437
use OCP\Files\IMimeTypeLoader;
38+
use OCP\Files\IRootFolder;
39+
use OCP\Files\Mount\IMountPoint;
3540
use OCP\Files\Search\ISearchBinaryOperator;
3641
use OCP\Files\Search\ISearchQuery;
3742
use OCP\IDBConnection;
@@ -190,4 +195,38 @@ public function searchInCaches(ISearchQuery $searchQuery, array $caches): array
190195
}
191196
return $results;
192197
}
198+
199+
/**
200+
* @return array{array<string, ICache>, array<string, IMountPoint>}
201+
*/
202+
public function getCachesAndMountPointsForSearch(Root $root, string $path, bool $limitToHome = false): array {
203+
$rootLength = strlen($path);
204+
$mount = $root->getMount($path);
205+
$storage = $mount->getStorage();
206+
$internalPath = $mount->getInternalPath($path);
207+
208+
if ($internalPath !== '') {
209+
// a temporary CacheJail is used to handle filtering down the results to within this folder
210+
$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
211+
} else {
212+
$caches = ['' => $storage->getCache('')];
213+
}
214+
$mountByMountPoint = ['' => $mount];
215+
216+
if (!$limitToHome) {
217+
/** @var IMountPoint[] $mounts */
218+
$mounts = $root->getMountsIn($path);
219+
foreach ($mounts as $mount) {
220+
$storage = $mount->getStorage();
221+
if ($storage) {
222+
$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
223+
$caches[$relativeMountPoint] = $storage->getCache('');
224+
$mountByMountPoint[$relativeMountPoint] = $mount;
225+
}
226+
}
227+
}
228+
229+
return [$caches, $mountByMountPoint];
230+
}
231+
193232
}

lib/private/Files/Node/Folder.php

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
use OC\Files\Cache\QuerySearchHelper;
3535
use OC\Files\Search\SearchBinaryOperator;
36-
use OC\Files\Cache\Wrapper\CacheJail;
3736
use OC\Files\Search\SearchComparison;
3837
use OC\Files\Search\SearchOrder;
3938
use OC\Files\Search\SearchQuery;
@@ -215,37 +214,6 @@ private function queryFromOperator(ISearchOperator $operator, string $uid = null
215214
return new SearchQuery($operator, $limit, $offset, [], $user);
216215
}
217216

218-
/**
219-
* @psalm-return list{0: array<string, \OCP\Files\Cache\ICache>, 1: array<string, \OCP\Files\Mount\IMountPoint>}
220-
*/
221-
protected function getCachesAndMountpointsForSearch(bool $limitToHome = false): array {
222-
$rootLength = strlen($this->path);
223-
$mount = $this->root->getMount($this->path);
224-
$storage = $mount->getStorage();
225-
$internalPath = $mount->getInternalPath($this->path);
226-
if ($internalPath !== '') {
227-
// a temporary CacheJail is used to handle filtering down the results to within this folder
228-
$caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
229-
} else {
230-
$caches = ['' => $storage->getCache('')];
231-
}
232-
$mountByMountPoint = ['' => $mount];
233-
234-
if (!$limitToHome) {
235-
$mounts = $this->root->getMountsIn($this->path);
236-
foreach ($mounts as $mount) {
237-
$storage = $mount->getStorage();
238-
if ($storage) {
239-
$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
240-
$caches[$relativeMountPoint] = $storage->getCache('');
241-
$mountByMountPoint[$relativeMountPoint] = $mount;
242-
}
243-
}
244-
}
245-
246-
return [$caches, $mountByMountPoint];
247-
}
248-
249217
/**
250218
* search for files with the name matching $query
251219
*
@@ -265,10 +233,9 @@ public function search($query) {
265233
throw new \InvalidArgumentException('searching by owner is only allowed in the users home folder');
266234
}
267235

268-
[$caches, $mountByMountPoint] = $this->getCachesAndMountpointsForSearch($limitToHome);
269-
270236
/** @var QuerySearchHelper $searchHelper */
271237
$searchHelper = \OC::$server->get(QuerySearchHelper::class);
238+
[$caches, $mountByMountPoint] = $searchHelper->getCachesAndMountPointsForSearch($this->root, $this->path, $limitToHome);
272239
$resultsPerCache = $searchHelper->searchInCaches($query, $caches);
273240

274241
// loop through all results per-cache, constructing the FileInfo object from the CacheEntry and merge them all
@@ -337,24 +304,6 @@ public function searchByTag($tag, $userId) {
337304
return $this->search($query);
338305
}
339306

340-
/**
341-
*
342-
* @return array<array-key, array{id: int, name: string, visibility: int, editable: int, ref_file_id: int, number_files: int}>
343-
*/
344-
public function getSystemTags(string $mediaType, int $limit = 0, int $offset = 0): array {
345-
// Currently query has to have exactly one search condition. If no media type is provided,
346-
// we fall back to the presence of a systemtag.
347-
if (empty($mediaType)) {
348-
$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'systemtag', '%'), null, $limit, $offset);
349-
} else {
350-
$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mediaType . '/%'), null, $limit, $offset);
351-
}
352-
[$caches, ] = $this->getCachesAndMountpointsForSearch();
353-
/** @var QuerySearchHelper $searchHelper */
354-
$searchHelper = \OCP\Server::get(QuerySearchHelper::class);
355-
return $searchHelper->findUsedTagsInCaches($query, $caches);
356-
}
357-
358307
/**
359308
* @param int $id
360309
* @return \OC\Files\Node\Node[]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright Copyright (c) 2023 Arthur Schiwon <blizzz@arthur-schiwon.de>
7+
*
8+
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
namespace OC\SystemTag;
28+
29+
use OC\Files\Cache\QuerySearchHelper;
30+
use OC\Files\Node\Root;
31+
use OC\Files\Search\SearchComparison;
32+
use OC\Files\Search\SearchQuery;
33+
use OCP\Files\Folder;
34+
use OCP\Files\Search\ISearchComparison;
35+
36+
class SystemTagsInFilesDetector {
37+
public function __construct(protected QuerySearchHelper $searchHelper) {
38+
}
39+
40+
public function detectAssignedSystemTagsIn(
41+
Folder $folder,
42+
string $filteredMediaType = '',
43+
int $limit = 0,
44+
int $offset = 0
45+
): array {
46+
// Currently query has to have exactly one search condition. If no media type is provided,
47+
// we fall back to the presence of a system tag.
48+
if (empty($filteredMediaType)) {
49+
$query = new SearchQuery(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'systemtag', '%'), $limit, $offset, []);
50+
} else {
51+
$query = new SearchQuery(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $filteredMediaType . '/%'), $limit, $offset, []);
52+
}
53+
[$caches, ] = $this->searchHelper->getCachesAndMountPointsForSearch(
54+
$this->getRootFolder($folder),
55+
$folder->getPath(),
56+
);
57+
return $this->searchHelper->findUsedTagsInCaches($query, $caches);
58+
}
59+
60+
protected function getRootFolder(?Folder $folder): Root {
61+
if ($folder instanceof Root) {
62+
return $folder;
63+
} elseif ($folder === null) {
64+
throw new \LogicException('Could not climb up to root folder');
65+
}
66+
return $this->getRootFolder($folder->getParent());
67+
}
68+
}

0 commit comments

Comments
 (0)