Skip to content

Commit 6278e68

Browse files
author
Mantas Urnieža
committed
Merge pull request #89 from asev/sorting_fields
Sort by multiple fields
2 parents 124ec0d + 143f726 commit 6278e68

File tree

5 files changed

+90
-16
lines changed

5 files changed

+90
-16
lines changed

DependencyInjection/Configuration.php

+26-8
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,22 @@ private function buildFilterTree($filterName)
181181
->arrayNode('choices')
182182
->prototype('array')
183183
->beforeNormalization()
184-
->ifTrue(
184+
->always(
185185
function ($v) {
186-
return empty($v['label']);
187-
}
188-
)
189-
->then(
190-
function ($v) {
191-
$v['label'] = $v['field'];
186+
if (empty($v['fields']) && !empty($v['field'])) {
187+
$field = ['field' => $v['field']];
188+
if (array_key_exists('order', $v)) {
189+
$field['order'] = $v['order'];
190+
}
191+
if (array_key_exists('mode', $v)) {
192+
$field['mode'] = $v['mode'];
193+
}
194+
$v['fields'][] = $field;
195+
}
196+
197+
if (empty($v['label'])) {
198+
$v['label'] = $v['fields'][0]['field'];
199+
}
192200

193201
return $v;
194202
}
@@ -197,11 +205,21 @@ function ($v) {
197205
->addDefaultsIfNotSet()
198206
->children()
199207
->scalarNode('label')->end()
200-
->scalarNode('field')->isRequired()->end()
208+
->scalarNode('field')->end()
201209
->scalarNode('order')->defaultValue('asc')->end()
202210
->scalarNode('mode')->defaultNull()->end()
203211
->scalarNode('key')->info('Custom parameter value')->end()
204212
->booleanNode('default')->defaultFalse()->end()
213+
->arrayNode('fields')
214+
->isRequired()
215+
->requiresAtLeastOneElement()
216+
->prototype('array')
217+
->children()
218+
->scalarNode('field')->isRequired()->end()
219+
->scalarNode('order')->defaultValue('asc')->end()
220+
->scalarNode('mode')->defaultNull()->end()
221+
->end()
222+
->end()
205223
->end()
206224
->end()
207225
->end()

Filters/Widget/Sort/Sort.php

+10-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,16 @@ class Sort extends AbstractSingleRequestValueFilter implements ViewDataFactoryIn
3737
public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
3838
{
3939
if ($state && $state->isActive()) {
40-
$search->addSort(
41-
new EsSort(
42-
$this->choices[$state->getValue()]['field'],
43-
$this->choices[$state->getValue()]['order'],
44-
null,
45-
$this->choices[$state->getValue()]['mode']
46-
)
47-
);
40+
$stateValue = $state->getValue();
41+
42+
if (!empty($this->choices[$stateValue]['fields'])) {
43+
foreach ($this->choices[$stateValue]['fields'] as $sortField) {
44+
$search->addSort(new EsSort($sortField['field'], $sortField['order'], null, $sortField['mode']));
45+
}
46+
} else {
47+
$sortField = $this->choices[$stateValue];
48+
$search->addSort(new EsSort($sortField['field'], $sortField['order'], null, $sortField['mode']));
49+
}
4850
} else {
4951
foreach ($this->choices as $choice) {
5052
if ($choice['default']) {

Resources/doc/filter/sort.rst

+17
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ After which you can specify multiple sort options/choices:
6363
+------------------------+--------------------------------------------------------------------+
6464
| `mode` | For any arrays: `min`, `max`, for numeric arrays `avg`, `sum`. |
6565
+------------------------+--------------------------------------------------------------------+
66+
| `fields` | Array of fields to sort on. For more information see table below. |
67+
+------------------------+--------------------------------------------------------------------+
68+
69+
.. note:: `field`, `order`, and `mode` are ignored if at least one of fields is defined.
70+
71+
Each object in `fields` array specifies sorting condition. Available parameters are defined below:
72+
73+
+------------------------+--------------------------------------------------------------------+
74+
| Setting name | Meaning |
75+
+========================+====================================================================+
76+
| `field` | Specifies the field in repository to sort on. (e.g. `item_color`) |
77+
+------------------------+--------------------------------------------------------------------+
78+
| `order` | Order to sort by. Default `asc`. Valid values: `asc`, `desc`. |
79+
+------------------------+--------------------------------------------------------------------+
80+
| `mode` | For any arrays: `min`, `max`, for numeric arrays `avg`, `sum`. |
81+
+------------------------+--------------------------------------------------------------------+
6682

6783
Example:
6884

@@ -83,6 +99,7 @@ Example:
8399
choices:
84100
- { label: Color ascending, field: item_color, default: true }
85101
- { label: Color descending, field: item_color, order: desc }
102+
- { label: 'In stock & cheap', fields: [{field: stock, order: desc}, {field: price}] }
86103
87104
..
88105

Tests/Unit/DependencyInjection/ConfigurationTest.php

+36
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,34 @@ public function getTestConfigurationData()
117117
$expectedConfig['filters']['sort']['sorting']['choices'][0]['default'] = false;
118118
$expectedConfig['filters']['sort']['sorting']['choices'][0]['order'] = 'asc';
119119
$expectedConfig['filters']['sort']['sorting']['choices'][0]['mode'] = null;
120+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['field'] = 'test';
121+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['order'] = 'asc';
122+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['mode'] = null;
123+
unset($customConfig['filters']['document_field']);
124+
unset($customConfig['filters']['multi_choice']);
125+
unset($customConfig['filters']['fuzzy']);
126+
$cases[] = [
127+
$customConfig,
128+
$expectedConfig,
129+
];
130+
131+
// Case #3 sorting by multiple fields.
132+
$customConfig = $expectedBaseConfig;
133+
$customConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['field'] = 'price';
134+
$customConfig['filters']['sort']['sorting']['choices'][0]['fields'][1]['field'] = 'date';
135+
$customConfig['filters']['sort']['sorting']['choices'][0]['fields'][1]['order'] = 'desc';
136+
$expectedConfig = $customConfig;
137+
$expectedConfig['filters']['choice'] = ['single_choice' => ['request_field' => 'choice', 'tags' => ['badged']]];
138+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['label'] = 'price';
139+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['default'] = false;
140+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['order'] = 'asc';
141+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['mode'] = null;
142+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['field'] = 'price';
143+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['order'] = 'asc';
144+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][0]['mode'] = null;
145+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][1]['field'] = 'date';
146+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][1]['order'] = 'desc';
147+
$expectedConfig['filters']['sort']['sorting']['choices'][0]['fields'][1]['mode'] = null;
120148
unset($customConfig['filters']['document_field']);
121149
unset($customConfig['filters']['multi_choice']);
122150
unset($customConfig['filters']['fuzzy']);
@@ -219,6 +247,14 @@ public function getTestConfigurationExceptionData()
219247
'. Permissible values: "_term", "_count"',
220248
];
221249

250+
// Case #8 Sorting fields are not set.
251+
$config = $this->getBaseConfiguration();
252+
$config['filters']['sort']['sorting']['choices'][0]['label'] = 'test';
253+
$cases[] = [
254+
$config,
255+
'The child node "fields" at path "ongr_filter_manager.filters.sort.sorting.choices.0" must be configured.',
256+
];
257+
222258
return $cases;
223259
}
224260

Tests/app/config/config_test.yml

+1
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,4 @@ ongr_filter_manager:
102102
request_field: 'sort'
103103
choices:
104104
- { label: foo, field: price, default: true, order: asc }
105+
- { label: bar, fields: [{field: price, order: asc}, {field: date, order: desc}]}

0 commit comments

Comments
 (0)