Total Complexity | 121 |
Total Lines | 879 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like GetPaid_Data often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use GetPaid_Data, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | abstract class GetPaid_Data { |
||
23 | |||
24 | /** |
||
25 | * ID for this object. |
||
26 | * |
||
27 | * @since 1.0.19 |
||
28 | * @var int |
||
29 | */ |
||
30 | protected $id = 0; |
||
31 | |||
32 | /** |
||
33 | * Core data for this object. Name value pairs (name + default value). |
||
34 | * |
||
35 | * @since 1.0.19 |
||
36 | * @var array |
||
37 | */ |
||
38 | protected $data = array(); |
||
39 | |||
40 | /** |
||
41 | * Core data changes for this object. |
||
42 | * |
||
43 | * @since 1.0.19 |
||
44 | * @var array |
||
45 | */ |
||
46 | protected $changes = array(); |
||
47 | |||
48 | /** |
||
49 | * This is false until the object is read from the DB. |
||
50 | * |
||
51 | * @since 1.0.19 |
||
52 | * @var bool |
||
53 | */ |
||
54 | protected $object_read = false; |
||
55 | |||
56 | /** |
||
57 | * This is the name of this object type. |
||
58 | * |
||
59 | * @since 1.0.19 |
||
60 | * @var string |
||
61 | */ |
||
62 | protected $object_type = 'data'; |
||
63 | |||
64 | /** |
||
65 | * Extra data for this object. Name value pairs (name + default value). |
||
66 | * Used as a standard way for sub classes (like item types) to add |
||
67 | * additional information to an inherited class. |
||
68 | * |
||
69 | * @since 1.0.19 |
||
70 | * @var array |
||
71 | */ |
||
72 | protected $extra_data = array(); |
||
73 | |||
74 | /** |
||
75 | * Set to _data on construct so we can track and reset data if needed. |
||
76 | * |
||
77 | * @since 1.0.19 |
||
78 | * @var array |
||
79 | */ |
||
80 | protected $default_data = array(); |
||
81 | |||
82 | /** |
||
83 | * Contains a reference to the data store for this class. |
||
84 | * |
||
85 | * @since 1.0.19 |
||
86 | * @var GetPaid_Data_Store |
||
87 | */ |
||
88 | protected $data_store; |
||
89 | |||
90 | /** |
||
91 | * Stores meta in cache for future reads. |
||
92 | * A group must be set to to enable caching. |
||
93 | * |
||
94 | * @since 1.0.19 |
||
95 | * @var string |
||
96 | */ |
||
97 | protected $cache_group = ''; |
||
98 | |||
99 | /** |
||
100 | * Stores the last error. |
||
101 | * |
||
102 | * @since 1.0.19 |
||
103 | * @var string |
||
104 | */ |
||
105 | public $last_error = ''; |
||
106 | |||
107 | /** |
||
108 | * Stores additional meta data. |
||
109 | * |
||
110 | * @since 1.0.19 |
||
111 | * @var array |
||
112 | */ |
||
113 | protected $meta_data = null; |
||
114 | |||
115 | /** |
||
116 | * Default constructor. |
||
117 | * |
||
118 | * @param int|object|array|string $read ID to load from the DB (optional) or already queried data. |
||
119 | */ |
||
120 | public function __construct( $read = 0 ) { |
||
121 | $this->data = array_merge( $this->data, $this->extra_data ); |
||
122 | $this->default_data = $this->data; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Only store the object ID to avoid serializing the data object instance. |
||
127 | * |
||
128 | * @return array |
||
129 | */ |
||
130 | public function __sleep() { |
||
131 | return array( 'id' ); |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Re-run the constructor with the object ID. |
||
136 | * |
||
137 | * If the object no longer exists, remove the ID. |
||
138 | */ |
||
139 | public function __wakeup() { |
||
140 | $this->__construct( absint( $this->id ) ); |
||
141 | |||
142 | if ( ! empty( $this->last_error ) ) { |
||
143 | $this->set_id( 0 ); |
||
144 | } |
||
145 | |||
146 | } |
||
147 | |||
148 | /** |
||
149 | * When the object is cloned, make sure meta is duplicated correctly. |
||
150 | * |
||
151 | * @since 1.0.19 |
||
152 | */ |
||
153 | public function __clone() { |
||
154 | $this->maybe_read_meta_data(); |
||
155 | if ( ! empty( $this->meta_data ) ) { |
||
156 | foreach ( $this->meta_data as $array_key => $meta ) { |
||
157 | $this->meta_data[ $array_key ] = clone $meta; |
||
158 | if ( ! empty( $meta->id ) ) { |
||
159 | $this->meta_data[ $array_key ]->id = null; |
||
160 | } |
||
161 | } |
||
162 | } |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Get the data store. |
||
167 | * |
||
168 | * @since 1.0.19 |
||
169 | * @return object |
||
170 | */ |
||
171 | public function get_data_store() { |
||
172 | return $this->data_store; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Get the object type. |
||
177 | * |
||
178 | * @since 1.0.19 |
||
179 | * @return string |
||
180 | */ |
||
181 | public function get_object_type() { |
||
182 | return $this->object_type; |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Returns the unique ID for this object. |
||
187 | * |
||
188 | * @since 1.0.19 |
||
189 | * @return int |
||
190 | */ |
||
191 | public function get_id() { |
||
192 | return $this->id; |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Get form status. |
||
197 | * |
||
198 | * @since 1.0.19 |
||
199 | * @param string $context View or edit context. |
||
200 | * @return string |
||
201 | */ |
||
202 | public function get_status( $context = 'view' ) { |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Delete an object, set the ID to 0, and return result. |
||
208 | * |
||
209 | * @since 1.0.19 |
||
210 | * @param bool $force_delete Should the data be deleted permanently. |
||
211 | * @return bool result |
||
212 | */ |
||
213 | public function delete( $force_delete = false ) { |
||
214 | if ( $this->data_store && $this->exists() ) { |
||
215 | $this->data_store->delete( $this, array( 'force_delete' => $force_delete ) ); |
||
216 | $this->set_id( 0 ); |
||
217 | return true; |
||
218 | } |
||
219 | return false; |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Save should create or update based on object existence. |
||
224 | * |
||
225 | * @since 1.0.19 |
||
226 | * @return int |
||
227 | */ |
||
228 | public function save() { |
||
229 | if ( ! $this->data_store ) { |
||
230 | return $this->get_id(); |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Trigger action before saving to the DB. Allows you to adjust object props before save. |
||
235 | * |
||
236 | * @param GetPaid_Data $this The object being saved. |
||
237 | * @param GetPaid_Data_Store_WP $data_store The data store persisting the data. |
||
238 | */ |
||
239 | do_action( 'getpaid_before_' . $this->object_type . '_object_save', $this, $this->data_store ); |
||
240 | |||
241 | if ( $this->get_id() ) { |
||
242 | $this->data_store->update( $this ); |
||
243 | } else { |
||
244 | $this->data_store->create( $this ); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Trigger action after saving to the DB. |
||
249 | * |
||
250 | * @param GetPaid_Data $this The object being saved. |
||
251 | * @param GetPaid_Data_Store_WP $data_store The data store persisting the data. |
||
252 | */ |
||
253 | do_action( 'getpaid_after_' . $this->object_type . '_object_save', $this, $this->data_store ); |
||
254 | |||
255 | return $this->get_id(); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Change data to JSON format. |
||
260 | * |
||
261 | * @since 1.0.19 |
||
262 | * @return string Data in JSON format. |
||
263 | */ |
||
264 | public function __toString() { |
||
265 | return wp_json_encode( $this->get_data() ); |
||
|
|||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Returns all data for this object. |
||
270 | * |
||
271 | * @since 1.0.19 |
||
272 | * @return array |
||
273 | */ |
||
274 | public function get_data() { |
||
275 | return array_merge( array( 'id' => $this->get_id() ), $this->data, array( 'meta_data' => $this->get_meta_data() ) ); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Returns array of expected data keys for this object. |
||
280 | * |
||
281 | * @since 1.0.19 |
||
282 | * @return array |
||
283 | */ |
||
284 | public function get_data_keys() { |
||
285 | return array_keys( $this->data ); |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Returns all "extra" data keys for an object (for sub objects like item types). |
||
290 | * |
||
291 | * @since 1.0.19 |
||
292 | * @return array |
||
293 | */ |
||
294 | public function get_extra_data_keys() { |
||
295 | return array_keys( $this->extra_data ); |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Filter null meta values from array. |
||
300 | * |
||
301 | * @since 1.0.19 |
||
302 | * @param mixed $meta Meta value to check. |
||
303 | * @return bool |
||
304 | */ |
||
305 | protected function filter_null_meta( $meta ) { |
||
306 | return ! is_null( $meta->value ); |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Get All Meta Data. |
||
311 | * |
||
312 | * @since 1.0.19 |
||
313 | * @return array of objects. |
||
314 | */ |
||
315 | public function get_meta_data() { |
||
316 | $this->maybe_read_meta_data(); |
||
317 | return array_values( array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) ) ); |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * Check if the key is an internal one. |
||
322 | * |
||
323 | * @since 1.0.19 |
||
324 | * @param string $key Key to check. |
||
325 | * @return bool true if it's an internal key, false otherwise |
||
326 | */ |
||
327 | protected function is_internal_meta_key( $key ) { |
||
328 | $internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true ); |
||
329 | |||
330 | if ( ! $internal_meta_key ) { |
||
331 | return false; |
||
332 | } |
||
333 | |||
334 | $has_setter_or_getter = is_callable( array( $this, 'set_' . $key ) ) || is_callable( array( $this, 'get_' . $key ) ); |
||
335 | |||
336 | if ( ! $has_setter_or_getter ) { |
||
337 | return false; |
||
338 | } |
||
339 | |||
340 | /* translators: %s: $key Key to check */ |
||
341 | getpaid_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'invoicing' ), $key ), '1.0.19' ); |
||
342 | |||
343 | return true; |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Magic method for setting data fields. |
||
348 | * |
||
349 | * This method does not update custom fields in the database. |
||
350 | * |
||
351 | * @since 1.0.19 |
||
352 | * @access public |
||
353 | * |
||
354 | */ |
||
355 | public function __set( $key, $value ) { |
||
369 | } |
||
370 | |||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Margic method for retrieving a property. |
||
375 | */ |
||
376 | public function __get( $key ) { |
||
395 | |||
396 | } |
||
397 | |||
398 | /** |
||
399 | * Get Meta Data by Key. |
||
400 | * |
||
401 | * @since 1.0.19 |
||
402 | * @param string $key Meta Key. |
||
403 | * @param bool $single return first found meta with key, or all with $key. |
||
404 | * @param string $context What the value is for. Valid values are view and edit. |
||
405 | * @return mixed |
||
406 | */ |
||
407 | public function get_meta( $key = '', $single = true, $context = 'view' ) { |
||
408 | |||
409 | // Check if this is an internal meta key. |
||
410 | $_key = str_replace( '_wpinv', '', $key ); |
||
411 | $_key = str_replace( 'wpinv', '', $_key ); |
||
412 | if ( $this->is_internal_meta_key( $key ) ) { |
||
413 | $function = 'get_' . $_key; |
||
414 | |||
415 | if ( is_callable( array( $this, $function ) ) ) { |
||
416 | return $this->{$function}(); |
||
417 | } |
||
418 | } |
||
419 | |||
420 | // Read the meta data if not yet read. |
||
421 | $this->maybe_read_meta_data(); |
||
422 | $meta_data = $this->get_meta_data(); |
||
423 | $array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true ); |
||
424 | $value = $single ? '' : array(); |
||
425 | |||
426 | if ( ! empty( $array_keys ) ) { |
||
427 | // We don't use the $this->meta_data property directly here because we don't want meta with a null value (i.e. meta which has been deleted via $this->delete_meta_data()). |
||
428 | if ( $single ) { |
||
429 | $value = $meta_data[ current( $array_keys ) ]->value; |
||
430 | } else { |
||
431 | $value = array_intersect_key( $meta_data, array_flip( $array_keys ) ); |
||
432 | } |
||
433 | } |
||
434 | |||
435 | if ( 'view' === $context ) { |
||
436 | $value = apply_filters( $this->get_hook_prefix() . $key, $value, $this ); |
||
437 | } |
||
438 | |||
439 | return $value; |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * See if meta data exists, since get_meta always returns a '' or array(). |
||
444 | * |
||
445 | * @since 1.0.19 |
||
446 | * @param string $key Meta Key. |
||
447 | * @return boolean |
||
448 | */ |
||
449 | public function meta_exists( $key = '' ) { |
||
450 | $this->maybe_read_meta_data(); |
||
451 | $array_keys = wp_list_pluck( $this->get_meta_data(), 'key' ); |
||
452 | return in_array( $key, $array_keys, true ); |
||
453 | } |
||
454 | |||
455 | /** |
||
456 | * Set all meta data from array. |
||
457 | * |
||
458 | * @since 1.0.19 |
||
459 | * @param array $data Key/Value pairs. |
||
460 | */ |
||
461 | public function set_meta_data( $data ) { |
||
462 | if ( ! empty( $data ) && is_array( $data ) ) { |
||
463 | $this->maybe_read_meta_data(); |
||
464 | foreach ( $data as $meta ) { |
||
465 | $meta = (array) $meta; |
||
466 | if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) { |
||
467 | $this->meta_data[] = new GetPaid_Meta_Data( |
||
468 | array( |
||
469 | 'id' => $meta['id'], |
||
470 | 'key' => $meta['key'], |
||
471 | 'value' => $meta['value'], |
||
472 | ) |
||
473 | ); |
||
474 | } |
||
475 | } |
||
476 | } |
||
477 | } |
||
478 | |||
479 | /** |
||
480 | * Add meta data. |
||
481 | * |
||
482 | * @since 1.0.19 |
||
483 | * |
||
484 | * @param string $key Meta key. |
||
485 | * @param string|array $value Meta value. |
||
486 | * @param bool $unique Should this be a unique key?. |
||
487 | */ |
||
488 | public function add_meta_data( $key, $value, $unique = false ) { |
||
489 | if ( $this->is_internal_meta_key( $key ) ) { |
||
490 | $function = 'set_' . $key; |
||
491 | |||
492 | if ( is_callable( array( $this, $function ) ) ) { |
||
493 | return $this->{$function}( $value ); |
||
494 | } |
||
495 | } |
||
496 | |||
497 | $this->maybe_read_meta_data(); |
||
498 | if ( $unique ) { |
||
499 | $this->delete_meta_data( $key ); |
||
500 | } |
||
501 | $this->meta_data[] = new GetPaid_Meta_Data( |
||
502 | array( |
||
503 | 'key' => $key, |
||
504 | 'value' => $value, |
||
505 | ) |
||
506 | ); |
||
507 | |||
508 | $this->save(); |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * Update meta data by key or ID, if provided. |
||
513 | * |
||
514 | * @since 1.0.19 |
||
515 | * |
||
516 | * @param string $key Meta key. |
||
517 | * @param string|array $value Meta value. |
||
518 | * @param int $meta_id Meta ID. |
||
519 | */ |
||
520 | public function update_meta_data( $key, $value, $meta_id = 0 ) { |
||
521 | if ( $this->is_internal_meta_key( $key ) ) { |
||
522 | $function = 'set_' . $key; |
||
523 | |||
524 | if ( is_callable( array( $this, $function ) ) ) { |
||
525 | return $this->{$function}( $value ); |
||
526 | } |
||
527 | } |
||
528 | |||
529 | $this->maybe_read_meta_data(); |
||
530 | |||
531 | $array_key = false; |
||
532 | |||
533 | if ( $meta_id ) { |
||
534 | $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id, true ); |
||
535 | $array_key = $array_keys ? current( $array_keys ) : false; |
||
536 | } else { |
||
537 | // Find matches by key. |
||
538 | $matches = array(); |
||
539 | foreach ( $this->meta_data as $meta_data_array_key => $meta ) { |
||
540 | if ( $meta->key === $key ) { |
||
541 | $matches[] = $meta_data_array_key; |
||
542 | } |
||
543 | } |
||
544 | |||
545 | if ( ! empty( $matches ) ) { |
||
546 | // Set matches to null so only one key gets the new value. |
||
547 | foreach ( $matches as $meta_data_array_key ) { |
||
548 | $this->meta_data[ $meta_data_array_key ]->value = null; |
||
549 | } |
||
550 | $array_key = current( $matches ); |
||
551 | } |
||
552 | } |
||
553 | |||
554 | if ( false !== $array_key ) { |
||
555 | $meta = $this->meta_data[ $array_key ]; |
||
556 | $meta->key = $key; |
||
557 | $meta->value = $value; |
||
558 | } else { |
||
559 | $this->add_meta_data( $key, $value, true ); |
||
560 | } |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Delete meta data. |
||
565 | * |
||
566 | * @since 1.0.19 |
||
567 | * @param string $key Meta key. |
||
568 | */ |
||
569 | public function delete_meta_data( $key ) { |
||
570 | $this->maybe_read_meta_data(); |
||
571 | $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true ); |
||
572 | |||
573 | if ( $array_keys ) { |
||
574 | foreach ( $array_keys as $array_key ) { |
||
575 | $this->meta_data[ $array_key ]->value = null; |
||
576 | } |
||
577 | } |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * Delete meta data. |
||
582 | * |
||
583 | * @since 1.0.19 |
||
584 | * @param int $mid Meta ID. |
||
585 | */ |
||
586 | public function delete_meta_data_by_mid( $mid ) { |
||
587 | $this->maybe_read_meta_data(); |
||
588 | $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true ); |
||
589 | |||
590 | if ( $array_keys ) { |
||
591 | foreach ( $array_keys as $array_key ) { |
||
592 | $this->meta_data[ $array_key ]->value = null; |
||
593 | } |
||
594 | } |
||
595 | } |
||
596 | |||
597 | /** |
||
598 | * Read meta data if null. |
||
599 | * |
||
600 | * @since 1.0.19 |
||
601 | */ |
||
602 | protected function maybe_read_meta_data() { |
||
603 | if ( is_null( $this->meta_data ) ) { |
||
604 | $this->read_meta_data(); |
||
605 | } |
||
606 | } |
||
607 | |||
608 | /** |
||
609 | * Read Meta Data from the database. Ignore any internal properties. |
||
610 | * Uses it's own caches because get_metadata does not provide meta_ids. |
||
611 | * |
||
612 | * @since 1.0.19 |
||
613 | * @param bool $force_read True to force a new DB read (and update cache). |
||
614 | */ |
||
615 | public function read_meta_data( $force_read = false ) { |
||
616 | |||
617 | // Reset meta data. |
||
618 | $this->meta_data = array(); |
||
619 | |||
620 | // Maybe abort early. |
||
621 | if ( ! $this->get_id() || ! $this->data_store ) { |
||
622 | return; |
||
623 | } |
||
624 | |||
625 | // Only read from cache if the cache key is set. |
||
626 | $cache_key = null; |
||
627 | if ( ! $force_read && ! empty( $this->cache_group ) ) { |
||
628 | $cache_key = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id(); |
||
629 | $raw_meta_data = wp_cache_get( $cache_key, $this->cache_group ); |
||
630 | } |
||
631 | |||
632 | // Should we force read? |
||
633 | if ( empty( $raw_meta_data ) ) { |
||
634 | $raw_meta_data = $this->data_store->read_meta( $this ); |
||
635 | |||
636 | if ( ! empty( $cache_key ) ) { |
||
637 | wp_cache_set( $cache_key, $raw_meta_data, $this->cache_group ); |
||
638 | } |
||
639 | } |
||
640 | |||
641 | // Set meta data. |
||
642 | if ( is_array( $raw_meta_data ) ) { |
||
643 | |||
644 | foreach ( $raw_meta_data as $meta ) { |
||
645 | $this->meta_data[] = new GetPaid_Meta_Data( |
||
646 | array( |
||
647 | 'id' => (int) $meta->meta_id, |
||
648 | 'key' => $meta->meta_key, |
||
649 | 'value' => maybe_unserialize( $meta->meta_value ), |
||
650 | ) |
||
651 | ); |
||
652 | } |
||
653 | } |
||
654 | |||
655 | } |
||
656 | |||
657 | /** |
||
658 | * Update Meta Data in the database. |
||
659 | * |
||
660 | * @since 1.0.19 |
||
661 | */ |
||
662 | public function save_meta_data() { |
||
663 | if ( ! $this->data_store || is_null( $this->meta_data ) ) { |
||
664 | return; |
||
665 | } |
||
666 | foreach ( $this->meta_data as $array_key => $meta ) { |
||
667 | if ( is_null( $meta->value ) ) { |
||
668 | if ( ! empty( $meta->id ) ) { |
||
669 | $this->data_store->delete_meta( $this, $meta ); |
||
670 | unset( $this->meta_data[ $array_key ] ); |
||
671 | } |
||
672 | } elseif ( empty( $meta->id ) ) { |
||
673 | $meta->id = $this->data_store->add_meta( $this, $meta ); |
||
674 | $meta->apply_changes(); |
||
675 | } else { |
||
676 | if ( $meta->get_changes() ) { |
||
677 | $this->data_store->update_meta( $this, $meta ); |
||
678 | $meta->apply_changes(); |
||
679 | } |
||
680 | } |
||
681 | } |
||
682 | if ( ! empty( $this->cache_group ) ) { |
||
683 | $cache_key = GetPaid_Cache_Helper::get_cache_prefix( $this->cache_group ) . GetPaid_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id(); |
||
684 | wp_cache_delete( $cache_key, $this->cache_group ); |
||
685 | } |
||
686 | } |
||
687 | |||
688 | /** |
||
689 | * Set ID. |
||
690 | * |
||
691 | * @since 1.0.19 |
||
692 | * @param int $id ID. |
||
693 | */ |
||
694 | public function set_id( $id ) { |
||
695 | $this->id = absint( $id ); |
||
696 | } |
||
697 | |||
698 | /** |
||
699 | * Sets item status. |
||
700 | * |
||
701 | * @since 1.0.19 |
||
702 | * @param string $status New status. |
||
703 | * @return array details of change. |
||
704 | */ |
||
705 | public function set_status( $status ) { |
||
713 | ); |
||
714 | } |
||
715 | |||
716 | /** |
||
717 | * Set all props to default values. |
||
718 | * |
||
719 | * @since 1.0.19 |
||
720 | */ |
||
721 | public function set_defaults() { |
||
725 | } |
||
726 | |||
727 | /** |
||
728 | * Set object read property. |
||
729 | * |
||
730 | * @since 1.0.19 |
||
731 | * @param boolean $read Should read?. |
||
732 | */ |
||
733 | public function set_object_read( $read = true ) { |
||
734 | $this->object_read = (bool) $read; |
||
735 | } |
||
736 | |||
737 | /** |
||
738 | * Get object read property. |
||
739 | * |
||
740 | * @since 1.0.19 |
||
741 | * @return boolean |
||
742 | */ |
||
743 | public function get_object_read() { |
||
745 | } |
||
746 | |||
747 | /** |
||
748 | * Set a collection of props in one go, collect any errors, and return the result. |
||
749 | * Only sets using public methods. |
||
750 | * |
||
751 | * @since 1.0.19 |
||
752 | * |
||
753 | * @param array $props Key value pairs to set. Key is the prop and should map to a setter function name. |
||
754 | * @param string $context In what context to run this. |
||
755 | * |
||
756 | * @return bool|WP_Error |
||
757 | */ |
||
758 | public function set_props( $props, $context = 'set' ) { |
||
759 | $errors = false; |
||
760 | |||
761 | $props = wp_unslash( $props ); |
||
762 | foreach ( $props as $prop => $value ) { |
||
763 | try { |
||
764 | /** |
||
765 | * Checks if the prop being set is allowed, and the value is not null. |
||
766 | */ |
||
767 | if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) { |
||
768 | continue; |
||
769 | } |
||
770 | $setter = "set_$prop"; |
||
771 | |||
772 | if ( is_callable( array( $this, $setter ) ) ) { |
||
773 | $this->{$setter}( $value ); |
||
774 | } |
||
775 | } catch ( Exception $e ) { |
||
776 | if ( ! $errors ) { |
||
777 | $errors = new WP_Error(); |
||
778 | } |
||
779 | $errors->add( $e->getCode(), $e->getMessage() ); |
||
780 | $this->last_error = $e->getMessage(); |
||
781 | } |
||
782 | } |
||
783 | |||
784 | return $errors && count( $errors->get_error_codes() ) ? $errors : true; |
||
785 | } |
||
786 | |||
787 | /** |
||
788 | * Sets a prop for a setter method. |
||
789 | * |
||
790 | * This stores changes in a special array so we can track what needs saving |
||
791 | * the the DB later. |
||
792 | * |
||
793 | * @since 1.0.19 |
||
794 | * @param string $prop Name of prop to set. |
||
795 | * @param mixed $value Value of the prop. |
||
796 | */ |
||
797 | protected function set_prop( $prop, $value ) { |
||
798 | if ( array_key_exists( $prop, $this->data ) ) { |
||
799 | if ( true === $this->object_read ) { |
||
800 | if ( $value !== $this->data[ $prop ] || array_key_exists( $prop, $this->changes ) ) { |
||
801 | $this->changes[ $prop ] = $value; |
||
802 | } |
||
803 | } else { |
||
804 | $this->data[ $prop ] = $value; |
||
805 | } |
||
806 | } |
||
807 | } |
||
808 | |||
809 | /** |
||
810 | * Return data changes only. |
||
811 | * |
||
812 | * @since 1.0.19 |
||
813 | * @return array |
||
814 | */ |
||
815 | public function get_changes() { |
||
816 | return $this->changes; |
||
817 | } |
||
818 | |||
819 | /** |
||
820 | * Merge changes with data and clear. |
||
821 | * |
||
822 | * @since 1.0.19 |
||
823 | */ |
||
824 | public function apply_changes() { |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Prefix for action and filter hooks on data. |
||
831 | * |
||
832 | * @since 1.0.19 |
||
833 | * @return string |
||
834 | */ |
||
835 | protected function get_hook_prefix() { |
||
836 | return 'wpinv_get_' . $this->object_type . '_'; |
||
837 | } |
||
838 | |||
839 | /** |
||
840 | * Gets a prop for a getter method. |
||
841 | * |
||
842 | * Gets the value from either current pending changes, or the data itself. |
||
843 | * Context controls what happens to the value before it's returned. |
||
844 | * |
||
845 | * @since 1.0.19 |
||
846 | * @param string $prop Name of prop to get. |
||
847 | * @param string $context What the value is for. Valid values are view and edit. |
||
848 | * @return mixed |
||
849 | */ |
||
850 | protected function get_prop( $prop, $context = 'view' ) { |
||
851 | $value = null; |
||
852 | |||
853 | if ( array_key_exists( $prop, $this->data ) ) { |
||
854 | $value = array_key_exists( $prop, $this->changes ) ? $this->changes[ $prop ] : $this->data[ $prop ]; |
||
855 | |||
856 | if ( 'view' === $context ) { |
||
857 | $value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this ); |
||
858 | } |
||
859 | } |
||
860 | |||
861 | return $value; |
||
862 | } |
||
863 | |||
864 | /** |
||
865 | * Sets a date prop whilst handling formatting and datetime objects. |
||
866 | * |
||
867 | * @since 1.0.19 |
||
868 | * @param string $prop Name of prop to set. |
||
869 | * @param string|integer $value Value of the prop. |
||
870 | */ |
||
871 | protected function set_date_prop( $prop, $value ) { |
||
872 | |||
873 | if ( empty( $value ) ) { |
||
874 | $this->set_prop( $prop, null ); |
||
875 | return; |
||
876 | } |
||
877 | $this->set_prop( $prop, $value ); |
||
878 | |||
879 | } |
||
880 | |||
881 | /** |
||
882 | * When invalid data is found, throw an exception unless reading from the DB. |
||
883 | * |
||
884 | * @since 1.0.19 |
||
885 | * @param string $code Error code. |
||
886 | * @param string $message Error message. |
||
887 | */ |
||
888 | protected function error( $code, $message ) { |
||
890 | } |
||
891 | |||
892 | /** |
||
893 | * Checks if the object is saved in the database |
||
894 | * |
||
895 | * @since 1.0.19 |
||
896 | * @return bool |
||
897 | */ |
||
898 | public function exists() { |
||
904 |
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.