PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 2.19.6
GiveWP – Donation Plugin and Fundraising Platform v2.19.6
4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 All 253 releases
give / src / Framework / Models / Model.php

Model.php in GiveWP – Donation Plugin and Fundraising Platform 2.19.6, at src/Framework/Models/Model.php

357 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Give\Framework\Models;
4
5 use Give\Framework\Exceptions\Primitives\InvalidArgumentException;
6 use Give\Framework\Models\ValueObjects\Relationship;
7 use Give\Framework\Support\Contracts\Arrayable;
8 use RuntimeException;
9
10 /**
11 * @since 2.19.6
12 */
13 abstract class Model implements Arrayable
14 {
15
16 /**
17 * The model's attributes.
18 *
19 * @var array
20 */
21 protected $attributes = [];
22
23 /**
24 * The model attribute's original state.
25 *
26 * @var array
27 */
28 protected $original = [];
29
30 /**
31 * The model properties assigned to their types
32 *
33 * @var array
34 */
35 protected $properties = [];
36
37 /**
38 * The model relationships assigned to their relationship types
39 *
40 * @var array
41 */
42 protected $relationships = [];
43
44 /**
45 * Create a new model instance.
46 *
47 * @since 2.19.6
48 *
49 * @param array $attributes
50 * @return void
51 */
52 public function __construct(array $attributes = [])
53 {
54 $this->attributes = $attributes;
55
56 $this->syncOriginal();
57
58 $this->fill($attributes);
59 }
60
61 /**
62 * Sync the original attributes with the current.
63 *
64 * @since 2.19.6
65 *
66 * @return $this
67 */
68 protected function syncOriginal()
69 {
70 $this->original = $this->attributes;
71
72 return $this;
73 }
74
75 /**
76 * Get the model's original attribute values.
77 *
78 * @since 2.19.6
79 *
80 * @param string|null $key
81 * @return mixed|array
82 */
83 public function getOriginal($key = null)
84 {
85 return $key ? $this->original[$key] : $this->original;
86 }
87
88 /**
89 * Determine if a given attribute is dirty.
90 *
91 * @since 2.19.6
92 *
93 * @param string|null $attribute
94 * @return bool
95 */
96 public function isDirty($attribute = null)
97 {
98 if (!$attribute) {
99 return (bool)$this->getDirty();
100 }
101
102 return array_key_exists($attribute, $this->getDirty());
103 }
104
105 /**
106 * Determine if a given attribute is clean.
107 *
108 * @since 2.19.6
109 *
110 * @param string|null $attribute
111 * @return bool
112 */
113 public function isClean($attribute = null)
114 {
115 return !$this->isDirty($attribute);
116 }
117
118 /**
119 * Get the attributes that have been changed since last sync.
120 *
121 * @since 2.19.6
122 *
123 * @return array
124 */
125 public function getDirty()
126 {
127 $dirty = [];
128
129 foreach ($this->attributes as $key => $value) {
130 if (!array_key_exists($key, $this->original) || $value !== $this->original[$key]) {
131 $dirty[$key] = $value;
132 }
133 }
134
135 return $dirty;
136 }
137
138 /**
139 * Fill the model with an array of attributes.
140 *
141 * @since 2.19.6
142 *
143 * @param array $attributes
144 * @return $this
145 */
146 public function fill(array $attributes)
147 {
148 foreach ($attributes as $key => $value) {
149 $this->setAttribute($key, $value);
150 }
151
152 return $this;
153 }
154
155 /**
156 * Get an attribute from the model.
157 *
158 * @since 2.19.6
159 *
160 * @param string $key
161 * @return mixed
162 *
163 * @throws RuntimeException
164 */
165 public function getAttribute($key)
166 {
167 if (!array_key_exists($key, $this->properties)) {
168 throw new InvalidArgumentException("$key is not a valid property.");
169 }
170
171 return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
172 }
173
174 /**
175 * Set a given attribute on the model.
176 *
177 * @since 2.19.6
178 *
179 * @param string $key
180 * @param mixed $value
181 */
182 public function setAttribute($key, $value)
183 {
184 $this->validatePropertyType($key, $value);
185
186 $this->attributes[$key] = $value;
187
188 return $this;
189 }
190
191 /**
192 * Validate an attribute to a PHP type.
193 *
194 * @since 2.19.6
195 *
196 * @param string $key
197 * @param mixed $value
198 *
199 * @return bool
200 */
201 public function isPropertyTypeValid($key, $value)
202 {
203 if (is_null($value)) {
204 return true;
205 }
206
207 $type = $this->getPropertyType($key);
208
209 switch ($type) {
210 case 'int':
211 return is_int($value);
212 case 'string':
213 return is_string($value);
214 case 'bool':
215 return is_bool($value);
216 case 'array':
217 return is_array($value);
218 default:
219 return $value instanceof $type;
220 }
221 }
222
223 /**
224 * Validate property type
225 *
226 * @param string $key
227 * @param mixed $value
228 *
229 * @return void
230 *
231 * @throws InvalidArgumentException
232 */
233 protected function validatePropertyType($key, $value)
234 {
235 if (!$this->isPropertyTypeValid($key, $value)) {
236 $type = $this->getPropertyType($key);
237
238 throw new InvalidArgumentException("Invalid attribute assignment. '$key' should be of type: '$type'");
239 }
240 }
241
242 /**
243 * Get the property type
244 *
245 * @since 2.19.6
246 *
247 * @param $key
248 * @return string
249 */
250 protected function getPropertyType($key)
251 {
252 return strtolower(trim($this->properties[$key]));
253 }
254
255 /**
256 * @since 2.19.6
257 *
258 * @return array
259 */
260 public function toArray()
261 {
262 return $this->attributes;
263 }
264
265 /**
266 * @since 2.19.6
267 *
268 * @return array
269 */
270 public function getAttributes()
271 {
272 return $this->attributes;
273 }
274
275 /**
276 * @return int[]|string[]
277 */
278 public static function propertyKeys()
279 {
280 return array_keys((new static)->properties);
281 }
282
283 /**
284 * Dynamically retrieve attributes on the model.
285 *
286 * @since 2.19.6
287 *
288 * @param string $key
289 * @return mixed
290 */
291 public function __get($key)
292 {
293 if (array_key_exists($key, $this->relationships)) {
294 return $this->getRelationship($key);
295 }
296
297 return $this->getAttribute($key);
298 }
299
300 /**
301 * Dynamically set attributes on the model.
302 *
303 * @since 2.19.6
304 *
305 * @param string $key
306 * @param mixed $value
307 * @return void
308 */
309 public function __set($key, $value)
310 {
311 $this->setAttribute($key, $value);
312 }
313
314 /**
315 * Determine if an attribute exists on the model.
316 *
317 * @since 2.19.6
318 *
319 * @param string $key
320 * @return bool
321 */
322 public function __isset($key)
323 {
324 return isset($this->attributes[$key]);
325 }
326
327 /**
328 * @since 2.19.6
329 *
330 * @param $key
331 *
332 * @return Model|Model[]
333 *
334 * @throws InvalidArgumentException
335 */
336 protected function getRelationship($key)
337 {
338 if (!is_callable([$this, $key])) {
339 throw new InvalidArgumentException("$key() does not exist.");
340 }
341
342 $relationship = new Relationship($this->relationships[$key]);
343
344 switch (true) {
345 case ($relationship->equals(Relationship::BELONGS_TO())):
346 case ($relationship->equals(Relationship::HAS_ONE())):
347 return $this->$key()->get();
348 case ($relationship->equals(Relationship::HAS_MANY())):
349 case ($relationship->equals(Relationship::BELONGS_TO_MANY())):
350 case ($relationship->equals(Relationship::MANY_TO_MANY())):
351 return $this->$key()->getAll();
352 }
353
354 return null;
355 }
356 }
357