From aa6f01be72ce80a28e2d74308e906bac17b3638c Mon Sep 17 00:00:00 2001 From: evgen-d Date: Tue, 29 Jul 2014 09:47:49 +0400 Subject: [PATCH] arango filter implement --- Query.php | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 4 deletions(-) diff --git a/Query.php b/Query.php index 1ed575e..4413970 100644 --- a/Query.php +++ b/Query.php @@ -5,10 +5,10 @@ namespace devgroup\arangodb; use Yii; use yii\base\Component; use yii\base\InvalidParamException; +use yii\base\NotSupportedException; use yii\db\QueryInterface; use yii\helpers\ArrayHelper; use yii\helpers\Json; -use yii\helpers\VarDumper; use triagens\ArangoDb\Statement; @@ -542,19 +542,163 @@ class Query extends Component implements QueryInterface return $this; } + /** + * Sets the WHERE part of the query but ignores [[isEmpty()|empty operands]]. + * + * This method is similar to [[where()]]. The main difference is that this method will + * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited + * for building query conditions based on filter values entered by users. + * + * The following code shows the difference between this method and [[where()]]: + * + * ```php + * // WHERE `age`=:age + * $query->filterWhere(['name' => null, 'age' => 20]); + * // WHERE `age`=:age + * $query->where(['age' => 20]); + * // WHERE `name` IS NULL AND `age`=:age + * $query->where(['name' => null, 'age' => 20]); + * ``` + * + * Note that unlike [[where()]], you cannot pass binding parameters to this method. + * + * @param array $condition the conditions that should be put in the WHERE part. + * See [[where()]] on how to specify this parameter. + * @return static the query object itself. + * @see where() + * @see andFilterWhere() + * @see orFilterWhere() + */ public function filterWhere(array $condition) { - // TODO: Implement filterWhere() method. + $condition = $this->filterCondition($condition); + if ($condition !== []) { + $this->where($condition); + } + return $this; } + /** + * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. + * The new condition and the existing one will be joined using the 'AND' operator. + * + * This method is similar to [[andWhere()]]. The main difference is that this method will + * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited + * for building query conditions based on filter values entered by users. + * + * @param array $condition the new WHERE condition. Please refer to [[where()]] + * on how to specify this parameter. + * @return static the query object itself. + * @see filterWhere() + * @see orFilterWhere() + */ public function andFilterWhere(array $condition) { - // TODO: Implement andFilterWhere() method. + $condition = $this->filterCondition($condition); + if ($condition !== []) { + $this->andWhere($condition); + } + return $this; } + /** + * Adds an additional WHERE condition to the existing one but ignores [[isEmpty()|empty operands]]. + * The new condition and the existing one will be joined using the 'OR' operator. + * + * This method is similar to [[orWhere()]]. The main difference is that this method will + * remove [[isEmpty()|empty query operands]]. As a result, this method is best suited + * for building query conditions based on filter values entered by users. + * + * @param array $condition the new WHERE condition. Please refer to [[where()]] + * on how to specify this parameter. + * @return static the query object itself. + * @see filterWhere() + * @see andFilterWhere() + */ public function orFilterWhere(array $condition) { - // TODO: Implement orFilterWhere() method. + $condition = $this->filterCondition($condition); + if ($condition !== []) { + $this->orWhere($condition); + } + return $this; + } + + /** + * Returns a value indicating whether the give value is "empty". + * + * The value is considered "empty", if one of the following conditions is satisfied: + * + * - it is `null`, + * - an empty string (`''`), + * - a string containing only whitespace characters, + * - or an empty array. + * + * @param mixed $value + * @return boolean if the value is empty + */ + protected function isEmpty($value) + { + return $value === '' || $value === [] || $value === null || is_string($value) && trim($value) === ''; + } + + /** + * Removes [[isEmpty()|empty operands]] from the given query condition. + * + * @param array $condition the original condition + * @return array the condition with [[isEmpty()|empty operands]] removed. + * @throws NotSupportedException if the condition operator is not supported + */ + protected function filterCondition($condition) + { + if (!is_array($condition)) { + return $condition; + } + + if (!isset($condition[0])) { + // hash format: 'column1' => 'value1', 'column2' => 'value2', ... + foreach ($condition as $name => $value) { + if ($this->isEmpty($value)) { + unset($condition[$name]); + } + } + return $condition; + } + + // operator format: operator, operand 1, operand 2, ... + + $operator = array_shift($condition); + + switch (strtoupper($operator)) { + case 'NOT': + case 'AND': + case 'OR': + foreach ($condition as $i => $operand) { + $subCondition = $this->filterCondition($operand); + if ($this->isEmpty($subCondition)) { + unset($condition[$i]); + } else { + $condition[$i] = $subCondition; + } + } + + if (empty($condition)) { + return []; + } + break; + case 'IN': + case 'LIKE': + if (array_key_exists(1, $condition) && $this->isEmpty($condition[1])) { + return []; + } + break; + default: + throw new NotSupportedException("Operator not supported: $operator"); + } + + array_unshift($condition, $operator); + + return $condition; } public function orderBy($columns)