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 1a63088 commit bb78977
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 15 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 @@ -209,11 +209,21 @@ protected function applyFilter($row, Filter $filter)

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

$found = [];

foreach ($words as $word) {
if (strpos($row_value, strtolower(Strings::toAscii($word))) !== false) {
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 @@ -215,7 +215,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (sizeof($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 @@ -136,7 +136,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (sizeof($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 @@ -33,7 +33,7 @@ protected function applyFilterText(FilterText $filter): void
}

if (sizeof($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 @@ -226,7 +226,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 @@ -319,7 +319,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 @@ -224,31 +224,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 .= "$column = ? OR ";
$like .= "$column = ? $operator ";
$args[] = "$value";
} else {
$words = $filter->hasSplitWordsSearch() === false ? [$value] : explode(' ', $value);

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

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

$or[] = $like;
$bigOr .= "$like OR ";
$bigOr .= "$like $operator ";
$bigOrArgs = array_merge($bigOrArgs, $args);
}

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

$query = array_merge([$bigOr], $bigOrArgs);

Expand Down
9 changes: 5 additions & 4 deletions src/DataSource/NextrasDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ protected function applyFilterText(FilterText $filter): void
// native handling with LikeFunction in v4
if (class_exists(LikeExpression::class)) {
$conditions = [
ICollection::OR,
$filter->hasConjunctionSearch() ? ICollection::AND : ICollection::OR,
];

foreach ($filter->getCondition() as $column => $value) {
Expand Down Expand Up @@ -272,10 +272,11 @@ protected function applyFilterText(FilterText $filter): void
$condition = $filter->getCondition();
$expr = '(';
$params = [];
$operator = $filter->hasConjunctionSearch() ? 'AND' : 'OR';

foreach ($condition as $column => $value) {
if ($filter->isExactSearch()) {
$expr .= '%column = %s OR ';
$expr .= "%column = %s $operator ";
$params[] = $column;
$params[] = "$value";

Expand All @@ -285,13 +286,13 @@ protected function applyFilterText(FilterText $filter): void
$words = $filter->hasSplitWordsSearch() === false ? [$value] : explode(' ', $value);

foreach ($words as $word) {
$expr .= '%column LIKE %s OR ';
$expr .= "%column LIKE %s $operator ";
$params[] = $column;
$params[] = "%$word%";
}
}

$expr = preg_replace('/ OR $/', ')', $expr);
$expr = preg_replace("/ $operator $/", ')', $expr);

array_unshift($params, $expr);

Expand Down
18 changes: 18 additions & 0 deletions src/Filter/FilterText.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class FilterText extends Filter
*/
protected $splitWordsSearch = true;

/**
* @var bool
*/
protected $conjunctionSearch = false;

/**
* @var array|string[]
*/
Expand Down Expand Up @@ -110,4 +115,17 @@ 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 @@ -47,6 +47,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 @@ -65,6 +70,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 bb78977

Please sign in to comment.