|
|
|
|
@ -29,25 +29,32 @@ declare(strict_types=1); |
|
|
|
|
*/ |
|
|
|
|
namespace OCA\Files\Search; |
|
|
|
|
|
|
|
|
|
use InvalidArgumentException; |
|
|
|
|
use OCP\Files\Search\ISearchOperator; |
|
|
|
|
use OCP\Search\FilterDefinition; |
|
|
|
|
use OCP\Search\IFilter; |
|
|
|
|
use OCP\Search\IFilteringProvider; |
|
|
|
|
use OCP\Share\IShare; |
|
|
|
|
use OC\Files\Search\SearchBinaryOperator; |
|
|
|
|
use OC\Files\Search\SearchComparison; |
|
|
|
|
use OC\Files\Search\SearchOrder; |
|
|
|
|
use OC\Files\Search\SearchQuery; |
|
|
|
|
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\ISearchQuery; |
|
|
|
|
use OCP\Search\SearchResult; |
|
|
|
|
use OCP\Search\SearchResultEntry; |
|
|
|
|
use OC\Search\Filter\GroupFilter; |
|
|
|
|
use OC\Search\Filter\UserFilter; |
|
|
|
|
|
|
|
|
|
class FilesSearchProvider implements IProvider { |
|
|
|
|
|
|
|
|
|
class FilesSearchProvider implements IFilteringProvider { |
|
|
|
|
/** @var IL10N */ |
|
|
|
|
private $l10n; |
|
|
|
|
|
|
|
|
|
@ -97,21 +104,38 @@ class FilesSearchProvider implements IProvider { |
|
|
|
|
return 5; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @inheritDoc |
|
|
|
|
*/ |
|
|
|
|
public function getSupportedFilters(): array { |
|
|
|
|
return [ |
|
|
|
|
'term', |
|
|
|
|
'since', |
|
|
|
|
'until', |
|
|
|
|
'person', |
|
|
|
|
'min-size', |
|
|
|
|
'max-size', |
|
|
|
|
'mime', |
|
|
|
|
'type', |
|
|
|
|
'is-favorite', |
|
|
|
|
'title-only', |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function getAlternateIds(): array { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function getCustomFilters(): array { |
|
|
|
|
return [ |
|
|
|
|
new FilterDefinition('min-size', FilterDefinition::TYPE_INT), |
|
|
|
|
new FilterDefinition('max-size', FilterDefinition::TYPE_INT), |
|
|
|
|
new FilterDefinition('mime', FilterDefinition::TYPE_STRING), |
|
|
|
|
new FilterDefinition('type', FilterDefinition::TYPE_STRING), |
|
|
|
|
new FilterDefinition('is-favorite', FilterDefinition::TYPE_BOOL), |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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 +165,53 @@ class FilesSearchProvider implements IProvider { |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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() . '/%'), |
|
|
|
|
'person' => $this->buildPersonSearchQuery($filter), |
|
|
|
|
default => throw new InvalidArgumentException('Unsupported comparison'), |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private function buildPersonSearchQuery(IFilter $person): ISearchOperator { |
|
|
|
|
if ($person instanceof UserFilter) { |
|
|
|
|
return new SearchBinaryOperator(SearchBinaryOperator::OPERATOR_OR, [ |
|
|
|
|
new SearchBinaryOperator(SearchBinaryOperator::OPERATOR_AND, [ |
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'share_with', $person->get()->getUID()), |
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'share_type', IShare::TYPE_USER), |
|
|
|
|
]), |
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'owner', $person->get()->getUID()), |
|
|
|
|
]); |
|
|
|
|
} |
|
|
|
|
if ($person instanceof GroupFilter) { |
|
|
|
|
return new SearchBinaryOperator(SearchBinaryOperator::OPERATOR_AND, [ |
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'share_with', $person->get()->getGID()), |
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'share_type', IShare::TYPE_GROUP), |
|
|
|
|
]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
throw new InvalidArgumentException('Unsupported filter type'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Format subline for files |
|
|
|
|
* |
|
|
|
|
|