Passed
Push — main ( a077ec...e0d381 )
by Pranjal
02:18
created

Model::getForeignModels()   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 1
dl 0
loc 3
rs 10
1
<?php
2
declare(strict_types=1);
3
namespace Scrawler\Arca;
4
5
/**
6
 * Model class that represents single record in database
7
 */
8
class Model
9
{
10
    private array $properties = array();
11
    private string $table;
12
    private $_id = 0;
13
    private array $__meta = [];
14
    private \Scrawler\Arca\Database $db;
15
16
17
    public function __construct(string $name, Database $db)
18
    {
19
        $this->db = $db;
20
        $this->table = $name;
21
        $this->__meta['has_foreign']['oto'] = false;
22
        $this->__meta['has_foreign']['otm'] = false;
23
        $this->__meta['has_foreign']['mtm'] = false;
24
        $this->__meta['is_loaded'] = false;
25
        $this->__meta['foreign_models']['otm'] = [];
26
        $this->__meta['foreign_models']['oto'] = [];
27
        $this->__meta['foreign_models']['mtm'] = [];
28
    }
29
30
    /**
31
     * adds the key to properties
32
     *
33
     * @param String $key
34
     * @param Mixed $val
35
     */
36
    public function __set(string $key, mixed $val): void
37
    {
38
        $this->set($key, $val);
39
    }
40
41
    /**
42
     * adds the key to properties
43
     *
44
     * @param String $key
45
     * @param Mixed $val
46
     */
47
    public function set(string $key, mixed $val): void
48
    {
49
        //bug: fix issue with bool storage
50
        if (gettype($val) == 'boolean') {
51
            ($val) ? $val = 1 : $val = 0;
52
        }
53
54
        if (preg_match('/[A-Z]/', $key)) {
55
            $parts = preg_split('/(?=[A-Z])/', $key, -1, PREG_SPLIT_NO_EMPTY);
56
            if (strtolower($parts[0]) == 'own') {
57
                if (gettype($val) == 'array') {
58
                    array_push($this->__meta['foreign_models']['otm'], $val);
59
                    $this->__meta['has_foreign']['otm'] = true;
60
                }
61
                return;
62
            }
63
            if (strtolower($parts[0]) == 'shared') {
64
                if (gettype($val) == 'array') {
65
                    array_push($this->__meta['foreign_models']['mtm'], $val);
66
                    $this->__meta['has_foreign']['mtm'] = true;
67
                }
68
                return;
69
            }
70
        }
71
        if ($val instanceof Model) {
72
            $this->__meta['has_foreign']['oto'] = true;
73
            array_push($this->__meta['foreign_models']['oto'], $val);
74
            return;
75
        }
76
77
        $this->properties[$key] = $val;
78
    }
79
80
    /**
81
     * Get a key from properties, keys can be relational
82
     * like sharedList,ownList or foreign table
83
     * @param string $key
84
     * @return mixed
85
     */
86
    public function __get(string $key): mixed
87
    {
88
        return $this->get($key);
89
    }
90
91
    /**
92
     * Get a key from properties, keys can be relational
93
     * like sharedList,ownList or foreign table
94
     * @param string $key
95
     * @return mixed
96
     */
97
    public function get(string $key)
98
    {
99
100
        if (preg_match('/[A-Z]/', $key)) {
101
            $parts = preg_split('/(?=[A-Z])/', $key, -1, PREG_SPLIT_NO_EMPTY);
102
            if (strtolower($parts[0]) == 'own') {
103
                if (strtolower($parts[2]) == 'list') {
104
                    return $this->db->find(strtolower($parts[1]))->where($this->getName() . '_id = "' . $this->_id . '"')->get();
105
                }
106
            }
107
            if (strtolower($parts[0]) == 'shared') {
108
                if (strtolower($parts[2]) == 'list') {
109
                    $rel_table = $this->db->getTableManager()->tableExists($this->table . '_' . strtolower($parts[1])) ? $this->table . '_' . strtolower($parts[1]) : strtolower($parts[1]) . '_' . $this->table;
110
                    $relations = $this->db->find($rel_table)->where($this->getName() . '_id = "' . $this->_id . '"')->get();
111
                    $rel_ids = '';
112
                    foreach ($relations as $relation) {
113
                        $key = strtolower($parts[1]) . '_id';
114
                        $rel_ids .= "'" . $relation->$key . "',";
115
                    }
116
                    $rel_ids = substr($rel_ids, 0, -1);
117
                    return $this->db->find(strtolower($parts[1]))->where('id IN (' . $rel_ids . ')')->get();
118
                }
119
            }
120
        }
121
122
        if (array_key_exists($key, $this->properties)) {
123
            return $this->properties[$key];
124
        }
125
126
        if (array_key_exists($key . '_id', $this->properties)) {
127
            return $this->db->get($key, $this->properties[$key . '_id']);
128
        }
129
130
        throw new Exception\KeyNotFoundException();
131
    }
132
133
    public function with(array $relations) : Model
134
    {
135
        foreach ($relations as $relation) {
136
            $this->get($relation);
137
        }
138
        return $this;
139
    }
140
141
142
    /**
143
     * Unset a property from model
144
     *
145
     * @param string $key
146
     */
147
    public function __unset(string $key): void
148
    {
149
        $this->unset($key);
150
    }
151
152
    /**
153
     * Unset a property from model
154
     *
155
     * @param string $key
156
     */
157
    public function unset(string $key): void
158
    {
159
        unset($this->properties[$key]);
160
    }
161
162
    /**
163
     * Check if property exists
164
     *
165
     * @param string $key
166
     * @return boolean
167
     */
168
    public function __isset(string $key): bool
169
    {
170
        return $this->isset($key);
171
    }
172
173
    /**
174
     * Check if property exists
175
     *
176
     * @param string $key
177
     * @return boolean
178
     */
179
    public function isset(string $key): bool
180
    {
181
        return array_key_exists($key, $this->properties);
182
    }
183
184
    /**
185
     * Set all properties of model via array
186
     *
187
     * @param array $properties
188
     * @return Model
189
     */
190
    public function setProperties(array $properties): Model
191
    {
192
        $this->properties = array_merge($this->properties, $properties);
193
        if (isset($properties['id'])) {
194
            $this->_id = $properties['id'];
195
        }
196
        return $this;
197
    }
198
199
    /**
200
     * Get all properties in array form
201
     *
202
     * @return array
203
     */
204
    public function getProperties(): array
205
    {
206
        return $this->properties;
207
    }
208
209
    /**
210
     * Get all properties in array form
211
     *
212
     * @return array
213
     */
214
    public function toArray(): array
215
    {
216
        return $this->getProperties();
217
    }
218
219
    /**
220
     *  check if model loaded from db
221
     * @return array
222
     */
223
    public function isLoaded(): bool
224
    {
225
        return $this->__meta['is_loaded'];
226
    }
227
228
    /**
229
     * call when model is loaded from database
230
     *
231
     * @return Model
232
     */
233
    public function setLoaded(): Model
234
    {
235
        $this->__meta['is_loaded'] = true;
236
        return $this;
237
    }
238
239
    /**
240
     * Get current table name of model
241
     *
242
     * @return String
243
     */
244
    public function getName(): string
245
    {
246
        return $this->table;
247
    }
248
249
    /**
250
     * Get current model Id or UUID
251
     *
252
     * @return mixed
253
     */
254
    public function getId(): mixed
255
    {
256
        return $this->_id;
257
    }
258
259
260
    /**
261
     * Save model to database
262
     *
263
     * @return mixed returns int when id is used else returns string for uuid
264
     */
265
    public function save(): mixed
266
    {
267
        $id = $this->db->save($this);
268
        $this->id = $id;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
269
        $this->_id = $id;
270
        return $id;
271
    }
272
273
    /**
274
     * Delete model data
275
     */
276
    public function delete(): void
277
    {
278
        $this->db->delete($this);
279
    }
280
281
    /**
282
     * Converts model into json object
283
     * @return string
284
     */
285
    public function toString(): string
286
    {
287
        return \json_encode($this->properties);
288
    }
289
290
    /**
291
     * Converts model into json object
292
     * @return string
293
     */
294
    public function __toString(): string
295
    {
296
        return $this->toString();
297
    }
298
299
300
    /**
301
     * Function used to compare to models
302
     *
303
     * @param self $other
304
     * @return boolean
305
     */
306
    public function equals(self$other): bool
307
    {
308
        return ($this->getId() === $other->getId() && $this->toString() === $other->toString());
309
    }
310
311
    /**
312
     * Check if model has any relations
313
     *
314
     * @return boolean
315
     */
316
    public function hasForeign($type): bool
317
    {
318
        return $this->__meta['has_foreign'][$type];
319
    }
320
321
    /**
322
     * returns all relational models
323
     *
324
     * @return array
325
     */
326
    public function getForeignModels($type): array
327
    {
328
        return $this->__meta['foreign_models'][$type];
329
    }
330
}