diff options
Diffstat (limited to 'vendor/ipl/sql/src/Where.php')
-rw-r--r-- | vendor/ipl/sql/src/Where.php | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/vendor/ipl/sql/src/Where.php b/vendor/ipl/sql/src/Where.php new file mode 100644 index 0000000..f862846 --- /dev/null +++ b/vendor/ipl/sql/src/Where.php @@ -0,0 +1,158 @@ +<?php + +namespace ipl\Sql; + +/** + * Implementation for the {@link WhereInterface} + */ +trait Where +{ + /** @var array|null Internal representation for the WHERE part of the query */ + protected $where; + + public function getWhere() + { + return $this->where; + } + + public function where($condition, ...$args) + { + list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ALL); + + return $this; + } + + public function orWhere($condition, ...$args) + { + list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ANY); + + return $this; + } + + public function notWhere($condition, ...$args) + { + list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ALL); + + return $this; + } + + public function orNotWhere($condition, ...$args) + { + list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ANY); + + return $this; + } + + public function resetWhere() + { + $this->where = null; + + return $this; + } + + /** + * Make $condition an array and build an array like this: [$operator, [$condition]] + * + * If $condition is empty, replace it with a boolean constant depending on the operator. + * + * @param string|array $condition + * @param string $operator + * + * @return array + */ + protected function buildCondition($condition, $operator) + { + if (is_array($condition)) { + if (empty($condition)) { + $condition = [$operator === Sql::ALL ? '1' : '0']; + } elseif (in_array(reset($condition), [Sql::ALL, Sql::ANY, Sql::NOT_ALL, Sql::NOT_ANY], true)) { + return $condition; + } + } else { + $condition = [$condition]; + } + + return [$operator, $condition]; + } + + /** + * Merge the given condition with ours via the given operator + * + * @param mixed $base Our condition + * @param array $condition As returned by {@link buildCondition()} + * @param string $operator + */ + protected function mergeCondition(&$base, array $condition, $operator) + { + if ($base === null) { + $base = [$operator, [$condition]]; + } else { + if ($base[0] === $operator) { + $base[1][] = $condition; + } elseif ($operator === Sql::NOT_ALL) { + $base = [Sql::ALL, [$base, [$operator, [$condition]]]]; + } elseif ($operator === Sql::NOT_ANY) { + $base = [Sql::ANY, [$base, [$operator, [$condition]]]]; + } else { + $base = [$operator, [$base, $condition]]; + } + } + } + + /** + * Prepare condition arguments from the different supported where styles + * + * @param mixed $condition + * @param array $args + * + * @return array + */ + protected function prepareConditionArguments($condition, array $args) + { + // Default operator + $operator = Sql::ALL; + + if (! is_array($condition) && ! empty($args)) { + // Variadic + $condition = [(string) $condition => $args]; + } else { + // Array or string format + $operator = array_shift($args) ?: $operator; + } + + return [$condition, $operator]; + } + + /** + * Clone the properties provided by this trait + * + * Shall be called by using classes in their __clone() + */ + protected function cloneWhere() + { + if ($this->where !== null) { + $this->cloneCondition($this->where); + } + } + + /** + * Clone a condition in-place + * + * @param array $condition As returned by {@link buildCondition()} + */ + protected function cloneCondition(array &$condition) + { + foreach ($condition as &$subCondition) { + if (is_array($subCondition)) { + $this->cloneCondition($subCondition); + } elseif ($subCondition instanceof ExpressionInterface || $subCondition instanceof Select) { + $subCondition = clone $subCondition; + } + } + unset($subCondition); + } +} |