Respect limit and order in webdav search

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
Roeland Jago Douma 2018-01-24 14:05:03 +01:00
parent 3063131e6d
commit ec144281ef
No known key found for this signature in database
GPG Key ID: F941078878347C0C
1 changed files with 98 additions and 3 deletions

View File

@ -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);
}
/**