summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2018-01-24 14:05:03 +0100
committerRoeland Jago Douma <roeland@famdouma.nl>2018-02-07 13:41:15 +0100
commitec144281efd2d5fec3d4af9fa50e0ecdfed97b26 (patch)
treeb4f0a906ff8ce948d14b3464ba4cd803e4951da9
parent3063131e6d3e222cb7a6aefd008d9127461119c1 (diff)
downloadnextcloud-server-ec144281efd2d5fec3d4af9fa50e0ecdfed97b26.tar.gz
nextcloud-server-ec144281efd2d5fec3d4af9fa50e0ecdfed97b26.zip
Respect limit and order in webdav search
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
-rw-r--r--apps/dav/lib/Files/FileSearchBackend.php101
1 files changed, 98 insertions, 3 deletions
diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php
index 9616d21b887..2aa2ccba214 100644
--- a/apps/dav/lib/Files/FileSearchBackend.php
+++ b/apps/dav/lib/Files/FileSearchBackend.php
@@ -157,7 +157,8 @@ class FileSearchBackend implements ISearchBackend {
/** @var Folder $folder $results */
$results = $folder->search($query);
- return array_map(function (Node $node) {
+ /** @var SearchResult[] $nodes */
+ $nodes = array_map(function (Node $node) {
if ($node instanceof Folder) {
$davNode = new \OCA\DAV\Connector\Sabre\Directory($this->view, $node, $this->tree, $this->shareManager);
} else {
@@ -167,6 +168,99 @@ class FileSearchBackend implements ISearchBackend {
$this->tree->cacheNode($davNode, $path);
return new SearchResult($davNode, $path);
}, $results);
+
+ // Sort again, since the result from multiple storages is appended and not sorted
+ usort($nodes, function(SearchResult $a, SearchResult $b) use ($search) {
+ return $this->sort($a, $b, $search->orderBy);
+ });
+
+ // If a limit is provided use only return that number of files
+ if ($search->limit->maxResults !== 0) {
+ $nodes = \array_slice($nodes, 0, $search->limit->maxResults);
+ }
+
+ return $nodes;
+ }
+
+ private function sort(SearchResult $a, SearchResult $b, array $orders) {
+ /** @var Order $oder */
+ foreach ($orders as $order) {
+ $v1 = $this->getSearchResultProperty($a, $order->property);
+ $v2 = $this->getSearchResultProperty($b, $order->property);
+
+
+ if ($v1 === null && $v2 === null) {
+ continue;
+ }
+ if ($v1 === null) {
+ return $order->order === Order::ASC ? 1 : -1;
+ }
+ if ($v2 === null) {
+ return $order->order === Order::ASC ? -1 : 1;
+ }
+
+ $s = $this->compareProperties($v1, $v2, $order);
+ if ($s === 0) {
+ continue;
+ }
+
+ if ($order->order === Order::DESC) {
+ $s = -$s;
+ }
+ return $s;
+ }
+
+ return 0;
+ }
+
+ private function compareProperties($a, $b, $order) {
+ $allProps = $this->getPropertyDefinitionsForScope('', '');
+
+ foreach ($allProps as $prop) {
+ if ($prop->name === $order->property) {
+ $dataType = $prop->dataType;
+ switch ($dataType) {
+ case SearchPropertyDefinition::DATATYPE_STRING:
+ return strcmp($a, $b);
+ case SearchPropertyDefinition::DATATYPE_BOOLEAN:
+ if ($a === $b) {
+ return 0;
+ }
+ if ($a === false) {
+ return -1;
+ }
+ return 1;
+ default:
+ if ($a === $b) {
+ return 0;
+ }
+ if ($a < $b) {
+ return -1;
+ }
+ if ($a > $b) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ private function getSearchResultProperty(SearchResult $result, $propertyName) {
+ /** @var \OCA\DAV\Connector\Sabre\Node $node */
+ $node = $result->node;
+
+ switch ($propertyName) {
+ case '{DAV:}displayname':
+ return $node->getName();
+ case '{DAV:}getlastmodified':
+ return $node->getLastModified();
+ case FilesPlugin::SIZE_PROPERTYNAME:
+ return $node->getSize();
+ case FilesPlugin::INTERNAL_FILEID_PROPERTYNAME:
+ return $node->getInternalFileId();
+ default:
+ return null;
+ }
}
/**
@@ -183,9 +277,10 @@ class FileSearchBackend implements ISearchBackend {
* @return ISearchQuery
*/
private function transformQuery(BasicSearch $query) {
- // TODO offset, limit
+ // TODO offset
+ $limit = $query->limit;
$orders = array_map([$this, 'mapSearchOrder'], $query->orderBy);
- return new SearchQuery($this->transformSearchOperation($query->where), 0, 0, $orders, $this->user);
+ return new SearchQuery($this->transformSearchOperation($query->where), $limit->maxResults, 0, $orders, $this->user);
}
/**