Passed
Push — master ( 0ced5e...1a41ca )
by Pierre
03:06
created

Orm   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 343
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 114
c 1
b 0
f 0
dl 0
loc 343
ccs 111
cts 111
cp 1
rs 9.2
wmc 40

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A find() 0 10 2
A update() 0 6 1
A count() 0 13 2
A setColumns() 0 4 1
A insert() 0 6 1
A delete() 0 6 1
A getSql() 0 3 1
A getQuery() 0 3 1
A getBuilderValues() 0 4 1
A buildWhere() 0 9 3
B build() 0 47 11
A setOrder() 0 7 2
A getQueryBuilder() 0 3 1
B getWhereOperator() 0 19 9
A setQuery() 0 4 1
A getPrimary() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Orm often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Orm, and based on these observations, apply Extract Interface, too.

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 25
    public function __construct(Container $container)
86
    {
87 25
        $this->config = $container->getService(Config::class);
88 25
        $this->queryBuilder = new GenericBuilder();
89 25
        $this->query = null;
90 25
        $this->columns = [];
91 25
        $this->where = [];
92 25
        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
     * get primary key
187
     *
188
     * @return string
189
     */
190 1
    public function getPrimary(): string
191
    {
192 1
        return $this->primary;
193
    }
194
195
    /**
196
     * builder instance
197
     * @return GenericBuilder
198
     */
199 1
    public function getQueryBuilder(): GenericBuilder
200
    {
201 1
        return $this->queryBuilder;
202
    }
203
204
    /**
205
     * query instance
206
     * @return object
207
     */
208 18
    public function getQuery()
209
    {
210 18
        return $this->query;
211
    }
212
213
    /**
214
     * query builder values
215
     * @return array
216
     */
217 1
    public function getBuilderValues(): array
218
    {
219 1
        $this->getSql();
220 1
        return $this->queryBuilder->getValues();
221
    }
222
223
    /**
224
     * set query instance
225
     *
226
     * @param Select|Update|Insert|Delete $query
227
     * @return Orm
228
     */
229 19
    public function setQuery($query): Orm
230
    {
231 19
        $this->query = $query;
232 19
        return $this;
233
    }
234
235
    /**
236
     * query sql string
237
     * @return string
238
     */
239 3
    public function getSql(): string
240
    {
241 3
        return $this->queryBuilder->write($this->query);
242
    }
243
244
    /**
245
     * build query
246
     *
247
     * @param string $tablename
248
     * @param array $columns
249
     * @param array $where
250
     * @return Orm
251
     */
252 10
    protected function build(string $tablename, array $columns, array $where): Orm
253
    {
254 10
        if (false === is_object($this->getQuery())) {
255 1
            throw new \Exception('Build : Invalid query instance');
256
        }
257 9
        $queryClassname = get_class($this->getQuery());
258
        $allowedClasses = [
259 9
            Update::class, Select::class, Delete::class, Insert::class
260
        ];
261 9
        if (false === in_array($queryClassname, $allowedClasses)) {
262 1
            throw new \Exception('Build : Invalid query type');
263
        }
264 8
        $this->query->setTable($tablename);
265 8
        switch ($queryClassname) {
266
            case Select::class:
267 1
                $this->query->setColumns($columns);
268 1
                break;
269
            case Update::class:
270 3
                if (empty($columns)) {
271 1
                    throw new \Exception(
272 1
                        'Build : Update requires not empty payload'
273
                    );
274
                }
275 2
                if (empty($where)) {
276 1
                    throw new \Exception(
277 1
                        'Build : Update requires at least one condition'
278
                    );
279
                }
280 1
                $this->query->setValues($columns);
281 1
                break;
282
            case Insert::class:
283 2
                if (empty($columns)) {
284 1
                    throw new \Exception(
285 1
                        'Build : Insert requires not empty payload'
286
                    );
287
                }
288 1
                $this->query->setValues($columns);
289 1
                break;
290
            case Delete::class:
291 2
                if (empty($where)) {
292 1
                    throw new \Exception(
293 1
                        'Build : Delete requires at least one condition'
294
                    );
295
                }
296 1
                break;
297
        }
298 4
        return $this->buildWhere($where);
299
    }
300
301
    /**
302
     * build where condition on query
303
     *
304
     * @param array $where
305
     * @return Orm
306
     */
307 1
    protected function buildWhere(array $where): Orm
308
    {
309 1
        if (false === empty($where)) {
310 1
            foreach ($where as $k => $v) {
311 1
                $whereOperator = $this->getWhereOperator($k, $v);
312 1
                $this->query->where()->{$whereOperator}($k, $v);
313
            }
314
        }
315 1
        return $this;
316
    }
317
318
    /**
319
     * check where condition ket values to find operators
320
     *
321
     * @param string $whereColumn
322
     * @return string
323
     */
324 1
    protected function getWhereOperator(string &$whereColumn, $value): string
325
    {
326 1
        $hasArray = is_array($value);
327 1
        $operator = $whereColumn[strlen($whereColumn) - 1];
328 1
        $hasOperator = in_array($operator, self::OPERATORS);
329 1
        if (false === $hasOperator) {
330 1
            return ($hasArray) ? 'in' : 'equals';
331
        }
332 1
        foreach (self::OPERATORS as $op) {
333 1
            $whereColumn = str_replace($op, '', $whereColumn);
334
        }
335 1
        if ($operator == '!') {
336 1
            return ($hasArray) ? 'notIn' : 'notEquals';
337 1
        } elseif ($operator == '<') {
338 1
            return 'lessThan';
339 1
        } elseif ($operator == '>') {
340 1
            return 'greaterThan';
341 1
        } elseif ($operator == '#') {
342 1
            return 'like';
343
        }
344
    }
345
346
    /**
347
     * set query sort order
348
     *
349
     * @param array $orders
350
     * @return Orm
351
     */
352 1
    protected function setOrder(array $orders): Orm
353
    {
354 1
        $this->order = $orders;
355 1
        foreach ($this->order as $k => $v) {
356 1
            $this->query->orderBy($k, $v);
357
        }
358 1
        return $this;
359
    }
360
}
361