1 | <?php |
||||
2 | /** |
||||
3 | * Where statements |
||||
4 | * User: moyo |
||||
5 | * Date: 22/12/2017 |
||||
6 | * Time: 4:22 PM |
||||
7 | */ |
||||
8 | |||||
9 | namespace Carno\Database\SQL\Builders; |
||||
10 | |||||
11 | use Carno\Database\SQL\Builder; |
||||
12 | use Carno\Database\SQL\Exception\InvalidWhereStatementException; |
||||
13 | use Closure; |
||||
14 | |||||
15 | trait Where |
||||
16 | { |
||||
17 | /** |
||||
18 | * @var array |
||||
19 | */ |
||||
20 | private $bWheres = []; |
||||
21 | |||||
22 | /** |
||||
23 | * @var string |
||||
24 | */ |
||||
25 | private $bWGrouped = null; |
||||
26 | |||||
27 | /** |
||||
28 | * @var array |
||||
29 | */ |
||||
30 | private $bWGroupSTA = []; |
||||
31 | |||||
32 | /** |
||||
33 | * @var int |
||||
34 | */ |
||||
35 | private $bWGDepth = 0; |
||||
36 | |||||
37 | /** |
||||
38 | * @return string |
||||
39 | */ |
||||
40 | protected function gWheres() : string |
||||
41 | { |
||||
42 | return ($sql = $this->gWStmt()) ? sprintf(' WHERE %s', $sql) : ''; |
||||
43 | } |
||||
44 | |||||
45 | /** |
||||
46 | * @return string |
||||
47 | */ |
||||
48 | private function gWStmt() : string |
||||
49 | { |
||||
50 | $stmt = ''; |
||||
51 | |||||
52 | $stash = $this->bWGrouped[$this->bWGDepth] ?? null |
||||
53 | ? $this->bWGroupSTA[$this->bWGDepth] |
||||
54 | : $this->bWheres |
||||
55 | ; |
||||
56 | |||||
57 | $pack = $cond = false; |
||||
58 | |||||
59 | foreach ($stash as $part) { |
||||
60 | if (substr($part, 0, 1) === '#') { |
||||
61 | $pack = true; |
||||
62 | $stmt .= substr($part, 1); |
||||
63 | } else { |
||||
64 | $cond = true; |
||||
65 | $stmt .= $stmt ? sprintf(' AND %s', $part) : $part; |
||||
66 | } |
||||
67 | } |
||||
68 | |||||
69 | ($pack && !$cond) && $stmt = sprintf('1%s', $stmt); |
||||
70 | |||||
71 | return $stmt; |
||||
72 | } |
||||
73 | |||||
74 | /** |
||||
75 | * @param array ...$conditions |
||||
76 | * @return Builder |
||||
77 | */ |
||||
78 | public function where(...$conditions) : Builder |
||||
79 | { |
||||
80 | $expr = false; |
||||
81 | |||||
82 | foreach ($conditions as $condition) { |
||||
83 | if (is_array($condition)) { |
||||
84 | // expr sta |
||||
85 | $expr = true; |
||||
86 | |||||
87 | // where([expr], [expr]) |
||||
88 | if (isset($condition[0])) { |
||||
89 | $this->where(...$condition); |
||||
90 | continue; |
||||
91 | } |
||||
92 | |||||
93 | // where([k1 => v1, k2 => v2], [k3 => v3]) |
||||
94 | foreach ($condition as $k => $v) { |
||||
95 | $this->jWStmt($k, $v); |
||||
96 | } |
||||
97 | } elseif ($expr) { |
||||
98 | // -> where([expr]) |
||||
99 | $this->jWStmt(...(is_array($condition) ? $condition : [$condition])); |
||||
100 | } else { |
||||
101 | // where(expr) |
||||
102 | $this->jWStmt(...$conditions); |
||||
103 | break; |
||||
104 | } |
||||
105 | } |
||||
106 | |||||
107 | return $this; |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
108 | } |
||||
109 | |||||
110 | /** |
||||
111 | * @param mixed $current |
||||
112 | * @param mixed ...$extras |
||||
113 | */ |
||||
114 | private function jWStmt($current, ...$extras) : void |
||||
115 | { |
||||
116 | if (is_string($current)) { |
||||
117 | switch (count($extras)) { |
||||
118 | case 0: |
||||
119 | // where('sql') |
||||
120 | $this->addWSta($current); |
||||
121 | break; |
||||
122 | case 1: |
||||
123 | // where('key', 'val') |
||||
124 | $this->addWSta($this->genWSQL($current, '=', $extras[0])); |
||||
125 | break; |
||||
126 | case 2: |
||||
127 | // where('key', 'exp', 'val') |
||||
128 | $this->addWSta($this->genWSQL($current, ...$extras)); |
||||
129 | break; |
||||
130 | default: |
||||
131 | throw new InvalidWhereStatementException; |
||||
132 | } |
||||
133 | } elseif (is_integer($current)) { |
||||
134 | // where(123) primary key |
||||
135 | $this->addWSta($this->genWSQL('id', '=', $current)); |
||||
136 | } else { |
||||
137 | throw new InvalidWhereStatementException; |
||||
138 | } |
||||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * Grouping "AND" |
||||
143 | * @param Closure $builder |
||||
144 | * @return Builder |
||||
145 | */ |
||||
146 | public function and(Closure $builder) : Builder |
||||
147 | { |
||||
148 | return $this->jWStack($builder, 'AND'); |
||||
149 | } |
||||
150 | |||||
151 | /** |
||||
152 | * Grouping "OR" |
||||
153 | * @param Closure $builder |
||||
154 | * @return Builder |
||||
155 | */ |
||||
156 | public function or(Closure $builder) : Builder |
||||
157 | { |
||||
158 | return $this->jWStack($builder, 'OR'); |
||||
159 | } |
||||
160 | |||||
161 | /** |
||||
162 | * @param Closure $builder |
||||
163 | * @param string $group |
||||
164 | * @return Builder |
||||
165 | */ |
||||
166 | private function jWStack(Closure $builder, string $group) : Builder |
||||
167 | { |
||||
168 | $this->bWGDepth ++; |
||||
169 | |||||
170 | $this->bWGrouped[$this->bWGDepth] = $group; |
||||
171 | $this->bWGroupSTA[$this->bWGDepth] = []; |
||||
172 | |||||
173 | $builder($this); |
||||
174 | |||||
175 | $stage = $this->gWStmt(); |
||||
176 | |||||
177 | unset($this->bWGrouped[$this->bWGDepth]); |
||||
178 | unset($this->bWGroupSTA[$this->bWGDepth]); |
||||
179 | |||||
180 | $this->bWGDepth --; |
||||
181 | |||||
182 | $this->addWSta(sprintf('# %s (%s)', $group, $stage)); |
||||
183 | |||||
184 | return $this; |
||||
0 ignored issues
–
show
|
|||||
185 | } |
||||
186 | |||||
187 | /** |
||||
188 | * @param string $sql |
||||
189 | */ |
||||
190 | private function addWSta(string $sql) : void |
||||
191 | { |
||||
192 | if ($this->bWGrouped[$this->bWGDepth] ?? null) { |
||||
193 | $this->bWGroupSTA[$this->bWGDepth][] = $sql; |
||||
194 | } else { |
||||
195 | $this->bWheres[] = $sql; |
||||
196 | } |
||||
197 | } |
||||
198 | |||||
199 | /** |
||||
200 | * @param string $key |
||||
201 | * @param string $expr |
||||
202 | * @param mixed $val |
||||
203 | * @return string |
||||
204 | */ |
||||
205 | private function genWSQL(string $key, string $expr, $val) : string |
||||
206 | { |
||||
207 | $expr = strtoupper($expr); |
||||
208 | |||||
209 | switch ($expr) { |
||||
210 | case 'IN': |
||||
211 | is_array($val) && $val = sprintf('(%s)', implode(',', array_map(function ($id) { |
||||
212 | return (int) $id; |
||||
213 | }, $val))); |
||||
214 | break; |
||||
215 | default: |
||||
216 | $val = sprintf('?%d', $this->stash($val)); |
||||
0 ignored issues
–
show
It seems like
stash() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
217 | } |
||||
218 | |||||
219 | return sprintf('`%s` %s %s', $key, $expr, $val); |
||||
220 | } |
||||
221 | } |
||||
222 |