ConditionTrait   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 1 Features 1
Metric Value
eloc 20
c 4
b 1
f 1
dl 0
loc 147
ccs 24
cts 24
cp 1
rs 10
wmc 11

6 Methods

Rating   Name   Duplication   Size   Complexity  
A where() 0 8 3
A orWhere() 0 3 1
A limit() 0 4 1
A appendConditionPart() 0 14 4
A andWhere() 0 3 1
A offset() 0 4 1
1
<?php
2
/**
3
 * Copyright 2021 Aleksandar Panic
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace ArekX\PQL\Sql\Query\Traits;
19
20
use ArekX\PQL\Contracts\StructuredQuery;
21
use http\Exception\InvalidArgumentException;
22
23
trait ConditionTrait
24
{
25
    /**
26
     * Set a filter for the results
27
     *
28
     * Filter can be an array containing a defined condition in an
29
     * array format or an StructuredQuery which will be used
30
     * directly as is.
31
     *
32
     * If null is sent, where will not be used.
33
     *
34
     * When array is passed, it can be one of the expressions:
35
     * - ['not', expression] - Not expression
36
     * - ['and', expression1, ..., expressionN] - AND expression
37
     * - ['or', expression1, ..., expressionN] - OR expression
38
     * - ['=', leftExpression, rightExpression] - Comparison expression (equals)
39
     * - ['!=', leftExpression, rightExpression] - Comparison expression (notEquals)
40
     * - ['<>', leftExpression, rightExpression] - Comparison expression (notEquals)
41
     * - ['<', leftExpression, rightExpression] - Comparison expression (lessThan)
42
     * - ['>', leftExpression, rightExpression] - Comparison expression (greaterThan)
43
     * - ['>=', leftExpression, rightExpression] - Comparison expression (greaterEqualThan)
44
     * - ['<=', leftExpression, rightExpression] - Comparison expression (lessEqualThan)
45
     * - ['like', leftExpression, rightExpression] - Like expression
46
     * - ['exists', expression] - Exists expression
47
     * - ['in', leftExpression, rightExpression] - In expression
48
     * - ['between', expression, fromExpression, toExpression] - Between expression
49
     * - ['all', associativeArray] - Associative array where key is the column and value is a prepared statement value.
50
     *                                All keys are turned into conditions joined together by AND.
51
     *                                All values are properly escaped and can be user inputs.
52
     *                                If a value is an array it wil be processed as an expression.
53
     *                                If a value is a StructuredQuery it will be pre-processed.
54
     * - ['any', associativeArray] - Associative array where key is the column and value is a prepared statement value.
55
     *                                All keys are turned into conditions joined by OR.
56
     *                                All values are properly escaped and can be user inputs.
57
     *                                If a value is a StructuredQuery it will be pre-processed.
58
     * - ['column', string] - Represents a column name or a `table.column` name.
59
     *                      This value is not escaped and should NOT contain user input.
60
     * - ['value', value, type] - Represents a value which can be user input. Type is optional.
61
     *                          Type must be a value supported by the driver if not passed, type will be inferred from
62
     *                          the value.
63
     *                          If a value is an array it will result in multiple parameters. This is useful for IN
64
     *                          expression checks.
65
     * - StructuredQuery - If this is passed it will be parsed by the builder as a sub query. This is useful for passing
66
     *                   raw query values in any expression or just using a raw query for the where part.
67
     *
68
     * These expressions are recursively parsed during query building.
69
     *
70
     * StructuredQuery - When this is placed as a variable, driver will also process this query and join its data
71
     *                   and parameters into this query meaning StructuredQueries can be used as sub-queries or
72
     *                   for raw input (you can use Raw class for this).
73
     *
74
     * @param array|StructuredQuery|null $where
75
     * @return $this
76
     */
77 10
    public function where(StructuredQuery|array|null $where): static
78
    {
79 10
        if (is_array($where) && empty($where[0])) {
80 1
            throw new \InvalidArgumentException("First parameter of where array must be an operation.");
81
        }
82
83 9
        $this->use('where', $where);
84 9
        return $this;
85
    }
86
87
    /**
88
     * Append where to the existing one by AND-ing the previous where
89
     * filter to the value specified in $where.
90
     *
91
     * If the current condition in part is an `['abd', condition]`, new condition
92
     * will be appended to it, otherwise the previous condition and this condition will
93
     * be wrapped as `['abd', previous, current]`
94
     *
95
     * @param array|StructuredQuery $where
96
     * @return $this
97
     * @see ConditionTrait::appendConditionPart()
98
     * @see ConditionTrait::where()
99
     */
100 3
    public function andWhere(StructuredQuery|array $where): static
101
    {
102 3
        return $this->appendConditionPart('where', 'and', $where);
103
    }
104
105
    /**
106
     * Appends a condition part to the query.
107
     *
108
     * @param string $part To which part to append the condition.
109
     * @param string $glue Which glue (AND/OR) to use to append the condition.
110
     * @param array|StructuredQuery $condition Condition to append
111
     * @return $this
112
     * @see ConditionTrait::where()
113
     */
114 8
    protected function appendConditionPart(string $part, string $glue, StructuredQuery|array $condition): static
115
    {
116 8
        $current = $this->get($part);
117
118 8
        if (is_array($current) && ($current[0] ?? '') === $glue) {
119 8
            $current[] = $condition;
120 8
        } elseif ($current === null) {
121 8
            $current = $condition;
122
        } else {
123 8
            $current = [$glue, $current, $condition];
124
        }
125
126 8
        $this->use($part, $current);
127 8
        return $this;
128
    }
129
130
    /**
131
     * Append where to the existing one by OR-ing the previous where
132
     * filter to the value specified in $where.
133
     *
134
     * If the current condition in part is an `['or', condition]`, new condition
135
     * will be appended to it, otherwise the previous condition and this condition will
136
     * be wrapped as `['or', previous, current]`
137
     *
138
     * @param array|StructuredQuery $where
139
     * @return $this
140
     * @see ConditionTrait::appendConditionPart()
141
     * @see ConditionTrait::where()
142
     */
143 3
    public function orWhere(StructuredQuery|array $where): static
144
    {
145 3
        return $this->appendConditionPart('where', 'or', $where);
146
    }
147
148
    /**
149
     * Set the limit for how many results to return.
150
     *
151
     * @param int $limit
152
     * @return $this
153
     */
154 7
    public function limit(int $limit): static
155
    {
156 7
        $this->use('limit', $limit);
157 7
        return $this;
158
    }
159
160
    /**
161
     * Set the offset for how many rows to skip in the result set.
162
     *
163
     * @param int $offset
164
     * @return $this
165
     */
166 4
    public function offset(int $offset): static
167
    {
168 4
        $this->use('offset', $offset);
169 4
        return $this;
170
    }
171
}
172