Passed
Push — master ( 6929e7...c24352 )
by Brian
10:18 queued 05:36
created

GetPaid_Payment_Form_Submission::get_company()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 3
nc 3
nop 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Payment form submission class
8
 *
9
 */
10
class GetPaid_Payment_Form_Submission {
11
12
    /**
13
	 * Submission ID
14
	 *
15
	 * @var string
16
	 */
17
	public $id = null;
18
19
	/**
20
	 * Sets the associated payment form.
21
	 *
22
	 * @var GetPaid_Payment_Form
23
	 */
24
    protected $payment_form = null;
25
26
    /**
27
	 * The country for the submission.
28
	 *
29
	 * @var string
30
	 */
31
	public $country = null;
32
33
    /**
34
	 * The state for the submission.
35
	 *
36
	 * @since 1.0.19
37
	 * @var string
38
	 */
39
	public $state = null;
40
41
	/**
42
	 * The invoice associated with the submission.
43
	 *
44
	 * @var WPInv_Invoice
45
	 */
46
	protected $invoice = null;
47
48
	/**
49
	 * The discount associated with the submission.
50
	 *
51
	 * @var WPInv_Discount
52
	 */
53
	protected $discount = null;
54
55
	/**
56
	 * The raw submission data.
57
	 *
58
	 * @var array
59
	 */
60
	protected $data = null;
61
62
	/**
63
	 * Whether this submission contains a recurring item.
64
	 *
65
	 * @var bool
66
	 */
67
	public $has_recurring = false;
68
69
	/**
70
	 * The sub total amount for the submission.
71
	 *
72
	 * @var float
73
	 */
74
	public $subtotal_amount = 0;
75
76
	/**
77
	 * The total discount amount for the submission.
78
	 *
79
	 * @var float
80
	 */
81
	protected $total_discount_amount = 0;
82
83
	/**
84
	 * The total tax amount for the submission.
85
	 *
86
	 * @var float
87
	 */
88
	protected $total_tax_amount = 0;
89
90
	/**
91
	 * The total fees amount for the submission.
92
	 *
93
	 * @var float
94
	 */
95
	protected $total_fees_amount = 0;
96
97
	/**
98
	 * An array of fees for the submission.
99
	 *
100
	 * @var array
101
	 */
102
	protected $fees = array();
103
104
	/**
105
	 * An array of discounts for the submission.
106
	 *
107
	 * @var array
108
	 */
109
	protected $discounts = array();
110
111
	/**
112
	 * An array of taxes for the submission.
113
	 *
114
	 * @var array
115
	 */
116
	protected $taxes = array();
117
118
	/**
119
	 * An array of items for the submission.
120
	 *
121
	 * @var GetPaid_Form_Item[]
122
	 */
123
	protected $items = array();
124
125
	/**
126
	 * The last error.
127
	 *
128
	 * @var string
129
	 */
130
	public $last_error = null;
131
132
	/**
133
	 * Is the discount valid?
134
	 *
135
	 * @var bool
136
	 */
137
	public $is_discount_valid = true;
138
	
139
	/**
140
	 * Checks if we have a digital vat rule.
141
	 *
142
	 * @var bool
143
	 */
144
	public $has_digital = false;
145
	
146
	/**
147
	 * Checks if we require vat.
148
	 *
149
	 * @var bool
150
	 */
151
    public $requires_vat = false;
152
153
    /**
154
	 * Class constructor.
155
	 *
156
	 */
157
	public function __construct() {
158
159
		// Set the state and country to the default state and country.
160
		$this->country = wpinv_default_billing_country();
161
		$this->state = wpinv_get_default_state();
0 ignored issues
show
Documentation Bug introduced by
It seems like wpinv_get_default_state() can also be of type false. However, the property $state is declared as type string. 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...
162
163
		// Do we have an actual submission?
164
		if ( isset( $_POST['getpaid_payment_form_submission'] ) ) {
165
			$this->load_data( $_POST );
166
		}
167
	}
168
169
	/**
170
	 * Loads submission data.
171
	 *
172
	 * @param array $data
173
	 */
174
	public function load_data( $data ) {
175
176
		// Prepare submitted data...
177
		$data = wp_unslash( $data );
178
179
		// Filter the data.
180
		$data = apply_filters( 'getpaid_submission_data', $data, $this );
181
182
		$this->data = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data can also be of type string. However, the property $data is declared as type array. 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...
183
184
		$this->id = md5( wp_json_encode( $data ) );
0 ignored issues
show
Bug introduced by
It seems like wp_json_encode($data) can also be of type false; however, parameter $str of md5() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

184
		$this->id = md5( /** @scrutinizer ignore-type */ wp_json_encode( $data ) );
Loading history...
185
186
		// Every submission needs an active payment form.
187
		if ( empty( $data['form_id'] ) ) {
188
			$this->last_error = __( 'Missing payment form', 'invoicing' );
189
            return;
190
		}
191
192
		// Fetch the payment form.
193
		$form = new GetPaid_Payment_Form( $data['form_id'] );
194
195
		if ( ! $form->is_active() ) {
196
			$this->last_error = __( 'Payment form not active', 'invoicing' );
197
			return;
198
		}
199
200
		// Fetch the payment form.
201
		$this->payment_form = $form;
202
203
		// For existing invoices, make sure that it is valid.
204
        if ( ! empty( $data['invoice_id'] ) ) {
205
            $invoice = wpinv_get_invoice( $data['invoice_id'] );
206
207
            if ( empty( $invoice ) ) {
208
				$this->last_error = __( 'Invalid invoice', 'invoicing' );
209
                return;
210
			}
211
			
212
			if ( $invoice->is_paid() ) {
213
				$this->last_error = __( 'This invoice is already paid for.', 'invoicing' );
214
                return;
215
			}
216
217
			$this->payment_form->set_items( $invoice->get_items() );
218
219
			$this->country = $invoice->get_country();
220
			$this->state = $invoice->get_state();
221
222
		// Default forms do not have items.
223
        } else if ( $form->is_default() && isset( $data['form_items'] ) ) {
224
			$this->payment_form->set_items( $data['form_items'] );
225
		}
226
227
		// User's country.
228
		if ( ! empty( $data['wpinv_country'] ) ) {
229
			$this->country = $data['wpinv_country'];
230
		}
231
232
		// User's state.
233
		if ( ! empty( $data['wpinv_state'] ) ) {
234
			$this->country = $data['wpinv_state'];
235
		}
236
237
		// Handle discounts.
238
		$this->maybe_prepare_discount();
239
240
		// Handle items.
241
		$selected_items = array();
242
		if ( ! empty( $data['getpaid-items'] ) ) {
243
			$selected_items = wpinv_clean( $data['getpaid-items'] );
244
		}
245
246
		foreach ( $this->payment_form->get_items() as $item ) {
247
248
			// Continue if this is an optional item and it has not been selected.
249
			if ( ! $item->is_required() && ! isset( $selected_items[ $item->get_id() ] ) ) {
250
				continue;
251
			}
252
253
			// (maybe) let customers change the quantities and prices.
254
			if ( isset( $selected_items[ $item->get_id() ] ) ) {
255
256
				// Maybe change the quantities.
257
				if ( $item->allows_quantities() && is_numeric( $selected_items[ $item->get_id() ]['quantity'] ) ) {
258
					$item->set_quantity( (int) $selected_items[ $item->get_id() ]['quantity'] );
259
				}
260
261
				// Maybe change the price.
262
				if ( $item->user_can_set_their_price() ) {
263
					$price = (float) wpinv_sanitize_amount( $selected_items[ $item->get_id() ]['price'] );
264
265
					// But don't get lower than the minimum price.
266
					if ( $price < $item->get_minimum_price() ) {
267
						$price = $item->get_minimum_price();
268
					}
269
270
					$item->set_price( $price );
271
272
				}
273
274
			}
275
276
			// Add the item to the form.
277
			$this->add_item( $item );
278
279
		}
280
281
		// (Maybe) validate vat number.
282
		$this->maybe_validate_vat();
283
284
		// Fired when we are done processing a submission.
285
		do_action_ref_array( 'getpaid_process_submission', array( &$this ) );
286
287
		// Remove invalid discount.
288
		$this->maybe_remove_discount();
289
290
	}
291
292
    /**
293
	 * Returns the payment form.
294
	 *
295
	 * @since 1.0.19
296
	 * @return GetPaid_Payment_Form
297
	 */
298
	public function get_payment_form() {
299
		return $this->payment_form;
300
	}
301
302
	/**
303
	 * Returns the associated invoice.
304
	 *
305
	 * @since 1.0.19
306
	 * @return WPInv_Invoice
307
	 */
308
	public function get_invoice() {
309
		return $this->invoice;
310
	}
311
312
	/**
313
	 * Checks whether there is an invoice associated with this submission.
314
	 *
315
	 * @since 1.0.19
316
	 * @return bool
317
	 */
318
	public function has_invoice() {
319
		return ! empty( $this->invoice );
320
	}
321
322
	/**
323
	 * Retrieves the vat number.
324
	 *
325
	 * @since 1.0.19
326
	 * @return string
327
	 */
328
	public function get_vat_number() {
329
330
		// Retrieve from the posted data.
331
		if ( ! empty( $this->data['wpinv_vat_number'] ) ) {
332
			return wpinv_clean( $this->data['wpinv_vat_number'] );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_clean($this...ta['wpinv_vat_number']) also could return the type array which is incompatible with the documented return type string.
Loading history...
333
		}
334
335
		// Retrieve from the invoice.
336
		return $this->has_invoice() ? $this->invoice->get_vat_number() : '';
337
	}
338
339
	/**
340
	 * Retrieves the company.
341
	 *
342
	 * @since 1.0.19
343
	 * @return string
344
	 */
345
	public function get_company() {
346
347
		// Retrieve from the posted data.
348
		if ( ! empty( $this->data['wpinv_company'] ) ) {
349
			return wpinv_clean( $this->data['wpinv_company'] );
0 ignored issues
show
Bug Best Practice introduced by
The expression return wpinv_clean($this->data['wpinv_company']) also could return the type array which is incompatible with the documented return type string.
Loading history...
350
		}
351
352
		// Retrieve from the invoice.
353
		return $this->has_invoice() ? $this->invoice->get_company() : '';
354
	}
355
	
356
	/**
357
	 * Returns the appropriate currency for the submission.
358
	 *
359
	 * @since 1.0.19
360
	 * @return string
361
	 */
362
	public function get_currency() {
363
		if ( $this->has_invoice() ) {
364
			return $this->invoice->get_currency();
365
		}
366
		return wpinv_get_currency();
367
    }
368
369
    /**
370
	 * Returns the raw submission data.
371
	 *
372
	 * @since 1.0.19
373
	 * @return array
374
	 */
375
	public function get_data() {
376
		return $this->data;
377
	}
378
379
	/**
380
	 * Checks if a required field is set.
381
	 *
382
	 * @since 1.0.19
383
	 */
384
	public function is_required_field_set( $field ) {
385
		return empty( $field['required'] ) || ! empty( $this->data[ $field['id'] ] );
386
	}
387
388
	///////// Items //////////////
389
390
	/**
391
	 * Adds an item to the submission.
392
	 *
393
	 * @since 1.0.19
394
	 * @param GetPaid_Form_Item $item
395
	 */
396
	public function add_item( $item ) {
397
398
		// Make sure that it is available for purchase.
399
		if ( ! $item->can_purchase() ) {
400
			return;
401
		}
402
403
		// Do we have a recurring item?
404
		if ( $item->is_recurring() ) {
405
406
			if ( $this->has_recurring ) {
407
				$this->last_error = __( 'You can only buy one recurring item at a time.', 'invoicing' );
408
			}
409
410
			$this->has_recurring = true;
411
412
		}
413
414
		$this->items[ $item->get_id() ] = $item;
415
416
		$this->subtotal_amount += $item->get_sub_total();
417
418
		$this->process_item_discount( $item );
419
420
		$this->process_item_tax( $item );
421
	}
422
423
	/**
424
	 * Retrieves a specific item.
425
	 *
426
	 * @since 1.0.19
427
	 */
428
	public function get_item( $item_id ) {
429
		return isset( $this->items[ $item_id ] ) ? $this->items[ $item_id ] : null;
430
	}
431
432
	/**
433
	 * Returns all items.
434
	 *
435
	 * @since 1.0.19
436
	 * @return GetPaid_Form_Item[]
437
	 */
438
	public function get_items() {
439
		return $this->items;
440
	}
441
442
	///////// TAXES //////////////
443
444
	/**
445
	 * Adds a tax to the submission.
446
	 *
447
	 * @since 1.0.19
448
	 */
449
	public function add_tax( $name, $amount ) {
450
		$amount = (float) wpinv_sanitize_amount( $amount );
451
452
		$this->total_tax_amount += $amount;
453
454
		if ( isset( $this->taxes[ $name ] ) ) {
455
			$this->taxes[ $name ] += $amount;
456
		} else {
457
			$this->taxes[ $name ] = $amount;
458
		}
459
460
	}
461
462
	/**
463
	 * Whether or not we'll use taxes for the submission.
464
	 *
465
	 * @since 1.0.19
466
	 */
467
	public function use_taxes() {
468
469
		$use_taxes = wpinv_use_taxes();
470
471
		if ( $this->has_invoice() && $this->invoice->disable_taxes ) {
0 ignored issues
show
Bug Best Practice introduced by
The property disable_taxes does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
472
			$use_taxes = false;
473
		}
474
475
		return apply_filters( 'getpaid_submission_use_taxes', $use_taxes, $this );
476
477
	}
478
479
	/**
480
	 * Maybe process tax.
481
	 *
482
	 * @since 1.0.19 
483
	 * @param GetPaid_Form_Item $item
484
	 */
485
	public function process_item_tax( $item ) {
486
487
		// Abort early if we're not using taxes.
488
		if ( ! $this->use_taxes() ) {
489
			return;
490
		}
491
492
		$rate  = wpinv_get_tax_rate( $this->country, $this->state, $item->get_id() );
493
		$price = $item->get_sub_total();
494
495
		if ( wpinv_prices_include_tax() ) {
496
			$item_tax = $price - ( $price - $price * $rate * 0.01 );
497
		} else {
498
			$item_tax = $price * $rate * 0.01;
499
		}
500
501
		$this->add_tax( 'Tax', $item_tax );
502
503
	}
504
505
	/**
506
	 * Returns the total tax amount.
507
	 *
508
	 * @since 1.0.19
509
	 */
510
	public function get_total_tax() {
511
		return $this->total_tax_amount;
512
	}
513
514
	/**
515
	 * Retrieves a specific tax.
516
	 *
517
	 * @since 1.0.19
518
	 */
519
	public function get_tax( $name ) {
520
		return isset( $this->taxes[ $name ] ) ? $this->taxes[ $name ] : 0;
521
	}
522
523
	/**
524
	 * Returns all taxes.
525
	 *
526
	 * @since 1.0.19
527
	 */
528
	public function get_taxes() {
529
		return $this->taxes;
530
	}
531
532
	///////// DISCOUNTS //////////////
533
534
	/**
535
	 * Adds a discount to the submission.
536
	 *
537
	 * @since 1.0.19
538
	 */
539
	public function add_discount( $name, $amount ) {
540
		$amount = wpinv_sanitize_amount( $amount );
541
542
		$this->total_discount_amount += $amount;
543
544
		if ( isset( $this->discounts[ $name ] ) ) {
545
			$this->discounts[ $name ] += $amount;
546
		} else {
547
			$this->discounts[ $name ] = $amount;
548
		}
549
550
	}
551
552
	/**
553
	 * Removes a discount from the submission.
554
	 *
555
	 * @since 1.0.19
556
	 */
557
	public function remove_discount( $name ) {
558
559
		if ( isset( $this->discounts[ $name ] ) ) {
560
			$this->total_discount_amount -= $this->discounts[ $name ];
561
			unset( $this->discounts[ $name ] );
562
		}
563
564
	}
565
566
	/**
567
	 * Checks whether there is a discount code associated with this submission.
568
	 *
569
	 * @since 1.0.19
570
	 * @return bool
571
	 */
572
	public function has_discount_code() {
573
		return ! empty( $this->discount );
574
	}
575
576
	/**
577
	 * Returns the discount code.
578
	 *
579
	 * @since 1.0.19
580
	 * @return bool
581
	 */
582
	public function get_discount_code() {
583
		return $this->has_discount_code() ? $this->discount->code : '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->has_discou...is->discount->code : '' also could return the type string which is incompatible with the documented return type boolean.
Loading history...
Bug Best Practice introduced by
The property code does not exist on WPInv_Discount. Since you implemented __get, consider adding a @property annotation.
Loading history...
584
	}
585
586
	/**
587
	 * Prepares an item discount.
588
	 *
589
	 * @since 1.0.19
590
	 */
591
	public function maybe_prepare_discount() {
592
593
		// Do we have a discount?
594
		if ( empty( $this->data['discount'] ) ) {
595
			return;
596
		}
597
598
		// Fetch the discount.
599
		$discount = wpinv_get_discount_obj( $this->data['discount'] );
600
601
		// Ensure it is active.
602
        if ( ! $discount->exists() || ! $discount->is_active() || ! $discount->has_started() || $discount->is_expired() ) {
603
			$this->is_discount_valid = false;
604
			$this->last_error = __( 'Invalid or expired discount code', 'invoicing' );
605
			return;
606
		}
607
608
		// For single use discounts...
609
		if ( $discount->is_single_use ) {
0 ignored issues
show
Bug Best Practice introduced by
The property is_single_use does not exist on WPInv_Discount. Since you implemented __get, consider adding a @property annotation.
Loading history...
610
611
			if ( ! $this->has_billing_email() ) {
612
				$this->is_discount_valid = false;
613
				$this->last_error = __( 'You need to enter your billing email before applying this discount', 'invoicing' );
614
				return;
615
			}
616
617
			if ( ! $discount->is_valid_for_user( $this->get_billing_email() ) ) {
618
				$this->is_discount_valid = false;
619
				$this->last_error = __( 'You have already used this discount', 'invoicing' );
620
				return;
621
			}
622
623
		}
624
625
		// Set the discount.
626
		$this->discount = $discount;
627
628
	}
629
630
	/**
631
	 * Removes an invalid discount code.
632
	 *
633
	 * @since 1.0.19
634
	 */
635
	public function maybe_remove_discount() {
636
637
		// Do we have a discount?
638
		if ( empty( $this->has_discount_code() ) ) {
639
			return;
640
		}
641
642
		// Fetch the discount amount.
643
		$amount = $this->get_discount( 'Discount' );
644
645
		// Abort early if this is a "zero" discount.
646
		if ( empty( $amount ) ) {
647
			return;
648
		}
649
650
		$total = $this->subtotal_amount + $this->get_total_fees() + $this->get_total_tax();
651
652
		if ( ! $this->discount->is_minimum_amount_met( $total ) ) {
653
			$this->is_discount_valid = false;
654
            $min = wpinv_price( wpinv_format_amount( $$this->discount->min_total ) );
655
			$this->last_error = sprintf( __( 'The minimum total for using this discount is %s', 'invoicing' ), $min );
656
        }
657
658
        if ( ! $this->discount->is_maximum_amount_met( $total ) ) {
659
			$this->is_discount_valid = false;
660
            $max = wpinv_price( wpinv_format_amount( $$this->discount->max_total ) );
661
			$this->last_error = sprintf( __( 'The maximum total for using this discount is %s', 'invoicing' ), $max );
662
		}
663
664
		if ( ! $this->is_discount_valid ) {
665
			$this->discount = null;
666
			$this->remove_discount( 'Discount' );
667
		}
668
669
    }
670
671
	/**
672
	 * Maybe process discount.
673
	 *
674
	 * @since 1.0.19
675
	 * @param GetPaid_Form_Item $item
676
	 */
677
	public function process_item_discount( $item ) {
678
679
		// Abort early if there is no discount.
680
		if ( ! $this->has_discount_code() ) {
681
			return;
682
		}
683
684
		// Ensure that it is valid for this item.
685
		if ( ! $this->discount->is_valid_for_items( array( $item->get_id() ) ) ) {
686
			return;
687
		}
688
689
		// Fetch the discounted amount.
690
		$discount = $this->discount->get_discounted_amount( $item->get_price() * $item->get_quantity() );
691
692
		$this->add_discount( 'Discount', $discount );
693
694
	}
695
696
	/**
697
	 * Returns the total discount amount.
698
	 *
699
	 * @since 1.0.19
700
	 */
701
	public function get_total_discount() {
702
		return $this->total_discount_amount;
703
	}
704
705
	/**
706
	 * Gets a specific discount.
707
	 *
708
	 * @since 1.0.19
709
	 */
710
	public function get_discount( $name ) {
711
		return isset( $this->discounts[ $name ] ) ? $this->discounts[ $name ] : 0;
712
	}
713
714
	/**
715
	 * Returns all discounts.
716
	 *
717
	 * @since 1.0.19
718
	 */
719
	public function get_discounts() {
720
		return $this->discounts;
721
	}
722
723
	///////// FEES //////////////
724
725
	/**
726
	 * Adds a fee to the submission.
727
	 *
728
	 * @since 1.0.19
729
	 */
730
	public function add_fee( $name, $amount ) {
731
		$amount = wpinv_sanitize_amount( $amount );
732
733
		$this->total_fees_amount += $amount;
734
735
		if ( isset( $this->fees[ $name ] ) ) {
736
			$this->fees[ $name ] += $amount;
737
		} else {
738
			$this->fees[ $name ] = $amount;
739
		}
740
741
	}
742
743
	/**
744
	 * Returns the total fees amount.
745
	 *
746
	 * @since 1.0.19
747
	 */
748
	public function get_total_fees() {
749
		return $this->total_fees_amount;
750
	}
751
752
	/**
753
	 * Retrieves a specific fee.
754
	 *
755
	 * @since 1.0.19
756
	 */
757
	public function get_fee( $name ) {
758
		return isset( $this->fees[ $name ] ) ? $this->fees[ $name ] : 0;
759
	}
760
761
	/**
762
	 * Returns all fees.
763
	 *
764
	 * @since 1.0.19
765
	 */
766
	public function get_fees() {
767
		return $this->fees;
768
	}
769
770
	// MISC //
771
772
	/**
773
	 * Returns the total amount to collect for this submission.
774
	 *
775
	 * @since 1.0.19
776
	 */
777
	public function get_total() {
778
		$total = $this->subtotal_amount + $this->get_total_fees() - $this->get_total_discount() + $this->get_total_tax();
779
		$total = apply_filters( 'getpaid_get_submission_total_amount', $total, $this  );
780
		return wpinv_sanitize_amount( $total );
781
	}
782
783
	/**
784
	 * Whether payment details should be collected for this submission.
785
	 *
786
	 * @since 1.0.19
787
	 */
788
	public function get_payment_details() {
789
		$collect = $this->subtotal_amount + $this->get_total_fees() - $this->get_total_discount() + $this->get_total_tax();
790
791
		if ( $this->has_recurring ) {
792
			$collect = true;
793
		}
794
795
		$collect = apply_filters( 'getpaid_submission_collect_payment_details', $collect, $this  );
796
		return $collect;
797
	}
798
799
	/**
800
	 * Returns the billing email of the user.
801
	 *
802
	 * @since 1.0.19
803
	 */
804
	public function get_billing_email() {
805
		$billing_email = empty( $this->data['billing_email'] ) ? '' : $this->data['billing_email'];
806
		return apply_filters( 'getpaid_get_submission_billing_email', $billing_email, $this  );
807
	}
808
809
	/**
810
	 * Checks if the submitter has a billing email.
811
	 *
812
	 * @since 1.0.19
813
	 */
814
	public function has_billing_email() {
815
		$billing_email = $this->get_billing_email();
816
		return ! empty( $billing_email );
817
	}
818
819
	/**
820
	 * Validate VAT data.
821
	 *
822
	 * @since 1.0.19
823
	 */
824
	public function maybe_validate_vat() {
825
		
826
		// Make sure that taxes are enabled.
827
		if ( ! wpinv_use_taxes() ) {
828
			return;
829
		}
830
831
		// Check if we have a digital VAT rule.
832
		$has_digital = false;
833
834
		foreach ( $this->get_items() as $item ) {
835
836
			if ( 'digital' == $item->get_vat_rule() ) {
837
				$has_digital = true;
838
				break;
839
			}
840
841
		}
842
843
		$this->has_digital = $has_digital;
844
845
		// Check if we require vat.
846
		$requires_vat = (
847
			( getpaid_is_eu_state( $this->country ) && ( getpaid_is_eu_state( wpinv_get_default_country() ) || $has_digital ) )
848
			|| ( getpaid_is_gst_country( $this->country ) && getpaid_is_gst_country( wpinv_get_default_country() ) )
849
		);
850
851
		$this->requires_vat = $requires_vat;
852
853
		// Abort if we are not calculating the taxes.
854
		if ( ! $has_digital && ! $requires_vat ) {
855
            return;
856
		}
857
858
		// Prepare variables.
859
		$vat_number = $this->get_vat_number();
860
		$company    = $this->get_company();
861
		$ip_country = WPInv_EUVat::get_country_by_ip();
862
        $is_eu      = getpaid_is_eu_state( $this->country );
863
        $is_ip_eu   = getpaid_is_eu_state( $ip_country );
864
		$is_non_eu  = ! $is_eu && ! $is_ip_eu;
865
		$prevent_b2c = wpinv_get_option( 'vat_prevent_b2c_purchase' );
866
867
		// If we're preventing business to consumer purchases...
868
		if ( ! empty( $prevent_b2c ) && ! $is_non_eu && ( empty( $vat_number ) || ! $requires_vat ) ) {
869
870
            if ( $is_eu ) {
871
				$this->last_error = wp_sprintf(
872
					__( 'Please enter your %s number to verify your purchase is by an EU business.', 'invoicing' ),
873
					getpaid_vat_name()
874
				);
875
            } else if ( $has_digital && $is_ip_eu ) {
876
877
				$this->last_error = wp_sprintf(
878
					__( 'Sales to non-EU countries cannot be completed because %s must be applied.', 'invoicing' ),
879
					getpaid_vat_name()
880
				);
881
882
			}
883
884
		}
885
		
886
		// Abort if we are not validating vat.
887
		if ( ! $is_eu || ! $requires_vat || empty( $vat_number ) ) {
888
            return;
889
		}
890
891
		$is_valid = WPInv_EUVat::validate_vat_number( $vat_number, $company, $this->country );
892
893
		if ( is_string( $is_valid ) ) {
0 ignored issues
show
introduced by
The condition is_string($is_valid) is always true.
Loading history...
894
			$this->last_error = $is_valid;
895
		}
896
897
	}
898
899
}
900