Completed
Push — master ( f84b1b...3c5fbc )
by Arman
14s
created

DbModel::relations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 3.0.0
13
 */
14
15
namespace Quantum\Model;
16
17
use Quantum\Libraries\Database\Contracts\DbalInterface;
18
use Quantum\Paginator\Exceptions\PaginatorException;
19
use Quantum\Paginator\Factories\PaginatorFactory;
20
use Quantum\Model\Exceptions\ModelException;
21
use Quantum\App\Exceptions\BaseException;
22
use Quantum\Paginator\Paginator;
23
24
/**
25
 * Class DbModel
26
 * @package Quantum\Model
27
 *
28
 * @method string getTable()
29
 * @method string getModelName()
30
 * @method self select(...$columns)
31
 * @method self criteria(string $column, string $operator, $value = null)
32
 * @method self criterias(...$criterias)
33
 * @method self having(string $column, string $operator, string $value = null)
34
 * @method self orderBy(string $column, string $direction)
35
 * @method self offset(int $offset)
36
 * @method self limit(int $limit)
37
 * @method int count()
38
 * @method bool deleteMany()
39
 * @method self joinTo(DbModel $model, bool $switch = true)
40
 * @method self isNull(string $column)
41
 * @method self isNotNull(string $column)
42
 */
43
abstract class DbModel extends Model
44
{
45
    /**
46
     * Database table
47
     * @var string
48
     */
49
    public string $table = '';
50
51
    /**
52
     * Primary key column
53
     * @var string
54
     */
55
    public string $idColumn = 'id';
56
57
    /**
58
     * ORM instance (Idiorm or SleekDB)
59
     * @var DbalInterface|null
60
     */
61
    protected ?DbalInterface $ormInstance = null;
62
63
    /**
64
     * Set ORM instance
65
     * @param DbalInterface $ormInstance
66
     * @return void
67
     */
68
    public function setOrmInstance(DbalInterface $ormInstance): void
69
    {
70
        $this->ormInstance = $ormInstance;
71
    }
72
73
    /**
74
     * Get ORM instance
75
     * @return DbalInterface
76
     * @throws ModelException
77
     */
78
    public function getOrmInstance(): DbalInterface
79
    {
80
        if (!isset($this->ormInstance)) {
81
            throw ModelException::ormIsNotSet();
82
        }
83
84
        return $this->ormInstance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->ormInstance could return the type null which is incompatible with the type-hinted return Quantum\Libraries\Database\Contracts\DbalInterface. Consider adding an additional type-check to rule them out.
Loading history...
85
    }
86
87
    /**
88
     * @return array
89
     */
90
    public function relations(): array
91
    {
92
        return [];
93
    }
94
95
    /**
96
     * Finds the record by primary key and returns a new model instance
97
     * @param int $id
98
     * @return DbModel|null
99
     * @throws BaseException
100
     */
101
    public function findOne(int $id): ?DbModel
102
    {
103
        $orm = $this->getOrmInstance()->findOne($id);
104
105
        return wrapToModel($orm, static::class);
106
    }
107
108
    /**
109
     * Finds the record by given column and value and returns a new model instance
110
     * @param string $column
111
     * @param mixed $value
112
     * @return DbModel|null
113
     * @throws BaseException
114
     */
115
    public function findOneBy(string $column, $value): ?DbModel
116
    {
117
        $orm = $this->getOrmInstance()->findOneBy($column, $value);
118
119
        return wrapToModel($orm, static::class);
120
    }
121
122
    /**
123
     * Gets the first record and returns a new model instance
124
     * @return DbModel|null
125
     * @throws BaseException
126
     */
127
    public function first(): ?DbModel
128
    {
129
        $orm = $this->getOrmInstance()->first();
130
131
        return wrapToModel($orm, static::class);
132
    }
133
134
    /**
135
     * Fetch multiple results
136
     * @return ModelCollection
137
     * @throws BaseException
138
     */
139
    public function get(): ModelCollection
140
    {
141
        $models = array_map(
142
            fn ($item) => wrapToModel($item, static::class),
143
            $this->getOrmInstance()->get()
144
        );
145
146
        return new ModelCollection($models);
147
    }
148
149
    /**
150
     * Paginates the result
151
     * @param int $perPage
152
     * @param int $currentPage
153
     * @return Paginator
154
     * @throws BaseException
155
     * @throws PaginatorException
156
     */
157
    public function paginate(int $perPage, int $currentPage = 1): Paginator
158
    {
159
        return PaginatorFactory::create(Paginator::MODEL, [
160
            'model' => $this,
161
            'perPage' => $perPage,
162
            'page' => $currentPage,
163
        ]);
164
    }
165
166
    /**
167
     * Creates a new record
168
     * @return $this
169
     * @throws ModelException
170
     */
171
    public function create(): self
172
    {
173
        $this->attributes = [];
174
        $this->getOrmInstance()->create();
175
        return $this;
176
    }
177
178
    /**
179
     * Save model
180
     * @return bool
181
     * @throws ModelException
182
     */
183
    public function save(): bool
184
    {
185
        $this->syncAttributesToOrm();
186
187
        $result = $this->getOrmInstance()->save();
188
189
        $this->syncPrimaryKeyFromOrm();
190
191
        return $result;
192
    }
193
194
    /**
195
     * Delete model
196
     * @return bool
197
     * @throws ModelException
198
     */
199
    public function delete(): bool
200
    {
201
        return $this->getOrmInstance()->delete();
202
    }
203
204
    /**
205
     * @param array $data
206
     * @return $this
207
     */
208
    public function hydrateFromOrm(array $data): self
209
    {
210
        $this->attributes = $data;
211
        return $this;
212
    }
213
214
    /**
215
     * @param string $method
216
     * @param array $args
217
     * @return mixed
218
     * @throws ModelException
219
     */
220
    public function __call(string $method, array $args = [])
221
    {
222
        $orm = $this->getOrmInstance();
223
224
        if (!method_exists($orm, $method)) {
225
            throw ModelException::methodNotSupported(
226
                $method,
227
                get_class($orm)
228
            );
229
        }
230
231
        $result = $orm->{$method}(...$args);
232
233
        return $result instanceof DbalInterface ? $this : $result;
234
    }
235
236
    /**
237
     * @return string[]
238
     */
239
    public function __sleep()
240
    {
241
        return [
242
            'table',
243
            'idColumn',
244
            'hidden',
245
            'attributes',
246
        ];
247
    }
248
249
    /**
250
     * Sync model attributes into ORM
251
     * @return void
252
     * @throws ModelException
253
     */
254
    protected function syncAttributesToOrm(): void
255
    {
256
        $orm = $this->getOrmInstance();
257
258
        foreach ($this->attributes as $key => $value) {
259
            if ($key === $this->idColumn) {
260
                continue;
261
            }
262
263
            $orm->prop($key, $value);
264
        }
265
    }
266
267
    /**
268
     * @param string $key
269
     * @return bool
270
     */
271
    protected function shouldFill(string $key): bool
272
    {
273
        if ($key === $this->idColumn) {
274
            return false;
275
        }
276
277
        return parent::shouldFill($key);
278
    }
279
280
    /**
281
     * Syncs primary key from ORM to model attributes
282
     * @return void
283
     * @throws ModelException
284
     */
285
    private function syncPrimaryKeyFromOrm(): void
286
    {
287
        $id = $this->getOrmInstance()->prop($this->idColumn);
288
289
        if ($id !== null) {
290
            $this->attributes[$this->idColumn] = $id;
291
        }
292
    }
293
}
294