Completed
Push — master ( b13427...d9cbc5 )
by Pierre
03:45
created

Orm::getQueryBuilder()   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 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Component\Model\Orm;
4
5
use Nymfonya\Component\Config;
6
use Nymfonya\Component\Container;
7
use NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder;
8
use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
9
use NilPortugues\Sql\QueryBuilder\Manipulation\Update;
10
use NilPortugues\Sql\QueryBuilder\Manipulation\Insert;
11
use NilPortugues\Sql\QueryBuilder\Manipulation\Delete;
12
13
/**
14
 * Poor man orm
15
 */
16
class Orm implements IOrm
17
{
18
19
    /**
20
     * service container
21
     *
22
     * @var Container
23
     */
24
    private $container;
25
26
    /**
27
     * config
28
     *
29
     * @var Config
30
     */
31
    protected $config;
32
33
    /**
34
     * columns fields
35
     * @var array
36
     */
37
    protected $columns;
38
39
    /**
40
     * where criterias
41
     * @var array
42
     */
43
    protected $where;
44
45
    /**
46
     * sort order
47
     * @var array
48
     */
49
    protected $order;
50
51
    /**
52
     * table name
53
     * @var string
54
     */
55
    protected $tablename;
56
57
    /**
58
     * table primary key
59
     * @var string
60
     */
61
    protected $primary;
62
63
    /**
64
     * database name
65
     * @var string
66
     */
67
    protected $database;
68
69
    /**
70
     * db slot pool name
71
     * @var string
72
     */
73
    protected $slot;
74
75
    /**
76
     * query builder instance
77
     * @var GenericBuilder
78
     * @see https://github.com/nilportugues/php-sql-query-builder
79
     */
80
    protected $queryBuilder;
81
82
    /**
83
     * query from builder
84
     * @var object
85
     */
86
    protected $query;
87
88
    /**
89
     * instanciate
90
     * @param Container $container
91
     */
92 30
    public function __construct(Container $container)
93
    {
94 30
        $this->container = $container;
95 30
        $this->config = $container->getService(Config::class);
96 30
        $this->queryBuilder = new GenericBuilder();
97 30
        $this->query = null;
98 30
        $this->columns = [];
99 30
        $this->where = [];
100 30
        return $this;
101
    }
102
103
    /**
104
     * reset query builder
105
     *
106
     * @return void
107
     */
108 1
    public function resetBuilder(): Orm
109
    {
110 1
        $this->queryBuilder = new GenericBuilder();
111 1
        return $this;
112
    }
113
114
    /**
115
     * set required columns
116
     *
117
     * @param array $columns
118
     * @return Orm
119
     */
120 10
    public function setColumns(array $columns): Orm
121
    {
122 10
        $this->columns = $columns;
123 10
        return $this;
124
    }
125
126
    /**
127
     * find a record with columns field matching where criterias
128
     * @param array $columns
129
     * @param array $where
130
     * @param array $order
131
     */
132 8
    public function find(array $columns = [], array $where = [], array $order = []): Orm
133
    {
134 8
        $this->where = $where;
135 8
        $order = (empty($order)) ? [$this->primary => 'DESC'] : $order;
136
        $this
137 8
            ->setColumns($columns)
138 8
            ->setQuery(new Select())
139 8
            ->build($this->tablename, $this->columns, $this->where)
140 8
            ->setOrder($order);
141 8
        return $this;
142
    }
143
144
    /**
145
     * count records matching where criterias.
146
     * aliases is formely [columnn => column_alias]
147
     *
148
     * @param array $where
149
     * @param array $aliases
150
     * @return Orm
151
     */
152 2
    public function count(array $where = [], array $aliases = []): Orm
153
    {
154 2
        $this->where = $where;
155 2
        $this->setQuery(new Select());
156 2
        if (empty($aliases)) {
157 1
            $this->query->count();
158
        } else {
159 1
            reset($aliases);
160 1
            $fistKey = key($aliases);
161 1
            $aliasValue = $aliases[$fistKey];
162 1
            $this->query->count($fistKey, $aliasValue);
163
        }
164 2
        return $this->buildWhere($this->where);
165
    }
166
167
    /**
168
     * update a record with columns fields matching where criterias
169
     * @param array $columns
170
     * @param array $where
171
     */
172 1
    public function update(array $columns = [], array $where = []): Orm
173
    {
174 1
        $this->where = $where;
175 1
        return $this->setColumns($columns)
176 1
            ->setQuery(new Update())
177 1
            ->build($this->tablename, $this->columns, $this->where);
178
    }
179
180
    /**
181
     * insert record with columns fields
182
     * @param array $columns
183
     */
184 1
    public function insert(array $columns = []): Orm
185
    {
186
        return $this
187 1
            ->setColumns($columns)
188 1
            ->setQuery(new Insert())
189 1
            ->build($this->tablename, $this->columns, []);
190
    }
191
192
    /**
193
     * delete matching where criterias
194
     * @param array $where
195
     */
196 1
    public function delete(array $where = []): Orm
197
    {
198 1
        $this->where = $where;
199
        return $this
200 1
            ->setQuery(new Delete())
201 1
            ->build($this->tablename, [], $this->where);
202
    }
203
204
    /**
205
     * get primary key
206
     *
207
     * @return string
208
     */
209 2
    public function getPrimary(): string
210
    {
211 2
        return $this->primary;
212
    }
213
214
    /**
215
     * get slot name
216
     *
217
     * @return string
218
     */
219 1
    public function getSlot(): string
220
    {
221 1
        return $this->slot;
222
    }
223
224
    /**
225
     * get service container
226
     *
227
     * @return Container
228
     */
229 1
    public function getContainer(): Container
230
    {
231 1
        return $this->container;
232
    }
233
234
    /**
235
     * get database name
236
     *
237
     * @return string
238
     */
239 1
    public function getDatabase(): string
240
    {
241 1
        return $this->database;
242
    }
243
244
    /**
245
     * get table name
246
     *
247
     * @return string
248
     */
249 1
    public function getTable(): string
250
    {
251 1
        return $this->tablename;
252
    }
253
254
    /**
255
     * builder instance
256
     * @return GenericBuilder
257
     */
258 2
    public function getQueryBuilder(): GenericBuilder
259
    {
260 2
        return $this->queryBuilder;
261
    }
262
263
    /**
264
     * query instance
265
     * @return object
266
     */
267 20
    public function getQuery()
268
    {
269 20
        return $this->query;
270
    }
271
272
    /**
273
     * query builder values
274
     * @return array
275
     */
276 3
    public function getBuilderValues(): array
277
    {
278 3
        $this->getSql();
279 3
        return $this->queryBuilder->getValues();
280
    }
281
282
    /**
283
     * set query instance
284
     *
285
     * @param Select|Update|Insert|Delete $query
286
     * @return Orm
287
     */
288 21
    public function setQuery($query): Orm
289
    {
290 21
        $this->query = $query;
291 21
        return $this;
292
    }
293
294
    /**
295
     * query sql string
296
     * @return string
297
     */
298 5
    public function getSql(bool $reset = true): string
299
    {
300 5
        return $this->queryBuilder->write($this->query, $reset);
301
    }
302
303
    /**
304
     * build query
305
     *
306
     * @param string $tablename
307
     * @param array $columns
308
     * @param array $where
309
     * @return Orm
310
     */
311 10
    protected function build(string $tablename, array $columns, array $where): Orm
312
    {
313 10
        if (false === is_object($this->getQuery())) {
314 1
            throw new \Exception('Build : Invalid query instance');
315
        }
316 9
        $queryClassname = get_class($this->getQuery());
317
        $allowedClasses = [
318 9
            Update::class, Select::class, Delete::class, Insert::class
319
        ];
320 9
        if (false === in_array($queryClassname, $allowedClasses)) {
321 1
            throw new \Exception('Build : Invalid query type');
322
        }
323 8
        $this->query->setTable($tablename);
324 8
        switch ($queryClassname) {
325
            case Select::class:
326 1
                $this->query->setColumns($columns);
327 1
                break;
328
            case Update::class:
329 3
                if (empty($columns)) {
330 1
                    throw new \Exception(
331 1
                        'Build : Update requires not empty payload'
332
                    );
333
                }
334 2
                if (empty($where)) {
335 1
                    throw new \Exception(
336 1
                        'Build : Update requires at least one condition'
337
                    );
338
                }
339 1
                $this->query->setValues($columns);
340 1
                break;
341
            case Insert::class:
342 2
                if (empty($columns)) {
343 1
                    throw new \Exception(
344 1
                        'Build : Insert requires not empty payload'
345
                    );
346
                }
347 1
                $this->query->setValues($columns);
348 1
                break;
349
            case Delete::class:
350 2
                if (empty($where)) {
351 1
                    throw new \Exception(
352 1
                        'Build : Delete requires at least one condition'
353
                    );
354
                }
355 1
                break;
356
        }
357 4
        return $this->buildWhere($where);
358
    }
359
360
    /**
361
     * build where condition on query
362
     *
363
     * @param array $where
364
     * @return Orm
365
     */
366 1
    protected function buildWhere(array $where): Orm
367
    {
368 1
        if (false === empty($where)) {
369 1
            foreach ($where as $k => $v) {
370 1
                $whereOperator = $this->getWhereOperator($k, $v);
371 1
                $this->query->where()->{$whereOperator}($k, $v);
372
            }
373
        }
374 1
        return $this;
375
    }
376
377
    /**
378
     * check where condition ket values to find operators
379
     *
380
     * @param string $whereColumn
381
     * @return string
382
     */
383 1
    protected function getWhereOperator(string &$whereColumn, $value): string
384
    {
385 1
        $hasArray = is_array($value);
386 1
        $operator = $whereColumn[strlen($whereColumn) - 1];
387 1
        $hasOperator = in_array($operator, self::OPERATORS);
388 1
        if (false === $hasOperator) {
389 1
            return ($hasArray) ? 'in' : 'equals';
390
        }
391 1
        foreach (self::OPERATORS as $op) {
392 1
            $whereColumn = str_replace($op, '', $whereColumn);
393
        }
394 1
        if ($operator == '!') {
395 1
            return ($hasArray) ? 'notIn' : 'notEquals';
396 1
        } elseif ($operator == '<') {
397 1
            return 'lessThan';
398 1
        } elseif ($operator == '>') {
399 1
            return 'greaterThan';
400 1
        } elseif ($operator == '#') {
401 1
            return 'like';
402
        }
403
    }
404
405
    /**
406
     * set query sort order
407
     *
408
     * @param array $orders
409
     * @return Orm
410
     */
411 1
    protected function setOrder(array $orders): Orm
412
    {
413 1
        $this->order = $orders;
414 1
        foreach ($this->order as $k => $v) {
415 1
            $this->query->orderBy($k, $v);
416
        }
417 1
        return $this;
418
    }
419
}
420