Passed
Branch master (bf6366)
by Henri
02:19 queued 01:07
created

Datamanager::mountTable_Default()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
rs 10
1
<?php
2
3
namespace HnrAzevedo\Datamanager;
4
5
use Exception;
6
7
abstract class Datamanager
8
{
9
    use CrudTrait;
10
11
    private ?string $table = null;
12
    private ?string $primary = null;
13
    private array $result = [];
14
    protected array $data = [];
15
    
16
    private bool $full = false;
17
    private ?string $clause = null;
18
19
20
    private array $where = [''=> ["1",'=',"1"] ];
21
    private ?string $order = null;
22
    private ?string $limit = null;
23
    private ?int $offset = null;
24
    private array $excepts = [];
25
    private int $count = 0;
26
    private array $select = [];
27
    private ?string $query = null;
28
29
30
    protected function create(string $table, string $primary): Datamanager
31
    {
32
        $this->table = $table;
33
        $this->primary = $primary;
34
        $describe = $this->describe();
35
        
36
        $this->check_fail();
37
38
        $this->mountData($describe);
39
        $this->full = true;
40
        return $this;
41
    }
42
43
    private function mountTable_Field(string $field, $value = null)
44
    {
45
        $this->$field = null;
46
    }
47
48
    private function mountTable_Type(string $field, $value = null)
49
    {
50
        $type = $value;
51
        $maxlength = null;
52
53
        if(strpos($value,'(')){
54
            $type = (array_key_exists( substr($value,0,strpos($value,'(')) , ['varchar','char','text'])) ? 'string' : $type;
55
            $type = (array_key_exists( substr($value,0,strpos($value,'(')) , ['tinyint','mediumint','smallint','bigtint','int'])) ? 'int' : $type;
56
            $type = (array_key_exists( substr($value,0,strpos($value,'(')) , ['decimal','float','double','real'])) ? 'float' : $type;
57
        }
58
59
        $maxlength = (array_key_exists( $type , ['string','float','int'])) ? substr($value,(strpos($value,'(')+1),-1) : $maxlength;
60
        $maxlength = (array_key_exists( $type , ['date'])) ? 10 : $maxlength;
61
        $maxlength = (array_key_exists( $type , ['datetime'])) ? 19 : $maxlength;
62
        $maxlength = (array_key_exists( $type , ['boolean'])) ? 1 : $maxlength;
63
64
        $this->$field = ['maxlength' => $maxlength];
65
        $this->$field = ['type' => $type];
66
    }
67
68
    private function mountTable_Null(string $field, $value = null)
69
    {
70
        $this->$field = ['null' => ($value === 'YES') ? 1 : 0];
71
    }
72
73
    private function mountTable_Key(string $field, $value = null)
74
    {
75
        $this->$field = ['key' => $value];
76
        $this->$field = ['upgradeable' => ($value == 'PRI') ? 0 : 1];
77
    }
78
79
    private function mountTable_Extra(string $field, $value = null)
80
    {
81
        $this->$field = ['extra' => $value];
82
    }
83
84
    private function mountTable_Default(string $field, $value = null)
85
    {
86
        $this->$field = ['default' => $value];
87
        $this->$field = ['value' => null];
88
        $this->$field = ['changed' => false];
89
        $this->select[$field] = true;
90
    }
91
92
    private function mountData(array $table): Datamanager
93
    {
94
        foreach ($table as $column) {
95
            foreach ($column as $propriety => $value) {
96
                $method = "mountTable_{$propriety}";
97
                $this->$method($column['Field'], $value);
98
            }
99
        }
100
        return $this;
101
    }
102
103
    public function __set(string $prop,$value): Datamanager
104
    {
105
106
        if(is_array($value)){
107
            $attr = array_keys($value)[0];
108
            $this->data[$prop][$attr] = $value[$attr];
109
            return $this;
110
        }
111
112
        if($this->full && !array_key_exists($prop,$this->data)){
113
            throw new Exception("{$prop} field does not exist in the table {$this->table}.");
114
        }
115
116
        $this->data[$prop]['changed'] = true;
117
        $this->data[$prop]['value'] = $value;
118
        
119
        return $this;
120
    }
121
122
    public function getData(): ?array
123
    {
124
        return $this->data;
125
    }
126
127
    public function __get(string $field)
128
    {
129
        if($this->full && !array_key_exists($field,$this->data)){
130
            throw new Exception("{$field} field does not exist in the table {$this->table}.");
131
        }
132
133
        return $this->data[$field]['value'];
134
    }
135
136
    public function getCount(): int
137
    {
138
        return $this->count;
139
    }
140
141
    public function except($deniable): Datamanager
142
    {
143
        $deniable = (is_array($deniable)) ? $deniable : [$deniable];
144
145
        foreach ($deniable as $field) {
146
            if(!array_key_exists($field,$this->data)){
147
                throw new Exception("{$field} field does not exist in the table {$this->table}.");
148
            }
149
150
            $this->excepts[$field] = true;
151
        }
152
153
        return $this;
154
    }
155
156
    public function deny(): Datamanager
157
    {
158
        foreach ($this->excepts as $field => $value) {
159
            unset($this->select[$field]);
160
        }
161
        return $this;
162
    }
163
164
    public function orderBy(string $field, string $ord = 'ASC'): Datamanager
165
    {
166
        if(!array_key_exists(str_replace(['asc','ASC','desc','DESC',' '],'',$field),$this->data) && $this->full){
167
            throw new Exception("{$field} field does not exist in the table {$this->table}.");
168
        }
169
170
        if(strpos(strtolower($field),'asc') || strpos(strtolower($field),'desc')){
171
            $ord = '';
172
        }
173
174
        $this->order = " ORDER BY {$field} {$ord} ";
175
        return $this;
176
    }
177
178
    public function only($params): Datamanager
179
    {
180
        $params = (is_array($params)) ? $params : [$params];
181
        $this->select = [];
182
183
        foreach ($params as $field) {
184
185
            if(!array_key_exists($field,$this->data) && $this->full){
186
                throw new Exception("{$field} field does not exist in the table {$this->table}.");
187
            }
188
189
            $this->select[$field] = true;
190
        }
191
        $this->select[$this->primary] = true;
192
193
        return $this;
194
    }
195
196
    public function where(array $where): Datamanager
197
    {
198
        $this->where['AND'] = (array_key_exists('AND',$this->where)) ?? '';
199
        $w = [];
200
        foreach ($where as $condition => $values) {
201
202
            if(!is_array($values)){
203
                $w['AND'][] = $values;
204
                continue;
205
            }
206
207
            $this->check_where_array($values);
208
209
            $w[(is_int($condition) ? 'AND' : $condition)][] = $values;
210
                       
211
        }
212
213
        $this->where = array_merge($this->where,$w);
214
215
        return $this;
216
    }
217
218
    public function check_where_array(array $where)
219
    {
220
        if(count($where) != 3){
221
            throw new Exception("Condition where set incorrectly: ".implode(' ',$where));
222
        }
223
224
        if(!array_key_exists($where[0],$this->data) && $this->full){
225
            throw new Exception("{$where[0]} field does not exist in the table {$this->table}.");
226
        }
227
    }
228
229
    public function limit(string $limit): Datamanager
230
    {
231
        $this->limit = $limit;
232
        return $this;
233
    }
234
235
    public function offset(int $offset): Datamanager
236
    {
237
        if(is_null($this->limit)){
238
            throw new Exception("The limit must be set before the offset.");
239
        }
240
241
        $this->offset = $offset;
242
        return $this;
243
    }
244
245
    public function result(): array
246
    {
247
        return $this->result;
248
    }
249
250
    public function first(): Datamanager
251
    {
252
        return  (count($this->result) > 0) ? $this->setByDatabase($this->result[0]) : $this;
253
    }
254
255
    public function setByDatabase(array $arrayValues): Datamanager
256
    {
257
        $clone = clone $this;
258
        
259
        $clone->result = [
260
            0 => $this->result[0]
261
        ];
262
263
        $clone->count = 1;
264
265
        foreach ($arrayValues as $key => $value) {
266
267
            if(!array_key_exists($key,$this->data)){
268
                throw new Exception("{$key} field does not exist in the table {$this->table}.");
269
            }
270
271
            $clone->data[$key]['value'] = $value;
272
        }
273
        return $clone;
274
    }
275
276
    public function toJson(): string
277
    {
278
        $string = '';
279
        foreach ($this->data as $key => $value) {
280
281
            if(gettype($value)==='object'){
282
                $value = $value->getData()[$this->primary]['value'];
283
            }
284
285
            $string .= '"'.$key.'"'.':"'.$value.'",';
286
        }
287
        return str_replace(',}', '}', '{'.$string.'}');
288
    }
289
290
    private function mountRemove(): array
291
    {
292
        $return = ['data' => null, 'where' => null];
293
        foreach($this->where as $clause => $condition){
294
            if(strlen($clause) === 0){
295
                $return['where'] .= " {$clause} {$condition[0]} {$condition[1]} :q_{$condition[0]} ";
296
                $return['data'] .= "q_{$condition[0]}={$condition[2]}&";
297
                continue;
298
            }
299
                
300
            foreach($condition as $value){
301
                $return['where'] .= " {$clause} {$value[0]} {$value[1]} :q_{$value[0]} ";
302
                $return['data'] .= "q_{$value[0]}={$value[2]}&";
303
            }
304
        }
305
        return $return;
306
    }   
307
308
    public function remove(?bool $exec = false): Datamanager
309
    {
310
        if(!$exec){
0 ignored issues
show
Bug Best Practice introduced by
The expression $exec of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
311
            $this->clause = 'remove';    
312
            return $this;
313
        }
314
315
        $this->clause = null;
316
317
        if(count($this->where) == 1){
318
            $this->removeById();
319
            return $this;
320
        }
321
322
        $this->delete($this->mountRemove()['where'], substr( $this->mountRemove()['data'] ,0,-1) );
323
324
        $this->check_fail();
325
            
326
        return $this;
327
    }
328
329
    private function removeById(): bool
330
    {
331
        $delete = $this->delete("{$this->primary}=:{$this->primary}","{$this->primary}={$this->getData()[$this->primary]['value']}");
332
333
        $this->check_fail();
334
335
        return $delete;
336
    }
337
338
    private function mountSave(): array
339
    {
340
        $return = ['data' => null];
341
342
        foreach ($this->data as $key => $value) {
343
            if(strstr($this->data[$key]['extra'],'auto_increment') && $key !== $this->primary){
344
                continue;
345
            }
346
347
            if(($this->data[$key]['changed'] && $this->data[$key]['upgradeable']) || $this->primary === $key){
348
                $return['data'][$key] = $this->data[$key]['value'];
349
            }
350
        }
351
352
        return $return;
353
    }
354
355
    public function save(): Datamanager
356
    {
357
        
358
        $this->transaction('begin');
359
360
        try{
361
            $this->update(
362
                $this->mountSave()['data'],
0 ignored issues
show
Bug introduced by
$this->mountSave()['data'] of type null is incompatible with the type array expected by parameter $data of HnrAzevedo\Datamanager\Datamanager::update(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

362
                /** @scrutinizer ignore-type */ $this->mountSave()['data'],
Loading history...
363
                "{$this->primary}=:{$this->primary}", 
364
                $this->primary.'='.$this->getData()[$this->primary]['value']
365
            );
366
367
            $this->check_fail();
368
369
            $this->transaction('commit');
370
        }catch(Exception $er){
371
            $this->transaction('rollback');
372
            throw $er;
373
        }
374
375
        return $this;
376
    }
377
378
    public function persist(): Datamanager
379
    {
380
        $columns = '';
381
        $values = '';
382
        $data = [];
383
384
        foreach ($this->data as $key => $value) {
385
            if(strstr($this->data[$key]['extra'],'auto_increment')){
386
                continue;
387
            }
388
389
            if(strlen($value['value']) > $value['maxlength']){
390
                throw new Exception("The information provided for column {$key} of table {$this->table} exceeded that allowed.");
391
            }
392
393
            $columns .= $key.',';
394
            $values .= ':'.$key.',';
395
            $data[$key] = $value['value'];
396
        }
397
398
        $this->transaction('begin');
399
        try{
400
           
401
            $id = $this->insert($data);
402
403
            $this->check_fail();
404
405
            $this->getData()[$this->primary]['value'] = $id;
406
            
407
            $this->transaction('commit');
408
409
        }catch(Exception $er){
410
            $this->transaction('rollback');
411
            throw $er;
412
        }
413
414
        return $this;
415
    }
416
417
    public function toEntity()
418
    {
419
        if($this->getCount() === 0){
420
            return null;
421
        }
422
423
        $entity = $this->setByDatabase($this->result[0]);
424
425
        if(count($this->result) > 1){
426
            $entity = [];
427
            foreach ($this->result as $key => $value) {
428
                $entity[] = $this->setByDatabase($value);
429
            }
430
        }
431
432
        return $entity;
433
    }
434
435
    public function findById($id): Datamanager
436
    {
437
        $this->where([$this->primary,'=',$id]);
438
        return $this;
439
    }
440
441
    private function mountWhereExec(): array
442
    {
443
        $return = ['where' => null, 'data' => null];
444
445
        foreach ($this->where as $key => $value) {
446
447
            $key = (!$key) ? '' : " {$key} ";
448
449
            if(is_array($value[0])){
450
451
                foreach ($value as $k => $v) {
452
                    $return['where'] .= " {$key} {$v[0]} {$v[1]} :q_{$v[0]} ";
453
                    $return['data']["q_{$v[0]}"] = $v[2];
454
                }
455
456
                continue;
457
            }
458
             
459
            $return['where'] .= " {$key} {$value[0]} {$value[1]} :q_{$value[0]} ";
460
            $return['data']["q_{$value[0]}"] = $value[2];
461
462
        }
463
        return $return;
464
    }
465
466
    public function execute(): Datamanager
467
    {
468
        if(!is_null($this->clause) && $this->clause == 'remove'){
469
            return $this->remove(true);
470
        }
471
472
        $this->deny();
473
        
474
        $this->mountSelect();
475
        
476
        $where = substr($this->mountWhereExec()['where'],0,-1);
477
        $this->query .= " WHERE {$where} ";
478
479
        $this->query .= $this->order;
480
       
481
        $this->mountLimit();
482
        $this->mountOffset();
483
484
        $this->result = $this->select($this->query, $this->mountWhereExec()['data']);
485
486
        $this->check_fail();
487
488
        $this->count = count($this->result);
489
        $this->query = null;
490
491
        return $this;
492
    }
493
494
    private function mountSelect()
495
    {
496
        $select = implode(',',array_keys($this->select));
497
498
        $this->query = str_replace('*', $select,$this->query);
499
    }
500
501
    private function mountLimit()
502
    {
503
        if(!is_null($this->limit)){
504
            $this->query .= " LIMIT {$this->limit}";
505
        }
506
    }
507
508
    private function mountOffset()
509
    {
510
        if(!is_null($this->offset)){
511
            $this->query .= " OFFSET {$this->offset}";
512
        }
513
    }
514
515
    public function find(?int $key = null): Datamanager
516
    {
517
        $this->query = " SELECT * FROM {$this->table} ";
518
519
        if(is_int($key)){
520
            return $this->findById($key);
521
        }
522
523
        return $this;
524
    }
525
526
}
527