Skip to content

Feature/Add build from source. #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/Contracts/CriteriaSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace ComplexHeart\Domain\Criteria\Contracts;

/**
* Interface CriteriaSource
*
* @author Unay Santisteban <usantisteban@othercode.io>
* @package ComplexHeart\Domain\Criteria\Contracts
*/
interface CriteriaSource
{
/**
* Provides the list of filter groups. Each filter group is a list of
* filters. A filter is the combination of field or attribute, operator
* and value:
*
* [
* [
* ["field" => "title", "operator" => "like", "value" => "to hero"],
* ["field" => "tag", "operator" => "in", "value" => ["beginner", "intermediate"]],
* ],
* ];
*
* @return array<array<array<string, mixed>>>
*/
public function filterGroups(): array;

/**
* One of: asc, desc, none or random.
*
* @return string
*/
public function orderType(): string;

/**
* The field or attribute to order by.
*
* @return string
*/
public function orderBy(): string;

/**
* Provides the size of a page.
*
* @return int
*/
public function pageLimit(): int;

/**
* Provides the offset, by default should be 0.
*
* @return int
*/
public function pageOffset(): int;
}
86 changes: 71 additions & 15 deletions src/Criteria.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use Closure;
use ComplexHeart\Domain\Contracts\Model\ValueObject;
use ComplexHeart\Domain\Criteria\Contracts\CriteriaSource;
use ComplexHeart\Domain\Criteria\Errors\CriteriaError;
use ComplexHeart\Domain\Model\IsValueObject;

use function Lambdish\Phunctional\map;
Expand All @@ -32,6 +34,27 @@ public function __construct(
private readonly Order $order,
private readonly Page $page,
) {
$this->check();
}

protected function invariantGroupsMustBeArrayOfFilterGroup(): bool
{
foreach ($this->groups as $group) {
if (!($group instanceof FilterGroup)) {
return false;
}
}

return true;
}

/**
* @param array<string> $violations
* @return void
*/
protected function invariantHandler(array $violations): void
{
throw CriteriaError::create('Unable to create criteria object.', $violations);
}

/**
Expand All @@ -42,12 +65,30 @@ public function __construct(
*/
public static function create(array $groups, Order $order, Page $page): self
{
return new self($groups, $order, $page);
return new self(groups: $groups, order: $order, page: $page);
}

/**
* Creates a new instance of Criteria from the given data source.
*
* @param CriteriaSource $source
* @return Criteria
*/
public static function fromSource(CriteriaSource $source): self
{
return Criteria::create(
groups: map(
fn(array $g): FilterGroup => FilterGroup::createFromArray($g),
$source->filterGroups()
),
order: Order::create($source->orderBy(), OrderType::make($source->orderType())),
page: Page::create($source->pageLimit(), $source->pageOffset())
);
}

public static function default(): self
{
return self::create([], Order::none(), Page::create());
return self::create(groups: [], order: Order::none(), page: Page::create());
}

/**
Expand All @@ -58,7 +99,11 @@ public static function default(): self
*/
public function withFilterGroups(array $groups): self
{
return self::create($groups, $this->order, $this->page);
return self::create(
groups: $groups,
order: $this->order,
page: $this->page
);
}

/**
Expand All @@ -73,50 +118,61 @@ public function withFilterGroup(FilterGroup|Closure $group): self
$group = $group(new FilterGroup());
}

return $this->withFilterGroups(array_merge($this->groups, [$group]));
// push single FilterGroup into an array.
$group = is_array($group) ? $group : [$group];

return $this->withFilterGroups(groups: array_merge($this->groups, $group));
}

public function withOrder(Order $order): self
{
return self::create($this->groups, $order, $this->page);
return self::create(groups: $this->groups, order: $order, page: $this->page);
}

public function withOrderRandom(): self
{
return self::create($this->groups, Order::random(), $this->page);
return self::create(groups: $this->groups, order: Order::random(), page: $this->page);
}

public function withOrderBy(string $field): self
{
return self::create($this->groups, Order::create($field, $this->order->type()), $this->page);
return self::create(
groups: $this->groups,
order: Order::create($field, $this->order->type()),
page: $this->page
);
}

public function withOrderType(string $type): self
{
return self::create(
$this->groups,
Order::create($this->orderBy(), OrderType::make($type)),
$this->page
groups: $this->groups,
order: Order::create($this->orderBy(), OrderType::make($type)),
page: $this->page
);
}

public function withPage(Page $page): self
{
return self::create($this->groups, $this->order, $page);
return self::create(groups: $this->groups, order: $this->order, page: $page);
}

public function withPageOffset(int $offset): self
{
return self::create(
$this->groups,
$this->order,
Page::create($this->pageLimit(), $offset)
groups: $this->groups,
order: $this->order,
page: Page::create($this->pageLimit(), $offset)
);
}

public function withPageLimit(int $limit): self
{
return self::create($this->groups, $this->order, Page::create($limit, $this->pageOffset()));
return self::create(
groups: $this->groups,
order: $this->order,
page: Page::create($limit, $this->pageOffset())
);
}

/**
Expand Down
59 changes: 59 additions & 0 deletions src/Errors/CriteriaError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace ComplexHeart\Domain\Criteria\Errors;

use Error;
use Throwable;

/**
* Class CriteriaError
*
* @author Unay Santisteban <usantisteban@othercode.io>
* @package ComplexHeart\Domain\Criteria\Errors
*/
class CriteriaError extends Error
{
/**
* List of invariant violations.
*
* @var array<string>
*/
private array $violations;

/**
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @param array<string> $violations
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = null, array $violations = [])
{
parent::__construct($message, $code, $previous);

$this->violations = $violations;
}

/**
* @param string $message
* @param array<string> $violations
* @param int $code
* @param Throwable|null $previous
* @return self
*/
public static function create(string $message, array $violations, int $code = 0, Throwable $previous = null): self
{
return new self($message, $code, $previous, $violations);
}

/**
* Returns the list of invariant violations.
*
* @return array<string>
*/
public function violations(): array
{
return $this->violations;
}
}
30 changes: 15 additions & 15 deletions src/FilterGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __construct(array $items = [])
* @param Filter ...$filters
* @return FilterGroup
*/
public static function create(Filter ...$filters): FilterGroup
public static function create(Filter ...$filters): self
{
return new self(array_values($filters));
}
Expand All @@ -45,7 +45,7 @@ public static function create(Filter ...$filters): FilterGroup
* @param array<int, array<int|string, mixed>> $filters
* @return FilterGroup
*/
public static function createFromArray(array $filters): FilterGroup
public static function createFromArray(array $filters): self
{
return self::create(
...map(fn(array $filter): Filter => Filter::createFromArray($filter), $filters)
Expand All @@ -59,7 +59,7 @@ public static function createFromArray(array $filters): FilterGroup
*
* @return self
*/
public function addFilter(Filter $new): FilterGroup
public function addFilter(Filter $new): self
{
if ($this->filter(fn(Filter $filter): bool => $filter->equals($new))->count() > 0) {
return $this;
Expand All @@ -70,37 +70,37 @@ public function addFilter(Filter $new): FilterGroup
return $this;
}

public function addFilterEqual(string $field, mixed $value): FilterGroup
public function addFilterEqual(string $field, mixed $value): self
{
$this->addFilter(Filter::createEqual($field, $value));
return $this;
}

public function addFilterNotEqual(string $field, mixed $value): FilterGroup
public function addFilterNotEqual(string $field, mixed $value): self
{
$this->addFilter(Filter::createNotEqual($field, $value));
return $this;
}

public function addFilterGreaterThan(string $field, mixed $value): FilterGroup
public function addFilterGreaterThan(string $field, mixed $value): self
{
$this->addFilter(Filter::createGreaterThan($field, $value));
return $this;
}

public function addFilterGreaterOrEqualThan(string $field, mixed $value): FilterGroup
public function addFilterGreaterOrEqualThan(string $field, mixed $value): self
{
$this->addFilter(Filter::createGreaterOrEqualThan($field, $value));
return $this;
}

public function addFilterLessThan(string $field, mixed $value): FilterGroup
public function addFilterLessThan(string $field, mixed $value): self
{
$this->addFilter(Filter::createLessThan($field, $value));
return $this;
}

public function addFilterLessOrEqualThan(string $field, mixed $value): FilterGroup
public function addFilterLessOrEqualThan(string $field, mixed $value): self
{
$this->addFilter(Filter::createLessOrEqualThan($field, $value));
return $this;
Expand All @@ -111,7 +111,7 @@ public function addFilterLessOrEqualThan(string $field, mixed $value): FilterGro
* @param array<scalar> $value
* @return $this
*/
public function addFilterIn(string $field, array $value): FilterGroup
public function addFilterIn(string $field, array $value): self
{
$this->addFilter(Filter::createIn($field, $value));
return $this;
Expand All @@ -122,31 +122,31 @@ public function addFilterIn(string $field, array $value): FilterGroup
* @param array<scalar> $value
* @return $this
*/
public function addFilterNotIn(string $field, array $value): FilterGroup
public function addFilterNotIn(string $field, array $value): self
{
$this->addFilter(Filter::createNotIn($field, $value));
return $this;
}

public function addFilterLike(string $field, string $value): FilterGroup
public function addFilterLike(string $field, string $value): self
{
$this->addFilter(Filter::createLike($field, $value));
return $this;
}

public function addFilterNotLike(string $field, string $value): FilterGroup
public function addFilterNotLike(string $field, string $value): self
{
$this->addFilter(Filter::createNotLike($field, $value));
return $this;
}

public function addFilterContains(string $field, string $value): FilterGroup
public function addFilterContains(string $field, string $value): self
{
$this->addFilter(Filter::createContains($field, $value));
return $this;
}

public function addFilterNotContains(string $field, string $value): FilterGroup
public function addFilterNotContains(string $field, string $value): self
{
$this->addFilter(Filter::createNotContains($field, $value));
return $this;
Expand Down
Loading