From cac1e7a3e9bc458f37361e530c3dba2feb9af04b Mon Sep 17 00:00:00 2001 From: Dan Feder Date: Tue, 1 Mar 2022 08:49:26 -0500 Subject: [PATCH] Multiple sorts in search (#3758) --- .../metastore_search/docs/openapi_spec.json | 4 +- .../src/QueryBuilderTrait.php | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/modules/metastore/modules/metastore_search/docs/openapi_spec.json b/modules/metastore/modules/metastore_search/docs/openapi_spec.json index aa3ac45374..6b17b9105c 100644 --- a/modules/metastore/modules/metastore_search/docs/openapi_spec.json +++ b/modules/metastore/modules/metastore_search/docs/openapi_spec.json @@ -72,7 +72,7 @@ { "name": "sort", "in": "query", - "description": "Which property to sort results on.", + "description": "Which property to sort results on. Use array format to sort on multiple properties, e.g. sort[0]=field1&sort[1]=field2", "schema": { "type": "string" }, @@ -81,7 +81,7 @@ { "name": "sort-order", "in": "query", - "description": "Sort results in ascending or descending order.", + "description": "Sort results in ascending or descending order. If sorting on multiple properties, use array format to map to sort values, e.g. sort-order[0]=asc&sort-order[1]=desc", "schema": { "type": "string", "default": "asc", diff --git a/modules/metastore/modules/metastore_search/src/QueryBuilderTrait.php b/modules/metastore/modules/metastore_search/src/QueryBuilderTrait.php index b342f36e1e..28f2a70e4e 100644 --- a/modules/metastore/modules/metastore_search/src/QueryBuilderTrait.php +++ b/modules/metastore/modules/metastore_search/src/QueryBuilderTrait.php @@ -158,12 +158,19 @@ private function setFieldConditions(QueryInterface $query, array $params, IndexI private function setSort(QueryInterface $query, array $params, IndexInterface $index): QueryInterface { $fields = array_keys($index->getFields()); - if (isset($params['sort']) && in_array($params['sort'], $fields)) { - $query->sort($params['sort'], $this->getSortOrder($params)); - return $query; + $sorts = $params['sort'] ?? []; + if (!is_array($sorts)) { + $sorts = [$sorts]; + } + if (empty($sorts)) { + $query->sort('search_api_relevance', Query::SORT_DESC); + } + foreach ($sorts as $index => $sort) { + if (in_array($sort, $fields)) { + $query->sort($sort, $this->getSortOrder($params, $index)); + } } - $query->sort('search_api_relevance', Query::SORT_DESC); return $query; } @@ -172,20 +179,30 @@ private function setSort(QueryInterface $query, array $params, IndexInterface $i * * @param array $params * Search parameters. + * @param int $index + * The array index to match the sort order to the sort field, in case + * of multiple sorts. * * @return mixed * String describing sort order as ascending or descending. */ - private function getSortOrder(array $params) { + private function getSortOrder(array $params, int $index = 0) { + $allowed = [ + strtolower(QueryInterface::SORT_ASC), + strtolower(QueryInterface::SORT_DESC), + ]; $default = QueryInterface::SORT_ASC; - if (!isset($params['sort-order'])) { - return $default; + + $orders = $params['sort-order'] ?? []; + if (!is_array($orders)) { + $orders = [$orders]; } - if ($params['sort-order'] != 'asc' && $params['sort-order'] != 'desc') { + + if (!isset($orders[$index]) || !in_array($orders[$index], $allowed)) { return $default; } - return ($params['sort-order'] == 'asc') ? QueryInterface::SORT_ASC : - QueryInterface::SORT_DESC; + + return strtoupper($orders[$index]); } /**