Completed
Push — master ( 5652bd...9532f5 )
by Pierre
02:48
created

Orm::buildWhere()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 1
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Component\Model\Orm;
4
5
use App\Config;
6
use App\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 25
    public function __construct(Container $container)
93
    {
94 25
        $this->container = $container;
95 25
        $this->config = $container->getService(Config::class);
96 25
        $this->queryBuilder = new GenericBuilder();
97 25
        $this->query = null;
98 25
        $this->columns = [];
99 25
        $this->where = [];
100 25
        return $this;
101
    }
102
103
    /**
104
     * set required columns
105
     *
106
     * @param array $columns
107
     * @return Orm
108
     */
109 8
    public function setColumns(array $columns): Orm
110
    {
111 8
        $this->columns = $columns;
112 8
        return $this;
113
    }
114
115
    /**
116
     * find a record with columns field matching where criterias
117
     * @param array $columns
118
     * @param array $where
119
     * @param array $order
120
     */
121 6
    public function find(array $columns = [], array $where = [], array $order = []): Orm
122
    {
123 6
        $this->where = $where;
124 6
        $order = (empty($order)) ? [$this->primary => 'DESC'] : $order;
125
        $this
126 6
            ->setColumns($columns)
127 6
            ->setQuery(new Select())
128 6
            ->build($this->tablename, $this->columns, $this->where)
129 6
            ->setOrder($order);
130 6
        return $this;
131
    }
132
133
    /**
134
     * count records matching where criterias.
135
     * aliases is formely [columnn => column_alias]
136
     *
137
     * @param array $where
138
     * @param array $aliases
139
     * @return Orm
140
     */
141 2
    public function count(array $where = [], array $aliases = []): Orm
142
    {
143 2
        $this->where = $where;
144 2
        $this->setQuery(new Select());
145 2
        if (empty($aliases)) {
146 1
            $this->query->count();
147
        } else {
148 1
            reset($aliases);
149 1
            $fistKey = key($aliases);
150 1
            $aliasValue = $aliases[$fistKey];
151 1
            $this->query->count($fistKey, $aliasValue);
152
        }
153 2
        return $this->buildWhere($this->where);
154
    }
155
156
    /**
157
     * update a record with columns fields matching where criterias
158
     * @param array $columns
159
     * @param array $where
160
     */
161 1
    public function update(array $columns = [], array $where = []): Orm
162
    {
163 1
        $this->where = $where;
164 1
        return $this->setColumns($columns)
165 1
            ->setQuery(new Update())
166 1
            ->build($this->tablename, $this->columns, $this->where);
167
    }
168
169
    /**
170
     * insert record with columns fields
171
     * @param array $columns
172
     */
173 1
    public function insert(array $columns = []): Orm
174
    {
175
        return $this
176 1
            ->setColumns($columns)
177 1
            ->setQuery(new Insert())
178 1
            ->build($this->tablename, $this->columns, []);
179
    }
180
181
    /**
182
     * delete matching where criterias
183
     * @param array $where
184
     */
185 1
    public function delete(array $where = []): Orm
186
    {
187 1
        $this->where = $where;
188
        return $this
189 1
            ->setQuery(new Delete())
190 1
            ->build($this->tablename, [], $this->where);
191
    }
192
193
    /**
194
     * get primary key
195
     *
196
     * @return string
197
     */
198 1
    public function getPrimary(): string
199
    {
200 1
        return $this->primary;
201
    }
202
203
    /**
204
     * get slot name
205
     *
206
     * @return string
207
     */
208
    public function getSlot(): string
209
    {
210
        return $this->slot;
211
    }
212
213
    /**
214
     * get service container
215
     *
216
     * @return Container
217
     */
218
    public function getContainer(): Container
219
    {
220
        return $this->container;
221
    }
222
223
    /**
224
     * get database name
225
     *
226
     * @return string
227
     */
228
    public function getDatabase(): string
229
    {
230
        return $this->database;
231
    }
232
233
    /**
234
     * builder instance
235
     * @return GenericBuilder
236
     */
237 1
    public function getQueryBuilder(): GenericBuilder
238
    {
239 1
        return $this->queryBuilder;
240
    }
241
242
    /**
243
     * query instance
244
     * @return object
245
     */
246 18
    public function getQuery()
247
    {
248 18
        return $this->query;
249
    }
250
251
    /**
252
     * query builder values
253
     * @return array
254
     */
255 1
    public function getBuilderValues(): array
256
    {
257 1
        $this->getSql();
258 1
        return $this->queryBuilder->getValues();
259
    }
260
261
    /**
262
     * set query instance
263
     *
264
     * @param Select|Update|Insert|Delete $query
265
     * @return Orm
266
     */
267 19
    public function setQuery($query): Orm
268
    {
269 19
        $this->query = $query;
270 19
        return $this;
271
    }
272
273
    /**
274
     * query sql string
275
     * @return string
276
     */
277 3
    public function getSql(): string
278
    {
279 3
        return $this->queryBuilder->write($this->query);
280
    }
281
282
    /**
283
     * build query
284
     *
285
     * @param string $tablename
286
     * @param array $columns
287
     * @param array $where
288
     * @return Orm
289
     */
290 10
    protected function build(string $tablename, array $columns, array $where): Orm
291
    {
292 10
        if (false === is_object($this->getQuery())) {
293 1
            throw new \Exception('Build : Invalid query instance');
294
        }
295 9
        $queryClassname = get_class($this->getQuery());
296
        $allowedClasses = [
297 9
            Update::class, Select::class, Delete::class, Insert::class
298
        ];
299 9
        if (false === in_array($queryClassname, $allowedClasses)) {
300 1
            throw new \Exception('Build : Invalid query type');
301
        }
302 8
        $this->query->setTable($tablename);
303 8
        switch ($queryClassname) {
304
            case Select::class:
305 1
                $this->query->setColumns($columns);
306 1
                break;
307
            case Update::class:
308 3
                if (empty($columns)) {
309 1
                    throw new \Exception(
310 1
                        'Build : Update requires not empty payload'
311
                    );
312
                }
313 2
                if (empty($where)) {
314 1
                    throw new \Exception(
315 1
                        'Build : Update requires at least one condition'
316
                    );
317
                }
318 1
                $this->query->setValues($columns);
319 1
                break;
320
            case Insert::class:
321 2
                if (empty($columns)) {
322 1
                    throw new \Exception(
323 1
                        'Build : Insert requires not empty payload'
324
                    );
325
                }
326 1
                $this->query->setValues($columns);
327 1
                break;
328
            case Delete::class:
329 2
                if (empty($where)) {
330 1
                    throw new \Exception(
331 1
                        'Build : Delete requires at least one condition'
332
                    );
333
                }
334 1
                break;
335
        }
336 4
        return $this->buildWhere($where);
337
    }
338
339
    /**
340
     * build where condition on query
341
     *
342
     * @param array $where
343
     * @return Orm
344
     */
345 1
    protected function buildWhere(array $where): Orm
346
    {
347 1
        if (false === empty($where)) {
348 1
            foreach ($where as $k => $v) {
349 1
                $whereOperator = $this->getWhereOperator($k, $v);
350 1
                $this->query->where()->{$whereOperator}($k, $v);
351
            }
352
        }
353 1
        return $this;
354
    }
355
356
    /**
357
     * check where condition ket values to find operators
358
     *
359
     * @param string $whereColumn
360
     * @return string
361
     */
362 1
    protected function getWhereOperator(string &$whereColumn, $value): string
363
    {
364 1
        $hasArray = is_array($value);
365 1
        $operator = $whereColumn[strlen($whereColumn) - 1];
366 1
        $hasOperator = in_array($operator, self::OPERATORS);
367 1
        if (false === $hasOperator) {
368 1
            return ($hasArray) ? 'in' : 'equals';
369
        }
370 1
        foreach (self::OPERATORS as $op) {
371 1
            $whereColumn = str_replace($op, '', $whereColumn);
372
        }
373 1
        if ($operator == '!') {
374 1
            return ($hasArray) ? 'notIn' : 'notEquals';
375 1
        } elseif ($operator == '<') {
376 1
            return 'lessThan';
377 1
        } elseif ($operator == '>') {
378 1
            return 'greaterThan';
379 1
        } elseif ($operator == '#') {
380 1
            return 'like';
381
        }
382
    }
383
384
    /**
385
     * set query sort order
386
     *
387
     * @param array $orders
388
     * @return Orm
389
     */
390 1
    protected function setOrder(array $orders): Orm
391
    {
392 1
        $this->order = $orders;
393 1
        foreach ($this->order as $k => $v) {
394 1
            $this->query->orderBy($k, $v);
395
        }
396 1
        return $this;
397
    }
398
}
399