Passed
Pull Request — master (#410)
by Arman
03:10
created

DbModel::getOrmInstance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
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 static select(...$columns)
31
 * @method static criteria(string $column, string $operator, $value = null)
32
 * @method static criterias(...$criterias)
33
 * @method static having(string $column, string $operator, string $value = null)
34
 * @method static orderBy(string $column, string $direction)
35
 * @method static offset(int $offset)
36
 * @method static limit(int $limit)
37
 * @method int count()
38
 * @method bool deleteMany()
39
 * @method static joinTo(DbModel $model, bool $switch = true)
40
 * @method static isNull(string $column)
41
 * @method static isNotNull(string $column)
42
 * /
43
 */
44
abstract class DbModel extends Model
45
{
46
    /**
47
     * Database table
48
     * @var string
49
     */
50
    public string $table = '';
51
52
    /**
53
     * Primary key column
54
     * @var string
55
     */
56
    public string $idColumn = 'id';
57
58
    /**
59
     * ORM instance (Idiorm or SleekDB)
60
     * @var DbalInterface|null
61
     */
62
    protected ?DbalInterface $ormInstance = null;
63
64
    /**
65
     * Set ORM instance
66
     * @param DbalInterface $ormInstance
67
     * @return void
68
     */
69
    public function setOrmInstance(DbalInterface $ormInstance): void
70
    {
71
        $this->ormInstance = $ormInstance;
72
    }
73
74
    /**
75
     * Get ORM instance
76
     * @return DbalInterface
77
     * @throws ModelException
78
     */
79
    public function getOrmInstance(): DbalInterface
80
    {
81
        if (!isset($this->ormInstance)) {
82
            throw ModelException::ormIsNotSet();
83
        }
84
85
        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...
86
    }
87
88
    /**
89
     * @return array
90
     */
91
    public function relations(): array
92
    {
93
        return [];
94
    }
95
96
    /**
97
     * Finds the record by primary key and returns a new model instance
98
     * @param int $id
99
     * @return DbModel|null
100
     * @throws BaseException
101
     */
102
    public function findOne(int $id): ?DbModel
103
    {
104
        $orm = $this->ormInstance->findOne($id);
0 ignored issues
show
Bug introduced by
The method findOne() does not exist on null. ( Ignorable by Annotation )

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

104
        /** @scrutinizer ignore-call */ 
105
        $orm = $this->ormInstance->findOne($id);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
106
        return wrapToModel($orm, static::class);
107
    }
108
109
    /**
110
     * Finds the record by given column and value and returns a new model instance
111
     * @param string $column
112
     * @param mixed $value
113
     * @return DbModel|null
114
     * @throws BaseException
115
     */
116
    public function findOneBy(string $column, $value): ?DbModel
117
    {
118
        $orm = $this->ormInstance->findOneBy($column, $value);
119
120
        return wrapToModel($orm, static::class);
121
    }
122
123
    /**
124
     * Gets the first record and returns a new model instance
125
     * @return DbModel|null
126
     * @throws BaseException
127
     */
128
    public function first(): ?DbModel
129
    {
130
        $orm = $this->ormInstance->first();
131
132
        return wrapToModel($orm, static::class);
133
    }
134
135
    /**
136
     * Fetch multiple results
137
     * @return ModelCollection
138
     * @throws BaseException
139
     */
140
    public function get(): ModelCollection
141
    {
142
        $models = array_map(
143
            fn ($item) => wrapToModel($item, static::class),
144
            $this->ormInstance->get()
145
        );
146
147
        return new ModelCollection($models);
148
    }
149
150
    /**
151
     * Paginates the result
152
     * @param int $perPage
153
     * @param int $currentPage
154
     * @return Paginator
155
     * @throws BaseException
156
     * @throws PaginatorException
157
     */
158
    public function paginate(int $perPage, int $currentPage = 1): Paginator
159
    {
160
        return PaginatorFactory::create(Paginator::MODEL, [
161
            'model' => $this,
162
            'perPage' => $perPage,
163
            'page' => $currentPage,
164
        ]);
165
    }
166
167
    /**
168
     * Creates a new record
169
     * @return $this
170
     */
171
    public function create(): self
172
    {
173
        $this->attributes = [];
174
        $this->ormInstance->create();
175
        return $this;
176
    }
177
178
    /**
179
     * Save model
180
     * @return bool
181
     */
182
    public function save(): bool
183
    {
184
        $this->syncAttributesToOrm();
185
186
        $result = $this->ormInstance->save();
187
188
        $this->syncPrimaryKeyFromOrm();
189
190
        return $result;
191
    }
192
193
    /**
194
     * Delete model
195
     * @return bool
196
     */
197
    public function delete(): bool
198
    {
199
        return $this->ormInstance->delete();
200
    }
201
202
    /**
203
     * @param array $data
204
     * @return $this
205
     */
206
    public function hydrateFromOrm(array $data): DbModel
207
    {
208
        $this->attributes = $data;
209
        return $this;
210
    }
211
212
    /**
213
     * @param string $method
214
     * @param $args
215
     * @return $this|DbModel
216
     * @throws ModelException
217
     */
218
    public function __call(string $method, $args = null)
219
    {
220
        if (!method_exists($this->ormInstance, $method)) {
221
            throw ModelException::methodNotSupported(
222
                $method,
223
                get_class($this->ormInstance)
0 ignored issues
show
Bug introduced by
It seems like $this->ormInstance can also be of type null; however, parameter $object of get_class() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

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

223
                get_class(/** @scrutinizer ignore-type */ $this->ormInstance)
Loading history...
224
            );
225
        }
226
227
        $result = $this->ormInstance->{$method}(...$args);
228
229
        return $result instanceof DbalInterface ? $this : $result;
230
    }
231
232
    /**
233
     * @return string[]
234
     */
235
    public function __sleep()
236
    {
237
        return [
238
            'table',
239
            'idColumn',
240
            'hidden',
241
        ];
242
    }
243
244
    /**
245
     * Sync model attributes into ORM
246
     * @return void
247
     */
248
    protected function syncAttributesToOrm(): void
249
    {
250
        foreach ($this->attributes as $key => $value) {
251
            $this->ormInstance->prop($key, $value);
252
        }
253
    }
254
255
    /**
256
     * @param string $key
257
     * @return bool
258
     */
259
    protected function shouldFill(string $key): bool
260
    {
261
        if ($key === $this->idColumn) {
262
            return false;
263
        }
264
265
        return parent::shouldFill($key);
266
    }
267
268
    /**
269
     * Syncs primary key from ORM to model attributes
270
     * @return void
271
     */
272
    private function syncPrimaryKeyFromOrm(): void
273
    {
274
        $id = $this->ormInstance->prop($this->idColumn);
275
276
        if ($id !== null) {
277
            $this->attributes[$this->idColumn] = $id;
278
        }
279
    }
280
}
281