Passed
Pull Request — master (#371)
by Brian
88:26
created

GetPaid_Data::set_props()   B

Complexity

Conditions 9
Paths 40

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 13
c 1
b 0
f 0
nc 40
nop 2
dl 0
loc 25
rs 8.0555
1
<?php
2
3
/**
4
 * Abstract Data.
5
 *
6
 * Handles generic data interaction which is implemented by
7
 * the different data store classes.
8
 *
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
/**
16
 * Abstract GetPaid Data Class
17
 *
18
 * Implemented by classes using the same CRUD(s) pattern.
19
 *
20
 * @version  1.0.19
21
 */
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 object
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 additional meta data.
101
	 *
102
	 * @since 1.0.19
103
	 * @var array
104
	 */
105
	protected $meta_data = null;
106
107
	/**
108
	 * Default constructor.
109
	 *
110
	 * @param int|object|array $read ID to load from the DB (optional) or already queried data.
111
	 */
112
	public function __construct( $read = 0 ) {
113
		$this->data         = array_merge( $this->data, $this->extra_data );
114
		$this->default_data = $this->data;
115
	}
116
117
	/**
118
	 * Only store the object ID to avoid serializing the data object instance.
119
	 *
120
	 * @return array
121
	 */
122
	public function __sleep() {
123
		return array( 'id' );
124
	}
125
126
	/**
127
	 * Re-run the constructor with the object ID.
128
	 *
129
	 * If the object no longer exists, remove the ID.
130
	 */
131
	public function __wakeup() {
132
		try {
133
			$this->__construct( absint( $this->id ) );
134
		} catch ( Exception $e ) {
135
			$this->set_id( 0 );
136
			$this->set_object_read( true );
137
		}
138
	}
139
140
	/**
141
	 * When the object is cloned, make sure meta is duplicated correctly.
142
	 *
143
	 * @since 1.0.19
144
	 */
145
	public function __clone() {
146
		$this->maybe_read_meta_data();
147
		if ( ! empty( $this->meta_data ) ) {
148
			foreach ( $this->meta_data as $array_key => $meta ) {
149
				$this->meta_data[ $array_key ] = clone $meta;
150
				if ( ! empty( $meta->id ) ) {
151
					$this->meta_data[ $array_key ]->id = null;
152
				}
153
			}
154
		}
155
	}
156
157
	/**
158
	 * Get the data store.
159
	 *
160
	 * @since  1.0.19
161
	 * @return object
162
	 */
163
	public function get_data_store() {
164
		return $this->data_store;
165
	}
166
167
	/**
168
	 * Returns the unique ID for this object.
169
	 *
170
	 * @since  1.0.19
171
	 * @return int
172
	 */
173
	public function get_id() {
174
		return $this->id;
175
	}
176
177
	/**
178
	 * Delete an object, set the ID to 0, and return result.
179
	 *
180
	 * @since  1.0.19
181
	 * @param  bool $force_delete Should the data be deleted permanently.
182
	 * @return bool result
183
	 */
184
	public function delete( $force_delete = false ) {
185
		if ( $this->data_store ) {
186
			$this->data_store->delete( $this, array( 'force_delete' => $force_delete ) );
187
			$this->set_id( 0 );
188
			return true;
189
		}
190
		return false;
191
	}
192
193
	/**
194
	 * Save should create or update based on object existence.
195
	 *
196
	 * @since  1.0.19
197
	 * @return int
198
	 */
199
	public function save() {
200
		if ( ! $this->data_store ) {
201
			return $this->get_id();
202
		}
203
204
		/**
205
		 * Trigger action before saving to the DB. Allows you to adjust object props before save.
206
		 *
207
		 * @param GetPaid_Data          $this The object being saved.
208
		 * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
209
		 */
210
		do_action( 'getpaid_before_' . $this->object_type . '_object_save', $this, $this->data_store );
211
212
		if ( $this->get_id() ) {
213
			$this->data_store->update( $this );
214
		} else {
215
			$this->data_store->create( $this );
216
		}
217
218
		/**
219
		 * Trigger action after saving to the DB.
220
		 *
221
		 * @param GetPaid_Data          $this The object being saved.
222
		 * @param GetPaid_Data_Store_WP $data_store The data store persisting the data.
223
		 */
224
		do_action( 'getpaid_after_' . $this->object_type . '_object_save', $this, $this->data_store );
225
226
		return $this->get_id();
227
	}
228
229
	/**
230
	 * Change data to JSON format.
231
	 *
232
	 * @since  1.0.19
233
	 * @return string Data in JSON format.
234
	 */
235
	public function __toString() {
236
		return wp_json_encode( $this->get_data() );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wp_json_encode($this->get_data()) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
237
	}
238
239
	/**
240
	 * Returns all data for this object.
241
	 *
242
	 * @since  1.0.19
243
	 * @return array
244
	 */
245
	public function get_data() {
246
		return array_merge( array( 'id' => $this->get_id() ), $this->data, array( 'meta_data' => $this->get_meta_data() ) );
247
	}
248
249
	/**
250
	 * Returns array of expected data keys for this object.
251
	 *
252
	 * @since   1.0.19
253
	 * @return array
254
	 */
255
	public function get_data_keys() {
256
		return array_keys( $this->data );
257
	}
258
259
	/**
260
	 * Returns all "extra" data keys for an object (for sub objects like item types).
261
	 *
262
	 * @since  1.0.19
263
	 * @return array
264
	 */
265
	public function get_extra_data_keys() {
266
		return array_keys( $this->extra_data );
267
	}
268
269
	/**
270
	 * Filter null meta values from array.
271
	 *
272
	 * @since  1.0.19
273
	 * @param mixed $meta Meta value to check.
274
	 * @return bool
275
	 */
276
	protected function filter_null_meta( $meta ) {
277
		return ! is_null( $meta->value );
278
	}
279
280
	/**
281
	 * Get All Meta Data.
282
	 *
283
	 * @since 1.0.19
284
	 * @return array of objects.
285
	 */
286
	public function get_meta_data() {
287
		$this->maybe_read_meta_data();
288
		return array_values( array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) ) );
289
	}
290
291
	/**
292
	 * Check if the key is an internal one.
293
	 *
294
	 * @since  1.0.19
295
	 * @param  string $key Key to check.
296
	 * @return bool   true if it's an internal key, false otherwise
297
	 */
298
	protected function is_internal_meta_key( $key ) {
299
		$internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true );
300
301
		if ( ! $internal_meta_key ) {
302
			return false;
303
		}
304
305
		$has_setter_or_getter = is_callable( array( $this, 'set_' . $key ) ) || is_callable( array( $this, 'get_' . $key ) );
306
307
		if ( ! $has_setter_or_getter ) {
308
			return false;
309
		}
310
311
		/* translators: %s: $key Key to check */
312
		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.', 'getpaid' ), $key ), '1.0.19' );
313
314
		return true;
315
	}
316
317
	/**
318
	 * Get Meta Data by Key.
319
	 *
320
	 * @since  1.0.19
321
	 * @param  string $key Meta Key.
322
	 * @param  bool   $single return first found meta with key, or all with $key.
323
	 * @param  string $context What the value is for. Valid values are view and edit.
324
	 * @return mixed
325
	 */
326
	public function get_meta( $key = '', $single = true, $context = 'view' ) {
327
328
		// Check if this is an internal meta key.
329
		if ( $this->is_internal_meta_key( $key ) ) {
330
			$function = 'get_' . $key;
331
332
			if ( is_callable( array( $this, $function ) ) ) {
333
				return $this->{$function}();
334
			}
335
		}
336
337
		// Read the meta data if not yet read.
338
		$this->maybe_read_meta_data();
339
		$meta_data  = $this->get_meta_data();
340
		$array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true );
341
		$value      = $single ? '' : array();
342
343
		if ( ! empty( $array_keys ) ) {
344
			// 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()).
345
			if ( $single ) {
346
				$value = $meta_data[ current( $array_keys ) ]->value;
347
			} else {
348
				$value = array_intersect_key( $meta_data, array_flip( $array_keys ) );
349
			}
350
		}
351
352
		if ( 'view' === $context ) {
353
			$value = apply_filters( $this->get_hook_prefix() . $key, $value, $this );
354
		}
355
356
		return $value;
357
	}
358
359
	/**
360
	 * See if meta data exists, since get_meta always returns a '' or array().
361
	 *
362
	 * @since  1.0.19
363
	 * @param  string $key Meta Key.
364
	 * @return boolean
365
	 */
366
	public function meta_exists( $key = '' ) {
367
		$this->maybe_read_meta_data();
368
		$array_keys = wp_list_pluck( $this->get_meta_data(), 'key' );
369
		return in_array( $key, $array_keys, true );
370
	}
371
372
	/**
373
	 * Set all meta data from array.
374
	 *
375
	 * @since 1.0.19
376
	 * @param array $data Key/Value pairs.
377
	 */
378
	public function set_meta_data( $data ) {
379
		if ( ! empty( $data ) && is_array( $data ) ) {
380
			$this->maybe_read_meta_data();
381
			foreach ( $data as $meta ) {
382
				$meta = (array) $meta;
383
				if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) {
384
					$this->meta_data[] = new GetPaid_Meta_Data(
385
						array(
386
							'id'    => $meta['id'],
387
							'key'   => $meta['key'],
388
							'value' => $meta['value'],
389
						)
390
					);
391
				}
392
			}
393
		}
394
	}
395
396
	/**
397
	 * Add meta data.
398
	 *
399
	 * @since 1.0.19
400
	 *
401
	 * @param string       $key Meta key.
402
	 * @param string|array $value Meta value.
403
	 * @param bool         $unique Should this be a unique key?.
404
	 */
405
	public function add_meta_data( $key, $value, $unique = false ) {
406
		if ( $this->is_internal_meta_key( $key ) ) {
407
			$function = 'set_' . $key;
408
409
			if ( is_callable( array( $this, $function ) ) ) {
410
				return $this->{$function}( $value );
411
			}
412
		}
413
414
		$this->maybe_read_meta_data();
415
		if ( $unique ) {
416
			$this->delete_meta_data( $key );
417
		}
418
		$this->meta_data[] = new GetPaid_Meta_Data(
419
			array(
420
				'key'   => $key,
421
				'value' => $value,
422
			)
423
		);
424
	}
425
426
	/**
427
	 * Update meta data by key or ID, if provided.
428
	 *
429
	 * @since  1.0.19
430
	 *
431
	 * @param  string       $key Meta key.
432
	 * @param  string|array $value Meta value.
433
	 * @param  int          $meta_id Meta ID.
434
	 */
435
	public function update_meta_data( $key, $value, $meta_id = 0 ) {
436
		if ( $this->is_internal_meta_key( $key ) ) {
437
			$function = 'set_' . $key;
438
439
			if ( is_callable( array( $this, $function ) ) ) {
440
				return $this->{$function}( $value );
441
			}
442
		}
443
444
		$this->maybe_read_meta_data();
445
446
		$array_key = false;
447
448
		if ( $meta_id ) {
449
			$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id, true );
450
			$array_key  = $array_keys ? current( $array_keys ) : false;
451
		} else {
452
			// Find matches by key.
453
			$matches = array();
454
			foreach ( $this->meta_data as $meta_data_array_key => $meta ) {
455
				if ( $meta->key === $key ) {
456
					$matches[] = $meta_data_array_key;
457
				}
458
			}
459
460
			if ( ! empty( $matches ) ) {
461
				// Set matches to null so only one key gets the new value.
462
				foreach ( $matches as $meta_data_array_key ) {
463
					$this->meta_data[ $meta_data_array_key ]->value = null;
464
				}
465
				$array_key = current( $matches );
466
			}
467
		}
468
469
		if ( false !== $array_key ) {
470
			$meta        = $this->meta_data[ $array_key ];
471
			$meta->key   = $key;
472
			$meta->value = $value;
473
		} else {
474
			$this->add_meta_data( $key, $value, true );
475
		}
476
	}
477
478
	/**
479
	 * Delete meta data.
480
	 *
481
	 * @since 1.0.19
482
	 * @param string $key Meta key.
483
	 */
484
	public function delete_meta_data( $key ) {
485
		$this->maybe_read_meta_data();
486
		$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true );
487
488
		if ( $array_keys ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array_keys of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
489
			foreach ( $array_keys as $array_key ) {
490
				$this->meta_data[ $array_key ]->value = null;
491
			}
492
		}
493
	}
494
495
	/**
496
	 * Delete meta data.
497
	 *
498
	 * @since 1.0.19
499
	 * @param int $mid Meta ID.
500
	 */
501
	public function delete_meta_data_by_mid( $mid ) {
502
		$this->maybe_read_meta_data();
503
		$array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true );
504
505
		if ( $array_keys ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array_keys of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
506
			foreach ( $array_keys as $array_key ) {
507
				$this->meta_data[ $array_key ]->value = null;
508
			}
509
		}
510
	}
511
512
	/**
513
	 * Read meta data if null.
514
	 *
515
	 * @since 1.0.19
516
	 */
517
	protected function maybe_read_meta_data() {
518
		if ( is_null( $this->meta_data ) ) {
0 ignored issues
show
introduced by
The condition is_null($this->meta_data) is always false.
Loading history...
519
			$this->read_meta_data();
520
		}
521
	}
522
523
	/**
524
	 * Read Meta Data from the database. Ignore any internal properties.
525
	 * Uses it's own caches because get_metadata does not provide meta_ids.
526
	 *
527
	 * @since 1.0.19
528
	 * @param bool $force_read True to force a new DB read (and update cache).
529
	 */
530
	public function read_meta_data( $force_read = false ) {
531
		$this->meta_data = array();
532
		$cache_loaded    = false;
533
534
		if ( ! $this->get_id() ) {
535
			return;
536
		}
537
538
		if ( ! $this->data_store ) {
539
			return;
540
		}
541
542
		if ( ! empty( $this->cache_group ) ) {
543
			// Prefix by group allows invalidation by group until https://core.trac.wordpress.org/ticket/4476 is implemented.
544
			$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();
545
		}
546
547
		if ( ! $force_read ) {
548
			if ( ! empty( $this->cache_group ) ) {
549
				$cached_meta  = wp_cache_get( $cache_key, $this->cache_group );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cache_key does not seem to be defined for all execution paths leading up to this point.
Loading history...
550
				$cache_loaded = ! empty( $cached_meta );
551
			}
552
		}
553
554
		$raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cached_meta does not seem to be defined for all execution paths leading up to this point.
Loading history...
555
		if ( $raw_meta_data ) {
556
			foreach ( $raw_meta_data as $meta ) {
557
				$this->meta_data[] = new GetPaid_Meta_Data(
558
					array(
559
						'id'    => (int) $meta->meta_id,
560
						'key'   => $meta->meta_key,
561
						'value' => maybe_unserialize( $meta->meta_value ),
562
					)
563
				);
564
			}
565
566
			if ( ! $cache_loaded && ! empty( $this->cache_group ) ) {
567
				wp_cache_set( $cache_key, $raw_meta_data, $this->cache_group );
568
			}
569
		}
570
	}
571
572
	/**
573
	 * Update Meta Data in the database.
574
	 *
575
	 * @since 1.0.19
576
	 */
577
	public function save_meta_data() {
578
		if ( ! $this->data_store || is_null( $this->meta_data ) ) {
579
			return;
580
		}
581
		foreach ( $this->meta_data as $array_key => $meta ) {
582
			if ( is_null( $meta->value ) ) {
583
				if ( ! empty( $meta->id ) ) {
584
					$this->data_store->delete_meta( $this, $meta );
585
					unset( $this->meta_data[ $array_key ] );
586
				}
587
			} elseif ( empty( $meta->id ) ) {
588
				$meta->id = $this->data_store->add_meta( $this, $meta );
589
				$meta->apply_changes();
590
			} else {
591
				if ( $meta->get_changes() ) {
592
					$this->data_store->update_meta( $this, $meta );
593
					$meta->apply_changes();
594
				}
595
			}
596
		}
597
		if ( ! empty( $this->cache_group ) ) {
598
			$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();
599
			wp_cache_delete( $cache_key, $this->cache_group );
600
		}
601
	}
602
603
	/**
604
	 * Set ID.
605
	 *
606
	 * @since 1.0.19
607
	 * @param int $id ID.
608
	 */
609
	public function set_id( $id ) {
610
		$this->id = absint( $id );
611
	}
612
613
	/**
614
	 * Set all props to default values.
615
	 *
616
	 * @since 1.0.19
617
	 */
618
	public function set_defaults() {
619
		$this->data    = $this->default_data;
620
		$this->changes = array();
621
		$this->set_object_read( false );
622
	}
623
624
	/**
625
	 * Set object read property.
626
	 *
627
	 * @since 1.0.19
628
	 * @param boolean $read Should read?.
629
	 */
630
	public function set_object_read( $read = true ) {
631
		$this->object_read = (bool) $read;
632
	}
633
634
	/**
635
	 * Get object read property.
636
	 *
637
	 * @since  1.0.19
638
	 * @return boolean
639
	 */
640
	public function get_object_read() {
641
		return (bool) $this->object_read;
642
	}
643
644
	/**
645
	 * Set a collection of props in one go, collect any errors, and return the result.
646
	 * Only sets using public methods.
647
	 *
648
	 * @since  1.0.19
649
	 *
650
	 * @param array  $props Key value pairs to set. Key is the prop and should map to a setter function name.
651
	 * @param string $context In what context to run this.
652
	 *
653
	 * @return bool|WP_Error
654
	 */
655
	public function set_props( $props, $context = 'set' ) {
656
		$errors = false;
657
658
		foreach ( $props as $prop => $value ) {
659
			try {
660
				/**
661
				 * Checks if the prop being set is allowed, and the value is not null.
662
				 */
663
				if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) {
664
					continue;
665
				}
666
				$setter = "set_$prop";
667
668
				if ( is_callable( array( $this, $setter ) ) ) {
669
					$this->{$setter}( $value );
670
				}
671
			} catch ( Exception $e ) {
672
				if ( ! $errors ) {
673
					$errors = new WP_Error();
674
				}
675
				$errors->add( $e->getCode(), $e->getMessage() );
676
			}
677
		}
678
679
		return $errors && count( $errors->get_error_codes() ) ? $errors : true;
680
	}
681
682
	/**
683
	 * Sets a prop for a setter method.
684
	 *
685
	 * This stores changes in a special array so we can track what needs saving
686
	 * the the DB later.
687
	 *
688
	 * @since 1.0.19
689
	 * @param string $prop Name of prop to set.
690
	 * @param mixed  $value Value of the prop.
691
	 */
692
	protected function set_prop( $prop, $value ) {
693
		if ( array_key_exists( $prop, $this->data ) ) {
694
			if ( true === $this->object_read ) {
695
				if ( $value !== $this->data[ $prop ] || array_key_exists( $prop, $this->changes ) ) {
696
					$this->changes[ $prop ] = $value;
697
				}
698
			} else {
699
				$this->data[ $prop ] = $value;
700
			}
701
		}
702
	}
703
704
	/**
705
	 * Return data changes only.
706
	 *
707
	 * @since 1.0.19
708
	 * @return array
709
	 */
710
	public function get_changes() {
711
		return $this->changes;
712
	}
713
714
	/**
715
	 * Merge changes with data and clear.
716
	 *
717
	 * @since 1.0.19
718
	 */
719
	public function apply_changes() {
720
		$this->data    = array_replace_recursive( $this->data, $this->changes );
721
		$this->changes = array();
722
	}
723
724
	/**
725
	 * Prefix for action and filter hooks on data.
726
	 *
727
	 * @since  1.0.19
728
	 * @return string
729
	 */
730
	protected function get_hook_prefix() {
731
		return 'wpinv_get_' . $this->object_type . '_';
732
	}
733
734
	/**
735
	 * Gets a prop for a getter method.
736
	 *
737
	 * Gets the value from either current pending changes, or the data itself.
738
	 * Context controls what happens to the value before it's returned.
739
	 *
740
	 * @since  1.0.19
741
	 * @param  string $prop Name of prop to get.
742
	 * @param  string $context What the value is for. Valid values are view and edit.
743
	 * @return mixed
744
	 */
745
	protected function get_prop( $prop, $context = 'view' ) {
746
		$value = null;
747
748
		if ( array_key_exists( $prop, $this->data ) ) {
749
			$value = array_key_exists( $prop, $this->changes ) ? $this->changes[ $prop ] : $this->data[ $prop ];
750
751
			if ( 'view' === $context ) {
752
				$value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this );
753
			}
754
		}
755
756
		return $value;
757
	}
758
759
	/**
760
	 * Sets a date prop whilst handling formatting and datetime objects.
761
	 *
762
	 * @since 1.0.19
763
	 * @param string         $prop Name of prop to set.
764
	 * @param string|integer $value Value of the prop.
765
	 */
766
	protected function set_date_prop( $prop, $value ) {
767
768
		if ( empty( $value ) ) {
769
			$this->set_prop( $prop, null );
770
			return;
771
		}
772
		$this->set_prop( $prop, $value );
773
774
	}
775
776
	/**
777
	 * When invalid data is found, throw an exception unless reading from the DB.
778
	 *
779
	 * @throws Exception Data Exception.
780
	 * @since 1.0.19
781
	 * @param string $code             Error code.
782
	 * @param string $message          Error message.
783
	 */
784
	protected function error( $code, $message ) {
785
		throw new Exception( $message, $code );
0 ignored issues
show
Bug introduced by
$code of type string is incompatible with the type integer expected by parameter $code of Exception::__construct(). ( Ignorable by Annotation )

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

785
		throw new Exception( $message, /** @scrutinizer ignore-type */ $code );
Loading history...
786
	}
787
}
788