yii2

Форк
1
/
ActiveDataFilter.php 
203 строки · 6.4 Кб
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7

8
namespace yii\data;
9

10
/**
11
 * ActiveDataFilter allows composing a filtering condition in a format suitable for [[\yii\db\QueryInterface::where()]].
12
 *
13
 * @see DataFilter
14
 *
15
 * @author Paul Klimov <klimov.paul@gmail.com>
16
 * @since 2.0.13
17
 */
18
class ActiveDataFilter extends DataFilter
19
{
20
    /**
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:
24
     *
25
     * ```php
26
     * [
27
     *     'XOR' => function (string $operator, mixed $condition) {
28
     *         //return array;
29
     *     },
30
     *     'LIKE' => function (string $operator, mixed $condition, string $attribute) {
31
     *         //return array;
32
     *     },
33
     * ]
34
     * ```
35
     */
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',
49
    ];
50
    /**
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.
54
     *
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:
58
     *
59
     * ```php
60
     * [
61
     *     'LIKE' => 'ILIKE'
62
     * ]
63
     * ```
64
     */
65
    public $queryOperatorMap = [];
66

67

68
    /**
69
     * {@inheritdoc}
70
     */
71
    protected function buildInternal()
72
    {
73
        $filter = $this->normalize(false);
74
        if (empty($filter)) {
75
            return [];
76
        }
77

78
        return $this->buildCondition($filter);
79
    }
80

81
    /**
82
     * @param array $condition
83
     * @return array built condition.
84
     */
85
    protected function buildCondition($condition)
86
    {
87
        $parts = [];
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];
93
                } else {
94
                    $callback = $method;
95
                }
96
            } else {
97
                $callback = [$this, 'buildAttributeCondition'];
98
            }
99
            $parts[] = $callback($key, $value);
100
        }
101

102
        if (!empty($parts)) {
103
            if (count($parts) > 1) {
104
                array_unshift($parts, 'AND');
105
            } else {
106
                $parts = array_shift($parts);
107
            }
108
        }
109

110
        return $parts;
111
    }
112

113
    /**
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.
119
     */
120
    protected function buildConjunctionCondition($operator, $condition)
121
    {
122
        if (isset($this->queryOperatorMap[$operator])) {
123
            $operator = $this->queryOperatorMap[$operator];
124
        }
125
        $result = [$operator];
126

127
        foreach ($condition as $part) {
128
            $result[] = $this->buildCondition($part);
129
        }
130

131
        return $result;
132
    }
133

134
    /**
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.
140
     */
141
    protected function buildBlockCondition($operator, $condition)
142
    {
143
        if (isset($this->queryOperatorMap[$operator])) {
144
            $operator = $this->queryOperatorMap[$operator];
145
        }
146
        return [
147
            $operator,
148
            $this->buildCondition($condition),
149
        ];
150
    }
151

152
    /**
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.
157
     */
158
    protected function buildAttributeCondition($attribute, $condition)
159
    {
160
        if (is_array($condition)) {
161
            $parts = [];
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];
168
                        } else {
169
                            $callback = $method;
170
                        }
171
                        $parts[] = $callback($operator, $value, $attribute);
172
                    } else {
173
                        $parts[] = $this->buildOperatorCondition($operator, $value, $attribute);
174
                    }
175
                }
176
            }
177

178
            if (!empty($parts)) {
179
                if (count($parts) > 1) {
180
                    return array_merge(['AND'], $parts);
181
                }
182
                return array_shift($parts);
183
            }
184
        }
185

186
        return [$attribute => $this->filterAttributeValue($attribute, $condition)];
187
    }
188

189
    /**
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.
195
     */
196
    protected function buildOperatorCondition($operator, $condition, $attribute)
197
    {
198
        if (isset($this->queryOperatorMap[$operator])) {
199
            $operator = $this->queryOperatorMap[$operator];
200
        }
201
        return [$operator, $attribute, $this->filterAttributeValue($attribute, $condition)];
202
    }
203
}
204

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.