3
* @link https://www.yiiframework.com/
4
* @copyright Copyright (c) 2008 Yii Software LLC
5
* @license https://www.yiiframework.com/license/
11
* ActiveDataFilter allows composing a filtering condition in a format suitable for [[\yii\db\QueryInterface::where()]].
15
* @author Paul Klimov <klimov.paul@gmail.com>
18
class ActiveDataFilter extends DataFilter
21
* @var array maps filtering condition keywords to build methods.
22
* These methods are used by [[buildCondition()]] to build the actual filtering conditions.
23
* Particular condition builder can be specified using a PHP callback. For example:
27
* 'XOR' => function (string $operator, mixed $condition) {
30
* 'LIKE' => function (string $operator, mixed $condition, string $attribute) {
36
public $conditionBuilders = [
37
'AND' => 'buildConjunctionCondition',
38
'OR' => 'buildConjunctionCondition',
39
'NOT' => 'buildBlockCondition',
40
'<' => 'buildOperatorCondition',
41
'>' => 'buildOperatorCondition',
42
'<=' => 'buildOperatorCondition',
43
'>=' => 'buildOperatorCondition',
44
'=' => 'buildOperatorCondition',
45
'!=' => 'buildOperatorCondition',
46
'IN' => 'buildOperatorCondition',
47
'NOT IN' => 'buildOperatorCondition',
48
'LIKE' => 'buildOperatorCondition',
51
* @var array map filtering operators to operators used in [[\yii\db\QueryInterface::where()]].
52
* The format is: `[filterOperator => queryOperator]`.
53
* If particular operator keyword does not appear in the map, it will be used as is.
55
* Usually the map can be left empty as filter operator names are consistent with the ones
56
* used in [[\yii\db\QueryInterface::where()]]. However, you may want to adjust it in some special cases.
57
* For example, when using PostgreSQL you may want to setup the following map:
65
public $queryOperatorMap = [];
71
protected function buildInternal()
73
$filter = $this->normalize(false);
78
return $this->buildCondition($filter);
82
* @param array $condition
83
* @return array built condition.
85
protected function buildCondition($condition)
88
foreach ($condition as $key => $value) {
89
if (isset($this->conditionBuilders[$key])) {
90
$method = $this->conditionBuilders[$key];
91
if (is_string($method)) {
92
$callback = [$this, $method];
97
$callback = [$this, 'buildAttributeCondition'];
99
$parts[] = $callback($key, $value);
102
if (!empty($parts)) {
103
if (count($parts) > 1) {
104
array_unshift($parts, 'AND');
106
$parts = array_shift($parts);
114
* Builds conjunction condition, which consists of multiple independent ones.
115
* It covers such operators as `and` and `or`.
116
* @param string $operator operator keyword.
117
* @param mixed $condition raw condition.
118
* @return array actual condition.
120
protected function buildConjunctionCondition($operator, $condition)
122
if (isset($this->queryOperatorMap[$operator])) {
123
$operator = $this->queryOperatorMap[$operator];
125
$result = [$operator];
127
foreach ($condition as $part) {
128
$result[] = $this->buildCondition($part);
135
* Builds block condition, which consists of a single condition.
136
* It covers such operators as `not`.
137
* @param string $operator operator keyword.
138
* @param mixed $condition raw condition.
139
* @return array actual condition.
141
protected function buildBlockCondition($operator, $condition)
143
if (isset($this->queryOperatorMap[$operator])) {
144
$operator = $this->queryOperatorMap[$operator];
148
$this->buildCondition($condition),
153
* Builds search condition for a particular attribute.
154
* @param string $attribute search attribute name.
155
* @param mixed $condition search condition.
156
* @return array actual condition.
158
protected function buildAttributeCondition($attribute, $condition)
160
if (is_array($condition)) {
162
foreach ($condition as $operator => $value) {
163
if (isset($this->operatorTypes[$operator])) {
164
if (isset($this->conditionBuilders[$operator])) {
165
$method = $this->conditionBuilders[$operator];
166
if (is_string($method)) {
167
$callback = [$this, $method];
171
$parts[] = $callback($operator, $value, $attribute);
173
$parts[] = $this->buildOperatorCondition($operator, $value, $attribute);
178
if (!empty($parts)) {
179
if (count($parts) > 1) {
180
return array_merge(['AND'], $parts);
182
return array_shift($parts);
186
return [$attribute => $this->filterAttributeValue($attribute, $condition)];
190
* Builds an operator condition.
191
* @param string $operator operator keyword.
192
* @param mixed $condition attribute condition.
193
* @param string $attribute attribute name.
194
* @return array actual condition.
196
protected function buildOperatorCondition($operator, $condition, $attribute)
198
if (isset($this->queryOperatorMap[$operator])) {
199
$operator = $this->queryOperatorMap[$operator];
201
return [$operator, $attribute, $this->filterAttributeValue($attribute, $condition)];