Skip to content

Commit

Permalink
Feature/Added Criteria Builder. (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
othercodes committed Feb 11, 2021
1 parent 0087b30 commit 430e44a
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 1 deletion.
223 changes: 223 additions & 0 deletions src/Application/CriteriaBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
<?php

declare(strict_types=1);

namespace OtherCode\ComplexHeart\Application;

use OtherCode\ComplexHeart\Domain\Criteria\Criteria;
use OtherCode\ComplexHeart\Domain\Criteria\Filter;
use OtherCode\ComplexHeart\Domain\Criteria\FilterGroup;
use OtherCode\ComplexHeart\Domain\Criteria\Order;
use OtherCode\ComplexHeart\Domain\Criteria\Page;

/**
* Class CriteriaBuilder
*
* @author Unay Santisteban <usantisteban@othercode.es>
* @package OtherCode\ComplexHeart\Application
*/
final class CriteriaBuilder
{
private array $filters = [];

private string $orderBy = '';

private string $orderType = 'asc';

private int $pageOffset = 0;

private int $pageLimit = 1000;

/**
* Adds an arbitrary filter.
*
* @param string $field
* @param string $operator
* @param mixed $value
* @return $this
*/
public function filter(string $field, string $operator, $value): self
{
$this->filters[] = [$field, $operator, $value];
return $this;
}

/**
* Adds new filter for equals operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterEqual(string $field, $value): self
{
$this->filter($field, Filter::EQUAL, $value);
return $this;
}

/**
* Adds new filter for not equals operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterNotEqual(string $field, $value): self
{
$this->filter($field, Filter::NOT_EQUAL, $value);
return $this;
}

/**
* Adds new filter for greater than operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterGreaterThan(string $field, $value): self
{
$this->filter($field, Filter::GT, $value);
return $this;
}

/**
* Adds new filter for greater or equal than operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterGreaterOrEqualThan(string $field, $value): self
{
$this->filter($field, Filter::GTE, $value);
return $this;
}

/**
* Adds new filter for less than operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterLessThan(string $field, $value): self
{
$this->filter($field, Filter::LT, $value);
return $this;
}

/**
* Adds new filter for less or equal than operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterLessOrEqualThan(string $field, $value): self
{
$this->filter($field, Filter::LTE, $value);
return $this;
}

/**
* Adds new filter for in operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterIn(string $field, $value): self
{
$this->filter($field, Filter::IN, $value);
return $this;
}

/**
* Adds new filter for not in operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterNotIn(string $field, $value): self
{
$this->filter($field, Filter::NOT_IN, $value);
return $this;
}

/**
* Adds new filter for like operator.
*
* @param string $field
* @param mixed $value
* @return $this
*/
public function filterLike(string $field, $value): self
{
$this->filter($field, Filter::LIKE, $value);
return $this;
}

/**
* Sets the order by field parameter.
*
* @param string $field
* @return $this
*/
public function orderedBy(string $field): self
{
$this->orderBy = $field;
return $this;
}

/**
* Sets the order type parameter.
*
* @param string $type
* @return $this
*/
public function orderedType(string $type): self
{
$this->orderType = $type;
return $this;
}

/**
* Set the page limit parameter.
*
* @param int $limit
* @return $this
*/
public function withLimit(int $limit): self
{
$this->pageLimit = $limit;
return $this;
}

/**
* Set the page offset parameter.
*
* @param int $offset
* @return $this
*/
public function withOffset(int $offset): self
{
$this->pageOffset = $offset;
return $this;
}

/**
* Builds the Criteria object.
*
* @return Criteria
*/
public function build(): Criteria
{
return new Criteria(
FilterGroup::create($this->filters),
Order::create($this->orderBy, $this->orderType),
Page::create($this->pageLimit, $this->pageOffset)
);
}
}
2 changes: 1 addition & 1 deletion src/Domain/Criteria/FilterGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static function create(array $filters): FilterGroup

public function add(Filter $filter): FilterGroup
{
return new self(array_merge($this->filters, [$filter]));
return new self(...array_merge($this->filters, [$filter]));
}

public function filters(): array
Expand Down
63 changes: 63 additions & 0 deletions tests/Application/CriteriaBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace OtherCode\ComplexHeart\Tests\Application;

use Mockery\Adapter\Phpunit\MockeryTestCase;
use OtherCode\ComplexHeart\Application\CriteriaBuilder;
use OtherCode\ComplexHeart\Domain\Criteria\Criteria;

/**
* Class CriteriaBuilderTest
*
* @author Unay Santisteban <usantisteban@othercode.es>
* @package OtherCode\ComplexHeart\Tests\Application
*/
class CriteriaBuilderTest extends MockeryTestCase
{
public function testShouldBuildCriteriaInstance(): void
{
$criteria = (new CriteriaBuilder())->build();
$this->assertInstanceOf(Criteria::class, $criteria);
}

public function testShouldAddFiltersToCriteria(): void
{
$criteria = (new CriteriaBuilder())
->filterEqual('name', 'Jules')
->filterNotEqual('surname', 'Wallace')
->filterGreaterThan('height', 1)
->filterLessThan('weight', 100)
->filterGreaterOrEqualThan('age', 18)
->filterLessOrEqualThan('age', 50)
->filterIn('address.state', ['FL', 'NY'])
->filterNotIn('address.zip', [10, 11, 12, 13])
->filterLike('job.title', '%Gangster%')
->build();

$this->assertCount(9, $criteria->filters());
}

public function testShouldSetOrderByAndOrderType(): void
{
$criteria = (new CriteriaBuilder())
->orderedBy('name')
->orderedType('desc')
->build();

$this->assertEquals('name', $criteria->orderBy());
$this->assertEquals('desc', $criteria->orderType());
}

public function testShouldSetPageLimitAndPageOffset(): void
{
$criteria = (new CriteriaBuilder())
->withLimit(50)
->withOffset(100)
->build();

$this->assertEquals(50, $criteria->pageLimit());
$this->assertEquals(100, $criteria->pageOffset());
}
}

0 comments on commit 430e44a

Please sign in to comment.