Skip to content

Commit c03c947

Browse files
authored
Add Stringable type support to filter values (#237)
1 parent fcdfcee commit c03c947

File tree

12 files changed

+67
-23
lines changed

12 files changed

+67
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 2.0.0 under development
44

5+
- New #237: Add `Stringable` type support to filter values (@vjik)
56
- New #150: Extract `withLimit()` from `ReadableDataInterface` into `LimitableDataInterface` (@vjik)
67
- Enh #150: `PaginatorInterface` now extends `ReadableDataInterface` (@vjik)
78
- Chg #151: Rename `isRequired()` method in `PaginatorInterface` to `isPaginationRequired()` (@vjik)

src/Reader/Filter/Between.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Data\Reader\Filter;
66

77
use DateTimeInterface;
8+
use Stringable;
89
use Yiisoft\Data\Reader\FilterInterface;
910

1011
/**
@@ -15,13 +16,13 @@ final class Between implements FilterInterface
1516
{
1617
/**
1718
* @param string $field Name of the field to compare.
18-
* @param bool|DateTimeInterface|float|int|string $minValue Minimal field value.
19-
* @param bool|DateTimeInterface|float|int|string $maxValue Maximal field value.
19+
* @param bool|DateTimeInterface|float|int|string|Stringable $minValue Minimal field value.
20+
* @param bool|DateTimeInterface|float|int|string|Stringable $maxValue Maximal field value.
2021
*/
2122
public function __construct(
2223
public readonly string $field,
23-
public readonly bool|DateTimeInterface|float|int|string $minValue,
24-
public readonly bool|DateTimeInterface|float|int|string $maxValue
24+
public readonly bool|DateTimeInterface|float|int|string|Stringable $minValue,
25+
public readonly bool|DateTimeInterface|float|int|string|Stringable $maxValue
2526
) {
2627
}
2728
}

src/Reader/Filter/Compare.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Data\Reader\Filter;
66

77
use DateTimeInterface;
8+
use Stringable;
89
use Yiisoft\Data\Reader\FilterInterface;
910

1011
/**
@@ -14,18 +15,18 @@ abstract class Compare implements FilterInterface
1415
{
1516
/**
1617
* @param string $field Name of the field to compare.
17-
* @param bool|DateTimeInterface|float|int|string $value Value to compare to.
18+
* @param bool|DateTimeInterface|float|int|string|Stringable $value Value to compare to.
1819
*/
1920
final public function __construct(
2021
public readonly string $field,
21-
public readonly bool|DateTimeInterface|float|int|string $value,
22+
public readonly bool|DateTimeInterface|float|int|string|Stringable $value,
2223
) {
2324
}
2425

2526
/**
26-
* @param bool|DateTimeInterface|float|int|string $value Value to compare to.
27+
* @param bool|DateTimeInterface|float|int|string|Stringable $value Value to compare to.
2728
*/
28-
final public function withValue(bool|DateTimeInterface|float|int|string $value): static
29+
final public function withValue(bool|DateTimeInterface|float|int|string|Stringable $value): static
2930
{
3031
return new static($this->field, $value);
3132
}

src/Reader/Filter/In.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Data\Reader\Filter;
66

77
use InvalidArgumentException;
8+
use Stringable;
89
use Yiisoft\Data\Reader\FilterInterface;
910

1011
use function is_scalar;
@@ -17,11 +18,11 @@ final class In implements FilterInterface
1718
{
1819
/**
1920
* @param string $field Name of the field to compare.
20-
* @param bool[]|float[]|int[]|string[] $values Values to check against.
21+
* @param bool[]|float[]|int[]|string[]|Stringable[] $values Values to check against.
2122
*/
2223
public function __construct(
2324
public readonly string $field,
24-
/** @var bool[]|float[]|int[]|string[] Values to check against. */
25+
/** @var bool[]|float[]|int[]|string[]|Stringable[] Values to check against. */
2526
public readonly array $values
2627
) {
2728
$this->assertValues($values);
@@ -30,10 +31,10 @@ public function __construct(
3031
private function assertValues(array $values): void
3132
{
3233
foreach ($values as $value) {
33-
if (!is_scalar($value)) {
34+
if (!is_scalar($value) && !$value instanceof Stringable) {
3435
throw new InvalidArgumentException(
3536
sprintf(
36-
'The value should be scalar. "%s" is received.',
37+
'The value should be scalar or Stringable. "%s" is received.',
3738
get_debug_type($value),
3839
)
3940
);

src/Reader/Filter/Like.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Yiisoft\Data\Reader\Filter;
66

7+
use Stringable;
78
use Yiisoft\Data\Reader\FilterInterface;
89

910
/**
@@ -13,7 +14,7 @@ final class Like implements FilterInterface
1314
{
1415
/**
1516
* @param string $field Name of the field to compare.
16-
* @param string $value Value to like-compare with.
17+
* @param string|Stringable $value Value to like-compare with.
1718
* @param bool|null $caseSensitive Whether search must be case-sensitive:
1819
*
1920
* - `null` - depends on implementation;
@@ -23,7 +24,7 @@ final class Like implements FilterInterface
2324
*/
2425
public function __construct(
2526
public readonly string $field,
26-
public readonly string $value,
27+
public readonly string|Stringable $value,
2728
public readonly ?bool $caseSensitive = null,
2829
public readonly LikeMode $mode = LikeMode::Contains,
2930
) {

src/Reader/Iterable/FilterHandler/LikeHandler.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@ public function match(object|array $item, FilterInterface $filter, Context $cont
3131
return false;
3232
}
3333

34-
if ($filter->value === '') {
34+
$searchValue = (string) $filter->value;
35+
if ($searchValue === '') {
3536
return true;
3637
}
3738

3839
return match ($filter->mode) {
39-
LikeMode::Contains => $this->matchContains($itemValue, $filter->value, $filter->caseSensitive),
40-
LikeMode::StartsWith => $this->matchStartsWith($itemValue, $filter->value, $filter->caseSensitive),
41-
LikeMode::EndsWith => $this->matchEndsWith($itemValue, $filter->value, $filter->caseSensitive),
40+
LikeMode::Contains => $this->matchContains($itemValue, $searchValue, $filter->caseSensitive),
41+
LikeMode::StartsWith => $this->matchStartsWith($itemValue, $searchValue, $filter->caseSensitive),
42+
LikeMode::EndsWith => $this->matchEndsWith($itemValue, $searchValue, $filter->caseSensitive),
4243
};
4344
}
4445

tests/Common/Reader/ReaderWithFilter/BaseReaderWithBetweenTestCase.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Yiisoft\Data\Reader\Filter\Between;
1010
use Yiisoft\Data\Tests\Common\Reader\BaseReaderTestCase;
11+
use Yiisoft\Data\Tests\Support\StringableValue;
1112

1213
abstract class BaseReaderWithBetweenTestCase extends BaseReaderTestCase
1314
{
1415
public static function dataWithReader(): iterable
1516
{
17+
yield 'stringable' => [new Between('email', new StringableValue('ta'), new StringableValue('tz')), [4, 5]];
1618
yield 'float' => [new Between('balance', 10.25, 100.0), [1, 3, 5]];
1719
yield 'datetime' => [new Between('born_at', new DateTimeImmutable('1989-01-01'), new DateTimeImmutable('1991-01-01')), [5]];
1820
yield 'datetime 2' => [new Between('born_at', new DateTimeImmutable('1990-01-02'), new DateTimeImmutable('1990-01-03')), []];

tests/Common/Reader/ReaderWithFilter/BaseReaderWithEqualsTestCase.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Yiisoft\Data\Reader\Filter\Equals;
1010
use Yiisoft\Data\Tests\Common\Reader\BaseReaderTestCase;
11+
use Yiisoft\Data\Tests\Support\StringableValue;
1112

1213
abstract class BaseReaderWithEqualsTestCase extends BaseReaderTestCase
1314
{
@@ -16,6 +17,7 @@ public static function dataWithReader(): iterable
1617
yield 'integer' => [new Equals('number', 2), [2]];
1718
yield 'float' => [new Equals('balance', 10.25), [1]];
1819
yield 'string' => [new Equals('email', 'the@best'), [4]];
20+
yield 'stringable' => [new Equals('email', new StringableValue('the@best')), [4]];
1921
yield 'datetime' => [new Equals('born_at', new DateTimeImmutable('1990-01-01')), [5]];
2022
}
2123

tests/Common/Reader/ReaderWithFilter/BaseReaderWithInTestCase.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,26 @@
44

55
namespace Yiisoft\Data\Tests\Common\Reader\ReaderWithFilter;
66

7+
use PHPUnit\Framework\Attributes\DataProvider;
78
use Yiisoft\Data\Reader\Filter\In;
89
use Yiisoft\Data\Tests\Common\Reader\BaseReaderTestCase;
10+
use Yiisoft\Data\Tests\Support\StringableValue;
911

1012
abstract class BaseReaderWithInTestCase extends BaseReaderTestCase
1113
{
12-
public function testWithReader(): void
14+
public static function dataWithReader(): iterable
1315
{
14-
$reader = $this->getReader()->withFilter(new In('number', [2, 3]));
15-
$this->assertFixtures([1, 2], $reader->read());
16+
yield 'int' => [new In('number', [2, 3]), [1, 2]];
17+
yield 'stringable' => [
18+
new In('email', [new StringableValue('seed@beat'), new StringableValue('the@best')]),
19+
[2, 3],
20+
];
21+
}
22+
23+
#[DataProvider('dataWithReader')]
24+
public function testWithReader(In $filter, array $expected): void
25+
{
26+
$reader = $this->getReader()->withFilter($filter);
27+
$this->assertFixtures($expected, $reader->read());
1628
}
1729
}

tests/Common/Reader/ReaderWithFilter/BaseReaderWithLikeTestCase.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Yiisoft\Data\Reader\Filter\Like;
99
use Yiisoft\Data\Reader\Filter\LikeMode;
1010
use Yiisoft\Data\Tests\Common\Reader\BaseReaderTestCase;
11+
use Yiisoft\Data\Tests\Support\StringableValue;
1112

1213
abstract class BaseReaderWithLikeTestCase extends BaseReaderTestCase
1314
{
@@ -24,13 +25,14 @@ public static function dataWithReader(): array
2425
'wildcard is not supported, %' => ['email', '%st', null, []],
2526
'wildcard is not supported, _' => ['email', '____@___t', null, []],
2627
'search: contains backslash' => ['email', 'foo@bar\\baz', null, [0]],
28+
'stringable' => ['email', new StringableValue('seed@'), null, [2]],
2729
];
2830
}
2931

3032
#[DataProvider('dataWithReader')]
3133
public function testWithReader(
3234
string $field,
33-
string $value,
35+
mixed $value,
3436
bool|null $caseSensitive,
3537
array $expectedFixtureIndexes,
3638
): void {

0 commit comments

Comments
 (0)