calculate_discount()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 2
rs 10
1
<?php
2
/**
3
 * Processes discounts for a payment form submission.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Payment form submission discount class
11
 *
12
 */
13
class GetPaid_Payment_Form_Submission_Discount {
14
15
	/**
16
	 * Submission discounts.
17
	 * @var array
18
	 */
19
	public $discounts = array();
20
21
    /**
22
	 * Class constructor
23
	 *
24
	 * @param GetPaid_Payment_Form_Submission $submission
25
	 * @param float                           $initial_total
26
	 * @param float                           $recurring_total
27
	 */
28
	public function __construct( $submission, $initial_total, $recurring_total ) {
29
30
		// Process any existing invoice discounts.
31
		if ( $submission->has_invoice() ) {
32
			$this->discounts = $submission->get_invoice()->get_discounts();
33
		}
34
35
		// Do we have a discount?
36
		$discount = $submission->get_field( 'discount' );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $discount is correct as $submission->get_field('discount') targeting GetPaid_Payment_Form_Submission::get_field() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
37
38
		if ( empty( $discount ) ) {
39
40
			if ( isset( $this->discounts['discount_code'] ) ) {
41
				unset( $this->discounts['discount_code'] );
42
			}
43
44
			return;
45
		}
46
47
		// Processes the discount code.
48
		$amount = max( $initial_total, $recurring_total );
49
		$this->process_discount( $submission, $discount, $amount );
50
51
	}
52
53
	/**
54
	 * Processes a submission discount.
55
	 *
56
	 * @param GetPaid_Payment_Form_Submission $submission
57
	 * @param string                          $discount
58
	 * @param float                           $amount
59
	 */
60
	public function process_discount( $submission, $discount, $amount ) {
61
62
		// Fetch the discount.
63
		$discount = new WPInv_Discount( $discount );
64
65
		// Ensure it is active.
66
        if ( ! $this->is_discount_active( $discount ) ) {
67
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'Invalid or expired discount code', 'invoicing' ) );
68
		}
69
70
		// Required items.
71
		if ( ! $discount->is_required_items_met( array_keys( $submission->get_items() ) ) ) {
72
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You are not allowed to use this discount code.', 'invoicing' ) );
73
		}
74
75
		// Exceeded limit.
76
		if ( $discount->has_exceeded_limit() ) {
77
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'This discount code has been used up', 'invoicing' ) );
78
		}
79
80
		// Validate usages.
81
		$this->validate_single_use_discount( $submission, $discount );
82
83
		// Validate amount.
84
		$this->validate_discount_amount( $submission, $discount, $amount );
85
86
		// Save the discount.
87
		$this->discounts['discount_code'] = $this->calculate_discount( $submission, $discount );
88
	}
89
90
	/**
91
	 * Validates a single use discount.
92
	 *
93
	 * @param WPInv_Discount                  $discount
94
	 * @return bool
95
	 */
96
	public function is_discount_active( $discount ) {
97
		return $discount->exists() && $discount->is_active() && $discount->has_started() && ! $discount->is_expired();
98
	}
99
100
	/**
101
	 * Returns a user's id or email.
102
	 *
103
	 * @param string $email
104
	 * @return int|string|false
105
	 */
106
	public function get_user_id_or_email( $email ) {
107
108
		if ( is_user_logged_in() ) {
109
			return get_current_user_id();
110
		}
111
112
		return empty( $email ) ? false : sanitize_email( $email );
113
	}
114
115
	/**
116
	 * Validates a single use discount.
117
	 *
118
	 * @param GetPaid_Payment_Form_Submission $submission
119
	 * @param WPInv_Discount                  $discount
120
	 */
121
	public function validate_single_use_discount( $submission, $discount ) {
122
123
		// Abort if it is not a single use discount.
124
		if ( ! $discount->is_single_use() ) {
125
			return;
126
		}
127
128
		// Ensure there is a valid billing email.
129
		$user = $this->get_user_id_or_email( $submission->get_billing_email() );
130
131
		if ( empty( $user ) ) {
132
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You need to either log in or enter your billing email before applying this discount', 'invoicing' ) );
133
		}
134
135
		// Has the user used this discount code before?
136
		if ( ! $discount->is_valid_for_user( $user ) ) {
137
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', __( 'You have already used this discount', 'invoicing' ) );
138
		}
139
140
	}
141
142
	/**
143
	 * Validates the discount's amount.
144
	 *
145
	 * @param GetPaid_Payment_Form_Submission $submission
146
	 * @param WPInv_Discount         $discount
147
	 * @param float                  $amount
148
	 */
149
	public function validate_discount_amount( $submission, $discount, $amount ) {
150
151
		// Validate minimum amount.
152
		if ( ! $discount->is_minimum_amount_met( $amount ) ) {
153
			$min = wpinv_price( $discount->get_minimum_total(), $submission->get_currency() );
154
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The minimum total for using this discount is %s', 'invoicing' ), $min ) );
155
		}
156
157
		// Validate the maximum amount.
158
		if ( ! $discount->is_maximum_amount_met( $amount ) ) {
159
			$max = wpinv_price( $discount->get_maximum_total(), $submission->get_currency() );
160
			throw new GetPaid_Payment_Exception( '.getpaid-discount-field .getpaid-custom-payment-form-errors', sprintf( __( 'The maximum total for using this discount is %s', 'invoicing' ), $max ) );
161
		}
162
163
	}
164
165
	/**
166
	 * Calculates the discount code's amount.
167
	 *
168
	 * Ensure that the discount exists and has been validated before calling this method.
169
	 *
170
	 * @param GetPaid_Payment_Form_Submission $submission
171
	 * @param WPInv_Discount                  $discount
172
	 * @return array
173
	 */
174
	public function calculate_discount( $submission, $discount ) {
175
		return getpaid_calculate_invoice_discount( $submission, $discount );
176
	}
177
178
}
179