Passed
Push — main ( 87c1e5...f29b76 )
by William
01:42
created

Base::mountQuery()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 6
rs 10
1
<?php
2
3
namespace Willry\QueryBuilder;
4
5
6
class Base
7
{
8
    /**
9
     * @var bool
10
     */
11
    protected $silentErrors;
12
13
    /**
14
     * @var \Exception|null
15
     */
16
    protected $fail;
17
18
    /**
19
     * @var string $entity database table
20
     */
21
    protected $entity;
22
23
    /**
24
     * @var array
25
     */
26
    protected $columns = [];
27
28
    /**
29
     * @var string
30
     */
31
    protected $where;
32
33
    /**
34
     * @var string
35
     */
36
    protected $order;
37
38
    /**
39
     * @var string
40
     */
41
    protected $limit;
42
43
    /**
44
     * @var string
45
     */
46
    protected $offset;
47
48
    /**
49
     * @var string
50
     */
51
    protected $joins;
52
53
    /**
54
     * @var string
55
     */
56
    protected $query;
57
58
    /**
59
     * @var string
60
     */
61
    protected $groupBy;
62
63
    /**
64
     * @var string
65
     */
66
    protected $having;
67
68
    /**
69
     * @var \PDO
70
     */
71
    protected $db;
72
73
    protected $fields = [];
74
75
    public $bindings = [
76
        'select' => [],
77
        'from' => [],
78
        'join' => [],
79
        'create' => [],
80
        'update' => [],
81
        'where' => [],
82
        'groupBy' => [],
83
        'having' => [],
84
        'order' => [],
85
        'union' => [],
86
        'unionOrder' => [],
87
    ];
88
89
    /**
90
     * @var array|null
91
     */
92
    protected $connectionConfig;
93
94
95
    public function __construct(string $connectionName = 'default', bool $regenerateConnection = false)
96
    {
97
        $this->db = Connect::getInstance($connectionName, $regenerateConnection);
98
        $this->connectionConfig = Connect::getConfig($connectionName);
99
    }
100
101
    public function from(string $entity)
102
    {
103
        $this->entity = $entity;
104
        return $this;
105
    }
106
107
    public function fromSubQuery($callback, string $alias = 'sub')
108
    {
109
        $query = new Query();
110
        $callback($query);
111
112
        $this->entity = "(" . $query->toSQL() . ") as $alias";
113
        $this->setBindings($query->flatBindings(), 'from');
114
115
        return $this;
116
    }
117
118
    public function setSilentErrors(bool $silentErrors = false)
119
    {
120
        $this->silentErrors = $silentErrors;
121
    }
122
123
    /**
124
     * @param string $where
125
     * @return $this
126
     */
127
    public function where(string $where, array $params = []): static
128
    {
129
        $this->setBindings($params, 'where');
130
131
        if (!empty($this->where)) {
132
            $this->where .= " AND {$where}";
133
            return $this;
134
        }
135
136
        $this->where = "WHERE $where";
137
        return $this;
138
    }
139
140
    /**
141
     * @param string $where
142
     * @return $this
143
     */
144
    public function orWhere(string $where, array $params = []): static
145
    {
146
        $this->setBindings($params, 'where');
147
        if (!empty($this->where)) {
148
            $this->where .= " OR {$where}";
149
            return $this;
150
        }
151
152
        $this->where = "WHERE $where";
153
        return $this;
154
    }
155
156
    public function whereIn(string $column, array $data): static
157
    {
158
        $inString = implode(',', array_fill(0, count($data), '?'));
159
        $this->setBindings($data, 'where');
160
161
        if (!empty($this->where)) {
162
            $this->where .= " AND {$column} IN ({$inString})";
163
            return $this;
164
        }
165
166
        $this->where = "WHERE {$column} IN ({$inString})";
167
        return $this;
168
    }
169
170
    public function orWhereIn(string $column, array $data): static
171
    {
172
173
        $inString = implode(',', array_fill(0, count($data), '?'));
174
        $this->setBindings($data, 'where');
175
176
        if (!empty($this->where)) {
177
            $this->where .= " OR {$column} IN ($inString)";
178
            return $this;
179
        }
180
181
        $this->where = "WHERE {$column} IN ($inString)";
182
        return $this;
183
    }
184
185
    public function getBindings()
186
    {
187
        return $this->bindings;
188
    }
189
190
    /**
191
     * @param array $params
192
     * @return $this
193
     */
194
    public function setBindings(array $params = [], string $type = 'where'): static
195
    {
196
        $this->bindings[$type] = array_merge($this->bindings[$type], $params);
197
198
        return $this;
199
    }
200
201
    /**
202
     * @param string $join
203
     * @return $this
204
     */
205
    public function leftJoin(string $join, array $params = []): static
206
    {
207
        $this->setBindings($params, 'join');
208
209
        $this->joins .= PHP_EOL;
210
211
        $this->joins .= "LEFT JOIN $join";
212
213
        return $this;
214
    }
215
216
    /**
217
     * @param string $join
218
     * @return $this
219
     */
220
    public function rightJoin(string $join, array $params = []): static
221
    {
222
        $this->setBindings($params, 'join');
223
224
        $this->joins .= PHP_EOL;
225
226
        $this->joins .= "RIGHT JOIN $join";
227
228
        return $this;
229
    }
230
231
    /**
232
     * @param string $join
233
     * @return $this
234
     */
235
    public function join(string $join, array $params = []): static
236
    {
237
        $this->setBindings($params, 'join');
238
239
        $this->joins .= PHP_EOL;
240
241
        $this->joins .= "INNER JOIN $join";
242
        return $this;
243
    }
244
245
    public function joinSub(Query $subquery, string $alias, $condition, array $params = [])
246
    {
247
        $this->setBindings($subquery->flatBindings(), 'join');
248
        $this->setBindings($params, 'join');
249
250
        $this->joins .= PHP_EOL;
251
252
        $this->joins .= "INNER JOIN ({$subquery->toSQL()}) AS $alias ON $condition";
253
254
        return $this;
255
    }
256
257
    public function leftJoinSub(Query $subquery, string $alias, $condition, array $params = [])
258
    {
259
        $this->setBindings($subquery->flatBindings(), 'join');
260
        $this->setBindings($params, 'join');
261
262
        $this->joins .= PHP_EOL;
263
264
        $this->joins .= "LEFT JOIN ({$subquery->toSQL()}) AS $alias ON $condition";
265
266
        return $this;
267
    }
268
269
    public function rightJoinSub(Query $subquery, string $alias, $condition, array $params = [])
270
    {
271
        $this->setBindings($subquery->flatBindings(), 'join');
272
        $this->setBindings($params, 'join');
273
274
        $this->joins .= PHP_EOL;
275
276
        $this->joins .= "RIGHT JOIN ({$subquery->toSQL()}) AS $alias ON $condition";
277
278
        return $this;
279
    }
280
281
    public function beginTransaction(): bool
282
    {
283
        return $this->db->beginTransaction();
284
    }
285
286
287
    public function commit(): bool
288
    {
289
        return $this->db->commit();
290
    }
291
292
    public function rollback(): bool
293
    {
294
        return $this->db->rollBack();
295
    }
296
297
    /**
298
     * @param  $exception
299
     * @throws Exception
300
     */
301
    protected function handleError(\Exception $exception)
302
    {
303
        if (!$this->silentErrors) {
304
            throw $exception;
305
        }
306
307
        $this->fail = $exception;
308
    }
309
310
    protected function mountQuery(): void
311
    {
312
313
        $columns = !empty($this->columns) ? $this->columns : ['*'];
314
        $columns = implode(',', $columns);
315
        $this->query = "SELECT $columns FROM $this->entity $this->joins $this->where $this->groupBy $this->having $this->order $this->limit $this->offset";
316
    }
317
318
    public function dump(): array
319
    {
320
        $this->mountQuery();
321
322
        return [
323
            "query" => $this->query,
324
            "raw_params" => $this->bindings,
325
        ];
326
    }
327
328
    public function toSQL()
329
    {
330
        $this->mountQuery();
331
        return $this->query;
332
    }
333
334
    public function flatBindings()
335
    {
336
        $params = [];
337
        foreach ($this->bindings as $key => $binds) {
338
            $params = array_merge($params, $this->bindings[$key]);
339
        }
340
341
        return $params;
342
    }
343
344
    public function mergeBindFromAnotherQuery(Query $query)
345
    {
346
        $array1 = $this->getBindings();
347
        $array2 = $query->getBindings();
348
        $mergedArray = [
349
            'select' => array_merge($array1['select'], $array2['select']),
350
            'from' => array_merge($array1['from'], $array2['from']),
351
            'join' => array_merge($array1['join'], $array2['join']),
352
            'update' => array_merge($array1['update'], $array2['update']),
353
            'where' => array_merge($array1['where'], $array2['where']),
354
            'groupBy' => array_merge($array1['groupBy'], $array2['groupBy']),
355
            'having' => array_merge($array1['having'], $array2['having']),
356
            'order' => array_merge($array1['order'], $array2['order']),
357
            'union' => array_merge($array1['union'], $array2['union']),
358
            'unionOrder' => array_merge($array1['unionOrder'], $array2['unionOrder']),
359
        ];
360
361
        $this->bindings = $mergedArray;
362
    }
363
}
364