Passed
Push — master ( 5aee45...200593 )
by Stiofan
04:14
created

GetPaid_Payment_Form::sanitize_array_values()   B

Complexity

Conditions 9
Paths 2

Size

Total Lines 37
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 14
nc 2
nop 1
dl 0
loc 37
rs 8.0555
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Payment form class
8
 *
9
 */
10
class GetPaid_Payment_Form extends GetPaid_Data {
11
12
    /**
13
	 * Which data store to load.
14
	 *
15
	 * @var string
16
	 */
17
    protected $data_store_name = 'payment_form';
18
19
    /**
20
	 * This is the name of this object type.
21
	 *
22
	 * @var string
23
	 */
24
	protected $object_type = 'payment_form';
25
26
    /**
27
	 * Form Data array. This is the core form data exposed in APIs.
28
	 *
29
	 * @since 1.0.19
30
	 * @var array
31
	 */
32
	protected $data = array(
33
		'status'               => 'draft',
34
		'version'              => '',
35
		'date_created'         => null,
36
        'date_modified'        => null,
37
        'name'                 => '',
38
        'author'               => 1,
39
        'elements'             => null,
40
		'items'                => null,
41
		'earned'               => 0,
42
		'refunded'             => 0,
43
		'cancelled'            => 0,
44
		'failed'               => 0,
45
	);
46
47
    /**
48
	 * Stores meta in cache for future reads.
49
	 *
50
	 * A group must be set to to enable caching.
51
	 *
52
	 * @var string
53
	 */
54
	protected $cache_group = 'getpaid_forms';
55
56
	/**
57
	 * Stores a reference to the invoice if the form is for an invoice..
58
	 *
59
	 * @var WPInv_Invoice
60
	 */
61
	public $invoice = 0;
62
63
    /**
64
     * Stores a reference to the original WP_Post object
65
     *
66
     * @var WP_Post
67
     */
68
    protected $post = null;
69
70
    /**
71
	 * Get the form if ID is passed, otherwise the form is new and empty.
72
	 *
73
	 * @param  int|object|GetPaid_Payment_Form|WP_Post $form Form to read.
74
	 */
75
	public function __construct( $form = 0 ) {
76
		parent::__construct( $form );
77
78
		if ( is_numeric( $form ) && $form > 0 ) {
79
			$this->set_id( $form );
80
		} elseif ( $form instanceof self ) {
81
82
			$this->set_id( $form->get_id() );
83
			$this->invoice = $form->invoice;
84
85
		} elseif ( ! empty( $form->ID ) ) {
86
			$this->set_id( $form->ID );
87
		} else {
88
			$this->set_object_read( true );
89
		}
90
91
        // Load the datastore.
92
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
93
94
		if ( $this->get_id() > 0 ) {
95
            $this->post = get_post( $this->get_id() );
0 ignored issues
show
Documentation Bug introduced by
It seems like get_post($this->get_id()) can also be of type array. However, the property $post is declared as type WP_Post. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
96
			$this->data_store->read( $this );
97
        }
98
99
	}
100
101
    /*
102
	|--------------------------------------------------------------------------
103
	| CRUD methods
104
	|--------------------------------------------------------------------------
105
	|
106
	| Methods which create, read, update and delete items from the database.
107
	|
108
    */
109
110
    /*
111
	|--------------------------------------------------------------------------
112
	| Getters
113
	|--------------------------------------------------------------------------
114
    */
115
116
    /**
117
	 * Get plugin version when the form was created.
118
	 *
119
	 * @since 1.0.19
120
	 * @param  string $context View or edit context.
121
	 * @return string
122
	 */
123
	public function get_version( $context = 'view' ) {
124
		return $this->get_prop( 'version', $context );
125
    }
126
127
    /**
128
	 * Get date when the form was created.
129
	 *
130
	 * @since 1.0.19
131
	 * @param  string $context View or edit context.
132
	 * @return string
133
	 */
134
	public function get_date_created( $context = 'view' ) {
135
		return $this->get_prop( 'date_created', $context );
136
    }
137
138
    /**
139
	 * Get GMT date when the form was created.
140
	 *
141
	 * @since 1.0.19
142
	 * @param  string $context View or edit context.
143
	 * @return string
144
	 */
145
	public function get_date_created_gmt( $context = 'view' ) {
146
        $date = $this->get_date_created( $context );
147
148
        if ( $date ) {
149
            $date = get_gmt_from_date( $date );
150
        }
151
		return $date;
152
    }
153
154
    /**
155
	 * Get date when the form was last modified.
156
	 *
157
	 * @since 1.0.19
158
	 * @param  string $context View or edit context.
159
	 * @return string
160
	 */
161
	public function get_date_modified( $context = 'view' ) {
162
		return $this->get_prop( 'date_modified', $context );
163
    }
164
165
    /**
166
	 * Get GMT date when the form was last modified.
167
	 *
168
	 * @since 1.0.19
169
	 * @param  string $context View or edit context.
170
	 * @return string
171
	 */
172
	public function get_date_modified_gmt( $context = 'view' ) {
173
        $date = $this->get_date_modified( $context );
174
175
        if ( $date ) {
176
            $date = get_gmt_from_date( $date );
177
        }
178
		return $date;
179
    }
180
181
    /**
182
	 * Get the form name.
183
	 *
184
	 * @since 1.0.19
185
	 * @param  string $context View or edit context.
186
	 * @return string
187
	 */
188
	public function get_name( $context = 'view' ) {
189
		return $this->get_prop( 'name', $context );
190
    }
191
192
    /**
193
	 * Alias of self::get_name().
194
	 *
195
	 * @since 1.0.19
196
	 * @param  string $context View or edit context.
197
	 * @return string
198
	 */
199
	public function get_title( $context = 'view' ) {
200
		return $this->get_name( $context );
201
	}
202
203
    /**
204
	 * Get the owner of the form.
205
	 *
206
	 * @since 1.0.19
207
	 * @param  string $context View or edit context.
208
	 * @return int
209
	 */
210
	public function get_author( $context = 'view' ) {
211
		return (int) $this->get_prop( 'author', $context );
212
    }
213
214
    /**
215
	 * Get the elements that make up the form.
216
	 *
217
	 * @since 1.0.19
218
	 * @param  string $context View or edit context.
219
	 * @return array
220
	 */
221
	public function get_elements( $context = 'view' ) {
222
		$elements = $this->get_prop( 'elements', $context );
223
224
		if ( empty( $elements ) || ! is_array( $elements ) ) {
225
            return wpinv_get_data( 'sample-payment-form' );
226
		}
227
228
		// Ensure that all required elements exist.
229
		$_elements = array();
230
		foreach ( $elements as $element ) {
231
232
			if ( $element['type'] == 'pay_button' && ! $this->has_element_type( 'gateway_select' ) ) {
233
234
				$_elements[] = array(
235
					'text'        => __( 'Select Payment Method', 'invoicing' ),
236
					'id'          => 'gtscicd',
237
					'name'        => 'gtscicd',
238
					'type'        => 'gateway_select',
239
					'premade'     => true
240
			
241
				);
242
243
			}
244
245
			$_elements[] = $element;
246
247
		}
248
249
        return $_elements;
250
	}
251
252
	/**
253
	 * Get the items sold via the form.
254
	 *
255
	 * @since 1.0.19
256
	 * @param  string $context View or edit context.
257
	 * @param  string $return objects or arrays.
258
	 * @return GetPaid_Form_Item[]
259
	 */
260
	public function get_items( $context = 'view', $return = 'objects' ) {
261
		$items = $this->get_prop( 'items', $context );
262
263
		if ( empty( $items ) || ! is_array( $items ) ) {
264
            $items = wpinv_get_data( 'sample-payment-form-items' );
265
		}
266
267
		// Convert the items.
268
		$prepared = array();
269
270
		foreach ( $items as $key => $value ) {
271
272
			// Form items.
273
			if ( $value instanceof GetPaid_Form_Item ) {
274
275
				if ( $value->can_purchase() ) {
276
					$prepared[] = $value;
277
				}
278
279
				continue;
280
281
			}
282
283
			// $item_id => $quantity (buy buttons)
284
			if ( is_numeric( $key ) && is_numeric( $value ) ) {
285
				$item = new GetPaid_Form_Item( $key );
286
287
				if ( $item->can_purchase() ) {
288
289
					$value = (float) $value;
290
					$item->set_quantity( $value );
291
					if ( 0 == $value ) {
292
						$item->set_quantity( 1 );
293
						$item->set_allow_quantities( true );
294
					}
295
296
					$prepared[] = $item;
297
				}
298
299
				continue;
300
			}
301
302
			// Items saved via payment forms editor.
303
			if ( is_array( $value ) && isset( $value['id'] ) ) {
304
305
				$item = new GetPaid_Form_Item( $value['id'] );
306
307
				if ( ! $item->can_purchase() ) {
308
					continue;
309
				}
310
311
				// Sub-total (Cart items).
312
				if ( isset( $value['subtotal'] ) ) {
313
					$item->set_price( $value['subtotal'] );
314
				}
315
316
				if ( isset( $value['quantity'] ) ) {
317
					$item->set_quantity( $value['quantity'] );
318
				}
319
320
				if ( isset( $value['allow_quantities'] ) ) {
321
					$item->set_allow_quantities( $value['allow_quantities'] );
322
				}
323
324
				if ( isset( $value['required'] ) ) {
325
					$item->set_is_required( $value['required'] );
326
				}
327
328
				if ( isset( $value['description'] ) ) {
329
					$item->set_custom_description( $value['description'] );
330
				}
331
332
				$prepared[] = $item;
333
				continue;
334
335
			}
336
337
			// $item_id => array( 'price' => 10 ) (item variations)
338
			if ( is_numeric( $key ) && is_array( $value ) ) {
339
				$item = new GetPaid_Form_Item( $key );
340
341
				if ( isset( $value['price'] ) && $item->user_can_set_their_price() ) {
342
					$item->set_price( $value['price'] );
343
				}
344
345
				if ( $item->can_purchase() ) {
346
					$prepared[] = $item;
347
				}
348
349
				continue;
350
			}
351
352
		}
353
354
		if ( 'objects' == $return && 'view' == $context ) {
355
			return $prepared;
356
		}
357
358
		$items = array();
359
		foreach ( $prepared as $item ) {
360
			$items[] = $item->prepare_data_for_use();
361
		}
362
363
		return $items;
364
	}
365
366
	/**
367
	 * Get a single item belonging to the form.
368
	 *
369
	 * @since 1.0.19
370
	 * @param  int $item_id The item id to return.
371
	 * @return GetPaid_Form_Item|bool
372
	 */
373
	public function get_item( $item_id ) {
374
375
		if ( empty( $item_id ) || ! is_numeric( $item_id ) ) {
376
			return false;
377
		}
378
379
		foreach( $this->get_items() as $item ) {
380
			if ( $item->get_id() == (int) $item_id ) {
381
				return $item;
382
			}
383
		}
384
385
		return false;
386
387
	}
388
389
	/**
390
	 * Gets a single element.
391
	 *
392
	 * @since 1.0.19
393
	 * @param  string $element_type The element type to return.
394
	 * @return array|bool
395
	 */
396
	public function get_element_type( $element_type ) {
397
398
		if ( empty( $element_type ) || ! is_scalar( $element_type ) ) {
399
			return false;
400
		}
401
402
		foreach ( $this->get_prop( 'elements' ) as $element ) {
403
404
			if ( $element['type'] == $element_type ) {
405
				return $element;
406
			}
407
408
		}
409
410
		return false;
411
412
	}
413
414
	/**
415
	 * Get the total amount earned via this form.
416
	 *
417
	 * @since 1.0.19
418
	 * @param  string $context View or edit context.
419
	 * @return float
420
	 */
421
	public function get_earned( $context = 'view' ) {
422
		return $this->get_prop( 'earned', $context );
423
	}
424
425
	/**
426
	 * Get the total amount refunded via this form.
427
	 *
428
	 * @since 1.0.19
429
	 * @param  string $context View or edit context.
430
	 * @return float
431
	 */
432
	public function get_refunded( $context = 'view' ) {
433
		return $this->get_prop( 'refunded', $context );
434
	}
435
436
	/**
437
	 * Get the total amount cancelled via this form.
438
	 *
439
	 * @since 1.0.19
440
	 * @param  string $context View or edit context.
441
	 * @return float
442
	 */
443
	public function get_cancelled( $context = 'view' ) {
444
		return $this->get_prop( 'cancelled', $context );
445
	}
446
447
	/**
448
	 * Get the total amount failed via this form.
449
	 *
450
	 * @since 1.0.19
451
	 * @param  string $context View or edit context.
452
	 * @return float
453
	 */
454
	public function get_failed( $context = 'view' ) {
455
		return $this->get_prop( 'failed', $context );
456
	}
457
458
	/**
459
	 * Get the currency.
460
	 *
461
	 * @since 1.0.19
462
	 * @param  string $context View or edit context.
463
	 * @return string
464
	 */
465
	public function get_currency() {
466
		$currency = empty( $this->invoice ) ? wpinv_get_currency() : $this->invoice->get_currency();
467
		return apply_filters( 'getpaid-payment-form-currency', $currency, $this );
468
	}
469
470
    /*
471
	|--------------------------------------------------------------------------
472
	| Setters
473
	|--------------------------------------------------------------------------
474
	|
475
	| Functions for setting order data. These should not update anything in the
476
	| database itself and should only change what is stored in the class
477
	| object.
478
    */
479
480
    /**
481
	 * Set plugin version when the item was created.
482
	 *
483
	 * @since 1.0.19
484
	 */
485
	public function set_version( $value ) {
486
		$this->set_prop( 'version', $value );
487
    }
488
489
    /**
490
	 * Set date when the item was created.
491
	 *
492
	 * @since 1.0.19
493
	 * @param string $value Value to set.
494
     * @return bool Whether or not the date was set.
495
	 */
496
	public function set_date_created( $value ) {
497
        $date = strtotime( $value );
498
499
        if ( $date ) {
500
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
501
            return true;
502
        }
503
504
        return false;
505
506
    }
507
508
    /**
509
	 * Set date when the item was last modified.
510
	 *
511
	 * @since 1.0.19
512
	 * @param string $value Value to set.
513
     * @return bool Whether or not the date was set.
514
	 */
515
	public function set_date_modified( $value ) {
516
        $date = strtotime( $value );
517
518
        if ( $date ) {
519
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
520
            return true;
521
        }
522
523
        return false;
524
525
    }
526
527
    /**
528
	 * Set the item name.
529
	 *
530
	 * @since 1.0.19
531
	 * @param  string $value New name.
532
	 */
533
	public function set_name( $value ) {
534
		$this->set_prop( 'name', sanitize_text_field( $value ) );
535
    }
536
537
    /**
538
	 * Alias of self::set_name().
539
	 *
540
	 * @since 1.0.19
541
	 * @param  string $value New name.
542
	 */
543
	public function set_title( $value ) {
544
		$this->set_name( $value );
545
    }
546
547
    /**
548
	 * Set the owner of the item.
549
	 *
550
	 * @since 1.0.19
551
	 * @param  int $value New author.
552
	 */
553
	public function set_author( $value ) {
554
		$this->set_prop( 'author', (int) $value );
555
	}
556
557
	/**
558
	 * Set the form elements.
559
	 *
560
	 * @since 1.0.19
561
	 * @sinve 2.3.4 Array values sanitized.
562
	 * @param  array $value Form elements.
563
	 */
564
	public function set_elements( $value ) {
565
		if ( is_array( $value ) ) {
0 ignored issues
show
introduced by
The condition is_array($value) is always true.
Loading history...
566
567
			// sanitize
568
			$value = $this->sanitize_array_values( $value );
569
570
			$this->set_prop( 'elements', $value );
571
		}
572
	}
573
574
	/**
575
	 * Sanitize array values.
576
	 *
577
	 * @param $value
578
	 *
579
	 * @return mixed
580
	 */
581
	public function sanitize_array_values($value){
582
583
		// sanitize
584
		if(!empty($value )){
585
586
			foreach($value as $key => $val_arr){
587
588
				if(is_array($val_arr)){
589
					// check if we have sub array items.
590
					$sub_arr = array();
591
					foreach($val_arr as $key2 => $val2){
592
						if(is_array($val2)){
593
							$sub_arr[$key2] = $this->sanitize_array_values($val2);
594
							unset($val_arr[$key][$key2]);
595
						}
596
					}
597
598
					// we allow some html in description so we sanitize it separately.
599
					$help_text = !empty($val_arr['description']) ? wp_kses_post($val_arr['description']) : '';
600
601
					// sanitize array elements
602
					$value[$key] = array_map( 'sanitize_text_field', $val_arr );
603
604
					// add back the description if set
605
					if(isset($val_arr['description'])){ $value[$key]['description'] = $help_text;}
606
607
					// add back sub array items after its been sanitized.
608
					if ( ! empty( $sub_arr ) ) {
609
						$value[$key] = array_merge($value[$key],$sub_arr);
610
					}
611
				}
612
613
			}
614
615
		}
616
617
		return $value;
618
	}
619
620
	/**
621
	 * Set the form items.
622
	 *
623
	 * @since 1.0.19
624
	 * @param  array $value Form elements.
625
	 */
626
	public function set_items( $value ) {
627
		if ( is_array( $value ) ) {
0 ignored issues
show
introduced by
The condition is_array($value) is always true.
Loading history...
628
			$this->set_prop( 'items', $value );
629
		}
630
	}
631
632
	/**
633
	 * Set the total amount earned via this form.
634
	 *
635
	 * @since 1.0.19
636
	 * @param  float $value Amount earned.
637
	 */
638
	public function set_earned( $value ) {
639
		$value = max( (float) $value, 0 );
640
		$this->set_prop( 'earned', $value );
641
	}
642
643
	/**
644
	 * Set the total amount refunded via this form.
645
	 *
646
	 * @since 1.0.19
647
	 * @param  float $value Amount refunded.
648
	 */
649
	public function set_refunded( $value ) {
650
		$value = max( (float) $value, 0 );
651
		$this->set_prop( 'refunded', $value );
652
	}
653
654
	/**
655
	 * Set the total amount cancelled via this form.
656
	 *
657
	 * @since 1.0.19
658
	 * @param  float $value Amount cancelled.
659
	 */
660
	public function set_cancelled( $value ) {
661
		$value = max( (float) $value, 0 );
662
		$this->set_prop( 'cancelled', $value );
663
	}
664
665
	/**
666
	 * Set the total amount failed via this form.
667
	 *
668
	 * @since 1.0.19
669
	 * @param  float $value Amount cancelled.
670
	 */
671
	public function set_failed( $value ) {
672
		$value = max( (float) $value, 0 );
673
		$this->set_prop( 'failed', $value );
674
	}
675
676
    /**
677
     * Create an item. For backwards compatibilty.
678
     *
679
     * @deprecated
680
	 * @return int item id
681
     */
682
    public function create( $data = array() ) {
683
684
		// Set the properties.
685
		if ( is_array( $data ) ) {
686
			$this->set_props( $data );
687
		}
688
689
		// Save the item.
690
		return $this->save();
691
692
    }
693
694
    /**
695
     * Updates an item. For backwards compatibilty.
696
     *
697
     * @deprecated
698
	 * @return int item id
699
     */
700
    public function update( $data = array() ) {
701
        return $this->create( $data );
0 ignored issues
show
Deprecated Code introduced by
The function GetPaid_Payment_Form::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

701
        return /** @scrutinizer ignore-deprecated */ $this->create( $data );
Loading history...
702
    }
703
704
    /*
705
	|--------------------------------------------------------------------------
706
	| Conditionals
707
	|--------------------------------------------------------------------------
708
	|
709
	| Checks if a condition is true or false.
710
	|
711
	*/
712
713
    /**
714
	 * Checks whether this is the default payment form.
715
	 *
716
	 * @since 1.0.19
717
	 * @return bool
718
	 */
719
    public function is_default() {
720
        $is_default = $this->get_id() == wpinv_get_default_payment_form();
721
        return (bool) apply_filters( 'wpinv_is_default_payment_form', $is_default, $this->get_id(), $this );
722
	}
723
724
    /**
725
	 * Checks whether the form is active.
726
	 *
727
	 * @since 1.0.19
728
	 * @return bool
729
	 */
730
    public function is_active() {
731
        $is_active = 0 !== (int) $this->get_id();
732
733
        if ( $is_active && ! current_user_can( 'edit_post', $this->get_id() ) && $this->get_status() != 'publish' ) {
734
            $is_active = false;
735
        }
736
737
        return (bool) apply_filters( 'wpinv_is_payment_form_active', $is_active, $this );
738
	}
739
740
	/**
741
	 * Checks whether the form has a given item.
742
	 *
743
	 * @since 1.0.19
744
	 * @return bool
745
	 */
746
    public function has_item( $item_id ) {
747
        return false !== $this->get_item( $item_id );
748
	}
749
750
	/**
751
	 * Checks whether the form has a given element.
752
	 *
753
	 * @since 1.0.19
754
	 * @return bool
755
	 */
756
    public function has_element_type( $element_type ) {
757
        return false !== $this->get_element_type( $element_type );
758
	}
759
760
	/**
761
	 * Checks whether this form is recurring or not.
762
	 *
763
	 * @since 1.0.19
764
	 * @return bool
765
	 */
766
    public function is_recurring() {
767
768
		if ( ! empty( $this->invoice ) ) {
769
			return $this->invoice->is_recurring();
770
		}
771
772
		foreach ( $this->get_items() as $item ) {
773
774
			if ( $item->is_recurring() ) {
775
				return true;
776
			}
777
778
		}
779
780
        return false;
781
	}
782
783
	/**
784
	 * Retrieves the form's html.
785
	 *
786
	 * @since 1.0.19
787
	 */
788
    public function get_html( $extra_markup = '' ) {
789
790
		// Return the HTML.
791
		return wpinv_get_template_html(
792
			'payment-forms/form.php',
793
			array(
794
				'form'         => $this,
795
				'extra_markup' => $extra_markup,
796
			)
797
		);
798
799
	}
800
801
	/**
802
	 * Displays the payment form.
803
	 *
804
	 * @since 1.0.19
805
	 */
806
    public function display( $extra_markup = '' ) {
807
		echo $this->get_html( $extra_markup );
808
    }
809
810
}
811