Skip to content

Commit

Permalink
feat: add conjunction search if text filter
Browse files Browse the repository at this point in the history
  • Loading branch information
martenb committed Oct 14, 2024
1 parent 0105ca3 commit 3e4becc
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 12 deletions.
7 changes: 7 additions & 0 deletions .docs/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ $grid->addFilterText('name', 'Name')
->setSplitWordsSearch(false);
```

If you need to find rows, that contains "foo" and "bar" (not just one of them), you can use `setConjunctionSearch()`.

```php
$grid->addFilterText('name', 'Name')
->setConjunctionSearch();
```

## FilterSelect

`FilterSelect` has one more parameter - options:
Expand Down
12 changes: 11 additions & 1 deletion src/DataSource/ArrayDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,21 @@ protected function applyFilter(mixed $row, Filter $filter): mixed

$row_value = strtolower(Strings::toAscii((string) $row[$column]));

$found = [];

foreach ($words as $word) {
if (str_contains($row_value, strtolower(Strings::toAscii($word)))) {
return $row;
if ($filter instanceof FilterText && !$filter->hasConjunctionSearch()) {
return $row;
} else {
$found[] = true;
}
}
}

if (count($found) === count($words)) {
return $row;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/DibiFluentDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (count($or) > 1) {
$this->dataSource->where('(%or)', $or);
$this->dataSource->where($filter->hasConjunctionSearch() ? '(%and)' : '(%or)', $or);
} else {
$this->dataSource->where($or);
}
Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/DibiFluentMssqlDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (count($or) > 1) {
$this->dataSource->where('(%or)', $or);
$this->dataSource->where($filter->hasConjunctionSearch() ? '(%and)' : '(%or)', $or);
} else {
$this->dataSource->where($or);
}
Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/DibiFluentPostgreDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (count($or) > 1) {
$this->dataSource->where('(%or)', $or);
$this->dataSource->where($filter->hasConjunctionSearch() ? '(%and)' : '(%or)', $or);
} else {
$this->dataSource->where($or);
}
Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/DoctrineCollectionDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ protected function applyFilterText(FilterText $filter): void
}
}

$expr = call_user_func_array([Criteria::expr(), 'orX'], $exprs);
$expr = call_user_func_array([Criteria::expr(), $filter->hasConjunctionSearch() ? 'andX' : 'orX'], $exprs);
$this->criteria->andWhere($expr);
}

Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/DoctrineDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ protected function applyFilterText(FilterText $filter): void
}
}

$or = call_user_func_array([$this->dataSource->expr(), 'orX'], $exprs);
$or = call_user_func_array([$this->dataSource->expr(), $filter->hasConjunctionSearch() ? 'andX' : 'orX'], $exprs);

$this->dataSource->andWhere($or);
}
Expand Down
12 changes: 7 additions & 5 deletions src/DataSource/NetteDatabaseTableDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,31 +194,33 @@ protected function applyFilterText(FilterText $filter): void
$bigOrArgs = [];
$condition = $filter->getCondition();

$operator = $filter->hasConjunctionSearch() ? 'AND' : 'OR';

foreach ($condition as $column => $value) {
$like = '(';
$args = [];

if ($filter->isExactSearch()) {
$like .= sprintf('%s = ? OR ', $column);
$like .= sprintf('%s = ? %s ', $column, $operator);
$args[] = sprintf('%s', $value);
} else {
$words = $filter->hasSplitWordsSearch() === false ? [$value] : explode(' ', $value);

foreach ($words as $word) {
$like .= sprintf('%s LIKE ? OR ', $column);
$like .= sprintf('%s LIKE ? %s ', $column, $operator);
$args[] = sprintf('%%%s%%', $word);
}
}

$like = substr($like, 0, strlen($like) - 4) . ')';
$like = substr($like, 0, strlen($like) - (strlen($operator) + 2)) . ')';

$or[] = $like;
$bigOr .= sprintf('%s OR ', $like);
$bigOr .= sprintf('%s %s ', $like, $operator);
$bigOrArgs = [...$bigOrArgs, ...$args];
}

if (count($or) > 1) {
$bigOr = substr($bigOr, 0, strlen($bigOr) - 4) . ')';
$bigOr = substr($bigOr, 0, strlen($bigOr) - (strlen($operator) + 2)) . ')';

$query = [...[$bigOr], ...$bigOrArgs];

Expand Down
2 changes: 1 addition & 1 deletion src/DataSource/NextrasDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ protected function applyFilterRange(FilterRange $filter): void
protected function applyFilterText(FilterText $filter): void
{
$conditions = [
ICollection::OR,
$filter->hasConjunctionSearch() ? ICollection::AND : ICollection::OR,
];

foreach ($filter->getCondition() as $column => $value) {
Expand Down
12 changes: 12 additions & 0 deletions src/Filter/FilterText.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class FilterText extends Filter

protected bool $splitWordsSearch = true;

protected bool $conjunctionSearch = false;

/**
* @param array|string[] $columns
*/
Expand Down Expand Up @@ -84,4 +86,14 @@ public function hasSplitWordsSearch(): bool
return $this->splitWordsSearch;
}

public function setConjunctionSearch(bool $conjunctionSearch = true): void
{
$this->conjunctionSearch = $conjunctionSearch;
}

public function hasConjunctionSearch(): bool
{
return $this->conjunctionSearch;
}

}
12 changes: 12 additions & 0 deletions tests/Cases/DataSources/BaseDataSourceTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ abstract class BaseDataSourceTest extends TestCase

$this->ds->filter([$filter]);
Assert::same(2, $this->ds->getCount());

$filter->setConjunctionSearch();

$this->ds->filter([$filter]);
Assert::same(1, $this->ds->getCount());
}

public function testGetData(): void
Expand All @@ -59,6 +64,13 @@ abstract class BaseDataSourceTest extends TestCase
$this->data[0],
$this->data[5],
], $this->getActualResultAsArray());

$filter->setConjunctionSearch();

$this->ds->filter([$filter]);
Assert::equal([
$this->data[5],
], $this->getActualResultAsArray());
}

public function testFilterMultipleColumns(): void
Expand Down

0 comments on commit 3e4becc

Please sign in to comment.