Passed
Branch master (ecbf8b)
by Robson
01:09
created

DataLayer::destroy()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
namespace CoffeeCode\DataLayer;
4
5
use PDO;
6
use PDOException;
7
use stdClass;
8
9
/**
10
 * Class DataLayer
11
 * @package CoffeeCode\DataLayer
12
 */
13
class DataLayer
14
{
15
    use CrudTrait;
16
17
    /** @var string $entity database table */
18
    private $entity;
19
20
    /** @var string $primary table primary key field */
21
    private $primary;
22
23
    /** @var array $required table required fields */
24
    private $required;
25
26
    /** @var string */
27
    protected $statement;
28
29
    /** @var string */
30
    protected $params;
31
32
    /** @var int */
33
    protected $order;
34
35
    /** @var int */
36
    protected $limit;
37
38
    /** @var string */
39
    protected $offset;
40
41
    /** @var \PDOException|null */
42
    protected $fail;
43
44
    /** @var object|null */
45
    protected $data;
46
47
    /**
48
     * DataLayer constructor.
49
     * @param string $entity
50
     * @param array $requiredFileds
51
     * @param string $primaryKey
52
     */
53
    public function __construct(string $entity, array $requiredFileds, string $primaryKey = 'id')
54
    {
55
        $this->entity = $entity;
56
        $this->primary = $primaryKey;
57
        $this->required = $requiredFileds;
58
    }
59
60
    /**
61
     * @param $name
62
     * @param $value
63
     */
64
    public function __set($name, $value)
65
    {
66
        if (empty($this->data)) {
67
            $this->data = new stdClass();
68
        }
69
70
        $this->data->$name = $value;
71
    }
72
73
    /**
74
     * @param $name
75
     * @return bool
76
     */
77
    public function __isset($name)
78
    {
79
        return isset($this->data->$name);
80
    }
81
82
    /**
83
     * @param $name
84
     * @return string|null
85
     */
86
    public function __get($name)
87
    {
88
        return ($this->data->$name ?? null);
89
    }
90
91
    /**
92
     * @return object|null
93
     */
94
    public function data(): ?object
95
    {
96
        return $this->data;
97
    }
98
99
    /**
100
     * @return PDOException|null
101
     */
102
    public function fail(): ?PDOException
103
    {
104
        return $this->fail;
105
    }
106
107
    /**
108
     * @param string|null $terms
109
     * @param string|null $params
110
     * @param string $columns
111
     * @return DataLayer
112
     */
113
    public function find(?string $terms = null, ?string $params = null, string $columns = "*"): DataLayer
114
    {
115
        if ($terms) {
116
            $this->statement = "SELECT {$columns} FROM {$this->entity} WHERE {$terms}";
117
            parse_str($params, $this->params);
0 ignored issues
show
Bug introduced by
$this->params of type string is incompatible with the type array|null expected by parameter $arr of parse_str(). ( Ignorable by Annotation )

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

117
            parse_str($params, /** @scrutinizer ignore-type */ $this->params);
Loading history...
118
            return $this;
119
        }
120
121
        $this->statement = "SELECT {$columns} FROM {$this->entity}";
122
        return $this;
123
    }
124
125
    /**
126
     * @param int $id
127
     * @param string $columns
128
     * @return DataLayer|null
129
     */
130
    public function findById(int $id, string $columns = "*"): ?DataLayer
131
    {
132
        $find = $this->find($this->primary . " = :id", "id={$id}", $columns);
133
        return $find->fetch();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $find->fetch() could return the type array which is incompatible with the type-hinted return CoffeeCode\DataLayer\DataLayer|null. Consider adding an additional type-check to rule them out.
Loading history...
134
    }
135
136
    /**
137
     * @param string $columnOrder
138
     * @return DataLayer|null
139
     */
140
    public function order(string $columnOrder): ?DataLayer
141
    {
142
        $this->order = " ORDER BY {$columnOrder}";
0 ignored issues
show
Documentation Bug introduced by
The property $order was declared of type integer, but ' ORDER BY '.$columnOrder is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
143
        return $this;
144
    }
145
146
    /**
147
     * @param int $limit
148
     * @return DataLayer|null
149
     */
150
    public function limit(int $limit): ?DataLayer
151
    {
152
        $this->limit = " LIMIT {$limit}";
0 ignored issues
show
Documentation Bug introduced by
The property $limit was declared of type integer, but ' LIMIT '.$limit is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
153
        return $this;
154
    }
155
156
    /**
157
     * @param int $offset
158
     * @return DataLayer|null
159
     */
160
    public function offset(int $offset): ?DataLayer
161
    {
162
        $this->offset = " OFFSET {$offset}";
163
        return $this;
164
    }
165
166
    /**
167
     * @param bool $all
168
     * @return array|mixed|null
169
     */
170
    public function fetch(bool $all = false)
171
    {
172
        try {
173
            $stmt = Connect::getInstance()->prepare($this->statement . $this->order . $this->limit . $this->offset);
174
            $stmt->execute($this->params);
0 ignored issues
show
Bug introduced by
$this->params of type string is incompatible with the type array expected by parameter $input_parameters of PDOStatement::execute(). ( Ignorable by Annotation )

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

174
            $stmt->execute(/** @scrutinizer ignore-type */ $this->params);
Loading history...
175
176
            if (!$stmt->rowCount()) {
177
                return null;
178
            }
179
180
            if ($all) {
181
                return $stmt->fetchAll(PDO::FETCH_CLASS, static::class);
182
            }
183
184
            return $stmt->fetchObject(static::class);
185
        } catch (PDOException $exception) {
186
            $this->fail = $exception;
187
            return null;
188
        }
189
    }
190
191
    /**
192
     * @return int
193
     */
194
    public function count(): int
195
    {
196
        $stmt = Connect::getInstance()->prepare($this->statement);
197
        $stmt->execute($this->params);
0 ignored issues
show
Bug introduced by
$this->params of type string is incompatible with the type array expected by parameter $input_parameters of PDOStatement::execute(). ( Ignorable by Annotation )

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

197
        $stmt->execute(/** @scrutinizer ignore-type */ $this->params);
Loading history...
198
        return $stmt->rowCount();
199
    }
200
201
    /**
202
     * @return bool
203
     */
204
    public function save(): bool
205
    {
206
        $primary = $this->primary;
207
        $id = null;
208
209
        try {
210
            if (!$this->required()) {
211
                throw new PDOException("Preencha os campos necessários");
212
            }
213
214
            /** Update */
215
            if (!empty($this->data->$primary)) {
216
                $id = $this->data->$primary;
217
                $this->update($this->safe(), $this->primary . " = :id", "id={$id}");
218
            }
219
220
            /** Create */
221
            if (empty($this->data->$primary)) {
222
                $id = $this->create($this->safe());
223
            }
224
225
            $this->data = $this->findById($id)->data();
226
            return true;
227
        } catch (PDOException $exception) {
228
            $this->fail = $exception;
229
            return false;
230
        }
231
    }
232
233
    /**
234
     * @return bool
235
     */
236
    public function destroy(): bool
237
    {
238
        $primary = $this->primary;
239
        $id = $this->data->$primary;
240
241
        if (empty($id)) {
242
            return false;
243
        }
244
245
        $destroy = $this->delete($this->primary . " = :id", "id={$id}");
246
        return $destroy;
247
    }
248
249
    /**
250
     * @return bool
251
     */
252
    protected function required(): bool
253
    {
254
        $data = (array)$this->data();
255
        foreach ($this->required as $field) {
256
            if (empty($data[$field])) {
257
                return false;
258
            }
259
        }
260
        return true;
261
    }
262
263
    /**
264
     * @return array|null
265
     */
266
    protected function safe(): ?array
267
    {
268
        $safe = (array)$this->data;
269
        foreach ([$this->primary, "updated_at", "created_at"] as $unset) {
270
            unset($safe[$unset]);
271
        }
272
273
        return $safe;
274
    }
275
}