| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- <?php
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\data;
- /**
- * ActiveDataFilter allows composing a filtering condition in a format suitable for [[\yii\db\QueryInterface::where()]].
- *
- * @see DataFilter
- *
- * @author Paul Klimov <klimov.paul@gmail.com>
- * @since 2.0.13
- */
- class ActiveDataFilter extends DataFilter
- {
- /**
- * @var array maps filtering condition keywords to build methods.
- * These methods are used by [[buildCondition()]] to build the actual filtering conditions.
- * Particular condition builder can be specified using a PHP callback. For example:
- *
- * ```php
- * [
- * 'XOR' => function (string $operator, mixed $condition) {
- * //return array;
- * },
- * 'LIKE' => function (string $operator, mixed $condition, string $attribute) {
- * //return array;
- * },
- * ]
- * ```
- */
- public $conditionBuilders = [
- 'AND' => 'buildConjunctionCondition',
- 'OR' => 'buildConjunctionCondition',
- 'NOT' => 'buildBlockCondition',
- '<' => 'buildOperatorCondition',
- '>' => 'buildOperatorCondition',
- '<=' => 'buildOperatorCondition',
- '>=' => 'buildOperatorCondition',
- '=' => 'buildOperatorCondition',
- '!=' => 'buildOperatorCondition',
- 'IN' => 'buildOperatorCondition',
- 'NOT IN' => 'buildOperatorCondition',
- 'LIKE' => 'buildOperatorCondition',
- ];
- /**
- * @var array map filtering operators to operators used in [[\yii\db\QueryInterface::where()]].
- * The format is: `[filterOperator => queryOperator]`.
- * If particular operator keyword does not appear in the map, it will be used as is.
- *
- * Usually the map can be left empty as filter operator names are consistent with the ones
- * used in [[\yii\db\QueryInterface::where()]]. However, you may want to adjust it in some special cases.
- * For example, when using PosgreSQL you may want to setup the following map:
- *
- * ```php
- * [
- * 'LIKE' => 'ILIKE'
- * ]
- * ```
- */
- public $queryOperatorMap = [];
- /**
- * {@inheritdoc}
- */
- protected function buildInternal()
- {
- $filter = $this->normalize(false);
- if (empty($filter)) {
- return [];
- }
- return $this->buildCondition($filter);
- }
- /**
- * @param array $condition
- * @return array built condition.
- */
- protected function buildCondition($condition)
- {
- $parts = [];
- foreach ($condition as $key => $value) {
- if (isset($this->conditionBuilders[$key])) {
- $method = $this->conditionBuilders[$key];
- if (is_string($method)) {
- $callback = [$this, $method];
- } else {
- $callback = $method;
- }
- } else {
- $callback = [$this, 'buildAttributeCondition'];
- }
- $parts[] = $callback($key, $value);
- }
- if (!empty($parts)) {
- if (count($parts) > 1) {
- $parts = array_merge(['AND'], $parts);
- } else {
- $parts = array_shift($parts);
- }
- }
- return $parts;
- }
- /**
- * Builds conjunction condition, which consists of multiple independent ones.
- * It covers such operators as `and` and `or`.
- * @param string $operator operator keyword.
- * @param mixed $condition raw condition.
- * @return array actual condition.
- */
- protected function buildConjunctionCondition($operator, $condition)
- {
- if (isset($this->queryOperatorMap[$operator])) {
- $operator = $this->queryOperatorMap[$operator];
- }
- $result = [$operator];
- foreach ($condition as $part) {
- $result[] = $this->buildCondition($part);
- }
- return $result;
- }
- /**
- * Builds block condition, which consists of a single condition.
- * It covers such operators as `not`.
- * @param string $operator operator keyword.
- * @param mixed $condition raw condition.
- * @return array actual condition.
- */
- protected function buildBlockCondition($operator, $condition)
- {
- if (isset($this->queryOperatorMap[$operator])) {
- $operator = $this->queryOperatorMap[$operator];
- }
- return [
- $operator,
- $this->buildCondition($condition),
- ];
- }
- /**
- * Builds search condition for a particular attribute.
- * @param string $attribute search attribute name.
- * @param mixed $condition search condition.
- * @return array actual condition.
- */
- protected function buildAttributeCondition($attribute, $condition)
- {
- if (is_array($condition)) {
- $parts = [];
- foreach ($condition as $operator => $value) {
- if (isset($this->operatorTypes[$operator])) {
- if (isset($this->conditionBuilders[$operator])) {
- $method = $this->conditionBuilders[$operator];
- if (is_string($method)) {
- $callback = [$this, $method];
- } else {
- $callback = $method;
- }
- $parts[] = $callback($operator, $value, $attribute);
- } else {
- $parts[] = $this->buildOperatorCondition($operator, $value, $attribute);
- }
- }
- }
- if (!empty($parts)) {
- if (count($parts) > 1) {
- return array_merge(['AND'], $parts);
- }
- return array_shift($parts);
- }
- }
- return [$attribute => $this->filterAttributeValue($attribute, $condition)];
- }
- /**
- * Builds an operator condition.
- * @param string $operator operator keyword.
- * @param mixed $condition attribute condition.
- * @param string $attribute attribute name.
- * @return array actual condition.
- */
- protected function buildOperatorCondition($operator, $condition, $attribute)
- {
- if (isset($this->queryOperatorMap[$operator])) {
- $operator = $this->queryOperatorMap[$operator];
- }
- return [$operator, $attribute, $this->filterAttributeValue($attribute, $condition)];
- }
- }
|