diff --git a/src/Column.php b/src/Column.php index ce0156f..3b83a1d 100644 --- a/src/Column.php +++ b/src/Column.php @@ -50,7 +50,19 @@ class Column * Custom filter * @var \Closure */ - public $customFilter; + public $customIndividualFilter; + + /** + * Custom filter + * @var \Closure + */ + public $customGlobalFilter; + + /** + * + * @var string + */ + public $customFilterType; /** * Column constructor. @@ -82,7 +94,7 @@ public function value($row): string * Set visibility of the column. * @param bool $searchable */ - public function hide($searchable = false): void + public function hide(bool $searchable = false): void { $this->hidden = true; $this->forceSearch = $searchable; @@ -91,9 +103,17 @@ public function hide($searchable = false): void /** * @return bool */ - public function hasFilter(): bool + public function hasCustomIndividualFilter(): bool + { + return $this->customIndividualFilter instanceof \Closure; + } + + /** + * @return bool + */ + public function hasCustomGlobalFilter(): bool { - return $this->customFilter instanceof \Closure; + return $this->customGlobalFilter instanceof \Closure; } /** diff --git a/src/CustomFilterType.php b/src/CustomFilterType.php new file mode 100644 index 0000000..61b65a8 --- /dev/null +++ b/src/CustomFilterType.php @@ -0,0 +1,10 @@ +exactMatch; + } + + /** + * @param bool $value + * @return void + */ + public function setExactMatch(bool $value) + { + $this->exactMatch = $value; + } + /** * @param Query $query * @param Column $column - * @param $word + * @param string $word * @return string */ public function makeLikeString(Query $query, Column $column, string $word) @@ -75,6 +94,17 @@ public function makeLikeString(Query $query, Column $column, string $word) return $column->name.' LIKE '.$this->escape('%'.$word.'%', $query); } + /** + * @param Query $query + * @param Column $column + * @param string $word + * @return string + */ + public function makeEqualString(Query $query, Column $column, string $word) + { + return $column->name.' = '.$this->escape( $word, $query); + } + /** * @param array $o * @return string diff --git a/src/DB/DatabaseInterface.php b/src/DB/DatabaseInterface.php index 183701a..c92a551 100644 --- a/src/DB/DatabaseInterface.php +++ b/src/DB/DatabaseInterface.php @@ -54,6 +54,17 @@ public function makeDistinctQueryString(Query $query, string $column); */ public function makeWhereString(array $filter); + /** + * @param bool $value + * @return void + */ + public function setExactMatch(bool $value); + + /** + * @return mixed + */ + public function isExactMatch(); + /** * @param Query $query * @param Column $column @@ -62,6 +73,15 @@ public function makeWhereString(array $filter); */ public function makeLikeString(Query $query, Column $column, string $word); + + /** + * @param Query $query + * @param Column $column + * @param string $word + * @return mixed + */ + public function makeEqualString(Query $query, Column $column, string $word); + /** * @param array $o * @return mixed diff --git a/src/Datatables.php b/src/Datatables.php index 19120a3..5cafca9 100644 --- a/src/Datatables.php +++ b/src/Datatables.php @@ -110,10 +110,18 @@ public function edit($column, Closure $closure): Datatables * @param Closure $closure * @return Datatables */ - public function filter($column, Closure $closure): Datatables + public function filter($column, Closure $closure, $filterType = CustomFilterType::INDIVIDUAL): Datatables { $column = $this->columns->getByName($column); - $column->customFilter = $closure; + $column->customIndividualFilter = $closure; + + $column->customFilterType = $filterType; + if ($filterType !== CustomFilterType::GLOBALLY) { + $column->customIndividualFilter = $closure; + } + if ($filterType !== CustomFilterType::INDIVIDUAL) { + $column->customGlobalFilter = $closure; + } return $this; } @@ -130,6 +138,17 @@ public function escape($key, $value): Datatables return $this; } + /** + * @param bool $value + * @return Datatables + */ + public function forceExactMatch(bool $value): Datatables + { + $this->db->setExactMatch($value); + + return $this; + } + /** * @param $name * @return Datatables diff --git a/src/FilterHelper.php b/src/FilterHelper.php index 6a5ab3e..d7b0f10 100644 --- a/src/FilterHelper.php +++ b/src/FilterHelper.php @@ -24,17 +24,24 @@ class FilterHelper */ private $db; + /** + * @var string|null + */ + private $searchValue; + + /** * FilterHelper constructor. * @param Query $query * @param Column $column * @param DatabaseInterface $db */ - public function __construct(Query $query, Column $column, DatabaseInterface $db) + public function __construct(Query $query, Column $column, DatabaseInterface $db, $searchValue = null) { $this->query = $query; $this->column = $column; $this->db = $db; + $this->searchValue = $searchValue; } /** @@ -51,7 +58,7 @@ public function escape($value): string */ public function searchValue(): string { - return $this->column->searchValue(); + return $this->searchValue ?? $this->column->searchValue(); } /** @@ -59,6 +66,10 @@ public function searchValue(): string */ public function defaultFilter(): string { + if ($this->db->isExactMatch()) { + return $this->db->makeEqualString($this->query, $this->column, $this->searchValue()); + } + return $this->db->makeLikeString($this->query, $this->column, $this->searchValue()); } @@ -116,4 +127,4 @@ public function lessThan($value): string return $this->column->name.' <= '.$this->escape($value); } -} \ No newline at end of file +} diff --git a/src/Iterators/IndividualSearchableColumns.php b/src/Iterators/IndividualSearchableColumns.php index 69ccf08..80dfc7b 100644 --- a/src/Iterators/IndividualSearchableColumns.php +++ b/src/Iterators/IndividualSearchableColumns.php @@ -17,6 +17,6 @@ class IndividualSearchableColumns extends FilterIterator */ public function accept(): bool { - return $this->current()->searchValue() !== '' || $this->current()->hasFilter(); + return $this->current()->searchValue() !== '' || $this->current()->hasCustomIndividualFilter(); } -} \ No newline at end of file +} diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 8862f0c..b83f9a6 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -231,9 +231,11 @@ protected function filterGlobal(Query $query): string $look = []; foreach ($columns as $column) { - $look[] = $this->db->makeLikeString($query, $column, $word); + $look[] = $this->columnGlobalFilter($column, new FilterHelper($query, $column, $this->db, $word)); } + $look = array_filter($look); + $search[] = '('.implode(' OR ', $look).')'; } @@ -250,7 +252,7 @@ protected function filterIndividual(Query $query): string $look = []; foreach ($columns as $column) { - $look[] = $this->columnFilter($column, new FilterHelper($query, $column, $this->db)); + $look[] = $this->columnIndividualFilter($column, new FilterHelper($query, $column, $this->db)); } $look = array_filter($look); @@ -319,10 +321,24 @@ public function defaultOrder(): string * @param FilterHelper $helper * @return string */ - public function columnFilter(Column $column, FilterHelper $helper): string + public function columnIndividualFilter(Column $column, FilterHelper $helper): string + { + if ($column->hasCustomIndividualFilter()) { + return $column->customIndividualFilter->call($helper) ?? $helper->defaultFilter(); + } + + return $helper->defaultFilter(); + } + + /** + * @param Column $column + * @param FilterHelper $helper + * @return string + */ + public function columnGlobalFilter(Column $column, FilterHelper $helper): string { - if ($column->hasFilter()) { - return $column->customFilter->call($helper) ?? $helper->defaultFilter(); + if ($column->hasCustomGlobalFilter()) { + return $column->customGlobalFilter->call($helper) ?? $helper->defaultFilter(); } return $helper->defaultFilter();