QueryBuilder::setBaseTable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace kalanis\kw_mapper\Storage\Shared;
4
5
6
use kalanis\kw_mapper\Interfaces\IQueryBuilder;
7
use kalanis\kw_mapper\MapperException;
8
9
10
/**
11
 * Class QueryBuilder
12
 * @package kalanis\kw_mapper\Storage\Shared
13
 * Prepare conditions, properties, joins and params as extra parts to pass to the storage
14
 */
15
class QueryBuilder
16
{
17
    protected QueryBuilder\UniqueId $uniqueId;
18
    protected QueryBuilder\Column $column;
19
    protected QueryBuilder\Condition $condition;
20
    protected QueryBuilder\Property $property;
21
    protected QueryBuilder\Join $join;
22
    protected QueryBuilder\Order $order;
23
    protected QueryBuilder\Group $group;
24
25
    protected string $relation = IQueryBuilder::RELATION_AND;
26
    protected string $baseTable = '';
27
    /** @var array<string, int|string|float|null> */
28
    protected array $params = [];
29
    /** @var QueryBuilder\Column[] */
30
    protected array $columns = [];
31
    /** @var QueryBuilder\Join[] */
32
    protected array $joins = [];
33
    /** @var QueryBuilder\Condition[] */
34
    protected array $conditions = [];
35
    /** @var QueryBuilder\Property[] */
36
    protected array $properties = [];
37
    /** @var QueryBuilder\Order[] */
38
    protected array $ordering = [];
39
    /** @var QueryBuilder\Group[] */
40
    protected array $grouping = [];
41
    /** @var QueryBuilder\Condition[] */
42
    protected array $having = [];
43
    protected ?int $offset = null;
44
    protected ?int $limit = null;
45
46 145
    public function __construct()
47
    {
48 145
        $this->column = new QueryBuilder\Column();
49 145
        $this->condition = new QueryBuilder\Condition();
50 145
        $this->property = new QueryBuilder\Property();
51 145
        $this->join = new QueryBuilder\Join();
52 145
        $this->order = new QueryBuilder\Order();
53 145
        $this->group = new QueryBuilder\Group();
54 145
        $this->uniqueId = QueryBuilder\UniqueIdFactory::getFactoryInstance()->getClass();
55
    }
56
57
    /**
58
     * @param string $tableName
59
     * @param string|int $columnName
60
     * @param string|int $alias
61
     * @param string $aggregate
62
     * @throws MapperException
63
     */
64 28
    public function addColumn(string $tableName, $columnName, $alias = '', string $aggregate = ''): void
65
    {
66 28
        if (!empty($aggregate) && !in_array($aggregate, [
67 28
                IQueryBuilder::AGGREGATE_AVG, IQueryBuilder::AGGREGATE_COUNT,
68 28
                IQueryBuilder::AGGREGATE_MIN, IQueryBuilder::AGGREGATE_MAX,
69 28
                IQueryBuilder::AGGREGATE_SUM,
70 28
            ])) {
71 1
            throw new MapperException(sprintf('Unknown aggregation by method *%s* !', $aggregate));
72
        }
73 27
        $column = clone $this->column;
74 27
        $this->columns[] = $column->setData($tableName, $columnName, $alias, $aggregate);
75
    }
76
77
    /**
78
     * @param string $tableName
79
     * @param string|int $columnName
80
     * @param string $operation
81
     * @param mixed $value
82
     * @throws MapperException
83
     */
84 64
    public function addCondition(string $tableName, $columnName, string $operation, $value = null): void
85
    {
86 64
        if (!empty($operation) && !in_array($operation, [
87 64
                IQueryBuilder::OPERATION_NULL, IQueryBuilder::OPERATION_NNULL,
88 64
                IQueryBuilder::OPERATION_EQ, IQueryBuilder::OPERATION_NEQ,
89 64
                IQueryBuilder::OPERATION_GT, IQueryBuilder::OPERATION_GTE,
90 64
                IQueryBuilder::OPERATION_LT, IQueryBuilder::OPERATION_LTE,
91 64
                IQueryBuilder::OPERATION_LIKE, IQueryBuilder::OPERATION_NLIKE,
92 64
                IQueryBuilder::OPERATION_REXP,
93 64
                IQueryBuilder::OPERATION_IN, IQueryBuilder::OPERATION_NIN,
94 64
            ])) {
95 1
            throw new MapperException(sprintf('Unknown operation *%s* !', $operation));
96
        }
97
98 63
        if (in_array($operation, [IQueryBuilder::OPERATION_EQ, IQueryBuilder::OPERATION_LIKE, IQueryBuilder::OPERATION_IN]) && is_null($value)) {
99 2
            $operation = IQueryBuilder::OPERATION_NULL;
100 62
        } elseif (in_array($operation, [IQueryBuilder::OPERATION_NEQ, IQueryBuilder::OPERATION_NLIKE, IQueryBuilder::OPERATION_NIN]) && is_null($value)) {
101 4
            $operation = IQueryBuilder::OPERATION_NNULL;
102
        }
103
104 63
        $condition = clone $this->condition;
105 63
        if (is_null($value)) {
106 9
            $this->conditions[] = $condition->setData($tableName, $columnName, $operation, $this->simpleNoValue($columnName));
107
        } else {
108 58
            $this->conditions[] = $condition->setData($tableName, $columnName, $operation, $this->multipleByValue($columnName, $value));
109
        }
110
    }
111
112
    /**
113
     * @param string|string[]|callable $operation
114
     * @param string $prefix
115
     * @param mixed $value
116
     */
117 3
    public function addRawCondition($operation, string $prefix = '', $value = null): void
118
    {
119 3
        $condition = clone $this->condition;
120 3
        if (is_null($value)) {
121 2
            $this->conditions[] = $condition->setRaw($operation);
122
        } else {
123 1
            $this->conditions[] = $condition->setRaw($operation, $this->multipleByValue($prefix, $value));
124
        }
125
    }
126
127
    /**
128
     * @param string $tableName
129
     * @param string|int $columnName
130
     * @param mixed $value
131
     */
132 21
    public function addProperty(string $tableName, $columnName, $value = null): void
133
    {
134 21
        $property = clone $this->property;
135 21
        $this->properties[] = $property->setData($tableName, $columnName, $this->simpleByValue($columnName, $value));
136
    }
137
138
    /**
139
     * @param string $joinUnderAlias
140
     * @param string $addTableName
141
     * @param string|int $addColumnName
142
     * @param string $knownTableName
143
     * @param string|int $knownColumnName
144
     * @param string $side
145
     * @param string $tableAlias
146
     */
147 7
    public function addJoin(string $joinUnderAlias, string $addTableName, $addColumnName, string $knownTableName, $knownColumnName, string $side = '', string $tableAlias = ''): void
148
    {
149 7
        $join = clone $this->join;
150 7
        $this->joins[] = $join->setData($joinUnderAlias, $addTableName, $addColumnName, $knownTableName, $knownColumnName, $side, $tableAlias);
151
    }
152
153
    /**
154
     * @param string $tableName
155
     * @param string|int $columnName
156
     * @param string $operation
157
     * @param string|int|float|null $value
158
     * @throws MapperException
159
     */
160 5
    public function addHavingCondition(string $tableName, $columnName, string $operation, $value = null): void
161
    {
162 5
        if (!empty($operation) && !in_array($operation, [
163 5
                IQueryBuilder::OPERATION_NULL, IQueryBuilder::OPERATION_NNULL,
164 5
                IQueryBuilder::OPERATION_EQ, IQueryBuilder::OPERATION_NEQ,
165 5
                IQueryBuilder::OPERATION_GT, IQueryBuilder::OPERATION_GTE,
166 5
                IQueryBuilder::OPERATION_LT, IQueryBuilder::OPERATION_LTE,
167 5
                IQueryBuilder::OPERATION_LIKE, IQueryBuilder::OPERATION_NLIKE,
168 5
                IQueryBuilder::OPERATION_REXP,
169 5
                IQueryBuilder::OPERATION_IN, IQueryBuilder::OPERATION_NIN,
170 5
            ])) {
171 1
            throw new MapperException(sprintf('Unknown operation *%s* !', $operation));
172
        }
173
174 4
        if (in_array($operation, [IQueryBuilder::OPERATION_EQ, IQueryBuilder::OPERATION_LIKE, IQueryBuilder::OPERATION_IN]) && is_null($value)) {
175 1
            $operation = IQueryBuilder::OPERATION_NULL;
176 3
        } elseif (in_array($operation, [IQueryBuilder::OPERATION_NEQ, IQueryBuilder::OPERATION_NLIKE, IQueryBuilder::OPERATION_NIN]) && is_null($value)) {
177 1
            $operation = IQueryBuilder::OPERATION_NNULL;
178
        }
179
180 4
        $condition = clone $this->condition;
181 4
        if (is_null($value)) {
182 2
            $this->having[] = $condition->setData($tableName, $columnName, $operation, $this->simpleNoValue($columnName));
183
        } else {
184 2
            $this->having[] = $condition->setData($tableName, $columnName, $operation, $this->multipleByValue($columnName, $value));
185
        }
186
    }
187
188
    /**
189
     * @param string|int $columnName
190
     * @param string|int|float|array<string|int|float|null>|null $value
191
     * @return string|string[]
192
     */
193 60
    protected function multipleByValue($columnName, $value)
194
    {
195 60
        if (is_array($value)) {
196 3
            $keys = [];
197 3
            foreach ($value as $item) {
198 3
                $keys[] = $this->simpleByValue($columnName, $item);
199
            }
200 3
            return $keys;
201
        } else {
202 58
            return $this->simpleByValue($columnName, $value);
203
        }
204
    }
205
206
    /**
207
     * @param string|int $columnName
208
     * @param string|int|float|null $value
209
     * @return string
210
     */
211 69
    protected function simpleByValue($columnName, $value): string
212
    {
213 69
        $columnKey = $this->simpleNoValue($columnName);
214 69
        $this->params[$columnKey] = is_null($value) ? null : strval($value);
215 69
        return $columnKey;
216
    }
217
218
    /**
219
     * @param string|int $columnName
220
     * @return string
221
     */
222 76
    protected function simpleNoValue($columnName): string
223
    {
224 76
        return sprintf(':%s_%s', $columnName, $this->uniqueId->get());
225
    }
226
227
    /**
228
     * @param string $tableName
229
     * @param string|int $columnName
230
     * @param string $direction
231
     * @throws MapperException
232
     */
233 19
    public function addOrderBy(string $tableName, $columnName, string $direction): void
234
    {
235 19
        if (!empty($direction) && !in_array($direction, [
236 19
                IQueryBuilder::ORDER_ASC, IQueryBuilder::ORDER_DESC,
237 19
            ])) {
238 1
            throw new MapperException(sprintf('Unknown direction *%s* !', $direction));
239
        }
240 18
        $order = clone $this->order;
241 18
        $this->ordering[] = $order->setData($tableName, $columnName, $direction);
242
    }
243
244
    /**
245
     * @param string $tableName
246
     * @param string|int $columnName
247
     */
248 9
    public function addGroupBy(string $tableName, $columnName): void
249
    {
250 9
        $group = clone $this->group;
251 9
        $this->grouping[] = $group->setData($tableName, $columnName);
252
    }
253
254 11
    public function setLimit(?int $limit): void
255
    {
256 11
        $this->limit = $limit;
257
    }
258
259 6
    public function setOffset(?int $offset): void
260
    {
261 6
        $this->offset = $offset;
262
    }
263
264 15
    public function setLimits(?int $offset, ?int $limit): void
265
    {
266 15
        $this->offset = $offset;
267 15
        $this->limit = $limit;
268
    }
269
270 2
    public function setRelations(string $relation): void
271
    {
272 2
        if (IQueryBuilder::RELATION_AND == $relation || IQueryBuilder::RELATION_OR == $relation) {
273 2
            $this->relation = $relation;
274
        }
275
    }
276
277 30
    public function clear(): void
278
    {
279 30
        $this->params = [];
280 30
        $this->columns = [];
281 30
        $this->conditions = [];
282 30
        $this->properties = [];
283 30
        $this->ordering = [];
284 30
        $this->grouping = [];
285 30
        $this->having = [];
286 30
        $this->joins = [];
287 30
        $this->offset = null;
288 30
        $this->limit = null;
289
    }
290
291 7
    public function clearColumns(): void
292
    {
293 7
        $this->columns = [];
294
    }
295
296 6
    public function clearOrdering(): void
297
    {
298 6
        $this->ordering = [];
299
    }
300
301 143
    public function setBaseTable(string $tableName): void
302
    {
303 143
        $this->baseTable = $tableName;
304
    }
305
306 44
    public function getRelation(): string
307
    {
308 44
        return $this->relation;
309
    }
310
311 52
    public function getBaseTable(): string
312
    {
313 52
        return $this->baseTable;
314
    }
315
316
    /**
317
     * @return array<string, int|string|float|null>
318
     */
319 73
    public function getParams(): array
320
    {
321 73
        return $this->params;
322
    }
323
324
    /**
325
     * @return QueryBuilder\Column[]
326
     */
327 28
    public function getColumns(): array
328
    {
329 28
        return $this->columns;
330
    }
331
332
    /**
333
     * @return QueryBuilder\Join[]
334
     */
335 29
    public function getJoins(): array
336
    {
337 29
        return $this->joins;
338
    }
339
340
    /**
341
     * @return QueryBuilder\Condition[]
342
     */
343 72
    public function getConditions(): array
344
    {
345 72
        return $this->conditions;
346
    }
347
348
    /**
349
     * @return QueryBuilder\Property[]
350
     */
351 23
    public function getProperties(): array
352
    {
353 23
        return $this->properties;
354
    }
355
356
    /**
357
     * @return QueryBuilder\Order[]
358
     */
359 46
    public function getOrdering(): array
360
    {
361 46
        return $this->ordering;
362
    }
363
364
    /**
365
     * @return QueryBuilder\Group[]
366
     */
367 46
    public function getGrouping(): array
368
    {
369 46
        return $this->grouping;
370
    }
371
372
    /**
373
     * @return QueryBuilder\Condition[]
374
     */
375 48
    public function getHavingCondition(): array
376
    {
377 48
        return $this->having;
378
    }
379
380 35
    public function getLimit(): ?int
381
    {
382 35
        return $this->limit;
383
    }
384
385 33
    public function getOffset(): ?int
386
    {
387 33
        return $this->offset;
388
    }
389
}
390