diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e7f9fed..4912bf20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ not found (@vjik) - Enh #161: Add more specified psalm annotations to `CountableDataInterface::count()`, `PaginatorInterface::getCurrentPageSize()` and `OffsetPaginator::getTotalItems()` (@vjik) +- Chg #165: Simplify `FilterInterface` and `FilterHandlerInterface` (@vjik) - Chg #166: Remove `EqualsEmpty` filter (@vjik) ## 1.0.1 January 25, 2023 diff --git a/src/Reader/Filter/All.php b/src/Reader/Filter/All.php index 7566f34e..0e971d4a 100644 --- a/src/Reader/Filter/All.php +++ b/src/Reader/Filter/All.php @@ -5,24 +5,18 @@ namespace Yiisoft\Data\Reader\Filter; /** - * `All` filter allows combining multiple criteria or sub-filters using "and" operator. + * `All` filter allows combining multiple sub-filters using "and" operator. * * ```php - * $dataReader->withFilter((new All())->withCriteriaArray( - * [ - * ['>', 'id', 88], - * ['and', [ - * ['=', 'state', 2], - * ['like', 'name', 'eva'], - * ], - * ] - * )); + * $dataReader->withFilter( + * new All( + * new GreaterThan('id', 88), + * new Equals('state', 2), + * new Like('name', 'eva'), + * ) + * ); * ``` */ final class All extends Group { - public static function getOperator(): string - { - return 'and'; - } } diff --git a/src/Reader/Filter/Any.php b/src/Reader/Filter/Any.php index 0e130ec5..08a92a41 100644 --- a/src/Reader/Filter/Any.php +++ b/src/Reader/Filter/Any.php @@ -5,24 +5,17 @@ namespace Yiisoft\Data\Reader\Filter; /** - * `Any` filter allows combining multiple criteria or sub-filters using "or" operator. + * `Any` filter allows combining multiple sub-filters using "or" operator. * * ```php - * $dataReader->withFilter((new Any())->withCriteriaArray( - * [ - * ['>', 'id', 88], - * ['or', [ - * ['=', 'state', 2], - * ['like', 'name', 'eva'], - * ], - * ] - * )); + * $dataReader->withFilter( + * new Any( + * new GreaterThan('id', 88), + * new Equals('state', 2), + * ) + * ); * ``` */ final class Any extends Group { - public static function getOperator(): string - { - return 'or'; - } } diff --git a/src/Reader/Filter/Between.php b/src/Reader/Filter/Between.php index 8de6daa3..5128c3b3 100644 --- a/src/Reader/Filter/Between.php +++ b/src/Reader/Filter/Between.php @@ -5,7 +5,6 @@ namespace Yiisoft\Data\Reader\Filter; use DateTimeInterface; -use Yiisoft\Data\Reader\FilterAssert; use Yiisoft\Data\Reader\FilterInterface; /** @@ -14,31 +13,30 @@ */ final class Between implements FilterInterface { - private bool|DateTimeInterface|float|int|string $minValue; - - private bool|DateTimeInterface|float|int|string $maxValue; - /** * @param string $field Name of the field to compare. * @param bool|DateTimeInterface|float|int|string $minValue Minimal field value. * @param bool|DateTimeInterface|float|int|string $maxValue Maximal field value. */ - public function __construct(private string $field, mixed $minValue, mixed $maxValue) - { - FilterAssert::isScalarOrInstanceOfDateTimeInterface($minValue); - FilterAssert::isScalarOrInstanceOfDateTimeInterface($maxValue); + public function __construct( + private readonly string $field, + private readonly bool|DateTimeInterface|float|int|string $minValue, + private readonly bool|DateTimeInterface|float|int|string $maxValue + ) { + } - $this->minValue = $minValue; - $this->maxValue = $maxValue; + public function getField(): string + { + return $this->field; } - public function toCriteriaArray(): array + public function getMinValue(): float|DateTimeInterface|bool|int|string { - return [self::getOperator(), $this->field, $this->minValue, $this->maxValue]; + return $this->minValue; } - public static function getOperator(): string + public function getMaxValue(): float|DateTimeInterface|bool|int|string { - return 'between'; + return $this->maxValue; } } diff --git a/src/Reader/Filter/Compare.php b/src/Reader/Filter/Compare.php index 39cd4d85..546da999 100644 --- a/src/Reader/Filter/Compare.php +++ b/src/Reader/Filter/Compare.php @@ -5,44 +5,40 @@ namespace Yiisoft\Data\Reader\Filter; use DateTimeInterface; -use Yiisoft\Data\Reader\FilterAssert; use Yiisoft\Data\Reader\FilterInterface; /** * `Compare` filter is a base class that defines a criteria for comparing field value with a given value. - * The operator is defined by child classes. */ abstract class Compare implements FilterInterface { - private bool|DateTimeInterface|float|int|string $value; - /** * @param string $field Name of the field to compare. * @param bool|DateTimeInterface|float|int|string $value Value to compare to. */ - public function __construct(private string $field, mixed $value) - { - $this->setValue($value); + public function __construct( + private readonly string $field, + private bool|DateTimeInterface|float|int|string $value, + ) { } - /** - * @param bool|DateTimeInterface|float|int|string $value Value to compare to. - */ - final public function withValue(mixed $value): static + public function getField(): string { - $new = clone $this; - $new->setValue($value); - return $new; + return $this->field; } - public function toCriteriaArray(): array + public function getValue(): float|DateTimeInterface|bool|int|string { - return [static::getOperator(), $this->field, $this->value]; + return $this->value; } - private function setValue(mixed $value): void + /** + * @param bool|DateTimeInterface|float|int|string $value Value to compare to. + */ + final public function withValue(bool|DateTimeInterface|float|int|string $value): static { - FilterAssert::isScalarOrInstanceOfDateTimeInterface($value); - $this->value = $value; + $new = clone $this; + $new->value = $value; + return $new; } } diff --git a/src/Reader/Filter/Equals.php b/src/Reader/Filter/Equals.php index d49bc483..6b7ef70e 100644 --- a/src/Reader/Filter/Equals.php +++ b/src/Reader/Filter/Equals.php @@ -9,8 +9,4 @@ */ final class Equals extends Compare { - public static function getOperator(): string - { - return '='; - } } diff --git a/src/Reader/Filter/EqualsNull.php b/src/Reader/Filter/EqualsNull.php index 164d8c15..9a48c4c1 100644 --- a/src/Reader/Filter/EqualsNull.php +++ b/src/Reader/Filter/EqualsNull.php @@ -14,17 +14,13 @@ final class EqualsNull implements FilterInterface /** * @param string $field Name of the field to check. */ - public function __construct(private string $field) - { - } - - public function toCriteriaArray(): array - { - return [self::getOperator(), $this->field]; + public function __construct( + private readonly string $field, + ) { } - public static function getOperator(): string + public function getField(): string { - return 'null'; + return $this->field; } } diff --git a/src/Reader/Filter/GreaterThan.php b/src/Reader/Filter/GreaterThan.php index 62995ae8..ec474b6d 100644 --- a/src/Reader/Filter/GreaterThan.php +++ b/src/Reader/Filter/GreaterThan.php @@ -5,13 +5,8 @@ namespace Yiisoft\Data\Reader\Filter; /** - * `GreaterThan` filter defines a criteria for ensuring field value - * is greater than a given value. + * `GreaterThan` filter defines a criteria for ensuring field value is greater than a given value. */ final class GreaterThan extends Compare { - public static function getOperator(): string - { - return '>'; - } } diff --git a/src/Reader/Filter/GreaterThanOrEqual.php b/src/Reader/Filter/GreaterThanOrEqual.php index 9daec46f..feb95371 100644 --- a/src/Reader/Filter/GreaterThanOrEqual.php +++ b/src/Reader/Filter/GreaterThanOrEqual.php @@ -5,13 +5,8 @@ namespace Yiisoft\Data\Reader\Filter; /** - * `GreaterThanOrEqual` filter defines a criteria for ensuring field value - * is greater than or equal to a given value. + * `GreaterThanOrEqual` filter defines a criteria for ensuring field value is greater than or equal to a given value. */ final class GreaterThanOrEqual extends Compare { - public static function getOperator(): string - { - return '>='; - } } diff --git a/src/Reader/Filter/Group.php b/src/Reader/Filter/Group.php index 1f6ac3b5..903ee18c 100644 --- a/src/Reader/Filter/Group.php +++ b/src/Reader/Filter/Group.php @@ -4,92 +4,31 @@ namespace Yiisoft\Data\Reader\Filter; -use InvalidArgumentException; use Yiisoft\Data\Reader\FilterInterface; -use function array_shift; -use function is_array; -use function is_string; -use function sprintf; - /** - * `Group` filter is an abstract class that allows combining multiple criteria or sub-filters. + * `Group` filter is an abstract class that allows combining multiple sub-filters. */ abstract class Group implements FilterInterface { /** - * @var array[]|FilterInterface[] Criteria and sub-filters to use. + * @var FilterInterface[] Sub-filters to use. */ - private array $filtersAndCriteria; + private array $filters; /** * @param FilterInterface ...$filters Sub-filters to use. */ public function __construct(FilterInterface ...$filters) { - $this->filtersAndCriteria = $filters; - } - - /** - * Get criteria array based on current filters and criteria. - * - * @return array Criteria array. - */ - public function toCriteriaArray(): array - { - $criteriaArray = []; - - foreach ($this->filtersAndCriteria as $filterOrCriteria) { - if ($filterOrCriteria instanceof FilterInterface) { - $filterOrCriteria = $filterOrCriteria->toCriteriaArray(); - } - - $criteriaArray[] = $filterOrCriteria; - } - - return [static::getOperator(), $criteriaArray]; + $this->filters = $filters; } /** - * Get a new instance with filters set from criteria array provided. - * - * ```php - * $dataReader->withFilter((new All())->withCriteriaArray( - * [ - * ['>', 'id', 88], - * ['or', [ - * ['=', 'state', 2], - * ['like', 'name', 'eva'], - * ], - * ] - * )); - * ``` - * - * @param array[] $criteriaArray Criteria array to use. - * Instances of FilterInterface are ignored. - * - * @throws InvalidArgumentException If criteria array is not valid. - * - * @return static New instance. - * - * @psalm-suppress DocblockTypeContradiction Needed to allow to validation of `$criteriaArray` + * @return FilterInterface[] */ - public function withCriteriaArray(array $criteriaArray): static + public function getFilters(): array { - foreach ($criteriaArray as $key => $item) { - if (!is_array($item)) { - throw new InvalidArgumentException(sprintf('Invalid filter on "%s" key.', $key)); - } - - $operator = array_shift($item); - - if (!is_string($operator) || $operator === '') { - throw new InvalidArgumentException(sprintf('Invalid filter operator on "%s" key.', $key)); - } - } - - $new = clone $this; - $new->filtersAndCriteria = $criteriaArray; - return $new; + return $this->filters; } } diff --git a/src/Reader/Filter/In.php b/src/Reader/Filter/In.php index 0ab535db..525b70ff 100644 --- a/src/Reader/Filter/In.php +++ b/src/Reader/Filter/In.php @@ -4,7 +4,7 @@ namespace Yiisoft\Data\Reader\Filter; -use Yiisoft\Data\Reader\FilterAssert; +use InvalidArgumentException; use Yiisoft\Data\Reader\FilterInterface; /** @@ -21,21 +21,34 @@ final class In implements FilterInterface * @param string $field Name of the field to compare. * @param bool[]|float[]|int[]|string[] $values Values to check against. */ - public function __construct(private string $field, array $values) - { + public function __construct( + private readonly string $field, + array $values + ) { foreach ($values as $value) { - FilterAssert::isScalar($value); + /** @psalm-suppress DocblockTypeContradiction */ + if (!is_scalar($value)) { + throw new InvalidArgumentException( + sprintf( + 'The value should be scalar. "%s" is received.', + get_debug_type($value), + ) + ); + } } $this->values = $values; } - public function toCriteriaArray(): array + public function getField(): string { - return [self::getOperator(), $this->field, $this->values]; + return $this->field; } - public static function getOperator(): string + /** + * @return bool[]|float[]|int[]|string[] + */ + public function getValues(): array { - return 'in'; + return $this->values; } } diff --git a/src/Reader/Filter/LessThan.php b/src/Reader/Filter/LessThan.php index 80f2b68f..eb2d0824 100644 --- a/src/Reader/Filter/LessThan.php +++ b/src/Reader/Filter/LessThan.php @@ -9,8 +9,4 @@ */ final class LessThan extends Compare { - public static function getOperator(): string - { - return '<'; - } } diff --git a/src/Reader/Filter/LessThanOrEqual.php b/src/Reader/Filter/LessThanOrEqual.php index 932958b2..876b60e1 100644 --- a/src/Reader/Filter/LessThanOrEqual.php +++ b/src/Reader/Filter/LessThanOrEqual.php @@ -9,8 +9,4 @@ */ final class LessThanOrEqual extends Compare { - public static function getOperator(): string - { - return '<='; - } } diff --git a/src/Reader/Filter/Like.php b/src/Reader/Filter/Like.php index 10a5e01c..fc6781f1 100644 --- a/src/Reader/Filter/Like.php +++ b/src/Reader/Filter/Like.php @@ -15,17 +15,19 @@ final class Like implements FilterInterface * @param string $field Name of the field to compare. * @param string $value Value to like-compare with. */ - public function __construct(private string $field, private string $value) - { + public function __construct( + private readonly string $field, + private readonly string $value, + ) { } - public function toCriteriaArray(): array + public function getField(): string { - return [self::getOperator(), $this->field, $this->value]; + return $this->field; } - public static function getOperator(): string + public function getValue(): string { - return 'like'; + return $this->value; } } diff --git a/src/Reader/Filter/Not.php b/src/Reader/Filter/Not.php index fe51a220..a7de17b1 100644 --- a/src/Reader/Filter/Not.php +++ b/src/Reader/Filter/Not.php @@ -14,17 +14,13 @@ final class Not implements FilterInterface /** * @param FilterInterface $filter Filter to negate. */ - public function __construct(private FilterInterface $filter) - { - } - - public function toCriteriaArray(): array - { - return [self::getOperator(), $this->filter->toCriteriaArray()]; + public function __construct( + private readonly FilterInterface $filter, + ) { } - public static function getOperator(): string + public function getFilter(): FilterInterface { - return 'not'; + return $this->filter; } } diff --git a/src/Reader/FilterAssert.php b/src/Reader/FilterAssert.php deleted file mode 100644 index c2aa611a..00000000 --- a/src/Reader/FilterAssert.php +++ /dev/null @@ -1,91 +0,0 @@ -getFilters() as $subFilter) { + $filterHandler = $iterableFilterHandlers[$subFilter::class] ?? null; + if ($filterHandler === null) { + throw new LogicException(sprintf('Filter "%s" is not supported.', $subFilter::class)); + } + if (!$filterHandler->match($item, $subFilter, $iterableFilterHandlers)) { + return false; + } + } + + return true; } } diff --git a/src/Reader/Iterable/FilterHandler/AnyHandler.php b/src/Reader/Iterable/FilterHandler/AnyHandler.php index 85f897b2..c26708dd 100644 --- a/src/Reader/Iterable/FilterHandler/AnyHandler.php +++ b/src/Reader/Iterable/FilterHandler/AnyHandler.php @@ -4,23 +4,36 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; +use LogicException; use Yiisoft\Data\Reader\Filter\Any; - -use function in_array; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `Any` iterable filter handler allows combining multiple sub-filters. * The filter matches if any of the sub-filters match. */ -final class AnyHandler extends GroupHandler +final class AnyHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Any::getOperator(); + return Any::class; } - protected function checkResults(array $results): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - return in_array(true, $results, true); + /** @var Any $filter */ + + foreach ($filter->getFilters() as $subFilter) { + $filterHandler = $iterableFilterHandlers[$subFilter::class] ?? null; + if ($filterHandler === null) { + throw new LogicException(sprintf('Filter "%s" is not supported.', $subFilter::class)); + } + if ($filterHandler->match($item, $subFilter, $iterableFilterHandlers)) { + return true; + } + } + + return false; } } diff --git a/src/Reader/Iterable/FilterHandler/BetweenHandler.php b/src/Reader/Iterable/FilterHandler/BetweenHandler.php index 9c8f92a4..5d87b94b 100644 --- a/src/Reader/Iterable/FilterHandler/BetweenHandler.php +++ b/src/Reader/Iterable/FilterHandler/BetweenHandler.php @@ -5,44 +5,37 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; -use InvalidArgumentException; use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\Between; -use Yiisoft\Data\Reader\FilterAssert; +use Yiisoft\Data\Reader\FilterInterface; use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; -use function count; - /** * `Between` iterable filter handler checks that the item's field value * is between minimal and maximal values. */ final class BetweenHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Between::getOperator(); + return Between::class; } - public function match(array|object $item, array $arguments, array $iterableFilterHandlers): bool + public function match(array|object $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - if (count($arguments) !== 3) { - throw new InvalidArgumentException('$arguments should contain exactly three elements.'); - } - - /** @var string $field */ - [$field, $minValue, $maxValue] = $arguments; - FilterAssert::fieldIsString($field); + /** @var Between $filter */ - $value = ArrayHelper::getValue($item, $field); + $value = ArrayHelper::getValue($item, $filter->getField()); + $min = $filter->getMinValue(); + $max = $filter->getMaxValue(); if (!$value instanceof DateTimeInterface) { - return $value >= $minValue && $value <= $maxValue; + return $value >= $min && $value <= $max; } - return $minValue instanceof DateTimeInterface - && $maxValue instanceof DateTimeInterface - && $value->getTimestamp() >= $minValue->getTimestamp() - && $value->getTimestamp() <= $maxValue->getTimestamp(); + return $min instanceof DateTimeInterface + && $max instanceof DateTimeInterface + && $value->getTimestamp() >= $min->getTimestamp() + && $value->getTimestamp() <= $max->getTimestamp(); } } diff --git a/src/Reader/Iterable/FilterHandler/CompareHandler.php b/src/Reader/Iterable/FilterHandler/CompareHandler.php deleted file mode 100644 index ffcf7329..00000000 --- a/src/Reader/Iterable/FilterHandler/CompareHandler.php +++ /dev/null @@ -1,42 +0,0 @@ -compare(ArrayHelper::getValue($item, $field), $value); - } -} diff --git a/src/Reader/Iterable/FilterHandler/EqualsHandler.php b/src/Reader/Iterable/FilterHandler/EqualsHandler.php index c76f245d..3a2f7dee 100644 --- a/src/Reader/Iterable/FilterHandler/EqualsHandler.php +++ b/src/Reader/Iterable/FilterHandler/EqualsHandler.php @@ -5,20 +5,28 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\Equals; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `Equals` iterable filter handler checks that the item's field value matches given value. */ -final class EqualsHandler extends CompareHandler +final class EqualsHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Equals::getOperator(); + return Equals::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { + /** @var Equals $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValue(); + if (!$itemValue instanceof DateTimeInterface) { return $itemValue == $argumentValue; } diff --git a/src/Reader/Iterable/FilterHandler/EqualsNullHandler.php b/src/Reader/Iterable/FilterHandler/EqualsNullHandler.php index 2c02ad9d..72a82d1c 100644 --- a/src/Reader/Iterable/FilterHandler/EqualsNullHandler.php +++ b/src/Reader/Iterable/FilterHandler/EqualsNullHandler.php @@ -4,34 +4,25 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; -use InvalidArgumentException; use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\EqualsNull; -use Yiisoft\Data\Reader\FilterAssert; +use Yiisoft\Data\Reader\FilterInterface; use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; -use function count; - /** * `EqualsNull` iterable filter handler checks that the item's field value is null. */ final class EqualsNullHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return EqualsNull::getOperator(); + return EqualsNull::class; } - public function match(array|object $item, array $arguments, array $iterableFilterHandlers): bool + public function match(array|object $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - if (count($arguments) !== 1) { - throw new InvalidArgumentException('$arguments should contain exactly one element.'); - } - - [$field] = $arguments; - FilterAssert::fieldIsString($field); + /** @var EqualsNull $filter */ - /** @var string $field */ - return ArrayHelper::getValue($item, $field) === null; + return ArrayHelper::getValue($item, $filter->getField()) === null; } } diff --git a/src/Reader/Iterable/FilterHandler/GreaterThanHandler.php b/src/Reader/Iterable/FilterHandler/GreaterThanHandler.php index eee247bc..72e36f85 100644 --- a/src/Reader/Iterable/FilterHandler/GreaterThanHandler.php +++ b/src/Reader/Iterable/FilterHandler/GreaterThanHandler.php @@ -5,20 +5,28 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\GreaterThan; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `GreaterThan` iterable filter handler checks that the item's field value is greater than the given value. */ -final class GreaterThanHandler extends CompareHandler +final class GreaterThanHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return GreaterThan::getOperator(); + return GreaterThan::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { + /** @var GreaterThan $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValue(); + if (!$itemValue instanceof DateTimeInterface) { return $itemValue > $argumentValue; } diff --git a/src/Reader/Iterable/FilterHandler/GreaterThanOrEqualHandler.php b/src/Reader/Iterable/FilterHandler/GreaterThanOrEqualHandler.php index d040ac5b..5e37b581 100644 --- a/src/Reader/Iterable/FilterHandler/GreaterThanOrEqualHandler.php +++ b/src/Reader/Iterable/FilterHandler/GreaterThanOrEqualHandler.php @@ -5,21 +5,29 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `GreaterThanOrEqual` iterable filter handler checks that the item's field value * is greater than or equal to the given value. */ -final class GreaterThanOrEqualHandler extends CompareHandler +final class GreaterThanOrEqualHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return GreaterThanOrEqual::getOperator(); + return GreaterThanOrEqual::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { + /** @var GreaterThanOrEqual $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValue(); + if (!$itemValue instanceof DateTimeInterface) { return $itemValue >= $argumentValue; } diff --git a/src/Reader/Iterable/FilterHandler/GroupHandler.php b/src/Reader/Iterable/FilterHandler/GroupHandler.php deleted file mode 100644 index 63ee1549..00000000 --- a/src/Reader/Iterable/FilterHandler/GroupHandler.php +++ /dev/null @@ -1,90 +0,0 @@ -match($item, $subFilter, $iterableFilterHandlers); - } - - return $this->checkResults($results); - } -} diff --git a/src/Reader/Iterable/FilterHandler/InHandler.php b/src/Reader/Iterable/FilterHandler/InHandler.php index 7fe85a1d..48a6f47c 100644 --- a/src/Reader/Iterable/FilterHandler/InHandler.php +++ b/src/Reader/Iterable/FilterHandler/InHandler.php @@ -4,23 +4,30 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\In; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; use function in_array; -use function is_array; /** * `In` iterable filter handler ensures that the field value matches one of the value provided. */ -final class InHandler extends CompareHandler +final class InHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return In::getOperator(); + return In::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - return is_array($argumentValue) && in_array($itemValue, $argumentValue, false); + /** @var In $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValues(); + + return in_array($itemValue, $argumentValue); } } diff --git a/src/Reader/Iterable/FilterHandler/LessThanHandler.php b/src/Reader/Iterable/FilterHandler/LessThanHandler.php index 1739d910..b48d41c3 100644 --- a/src/Reader/Iterable/FilterHandler/LessThanHandler.php +++ b/src/Reader/Iterable/FilterHandler/LessThanHandler.php @@ -5,20 +5,28 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\LessThan; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `LessThan` iterable filter handler checks that the item's field value is less than the given value. */ -final class LessThanHandler extends CompareHandler +final class LessThanHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return LessThan::getOperator(); + return LessThan::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { + /** @var LessThan $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValue(); + if (!$itemValue instanceof DateTimeInterface) { return $itemValue < $argumentValue; } diff --git a/src/Reader/Iterable/FilterHandler/LessThanOrEqualHandler.php b/src/Reader/Iterable/FilterHandler/LessThanOrEqualHandler.php index a469f4be..14047393 100644 --- a/src/Reader/Iterable/FilterHandler/LessThanOrEqualHandler.php +++ b/src/Reader/Iterable/FilterHandler/LessThanOrEqualHandler.php @@ -5,21 +5,29 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; use DateTimeInterface; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\LessThanOrEqual; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; /** * `LessThanOrEqual` iterable filter handler checks that the item's field value * is less than or equal to the given value. */ -final class LessThanOrEqualHandler extends CompareHandler +final class LessThanOrEqualHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return LessThanOrEqual::getOperator(); + return LessThanOrEqual::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { + /** @var LessThanOrEqual $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + $argumentValue = $filter->getValue(); + if (!$itemValue instanceof DateTimeInterface) { return $itemValue <= $argumentValue; } diff --git a/src/Reader/Iterable/FilterHandler/LikeHandler.php b/src/Reader/Iterable/FilterHandler/LikeHandler.php index d9e54552..5dac7d36 100644 --- a/src/Reader/Iterable/FilterHandler/LikeHandler.php +++ b/src/Reader/Iterable/FilterHandler/LikeHandler.php @@ -4,7 +4,10 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; +use Yiisoft\Arrays\ArrayHelper; use Yiisoft\Data\Reader\Filter\Like; +use Yiisoft\Data\Reader\FilterInterface; +use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; use function is_string; use function stripos; @@ -12,15 +15,19 @@ /** * `Like` iterable filter handler ensures that the field value is like-match to a given value. */ -final class LikeHandler extends CompareHandler +final class LikeHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Like::getOperator(); + return Like::class; } - protected function compare(mixed $itemValue, mixed $argumentValue): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - return is_string($itemValue) && is_string($argumentValue) && stripos($itemValue, $argumentValue) !== false; + /** @var Like $filter */ + + $itemValue = ArrayHelper::getValue($item, $filter->getField()); + + return is_string($itemValue) && stripos($itemValue, $filter->getValue()) !== false; } } diff --git a/src/Reader/Iterable/FilterHandler/NotHandler.php b/src/Reader/Iterable/FilterHandler/NotHandler.php index 1c5cac25..3eaa6025 100644 --- a/src/Reader/Iterable/FilterHandler/NotHandler.php +++ b/src/Reader/Iterable/FilterHandler/NotHandler.php @@ -4,15 +4,11 @@ namespace Yiisoft\Data\Reader\Iterable\FilterHandler; -use InvalidArgumentException; +use LogicException; use Yiisoft\Data\Reader\Filter\Not; -use Yiisoft\Data\Reader\FilterAssert; +use Yiisoft\Data\Reader\FilterInterface; use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; -use function array_shift; -use function count; -use function is_array; -use function is_string; use function sprintf; /** @@ -20,53 +16,21 @@ */ final class NotHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Not::getOperator(); + return Not::class; } - public function match(array|object $item, array $arguments, array $iterableFilterHandlers): bool + public function match(array|object $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - if (count($arguments) !== 1) { - throw new InvalidArgumentException('$arguments should contain exactly one element.'); - } - - [$values] = $arguments; + /** @var Not $filter */ - if (!is_array($values)) { - throw new InvalidArgumentException(sprintf( - 'The values should be array. The %s is received.', - get_debug_type($values), - )); - } - - if (empty($values)) { - throw new InvalidArgumentException('At least operator should be provided.'); - } - - $operator = array_shift($values); - - if (!is_string($operator)) { - throw new InvalidArgumentException(sprintf( - 'The operator should be string. The %s is received.', - get_debug_type($operator), - )); - } - - if ($operator === '') { - throw new InvalidArgumentException('The operator string cannot be empty.'); - } - - /** @var mixed $filterHandler */ - $filterHandler = $iterableFilterHandlers[$operator] ?? null; + $subFilter = $filter->getFilter(); + $filterHandler = $iterableFilterHandlers[$subFilter::class] ?? null; if ($filterHandler === null) { - throw new InvalidArgumentException(sprintf('"%s" operator is not supported.', $operator)); + throw new LogicException(sprintf('Filter "%s" is not supported.', $subFilter::class)); } - - FilterAssert::isIterableFilterHandlerInterface($filterHandler); - /** @var IterableFilterHandlerInterface $filterHandler */ - - return !$filterHandler->match($item, $values, $iterableFilterHandlers); + return !$filterHandler->match($item, $subFilter, $iterableFilterHandlers); } } diff --git a/src/Reader/Iterable/IterableDataReader.php b/src/Reader/Iterable/IterableDataReader.php index 2cd12f01..81cb90e1 100644 --- a/src/Reader/Iterable/IterableDataReader.php +++ b/src/Reader/Iterable/IterableDataReader.php @@ -28,9 +28,7 @@ use Yiisoft\Data\Reader\Sort; use function array_merge; -use function array_shift; use function count; -use function is_string; use function iterator_to_array; use function sprintf; use function uasort; @@ -165,7 +163,6 @@ public function read(): array { $data = []; $skipped = 0; - $filter = $this->filter?->toCriteriaArray(); $sortedData = $this->sort === null ? $this->data : $this->sortItems($this->data, $this->sort); foreach ($sortedData as $key => $item) { @@ -182,7 +179,7 @@ public function read(): array } // Filter items. - if ($filter === null || $this->matchFilter($item, $filter)) { + if ($this->filter === null || $this->matchFilter($item, $this->filter)) { $data[$key] = $item; } } @@ -203,35 +200,19 @@ public function readOne(): array|object|null * Return whether an item matches iterable filter. * * @param array|object $item Item to check. - * @param array $filter Filter. + * @param FilterInterface $filter Filter. * * @return bool Whether an item matches iterable filter. */ - private function matchFilter(array|object $item, array $filter): bool + private function matchFilter(array|object $item, FilterInterface $filter): bool { - $operation = array_shift($filter); - $arguments = $filter; - - if (!is_string($operation)) { - throw new RuntimeException( - sprintf( - 'The operator should be string. The %s is received.', - get_debug_type($operation), - ) - ); - } - - if ($operation === '') { - throw new RuntimeException('The operator string cannot be empty.'); - } - - $processor = $this->iterableFilterHandlers[$operation] ?? null; + $handler = $this->iterableFilterHandlers[$filter::class] ?? null; - if ($processor === null) { - throw new RuntimeException(sprintf('Operation "%s" is not supported.', $operation)); + if ($handler === null) { + throw new RuntimeException(sprintf('Filter "%s" is not supported.', $filter::class)); } - return $processor->match($item, $arguments, $this->iterableFilterHandlers); + return $handler->match($item, $filter, $this->iterableFilterHandlers); } /** @@ -296,7 +277,7 @@ private function prepareFilterHandlers(array $filterHandlers): array ) ); } - $result[$filterHandler->getOperator()] = $filterHandler; + $result[$filterHandler->getFilterClass()] = $filterHandler; } return $result; diff --git a/src/Reader/Iterable/IterableFilterHandlerInterface.php b/src/Reader/Iterable/IterableFilterHandlerInterface.php index 3283ded2..fb3d8961 100644 --- a/src/Reader/Iterable/IterableFilterHandlerInterface.php +++ b/src/Reader/Iterable/IterableFilterHandlerInterface.php @@ -5,6 +5,7 @@ namespace Yiisoft\Data\Reader\Iterable; use Yiisoft\Data\Reader\FilterHandlerInterface; +use Yiisoft\Data\Reader\FilterInterface; /** * Iterable filter handler checks whether an item matches criteria defined @@ -17,10 +18,11 @@ interface IterableFilterHandlerInterface extends FilterHandlerInterface * for the filters with matching operator active. * * @param array|object $item Item to check. - * @param array $arguments Arguments to pass to iterable filter handlers. - * @param array $iterableFilterHandlers Iterable filter handlers to use in case it is a group filter. + * @param FilterInterface $filter Matched filter. + * @param IterableFilterHandlerInterface[] $iterableFilterHandlers Iterable filter handlers to use in case it is + * a group filter. * * @return bool Whether item matches the filter. */ - public function match(array|object $item, array $arguments, array $iterableFilterHandlers): bool; + public function match(array|object $item, FilterInterface $filter, array $iterableFilterHandlers): bool; } diff --git a/tests/Reader/Filter/AllTest.php b/tests/Reader/Filter/AllTest.php deleted file mode 100644 index beb78d04..00000000 --- a/tests/Reader/Filter/AllTest.php +++ /dev/null @@ -1,88 +0,0 @@ -assertSame([ - 'and', - [ - ['<', 'test', 4], - ['>', 'test', 2], - ], - ], $filter->toCriteriaArray()); - } - - public function testWithCriteriaArrayIsImmutable(): void - { - $filter = new All( - new LessThan('test', 4), - new GreaterThan('test', 2), - ); - - $newFilter = $filter->withCriteriaArray([ - ['>', 'test', 1], - ['<', 'test', 5], - ]); - - $this->assertNotSame($filter, $newFilter); - } - - public function testWithCriteriaArrayOverridesConstructor(): void - { - $filter = new All( - new LessThan('test', 4), - new GreaterThan('test', 2), - ); - - $newFilter = $filter->withCriteriaArray([ - ['>', 'test', 1], - ['<', 'test', 5], - ]); - - $this->assertEquals( - [ - 'and', - [ - ['>', 'test', 1], - ['<', 'test', 5], - ], - ], - $newFilter->toCriteriaArray() - ); - } - - #[DataProvider('invalidFilterDataProvider')] - public function testWithCriteriaArrayFailForInvalidFilter($filter): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid filter on "1" key.'); - - (new All())->withCriteriaArray([['=', 'test', 1], $filter]); - } - - #[DataProvider('invalidFilterOperatorDataProvider')] - public function testWithCriteriaArrayFailForInvalidFilterOperator(array $filter): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid filter operator on "0" key.'); - - (new All())->withCriteriaArray([$filter]); - } -} diff --git a/tests/Reader/Filter/AnyTest.php b/tests/Reader/Filter/AnyTest.php deleted file mode 100644 index bd93d6d4..00000000 --- a/tests/Reader/Filter/AnyTest.php +++ /dev/null @@ -1,91 +0,0 @@ -assertSame([ - 'or', - [ - ['<', 'test', 4], - ['>', 'test', 2], - ], - ], $filter->toCriteriaArray()); - } - - public function testWithCriteriaArrayIsImmutable(): void - { - $filter = new Any( - new LessThan('test', 4), - new GreaterThan('test', 2), - ); - - $newFilter = $filter->withCriteriaArray([ - ['>', 'test', 1], - ['<', 'test', 5], - ]); - - $this->assertNotSame($filter, $newFilter); - } - - public function testWithCriteriaArrayOverridesConstructor(): void - { - $filter = new Any( - new LessThan('test', 4), - new GreaterThan('test', 2), - ); - - $newFilter = $filter->withCriteriaArray([ - ['>', 'test', 1], - ['<', 'test', 5], - ]); - - $this->assertEquals( - [ - 'or', - [ - ['>', 'test', 1], - ['<', 'test', 5], - ], - ], - $newFilter->toCriteriaArray() - ); - } - - #[DataProvider('invalidFilterDataProvider')] - public function testWithCriteriaArrayFailForInvalidFilter(mixed $filter): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid filter on "1" key.'); - - (new Any())->withCriteriaArray([ - ['=', 'test', 1], - $filter, - ]); - } - - #[DataProvider('invalidFilterOperatorDataProvider')] - public function testWithCriteriaArrayFailForInvalidFilterOperator(array $filter): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid filter operator on "0" key.'); - - (new Any())->withCriteriaArray([$filter]); - } -} diff --git a/tests/Reader/Filter/BetweenTest.php b/tests/Reader/Filter/BetweenTest.php deleted file mode 100644 index 5fa94aa2..00000000 --- a/tests/Reader/Filter/BetweenTest.php +++ /dev/null @@ -1,52 +0,0 @@ -assertSame(['between', 'test', $value, $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidFirstValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new Between('test', $value, 2); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidSecondValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new Between('test', 1, $value); - } -} diff --git a/tests/Reader/Filter/CompareTest.php b/tests/Reader/Filter/CompareTest.php index ff4b32b4..ac5915a5 100644 --- a/tests/Reader/Filter/CompareTest.php +++ b/tests/Reader/Filter/CompareTest.php @@ -14,6 +14,6 @@ public function testWithValue() $filter = new LessThan('field', 1); $this->assertNotSame($filter, $filter->withValue(1)); - $this->assertSame(['<', 'field', 2], $filter->withValue(2)->toCriteriaArray()); + $this->assertSame(2, $filter->withValue(2)->getValue()); } } diff --git a/tests/Reader/Filter/EqualsNullTest.php b/tests/Reader/Filter/EqualsNullTest.php deleted file mode 100644 index 61b7a76a..00000000 --- a/tests/Reader/Filter/EqualsNullTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertSame(['null', 'test'], $filter->toCriteriaArray()); - } -} diff --git a/tests/Reader/Filter/EqualsTest.php b/tests/Reader/Filter/EqualsTest.php deleted file mode 100644 index 71671ed7..00000000 --- a/tests/Reader/Filter/EqualsTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertSame(['=', 'test', $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new Equals('test', $value); - } -} diff --git a/tests/Reader/Filter/GreaterThanOrEqualTest.php b/tests/Reader/Filter/GreaterThanOrEqualTest.php deleted file mode 100644 index 1b610501..00000000 --- a/tests/Reader/Filter/GreaterThanOrEqualTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertSame(['>=', 'test', $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidScalarValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new GreaterThanOrEqual('test', $value); - } -} diff --git a/tests/Reader/Filter/GreaterThanTest.php b/tests/Reader/Filter/GreaterThanTest.php deleted file mode 100644 index 4fa33707..00000000 --- a/tests/Reader/Filter/GreaterThanTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertSame(['>', 'test', $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidScalarValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new GreaterThan('test', $value); - } -} diff --git a/tests/Reader/Filter/InTest.php b/tests/Reader/Filter/InTest.php index 4fdf94ce..555e4ce2 100644 --- a/tests/Reader/Filter/InTest.php +++ b/tests/Reader/Filter/InTest.php @@ -5,27 +5,16 @@ namespace Yiisoft\Data\Tests\Reader\Filter; use InvalidArgumentException; -use PHPUnit\Framework\Attributes\DataProvider; +use stdClass; use Yiisoft\Data\Reader\Filter\In; use Yiisoft\Data\Tests\TestCase; final class InTest extends TestCase { - public function testToArray(): void + public function testNotScalarValues(): void { - $filter = new In('test', [1, 2]); - - $this->assertSame(['in', 'test', [1, 2]], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidScalarValue($value): void - { - $type = get_debug_type($value); - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The value should be scalar. The $type is received."); - - new In('test', [$value]); + $this->expectExceptionMessage('The value should be scalar. "' . stdClass::class . '" is received.'); + new In('test', [new stdClass()]); } } diff --git a/tests/Reader/Filter/LessThanOrEqualTest.php b/tests/Reader/Filter/LessThanOrEqualTest.php deleted file mode 100644 index 0af2986c..00000000 --- a/tests/Reader/Filter/LessThanOrEqualTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertSame(['<=', 'test', $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidScalarValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new LessThanOrEqual('test', $value); - } -} diff --git a/tests/Reader/Filter/LessThanTest.php b/tests/Reader/Filter/LessThanTest.php deleted file mode 100644 index 2d40735b..00000000 --- a/tests/Reader/Filter/LessThanTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertSame(['<', 'test', $value], $filter->toCriteriaArray()); - } - - #[DataProvider('invalidScalarValueDataProvider')] - public function testConstructorFailForInvalidScalarValue($value): void - { - $this->expectException(InvalidArgumentException::class); - - $this->expectExceptionMessage(sprintf( - 'The value should be scalar or %s instance. The %s is received.', - DateTimeInterface::class, - get_debug_type($value), - )); - - new LessThan('test', $value); - } -} diff --git a/tests/Reader/Filter/LikeTest.php b/tests/Reader/Filter/LikeTest.php deleted file mode 100644 index c14a35c2..00000000 --- a/tests/Reader/Filter/LikeTest.php +++ /dev/null @@ -1,18 +0,0 @@ -assertSame(['like', 'test', 'value'], $filter->toCriteriaArray()); - } -} diff --git a/tests/Reader/Filter/NotTest.php b/tests/Reader/Filter/NotTest.php deleted file mode 100644 index 73e80394..00000000 --- a/tests/Reader/Filter/NotTest.php +++ /dev/null @@ -1,19 +0,0 @@ -assertSame(['not', ['like', 'test', 'value']], $filter->toCriteriaArray()); - } -} diff --git a/tests/Reader/IterableDataReaderTest.php b/tests/Reader/IterableDataReaderTest.php index a5355830..74069b37 100644 --- a/tests/Reader/IterableDataReaderTest.php +++ b/tests/Reader/IterableDataReaderTest.php @@ -5,10 +5,8 @@ namespace Yiisoft\Data\Tests\Reader; use ArrayIterator; -use DateTimeInterface; use Generator; use InvalidArgumentException; -use PHPUnit\Framework\Attributes\DataProvider; use RuntimeException; use Yiisoft\Data\Reader\DataReaderException; use Yiisoft\Data\Reader\Filter\All; @@ -21,15 +19,14 @@ use Yiisoft\Data\Reader\Filter\LessThanOrEqual; use Yiisoft\Data\Reader\Filter\Like; use Yiisoft\Data\Reader\Filter\Not; -use Yiisoft\Data\Reader\FilterAssert; use Yiisoft\Data\Reader\FilterHandlerInterface; use Yiisoft\Data\Reader\FilterInterface; -use Yiisoft\Data\Reader\Iterable\FilterHandler\CompareHandler; use Yiisoft\Data\Reader\Iterable\IterableDataReader; use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; use Yiisoft\Data\Reader\Sort; use Yiisoft\Data\Tests\Support\CustomFilter\Digital; use Yiisoft\Data\Tests\Support\CustomFilter\DigitalHandler; +use Yiisoft\Data\Tests\Support\CustomFilter\FilterWithoutHandler; use Yiisoft\Data\Tests\TestCase; use function array_slice; @@ -80,7 +77,7 @@ public function testImmutability(): void public function testExceptionOnPassingNonIterableFilters(): void { $nonIterableFilterHandler = new class () implements FilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { return '?'; } @@ -401,39 +398,23 @@ public function testCustomEqualsProcessor(): void $dataReader = (new IterableDataReader(self::DEFAULT_DATASET)) ->withSort($sort) - ->withFilterHandlers(new class () extends CompareHandler { - public function getOperator(): string - { - return Equals::getOperator(); - } - - protected function compare(mixed $itemValue, mixed $argumentValue): bool - { - if (!$itemValue instanceof DateTimeInterface) { - return $itemValue == $argumentValue; - } - - return $argumentValue instanceof DateTimeInterface - && $itemValue->getTimestamp() === $argumentValue->getTimestamp(); - } - - public function match(array|object $item, array $arguments, array $iterableFilterHandlers): bool - { - if (count($arguments) !== 2) { - throw new InvalidArgumentException('$arguments should contain exactly two elements.'); + ->withFilterHandlers( + new class () implements IterableFilterHandlerInterface { + public function getFilterClass(): string + { + return Equals::class; } - [$field, $value] = $arguments; - FilterAssert::fieldIsString($field); - - if ($item[$field] === 2) { - return true; + public function match( + array|object $item, + FilterInterface $filter, + array $iterableFilterHandlers + ): bool { + /** @var Equals $filter */ + return $item[$filter->getField()] === 2; } - - /** @var string $field */ - return array_key_exists($field, $item) && $this->compare($item[$field], $value); } - }); + ); $dataReader = $dataReader->withFilter(new Equals('id', 100)); $expected = [self::ITEM_2]; @@ -441,54 +422,13 @@ public function match(array|object $item, array $arguments, array $iterableFilte $this->assertSame($expected, array_values($this->iterableToArray($dataReader->read()))); } - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFilterFailIfOperatorIsNotString($operator): void - { - $reader = (new IterableDataReader(self::DEFAULT_DATASET)) - ->withFilter( - new class ($operator) implements FilterInterface { - public function __construct( - private mixed $operator - ) { - } - - public static function getOperator(): string - { - return 'custom-filter'; - } - - public function toCriteriaArray(): array - { - return [$this->operator, 'field', 'value']; - } - } - ); - - $type = get_debug_type($operator); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage("The operator should be string. The $type is received."); - $reader->read(); - } - - public function testNotSupportedOperator(): void - { - $dataReader = (new IterableDataReader(self::DEFAULT_DATASET)) - ->withFilter($this->createFilterWithNotSupportedOperator('---')); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Operation "---" is not supported.'); - - $dataReader->read(); - } - - public function testNotSupportedEmptyOperator(): void + public function testNotSupportedFilter(): void { $dataReader = (new IterableDataReader(self::DEFAULT_DATASET)) - ->withFilter($this->createFilterWithNotSupportedOperator('')); + ->withFilter(new FilterWithoutHandler()); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The operator string cannot be empty.'); + $this->expectExceptionMessage('Filter "' . FilterWithoutHandler::class . '" is not supported.'); $dataReader->read(); } @@ -565,28 +505,6 @@ public function testWithLimitZero(): void ); } - private function createFilterWithNotSupportedOperator(string $operator): FilterInterface - { - return new class ($operator) implements FilterInterface { - private static string $operator; - - public function __construct(string $operator) - { - self::$operator = $operator; - } - - public static function getOperator(): string - { - return self::$operator; - } - - public function toCriteriaArray(): array - { - return [self::getOperator(), self::$operator]; - } - }; - } - private function getDataSetAsGenerator(): Generator { yield from self::DEFAULT_DATASET; diff --git a/tests/Reader/IterableHandler/AllTest.php b/tests/Reader/IterableHandler/AllTest.php index 3cd9618b..8f0fb654 100644 --- a/tests/Reader/IterableHandler/AllTest.php +++ b/tests/Reader/IterableHandler/AllTest.php @@ -4,159 +4,81 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; -use stdClass; +use Yiisoft\Data\Reader\Filter\All; +use Yiisoft\Data\Reader\Filter\Equals; +use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual; +use Yiisoft\Data\Reader\Filter\LessThanOrEqual; use Yiisoft\Data\Reader\Iterable\FilterHandler\AllHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanOrEqualHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanOrEqualHandler; -use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; +use Yiisoft\Data\Tests\Support\CustomFilter\FilterWithoutHandler; use Yiisoft\Data\Tests\TestCase; final class AllTest extends TestCase { public static function matchDataProvider(): array { + $handlers = [ + Equals::class => new EqualsHandler(), + GreaterThanOrEqual::class => new GreaterThanOrEqualHandler(), + LessThanOrEqual::class => new LessThanOrEqualHandler(), + ]; + return [ [ true, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ true, - [[['=', 'value', '45'], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', '45'), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ false, - [[['=', 'value', 44], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 44), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ false, - [[['=', 'value', 45], ['>=', 'value', 46], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 46), new LessThanOrEqual('value', 45)], + $handlers, ], [ false, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 44]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 44)], + $handlers, ], [ false, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 44]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 44)], + $handlers, ], ]; } #[DataProvider('matchDataProvider')] - public function testMatch(bool $expected, array $arguments, array $filterHandlers): void + public function testMatch(bool $expected, array $filters, array $filterHandlers): void { - $processor = new AllHandler(); + $handler = new AllHandler(); $item = [ 'id' => 1, 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, $filterHandlers)); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'two' => [[1, 2]], - 'tree' => [[1, 2]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly one element.'); - - (new AllHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidArrayValueDataProvider')] - public function testMatchFailIfSubFiltersIsNotArray($subFilters): void - { - $type = get_debug_type($subFilters); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The sub filters should be array. The $type is received."); - - (new AllHandler())->match(['id' => 1], [$subFilters], []); - } - - #[DataProvider('invalidArrayValueDataProvider')] - public function testMatchFailIfSubFilterIsNotArray($subFilters): void - { - $type = get_debug_type($subFilters); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The sub filter should be array. The $type is received."); - - (new AllHandler())->match(['id' => 1], [[$subFilters]], []); - } - - public function testMatchFailIfArgumentValueIsEmptyArray(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('At least operator should be provided.'); - - (new AllHandler())->match(['id' => 1], [[[]]], []); - } - - public static function invalidFilterOperatorDataProvider(): array - { - $data = parent::invalidFilterOperatorDataProvider(); - unset($data['array'], $data['empty-string']); - return $data; - } - - #[DataProvider('invalidFilterOperatorDataProvider')] - public function testMatchFailForInvalidFilterOperator(array $filter): void - { - $type = get_debug_type($filter[0]); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The operator should be string. The $type is received."); - - (new AllHandler())->match(['id' => 1], [[$filter]], []); - } - - public function testMatchFailForEmptyFilterOperator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The operator string cannot be empty.'); - - (new AllHandler())->match(['id' => 1], [[['']]], []); + $this->assertSame($expected, $handler->match($item, new All(...$filters), $filterHandlers)); } public function testMatchFailIfFilterOperatorIsNotSupported(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('">" operator is not supported.'); - - (new AllHandler())->match(['id' => 1], [[['>']]], ['=' => new EqualsHandler()]); - } - - public function testMatchFailIfFilterHandlerIsNotIterable(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf( - 'The filter handler should be an object and implement "%s". The %s is received.', - IterableFilterHandlerInterface::class, - stdClass::class, - )); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Filter "' . FilterWithoutHandler::class . '" is not supported.'); - (new AllHandler())->match(['id' => 1], [[['=']]], ['=' => new stdClass()]); + (new AllHandler())->match(['id' => 1], new All(new FilterWithoutHandler()), []); } } diff --git a/tests/Reader/IterableHandler/AnyTest.php b/tests/Reader/IterableHandler/AnyTest.php index 0e74e41e..f2b80fb4 100644 --- a/tests/Reader/IterableHandler/AnyTest.php +++ b/tests/Reader/IterableHandler/AnyTest.php @@ -4,61 +4,64 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; -use stdClass; +use Yiisoft\Data\Reader\Filter\Any; +use Yiisoft\Data\Reader\Filter\Equals; +use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual; +use Yiisoft\Data\Reader\Filter\LessThanOrEqual; use Yiisoft\Data\Reader\Iterable\FilterHandler\AnyHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanOrEqualHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanOrEqualHandler; -use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; +use Yiisoft\Data\Tests\Support\CustomFilter\FilterWithoutHandler; use Yiisoft\Data\Tests\TestCase; final class AnyTest extends TestCase { public static function matchDataProvider(): array { + $handlers = [ + Equals::class => new EqualsHandler(), + GreaterThanOrEqual::class => new GreaterThanOrEqualHandler(), + LessThanOrEqual::class => new LessThanOrEqualHandler(), + ]; return [ [ true, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], - ], - [ - true, - [[['=', 'value', '45'], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ true, - [[['=', 'value', 44], ['>=', 'value', 45], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', '45'), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ true, - [[['=', 'value', 45], ['>=', 'value', 46], ['<=', 'value', 45]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 45)], + $handlers, ], [ true, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 44]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 46), new LessThanOrEqual('value', 45)], + $handlers, ], [ true, - [[['=', 'value', 45], ['>=', 'value', 45], ['<=', 'value', 44]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 45), new GreaterThanOrEqual('value', 45), new LessThanOrEqual('value', 44)], + $handlers, ], [ false, - [[['=', 'value', 44], ['>=', 'value', 46], ['<=', 'value', 44]]], - ['=' => new EqualsHandler(), '>=' => new GreaterThanOrEqualHandler(), '<=' => new LessThanOrEqualHandler()], + [new Equals('value', 44), new GreaterThanOrEqual('value', 46), new LessThanOrEqual('value', 44)], + $handlers, ], ]; } #[DataProvider('matchDataProvider')] - public function testMatch(bool $expected, array $arguments, array $filterHandlers): void + public function testMatch(bool $expected, array $filters, array $filterHandlers): void { $handler = new AnyHandler(); @@ -67,101 +70,14 @@ public function testMatch(bool $expected, array $arguments, array $filterHandler 'value' => 45, ]; - $this->assertSame($expected, $handler->match($item, $arguments, $filterHandlers)); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'two' => [[1, 2]], - 'tree' => [[1, 2]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly one element.'); - - (new AnyHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidArrayValueDataProvider')] - public function testMatchFailIfSubFiltersIsNotArray($subFilters): void - { - $type = get_debug_type($subFilters); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The sub filters should be array. The $type is received."); - - (new AnyHandler())->match(['id' => 1], [$subFilters], []); - } - - #[DataProvider('invalidArrayValueDataProvider')] - public function testMatchFailIfSubFilterIsNotArray($subFilters): void - { - $type = get_debug_type($subFilters); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The sub filter should be array. The $type is received."); - - (new AnyHandler())->match(['id' => 1], [[$subFilters]], []); - } - - public function testMatchFailIfArgumentValueIsEmptyArray(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('At least operator should be provided.'); - - (new AnyHandler())->match(['id' => 1], [[[]]], []); - } - - public static function invalidFilterOperatorDataProvider(): array - { - $data = parent::invalidFilterOperatorDataProvider(); - unset($data['array'], $data['empty-string']); - return $data; - } - - #[DataProvider('invalidFilterOperatorDataProvider')] - public function testMatchFailForInvalidFilterOperator(array $filter): void - { - $type = get_debug_type($filter[0]); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The operator should be string. The $type is received."); - - (new AnyHandler())->match(['id' => 1], [[$filter]], []); - } - - public function testMatchFailForEmptyFilterOperator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The operator string cannot be empty.'); - - (new AnyHandler())->match(['id' => 1], [[['']]], []); + $this->assertSame($expected, $handler->match($item, new Any(...$filters), $filterHandlers)); } public function testMatchFailIfFilterOperatorIsNotSupported(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('">" operator is not supported.'); - - (new AnyHandler())->match(['id' => 1], [[['>']]], ['=' => new EqualsHandler()]); - } - - public function testMatchFailIfFilterHandlerIsNotIterable(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf( - 'The filter handler should be an object and implement "%s". The %s is received.', - IterableFilterHandlerInterface::class, - stdClass::class, - )); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Filter "' . FilterWithoutHandler::class . '" is not supported.'); - (new AnyHandler())->match(['id' => 1], [[['=']]], ['=' => new stdClass()]); + (new AnyHandler())->match(['id' => 1], new Any(new FilterWithoutHandler()), []); } } diff --git a/tests/Reader/IterableHandler/BetweenTest.php b/tests/Reader/IterableHandler/BetweenTest.php index 88cfc64e..850cb78f 100644 --- a/tests/Reader/IterableHandler/BetweenTest.php +++ b/tests/Reader/IterableHandler/BetweenTest.php @@ -5,7 +5,6 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; use Yiisoft\Data\Reader\Filter\Between; use Yiisoft\Data\Reader\Iterable\FilterHandler\BetweenHandler; @@ -18,40 +17,40 @@ final class BetweenTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 42, 47]], - [true, ['value', 45, 45]], - [true, ['value', 45, 46]], - [false, ['value', 46, 47]], - [false, ['value', 46, 45]], + [true, new Between('value', 42, 47)], + [true, new Between('value', 45, 45)], + [true, new Between('value', 45, 46)], + [false, new Between('value', 46, 47)], + [false, new Between('value', 46, 45)], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, Between $filter): void { - $processor = new BetweenHandler(); + $handler = new BetweenHandler(); $item = [ 'id' => 1, 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $handler->match($item, $filter, [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:42'), new DateTimeImmutable('2022-02-22 16:00:47')]], - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:45'), new DateTimeImmutable('2022-02-22 16:00:45')]], - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:45'), new DateTimeImmutable('2022-02-22 16:00:46')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:46'), new DateTimeImmutable('2022-02-22 16:00:47')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:46'), new DateTimeImmutable('2022-02-22 16:00:45')]], + [true, new DateTimeImmutable('2022-02-22 16:00:42'), new DateTimeImmutable('2022-02-22 16:00:47')], + [true, new DateTimeImmutable('2022-02-22 16:00:45'), new DateTimeImmutable('2022-02-22 16:00:45')], + [true, new DateTimeImmutable('2022-02-22 16:00:45'), new DateTimeImmutable('2022-02-22 16:00:46')], + [false, new DateTimeImmutable('2022-02-22 16:00:46'), new DateTimeImmutable('2022-02-22 16:00:47')], + [false, new DateTimeImmutable('2022-02-22 16:00:46'), new DateTimeImmutable('2022-02-22 16:00:45')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $from, DateTimeImmutable $to): void { $processor = new BetweenHandler(); @@ -60,37 +59,7 @@ public function testMatchDateTimeInterface(bool $expected, array $arguments): vo 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'two' => [[1, 2]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly three elements.'); - - (new BetweenHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new BetweenHandler())->match(['id' => 1], [$field, 1, 2], []); + $this->assertSame($expected, $processor->match($item, new Between('value', $from, $to), [])); } public function testObjectWithGetters(): void diff --git a/tests/Reader/IterableHandler/EqualsNullTest.php b/tests/Reader/IterableHandler/EqualsNullTest.php index 2549cdba..607aaf9d 100644 --- a/tests/Reader/IterableHandler/EqualsNullTest.php +++ b/tests/Reader/IterableHandler/EqualsNullTest.php @@ -4,7 +4,6 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; use Yiisoft\Data\Reader\Filter\EqualsNull; use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsNullHandler; @@ -31,37 +30,7 @@ public static function matchDataProvider(): array #[DataProvider('matchDataProvider')] public function testMatch(bool $expected, array $item): void { - $this->assertSame($expected, (new EqualsNullHandler())->match($item, ['value'], [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'two' => [[1, 2]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly one element.'); - - (new EqualsNullHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new EqualsNullHandler())->match(['id' => 1], [$field], []); + $this->assertSame($expected, (new EqualsNullHandler())->match($item, new EqualsNull('value'), [])); } public function testObjectWithGetters(): void diff --git a/tests/Reader/IterableHandler/EqualsTest.php b/tests/Reader/IterableHandler/EqualsTest.php index 9257edbd..23faa915 100644 --- a/tests/Reader/IterableHandler/EqualsTest.php +++ b/tests/Reader/IterableHandler/EqualsTest.php @@ -5,7 +5,6 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; use Yiisoft\Data\Reader\Filter\Equals; use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsHandler; @@ -18,15 +17,15 @@ final class EqualsTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 45]], - [true, ['value', '45']], - [false, ['value', 44]], - [false, ['value', 46]], + [true, 45], + [true, '45'], + [false, 44], + [false, 46], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, mixed $value): void { $processor = new EqualsHandler(); @@ -35,59 +34,29 @@ public function testMatchScalar(bool $expected, array $arguments): void 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $processor->match($item, new Equals('value', $value), [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:45')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:44')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:46')]], + [true, new DateTimeImmutable('2022-02-22 16:00:45')], + [false, new DateTimeImmutable('2022-02-22 16:00:44')], + [false, new DateTimeImmutable('2022-02-22 16:00:46')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $value): void { - $processor = new EqualsHandler(); + $handler = new EqualsHandler(); $item = [ 'id' => 1, 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new EqualsHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new EqualsHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $handler->match($item, new Equals('value', $value), [])); } public function testObjectWithGetters(): void diff --git a/tests/Reader/IterableHandler/GreaterThanOrEqualTest.php b/tests/Reader/IterableHandler/GreaterThanOrEqualTest.php index 07492fd0..4336feda 100644 --- a/tests/Reader/IterableHandler/GreaterThanOrEqualTest.php +++ b/tests/Reader/IterableHandler/GreaterThanOrEqualTest.php @@ -5,8 +5,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual; use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanOrEqualHandler; use Yiisoft\Data\Tests\TestCase; @@ -15,15 +15,15 @@ final class GreaterThanOrEqualTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 44]], - [true, ['value', 45]], - [true, ['value', '45']], - [false, ['value', 46]], + [true, 44], + [true, 45], + [true, '45'], + [false, 46], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, mixed $value): void { $processor = new GreaterThanOrEqualHandler(); @@ -32,20 +32,20 @@ public function testMatchScalar(bool $expected, array $arguments): void 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $processor->match($item, new GreaterThanOrEqual('value', $value), [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:44')]], - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:45')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:46')]], + [true, new DateTimeImmutable('2022-02-22 16:00:44')], + [true, new DateTimeImmutable('2022-02-22 16:00:45')], + [false, new DateTimeImmutable('2022-02-22 16:00:46')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $value): void { $processor = new GreaterThanOrEqualHandler(); @@ -54,36 +54,6 @@ public function testMatchDateTimeInterface(bool $expected, array $arguments): vo 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new GreaterThanOrEqualHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new GreaterThanOrEqualHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $processor->match($item, new GreaterThanOrEqual('value', $value), [])); } } diff --git a/tests/Reader/IterableHandler/GreaterThanTest.php b/tests/Reader/IterableHandler/GreaterThanTest.php index f64cf38d..62c1914b 100644 --- a/tests/Reader/IterableHandler/GreaterThanTest.php +++ b/tests/Reader/IterableHandler/GreaterThanTest.php @@ -5,8 +5,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\GreaterThan; use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanHandler; use Yiisoft\Data\Tests\TestCase; @@ -15,75 +15,45 @@ final class GreaterThanTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 44]], - [true, ['value', '44']], - [false, ['value', 45]], - [false, ['value', 46]], + [true, 44], + [true, '44'], + [false, 45], + [false, 46], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, mixed $value): void { - $processor = new GreaterThanHandler(); + $handler = new GreaterThanHandler(); $item = [ 'id' => 1, 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $handler->match($item, new GreaterThan('value', $value), [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:44')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:45')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:46')]], + [true, new DateTimeImmutable('2022-02-22 16:00:44')], + [false, new DateTimeImmutable('2022-02-22 16:00:45')], + [false, new DateTimeImmutable('2022-02-22 16:00:46')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $value): void { - $processor = new GreaterThanHandler(); + $handler = new GreaterThanHandler(); $item = [ 'id' => 1, 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new GreaterThanHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new GreaterThanHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $handler->match($item, new GreaterThan('value', $value), [])); } } diff --git a/tests/Reader/IterableHandler/InTest.php b/tests/Reader/IterableHandler/InTest.php index 0ea1053a..126fe5b2 100644 --- a/tests/Reader/IterableHandler/InTest.php +++ b/tests/Reader/IterableHandler/InTest.php @@ -4,8 +4,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\In; use Yiisoft\Data\Reader\Iterable\FilterHandler\InHandler; use Yiisoft\Data\Tests\TestCase; @@ -14,52 +14,22 @@ final class InTest extends TestCase public static function matchDataProvider(): array { return [ - [true, ['value', [44, 45, 46]]], - [true, ['value', [44, '45', 46]]], - [false, ['value', [1, 2, 3]]], + [true, [44, 45, 46]], + [true, [44, '45', 46]], + [false, [1, 2, 3]], ]; } #[DataProvider('matchDataProvider')] - public function testMatch(bool $expected, array $arguments): void + public function testMatch(bool $expected, array $value): void { - $processor = new InHandler(); + $handler = new InHandler(); $item = [ 'id' => 1, 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[[]]], - 'three' => [[[], [], []]], - 'four' => [[[], [], [], []]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new InHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new InHandler())->match(['id' => 1], [$field, [1, 2, 3]], []); + $this->assertSame($expected, $handler->match($item, new In('value', $value), [])); } } diff --git a/tests/Reader/IterableHandler/LessThanOrEqualTest.php b/tests/Reader/IterableHandler/LessThanOrEqualTest.php index fe3e08eb..3c05c75b 100644 --- a/tests/Reader/IterableHandler/LessThanOrEqualTest.php +++ b/tests/Reader/IterableHandler/LessThanOrEqualTest.php @@ -5,8 +5,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\LessThanOrEqual; use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanOrEqualHandler; use Yiisoft\Data\Tests\TestCase; @@ -15,75 +15,45 @@ final class LessThanOrEqualTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 46]], - [true, ['value', 45]], - [true, ['value', '45']], - [false, ['value', 44]], + [true, 46], + [true, 45], + [true, '45'], + [false, 44], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, mixed $value): void { - $processor = new LessThanOrEqualHandler(); + $handler = new LessThanOrEqualHandler(); $item = [ 'id' => 1, 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $handler->match($item, new LessThanOrEqual('value', $value), [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:46')]], - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:45')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:44')]], + [true, new DateTimeImmutable('2022-02-22 16:00:46')], + [true, new DateTimeImmutable('2022-02-22 16:00:45')], + [false, new DateTimeImmutable('2022-02-22 16:00:44')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $value): void { - $processor = new LessThanOrEqualHandler(); + $handler = new LessThanOrEqualHandler(); $item = [ 'id' => 1, 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new LessThanOrEqualHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new LessThanOrEqualHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $handler->match($item, new LessThanOrEqual('value', $value), [])); } } diff --git a/tests/Reader/IterableHandler/LessThanTest.php b/tests/Reader/IterableHandler/LessThanTest.php index 0a3f1d17..7b5a51c1 100644 --- a/tests/Reader/IterableHandler/LessThanTest.php +++ b/tests/Reader/IterableHandler/LessThanTest.php @@ -5,8 +5,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; use DateTimeImmutable; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\LessThan; use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanHandler; use Yiisoft\Data\Tests\TestCase; @@ -15,15 +15,15 @@ final class LessThanTest extends TestCase public static function matchScalarDataProvider(): array { return [ - [true, ['value', 46]], - [true, ['value', '46']], - [false, ['value', 45]], - [false, ['value', 44]], + [true, 46], + [true, '46'], + [false, 45], + [false, 44], ]; } #[DataProvider('matchScalarDataProvider')] - public function testMatchScalar(bool $expected, array $arguments): void + public function testMatchScalar(bool $expected, mixed $value): void { $processor = new LessThanHandler(); @@ -32,58 +32,28 @@ public function testMatchScalar(bool $expected, array $arguments): void 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); + $this->assertSame($expected, $processor->match($item, new LessThan('value', $value), [])); } public static function matchDateTimeInterfaceDataProvider(): array { return [ - [true, ['value', new DateTimeImmutable('2022-02-22 16:00:46')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:45')]], - [false, ['value', new DateTimeImmutable('2022-02-22 16:00:44')]], + [true, new DateTimeImmutable('2022-02-22 16:00:46')], + [false, new DateTimeImmutable('2022-02-22 16:00:45')], + [false, new DateTimeImmutable('2022-02-22 16:00:44')], ]; } #[DataProvider('matchDateTimeInterfaceDataProvider')] - public function testMatchDateTimeInterface(bool $expected, array $arguments): void + public function testMatchDateTimeInterface(bool $expected, DateTimeImmutable $value): void { - $processor = new LessThanHandler(); + $handler = new LessThanHandler(); $item = [ 'id' => 1, 'value' => new DateTimeImmutable('2022-02-22 16:00:45'), ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new LessThanHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new LessThanHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $handler->match($item, new LessThan('value', $value), [])); } } diff --git a/tests/Reader/IterableHandler/LikeTest.php b/tests/Reader/IterableHandler/LikeTest.php index 953c59d9..f5a943f6 100644 --- a/tests/Reader/IterableHandler/LikeTest.php +++ b/tests/Reader/IterableHandler/LikeTest.php @@ -4,8 +4,8 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use Yiisoft\Data\Reader\Filter\Like; use Yiisoft\Data\Reader\Iterable\FilterHandler\LikeHandler; use Yiisoft\Data\Tests\TestCase; @@ -14,15 +14,14 @@ final class LikeTest extends TestCase public static function matchDataProvider(): array { return [ - [true, ['value', 'Great Cat Fighter']], - [true, ['value', 'Cat']], - [false, ['id', 1]], - [false, ['id', '1']], + [true, 'value', 'Great Cat Fighter'], + [true, 'value', 'Cat'], + [false, 'id', '1'], ]; } #[DataProvider('matchDataProvider')] - public function testMatch(bool $expected, array $arguments): void + public function testMatch(bool $expected, string $field, string $value): void { $processor = new LikeHandler(); @@ -31,36 +30,6 @@ public function testMatch(bool $expected, array $arguments): void 'value' => 'Great Cat Fighter', ]; - $this->assertSame($expected, $processor->match($item, $arguments, [])); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'one' => [[1]], - 'three' => [[1, 2, 3]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly two elements.'); - - (new LikeHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidStringValueDataProvider')] - public function testMatchFailForInvalidFieldValue($field): void - { - $type = get_debug_type($field); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The field should be string. The $type is received."); - - (new LikeHandler())->match(['id' => 1], [$field, 1], []); + $this->assertSame($expected, $processor->match($item, new Like($field, $value), [])); } } diff --git a/tests/Reader/IterableHandler/NotTest.php b/tests/Reader/IterableHandler/NotTest.php index b649f506..62ac72e5 100644 --- a/tests/Reader/IterableHandler/NotTest.php +++ b/tests/Reader/IterableHandler/NotTest.php @@ -4,12 +4,14 @@ namespace Yiisoft\Data\Tests\Reader\IterableHandler; -use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; -use stdClass; +use Yiisoft\Data\Reader\Filter\Equals; +use Yiisoft\Data\Reader\Filter\Not; +use Yiisoft\Data\Reader\FilterInterface; use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsHandler; use Yiisoft\Data\Reader\Iterable\FilterHandler\NotHandler; -use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; +use Yiisoft\Data\Tests\Support\CustomFilter\FilterWithoutHandler; use Yiisoft\Data\Tests\TestCase; final class NotTest extends TestCase @@ -17,15 +19,15 @@ final class NotTest extends TestCase public static function matchDataProvider(): array { return [ - [true, [['=', 'value', 44]], ['=' => new EqualsHandler()]], - [true, [['=', 'value', 46]], ['=' => new EqualsHandler()]], - [false, [['=', 'value', 45]], ['=' => new EqualsHandler()]], - [false, [['=', 'value', '45']], ['=' => new EqualsHandler()]], + [true, new Equals('value', 44), [Equals::class => new EqualsHandler()]], + [true, new Equals('value', 46), [Equals::class => new EqualsHandler()]], + [false, new Equals('value', 45), [Equals::class => new EqualsHandler()]], + [false, new Equals('value', '45'), [Equals::class => new EqualsHandler()]], ]; } #[DataProvider('matchDataProvider')] - public function testMatch(bool $expected, array $arguments, array $filterHandlers): void + public function testMatch(bool $expected, FilterInterface $filter, array $filterHandlers): void { $processor = new NotHandler(); @@ -34,90 +36,14 @@ public function testMatch(bool $expected, array $arguments, array $filterHandler 'value' => 45, ]; - $this->assertSame($expected, $processor->match($item, $arguments, $filterHandlers)); - } - - public static function invalidCountArgumentsDataProvider(): array - { - return [ - 'zero' => [[]], - 'two' => [[1, 2]], - 'tree' => [[1, 2]], - 'four' => [[1, 2, 3, 4]], - ]; - } - - #[DataProvider('invalidCountArgumentsDataProvider')] - public function testMatchFailForInvalidCountArguments($arguments): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('$arguments should contain exactly one element.'); - - (new NotHandler())->match(['id' => 1], $arguments, []); - } - - #[DataProvider('invalidArrayValueDataProvider')] - public function testMatchFailIfArgumentValueIsNotArray($value): void - { - $type = get_debug_type($value); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The values should be array. The $type is received."); - - (new NotHandler())->match(['id' => 1], [$value], []); - } - - public function testMatchFailIfArgumentValueIsEmptyArray(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('At least operator should be provided.'); - - (new NotHandler())->match(['id' => 1], [[]], []); - } - - public static function invalidFilterOperatorDataProvider(): array - { - $data = parent::invalidFilterOperatorDataProvider(); - unset($data['array'], $data['empty-string']); - return $data; - } - - #[DataProvider('invalidFilterOperatorDataProvider')] - public function testMatchFailForInvalidFilterOperator(array $filter): void - { - $type = get_debug_type($filter[0]); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("The operator should be string. The $type is received."); - - (new NotHandler())->match(['id' => 1], [$filter], []); - } - - public function testMatchFailForEmptyFilterOperator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The operator string cannot be empty.'); - - (new NotHandler())->match(['id' => 1], [['']], []); + $this->assertSame($expected, $processor->match($item, new Not($filter), $filterHandlers)); } public function testMatchFailIfFilterOperatorIsNotSupported(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('">" operator is not supported.'); - - (new NotHandler())->match(['id' => 1], [['>']], ['=' => new EqualsHandler()]); - } - - public function testMatchFailIfFilterHandlerIsNotIterable(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf( - 'The filter handler should be an object and implement "%s". The %s is received.', - IterableFilterHandlerInterface::class, - stdClass::class, - )); + $this->expectException(LogicException::class); + $this->expectExceptionMessage('Filter "' . FilterWithoutHandler::class . '" is not supported.'); - (new NotHandler())->match(['id' => 1], [['=']], ['=' => new stdClass()]); + (new NotHandler())->match(['id' => 1], new Not(new FilterWithoutHandler()), []); } } diff --git a/tests/Support/CustomFilter/Digital.php b/tests/Support/CustomFilter/Digital.php index 191c2158..0b1cb3c5 100644 --- a/tests/Support/CustomFilter/Digital.php +++ b/tests/Support/CustomFilter/Digital.php @@ -8,17 +8,7 @@ final class Digital implements FilterInterface { - public function __construct(private string $field) + public function __construct(public readonly string $field) { } - - public function toCriteriaArray(): array - { - return [self::getOperator(), $this->field]; - } - - public static function getOperator(): string - { - return 'digital'; - } } diff --git a/tests/Support/CustomFilter/DigitalHandler.php b/tests/Support/CustomFilter/DigitalHandler.php index 6a5a6b89..033cd33c 100644 --- a/tests/Support/CustomFilter/DigitalHandler.php +++ b/tests/Support/CustomFilter/DigitalHandler.php @@ -5,17 +5,19 @@ namespace Yiisoft\Data\Tests\Support\CustomFilter; use Yiisoft\Arrays\ArrayHelper; +use Yiisoft\Data\Reader\FilterInterface; use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface; final class DigitalHandler implements IterableFilterHandlerInterface { - public function getOperator(): string + public function getFilterClass(): string { - return Digital::getOperator(); + return Digital::class; } - public function match(object|array $item, array $arguments, array $iterableFilterHandlers): bool + public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool { - return ctype_digit((string) ArrayHelper::getValue($item, $arguments[0])); + /** @var Digital $filter */ + return ctype_digit((string) ArrayHelper::getValue($item, $filter->field)); } } diff --git a/tests/Support/CustomFilter/FilterWithoutHandler.php b/tests/Support/CustomFilter/FilterWithoutHandler.php new file mode 100644 index 00000000..e507f0d9 --- /dev/null +++ b/tests/Support/CustomFilter/FilterWithoutHandler.php @@ -0,0 +1,11 @@ + [[]], - 'bool-true' => [true], - 'bool-false' => [false], - 'callback' => [fn () => null], - 'float' => [1.0], - 'int' => [1], - 'null' => [null], - 'object' => [new stdClass()], - ]; - } - public static function invalidFilterDataProvider(): array { return [