diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2018-01-24 14:05:03 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2018-02-07 13:41:15 +0100 |
commit | ec144281efd2d5fec3d4af9fa50e0ecdfed97b26 (patch) | |
tree | b4f0a906ff8ce948d14b3464ba4cd803e4951da9 | |
parent | 3063131e6d3e222cb7a6aefd008d9127461119c1 (diff) | |
download | nextcloud-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.php | 101 |
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); } /** |