Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
`PaginatorInterface::getCurrentPageSize()` and `OffsetPaginator::getTotalItems()` (@vjik)
- Chg #165: Simplify `FilterInterface` and `FilterHandlerInterface` (@vjik)
- Chg #166: Remove `EqualsEmpty` filter (@vjik)
- Bug #173: Make `Like` filter case-sensitive (@arogachev)
- New #173: Add `ILike` filter (case-insensitive variation of `Like` filter) (@arogachev)

## 1.0.1 January 25, 2023

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Filter could be composed with:
- `EqualsNull`
- `GreaterThan`
- `GreaterThanOrEqual`
- `ILike`
- `In`
- `LessThan`
- `LessThanOrEqual`
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
],
"require": {
"php": "^8.1",
"ext-mbstring": "*",
"yiisoft/arrays": "^3.0"
},
"require-dev": {
Expand Down
33 changes: 33 additions & 0 deletions src/Reader/Filter/ILike.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Data\Reader\Filter;

use Yiisoft\Data\Reader\FilterInterface;

/**
* `ILike` filter defines a criteria for ensuring field value is like-match to a given value (case-insensitive).
*/
final class ILike implements FilterInterface
{
/**
* @param string $field Name of the field to compare.
* @param string $value Value to like-compare with.
*/
public function __construct(
private readonly string $field,
private readonly string $value,
) {
}

public function getField(): string
{
return $this->field;
}

public function getValue(): string
{
return $this->value;
}
}
2 changes: 1 addition & 1 deletion src/Reader/Filter/Like.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Yiisoft\Data\Reader\FilterInterface;

/**
* `Like` filter defines a criteria for ensuring field value is like-match to a given value.
* `Like` filter defines a criteria for ensuring field value is like-match to a given value (case-sensitive).
*/
final class Like implements FilterInterface
{
Expand Down
33 changes: 33 additions & 0 deletions src/Reader/Iterable/FilterHandler/ILikeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Data\Reader\Iterable\FilterHandler;

use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Data\Reader\Filter\ILike;
use Yiisoft\Data\Reader\FilterInterface;
use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface;

use function is_string;

/**
* `ILike` iterable filter handler ensures that the field value is like-match to a given value (case-insensitive).
*/
final class ILikeHandler implements IterableFilterHandlerInterface
{
public function getFilterClass(): string
{
return ILike::class;
}

public function match(object|array $item, FilterInterface $filter, array $iterableFilterHandlers): bool
{
/** @var ILike $filter */

$itemValue = ArrayHelper::getValue($item, $filter->getField());

/** @infection-ignore-all MBString No suitable test case was found yet. */
return is_string($itemValue) && mb_stripos($itemValue, $filter->getValue()) !== false;
}
}
6 changes: 3 additions & 3 deletions src/Reader/Iterable/FilterHandler/LikeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
use Yiisoft\Data\Reader\Iterable\IterableFilterHandlerInterface;

use function is_string;
use function stripos;

/**
* `Like` iterable filter handler ensures that the field value is like-match to a given value.
* `Like` iterable filter handler ensures that the field value is like-match to a given value (case-sensitive).
*/
final class LikeHandler implements IterableFilterHandlerInterface
{
Expand All @@ -28,6 +27,7 @@ public function match(object|array $item, FilterInterface $filter, array $iterab

$itemValue = ArrayHelper::getValue($item, $filter->getField());

return is_string($itemValue) && stripos($itemValue, $filter->getValue()) !== false;
/** @infection-ignore-all MBString No suitable test case was found yet. */
return is_string($itemValue) && mb_strpos($itemValue, $filter->getValue()) !== false;
}
}
2 changes: 2 additions & 0 deletions src/Reader/Iterable/IterableDataReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Yiisoft\Data\Reader\Iterable\FilterHandler\EqualsNullHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\GreaterThanOrEqualHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\ILikeHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\InHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanHandler;
use Yiisoft\Data\Reader\Iterable\FilterHandler\LessThanOrEqualHandler;
Expand Down Expand Up @@ -73,6 +74,7 @@ public function __construct(private iterable $data)
new EqualsNullHandler(),
new GreaterThanHandler(),
new GreaterThanOrEqualHandler(),
new ILikeHandler(),
new InHandler(),
new LessThanHandler(),
new LessThanOrEqualHandler(),
Expand Down
19 changes: 16 additions & 3 deletions tests/Reader/IterableDataReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Yiisoft\Data\Reader\Filter\Equals;
use Yiisoft\Data\Reader\Filter\GreaterThan;
use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual;
use Yiisoft\Data\Reader\Filter\ILike;
use Yiisoft\Data\Reader\Filter\In;
use Yiisoft\Data\Reader\Filter\LessThan;
use Yiisoft\Data\Reader\Filter\LessThanOrEqual;
Expand Down Expand Up @@ -264,7 +265,19 @@ public function testInFiltering(): void

public function testLikeFiltering(): void
{
$filter = new Like('name', 'agent');
$filter = new Like('name', 'Agent');
$reader = (new IterableDataReader(self::DEFAULT_DATASET))
->withFilter($filter);

$this->assertSame([
2 => self::ITEM_3,
3 => self::ITEM_4,
], $reader->read());
}

public function testILikeFiltering(): void
{
$filter = new ILike('name', 'agent');
$reader = (new IterableDataReader(self::DEFAULT_DATASET))
->withFilter($filter);

Expand Down Expand Up @@ -307,7 +320,7 @@ public function testAllFiltering(): void
{
$filter = new All(
new GreaterThan('id', 3),
new Like('name', 'agent')
new Like('name', 'Agent')
);
$reader = (new IterableDataReader(self::DEFAULT_DATASET))
->withFilter($filter);
Expand Down Expand Up @@ -343,7 +356,7 @@ public function testFilteredCount(): void

$this->assertSame(5, $total, 'Wrong count of elements');

$reader = $reader->withFilter(new Like('name', 'agent'));
$reader = $reader->withFilter(new Like('name', 'Agent'));
$totalAgents = count($reader);
$this->assertSame(2, $totalAgents, 'Wrong count of filtered elements');
}
Expand Down
32 changes: 32 additions & 0 deletions tests/Reader/IterableHandler/ILikeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Data\Tests\Reader\IterableHandler;

use PHPUnit\Framework\Attributes\DataProvider;
use Yiisoft\Data\Reader\Filter\ILike;
use Yiisoft\Data\Reader\Iterable\FilterHandler\ILikeHandler;
use Yiisoft\Data\Tests\TestCase;

final class ILikeTest extends TestCase
{
public static function matchDataProvider(): array
{
return [
[true, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'Great Cat Fighter'],
[true, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'Cat'],
[true, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'cat'],
[false, ['id' => 1, 'value' => 'Great Cat Fighter'], 'id', '1'],
[true, ['id' => 1, 'value' => '🙁🙂🙁'], 'value', '🙂'],
[true, ['id' => 1, 'value' => 'Привет мир'], 'value', ' '],
];
}

#[DataProvider('matchDataProvider')]
public function testMatch(bool $expected, array $item, string $field, string $value): void
{
$processor = new ILikeHandler();
$this->assertSame($expected, $processor->match($item, new ILike($field, $value), []));
}
}
17 changes: 7 additions & 10 deletions tests/Reader/IterableHandler/LikeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,19 @@ final class LikeTest extends TestCase
public static function matchDataProvider(): array
{
return [
[true, 'value', 'Great Cat Fighter'],
[true, 'value', 'Cat'],
[false, 'id', '1'],
[true, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'Great Cat Fighter'],
[true, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'Cat'],
[false, ['id' => 1, 'value' => 'Great Cat Fighter'], 'value', 'cat'],
[false, ['id' => 1, 'value' => 'Great Cat Fighter'], 'id', '1'],
[true, ['id' => 1, 'value' => '🙁🙂🙁'], 'value', '🙂'],
[true, ['id' => 1, 'value' => 'Привет мир'], 'value', ' '],
];
}

#[DataProvider('matchDataProvider')]
public function testMatch(bool $expected, string $field, string $value): void
public function testMatch(bool $expected, array $item, string $field, string $value): void
{
$processor = new LikeHandler();

$item = [
'id' => 1,
'value' => 'Great Cat Fighter',
];

$this->assertSame($expected, $processor->match($item, new Like($field, $value), []));
}
}