Orm::getWhereOperator()   B
last analyzed

Complexity

Conditions 9
Paths 14

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 9

Importance

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