Passed
Push — master ( 08c185...0abe41 )
by Brian
10:06 queued 05:09
created

WPInv_Item::get_owner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 1
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Item Class
8
 *
9
 */
10
class WPInv_Item  extends GetPaid_Data {
11
12
    /**
13
	 * Which data store to load.
14
	 *
15
	 * @var string
16
	 */
17
    protected $data_store_name = 'item';
18
19
    /**
20
	 * This is the name of this object type.
21
	 *
22
	 * @var string
23
	 */
24
	protected $object_type = 'item';
25
26
    /**
27
	 * Item Data array. This is the core item data exposed in APIs.
28
	 *
29
	 * @since 1.0.19
30
	 * @var array
31
	 */
32
	protected $data = array(
33
		'parent_id'            => 0,
34
		'status'               => 'draft',
35
		'version'              => '',
36
		'date_created'         => null,
37
        'date_modified'        => null,
38
        'name'                 => '',
39
        'description'          => '',
40
        'author'               => 1,
41
        'price'                => 0,
42
        'vat_rule'             => 'digital',
43
        'vat_class'            => '_standard',
44
        'type'                 => 'custom',
45
        'custom_id'            => null,
46
        'custom_name'          => null,
47
        'custom_singular_name' => null,
48
        'is_editable'          => 1,
49
        'is_dynamic_pricing'   => null,
50
        'minimum_price'        => null,
51
        'is_recurring'         => null,
52
        'recurring_period'     => null,
53
        'recurring_interval'   => null,
54
        'recurring_limit'      => null,
55
        'is_free_trial'        => null,
56
        'trial_period'         => null,
57
        'trial_interval'       => null,
58
    );
59
60
    /**
61
	 * Stores meta in cache for future reads.
62
	 *
63
	 * A group must be set to to enable caching.
64
	 *
65
	 * @var string
66
	 */
67
	protected $cache_group = 'getpaid_items';
68
69
    /**
70
     * Stores a reference to the original WP_Post object
71
     * 
72
     * @var WP_Post
73
     */
74
    protected $post = null;
75
76
    /**
77
	 * Get the item if ID is passed, otherwise the item is new and empty.
78
	 *
79
	 * @param  int|object|WPInv_Item|WP_Post $item Item to read.
80
	 */
81
	public function __construct( $item = 0 ) {
82
		parent::__construct( $item );
83
84
		if ( ! empty( $item ) && is_numeric( $item ) && 'wpi_item' == get_post_type( $item ) ) {
85
			$this->set_id( $item );
86
		} elseif ( $item instanceof self ) {
87
			$this->set_id( $item->get_id() );
88
		} elseif ( ! empty( $item->ID ) ) {
89
			$this->set_id( $item->ID );
90
		} elseif ( is_scalar( $item ) && $item_id = self::get_item_id_by_field( $item, 'custom_id' ) ) {
91
			$this->set_id( $item_id );
92
		} elseif ( is_scalar( $item ) && $item_id = self::get_item_id_by_field( $item, 'name' ) ) {
93
			$this->set_id( $item_id );
94
		} else {
95
			$this->set_object_read( true );
96
		}
97
98
        // Load the datastore.
99
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
100
101
		if ( $this->get_id() > 0 ) {
102
            $this->post = get_post( $this->get_id() );
103
            $this->ID   = $this->get_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...
104
			$this->data_store->read( $this );
105
        }
106
107
	}
108
109
    /*
110
	|--------------------------------------------------------------------------
111
	| CRUD methods
112
	|--------------------------------------------------------------------------
113
	|
114
	| Methods which create, read, update and delete items from the database.
115
	|
116
    */
117
118
    /*
119
	|--------------------------------------------------------------------------
120
	| Getters
121
	|--------------------------------------------------------------------------
122
    */
123
124
    /**
125
	 * Get parent item ID.
126
	 *
127
	 * @since 1.0.19
128
	 * @param  string $context View or edit context.
129
	 * @return int
130
	 */
131
	public function get_parent_id( $context = 'view' ) {
132
		return (int) $this->get_prop( 'parent_id', $context );
133
    }
134
135
    /**
136
	 * Get item status.
137
	 *
138
	 * @since 1.0.19
139
	 * @param  string $context View or edit context.
140
	 * @return string
141
	 */
142
	public function get_status( $context = 'view' ) {
143
		return $this->get_prop( 'status', $context );
144
    }
145
146
    /**
147
	 * Get plugin version when the item was created.
148
	 *
149
	 * @since 1.0.19
150
	 * @param  string $context View or edit context.
151
	 * @return string
152
	 */
153
	public function get_version( $context = 'view' ) {
154
		return $this->get_prop( 'version', $context );
155
    }
156
157
    /**
158
	 * Get date when the item was created.
159
	 *
160
	 * @since 1.0.19
161
	 * @param  string $context View or edit context.
162
	 * @return string
163
	 */
164
	public function get_date_created( $context = 'view' ) {
165
		return $this->get_prop( 'date_created', $context );
166
    }
167
168
    /**
169
	 * Get GMT date when the item was created.
170
	 *
171
	 * @since 1.0.19
172
	 * @param  string $context View or edit context.
173
	 * @return string
174
	 */
175
	public function get_date_created_gmt( $context = 'view' ) {
176
        $date = $this->get_date_created( $context );
177
178
        if ( $date ) {
179
            $date = get_gmt_from_date( $date );
180
        }
181
		return $date;
182
    }
183
184
    /**
185
	 * Get date when the item was last modified.
186
	 *
187
	 * @since 1.0.19
188
	 * @param  string $context View or edit context.
189
	 * @return string
190
	 */
191
	public function get_date_modified( $context = 'view' ) {
192
		return $this->get_prop( 'date_modified', $context );
193
    }
194
195
    /**
196
	 * Get GMT date when the item was last modified.
197
	 *
198
	 * @since 1.0.19
199
	 * @param  string $context View or edit context.
200
	 * @return string
201
	 */
202
	public function get_date_modified_gmt( $context = 'view' ) {
203
        $date = $this->get_date_modified( $context );
204
205
        if ( $date ) {
206
            $date = get_gmt_from_date( $date );
207
        }
208
		return $date;
209
    }
210
211
    /**
212
	 * Get the item name.
213
	 *
214
	 * @since 1.0.19
215
	 * @param  string $context View or edit context.
216
	 * @return string
217
	 */
218
	public function get_name( $context = 'view' ) {
219
		return $this->get_prop( 'name', $context );
220
    }
221
222
    /**
223
	 * Alias of self::get_name().
224
	 *
225
	 * @since 1.0.19
226
	 * @param  string $context View or edit context.
227
	 * @return string
228
	 */
229
	public function get_title( $context = 'view' ) {
230
		return $this->get_name( $context );
231
    }
232
233
    /**
234
	 * Get the item description.
235
	 *
236
	 * @since 1.0.19
237
	 * @param  string $context View or edit context.
238
	 * @return string
239
	 */
240
	public function get_description( $context = 'view' ) {
241
		return $this->get_prop( 'description', $context );
242
    }
243
244
    /**
245
	 * Alias of self::get_description().
246
	 *
247
	 * @since 1.0.19
248
	 * @param  string $context View or edit context.
249
	 * @return string
250
	 */
251
	public function get_excerpt( $context = 'view' ) {
252
		return $this->get_description( $context );
253
    }
254
255
    /**
256
	 * Alias of self::get_description().
257
	 *
258
	 * @since 1.0.19
259
	 * @param  string $context View or edit context.
260
	 * @return string
261
	 */
262
	public function get_summary( $context = 'view' ) {
263
		return $this->get_description( $context );
264
    }
265
266
    /**
267
	 * Get the owner of the item.
268
	 *
269
	 * @since 1.0.19
270
	 * @param  string $context View or edit context.
271
	 * @return int
272
	 */
273
	public function get_author( $context = 'view' ) {
274
		return (int) $this->get_prop( 'author', $context );
275
	}
276
	
277
	/**
278
	 * Alias of self::get_author().
279
	 *
280
	 * @since 1.0.19
281
	 * @param  string $context View or edit context.
282
	 * @return int
283
	 */
284
	public function get_owner( $context = 'view' ) {
285
		return $this->get_author( $context );
286
    }
287
288
    /**
289
	 * Get the price of the item.
290
	 *
291
	 * @since 1.0.19
292
	 * @param  string $context View or edit context.
293
	 * @return float
294
	 */
295
	public function get_price( $context = 'view' ) {
296
        return wpinv_sanitize_amount( $this->get_prop( 'price', $context ) );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_sanitize_am...rop('price', $context)) also could return the type string which is incompatible with the documented return type double.
Loading history...
297
	}
298
	
299
	/**
300
	 * Get the inital price of the item.
301
	 *
302
	 * @since 1.0.19
303
	 * @param  string $context View or edit context.
304
	 * @return float
305
	 */
306
	public function get_initial_price( $context = 'view' ) {
307
308
		$price = (float) $this->get_price( $context );
309
310
		if ( $this->has_free_trial() ) {
311
			$price = 0;
312
		}
313
314
        return wpinv_sanitize_amount( apply_filters( 'wpinv_get_initial_item_price', $price, $this ) );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_sanitize_am...price', $price, $this)) also could return the type string which is incompatible with the documented return type double.
Loading history...
315
    }
316
317
    /**
318
	 * Returns a formated price.
319
	 *
320
	 * @since 1.0.19
321
	 * @param  string $context View or edit context.
322
	 * @return string
323
	 */
324
    public function get_the_price() {
325
        return wpinv_price( wpinv_format_amount( $this->get_price() ) );
326
	}
327
328
	/**
329
	 * Returns the formated initial price.
330
	 *
331
	 * @since 1.0.19
332
	 * @param  string $context View or edit context.
333
	 * @return string
334
	 */
335
    public function get_the_initial_price() {
336
        return wpinv_price( wpinv_format_amount( $this->get_initial_price() ) );
337
    }
338
339
    /**
340
	 * Get the VAT rule of the item.
341
	 *
342
	 * @since 1.0.19
343
	 * @param  string $context View or edit context.
344
	 * @return string
345
	 */
346
	public function get_vat_rule( $context = 'view' ) {
347
        return $this->get_prop( 'vat_rule', $context );
348
    }
349
350
    /**
351
	 * Get the VAT class of the item.
352
	 *
353
	 * @since 1.0.19
354
	 * @param  string $context View or edit context.
355
	 * @return string
356
	 */
357
	public function get_vat_class( $context = 'view' ) {
358
        return $this->get_prop( 'vat_class', $context );
359
    }
360
361
    /**
362
	 * Get the type of the item.
363
	 *
364
	 * @since 1.0.19
365
	 * @param  string $context View or edit context.
366
	 * @return string
367
	 */
368
	public function get_type( $context = 'view' ) {
369
        return $this->get_prop( 'type', $context );
370
    }
371
372
    /**
373
	 * Get the custom id of the item.
374
	 *
375
	 * @since 1.0.19
376
	 * @param  string $context View or edit context.
377
	 * @return string
378
	 */
379
	public function get_custom_id( $context = 'view' ) {
380
        return $this->get_prop( 'custom_id', $context );
381
    }
382
383
    /**
384
	 * Get the custom name of the item.
385
	 *
386
	 * @since 1.0.19
387
	 * @param  string $context View or edit context.
388
	 * @return string
389
	 */
390
	public function get_custom_name( $context = 'view' ) {
391
        return $this->get_prop( 'custom_name', $context );
392
    }
393
394
    /**
395
	 * Get the custom singular name of the item.
396
	 *
397
	 * @since 1.0.19
398
	 * @param  string $context View or edit context.
399
	 * @return string
400
	 */
401
	public function get_custom_singular_name( $context = 'view' ) {
402
        return $this->get_prop( 'custom_singular_name', $context );
403
    }
404
405
    /**
406
	 * Checks if an item is editable..
407
	 *
408
	 * @since 1.0.19
409
	 * @param  string $context View or edit context.
410
	 * @return int
411
	 */
412
	public function get_is_editable( $context = 'view' ) {
413
        return (int) $this->get_prop( 'is_editable', $context );
414
    }
415
416
    /**
417
	 * Alias of self::get_is_editable().
418
	 *
419
	 * @since 1.0.19
420
	 * @param  string $context View or edit context.
421
	 * @return int
422
	 */
423
	public function get_editable( $context = 'view' ) {
424
		return $this->get_is_editable( $context );
425
    }
426
427
    /**
428
	 * Checks if dynamic pricing is enabled.
429
	 *
430
	 * @since 1.0.19
431
	 * @param  string $context View or edit context.
432
	 * @return int
433
	 */
434
	public function get_is_dynamic_pricing( $context = 'view' ) {
435
        return (int) $this->get_prop( 'is_dynamic_pricing', $context );
436
    }
437
438
    /**
439
	 * Returns the minimum price if dynamic pricing is enabled.
440
	 *
441
	 * @since 1.0.19
442
	 * @param  string $context View or edit context.
443
	 * @return float
444
	 */
445
	public function get_minimum_price( $context = 'view' ) {
446
        return wpinv_sanitize_amount( $this->get_prop( 'minimum_price', $context ) );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_sanitize_am...imum_price', $context)) also could return the type string which is incompatible with the documented return type double.
Loading history...
447
    }
448
449
    /**
450
	 * Checks if this is a recurring item.
451
	 *
452
	 * @since 1.0.19
453
	 * @param  string $context View or edit context.
454
	 * @return int
455
	 */
456
	public function get_is_recurring( $context = 'view' ) {
457
        return (int) $this->get_prop( 'is_recurring', $context );
458
	}
459
	
460
	/**
461
	 * Get the recurring price of the item.
462
	 *
463
	 * @since 1.0.19
464
	 * @param  string $context View or edit context.
465
	 * @return float
466
	 */
467
	public function get_recurring_price( $context = 'view' ) {
468
		$price = $this->get_price( $context );
469
        return wpinv_sanitize_amount( apply_filters( 'wpinv_get_recurring_item_price', $price, $this->ID ) );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_sanitize_am...e', $price, $this->ID)) also could return the type string which is incompatible with the documented return type double.
Loading history...
470
	}
471
472
	/**
473
	 * Get the formatted recurring price of the item.
474
	 *
475
	 * @since 1.0.19
476
	 * @param  string $context View or edit context.
477
	 * @return string
478
	 */
479
    public function get_the_recurring_price() {
480
        return wpinv_price( wpinv_format_amount( $this->get_recurring_price() ) );
481
	}
482
483
	/**
484
	 * Get the first renewal date (in timestamps) of the item.
485
	 *
486
	 * @since 1.0.19
487
	 * @return int
488
	 */
489
	public function get_first_renewal_date() {
490
491
		$periods = array(
492
			'D' => 'days',
493
			'W' => 'weeks',
494
			'M' => 'months',
495
			'Y' => 'years',
496
		);
497
498
		$period   = $this->get_recurring_period();
499
		$interval = $this->get_recurring_interval();
500
501
		if ( $this->has_free_trial() ) {
502
			$period   = $this->get_trial_period();
503
			$interval = $this->get_trial_interval();
504
		}
505
506
		$period       = $periods[ $period ];
507
		$interval     = empty( $interval ) ? 1 : $interval;
508
		$next_renewal = strtotime( "+$interval $period", current_time( 'timestamp' ) );
509
        return apply_filters( 'wpinv_get_first_renewal_date', $next_renewal, $this );
510
    }
511
512
    /**
513
	 * Get the recurring period.
514
	 *
515
	 * @since 1.0.19
516
	 * @param  bool $full Return abbreviation or in full.
517
	 * @return string
518
	 */
519
	public function get_recurring_period( $full = false ) {
520
        $period = $this->get_prop( 'recurring_period', 'view' );
521
522
        if ( $full && ! is_bool( $full ) ) {
0 ignored issues
show
introduced by
The condition is_bool($full) is always true.
Loading history...
523
            $full = false;
524
        }
525
526
        return getpaid_sanitize_recurring_period( $period, $full );
527
    }
528
529
    /**
530
	 * Get the recurring interval.
531
	 *
532
	 * @since 1.0.19
533
	 * @param  string $context View or edit context.
534
	 * @return int
535
	 */
536
	public function get_recurring_interval( $context = 'view' ) {
537
		$interval = absint( $this->get_prop( 'recurring_interval', $context ) );
538
539
		if ( $interval < 1 ) {
540
			$interval = 1;
541
		}
542
543
        return $interval;
544
    }
545
546
    /**
547
	 * Get the recurring limit.
548
	 *
549
	 * @since 1.0.19
550
	 * @param  string $context View or edit context.
551
	 * @return int
552
	 */
553
	public function get_recurring_limit( $context = 'view' ) {
554
        return (int) $this->get_prop( 'recurring_limit', $context );
555
    }
556
557
    /**
558
	 * Checks if we have a free trial.
559
	 *
560
	 * @since 1.0.19
561
	 * @param  string $context View or edit context.
562
	 * @return int
563
	 */
564
	public function get_is_free_trial( $context = 'view' ) {
565
        return (int) $this->get_prop( 'is_free_trial', $context );
566
    }
567
568
    /**
569
	 * Alias for self::get_is_free_trial().
570
	 *
571
	 * @since 1.0.19
572
	 * @param  string $context View or edit context.
573
	 * @return int
574
	 */
575
	public function get_free_trial( $context = 'view' ) {
576
        return $this->get_is_free_trial( $context );
577
    }
578
579
    /**
580
	 * Get the trial period.
581
	 *
582
	 * @since 1.0.19
583
	 * @param  bool $full Return abbreviation or in full.
584
	 * @return string
585
	 */
586
	public function get_trial_period( $full = false ) {
587
        $period = $this->get_prop( 'trial_period', 'view' );
588
589
        if ( $full && ! is_bool( $full ) ) {
0 ignored issues
show
introduced by
The condition is_bool($full) is always true.
Loading history...
590
            $full = false;
591
        }
592
593
        return getpaid_sanitize_recurring_period( $period, $full );
594
    }
595
596
    /**
597
	 * Get the trial interval.
598
	 *
599
	 * @since 1.0.19
600
	 * @param  string $context View or edit context.
601
	 * @return int
602
	 */
603
	public function get_trial_interval( $context = 'view' ) {
604
        return (int) $this->get_prop( 'trial_interval', $context );
605
	}
606
	
607
	/**
608
	 * Get the item's edit url.
609
	 *
610
	 * @since 1.0.19
611
	 * @return string
612
	 */
613
	public function get_edit_url() {
614
        return get_edit_post_link( $this->get_id() );
615
	}
616
617
	/**
618
	 * Given an item's name/custom id, it returns its id.
619
	 *
620
	 *
621
	 * @static
622
	 * @param string $value The item name or custom id.
623
	 * @param string $field Either name or custom_id.
624
	 * @param string $type in case you need to search for a given type.
625
	 * @since 1.0.15
626
	 * @return int
627
	 */
628
	public static function get_item_id_by_field( $value, $field = 'custom_id', $type = '' ) {
629
630
		// Trim the value.
631
		$value = trim( $value );
632
633
		if ( empty( $value ) ) {
634
			return 0;
635
		}
636
637
        // Valid fields.
638
        $fields = array( 'custom_id', 'name', 'slug' );
639
640
		// Ensure a field has been passed.
641
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
642
			return 0;
643
		}
644
645
		if ( $field == 'name' ) {
646
			$field = 'slug';
647
		} 
648
649
		// Maybe retrieve from the cache.
650
		$item_id = wp_cache_get( $value, "getpaid_{$type}_item_{$field}s_to_item_ids" );
651
		if ( ! empty( $item_id ) ) {
652
			return $item_id;
653
		}
654
655
		// Fetch from the db.
656
		if ( $field =='slug' ) {
657
			$items = get_posts(
658
				array(
0 ignored issues
show
Security Variable Injection introduced by
array('post_type' => 'wp...'post_status' => 'any') can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and Data is passed through wpinv_clean()
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 924
  2. array('transaction_id' => wpinv_clean($_POST['x_trans_id']), 'gateway' => $this->id) is assigned to $args
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 923
  3. WPInv_Subscription::add_payment() is called
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 928
  4. Enters via parameter $args
    in includes/wpinv-subscription.php on line 268
  5. WPInv_Invoice::set_gateway() is called
    in includes/wpinv-subscription.php on line 297
  6. Enters via parameter $value
    in includes/class-wpinv-invoice.php on line 2817
  7. GetPaid_Data::set_prop() is called
    in includes/class-wpinv-invoice.php on line 2818
  8. Enters via parameter $value
    in includes/data-stores/class-getpaid-data.php on line 793
  9. Data is passed through maybe_unserialize(), and maybe_unserialize($value) is assigned to property WPInv_Invoice::$changes
    in includes/data-stores/class-getpaid-data.php on line 797
  10. Read from property WPInv_Invoice::$changes, and array_key_exists($prop, $this->changes) ? $this->changes[$prop] : $this->data[$prop] is assigned to $value
    in includes/data-stores/class-getpaid-data.php on line 850
  11. $value is returned
    in includes/data-stores/class-getpaid-data.php on line 857
  12. $this->get_prop('country', $context) is assigned to $country
    in includes/class-wpinv-invoice.php on line 977
  13. empty($country) ? wpinv_get_default_country() : $country is returned
    in includes/class-wpinv-invoice.php on line 978
  14. $this->get_id() is assigned to property WPInv_Item::$ID
    in includes/class-wpinv-item.php on line 103
  15. Read from property WPInv_Item::$ID, and wpinv_get_item_price() is called
    in includes/class-wpinv-legacy-invoice.php on line 1918
  16. Enters via parameter $item_id
    in includes/wpinv-item-functions.php on line 151
  17. WPInv_Item::__construct() is called
    in includes/wpinv-item-functions.php on line 156
  18. Enters via parameter $item
    in includes/class-wpinv-item.php on line 81
  19. WPInv_Item::get_item_id_by_field() is called
    in includes/class-wpinv-item.php on line 90
  20. Enters via parameter $value
    in includes/class-wpinv-item.php on line 628
  21. Data is passed through trim(), and trim($value) is assigned to $value
    in includes/class-wpinv-item.php on line 631

Used in variable context

  1. get_posts() is called
    in includes/class-wpinv-item.php on line 636
  2. Enters via parameter $args
    in wordpress/wp-includes/post.php on line 2017
  3. wp_parse_args() is called
    in wordpress/wp-includes/post.php on line 2031
  4. Enters via parameter $args
    in wordpress/wp-includes/functions.php on line 4413
  5. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 4419
  6. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4938
  7. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4939

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
659
					'post_type'      => 'wpi_item',
660
					'name'           => $value,
661
					'posts_per_page' => 1,
662
					'post_status'    => 'any',
663
				)
664
			);
665
		}
666
667
		if ( $field =='custom_id' ) {
668
			$items = get_posts(
669
				array(
670
					'post_type'      => 'wpi_item',
671
					'posts_per_page' => 1,
672
					'post_status'    => 'any',
673
					'meta_query'     => array(
674
						array(
675
							'key'   => '_wpinv_type',
676
                			'value' => $type,
677
						),
678
						array(
679
							'key'   => '_wpinv_custom_id',
680
                			'value' => $type,
681
						)
682
					)
683
				)
684
			);
685
		}
686
687
		if ( empty( $items ) ) {
688
			return 0;
689
		}
690
691
		// Update the cache with our data
692
		wp_cache_set( $value, $items[0]->ID, "getpaid_{$type}_item_{$field}s_to_item_ids" );
693
694
		return $items[0]->ID;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $items does not seem to be defined for all execution paths leading up to this point.
Loading history...
695
    }
696
697
    /**
698
     * Margic method for retrieving a property.
699
     */
700
    public function __get( $key ) {
701
702
        // Check if we have a helper method for that.
703
        if ( method_exists( $this, 'get_' . $key ) ) {
704
            return call_user_func( array( $this, 'get_' . $key ) );
705
        }
706
707
        // Check if the key is in the associated $post object.
708
        if ( ! empty( $this->post ) && isset( $this->post->$key ) ) {
709
            return $this->post->$key;
710
        }
711
712
        return $this->get_prop( $key );
713
714
    }
715
716
    /*
717
	|--------------------------------------------------------------------------
718
	| Setters
719
	|--------------------------------------------------------------------------
720
	|
721
	| Functions for setting item data. These should not update anything in the
722
	| database itself and should only change what is stored in the class
723
	| object.
724
    */
725
726
    /**
727
	 * Set parent order ID.
728
	 *
729
	 * @since 1.0.19
730
	 */
731
	public function set_parent_id( $value ) {
732
		if ( $value && ( $value === $this->get_id() || ! get_post( $value ) ) ) {
733
			return;
734
		}
735
		$this->set_prop( 'parent_id', absint( $value ) );
736
	}
737
738
    /**
739
	 * Sets item status.
740
	 *
741
	 * @since 1.0.19
742
	 * @param  string $status New status.
743
	 * @return array details of change.
744
	 */
745
	public function set_status( $status ) {
746
        $old_status = $this->get_status();
747
748
        $this->set_prop( 'status', $status );
749
750
		return array(
751
			'from' => $old_status,
752
			'to'   => $status,
753
		);
754
    }
755
756
    /**
757
	 * Set plugin version when the item was created.
758
	 *
759
	 * @since 1.0.19
760
	 */
761
	public function set_version( $value ) {
762
		$this->set_prop( 'version', $value );
763
    }
764
765
    /**
766
	 * Set date when the item was created.
767
	 *
768
	 * @since 1.0.19
769
	 * @param string $value Value to set.
770
     * @return bool Whether or not the date was set.
771
	 */
772
	public function set_date_created( $value ) {
773
        $date = strtotime( $value );
774
775
        if ( $date ) {
776
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
777
            return true;
778
        }
779
780
        return false;
781
782
    }
783
784
    /**
785
	 * Set date when the item was last modified.
786
	 *
787
	 * @since 1.0.19
788
	 * @param string $value Value to set.
789
     * @return bool Whether or not the date was set.
790
	 */
791
	public function set_date_modified( $value ) {
792
        $date = strtotime( $value );
793
794
        if ( $date ) {
795
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
796
            return true;
797
        }
798
799
        return false;
800
801
    }
802
803
    /**
804
	 * Set the item name.
805
	 *
806
	 * @since 1.0.19
807
	 * @param  string $value New name.
808
	 */
809
	public function set_name( $value ) {
810
        $name = sanitize_text_field( $value );
811
		$this->set_prop( 'name', $name );
812
    }
813
814
    /**
815
	 * Alias of self::set_name().
816
	 *
817
	 * @since 1.0.19
818
	 * @param  string $value New name.
819
	 */
820
	public function set_title( $value ) {
821
		$this->set_name( $value );
822
    }
823
824
    /**
825
	 * Set the item description.
826
	 *
827
	 * @since 1.0.19
828
	 * @param  string $value New description.
829
	 */
830
	public function set_description( $value ) {
831
        $description = wp_kses_post( $value );
832
		return $this->set_prop( 'description', $description );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('description', $description) targeting GetPaid_Data::set_prop() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
833
    }
834
835
    /**
836
	 * Alias of self::set_description().
837
	 *
838
	 * @since 1.0.19
839
	 * @param  string $value New description.
840
	 */
841
	public function set_excerpt( $value ) {
842
		$this->set_description( $value );
843
    }
844
845
    /**
846
	 * Alias of self::set_description().
847
	 *
848
	 * @since 1.0.19
849
	 * @param  string $value New description.
850
	 */
851
	public function set_summary( $value ) {
852
		$this->set_description( $value );
853
    }
854
855
    /**
856
	 * Set the owner of the item.
857
	 *
858
	 * @since 1.0.19
859
	 * @param  int $value New author.
860
	 */
861
	public function set_author( $value ) {
862
		$this->set_prop( 'author', (int) $value );
863
	}
864
	
865
	/**
866
	 * Alias of self::set_author().
867
	 *
868
	 * @since 1.0.19
869
	 * @param  int $value New author.
870
	 */
871
	public function set_owner( $value ) {
872
		$this->set_author( $value );
873
    }
874
875
    /**
876
	 * Set the price of the item.
877
	 *
878
	 * @since 1.0.19
879
	 * @param  float $value New price.
880
	 */
881
	public function set_price( $value ) {
882
        $this->set_prop( 'price', (float) wpinv_sanitize_amount( $value ) );
883
    }
884
885
    /**
886
	 * Set the VAT rule of the item.
887
	 *
888
	 * @since 1.0.19
889
	 * @param  string $value new rule.
890
	 */
891
	public function set_vat_rule( $value ) {
892
        $this->set_prop( 'vat_rule', $value );
893
    }
894
895
    /**
896
	 * Set the VAT class of the item.
897
	 *
898
	 * @since 1.0.19
899
	 * @param  string $value new class.
900
	 */
901
	public function set_vat_class( $value ) {
902
        $this->set_prop( 'vat_class', $value );
903
    }
904
905
    /**
906
	 * Set the type of the item.
907
	 *
908
	 * @since 1.0.19
909
	 * @param  string $value new item type.
910
	 * @return string
911
	 */
912
	public function set_type( $value ) {
913
914
        if ( empty( $value ) ) {
915
            $value = 'custom';
916
        }
917
918
        $this->set_prop( 'type', $value );
919
    }
920
921
    /**
922
	 * Set the custom id of the item.
923
	 *
924
	 * @since 1.0.19
925
	 * @param  string $value new custom id.
926
	 */
927
	public function set_custom_id( $value ) {
928
        $this->set_prop( 'custom_id', $value );
929
    }
930
931
    /**
932
	 * Set the custom name of the item.
933
	 *
934
	 * @since 1.0.19
935
	 * @param  string $value new custom name.
936
	 */
937
	public function set_custom_name( $value ) {
938
        $this->set_prop( 'custom_name', $value );
939
    }
940
941
    /**
942
	 * Set the custom singular name of the item.
943
	 *
944
	 * @since 1.0.19
945
	 * @param  string $value new custom singular name.
946
	 */
947
	public function set_custom_singular_name( $value ) {
948
        $this->set_prop( 'custom_singular_name', $value );
949
    }
950
951
    /**
952
	 * Sets if an item is editable..
953
	 *
954
	 * @since 1.0.19
955
	 * @param  int|bool $value whether or not the item is editable.
956
	 */
957
	public function set_is_editable( $value ) {
958
		if ( is_numeric( $value ) ) {
959
			$this->set_prop( 'is_editable', (int) $value );
960
		}
961
    }
962
963
    /**
964
	 * Sets if dynamic pricing is enabled.
965
	 *
966
	 * @since 1.0.19
967
	 * @param  int|bool $value whether or not dynamic pricing is allowed.
968
	 */
969
	public function set_is_dynamic_pricing( $value ) {
970
        $this->set_prop( 'is_dynamic_pricing', (int) $value );
971
    }
972
973
    /**
974
	 * Sets the minimum price if dynamic pricing is enabled.
975
	 *
976
	 * @since 1.0.19
977
	 * @param  float $value minimum price.
978
	 */
979
	public function set_minimum_price( $value ) {
980
        $this->set_prop( 'minimum_price',  (float) wpinv_sanitize_amount( $value ) );
981
    }
982
983
    /**
984
	 * Sets if this is a recurring item.
985
	 *
986
	 * @since 1.0.19
987
	 * @param  int|bool $value whether or not dynamic pricing is allowed.
988
	 */
989
	public function set_is_recurring( $value ) {
990
        $this->set_prop( 'is_recurring', (int) $value );
991
    }
992
993
    /**
994
	 * Set the recurring period.
995
	 *
996
	 * @since 1.0.19
997
	 * @param  string $value new period.
998
	 */
999
	public function set_recurring_period( $value ) {
1000
        $this->set_prop( 'recurring_period', $value );
1001
    }
1002
1003
    /**
1004
	 * Set the recurring interval.
1005
	 *
1006
	 * @since 1.0.19
1007
	 * @param  int $value recurring interval.
1008
	 */
1009
	public function set_recurring_interval( $value ) {
1010
        return $this->set_prop( 'recurring_interval', (int) $value );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('recurri...interval', (int)$value) targeting GetPaid_Data::set_prop() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1011
    }
1012
1013
    /**
1014
	 * Get the recurring limit.
1015
	 * @since 1.0.19
1016
	 * @param  int $value The recurring limit.
1017
	 * @return int
1018
	 */
1019
	public function set_recurring_limit( $value ) {
1020
        $this->set_prop( 'recurring_limit', (int) $value );
1021
    }
1022
1023
    /**
1024
	 * Checks if we have a free trial.
1025
	 *
1026
	 * @since 1.0.19
1027
	 * @param  int|bool $value whether or not it has a free trial.
1028
	 */
1029
	public function set_is_free_trial( $value ) {
1030
        $this->set_prop( 'is_free_trial', (int) $value );
1031
    }
1032
1033
    /**
1034
	 * Set the trial period.
1035
	 *
1036
	 * @since 1.0.19
1037
	 * @param  string $value trial period.
1038
	 */
1039
	public function set_trial_period( $value ) {
1040
        $this->set_prop( 'trial_period', $value );
1041
    }
1042
1043
    /**
1044
	 * Set the trial interval.
1045
	 *
1046
	 * @since 1.0.19
1047
	 * @param  int $value trial interval.
1048
	 */
1049
	public function set_trial_interval( $value ) {
1050
        $this->set_prop( 'trial_interval', $value );
1051
    }
1052
1053
    /**
1054
     * Create an item. For backwards compatibilty.
1055
     * 
1056
     * @deprecated
1057
	 * @return int item id
1058
     */
1059
    public function create( $data = array() ) {
1060
1061
		// Set the properties.
1062
		if ( is_array( $data ) ) {
1063
			$this->set_props( $data );
1064
		}
1065
1066
		// Save the item.
1067
		return $this->save();
1068
1069
    }
1070
1071
    /**
1072
     * Updates an item. For backwards compatibilty.
1073
     * 
1074
     * @deprecated
1075
	 * @return int item id
1076
     */
1077
    public function update( $data = array() ) {
1078
        return $this->create( $data );
0 ignored issues
show
Deprecated Code introduced by
The function WPInv_Item::create() has been deprecated. ( Ignorable by Annotation )

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

1078
        return /** @scrutinizer ignore-deprecated */ $this->create( $data );
Loading history...
1079
    }
1080
1081
    /*
1082
	|--------------------------------------------------------------------------
1083
	| Conditionals
1084
	|--------------------------------------------------------------------------
1085
	|
1086
	| Checks if a condition is true or false.
1087
	|
1088
	*/
1089
1090
    /**
1091
	 * Checks whether the item has enabled dynamic pricing.
1092
	 *
1093
	 * @since 1.0.19
1094
	 * @return bool
1095
	 */
1096
	public function user_can_set_their_price() {
1097
        return (bool) $this->get_is_dynamic_pricing();
1098
	}
1099
	
1100
	/**
1101
	 * Checks whether the item is recurring.
1102
	 *
1103
	 * @since 1.0.19
1104
	 * @return bool
1105
	 */
1106
	public function is_recurring() {
1107
        return (bool) $this->get_is_recurring();
1108
    }
1109
1110
    /**
1111
	 * Checks whether the item has a free trial.
1112
	 *
1113
	 * @since 1.0.19
1114
	 * @return bool
1115
	 */
1116
    public function has_free_trial() {
1117
        $has_trial = $this->is_recurring() && (bool) $this->get_free_trial() ? true : false;
1118
        return (bool) apply_filters( 'wpinv_item_has_free_trial', $has_trial, $this->ID, $this );
1119
    }
1120
1121
    /**
1122
	 * Checks whether the item is free.
1123
	 *
1124
	 * @since 1.0.19
1125
	 * @return bool
1126
	 */
1127
    public function is_free() {
1128
        $is_free   = $this->get_price() == 0;
1129
        return (bool) apply_filters( 'wpinv_is_free_item', $is_free, $this->ID, $this );
1130
    }
1131
1132
    /**
1133
	 * Checks the item status against a passed in status.
1134
	 *
1135
	 * @param array|string $status Status to check.
1136
	 * @return bool
1137
	 */
1138
	public function has_status( $status ) {
1139
		$has_status = ( is_array( $status ) && in_array( $this->get_status(), $status, true ) ) || $this->get_status() === $status;
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $has_status = (is_array(...t_status() === $status), Probably Intended Meaning: $has_status = is_array($...t_status() === $status)
Loading history...
1140
		return (bool) apply_filters( 'getpaid_item_has_status', $has_status, $this, $status );
1141
    }
1142
1143
    /**
1144
	 * Checks the item type against a passed in types.
1145
	 *
1146
	 * @param array|string $type Type to check.
1147
	 * @return bool
1148
	 */
1149
	public function is_type( $type ) {
1150
		$is_type = ( is_array( $type ) && in_array( $this->get_type(), $type, true ) ) || $this->get_type() === $type;
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $is_type = (is_array($ty...->get_type() === $type), Probably Intended Meaning: $is_type = is_array($typ...->get_type() === $type)
Loading history...
1151
		return (bool) apply_filters( 'getpaid_item_is_type', $is_type, $this, $type );
1152
	}
1153
1154
    /**
1155
	 * Checks whether the item is editable.
1156
	 *
1157
	 * @since 1.0.19
1158
	 * @return bool
1159
	 */
1160
    public function is_editable() {
1161
        $is_editable = $this->get_is_editable();
1162
        return (bool) apply_filters( 'wpinv_item_is_editable', $is_editable, $this->ID, $this );
1163
	}
1164
1165
	/**
1166
	 * Returns an array of cart fees.
1167
	 */
1168
	public function get_fees( $type = 'fee', $item_id = 0 ) {
1169
        global $wpi_session;
1170
        
1171
        $fees = $wpi_session->get( 'wpi_cart_fees' );
1172
1173
        if ( ! wpinv_get_cart_contents() ) {
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_cart_contents() has been deprecated. ( Ignorable by Annotation )

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

1173
        if ( ! /** @scrutinizer ignore-deprecated */ wpinv_get_cart_contents() ) {
Loading history...
1174
            // We can only get item type fees when the cart is empty
1175
            $type = 'custom';
1176
        }
1177
1178
        if ( ! empty( $fees ) && ! empty( $type ) && 'all' !== $type ) {
1179
            foreach( $fees as $key => $fee ) {
1180
                if( ! empty( $fee['type'] ) && $type != $fee['type'] ) {
1181
                    unset( $fees[ $key ] );
1182
                }
1183
            }
1184
        }
1185
1186
        if ( ! empty( $fees ) && ! empty( $item_id ) ) {
1187
            // Remove fees that don't belong to the specified Item
1188
            foreach ( $fees as $key => $fee ) {
1189
                if ( (int) $item_id !== (int)$fee['custom_id'] ) {
1190
                    unset( $fees[ $key ] );
1191
                }
1192
            }
1193
        }
1194
1195
        if ( ! empty( $fees ) ) {
1196
            // Remove fees that belong to a specific item but are not in the cart
1197
            foreach( $fees as $key => $fee ) {
1198
                if( empty( $fee['custom_id'] ) ) {
1199
                    continue;
1200
                }
1201
1202
                if ( !wpinv_item_in_cart( $fee['custom_id'] ) ) {
1203
                    unset( $fees[ $key ] );
1204
                }
1205
            }
1206
        }
1207
1208
        return ! empty( $fees ) ? $fees : array();
1209
    }
1210
1211
    /**
1212
	 * Checks whether the item is purchasable.
1213
	 *
1214
	 * @since 1.0.19
1215
	 * @return bool
1216
	 */
1217
    public function can_purchase() {
1218
        $can_purchase = null !== $this->get_id();
1219
1220
        if ( ! current_user_can( 'edit_post', $this->ID ) && $this->post_status != 'publish' ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_status does not exist on WPInv_Item. Since you implemented __get, consider adding a @property annotation.
Loading history...
1221
            $can_purchase = false;
1222
        }
1223
1224
        return (bool) apply_filters( 'wpinv_can_purchase_item', $can_purchase, $this );
1225
    }
1226
1227
    /**
1228
	 * Checks whether the item supports dynamic pricing.
1229
	 *
1230
	 * @since 1.0.19
1231
	 * @return bool
1232
	 */
1233
    public function supports_dynamic_pricing() {
1234
        return (bool) apply_filters( 'wpinv_item_supports_dynamic_pricing', true, $this );
1235
    }
1236
}
1237