|
@@ -25,13 +25,17 @@
|
|
|
*/
|
|
|
namespace OC\Files\Cache;
|
|
|
|
|
|
+use OC\Files\Cache\Wrapper\CacheJail;
|
|
|
+use OC\Files\Node\Root;
|
|
|
use OC\Files\Search\QueryOptimizer\QueryOptimizer;
|
|
|
use OC\Files\Search\SearchBinaryOperator;
|
|
|
use OC\SystemConfig;
|
|
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
|
|
use OCP\Files\Cache\ICache;
|
|
|
use OCP\Files\Cache\ICacheEntry;
|
|
|
+use OCP\Files\Folder;
|
|
|
use OCP\Files\IMimeTypeLoader;
|
|
|
+use OCP\Files\Mount\IMountPoint;
|
|
|
use OCP\Files\Search\ISearchBinaryOperator;
|
|
|
use OCP\Files\Search\ISearchQuery;
|
|
|
use OCP\IDBConnection;
|
|
@@ -74,6 +78,45 @@ class QuerySearchHelper {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ protected function applySearchConstraints(CacheQueryBuilder $query, ISearchQuery $searchQuery, array $caches): void {
|
|
|
+ $storageFilters = array_values(array_map(function (ICache $cache) {
|
|
|
+ return $cache->getQueryFilterForStorage();
|
|
|
+ }, $caches));
|
|
|
+ $storageFilter = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters);
|
|
|
+ $filter = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [$searchQuery->getSearchOperation(), $storageFilter]);
|
|
|
+ $this->queryOptimizer->processOperator($filter);
|
|
|
+
|
|
|
+ $searchExpr = $this->searchBuilder->searchOperatorToDBExpr($query, $filter);
|
|
|
+ if ($searchExpr) {
|
|
|
+ $query->andWhere($searchExpr);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder());
|
|
|
+
|
|
|
+ if ($searchQuery->getLimit()) {
|
|
|
+ $query->setMaxResults($searchQuery->getLimit());
|
|
|
+ }
|
|
|
+ if ($searchQuery->getOffset()) {
|
|
|
+ $query->setFirstResult($searchQuery->getOffset());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return array<array-key, array{id: int, name: string, visibility: int, editable: int, ref_file_id: int, number_files: int}>
|
|
|
+ */
|
|
|
+ public function findUsedTagsInCaches(ISearchQuery $searchQuery, array $caches): array {
|
|
|
+ $query = $this->getQueryBuilder();
|
|
|
+ $query->selectTagUsage();
|
|
|
+
|
|
|
+ $this->applySearchConstraints($query, $searchQuery, $caches);
|
|
|
+
|
|
|
+ $result = $query->execute();
|
|
|
+ $tags = $result->fetchAll();
|
|
|
+ $result->closeCursor();
|
|
|
+ return $tags;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Perform a file system search in multiple caches
|
|
|
*
|
|
@@ -127,26 +170,7 @@ class QuerySearchHelper {
|
|
|
));
|
|
|
}
|
|
|
|
|
|
- $storageFilters = array_values(array_map(function (ICache $cache) {
|
|
|
- return $cache->getQueryFilterForStorage();
|
|
|
- }, $caches));
|
|
|
- $storageFilter = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $storageFilters);
|
|
|
- $filter = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [$searchQuery->getSearchOperation(), $storageFilter]);
|
|
|
- $this->queryOptimizer->processOperator($filter);
|
|
|
-
|
|
|
- $searchExpr = $this->searchBuilder->searchOperatorToDBExpr($builder, $filter);
|
|
|
- if ($searchExpr) {
|
|
|
- $query->andWhere($searchExpr);
|
|
|
- }
|
|
|
-
|
|
|
- $this->searchBuilder->addSearchOrdersToQuery($query, $searchQuery->getOrder());
|
|
|
-
|
|
|
- if ($searchQuery->getLimit()) {
|
|
|
- $query->setMaxResults($searchQuery->getLimit());
|
|
|
- }
|
|
|
- if ($searchQuery->getOffset()) {
|
|
|
- $query->setFirstResult($searchQuery->getOffset());
|
|
|
- }
|
|
|
+ $this->applySearchConstraints($query, $searchQuery, $caches);
|
|
|
|
|
|
$result = $query->execute();
|
|
|
$files = $result->fetchAll();
|
|
@@ -158,7 +182,7 @@ class QuerySearchHelper {
|
|
|
$result->closeCursor();
|
|
|
|
|
|
// loop through all caches for each result to see if the result matches that storage
|
|
|
- // results are grouped by the same array keys as the caches argument to allow the caller to distringuish the source of the results
|
|
|
+ // results are grouped by the same array keys as the caches argument to allow the caller to distinguish the source of the results
|
|
|
$results = array_fill_keys(array_keys($caches), []);
|
|
|
foreach ($rawEntries as $rawEntry) {
|
|
|
foreach ($caches as $cacheKey => $cache) {
|
|
@@ -170,4 +194,37 @@ class QuerySearchHelper {
|
|
|
}
|
|
|
return $results;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return array{array<string, ICache>, array<string, IMountPoint>}
|
|
|
+ */
|
|
|
+ public function getCachesAndMountPointsForSearch(Root $root, string $path, bool $limitToHome = false): array {
|
|
|
+ $rootLength = strlen($path);
|
|
|
+ $mount = $root->getMount($path);
|
|
|
+ $storage = $mount->getStorage();
|
|
|
+ $internalPath = $mount->getInternalPath($path);
|
|
|
+
|
|
|
+ if ($internalPath !== '') {
|
|
|
+ // a temporary CacheJail is used to handle filtering down the results to within this folder
|
|
|
+ $caches = ['' => new CacheJail($storage->getCache(''), $internalPath)];
|
|
|
+ } else {
|
|
|
+ $caches = ['' => $storage->getCache('')];
|
|
|
+ }
|
|
|
+ $mountByMountPoint = ['' => $mount];
|
|
|
+
|
|
|
+ if (!$limitToHome) {
|
|
|
+ /** @var IMountPoint[] $mounts */
|
|
|
+ $mounts = $root->getMountsIn($path);
|
|
|
+ foreach ($mounts as $mount) {
|
|
|
+ $storage = $mount->getStorage();
|
|
|
+ if ($storage) {
|
|
|
+ $relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
|
|
|
+ $caches[$relativeMountPoint] = $storage->getCache('');
|
|
|
+ $mountByMountPoint[$relativeMountPoint] = $mount;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return [$caches, $mountByMountPoint];
|
|
|
+ }
|
|
|
}
|