-
Notifications
You must be signed in to change notification settings - Fork 428
Expand file tree
/
Copy pathBase.php
More file actions
362 lines (315 loc) · 7.84 KB
/
Base.php
File metadata and controls
362 lines (315 loc) · 7.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
<?php
namespace EE\Model;
use EE;
/**
* Base EE Model class.
*/
abstract class Base extends \ArrayObject {
/**
* @var string Table that current model will write to
*/
protected static $table;
/**
* @var string Primary key of current model
*/
protected static $primary_key = 'id';
/**
* @var string It will contain an array of all fields that are present in database in table
*/
protected $fields;
/**
* @var bool Weather the model needs timestamp whenever it's updated
*/
protected static $needs_update_timestamp = false;
/**
* Base constructor.
*
* @param array $fields Array of fields containing fields from database
*/
public function __construct( array $fields = [] ) {
$this->fields = $fields;
}
/**
* Throws exception if model is not found
*
* @param string $value value to find
* @param string $column Column to find in. Defaults to primary key
*
* @throws \Exception
*
* @return static
*/
public static function find_or_fail( string $value, string $column = null ) {
$model = static::find( $value, $column );
if ( ! $model ) {
throw new \Exception( sprintf( 'Unable to find %s : with primary key: %s and value: %s', __CLASS__, static::$primary_key, $value ) );
}
return $model;
}
/**
* Returns single model fetched by primary key
*
* @param string $value value to find
* @param array $columns Columns to select.
*
* @throws \Exception
*
* @return bool|static
*/
public static function find( string $value, array $columns = [] ) {
$model = EE::db()
->table( static::$table )
->select( ...$columns )
->where( static::$primary_key, $value )
->first();
if ( false === $model ) {
return false;
}
return static::single_array_to_model( $model );
}
/**
* Converts single row fetched from database into model
*
* @param array $arr Associative array representing a row from database
*
* @return mixed
*/
protected static function single_array_to_model( array $arr ) {
return new static( $arr );
}
/**
* Exits with error if model is not found
*
* @param string $value value to find
* @param string $column Column to find in. Defaults to primary key
*
* @throws \Exception
*
* @return static
*/
public static function find_or_error( string $value, string $column = null ) {
$model = static::find( $value, $column );
if ( ! $model ) {
EE::error( sprintf( 'Unable to find %s : with primary key: %s and value: %s', __CLASS__, static::$primary_key, $value ) );
}
return $model;
}
/**
* Returns all models.
*
* @param array $columns Columns to select
*
* @throws \Exception
*
* @return array Array of models
*/
public static function all( $columns = [] ) {
$models = EE::db()
->table( static::$table )
->select( ...$columns )
->get();
return static::many_array_to_model( $models );
}
/**
* Converts an array of result from database to models
*
* @param array $arr Array of results from database
*
* @return array
*/
protected static function many_array_to_model( array $arr ) {
$result = [];
foreach ( $arr as $model ) {
$result[] = static::single_array_to_model( $model );
}
return $result;
}
/**
* Creates new entity in DB
*
* @param array $columns Columns and values to insert
*
* @throws \Exception
*
* @return bool Model created successfully
*/
public static function create( $columns = [] ) {
return EE::db()->table( static::$table )->insert( $columns );
}
/**
* Returns all model with condition
*
* @param string|array $column Column to search in
* @param string $value Value to match
*
* @throws \Exception
*
* @return array
*/
public static function where( $column, $value = '' ) {
if ( is_bool( $value ) ) {
$value = (int) $value;
}
return static::many_array_to_model(
EE::db()
->table( static::$table )
->where( $column, $value )
->all()
);
}
/**
* In model, every value is get in fields array.
* We populate it either during constructor or during find() method call
*
* This gives us benefit that models do not have to define properties in class
* They are automatically defined when fetched from database!
*
* @param string $name Name of property to get
*
* @throws \Exception
*
* @return mixed Value of property
*/
public function __get( string $name ) {
if ( array_key_exists( $name, $this->fields ) ) {
return $this->fields[ $name ];
}
throw new \Exception( "Unable to find variable: $name" );
}
/**
* In model, every value is set in fields array.
*
* This gives us benefit that models do not have to define the logic of saving them in database.
* While saving models, we use the $fields array to save it in database
*
*
* @param string $name Name of property to set
* @param mixed $value Value of property to set
*/
public function __set( string $name, $value ) {
$this->fields[$name] = $value;
}
/**
* Overriding isset for correct behaviour while using isset on model objects
*
* @param string|int $name Name of property to check
*
* @return bool
*/
public function __isset( $name ) {
return isset( $this->fields[$name] );
}
/**
* Removes a property from model
* It's done by removing it from $fields array
*
* @param string $name Name of property to unset
*/
public function __unset( $name ) {
unset( $this->fields[$name] );
}
/**
* Overriding offsetGet for correct behaviour while accessing object properties by array index.
*
* @param string|int $index Name of property to check
*
* @throws \Exception
*
* @return bool
*/
public function offsetGet( $index ) {
return $this->__get( $index );
}
/**
* Overriding offsetSet for correct behaviour while saving object properties by array index.
*
* @param string|int $index Name of property to check
* @param mixed $value Value of property to set
*
* @throws \Exception
*
* @return bool
*/
public function offsetSet( $index, $value ) {
return $this->__set( $index, $value );
}
/**
* Overriding offsetGet for correct behaviour while checking array_key_exists.
*
* @param string|int $index Name of property to check
*
* @throws \Exception
*
* @return bool
*/
public function offsetExists( $index ) {
return $this->__isset( $index );
}
/**
* Overriding offsetUnset for correct behaviour while deleting object properties by array index.
*
* @param string|int $index Name of property to check
*
* @throws \Exception
*/
public function offsetUnset( $index ) {
$this->__unset( $index );
}
/**
* Saves current model into database
*
* @throws \Exception
*
* @return bool Model saved successfully
*/
public function save() {
$fields = $this->fields;
foreach ( $fields as $key => $value ) {
if ( is_bool( $value ) ) {
$fields[ $key ] = (int) $value;
}
}
if ( static::$needs_update_timestamp ) {
$fields = array_merge(
$fields, [
'modified_on' => date( 'Y-m-d H:i:s' ),
]
);
}
$primary_key_column = static::$primary_key;
return EE::db()
->table( static::$table )
->where( $primary_key_column, $this->$primary_key_column )
->update( $fields );
}
/**
* Deletes current model from database
*
* @throws \Exception
*
* @return bool Model deleted successfully
*/
public function delete() {
$primary_key_column = static::$primary_key;
return EE::db()
->table( static::$table )
->where( $primary_key_column, $this->$primary_key_column )
->delete();
}
/**
* Updates current model from database
*
* @param array $where Where conditions to update
* @param array $updated_values Updated values
*
* @throws \Exception
*
* @return bool Model updated successfully
*/
public static function update( array $where, array $updated_values ) {
return EE::db()
->table( static::$table )
->where( $where )
->update( $updated_values );
}
}