Passed
Push — master ( bd1833...5bce6d )
by Petr
02:54
created

QueryBuilder::getColumns()   A

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