Completed
Push — master ( b074c6...0ced5e )
by Pierre
03:18
created

Orm::setOrder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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