Skip to content

Commit e6cc24e

Browse files
authored
Merge pull request #33 from ans-group/multiple-sorts
Allow multiple sorts to work when sort order doesn't match config order
2 parents fe2e4e7 + 706fb91 commit e6cc24e

File tree

3 files changed

+91
-37
lines changed

3 files changed

+91
-37
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ of the column this may not be the desired functionality. You can change this usi
103103
* `sort=priority:desc_nulls_first`
104104

105105

106-
You can set a default sort using the `setDefaultSort` on the`Sieve` class.
106+
You can set a default sort using the `setDefaultSort` on the`Sieve` class. The default sort uses the database column
107+
name rather than the mapped property name, meaning you can use the default sort property without having a map set up.
107108

108109
```php
109110
$sieve->setDefaultSort('name', 'asc')

src/Sieve.php

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ class Sieve
1212

1313
protected $defaultSort = null;
1414

15-
protected $sortable = [];
16-
1715
public function __construct(Request $request)
1816
{
1917
$this->request = $request;
@@ -57,8 +55,41 @@ public function apply($queryBuilder)
5755
$search = new SearchTerm($property, $operator, $property, $term);
5856
$filter->modifyQuery($queryBuilder, $search);
5957
}
58+
}
59+
60+
if ($this->request->has('sort')) {
61+
$this->applyRequestSorts($queryBuilder);
62+
} elseif ($this->defaultSort) {
63+
$this->applyDefaultSort($queryBuilder);
64+
}
65+
66+
return $this;
67+
}
68+
69+
public function getSort(): ?string
70+
{
71+
return $this->request->get("sort") ?? $this->defaultSort;
72+
}
73+
74+
public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
75+
{
76+
$this->defaultSort = $property . ':' . $direction;
77+
78+
return $this;
79+
}
80+
81+
protected function applyRequestSorts($queryBuilder): void {
82+
$sorts = explode(',', $this->getSort());
83+
foreach ($sorts as $sort) {
84+
$property = explode(':', $sort)[0];
85+
86+
$filterRule = collect($this->getFilters())->firstWhere('property', $property);
87+
if (!$filterRule) {
88+
continue;
89+
}
6090

6191
$column = $property;
92+
$filter = $filterRule['filter'];
6293
while ($filter instanceof WrapsFilter) {
6394
if ($filter instanceof MapFilter) {
6495
$column = $filter->target();
@@ -68,47 +99,33 @@ public function apply($queryBuilder)
6899
$filter = $filter->getWrapped();
69100
}
70101

71-
if (strpos($column, ".") !== false) {
102+
if (str_contains($column, ".")) {
72103
continue;
73104
}
74105

75-
$sorts = explode(',', $this->getSort());
76-
foreach ($sorts as $sort) {
77-
if ($sort == "$property:desc") {
78-
$queryBuilder->orderBy($column, "desc");
79-
}
106+
if ($sort == "$property:desc") {
107+
$queryBuilder->orderBy($column, "desc");
108+
}
80109

81-
if ($sort == "$property:asc" || $sort == $property) {
82-
$queryBuilder->orderBy($column, "asc");
83-
}
110+
if ($sort == "$property:asc" || $sort == $property) {
111+
$queryBuilder->orderBy($column, "asc");
112+
}
84113

85-
if ($sort == "$property:asc_nulls_last") {
86-
$queryBuilder->orderByRaw("ISNULL($column) asc")
87-
->orderBy($column, 'asc');
88-
}
114+
if ($sort == "$property:asc_nulls_last") {
115+
$queryBuilder->orderByRaw("ISNULL($column) asc")
116+
->orderBy($column, 'asc');
117+
}
89118

90-
if ($sort == "$property:desc_nulls_first") {
91-
$queryBuilder->orderByRaw("ISNULL($column) desc")
92-
->orderBy($column, 'desc');
93-
}
119+
if ($sort == "$property:desc_nulls_first") {
120+
$queryBuilder->orderByRaw("ISNULL($column) desc")
121+
->orderBy($column, 'desc');
94122
}
95123
}
96-
97-
return $this;
98124
}
99125

100-
public function getSort(): ?string
101-
{
102-
return $this->request->get("sort") ?? $this->defaultSort;
103-
}
104-
105-
public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
126+
protected function applyDefaultSort($queryBuilder): void
106127
{
107-
$this->sortable[] = $property;
108-
$this->defaultSort = $property . ':' . $direction;
109-
110-
return $this;
128+
list($column, $direction) = explode(':', $this->defaultSort);
129+
$queryBuilder->orderBy($column, $direction);
111130
}
112-
113-
114131
}

tests/SieveTest.php

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ public function filters_and_sorts()
2020
'sort' => 'name:desc'
2121
]);
2222

23-
$seive = new Sieve($request);
24-
$seive->configure(fn ($builder) => [
23+
$sieve = new Sieve($request);
24+
$sieve->configure(fn ($builder) => [
2525
'name' => $builder->string(),
2626
]);
2727

2828
/** @var Builder */
2929
$builder = $this->app->make(Builder::class);
3030
$builder->from('pets');
3131

32-
$seive->apply($builder);
32+
$sieve->apply($builder);
3333

3434
$this->assertEquals(
3535
'select * from "pets" where "name" in (?, ?) order by "name" desc',
@@ -48,6 +48,17 @@ public function set_default_sort_filter()
4848
$sieve->setDefaultSort('name', 'desc');
4949

5050
$this->assertEquals($sieve->getSort(), 'name:desc');
51+
52+
/** @var Builder */
53+
$builder = $this->app->make(Builder::class);
54+
$builder->from('pets');
55+
56+
$sieve->apply($builder);
57+
58+
$this->assertEquals(
59+
'select * from "pets" order by "name" desc',
60+
$builder->toSql()
61+
);
5162
}
5263

5364
/**
@@ -196,6 +207,31 @@ public function allows_multiple_columns_to_be_ordered_including_a_null_column()
196207
);
197208
}
198209

210+
/**
211+
* @test
212+
*/
213+
public function applies_order_by_in_order_when_sieve_config_order_is_different()
214+
{
215+
$request = Request::create('/', 'GET', [
216+
'sort' => 'type:asc,name:desc',
217+
]);
218+
219+
$seive = new Sieve($request);
220+
$seive->addFilter('name', new StringFilter);
221+
$seive->addFilter('type', new StringFilter);
222+
223+
/** @var Builder */
224+
$builder = $this->app->make(Builder::class);
225+
$builder->from('pets');
226+
227+
$seive->apply($builder);
228+
229+
$this->assertEquals(
230+
'select * from "pets" order by "type" asc, "name" desc',
231+
$builder->toSql()
232+
);
233+
}
234+
199235
/**
200236
* @test
201237
*/

0 commit comments

Comments
 (0)