Skip to content

Commit

Permalink
Merge pull request #18 from ukfast/add-tests
Browse files Browse the repository at this point in the history
Add tests
  • Loading branch information
Gman98ish authored Mar 23, 2022
2 parents 1635e5b + 1596a7b commit 88dc574
Show file tree
Hide file tree
Showing 20 changed files with 761 additions and 112 deletions.
2 changes: 2 additions & 0 deletions src/Exceptions/InvalidSearchTermException.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace UKFast\Sieve\Exceptions;

use RuntimeException;
use UKFast\Sieve\SearchTerm;

class InvalidSearchTermException extends RuntimeException
{
public ?array $allowedValues = [];
}
2 changes: 1 addition & 1 deletion src/Filters/DateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public function modifyQuery($query, SearchTerm $search)
$query->where($search->column(), $search->term());
}
if ($search->operator() == 'neq') {
$query->whereNot($search->column(), $search->term());
$query->where($search->column(), '!=', $search->term());
}
if ($search->operator() == 'in') {
$query->whereIn($search->column(), explode(',', $search->term()));
Expand Down
33 changes: 11 additions & 22 deletions src/Filters/EnumFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,21 @@ public function __construct($allowedValues)

public function modifyQuery($query, SearchTerm $search)
{
$terms = [$search->term()];
if ($search->operator() == 'nin' || $search->operator() == 'in') {
$terms = explode(",", $search->term());
foreach ($terms as $term) {
if (!in_array($term, $this->allowedValues())) {
throw new InvalidSearchTermException(
"{$search->property()} must be one of " . implode(", ", $this->allowedValues)
);
}
}
}

if ($search->operator() == 'eq') {
$query->where($search->column(), $search->term());
}

if ($search->operator() == 'neq') {
$query->where($search->column(), '!=', $search->term());
}

if ($search->operator() == 'in') {
$query->whereIn($search->column(), explode(',', $search->term()));
}

if ($search->operator() == 'nin') {
$query->whereNotIn($search->column(), explode(',', $search->term()));
foreach ($terms as $term) {
if (!in_array($term, $this->allowedValues())) {
$exception = new InvalidSearchTermException(
"{$search->property()} must be one of " . implode(", ", $this->allowedValues)
);
$exception->allowedValues = $this->allowedValues;
throw $exception;
}
}

(new StringFilter)->modifyQuery($query, $search);
}

public function operators()
Expand Down
10 changes: 10 additions & 0 deletions src/MapFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ public function wrap(ModifiesQueries $filter)
$this->filter = $filter;
}

public function getWrapped(): ModifiesQueries
{
return $this->filter;
}

public function target()
{
return $this->column;
}

public function modifyQuery($query, SearchTerm $search)
{
if (strpos($this->column, '.') !== false) {
Expand Down
65 changes: 28 additions & 37 deletions src/Sieve.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ class Sieve
{
protected $filters = [];

protected $sortable = [];

protected $request;

protected $defaultSort = null;
Expand All @@ -19,27 +17,18 @@ public function __construct(Request $request)
$this->request = $request;
}

public function configure($callback, array $sortable = [])
public function configure($callback)
{
foreach ($callback(new FilterBuilder) as $prop => $filter) {
$this->addFilter($prop, $filter);
}

foreach ($sortable as $sort) {
$this->addSort($sort);
}
}

public function addFilter($property, $filter)
{
$this->filters[] = compact('property', 'filter');
}

public function filters()
{
return new FilterBuilder;
}

public function getFilters()
{
return $this->filters;
Expand All @@ -66,43 +55,45 @@ public function apply($queryBuilder)
$search = new SearchTerm($property, $operator, $property, $term);
$filter->modifyQuery($queryBuilder, $search);
}
}

if ($sort = $this->getSort()) {
$queryBuilder->orderBy($sort['sortBy'], $sort['sortDirection']);
}
$column = $property;
while ($filter instanceof WrapsFilter) {
if ($filter instanceof MapFilter) {
$column = $filter->target();
break;
}

return $this;
}
$filter = $filter->getWrapped();
}

public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
{
$this->sortable[] = $property;
$this->defaultSort = $property . ':' . $direction;
if (strpos($column, ".") !== false) {
continue;
}

if ($this->getSort() == "$property:desc") {
$queryBuilder->orderBy($column, "desc");
}

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

return $this;
}

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

public function getSort(): ?array
public function setDefaultSort($property = 'id', $direction = 'asc'): Sieve
{
$sort = $this->request->get("sort") ?? $this->defaultSort ?? ':';

list($sortBy, $sortDirection) = explode(':', $sort, 2);

if ((in_array(strtolower($sortDirection), ['asc', 'desc'])) && (in_array($sortBy, $this->sortable))) {
return compact('sortBy', 'sortDirection');
}
$this->sortable[] = $property;
$this->defaultSort = $property . ':' . $direction;

return null;
return $this;
}

public function getSortable(): array
{
return $this->sortable;
}

}
2 changes: 2 additions & 0 deletions src/WrapsFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
interface WrapsFilter extends ModifiesQueries
{
public function wrap(ModifiesQueries $filter);

public function getWrapped(): ModifiesQueries;
}
100 changes: 100 additions & 0 deletions tests/FilterBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace Tests;

use PHPUnit\Util\Filter;
use Tests\Mocks\NoOpFilter;
use Tests\Mocks\PenceWrapper;
use UKFast\Sieve\FilterBuilder;
use UKFast\Sieve\Filters\BooleanFilter;
use UKFast\Sieve\Filters\DateFilter;
use UKFast\Sieve\Filters\EnumFilter;
use UKFast\Sieve\Filters\NumericFilter;
use UKFast\Sieve\Filters\StringFilter;
use UKFast\Sieve\MapFilter;

class FilterBuilderTest extends TestCase
{
/**
* @test
*/
public function can_build_strings()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(StringFilter::class, $builder->string());
}

/**
* @test
*/
public function can_build_enum()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(EnumFilter::class, $builder->enum(['a', 'b']));
}

/**
* @test
*/
public function can_build_numeric()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(NumericFilter::class, $builder->numeric());
}

/**
* @test
*/
public function can_build_date()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(DateFilter::class, $builder->date());
}

/**
* @test
*/
public function can_build_boolean()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(BooleanFilter::class, $builder->boolean());
}


/**
* @test
*/
public function can_build_custom_filters()
{
$builder = new FilterBuilder;

$this->assertInstanceOf(NoOpFilter::class, $builder->custom(new NoOpFilter));
}

/**
* @test
*/
public function can_wrap_filters()
{
$builder = new FilterBuilder;
$wrapped = $builder->wrap(new PenceWrapper)->string();

$this->assertInstanceOf(PenceWrapper::class, $wrapped);
}

/**
* @test
*/
public function can_wrap_multiple_filters()
{
$builder = new FilterBuilder;
$wrapped = $builder->wrap(new PenceWrapper)->wrap(new MapFilter('target'))->string();

$this->assertInstanceOf(MapFilter::class, $wrapped);
}
}
65 changes: 65 additions & 0 deletions tests/Filters/BooleanFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Test\Filters;

use Tests\Mocks\Pet;
use Tests\TestCase;
use UKFast\Sieve\Filters\BooleanFilter;
use UKFast\Sieve\SearchTerm;

class BooleanFilterTest extends TestCase
{
/**
* @test
*/
public function can_filter_eq()
{
$filter = new BooleanFilter;
$builder = Pet::query()->getQuery();
$filter->modifyQuery($builder, $this->searchTerm('eq', true));

$this->assertEquals(
"select * from `pets` where `is_active` = ?",
$builder->toSql()
);
$this->assertEquals([1], $builder->getBindings());
}

/**
* @test
*/
public function can_filter_neq()
{
$filter = new BooleanFilter;
$builder = Pet::query()->getQuery();
$filter->modifyQuery($builder, $this->searchTerm('neq', true));

$this->assertEquals(
"select * from `pets` where `is_active` != ?",
$builder->toSql()
);
$this->assertEquals([1], $builder->getBindings());
}

/**
* @test
*/
public function can_override_true_and_false_val()
{

$filter = new BooleanFilter('yes', 'no');
$builder = Pet::query()->getQuery();
$filter->modifyQuery($builder, $this->searchTerm('eq', true));

$this->assertEquals(
"select * from `pets` where `is_active` = ?",
$builder->toSql()
);
$this->assertEquals(['yes'], $builder->getBindings());
}

private function searchTerm($operator, $term)
{
return new SearchTerm('is_active', $operator, 'is_active', $term);
}
}
Loading

0 comments on commit 88dc574

Please sign in to comment.