Passed
Push — master ( ae9656...8b853b )
by Henri
01:13
created

DataTrait::remove()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 10
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 19
rs 9.9332
1
<?php
2
3
namespace HnrAzevedo\Datamanager;
4
5
use Exception;
6
7
trait DataTrait{
8
    protected ?string $table = null;
9
    protected ?string $primary = null;
10
11
    protected ?string $order = null;
12
    protected ?string $limit = null;
13
    protected ?int $offset = null;
14
    protected array $excepts = [];
15
    protected int $count = 0;
16
    protected array $select = [];
17
    protected ?string $query = null;
18
19
    protected function create(string $table, string $primary): Datamanager
20
    {
21
        $this->table = $table;
22
        $this->primary = $primary;
23
        $describe = $this->describe();
0 ignored issues
show
Bug introduced by
It seems like describe() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

23
        /** @scrutinizer ignore-call */ 
24
        $describe = $this->describe();
Loading history...
24
        
25
        $this->check_fail();
0 ignored issues
show
Bug introduced by
It seems like check_fail() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

25
        $this->/** @scrutinizer ignore-call */ 
26
               check_fail();
Loading history...
26
27
        $this->mountData($describe);
0 ignored issues
show
Bug introduced by
It seems like mountData() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

27
        $this->/** @scrutinizer ignore-call */ 
28
               mountData($describe);
Loading history...
28
        $this->full = true;
0 ignored issues
show
Bug Best Practice introduced by
The property full does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
29
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
30
    }
31
32
    public function __set(string $prop,$value): Datamanager
33
    {
34
35
        if(is_array($value)){
36
            $attr = array_keys($value)[0];
37
            $this->data[$prop][$attr] = $value[$attr];
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
38
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
39
        }
40
41
        if($this->full && !array_key_exists($prop,$this->data)){
42
            throw new Exception("{$prop} field does not exist in the table {$this->table}.");
43
        }
44
45
        $this->data[$prop]['changed'] = true;
46
        $this->data[$prop]['value'] = $value;
47
        
48
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
49
    }
50
51
    public function getData(): ?array
52
    {
53
        return $this->data;
54
    }
55
56
    public function __get(string $field)
57
    {
58
        if($this->full && !array_key_exists($field,$this->data)){
59
            throw new Exception("{$field} field does not exist in the table {$this->table}.");
60
        }
61
62
        return $this->data[$field]['value'];
63
    }
64
65
    public function getCount(): int
66
    {
67
        return $this->count;
68
    }
69
70
    public function except($deniable): Datamanager
71
    {
72
        $deniable = (is_array($deniable)) ? $deniable : [$deniable];
73
74
        foreach ($deniable as $field) {
75
            if(!array_key_exists($field,$this->data)){
76
                throw new Exception("{$field} field does not exist in the table {$this->table}.");
77
            }
78
79
            $this->excepts[$field] = true;
80
        }
81
82
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
83
    }
84
85
    public function deny(): Datamanager
86
    {
87
        foreach ($this->excepts as $field => $value) {
88
            unset($this->select[$field]);
89
        }
90
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
91
    }
92
93
    public function orderBy(string $field, string $ord = 'ASC'): Datamanager
94
    {
95
        if(!array_key_exists(str_replace(['asc','ASC','desc','DESC',' '],'',$field),$this->data) && $this->full){
96
            throw new Exception("{$field} field does not exist in the table {$this->table}.");
97
        }
98
99
        if(strpos(strtolower($field),'asc') || strpos(strtolower($field),'desc')){
100
            $ord = '';
101
        }
102
103
        $this->order = " ORDER BY {$field} {$ord} ";
104
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
105
    }
106
107
    public function only($params): Datamanager
108
    {
109
        $params = (is_array($params)) ? $params : [$params];
110
        $this->select = [];
111
112
        foreach ($params as $field) {
113
114
            if(!array_key_exists($field,$this->data) && $this->full){
115
                throw new Exception("{$field} field does not exist in the table {$this->table}.");
116
            }
117
118
            $this->select[$field] = true;
119
        }
120
        $this->select[$this->primary] = true;
121
122
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
123
    }
124
125
    public function where(array $where): Datamanager
126
    {
127
        $this->where['AND'] = (array_key_exists('AND',$this->where)) ?? '';
0 ignored issues
show
Bug Best Practice introduced by
The property where does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
128
        $w = [];
129
        foreach ($where as $condition => $values) {
130
131
            if(!is_array($values)){
132
                $w['AND'][] = $values;
133
                continue;
134
            }
135
136
            $this->check_where_array($values);
0 ignored issues
show
Bug introduced by
It seems like check_where_array() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

136
            $this->/** @scrutinizer ignore-call */ 
137
                   check_where_array($values);
Loading history...
137
138
            $w[(is_int($condition) ? 'AND' : $condition)][] = $values;
139
                       
140
        }
141
142
        $this->where = array_merge($this->where,$w);
143
144
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
145
    }
146
147
    public function limit(string $limit): Datamanager
148
    {
149
        $this->limit = $limit;
150
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
151
    }
152
153
    public function offset(int $offset): Datamanager
154
    {
155
        if(is_null($this->limit)){
156
            throw new Exception("The limit must be set before the offset.");
157
        }
158
159
        $this->offset = $offset;
160
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
161
    }
162
163
    public function result(): array
164
    {
165
        return $this->result;
166
    }
167
168
    public function first(): Datamanager
169
    {
170
        return  (count($this->result) > 0) ? $this->setByDatabase($this->result[0]) : $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return count($this->resu...his->result[0]) : $this could return the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager. Consider adding an additional type-check to rule them out.
Loading history...
171
    }
172
173
    public function setByDatabase(array $arrayValues): Datamanager
174
    {
175
        $clone = clone $this;
176
        
177
        $clone->result = [
0 ignored issues
show
Bug Best Practice introduced by
The property result does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
178
            0 => $this->result[0]
179
        ];
180
181
        $clone->count = 1;
182
183
        foreach ($arrayValues as $key => $value) {
184
185
            if(!array_key_exists($key,$this->data)){
186
                throw new Exception("{$key} field does not exist in the table {$this->table}.");
187
            }
188
189
            $clone->data[$key]['value'] = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
190
        }
191
        return $clone;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $clone returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
192
    }
193
194
    public function toJson(): string
195
    {
196
        $string = '';
197
        foreach ($this->data as $key => $value) {
198
199
            if(gettype($value)==='object'){
200
                $value = $value->getData()[$this->primary]['value'];
201
            }
202
203
            $string .= '"'.$key.'"'.':"'.$value.'",';
204
        }
205
        return str_replace(',}', '}', '{'.$string.'}');
206
    }
207
208
    public function remove(?bool $exec = false): Datamanager
209
    {
210
        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...
211
            $this->clause = 'remove';    
0 ignored issues
show
Bug Best Practice introduced by
The property clause does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
212
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
213
        }
214
215
        $this->clause = null;
216
217
        if(count($this->where) == 1){
218
            $this->removeById();
219
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
220
        }
221
222
        $this->delete($this->mountRemove()['where'], substr( $this->mountRemove()['data'] ,0,-1) );
0 ignored issues
show
Bug introduced by
It seems like mountRemove() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

222
        $this->delete($this->/** @scrutinizer ignore-call */ mountRemove()['where'], substr( $this->mountRemove()['data'] ,0,-1) );
Loading history...
Bug introduced by
It seems like delete() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

222
        $this->/** @scrutinizer ignore-call */ 
223
               delete($this->mountRemove()['where'], substr( $this->mountRemove()['data'] ,0,-1) );
Loading history...
223
224
        $this->check_fail();
225
            
226
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
227
    }
228
229
    private function removeById(): bool
230
    {
231
        $delete = $this->delete("{$this->primary}=:{$this->primary}","{$this->primary}={$this->getData()[$this->primary]['value']}");
232
233
        $this->check_fail();
234
235
        return $delete;
236
    }
237
238
    public function persist(): Datamanager
239
    {
240
        $columns = '';
241
        $values = '';
242
        $data = [];
243
244
        foreach ($this->data as $key => $value) {
245
            if(strstr($this->data[$key]['extra'],'auto_increment')){
246
                continue;
247
            }
248
249
            if(strlen($value['value']) > $value['maxlength']){
250
                throw new Exception("The information provided for column {$key} of table {$this->table} exceeded that allowed.");
251
            }
252
253
            $columns .= $key.',';
254
            $values .= ':'.$key.',';
255
            $data[$key] = $value['value'];
256
        }
257
258
        $this->transaction('begin');
0 ignored issues
show
Bug introduced by
It seems like transaction() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

258
        $this->/** @scrutinizer ignore-call */ 
259
               transaction('begin');
Loading history...
259
        try{
260
           
261
            $id = $this->insert($data);
0 ignored issues
show
Bug introduced by
It seems like insert() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

261
            /** @scrutinizer ignore-call */ 
262
            $id = $this->insert($data);
Loading history...
262
263
            $this->check_fail();
264
265
            $this->getData()[$this->primary]['value'] = $id;
266
            
267
            $this->transaction('commit');
268
269
        }catch(Exception $er){
270
            $this->transaction('rollback');
271
            throw $er;
272
        }
273
274
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
275
    }
276
277
    public function toEntity()
278
    {
279
        if($this->getCount() === 0){
280
            return null;
281
        }
282
283
        $entity = $this->setByDatabase($this->result[0]);
284
285
        if(count($this->result) > 1){
286
            $entity = [];
287
            foreach ($this->result as $key => $value) {
288
                $entity[] = $this->setByDatabase($value);
289
            }
290
        }
291
292
        return $entity;
293
    }
294
295
    public function findById($id): Datamanager
296
    {
297
        $this->where([$this->primary,'=',$id]);
298
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
299
    }
300
301
    public function execute(): Datamanager
302
    {
303
        if(!is_null($this->clause) && $this->clause == 'remove'){
304
            return $this->remove(true);
305
        }
306
307
        $this->deny();
308
        
309
        $this->mountSelect();
0 ignored issues
show
Bug introduced by
It seems like mountSelect() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

309
        $this->/** @scrutinizer ignore-call */ 
310
               mountSelect();
Loading history...
310
        
311
        $where = substr($this->mountWhereExec()['where'],0,-1);
0 ignored issues
show
Bug introduced by
It seems like mountWhereExec() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

311
        $where = substr($this->/** @scrutinizer ignore-call */ mountWhereExec()['where'],0,-1);
Loading history...
312
        $this->query .= " WHERE {$where} ";
313
314
        $this->query .= $this->order;
315
       
316
        $this->mountLimit();
0 ignored issues
show
Bug introduced by
It seems like mountLimit() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

316
        $this->/** @scrutinizer ignore-call */ 
317
               mountLimit();
Loading history...
317
        $this->mountOffset();
0 ignored issues
show
Bug introduced by
It seems like mountOffset() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

317
        $this->/** @scrutinizer ignore-call */ 
318
               mountOffset();
Loading history...
318
319
        $this->result = $this->select($this->query, $this->mountWhereExec()['data']);
0 ignored issues
show
Bug introduced by
It seems like select() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

319
        /** @scrutinizer ignore-call */ 
320
        $this->result = $this->select($this->query, $this->mountWhereExec()['data']);
Loading history...
Bug Best Practice introduced by
The property result does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
320
321
        $this->check_fail();
322
323
        $this->count = count($this->result);
324
        $this->query = null;
325
326
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
327
    }
328
329
    public function find(?int $key = null): Datamanager
330
    {
331
        $this->query = " SELECT * FROM {$this->table} ";
332
333
        if(is_int($key)){
334
            return $this->findById($key);
335
        }
336
337
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type HnrAzevedo\Datamanager\DataTrait which includes types incompatible with the type-hinted return HnrAzevedo\Datamanager\Datamanager.
Loading history...
338
    }
339
340
}