Skip to content

Commit

Permalink
Merge pull request #33 from ans-group/multiple-sorts
Browse files Browse the repository at this point in the history
Allow multiple sorts to work when sort order doesn't match config order
  • Loading branch information
Gman98ish authored Jan 23, 2023
2 parents fe2e4e7 + 706fb91 commit e6cc24e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 37 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ of the column this may not be the desired functionality. You can change this usi
* `sort=priority:desc_nulls_first`


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

```php
$sieve->setDefaultSort('name', 'asc')
Expand Down
83 changes: 50 additions & 33 deletions src/Sieve.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ class Sieve

protected $defaultSort = null;

protected $sortable = [];

public function __construct(Request $request)
{
$this->request = $request;
Expand Down Expand Up @@ -57,8 +55,41 @@ public function apply($queryBuilder)
$search = new SearchTerm($property, $operator, $property, $term);
$filter->modifyQuery($queryBuilder, $search);
}
}

if ($this->request->has('sort')) {
$this->applyRequestSorts($queryBuilder);
} elseif ($this->defaultSort) {
$this->applyDefaultSort($queryBuilder);
}

return $this;
}

public function getSort(): ?string
{
return $this->request->get("sort") ?? $this->defaultSort;
}

public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
{
$this->defaultSort = $property . ':' . $direction;

return $this;
}

protected function applyRequestSorts($queryBuilder): void {
$sorts = explode(',', $this->getSort());
foreach ($sorts as $sort) {
$property = explode(':', $sort)[0];

$filterRule = collect($this->getFilters())->firstWhere('property', $property);
if (!$filterRule) {
continue;
}

$column = $property;
$filter = $filterRule['filter'];
while ($filter instanceof WrapsFilter) {
if ($filter instanceof MapFilter) {
$column = $filter->target();
Expand All @@ -68,47 +99,33 @@ public function apply($queryBuilder)
$filter = $filter->getWrapped();
}

if (strpos($column, ".") !== false) {
if (str_contains($column, ".")) {
continue;
}

$sorts = explode(',', $this->getSort());
foreach ($sorts as $sort) {
if ($sort == "$property:desc") {
$queryBuilder->orderBy($column, "desc");
}
if ($sort == "$property:desc") {
$queryBuilder->orderBy($column, "desc");
}

if ($sort == "$property:asc" || $sort == $property) {
$queryBuilder->orderBy($column, "asc");
}
if ($sort == "$property:asc" || $sort == $property) {
$queryBuilder->orderBy($column, "asc");
}

if ($sort == "$property:asc_nulls_last") {
$queryBuilder->orderByRaw("ISNULL($column) asc")
->orderBy($column, 'asc');
}
if ($sort == "$property:asc_nulls_last") {
$queryBuilder->orderByRaw("ISNULL($column) asc")
->orderBy($column, 'asc');
}

if ($sort == "$property:desc_nulls_first") {
$queryBuilder->orderByRaw("ISNULL($column) desc")
->orderBy($column, 'desc');
}
if ($sort == "$property:desc_nulls_first") {
$queryBuilder->orderByRaw("ISNULL($column) desc")
->orderBy($column, 'desc');
}
}

return $this;
}

public function getSort(): ?string
{
return $this->request->get("sort") ?? $this->defaultSort;
}

public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
protected function applyDefaultSort($queryBuilder): void
{
$this->sortable[] = $property;
$this->defaultSort = $property . ':' . $direction;

return $this;
list($column, $direction) = explode(':', $this->defaultSort);
$queryBuilder->orderBy($column, $direction);
}


}
42 changes: 39 additions & 3 deletions tests/SieveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ public function filters_and_sorts()
'sort' => 'name:desc'
]);

$seive = new Sieve($request);
$seive->configure(fn ($builder) => [
$sieve = new Sieve($request);
$sieve->configure(fn ($builder) => [
'name' => $builder->string(),
]);

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

$seive->apply($builder);
$sieve->apply($builder);

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

$this->assertEquals($sieve->getSort(), 'name:desc');

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

$sieve->apply($builder);

$this->assertEquals(
'select * from "pets" order by "name" desc',
$builder->toSql()
);
}

/**
Expand Down Expand Up @@ -196,6 +207,31 @@ public function allows_multiple_columns_to_be_ordered_including_a_null_column()
);
}

/**
* @test
*/
public function applies_order_by_in_order_when_sieve_config_order_is_different()
{
$request = Request::create('/', 'GET', [
'sort' => 'type:asc,name:desc',
]);

$seive = new Sieve($request);
$seive->addFilter('name', new StringFilter);
$seive->addFilter('type', new StringFilter);

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

$seive->apply($builder);

$this->assertEquals(
'select * from "pets" order by "type" asc, "name" desc',
$builder->toSql()
);
}

/**
* @test
*/
Expand Down

0 comments on commit e6cc24e

Please sign in to comment.