Passed
Pull Request — master (#390)
by Brian
04:21
created

WPInv_Item::get_item_id_by_field()   B

Complexity

Conditions 9
Paths 20

Size

Total Lines 67
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 35
c 0
b 0
f 0
dl 0
loc 67
rs 8.0555
cc 9
nc 20
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 string
272
	 */
273
	public function get_author( $context = 'view' ) {
274
		return (int) $this->get_prop( 'author', $context );
275
    }
276
277
    /**
278
	 * Get the price of the item.
279
	 *
280
	 * @since 1.0.19
281
	 * @param  string $context View or edit context.
282
	 * @return float
283
	 */
284
	public function get_price( $context = 'view' ) {
285
        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...
286
	}
287
	
288
	/**
289
	 * Get the inital 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_initial_price( $context = 'view' ) {
296
297
		$price = (float) $this->get_price( $context );
298
299
		if ( $this->has_free_trial() ) {
300
			$price = 0;
301
		}
302
303
        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...
304
    }
305
306
    /**
307
	 * Returns a formated price.
308
	 *
309
	 * @since 1.0.19
310
	 * @param  string $context View or edit context.
311
	 * @return string
312
	 */
313
    public function get_the_price() {
314
        return wpinv_price( wpinv_format_amount( $this->get_price() ) );
315
	}
316
317
	/**
318
	 * Returns the formated initial price.
319
	 *
320
	 * @since 1.0.19
321
	 * @param  string $context View or edit context.
322
	 * @return string
323
	 */
324
    public function get_the_initial_price() {
325
        return wpinv_price( wpinv_format_amount( $this->get_initial_price() ) );
326
    }
327
328
    /**
329
	 * Get the VAT rule of the item.
330
	 *
331
	 * @since 1.0.19
332
	 * @param  string $context View or edit context.
333
	 * @return string
334
	 */
335
	public function get_vat_rule( $context = 'view' ) {
336
        return $this->get_prop( 'vat_rule', $context );
337
    }
338
339
    /**
340
	 * Get the VAT class 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_class( $context = 'view' ) {
347
        return $this->get_prop( 'vat_class', $context );
348
    }
349
350
    /**
351
	 * Get the type 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_type( $context = 'view' ) {
358
        return $this->get_prop( 'type', $context );
359
    }
360
361
    /**
362
	 * Get the custom id 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_custom_id( $context = 'view' ) {
369
        return $this->get_prop( 'custom_id', $context );
370
    }
371
372
    /**
373
	 * Get the custom name 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_name( $context = 'view' ) {
380
        return $this->get_prop( 'custom_name', $context );
381
    }
382
383
    /**
384
	 * Get the custom singular 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_singular_name( $context = 'view' ) {
391
        return $this->get_prop( 'custom_singular_name', $context );
392
    }
393
394
    /**
395
	 * Checks if an item is editable..
396
	 *
397
	 * @since 1.0.19
398
	 * @param  string $context View or edit context.
399
	 * @return int
400
	 */
401
	public function get_is_editable( $context = 'view' ) {
402
        return (int) $this->get_prop( 'is_editable', $context );
403
    }
404
405
    /**
406
	 * Alias of self::get_is_editable().
407
	 *
408
	 * @since 1.0.19
409
	 * @param  string $context View or edit context.
410
	 * @return int
411
	 */
412
	public function get_editable( $context = 'view' ) {
413
		return $this->get_is_editable( $context );
414
    }
415
416
    /**
417
	 * Checks if dynamic pricing is enabled.
418
	 *
419
	 * @since 1.0.19
420
	 * @param  string $context View or edit context.
421
	 * @return int
422
	 */
423
	public function get_is_dynamic_pricing( $context = 'view' ) {
424
        return (int) $this->get_prop( 'is_dynamic_pricing', $context );
425
    }
426
427
    /**
428
	 * Returns the minimum price if dynamic pricing is enabled.
429
	 *
430
	 * @since 1.0.19
431
	 * @param  string $context View or edit context.
432
	 * @return float
433
	 */
434
	public function get_minimum_price( $context = 'view' ) {
435
        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...
436
    }
437
438
    /**
439
	 * Checks if this is a recurring item.
440
	 *
441
	 * @since 1.0.19
442
	 * @param  string $context View or edit context.
443
	 * @return int
444
	 */
445
	public function get_is_recurring( $context = 'view' ) {
446
        return (int) $this->get_prop( 'is_recurring', $context );
447
	}
448
	
449
	/**
450
	 * Get the recurring price of the item.
451
	 *
452
	 * @since 1.0.19
453
	 * @param  string $context View or edit context.
454
	 * @return float
455
	 */
456
	public function get_recurring_price( $context = 'view' ) {
457
		$price = $this->get_price( $context );
458
        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...
459
	}
460
461
	/**
462
	 * Get the first renewal date (in timestamps) of the item.
463
	 *
464
	 * @since 1.0.19
465
	 * @return int
466
	 */
467
	public function get_first_renewal_date() {
468
469
		$periods = array(
470
			'D' => 'days',
471
			'W' => 'weeks',
472
			'M' => 'months',
473
			'Y' => 'years',
474
		);
475
476
		$period   = $this->get_recurring_period();
477
		$interval = $this->get_recurring_interval();
478
479
		if ( $this->has_free_trial() ) {
480
			$period   = $this->get_trial_period();
481
			$interval = $this->get_trial_interval();
482
		}
483
484
		$period       = $periods[ $period ];
485
		$interval     = empty( $interval ) ? 1 : $interval;
486
		$next_renewal = strtotime( "+$interval $period", current_time( 'timestamp' ) );
487
        return apply_filters( 'wpinv_get_first_renewal_date', $next_renewal, $this );
488
    }
489
490
    /**
491
	 * Get the recurring period.
492
	 *
493
	 * @since 1.0.19
494
	 * @param  bool $full Return abbreviation or in full.
495
	 * @return string
496
	 */
497
	public function get_recurring_period( $full = false ) {
498
        $period = $this->get_prop( 'recurring_period', 'view' );
499
500
        if ( $full && ! is_bool( $full ) ) {
0 ignored issues
show
introduced by
The condition is_bool($full) is always true.
Loading history...
501
            $full = false;
502
        }
503
504
        return getpaid_sanitize_recurring_period( $period, $full );
505
    }
506
507
    /**
508
	 * Get the recurring interval.
509
	 *
510
	 * @since 1.0.19
511
	 * @param  string $context View or edit context.
512
	 * @return int
513
	 */
514
	public function get_recurring_interval( $context = 'view' ) {
515
		$interval = absint( $this->get_prop( 'recurring_interval', $context ) );
516
517
		if ( $interval < 1 ) {
518
			$interval = 1;
519
		}
520
521
        return $interval;
522
    }
523
524
    /**
525
	 * Get the recurring limit.
526
	 *
527
	 * @since 1.0.19
528
	 * @param  string $context View or edit context.
529
	 * @return int
530
	 */
531
	public function get_recurring_limit( $context = 'view' ) {
532
        return (int) $this->get_prop( 'recurring_limit', $context );
533
    }
534
535
    /**
536
	 * Checks if we have a free trial.
537
	 *
538
	 * @since 1.0.19
539
	 * @param  string $context View or edit context.
540
	 * @return int
541
	 */
542
	public function get_is_free_trial( $context = 'view' ) {
543
        return (int) $this->get_prop( 'is_free_trial', $context );
544
    }
545
546
    /**
547
	 * Alias for self::get_is_free_trial().
548
	 *
549
	 * @since 1.0.19
550
	 * @param  string $context View or edit context.
551
	 * @return int
552
	 */
553
	public function get_free_trial( $context = 'view' ) {
554
        return $this->get_is_free_trial( $context );
555
    }
556
557
    /**
558
	 * Get the trial period.
559
	 *
560
	 * @since 1.0.19
561
	 * @param  bool $full Return abbreviation or in full.
562
	 * @return string
563
	 */
564
	public function get_trial_period( $full = false ) {
565
        $period = $this->get_prop( 'trial_period', 'view' );
566
567
        if ( $full && ! is_bool( $full ) ) {
0 ignored issues
show
introduced by
The condition is_bool($full) is always true.
Loading history...
568
            $full = false;
569
        }
570
571
        return getpaid_sanitize_recurring_period( $period, $full );
572
    }
573
574
    /**
575
	 * Get the trial interval.
576
	 *
577
	 * @since 1.0.19
578
	 * @param  string $context View or edit context.
579
	 * @return int
580
	 */
581
	public function get_trial_interval( $context = 'view' ) {
582
        return (int) $this->get_prop( 'trial_interval', $context );
583
	}
584
	
585
	/**
586
	 * Get the item's edit url.
587
	 *
588
	 * @since 1.0.19
589
	 * @return string
590
	 */
591
	public function get_edit_url() {
592
        return get_edit_post_link( $this->get_id() );
593
	}
594
595
	/**
596
	 * Given an item's name/custom id, it returns its id.
597
	 *
598
	 *
599
	 * @static
600
	 * @param string $value The item name or custom id.
601
	 * @param string $field Either name or custom_id.
602
	 * @param string $type in case you need to search for a given type.
603
	 * @since 1.0.15
604
	 * @return int
605
	 */
606
	public static function get_item_id_by_field( $value, $field = 'custom_id', $type = '' ) {
607
608
		// Trim the value.
609
		$value = trim( $value );
610
611
		if ( empty( $value ) ) {
612
			return 0;
613
		}
614
615
        // Valid fields.
616
        $fields = array( 'custom_id', 'name', 'slug' );
617
618
		// Ensure a field has been passed.
619
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
620
			return 0;
621
		}
622
623
		if ( $field == 'name' ) {
624
			$field = 'slug';
625
		} 
626
627
		// Maybe retrieve from the cache.
628
		$item_id = wp_cache_get( $value, "getpaid_{$type}_item_{$field}s_to_item_ids" );
629
		if ( ! empty( $item_id ) ) {
630
			return $item_id;
631
		}
632
633
		// Fetch from the db.
634
		if ( $field =='slug' ) {
635
			$items = get_posts(
636
				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 2807
  7. GetPaid_Data::set_prop() is called
    in includes/class-wpinv-invoice.php on line 2808
  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 606
  21. Data is passed through trim(), and trim($value) is assigned to $value
    in includes/class-wpinv-item.php on line 609

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...
637
					'post_type'      => 'wpi_item',
638
					'name'           => $value,
639
					'posts_per_page' => 1,
640
					'post_status'    => 'any',
641
				)
642
			);
643
		}
644
645
		if ( $field =='custom_id' ) {
646
			$items = get_posts(
647
				array(
648
					'post_type'      => 'wpi_item',
649
					'posts_per_page' => 1,
650
					'post_status'    => 'any',
651
					'meta_query'     => array(
652
						array(
653
							'key'   => '_wpinv_type',
654
                			'value' => $type,
655
						),
656
						array(
657
							'key'   => '_wpinv_custom_id',
658
                			'value' => $type,
659
						)
660
					)
661
				)
662
			);
663
		}
664
665
		if ( empty( $items ) ) {
666
			return 0;
667
		}
668
669
		// Update the cache with our data
670
		wp_cache_set( $value, $items[0]->ID, "getpaid_{$type}_item_{$field}s_to_item_ids" );
671
672
		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...
673
    }
674
675
    /**
676
     * Margic method for retrieving a property.
677
     */
678
    public function __get( $key ) {
679
680
        // Check if we have a helper method for that.
681
        if ( method_exists( $this, 'get_' . $key ) ) {
682
            return call_user_func( array( $this, 'get_' . $key ) );
683
        }
684
685
        // Check if the key is in the associated $post object.
686
        if ( ! empty( $this->post ) && isset( $this->post->$key ) ) {
687
            return $this->post->$key;
688
        }
689
690
        return $this->get_prop( $key );
691
692
    }
693
694
    /*
695
	|--------------------------------------------------------------------------
696
	| Setters
697
	|--------------------------------------------------------------------------
698
	|
699
	| Functions for setting item data. These should not update anything in the
700
	| database itself and should only change what is stored in the class
701
	| object.
702
    */
703
704
    /**
705
	 * Set parent order ID.
706
	 *
707
	 * @since 1.0.19
708
	 */
709
	public function set_parent_id( $value ) {
710
		if ( $value && ( $value === $this->get_id() || ! get_post( $value ) ) ) {
711
			return;
712
		}
713
		$this->set_prop( 'parent_id', absint( $value ) );
714
	}
715
716
    /**
717
	 * Sets item status.
718
	 *
719
	 * @since 1.0.19
720
	 * @param  string $status New status.
721
	 * @return array details of change.
722
	 */
723
	public function set_status( $status ) {
724
        $old_status = $this->get_status();
725
726
        $this->set_prop( 'status', $status );
727
728
		return array(
729
			'from' => $old_status,
730
			'to'   => $status,
731
		);
732
    }
733
734
    /**
735
	 * Set plugin version when the item was created.
736
	 *
737
	 * @since 1.0.19
738
	 */
739
	public function set_version( $value ) {
740
		$this->set_prop( 'version', $value );
741
    }
742
743
    /**
744
	 * Set date when the item was created.
745
	 *
746
	 * @since 1.0.19
747
	 * @param string $value Value to set.
748
     * @return bool Whether or not the date was set.
749
	 */
750
	public function set_date_created( $value ) {
751
        $date = strtotime( $value );
752
753
        if ( $date ) {
754
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
755
            return true;
756
        }
757
758
        return false;
759
760
    }
761
762
    /**
763
	 * Set date when the item was last modified.
764
	 *
765
	 * @since 1.0.19
766
	 * @param string $value Value to set.
767
     * @return bool Whether or not the date was set.
768
	 */
769
	public function set_date_modified( $value ) {
770
        $date = strtotime( $value );
771
772
        if ( $date ) {
773
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
774
            return true;
775
        }
776
777
        return false;
778
779
    }
780
781
    /**
782
	 * Set the item name.
783
	 *
784
	 * @since 1.0.19
785
	 * @param  string $value New name.
786
	 */
787
	public function set_name( $value ) {
788
        $name = sanitize_text_field( $value );
789
		$this->set_prop( 'name', $name );
790
    }
791
792
    /**
793
	 * Alias of self::set_name().
794
	 *
795
	 * @since 1.0.19
796
	 * @param  string $value New name.
797
	 */
798
	public function set_title( $value ) {
799
		$this->set_name( $value );
800
    }
801
802
    /**
803
	 * Set the item description.
804
	 *
805
	 * @since 1.0.19
806
	 * @param  string $value New description.
807
	 */
808
	public function set_description( $value ) {
809
        $description = wp_kses_post( $value );
810
		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...
811
    }
812
813
    /**
814
	 * Alias of self::set_description().
815
	 *
816
	 * @since 1.0.19
817
	 * @param  string $value New description.
818
	 */
819
	public function set_excerpt( $value ) {
820
		$this->set_description( $value );
821
    }
822
823
    /**
824
	 * Alias of self::set_description().
825
	 *
826
	 * @since 1.0.19
827
	 * @param  string $value New description.
828
	 */
829
	public function set_summary( $value ) {
830
		$this->set_description( $value );
831
    }
832
833
    /**
834
	 * Set the owner of the item.
835
	 *
836
	 * @since 1.0.19
837
	 * @param  int $value New author.
838
	 */
839
	public function set_author( $value ) {
840
		$this->set_prop( 'author', (int) $value );
841
    }
842
843
    /**
844
	 * Set the price of the item.
845
	 *
846
	 * @since 1.0.19
847
	 * @param  float $value New price.
848
	 */
849
	public function set_price( $value ) {
850
        $this->set_prop( 'price', (float) wpinv_sanitize_amount( $value ) );
851
    }
852
853
    /**
854
	 * Set the VAT rule of the item.
855
	 *
856
	 * @since 1.0.19
857
	 * @param  string $value new rule.
858
	 */
859
	public function set_vat_rule( $value ) {
860
        $this->set_prop( 'vat_rule', $value );
861
    }
862
863
    /**
864
	 * Set the VAT class of the item.
865
	 *
866
	 * @since 1.0.19
867
	 * @param  string $value new class.
868
	 */
869
	public function set_vat_class( $value ) {
870
        $this->set_prop( 'vat_class', $value );
871
    }
872
873
    /**
874
	 * Set the type of the item.
875
	 *
876
	 * @since 1.0.19
877
	 * @param  string $value new item type.
878
	 * @return string
879
	 */
880
	public function set_type( $value ) {
881
882
        if ( empty( $value ) ) {
883
            $value = 'custom';
884
        }
885
886
        $this->set_prop( 'type', $value );
887
    }
888
889
    /**
890
	 * Set the custom id of the item.
891
	 *
892
	 * @since 1.0.19
893
	 * @param  string $value new custom id.
894
	 */
895
	public function set_custom_id( $value ) {
896
        $this->set_prop( 'custom_id', $value );
897
    }
898
899
    /**
900
	 * Set the custom name of the item.
901
	 *
902
	 * @since 1.0.19
903
	 * @param  string $value new custom name.
904
	 */
905
	public function set_custom_name( $value ) {
906
        $this->set_prop( 'custom_name', $value );
907
    }
908
909
    /**
910
	 * Set the custom singular name of the item.
911
	 *
912
	 * @since 1.0.19
913
	 * @param  string $value new custom singular name.
914
	 */
915
	public function set_custom_singular_name( $value ) {
916
        $this->set_prop( 'custom_singular_name', $value );
917
    }
918
919
    /**
920
	 * Sets if an item is editable..
921
	 *
922
	 * @since 1.0.19
923
	 * @param  int|bool $value whether or not the item is editable.
924
	 */
925
	public function set_is_editable( $value ) {
926
		if ( is_numeric( $value ) ) {
927
			$this->set_prop( 'is_editable', (int) $value );
928
		}
929
    }
930
931
    /**
932
	 * Sets if dynamic pricing is enabled.
933
	 *
934
	 * @since 1.0.19
935
	 * @param  int|bool $value whether or not dynamic pricing is allowed.
936
	 */
937
	public function set_is_dynamic_pricing( $value ) {
938
        $this->set_prop( 'is_dynamic_pricing', (int) $value );
939
    }
940
941
    /**
942
	 * Sets the minimum price if dynamic pricing is enabled.
943
	 *
944
	 * @since 1.0.19
945
	 * @param  float $value minimum price.
946
	 */
947
	public function set_minimum_price( $value ) {
948
        $this->set_prop( 'minimum_price',  (float) wpinv_sanitize_amount( $value ) );
949
    }
950
951
    /**
952
	 * Sets if this is a recurring item.
953
	 *
954
	 * @since 1.0.19
955
	 * @param  int|bool $value whether or not dynamic pricing is allowed.
956
	 */
957
	public function set_is_recurring( $value ) {
958
        $this->set_prop( 'is_recurring', (int) $value );
959
    }
960
961
    /**
962
	 * Set the recurring period.
963
	 *
964
	 * @since 1.0.19
965
	 * @param  string $value new period.
966
	 */
967
	public function set_recurring_period( $value ) {
968
        $this->set_prop( 'recurring_period', $value );
969
    }
970
971
    /**
972
	 * Set the recurring interval.
973
	 *
974
	 * @since 1.0.19
975
	 * @param  int $value recurring interval.
976
	 */
977
	public function set_recurring_interval( $value ) {
978
        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...
979
    }
980
981
    /**
982
	 * Get the recurring limit.
983
	 * @since 1.0.19
984
	 * @param  int $value The recurring limit.
985
	 * @return int
986
	 */
987
	public function set_recurring_limit( $value ) {
988
        $this->set_prop( 'recurring_limit', (int) $value );
989
    }
990
991
    /**
992
	 * Checks if we have a free trial.
993
	 *
994
	 * @since 1.0.19
995
	 * @param  int|bool $value whether or not it has a free trial.
996
	 */
997
	public function set_is_free_trial( $value ) {
998
        $this->set_prop( 'is_free_trial', (int) $value );
999
    }
1000
1001
    /**
1002
	 * Set the trial period.
1003
	 *
1004
	 * @since 1.0.19
1005
	 * @param  string $value trial period.
1006
	 */
1007
	public function set_trial_period( $value ) {
1008
        $this->set_prop( 'trial_period', $value );
1009
    }
1010
1011
    /**
1012
	 * Set the trial interval.
1013
	 *
1014
	 * @since 1.0.19
1015
	 * @param  int $value trial interval.
1016
	 */
1017
	public function set_trial_interval( $value ) {
1018
        $this->set_prop( 'trial_interval', $value );
1019
    }
1020
1021
    /**
1022
     * Create an item. For backwards compatibilty.
1023
     * 
1024
     * @deprecated
1025
	 * @return int item id
1026
     */
1027
    public function create( $data = array() ) {
1028
1029
		// Set the properties.
1030
		if ( is_array( $data ) ) {
1031
			$this->set_props( $data );
1032
		}
1033
1034
		// Save the item.
1035
		return $this->save();
1036
1037
    }
1038
1039
    /**
1040
     * Updates an item. For backwards compatibilty.
1041
     * 
1042
     * @deprecated
1043
	 * @return int item id
1044
     */
1045
    public function update( $data = array() ) {
1046
        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

1046
        return /** @scrutinizer ignore-deprecated */ $this->create( $data );
Loading history...
1047
    }
1048
1049
    /*
1050
	|--------------------------------------------------------------------------
1051
	| Conditionals
1052
	|--------------------------------------------------------------------------
1053
	|
1054
	| Checks if a condition is true or false.
1055
	|
1056
	*/
1057
1058
    /**
1059
	 * Checks whether the item has enabled dynamic pricing.
1060
	 *
1061
	 * @since 1.0.19
1062
	 * @return bool
1063
	 */
1064
	public function user_can_set_their_price() {
1065
        return (bool) $this->get_is_dynamic_pricing();
1066
	}
1067
	
1068
	/**
1069
	 * Checks whether the item is recurring.
1070
	 *
1071
	 * @since 1.0.19
1072
	 * @return bool
1073
	 */
1074
	public function is_recurring() {
1075
        return (bool) $this->get_is_recurring();
1076
    }
1077
1078
    /**
1079
	 * Checks whether the item has a free trial.
1080
	 *
1081
	 * @since 1.0.19
1082
	 * @return bool
1083
	 */
1084
    public function has_free_trial() {
1085
        $has_trial = $this->is_recurring() && (bool) $this->get_free_trial() ? true : false;
1086
        return (bool) apply_filters( 'wpinv_item_has_free_trial', $has_trial, $this->ID, $this );
1087
    }
1088
1089
    /**
1090
	 * Checks whether the item is free.
1091
	 *
1092
	 * @since 1.0.19
1093
	 * @return bool
1094
	 */
1095
    public function is_free() {
1096
        $is_free   = $this->get_price() == 0;
1097
        return (bool) apply_filters( 'wpinv_is_free_item', $is_free, $this->ID, $this );
1098
    }
1099
1100
    /**
1101
	 * Checks the item status against a passed in status.
1102
	 *
1103
	 * @param array|string $status Status to check.
1104
	 * @return bool
1105
	 */
1106
	public function has_status( $status ) {
1107
		$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...
1108
		return (bool) apply_filters( 'getpaid_item_has_status', $has_status, $this, $status );
1109
    }
1110
1111
    /**
1112
	 * Checks the item type against a passed in types.
1113
	 *
1114
	 * @param array|string $type Type to check.
1115
	 * @return bool
1116
	 */
1117
	public function is_type( $type ) {
1118
		$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...
1119
		return (bool) apply_filters( 'getpaid_item_is_type', $is_type, $this, $type );
1120
	}
1121
1122
    /**
1123
	 * Checks whether the item is editable.
1124
	 *
1125
	 * @since 1.0.19
1126
	 * @return bool
1127
	 */
1128
    public function is_editable() {
1129
        $is_editable = $this->get_is_editable();
1130
        return (bool) apply_filters( 'wpinv_item_is_editable', $is_editable, $this->ID, $this );
1131
	}
1132
1133
	/**
1134
	 * Returns an array of cart fees.
1135
	 */
1136
	public function get_fees( $type = 'fee', $item_id = 0 ) {
1137
        global $wpi_session;
1138
        
1139
        $fees = $wpi_session->get( 'wpi_cart_fees' );
1140
1141
        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

1141
        if ( ! /** @scrutinizer ignore-deprecated */ wpinv_get_cart_contents() ) {
Loading history...
1142
            // We can only get item type fees when the cart is empty
1143
            $type = 'custom';
1144
        }
1145
1146
        if ( ! empty( $fees ) && ! empty( $type ) && 'all' !== $type ) {
1147
            foreach( $fees as $key => $fee ) {
1148
                if( ! empty( $fee['type'] ) && $type != $fee['type'] ) {
1149
                    unset( $fees[ $key ] );
1150
                }
1151
            }
1152
        }
1153
1154
        if ( ! empty( $fees ) && ! empty( $item_id ) ) {
1155
            // Remove fees that don't belong to the specified Item
1156
            foreach ( $fees as $key => $fee ) {
1157
                if ( (int) $item_id !== (int)$fee['custom_id'] ) {
1158
                    unset( $fees[ $key ] );
1159
                }
1160
            }
1161
        }
1162
1163
        if ( ! empty( $fees ) ) {
1164
            // Remove fees that belong to a specific item but are not in the cart
1165
            foreach( $fees as $key => $fee ) {
1166
                if( empty( $fee['custom_id'] ) ) {
1167
                    continue;
1168
                }
1169
1170
                if ( !wpinv_item_in_cart( $fee['custom_id'] ) ) {
1171
                    unset( $fees[ $key ] );
1172
                }
1173
            }
1174
        }
1175
1176
        return ! empty( $fees ) ? $fees : array();
1177
    }
1178
1179
    /**
1180
	 * Checks whether the item is purchasable.
1181
	 *
1182
	 * @since 1.0.19
1183
	 * @return bool
1184
	 */
1185
    public function can_purchase() {
1186
        $can_purchase = null !== $this->get_id();
1187
1188
        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...
1189
            $can_purchase = false;
1190
        }
1191
1192
        return (bool) apply_filters( 'wpinv_can_purchase_item', $can_purchase, $this );
1193
    }
1194
1195
    /**
1196
	 * Checks whether the item supports dynamic pricing.
1197
	 *
1198
	 * @since 1.0.19
1199
	 * @return bool
1200
	 */
1201
    public function supports_dynamic_pricing() {
1202
        return (bool) apply_filters( 'wpinv_item_supports_dynamic_pricing', true, $this );
1203
    }
1204
}
1205