Passed
Pull Request — master (#43)
by Kiran
03:49
created

wpinv-invoice-functions.php ➔ wpinv_checkout_validate_gateway()   D

Complexity

Conditions 9
Paths 11

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 18
nc 11
nop 0
dl 0
loc 29
rs 4.909
c 0
b 0
f 0
1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
function wpinv_get_invoice_cart_id() {
15
    $wpinv_checkout = wpinv_get_checkout_session();
16
    
17
    if ( !empty( $wpinv_checkout['invoice_id'] ) ) {
18
        return $wpinv_checkout['invoice_id'];
19
    }
20
    
21
    return NULL;
22
}
23
24
function wpinv_get_invoice( $invoice_id = 0, $cart = false ) {
25
    if ( $cart && empty( $invoice_id ) ) {
26
        $invoice_id = (int)wpinv_get_invoice_cart_id();
27
    }
28
29
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
30
    return $invoice;
31
}
32
33
function wpinv_get_invoice_cart( $invoice_id = 0 ) {
34
    return wpinv_get_invoice( $invoice_id, true );
35
}
36
37
function wpinv_get_invoice_description( $invoice_id = 0 ) {
38
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
39
    return $invoice->get_description();
40
}
41
42
function wpinv_get_invoice_currency_code( $invoice_id = 0 ) {
43
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
44
    return $invoice->get_currency();
45
}
46
47
function wpinv_get_payment_user_email( $invoice_id ) {
48
    $invoice = new WPInv_Invoice( $invoice_id );
49
    return $invoice->get_email();
50
}
51
52
function wpinv_get_user_id( $invoice_id ) {
53
    $invoice = new WPInv_Invoice( $invoice_id );
54
    return $invoice->get_user_id();
55
}
56
57
function wpinv_get_invoice_status( $invoice_id, $return_label = false ) {
58
    $invoice = new WPInv_Invoice( $invoice_id );
59
    
60
    return $invoice->get_status( $return_label );
61
}
62
63
function wpinv_get_payment_gateway( $invoice_id, $return_label = false ) {
64
    $invoice = new WPInv_Invoice( $invoice_id );
65
    
66
    return $invoice->get_gateway( $return_label );
0 ignored issues
show
Unused Code introduced by
The call to WPInv_Invoice::get_gateway() has too many arguments starting with $return_label.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
67
}
68
69
function wpinv_get_payment_gateway_name( $invoice_id ) {
70
    $invoice = new WPInv_Invoice( $invoice_id );
71
    
72
    return $invoice->get_gateway_title();
73
}
74
75
function wpinv_get_payment_transaction_id( $invoice_id ) {
76
    $invoice = new WPInv_Invoice( $invoice_id );
77
    
78
    return $invoice->get_transaction_id();
79
}
80
81 View Code Duplication
function wpinv_get_id_by_transaction_id( $key ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    global $wpdb;
83
84
    $invoice_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wpinv_transaction_id' AND meta_value = %s LIMIT 1", $key ) );
85
86
    if ( $invoice_id != NULL )
87
        return $invoice_id;
88
89
    return 0;
90
}
91
92
function wpinv_get_invoice_meta( $invoice_id = 0, $meta_key = '_wpinv_payment_meta', $single = true ) {
93
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
94
95
    return $invoice->get_meta( $meta_key, $single );
96
}
97
98
function wpinv_update_invoice_meta( $invoice_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
99
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
100
    
101
    return $invoice->update_meta( $meta_key, $meta_value, $prev_value );
102
}
103
104
function wpinv_get_items( $invoice_id = 0 ) {
105
    $invoice            = wpinv_get_invoice( $invoice_id );
106
    
107
    $items              = $invoice->get_items();
108
    $invoice_currency   = $invoice->get_currency();
109
110 View Code Duplication
    if ( !empty( $items ) && is_array( $items ) ) {
111
        foreach ( $items as $key => $item ) {
112
            $items[$key]['currency'] = $invoice_currency;
113
114
            if ( !isset( $cart_item['subtotal'] ) ) {
115
                $items[$key]['subtotal'] = $items[$key]['amount'] * 1;
116
            }
117
        }
118
    }
119
120
    return apply_filters( 'wpinv_get_items', $items, $invoice_id );
121
}
122
123
function wpinv_get_fees( $invoice_id = 0 ) {
124
    $invoice           = wpinv_get_invoice( $invoice_id );
125
    $fees              = $invoice->get_fees();
126
127
    return apply_filters( 'wpinv_get_fees', $fees, $invoice_id );
128
}
129
130
function wpinv_get_invoice_ip( $invoice_id ) {
131
    $invoice = new WPInv_Invoice( $invoice_id );
132
    return $invoice->get_ip();
133
}
134
135
function wpinv_get_invoice_user_info( $invoice_id ) {
136
    $invoice = new WPInv_Invoice( $invoice_id );
137
    return $invoice->get_user_info();
138
}
139
140
function wpinv_subtotal( $invoice_id = 0, $currency = false ) {
141
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
142
143
    return $invoice->get_subtotal( $currency );
144
}
145
146
function wpinv_tax( $invoice_id = 0, $currency = false ) {
147
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
148
149
    return $invoice->get_tax( $currency );
150
}
151
152
function wpinv_discount( $invoice_id = 0, $currency = false, $dash = false ) {
153
    $invoice = wpinv_get_invoice( $invoice_id );
154
155
    return $invoice->get_discount( $currency, $dash );
156
}
157
158
function wpinv_discount_code( $invoice_id = 0 ) {
159
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
160
161
    return $invoice->get_discount_code();
162
}
163
164
function wpinv_payment_total( $invoice_id = 0, $currency = false ) {
165
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
166
167
    return $invoice->get_total( $currency );
168
}
169
170
function wpinv_get_date_created( $invoice_id = 0 ) {
171
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
172
    
173
    $date_created   = $invoice->get_created_date();
174
    $date_created   = $date_created != '' && $date_created != '0000-00-00 00:00:00' ? date_i18n( get_option( 'date_format' ), strtotime( $date_created ) ) : '';
175
176
    return $date_created;
177
}
178
179
function wpinv_get_invoice_date( $invoice_id = 0, $format = '' ) {
180
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
181
    
182
    $format         = !empty( $format ) ? $format : get_option( 'date_format' );
183
    $date_completed = $invoice->get_completed_date();
184
    $invoice_date   = $date_completed != '' && $date_completed != '0000-00-00 00:00:00' ? date_i18n( $format, strtotime( $date_completed ) ) : '';
185
    if ( $invoice_date == '' ) {
186
        $date_created   = $invoice->get_created_date();
187
        $invoice_date   = $date_created != '' && $date_created != '0000-00-00 00:00:00' ? date_i18n( $format, strtotime( $date_created ) ) : '';
188
    }
189
190
    return $invoice_date;
191
}
192
193
function wpinv_get_invoice_vat_number( $invoice_id = 0 ) {
194
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
    
196
    return $invoice->vat_number;
197
}
198
199
function wpinv_insert_payment_note( $invoice_id = 0, $note = '', $user_type = false, $added_by_user = false ) {
200
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
201
202
    return $invoice->add_note( $note, $user_type, $added_by_user );
203
}
204
205
function wpinv_get_invoice_notes( $invoice_id = 0, $type = '' ) {
206
    global $invoicing;
207
    
208
    if ( empty( $invoice_id ) ) {
209
        return NULL;
210
    }
211
    
212
    $notes = $invoicing->notes->get_invoice_notes( $invoice_id, $type );
213
    
214
    return apply_filters( 'wpinv_invoice_notes', $notes, $invoice_id, $type );
215
}
216
217
function wpinv_get_payment_key( $invoice_id = 0 ) {
218
	$invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
219
    return $invoice->get_key();
220
}
221
222
function wpinv_get_invoice_number( $invoice_id = 0 ) {
223
    $invoice = new WPInv_Invoice( $invoice_id );
0 ignored issues
show
Documentation introduced by
$invoice_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
224
    return $invoice->get_number();
225
}
226
227
function wpinv_get_cart_discountable_subtotal( $code_id ) {
228
    $cart_items = wpinv_get_cart_content_details();
229
    $items      = array();
230
231
    $excluded_items = wpinv_get_discount_excluded_items( $code_id );
232
233
    if( $cart_items ) {
234
235
        foreach( $cart_items as $item ) {
236
237
            if( ! in_array( $item['id'], $excluded_items ) ) {
238
                $items[] =  $item;
239
            }
240
        }
241
    }
242
243
    $subtotal = wpinv_get_cart_items_subtotal( $items );
244
245
    return apply_filters( 'wpinv_get_cart_discountable_subtotal', $subtotal );
246
}
247
248
function wpinv_get_cart_items_subtotal( $items ) {
249
    $subtotal = 0.00;
250
251
    if ( is_array( $items ) && ! empty( $items ) ) {
252
        $prices = wp_list_pluck( $items, 'subtotal' );
253
254
        if( is_array( $prices ) ) {
255
            $subtotal = array_sum( $prices );
256
        } else {
257
            $subtotal = 0.00;
258
        }
259
260
        if( $subtotal < 0 ) {
261
            $subtotal = 0.00;
262
        }
263
    }
264
265
    return apply_filters( 'wpinv_get_cart_items_subtotal', $subtotal );
266
}
267
268
function wpinv_get_cart_subtotal( $items = array() ) {
269
    $items    = !empty( $items ) ? $items : wpinv_get_cart_content_details();
270
    $subtotal = wpinv_get_cart_items_subtotal( $items );
271
272
    return apply_filters( 'wpinv_get_cart_subtotal', $subtotal );
273
}
274
275
function wpinv_cart_subtotal( $items = array() ) {
276
    $price = wpinv_price( wpinv_format_amount( wpinv_get_cart_subtotal( $items ) ) );
277
278
    // Todo - Show tax labels here (if needed)
279
280
    return $price;
281
}
282
283
function wpinv_get_cart_total( $items = array(), $discounts = false, $invoice = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $discounts is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
284
    $subtotal  = (float)wpinv_get_cart_subtotal( $items );
285
    $discounts = (float)wpinv_get_cart_discounted_amount( $items );
286
    $cart_tax  = (float)wpinv_get_cart_tax( $items );
287
    $fees      = (float)wpinv_get_cart_fee_total();
288
    if ( !empty( $invoice ) && $invoice->is_free_trial() ) {
0 ignored issues
show
Bug introduced by
The method is_free_trial cannot be called on $invoice (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
289
        $total = 0;
290
    } else {
291
        $total     = $subtotal - $discounts + $cart_tax + $fees;
292
    }
293
294
    if ( $total < 0 ) {
295
        $total = 0.00;
296
    }
297
    
298
    $total = (float)apply_filters( 'wpinv_get_cart_total', $total, $items );
299
300
    return wpinv_sanitize_amount( $total );
301
}
302
303
function wpinv_cart_total( $cart_items = array(), $echo = true, $invoice = array() ) {
304
    global $cart_total;
305
    $total = wpinv_price( wpinv_format_amount( wpinv_get_cart_total( $cart_items, NULL, $invoice ) ) );
0 ignored issues
show
Documentation introduced by
NULL is of type null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
306
    $total = apply_filters( 'wpinv_cart_total', $total, $cart_items, $invoice );
307
308
    // Todo - Show tax labels here (if needed)
309
    
310
    $cart_total = $total;
311
312
    if ( !$echo ) {
313
        return $total;
314
    }
315
316
    echo $total;
317
}
318
319 View Code Duplication
function wpinv_get_cart_tax( $items = array() ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
320
    $cart_tax = 0;
321
    $items    = !empty( $items ) ? $items : wpinv_get_cart_content_details();
322
323
    if ( $items ) {
324
        $taxes = wp_list_pluck( $items, 'tax' );
325
326
        if( is_array( $taxes ) ) {
327
            $cart_tax = array_sum( $taxes );
328
        }
329
    }
330
331
    $cart_tax += wpinv_get_cart_fee_tax();
332
333
    return apply_filters( 'wpinv_get_cart_tax', wpinv_sanitize_amount( $cart_tax ) );
334
}
335
336 View Code Duplication
function wpinv_cart_tax( $items = array(), $echo = false ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
    $cart_tax = wpinv_get_cart_tax( $items );
338
    $cart_tax = wpinv_price( wpinv_format_amount( $cart_tax ) );
339
340
    $tax = apply_filters( 'wpinv_cart_tax', $cart_tax, $items );
341
342
    if ( !$echo ) {
343
        return $tax;
344
    }
345
346
    echo $tax;
347
}
348
349
function wpinv_get_cart_discount_code( $items = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $items is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
350
    $invoice = wpinv_get_invoice_cart();
351
    $cart_discount_code = !empty( $invoice ) ? $invoice->get_discount_code() : '';
352
    
353
    return apply_filters( 'wpinv_get_cart_discount_code', $cart_discount_code );
354
}
355
356
function wpinv_cart_discount_code( $items = array(), $echo = false ) {
357
    $cart_discount_code = wpinv_get_cart_discount_code( $items );
358
359
    if ( $cart_discount_code != '' ) {
360
        $cart_discount_code = ' (' . $cart_discount_code . ')';
361
    }
362
    
363
    $discount_code = apply_filters( 'wpinv_cart_discount_code', $cart_discount_code, $items );
364
365
    if ( !$echo ) {
366
        return $discount_code;
367
    }
368
369
    echo $discount_code;
370
}
371
372
function wpinv_get_cart_discount( $items = array() ) {
373
    $invoice = wpinv_get_invoice_cart();
374
    $cart_discount = !empty( $invoice ) ? $invoice->get_discount() : 0;
375
    
376
    return apply_filters( 'wpinv_get_cart_discount', wpinv_sanitize_amount( $cart_discount ), $items );
377
}
378
379 View Code Duplication
function wpinv_cart_discount( $items = array(), $echo = false ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
380
    $cart_discount = wpinv_get_cart_discount( $items );
381
    $cart_discount = wpinv_price( wpinv_format_amount( $cart_discount ) );
382
383
    $discount = apply_filters( 'wpinv_cart_discount', $cart_discount, $items );
384
385
    if ( !$echo ) {
386
        return $discount;
387
    }
388
389
    echo $discount;
390
}
391
392
function wpinv_get_cart_fees( $type = 'all', $item_id = 0 ) {
393
    $item = new WPInv_Item( $item_id );
0 ignored issues
show
Documentation introduced by
$item_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
394
    
395
    return $item->get_fees( $type, $item_id );
396
}
397
398
function wpinv_get_cart_fee_total() {
399
    $total  = 0;
400
    $fees = wpinv_get_cart_fees();
401
    
402
    if ( $fees ) {
403
        foreach ( $fees as $fee_id => $fee ) {
404
            $total += $fee['amount'];
405
        }
406
    }
407
408
    return apply_filters( 'wpinv_get_cart_fee_total', $total );
409
}
410
411
function wpinv_get_cart_fee_tax() {
412
    $tax  = 0;
413
    $fees = wpinv_get_cart_fees();
414
415
    if ( $fees ) {
416
        foreach ( $fees as $fee_id => $fee ) {
417
            if( ! empty( $fee['no_tax'] ) ) {
418
                continue;
419
            }
420
421
            $tax += wpinv_calculate_tax( $fee['amount'] );
422
        }
423
    }
424
425
    return apply_filters( 'wpinv_get_cart_fee_tax', $tax );
426
}
427
428
function wpinv_cart_has_recurring_item() {
429
    $cart_items = wpinv_get_cart_contents();
430
    
431
    if ( empty( $cart_items ) ) {
432
        return false;
433
    }
434
    
435
    $has_subscription = false;
436 View Code Duplication
    foreach( $cart_items as $cart_item ) {
437
        if ( !empty( $cart_item['id'] ) && wpinv_is_recurring_item( $cart_item['id'] )  ) {
438
            $has_subscription = true;
439
            break;
440
        }
441
    }
442
    
443
    return apply_filters( 'wpinv_cart_has_recurring_item', $has_subscription, $cart_items );
444
}
445
446
function wpinv_cart_has_free_trial() {
447
    $invoice = wpinv_get_invoice_cart();
448
    
449
    $free_trial = false;
450
    
451
    if ( !empty( $invoice ) && $invoice->is_free_trial() ) {
452
        $free_trial = true;
453
    }
454
    
455
    return apply_filters( 'wpinv_cart_has_free_trial', $free_trial, $invoice );
456
}
457
458
function wpinv_get_cart_contents() {
459
    $cart_details = wpinv_get_cart_details();
460
    
461
    return apply_filters( 'wpinv_get_cart_contents', $cart_details );
462
}
463
464
function wpinv_get_cart_content_details() {
465
    global $wpinv_euvat, $wpi_current_id, $wpi_item_id, $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
466
    $cart_items = wpinv_get_cart_contents();
467
    
468
    if ( empty( $cart_items ) ) {
469
        return false;
470
    }
471
    $invoice = wpinv_get_invoice_cart();
472
473
    $details = array();
474
    $length  = count( $cart_items ) - 1;
0 ignored issues
show
Unused Code introduced by
$length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
475
    
476
    if ( empty( $_POST['country'] ) ) {
477
        $_POST['country'] = $invoice->country;
478
    }
479
    if ( !isset( $_POST['state'] ) ) {
480
        $_POST['state'] = $invoice->state;
481
    }
482
483
    foreach( $cart_items as $key => $item ) {
484
        $item_id            = isset( $item['id'] ) ? sanitize_text_field( $item['id'] ) : '';
485
        if ( empty( $item_id ) ) {
486
            continue;
487
        }
488
        
489
        $wpi_current_id         = $invoice->ID;
490
        $wpi_item_id            = $item_id;
491
        
492
        $item_price         = wpinv_get_item_price( $item_id );
493
        $discount           = wpinv_get_cart_item_discount_amount( $item );
494
        $discount           = apply_filters( 'wpinv_get_cart_content_details_item_discount_amount', $discount, $item );
495
        $quantity           = wpinv_get_cart_item_quantity( $item );
496
        $fees               = wpinv_get_cart_fees( 'fee', $item_id );
497
        
498
        $subtotal           = $item_price * $quantity;
499
        $tax_rate           = wpinv_get_tax_rate( $_POST['country'], $_POST['state'], $wpi_item_id );
0 ignored issues
show
Documentation introduced by
$_POST['state'] is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
500
        $tax_class          = $wpinv_euvat->get_item_class( $item_id );
501
        $tax                = wpinv_get_cart_item_tax( $item_id, $subtotal - $discount );
502
        
503
        if ( wpinv_prices_include_tax() ) {
504
            $subtotal -= wpinv_format_amount( $tax, NULL, true );
505
        }
506
        
507
        $total              = $subtotal - $discount + $tax;
508
        
509
        // Do not allow totals to go negatve
510
        if( $total < 0 ) {
511
            $total = 0;
512
        }
513
        
514
        $details[ $key ]  = array(
515
            'id'                => $item_id,
516
            'name'              => !empty($item['name']) ? $item['name'] : get_the_title( $item_id ),
517
            'item_price'        => wpinv_format_amount( $item_price, NULL, true ),
518
            'quantity'          => $quantity,
519
            'discount'          => wpinv_format_amount( $discount, NULL, true ),
520
            'subtotal'          => wpinv_format_amount( $subtotal, NULL, true ),
521
            'tax'               => wpinv_format_amount( $tax, NULL, true ),
522
            'price'             => wpinv_format_amount( $total, NULL, true ),
523
            'vat_rates_class'   => $tax_class,
524
            'vat_rate'          => wpinv_format_amount( $tax_rate, NULL, true ),
525
            'meta'              => isset( $item['meta'] ) ? $item['meta'] : array(),
526
            'fees'              => $fees,
527
        );
528
        
529
        if ( $wpinv_is_last_cart_item ) {
530
            $wpinv_is_last_cart_item   = false;
531
            $wpinv_flat_discount_total = 0.00;
532
        }
533
    }
534
    
535
    return $details;
536
}
537
538
function wpinv_get_cart_details( $invoice_id = 0 ) {
539
    global $ajax_cart_details;
540
541
    $invoice      = wpinv_get_invoice_cart( $invoice_id );
542
    $cart_details = !empty( $ajax_cart_details ) ? $ajax_cart_details : $invoice->cart_details;
543
544
    $invoice_currency = $invoice->currency;
545
546 View Code Duplication
    if ( ! empty( $cart_details ) && is_array( $cart_details ) ) {
547
        foreach ( $cart_details as $key => $cart_item ) {
548
            $cart_details[ $key ]['currency'] = $invoice_currency;
549
550
            if ( ! isset( $cart_item['subtotal'] ) ) {
551
                $cart_details[ $key ]['subtotal'] = $cart_item['price'];
552
            }
553
        }
554
    }
555
556
    return apply_filters( 'wpinv_get_cart_details', $cart_details, $invoice_id );
557
}
558
559
function wpinv_record_status_change( $invoice_id, $new_status, $old_status ) {
560
    $invoice    = wpinv_get_invoice( $invoice_id );
561
    
562
    $old_status = wpinv_status_nicename( $old_status );
563
    $new_status = wpinv_status_nicename( $new_status );
564
565
    $status_change = sprintf( __( 'Invoice status changed from %s to %s', 'invoicing' ), $old_status, $new_status );
566
    
567
    // Add note
568
    return $invoice->add_note( $status_change, 0 );
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
569
}
570
add_action( 'wpinv_update_status', 'wpinv_record_status_change', 100, 3 );
571
572
function wpinv_complete_payment( $invoice_id, $new_status, $old_status ) {
573
    global $wpi_has_free_trial;
574
    
575
    $wpi_has_free_trial = false;
576
    
577
    if ( $old_status == 'publish' ) {
578
        return; // Make sure that payments are only paid once
579
    }
580
581
    // Make sure the payment completion is only processed when new status is paid
582
    if ( $new_status != 'publish' ) {
583
        return;
584
    }
585
586
    $invoice = new WPInv_Invoice( $invoice_id );
587
    if ( empty( $invoice ) ) {
588
        return;
589
    }
590
591
    $wpi_has_free_trial = $invoice->is_free_trial();
592
    $completed_date = $invoice->completed_date;
593
    $cart_details   = $invoice->cart_details;
594
595
    do_action( 'wpinv_pre_complete_payment', $invoice_id );
596
597
    if ( is_array( $cart_details ) ) {
598
        // Increase purchase count and earnings
599
        foreach ( $cart_details as $cart_index => $item ) {
600
            // Ensure these actions only run once, ever
601
            if ( empty( $completed_date ) ) {
602
                do_action( 'wpinv_complete_item_payment', $item['id'], $invoice_id, $item, $cart_index );
603
            }
604
        }
605
    }
606
    
607
    // Check for discount codes and increment their use counts
608
    if ( $discounts = $invoice->get_discounts( true ) ) {
609
        if( ! empty( $discounts ) ) {
610
            foreach( $discounts as $code ) {
611
                wpinv_increase_discount_usage( $code );
612
            }
613
        }
614
    }
615
    
616
    // Ensure this action only runs once ever
617
    if( empty( $completed_date ) ) {
618
        // Save the completed date
619
        $invoice->set( 'completed_date', current_time( 'mysql', 0 ) );
620
        $invoice->save();
621
622
        do_action( 'wpinv_complete_payment', $invoice_id );
623
    }
624
625
    // Empty the shopping cart
626
    wpinv_empty_cart();
627
}
628
add_action( 'wpinv_update_status', 'wpinv_complete_payment', 100, 3 );
629
630
function wpinv_update_payment_status( $invoice_id, $new_status = 'publish' ) {    
631
    $invoice = !empty( $invoice_id ) && is_object( $invoice_id ) ? $invoice_id : wpinv_get_invoice( (int)$invoice_id );
632
    
633
    if ( empty( $invoice ) ) {
634
        return false;
635
    }
636
    
637
    return $invoice->update_status( $new_status );
638
}
639
640
function wpinv_cart_has_fees( $type = 'all' ) {
641
    return false;
642
}
643
644
function wpinv_validate_checkout_fields() {    
645
    // Check if there is $_POST
646
    if ( empty( $_POST ) ) {
647
        return false;
648
    }
649
    
650
    // Start an array to collect valid data
651
    $valid_data = array(
652
        'gateway'          => wpinv_checkout_validate_gateway(), // Gateway fallback
653
        'discount'         => wpinv_checkout_validate_discounts(), // Set default discount
654
        'cc_info'          => wpinv_checkout_validate_cc() // Credit card info
655
    );
656
    
657
    // Validate agree to terms
658
    if ( wpinv_get_option( 'show_agree_to_terms', false ) ) {
659
        wpinv_checkout_validate_agree_to_terms();
660
    }
661
    
662
    $valid_data['logged_in_user']   = wpinv_checkout_validate_logged_in_user();
663
    
664
    // Return collected data
665
    return $valid_data;
666
}
667
668
function wpinv_checkout_validate_gateway() {
669
    $gateway = wpinv_get_default_gateway();
670
    
671
    $invoice = wpinv_get_invoice_cart();
672
    $has_subscription = $invoice->is_recurring();
673
    if ( empty( $invoice ) ) {
674
        wpinv_set_error( 'invalid_invoice', __( 'Your cart is empty.', 'invoicing' ) );
675
        return $gateway;
676
    }
677
678
    // Check if a gateway value is present
679
    if ( !empty( $_REQUEST['wpi-gateway'] ) ) {
680
        $gateway = sanitize_text_field( $_REQUEST['wpi-gateway'] );
681
682
        if ( $invoice->is_free() ) {
683
            $gateway = 'manual';
684
        } elseif ( !wpinv_is_gateway_active( $gateway ) ) {
685
            wpinv_set_error( 'invalid_gateway', __( 'The selected payment gateway is not enabled', 'invoicing' ) );
686
        } elseif ( $has_subscription && !wpinv_gateway_support_subscription( $gateway ) ) {
687
            wpinv_set_error( 'invalid_gateway', __( 'The selected payment gateway doesnot support subscription payment', 'invoicing' ) );
688
        }
689
    }
690
691
    if ( $has_subscription && count( wpinv_get_cart_contents() ) > 1 ) {
692
        wpinv_set_error( 'subscription_invalid', __( 'Only one subscription may be purchased through payment per checkout.', 'invoicing' ) );
693
    }
694
695
    return $gateway;
696
}
697
698
function wpinv_checkout_validate_discounts() {
699
    // Retrieve the discount stored in cookies
700
    $discounts = wpinv_get_cart_discounts();
701
    
702
    $error = false;
703
    // If we have discounts, loop through them
704
    if ( ! empty( $discounts ) ) {
705
        foreach ( $discounts as $discount ) {
706
            // Check if valid
707
            if (  !wpinv_is_discount_valid( $discount, get_current_user_id() ) ) {
708
                // Discount is not valid
709
                $error = true;
710
            }
711
        }
712
    } else {
713
        // No discounts
714
        return NULL;
715
    }
716
717
    if ( $error && !wpinv_get_errors() ) {
718
        wpinv_set_error( 'invalid_discount', __( 'Discount code you entered is invalid', 'invoicing' ) );
719
    }
720
721
    return implode( ',', $discounts );
722
}
723
724
function wpinv_checkout_validate_cc() {
725
    $card_data = wpinv_checkout_get_cc_info();
726
727
    // Validate the card zip
728
    if ( !empty( $card_data['wpinv_zip'] ) ) {
729
        if ( !wpinv_checkout_validate_cc_zip( $card_data['wpinv_zip'], $card_data['wpinv_country'] ) ) {
730
            wpinv_set_error( 'invalid_cc_zip', __( 'The zip / postcode you entered for your billing address is invalid', 'invoicing' ) );
731
        }
732
    }
733
734
    // This should validate card numbers at some point too
735
    return $card_data;
736
}
737
738
function wpinv_checkout_get_cc_info() {
739
	$cc_info = array();
740
	$cc_info['card_name']      = isset( $_POST['card_name'] )       ? sanitize_text_field( $_POST['card_name'] )       : '';
741
	$cc_info['card_number']    = isset( $_POST['card_number'] )     ? sanitize_text_field( $_POST['card_number'] )     : '';
742
	$cc_info['card_cvc']       = isset( $_POST['card_cvc'] )        ? sanitize_text_field( $_POST['card_cvc'] )        : '';
743
	$cc_info['card_exp_month'] = isset( $_POST['card_exp_month'] )  ? sanitize_text_field( $_POST['card_exp_month'] )  : '';
744
	$cc_info['card_exp_year']  = isset( $_POST['card_exp_year'] )   ? sanitize_text_field( $_POST['card_exp_year'] )   : '';
745
	$cc_info['card_address']   = isset( $_POST['wpinv_address'] )  ? sanitize_text_field( $_POST['wpinv_address'] ) : '';
746
	$cc_info['card_city']      = isset( $_POST['wpinv_city'] )     ? sanitize_text_field( $_POST['wpinv_city'] )    : '';
747
	$cc_info['card_state']     = isset( $_POST['wpinv_state'] )    ? sanitize_text_field( $_POST['wpinv_state'] )   : '';
748
	$cc_info['card_country']   = isset( $_POST['wpinv_country'] )  ? sanitize_text_field( $_POST['wpinv_country'] ) : '';
749
	$cc_info['card_zip']       = isset( $_POST['wpinv_zip'] )      ? sanitize_text_field( $_POST['wpinv_zip'] )     : '';
750
751
	// Return cc info
752
	return $cc_info;
753
}
754
755
function wpinv_checkout_validate_cc_zip( $zip = 0, $country_code = '' ) {
756
    $ret = false;
757
758
    if ( empty( $zip ) || empty( $country_code ) )
759
        return $ret;
760
761
    $country_code = strtoupper( $country_code );
762
763
    $zip_regex = array(
764
        "AD" => "AD\d{3}",
765
        "AM" => "(37)?\d{4}",
766
        "AR" => "^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$",
767
        "AS" => "96799",
768
        "AT" => "\d{4}",
769
        "AU" => "^(0[289][0-9]{2})|([1345689][0-9]{3})|(2[0-8][0-9]{2})|(290[0-9])|(291[0-4])|(7[0-4][0-9]{2})|(7[8-9][0-9]{2})$",
770
        "AX" => "22\d{3}",
771
        "AZ" => "\d{4}",
772
        "BA" => "\d{5}",
773
        "BB" => "(BB\d{5})?",
774
        "BD" => "\d{4}",
775
        "BE" => "^[1-9]{1}[0-9]{3}$",
776
        "BG" => "\d{4}",
777
        "BH" => "((1[0-2]|[2-9])\d{2})?",
778
        "BM" => "[A-Z]{2}[ ]?[A-Z0-9]{2}",
779
        "BN" => "[A-Z]{2}[ ]?\d{4}",
780
        "BR" => "\d{5}[\-]?\d{3}",
781
        "BY" => "\d{6}",
782
        "CA" => "^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$",
783
        "CC" => "6799",
784
        "CH" => "^[1-9][0-9][0-9][0-9]$",
785
        "CK" => "\d{4}",
786
        "CL" => "\d{7}",
787
        "CN" => "\d{6}",
788
        "CR" => "\d{4,5}|\d{3}-\d{4}",
789
        "CS" => "\d{5}",
790
        "CV" => "\d{4}",
791
        "CX" => "6798",
792
        "CY" => "\d{4}",
793
        "CZ" => "\d{3}[ ]?\d{2}",
794
        "DE" => "\b((?:0[1-46-9]\d{3})|(?:[1-357-9]\d{4})|(?:[4][0-24-9]\d{3})|(?:[6][013-9]\d{3}))\b",
795
        "DK" => "^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$",
796
        "DO" => "\d{5}",
797
        "DZ" => "\d{5}",
798
        "EC" => "([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?",
799
        "EE" => "\d{5}",
800
        "EG" => "\d{5}",
801
        "ES" => "^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$",
802
        "ET" => "\d{4}",
803
        "FI" => "\d{5}",
804
        "FK" => "FIQQ 1ZZ",
805
        "FM" => "(9694[1-4])([ \-]\d{4})?",
806
        "FO" => "\d{3}",
807
        "FR" => "^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$",
808
        "GE" => "\d{4}",
809
        "GF" => "9[78]3\d{2}",
810
        "GL" => "39\d{2}",
811
        "GN" => "\d{3}",
812
        "GP" => "9[78][01]\d{2}",
813
        "GR" => "\d{3}[ ]?\d{2}",
814
        "GS" => "SIQQ 1ZZ",
815
        "GT" => "\d{5}",
816
        "GU" => "969[123]\d([ \-]\d{4})?",
817
        "GW" => "\d{4}",
818
        "HM" => "\d{4}",
819
        "HN" => "(?:\d{5})?",
820
        "HR" => "\d{5}",
821
        "HT" => "\d{4}",
822
        "HU" => "\d{4}",
823
        "ID" => "\d{5}",
824
        "IE" => "((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?",
825
        "IL" => "\d{5}",
826
        "IN"=> "^[1-9][0-9][0-9][0-9][0-9][0-9]$", //india
827
        "IO" => "BBND 1ZZ",
828
        "IQ" => "\d{5}",
829
        "IS" => "\d{3}",
830
        "IT" => "^(V-|I-)?[0-9]{5}$",
831
        "JO" => "\d{5}",
832
        "JP" => "\d{3}-\d{4}",
833
        "KE" => "\d{5}",
834
        "KG" => "\d{6}",
835
        "KH" => "\d{5}",
836
        "KR" => "\d{3}[\-]\d{3}",
837
        "KW" => "\d{5}",
838
        "KZ" => "\d{6}",
839
        "LA" => "\d{5}",
840
        "LB" => "(\d{4}([ ]?\d{4})?)?",
841
        "LI" => "(948[5-9])|(949[0-7])",
842
        "LK" => "\d{5}",
843
        "LR" => "\d{4}",
844
        "LS" => "\d{3}",
845
        "LT" => "\d{5}",
846
        "LU" => "\d{4}",
847
        "LV" => "\d{4}",
848
        "MA" => "\d{5}",
849
        "MC" => "980\d{2}",
850
        "MD" => "\d{4}",
851
        "ME" => "8\d{4}",
852
        "MG" => "\d{3}",
853
        "MH" => "969[67]\d([ \-]\d{4})?",
854
        "MK" => "\d{4}",
855
        "MN" => "\d{6}",
856
        "MP" => "9695[012]([ \-]\d{4})?",
857
        "MQ" => "9[78]2\d{2}",
858
        "MT" => "[A-Z]{3}[ ]?\d{2,4}",
859
        "MU" => "(\d{3}[A-Z]{2}\d{3})?",
860
        "MV" => "\d{5}",
861
        "MX" => "\d{5}",
862
        "MY" => "\d{5}",
863
        "NC" => "988\d{2}",
864
        "NE" => "\d{4}",
865
        "NF" => "2899",
866
        "NG" => "(\d{6})?",
867
        "NI" => "((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?",
868
        "NL" => "^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$",
869
        "NO" => "\d{4}",
870
        "NP" => "\d{5}",
871
        "NZ" => "\d{4}",
872
        "OM" => "(PC )?\d{3}",
873
        "PF" => "987\d{2}",
874
        "PG" => "\d{3}",
875
        "PH" => "\d{4}",
876
        "PK" => "\d{5}",
877
        "PL" => "\d{2}-\d{3}",
878
        "PM" => "9[78]5\d{2}",
879
        "PN" => "PCRN 1ZZ",
880
        "PR" => "00[679]\d{2}([ \-]\d{4})?",
881
        "PT" => "\d{4}([\-]\d{3})?",
882
        "PW" => "96940",
883
        "PY" => "\d{4}",
884
        "RE" => "9[78]4\d{2}",
885
        "RO" => "\d{6}",
886
        "RS" => "\d{5}",
887
        "RU" => "\d{6}",
888
        "SA" => "\d{5}",
889
        "SE" => "^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$",
890
        "SG" => "\d{6}",
891
        "SH" => "(ASCN|STHL) 1ZZ",
892
        "SI" => "\d{4}",
893
        "SJ" => "\d{4}",
894
        "SK" => "\d{3}[ ]?\d{2}",
895
        "SM" => "4789\d",
896
        "SN" => "\d{5}",
897
        "SO" => "\d{5}",
898
        "SZ" => "[HLMS]\d{3}",
899
        "TC" => "TKCA 1ZZ",
900
        "TH" => "\d{5}",
901
        "TJ" => "\d{6}",
902
        "TM" => "\d{6}",
903
        "TN" => "\d{4}",
904
        "TR" => "\d{5}",
905
        "TW" => "\d{3}(\d{2})?",
906
        "UA" => "\d{5}",
907
        "UK" => "^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$",
908
        "US" => "^\d{5}([\-]?\d{4})?$",
909
        "UY" => "\d{5}",
910
        "UZ" => "\d{6}",
911
        "VA" => "00120",
912
        "VE" => "\d{4}",
913
        "VI" => "008(([0-4]\d)|(5[01]))([ \-]\d{4})?",
914
        "WF" => "986\d{2}",
915
        "YT" => "976\d{2}",
916
        "YU" => "\d{5}",
917
        "ZA" => "\d{4}",
918
        "ZM" => "\d{5}"
919
    );
920
921
    if ( ! isset ( $zip_regex[ $country_code ] ) || preg_match( "/" . $zip_regex[ $country_code ] . "/i", $zip ) )
922
        $ret = true;
923
924
    return apply_filters( 'wpinv_is_zip_valid', $ret, $zip, $country_code );
925
}
926
927
function wpinv_checkout_validate_agree_to_terms() {
928
    // Validate agree to terms
929
    if ( ! isset( $_POST['wpi_agree_to_terms'] ) || $_POST['wpi_agree_to_terms'] != 1 ) {
930
        // User did not agree
931
        wpinv_set_error( 'agree_to_terms', apply_filters( 'wpinv_agree_to_terms_text', __( 'You must agree to the terms of use', 'invoicing' ) ) );
932
    }
933
}
934
935
function wpinv_checkout_validate_logged_in_user() {
936
    $user_ID = get_current_user_id();
937
    
938
    $valid_user_data = array(
939
        // Assume there will be errors
940
        'user_id' => -1
941
    );
942
    
943
    // Verify there is a user_ID
944
    if ( $user_ID > 0 ) {
945
        // Get the logged in user data
946
        $user_data = get_userdata( $user_ID );
947
        $required_fields  = wpinv_checkout_required_fields();
948
949
        // Loop through required fields and show error messages
950
         if ( !empty( $required_fields ) ) {
951
            foreach ( $required_fields as $field_name => $value ) {
952
                if ( in_array( $value, $required_fields ) && empty( $_POST[ 'wpinv_' . $field_name ] ) ) {
953
                    wpinv_set_error( $value['error_id'], $value['error_message'] );
954
                }
955
            }
956
        }
957
958
        // Verify data
959
        if ( $user_data ) {
960
            // Collected logged in user data
961
            $valid_user_data = array(
962
                'user_id'     => $user_ID,
963
                'email'       => isset( $_POST['wpinv_email'] ) ? sanitize_email( $_POST['wpinv_email'] ) : $user_data->user_email,
964
                'first_name'  => isset( $_POST['wpinv_first_name'] ) && ! empty( $_POST['wpinv_first_name'] ) ? sanitize_text_field( $_POST['wpinv_first_name'] ) : $user_data->first_name,
965
                'last_name'   => isset( $_POST['wpinv_last_name'] ) && ! empty( $_POST['wpinv_last_name']  ) ? sanitize_text_field( $_POST['wpinv_last_name']  ) : $user_data->last_name,
966
            );
967
968
            if ( !empty( $_POST[ 'wpinv_email' ] ) && !is_email( $_POST[ 'wpinv_email' ] ) ) {
969
                wpinv_set_error( 'invalid_email', __( 'Please enter a valid email address', 'invoicing' ) );
970
            }
971
        } else {
972
            // Set invalid user error
973
            wpinv_set_error( 'invalid_user', __( 'The user billing information is invalid', 'invoicing' ) );
974
        }
975
    }
976
977
    // Return user data
978
    return $valid_user_data;
979
}
980
981
function wpinv_checkout_form_get_user( $valid_data = array() ) {
982
    // Initialize user
983
    $user    = false;
984
    $is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
0 ignored issues
show
Unused Code introduced by
$is_ajax is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
985
986
    /*if ( $is_ajax ) {
987
        // Do not create or login the user during the ajax submission (check for errors only)
988
        return true;
989
    } else */if ( is_user_logged_in() ) {
990
        // Set the valid user as the logged in collected data
991
        $user = $valid_data['logged_in_user'];
992
    }
993
994
    // Verify we have an user
995
    if ( false === $user || empty( $user ) ) {
996
        // Return false
997
        return false;
998
    }
999
    
1000
    $address_fields = array(
1001
        'first_name',
1002
        'last_name',
1003
        'company',
1004
        'vat_number',
1005
        ///'email',
1006
        'phone',
1007
        'address',
1008
        'city',
1009
        'state',
1010
        'country',
1011
        'zip',
1012
    );
1013
    
1014
    foreach ( $address_fields as $field ) {
1015
        $user[$field]  = !empty( $_POST['wpinv_' . $field] ) ? sanitize_text_field( $_POST['wpinv_' . $field] ) : false;
1016
        
1017
        if ( !empty( $user['user_id'] ) ) {
1018
            update_user_meta( $user['user_id'], '_wpinv_' . $field, $user[$field] );
1019
        }
1020
    }
1021
1022
    // Return valid user
1023
    return $user;
1024
}
1025
1026
function wpinv_set_checkout_session( $invoice_data = array() ) {
1027
    global $wpi_session;
1028
    
1029
    return $wpi_session->set( 'wpinv_checkout', $invoice_data );
1030
}
1031
1032
function wpinv_get_checkout_session() {
1033
	global $wpi_session;
1034
    
1035
    return $wpi_session->get( 'wpinv_checkout' );
1036
}
1037
1038
function wpinv_empty_cart() {
1039
    global $wpi_session;
1040
1041
    // Remove cart contents
1042
    $wpi_session->set( 'wpinv_checkout', NULL );
1043
1044
    // Remove all cart fees
1045
    $wpi_session->set( 'wpi_cart_fees', NULL );
1046
1047
    do_action( 'wpinv_empty_cart' );
1048
}
1049
1050
function wpinv_process_checkout() {
1051
    global $wpinv_euvat, $wpi_checkout_id;
1052
    
1053
    wpinv_clear_errors();
1054
    
1055
    $invoice = wpinv_get_invoice_cart();
1056
    
1057
    $wpi_checkout_id = $invoice->ID;
1058
    
1059
    do_action( 'wpinv_pre_process_checkout' );
1060
    
1061
    if ( !wpinv_get_cart_contents() ) { // Make sure the cart isn't empty
1062
        $valid_data = false;
1063
        wpinv_set_error( 'empty_cart', __( 'Your cart is empty', 'invoicing' ) );
1064
    } else {
1065
        // Validate the form $_POST data
1066
        $valid_data = wpinv_validate_checkout_fields();
1067
        
1068
        // Allow themes and plugins to hook to errors
1069
        do_action( 'wpinv_checkout_error_checks', $valid_data, $_POST );
1070
    }
1071
    
1072
    $is_ajax    = defined( 'DOING_AJAX' ) && DOING_AJAX;
1073
    
1074
    // Validate the user
1075
    $user = wpinv_checkout_form_get_user( $valid_data );
0 ignored issues
show
Security Bug introduced by
It seems like $valid_data can also be of type false; however, wpinv_checkout_form_get_user() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
1076
1077
    // Let extensions validate fields after user is logged in if user has used login/registration form
1078
    do_action( 'wpinv_checkout_user_error_checks', $user, $valid_data, $_POST );
1079
    
1080
    if ( false === $valid_data || wpinv_get_errors() || ! $user ) {
1081
        if ( $is_ajax ) {
1082
            do_action( 'wpinv_ajax_checkout_errors' );
1083
            die();
1084
        } else {
1085
            return false;
1086
        }
1087
    }
1088
1089
    if ( $is_ajax ) {
1090
        // Save address fields.
1091
        $address_fields = array( 'first_name', 'last_name', 'phone', 'address', 'city', 'country', 'state', 'zip', 'company' );
1092 View Code Duplication
        foreach ( $address_fields as $field ) {
1093
            if ( isset( $user[$field] ) ) {
1094
                $invoice->set( $field, $user[$field] );
1095
            }
1096
            
1097
            $invoice->save();
1098
        }
1099
1100
        $response['success']            = true;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1101
        $response['data']['subtotal']   = $invoice->get_subtotal();
1102
        $response['data']['subtotalf']  = $invoice->get_subtotal( true );
1103
        $response['data']['discount']   = $invoice->get_discount();
1104
        $response['data']['discountf']  = $invoice->get_discount( true );
1105
        $response['data']['tax']        = $invoice->get_tax();
1106
        $response['data']['taxf']       = $invoice->get_tax( true );
1107
        $response['data']['total']      = $invoice->get_total();
1108
        $response['data']['totalf']     = $invoice->get_total( true );
1109
        
1110
        wp_send_json( $response );
1111
    }
1112
    
1113
    $user_info = array(
1114
        'user_id'        => $user['user_id'],
1115
        'first_name'     => $user['first_name'],
1116
        'last_name'      => $user['last_name'],
1117
        'email'          => $user['email'],
1118
        'company'        => $user['company'],
1119
        'phone'          => $user['phone'],
1120
        'address'        => $user['address'],
1121
        'city'           => $user['city'],
1122
        'country'        => $user['country'],
1123
        'state'          => $user['state'],
1124
        'zip'            => $user['zip'],
1125
    );
1126
    
1127
    $cart_items = wpinv_get_cart_contents();
1128
    $discounts  = wpinv_get_cart_discounts();
1129
    
1130
    // Setup invoice information
1131
    $invoice_data = array(
1132
        'invoice_id'        => !empty( $invoice ) ? $invoice->ID : 0,
1133
        'items'             => $cart_items,
1134
        'cart_discounts'    => $discounts,
1135
        'fees'              => wpinv_get_cart_fees(),        // Any arbitrary fees that have been added to the cart
1136
        'subtotal'          => wpinv_get_cart_subtotal( $cart_items ),    // Amount before taxes and discounts
1137
        'discount'          => wpinv_get_cart_items_discount_amount( $cart_items, $discounts ), // Discounted amount
1138
        'tax'               => wpinv_get_cart_tax( $cart_items ),               // Taxed amount
1139
        'price'             => wpinv_get_cart_total( $cart_items, $discounts ),    // Amount after taxes
1140
        'invoice_key'       => $invoice->get_key() ? $invoice->get_key() : $invoice->generate_key(),
1141
        'user_email'        => $user['email'],
1142
        'date'              => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
1143
        'user_info'         => stripslashes_deep( $user_info ),
1144
        'post_data'         => $_POST,
1145
        'cart_details'      => $cart_items,
1146
        'gateway'           => $valid_data['gateway'],
1147
        'card_info'         => $valid_data['cc_info']
1148
    );
1149
    
1150
    $vat_info   = $wpinv_euvat->current_vat_data();
1151
    if ( is_array( $vat_info ) ) {
1152
        $invoice_data['user_info']['vat_number']        = $vat_info['number'];
1153
        $invoice_data['user_info']['vat_rate']          = wpinv_get_tax_rate($invoice_data['user_info']['country'], $invoice_data['user_info']['state']);
1154
        $invoice_data['user_info']['adddress_confirmed']    = isset($vat_info['adddress_confirmed']) ? $vat_info['adddress_confirmed'] : false;
1155
1156
        // Add the VAT rate to each item in the cart
1157
        foreach( $invoice_data['cart_details'] as $key => $item_data) {
1158
            $rate = wpinv_get_tax_rate($invoice_data['user_info']['country'], $invoice_data['user_info']['state'], $item_data['id']);
1159
            $invoice_data['cart_details'][$key]['vat_rate'] = round( $rate, 3 );
1160
        }
1161
    }
1162
    
1163
    // Save vat fields.
1164
    $address_fields = array( 'vat_number', 'vat_rate', 'adddress_confirmed' );
1165 View Code Duplication
    foreach ( $address_fields as $field ) {
1166
        if ( isset( $invoice_data['user_info'][$field] ) ) {
1167
            $invoice->set( $field, $invoice_data['user_info'][$field] );
1168
        }
1169
        
1170
        $invoice->save();
1171
    }
1172
1173
    // Add the user data for hooks
1174
    $valid_data['user'] = $user;
1175
    
1176
    // Allow themes and plugins to hook before the gateway
1177
    do_action( 'wpinv_checkout_before_gateway', $_POST, $user_info, $valid_data );
1178
    
1179
    // If the total amount in the cart is 0, send to the manual gateway. This emulates a free invoice
1180
    if ( !$invoice_data['price'] ) {
1181
        // Revert to manual
1182
        $invoice_data['gateway'] = 'manual';
1183
        $_POST['wpi-gateway'] = 'manual';
1184
    }
1185
    
1186
    // Allow the invoice data to be modified before it is sent to the gateway
1187
    $invoice_data = apply_filters( 'wpinv_data_before_gateway', $invoice_data, $valid_data );
1188
    
1189
    // Setup the data we're storing in the purchase session
1190
    $session_data = $invoice_data;
1191
    // Make sure credit card numbers are never stored in sessions
1192
    if ( !empty( $session_data['card_info']['card_number'] ) ) {
1193
        unset( $session_data['card_info']['card_number'] );
1194
    }
1195
    
1196
    // Used for showing item links to non logged-in users after purchase, and for other plugins needing purchase data.
1197
    wpinv_set_checkout_session( $invoice_data );
1198
    
1199
    // Set gateway
1200
    $invoice->update_meta( '_wpinv_gateway', $invoice_data['gateway'] );
1201
    $invoice->update_meta( '_wpinv_mode', ( wpinv_is_test_mode( $invoice_data['gateway'] ) ? 'test' : 'live' ) );
1202
    $invoice->update_meta( '_wpinv_checkout', true );
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1203
    
1204
    do_action( 'wpinv_checkout_before_send_to_gateway', $invoice, $invoice_data );
1205
1206
    // Send info to the gateway for payment processing
1207
    wpinv_send_to_gateway( $invoice_data['gateway'], $invoice_data );
1208
    die();
1209
}
1210
add_action( 'wpinv_payment', 'wpinv_process_checkout' );
1211
1212
function wpinv_get_invoices( $args ) {
1213
    $args = wp_parse_args( $args, array(
1214
        'status'   => array_keys( wpinv_get_invoice_statuses() ),
1215
        'type'     => 'wpi_invoice',
1216
        'parent'   => null,
1217
        'user'     => null,
1218
        'email'    => '',
1219
        'limit'    => get_option( 'posts_per_page' ),
1220
        'offset'   => null,
1221
        'page'     => 1,
1222
        'exclude'  => array(),
1223
        'orderby'  => 'date',
1224
        'order'    => 'DESC',
1225
        'return'   => 'objects',
1226
        'paginate' => false,
1227
    ) );
1228
    
1229
    // Handle some BW compatibility arg names where wp_query args differ in naming.
1230
    $map_legacy = array(
1231
        'numberposts'    => 'limit',
1232
        'post_type'      => 'type',
1233
        'post_status'    => 'status',
1234
        'post_parent'    => 'parent',
1235
        'author'         => 'user',
1236
        'posts_per_page' => 'limit',
1237
        'paged'          => 'page',
1238
    );
1239
1240
    foreach ( $map_legacy as $from => $to ) {
1241
        if ( isset( $args[ $from ] ) ) {
1242
            $args[ $to ] = $args[ $from ];
1243
        }
1244
    }
1245
    
1246
    if ( get_query_var( 'paged' ) )
1247
        $args['page'] = get_query_var('paged');
1248
    else if ( get_query_var( 'page' ) )
1249
        $args['page'] = get_query_var( 'page' );
1250
    else if ( !empty( $args[ 'page' ] ) )
1251
        $args['page'] = $args[ 'page' ];
1252
    else
1253
        $args['page'] = 1;
1254
1255
    /**
1256
     * Generate WP_Query args. This logic will change if orders are moved to
1257
     * custom tables in the future.
1258
     */
1259
    $wp_query_args = array(
1260
        'post_type'      => 'wpi_invoice',
1261
        'post_status'    => $args['status'],
1262
        'posts_per_page' => $args['limit'],
1263
        'meta_query'     => array(),
1264
        'date_query'     => !empty( $args['date_query'] ) ? $args['date_query'] : array(),
1265
        'fields'         => 'ids',
1266
        'orderby'        => $args['orderby'],
1267
        'order'          => $args['order'],
1268
    );
1269
    
1270
    if ( !empty( $args['user'] ) ) {
1271
        $wp_query_args['author'] = absint( $args['user'] );
1272
    }
1273
1274
    if ( ! is_null( $args['parent'] ) ) {
1275
        $wp_query_args['post_parent'] = absint( $args['parent'] );
1276
    }
1277
1278
    if ( ! is_null( $args['offset'] ) ) {
1279
        $wp_query_args['offset'] = absint( $args['offset'] );
1280
    } else {
1281
        $wp_query_args['paged'] = absint( $args['page'] );
1282
    }
1283
1284
    if ( ! empty( $args['exclude'] ) ) {
1285
        $wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
1286
    }
1287
1288
    if ( ! $args['paginate' ] ) {
1289
        $wp_query_args['no_found_rows'] = true;
1290
    }
1291
1292
    // Get results.
1293
    $invoices = new WP_Query( $wp_query_args );
1294
1295
    if ( 'objects' === $args['return'] ) {
1296
        $return = array_map( 'wpinv_get_invoice', $invoices->posts );
1297
    } elseif ( 'self' === $args['return'] ) {
1298
        return $invoices;
1299
    } else {
1300
        $return = $invoices->posts;
1301
    }
1302
1303
    if ( $args['paginate' ] ) {
1304
        return (object) array(
1305
            'invoices'      => $return,
1306
            'total'         => $invoices->found_posts,
1307
            'max_num_pages' => $invoices->max_num_pages,
1308
        );
1309
    } else {
1310
        return $return;
1311
    }
1312
}
1313
1314
function wpinv_get_user_invoices_columns() {
1315
    $columns = array(
1316
            'invoice-number'  => array( 'title' => __( 'ID', 'invoicing' ), 'class' => 'text-left' ),
1317
            'invoice-date'    => array( 'title' => __( 'Date', 'invoicing' ), 'class' => 'text-left' ),
1318
            'invoice-status'  => array( 'title' => __( 'Status', 'invoicing' ), 'class' => 'text-center' ),
1319
            'invoice-total'   => array( 'title' => __( 'Total', 'invoicing' ), 'class' => 'text-right' ),
1320
            'invoice-actions' => array( 'title' => '&nbsp;', 'class' => 'text-center' ),
1321
        );
1322
1323
    return apply_filters( 'wpinv_user_invoices_columns', $columns );
1324
}
1325
1326
function wpinv_payment_receipt( $atts, $content = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $content is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1327
    global $wpinv_receipt_args;
1328
1329
    $wpinv_receipt_args = shortcode_atts( array(
1330
        'error'           => __( 'Sorry, trouble retrieving payment receipt.', 'invoicing' ),
1331
        'price'           => true,
1332
        'discount'        => true,
1333
        'items'           => true,
1334
        'date'            => true,
1335
        'notes'           => true,
1336
        'invoice_key'     => false,
1337
        'payment_method'  => true,
1338
        'invoice_id'      => true
1339
    ), $atts, 'wpinv_receipt' );
1340
1341
    $session = wpinv_get_checkout_session();
1342
    if ( isset( $_GET['invoice_key'] ) ) {
1343
        $invoice_key = urldecode( $_GET['invoice_key'] );
1344
    } else if ( $session && isset( $session['invoice_key'] ) ) {
1345
        $invoice_key = $session['invoice_key'];
1346
    } elseif ( isset( $wpinv_receipt_args['invoice_key'] ) && $wpinv_receipt_args['invoice_key'] ) {
1347
        $invoice_key = $wpinv_receipt_args['invoice_key'];
1348
    } else if ( isset( $_GET['invoice-id'] ) ) {
1349
        $invoice_key = wpinv_get_payment_key( (int)$_GET['invoice-id'] );
1350
    }
1351
1352
    // No key found
1353
    if ( ! isset( $invoice_key ) ) {
1354
        return '<p class="alert alert-error">' . $wpinv_receipt_args['error'] . '</p>';
1355
    }
1356
1357
    $invoice_id    = wpinv_get_invoice_id_by_key( $invoice_key );
0 ignored issues
show
Unused Code introduced by
$invoice_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1358
    $user_can_view = wpinv_can_view_receipt( $invoice_key );
1359 View Code Duplication
    if ( $user_can_view && isset( $_GET['invoice-id'] ) ) {
1360
        $invoice_id     = (int)$_GET['invoice-id'];
0 ignored issues
show
Unused Code introduced by
$invoice_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1361
        $user_can_view  = $invoice_key == wpinv_get_payment_key( (int)$_GET['invoice-id'] ) ? true : false;
1362
    }
1363
1364
    // Key was provided, but user is logged out. Offer them the ability to login and view the receipt
1365
    if ( ! $user_can_view && ! empty( $invoice_key ) && ! is_user_logged_in() ) {
1366
        // login redirect
1367
        return '<p class="alert alert-error">' . __( 'You are not allowed to access this section', 'invoicing' ) . '</p>';
1368
    }
1369
1370
    if ( ! apply_filters( 'wpinv_user_can_view_receipt', $user_can_view, $wpinv_receipt_args ) ) {
1371
        return '<p class="alert alert-error">' . $wpinv_receipt_args['error'] . '</p>';
1372
    }
1373
1374
    ob_start();
1375
1376
    wpinv_get_template_part( 'wpinv-invoice-receipt' );
1377
1378
    $display = ob_get_clean();
1379
1380
    return $display;
1381
}
1382
1383 View Code Duplication
function wpinv_get_invoice_id_by_key( $key ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1384
	global $wpdb;
1385
1386
	$invoice_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wpinv_key' AND meta_value = %s LIMIT 1", $key ) );
1387
1388
	if ( $invoice_id != NULL )
1389
		return $invoice_id;
1390
1391
	return 0;
1392
}
1393
1394
function wpinv_can_view_receipt( $invoice_key = '' ) {
1395
	$return = false;
1396
1397
	if ( empty( $invoice_key ) ) {
1398
		return $return;
1399
	}
1400
1401
	global $wpinv_receipt_args;
1402
1403
	$wpinv_receipt_args['id'] = wpinv_get_invoice_id_by_key( $invoice_key );
1404
	if ( isset( $_GET['invoice-id'] ) ) {
1405
		$wpinv_receipt_args['id'] = $invoice_key == wpinv_get_payment_key( (int)$_GET['invoice-id'] ) ? (int)$_GET['invoice-id'] : 0;
1406
	}
1407
1408
	$user_id = (int) wpinv_get_user_id( $wpinv_receipt_args['id'] );
1409
    $invoice_meta = wpinv_get_invoice_meta( $wpinv_receipt_args['id'] );
1410
1411
	if ( is_user_logged_in() ) {
1412
		if ( $user_id === (int) get_current_user_id() ) {
1413
			$return = true;
1414
		}
1415
	}
1416
1417
	$session = wpinv_get_checkout_session();
1418
	if ( ! empty( $session ) && ! is_user_logged_in() ) {
1419
		if ( $session['invoice_key'] === $invoice_meta['key'] ) {
1420
			$return = true;
1421
		}
1422
	}
1423
1424
	return (bool) apply_filters( 'wpinv_can_view_receipt', $return, $invoice_key );
1425
}
1426
1427
function wpinv_pay_for_invoice() {
1428
    global $wpinv_euvat;
1429
    
1430
    if ( isset( $_GET['invoice_key'] ) ) {
1431
        $checkout_uri   = wpinv_get_checkout_uri();
1432
        $invoice_key    = sanitize_text_field( $_GET['invoice_key'] );
1433
        
1434
        if ( empty( $invoice_key ) ) {
1435
            wpinv_set_error( 'invalid_invoice', __( 'Invoice not found', 'invoicing' ) );
1436
            wp_redirect( $checkout_uri );
1437
            wpinv_die();
1438
        }
1439
        
1440
        do_action( 'wpinv_check_pay_for_invoice', $invoice_key );
1441
1442
        $invoice_id    = wpinv_get_invoice_id_by_key( $invoice_key );
1443
        $user_can_view = wpinv_can_view_receipt( $invoice_key );
1444 View Code Duplication
        if ( $user_can_view && isset( $_GET['invoice-id'] ) ) {
1445
            $invoice_id     = (int)$_GET['invoice-id'];
1446
            $user_can_view  = $invoice_key == wpinv_get_payment_key( (int)$_GET['invoice-id'] ) ? true : false;
1447
        }
1448
        
1449
        if ( $invoice_id && $user_can_view && ( $invoice = wpinv_get_invoice( $invoice_id ) ) ) {
1450
            if ( $invoice->needs_payment() ) {
1451
                $data                   = array();
1452
                $data['invoice_id']     = $invoice_id;
1453
                $data['cart_discounts'] = $invoice->get_discounts( true );
1454
                
1455
                wpinv_set_checkout_session( $data );
1456
                
1457
                if ( wpinv_get_option( 'vat_ip_country_default' ) ) {
1458
                    $_POST['country']   = $wpinv_euvat->get_country_by_ip();
1459
                    $_POST['state']     = $_POST['country'] == $invoice->country ? $invoice->state : '';
1460
                    
1461
                    wpinv_recalculate_tax( true );
1462
                }
1463
                
1464
            } else {
1465
                $checkout_uri = $invoice->get_view_url();
1466
            }
1467
        } else {
1468
            wpinv_set_error( 'invalid_invoice', __( 'You are not allowed to view this invoice', 'invoicing' ) );
1469
            
1470
            $checkout_uri = is_user_logged_in() ? wpinv_get_history_page_uri() : wp_login_url( get_permalink() );
1471
        }
1472
        
1473
        wp_redirect( $checkout_uri );
1474
        wpinv_die();
1475
    }
1476
}
1477
add_action( 'wpinv_pay_for_invoice', 'wpinv_pay_for_invoice' );
1478
1479
function wpinv_handle_pay_via_invoice_link( $invoice_key ) {
1480
    if ( !empty( $invoice_key ) && !empty( $_REQUEST['_wpipay'] ) && !is_user_logged_in() && $invoice_id = wpinv_get_invoice_id_by_key( $invoice_key ) ) {
1481
        if ( $invoice = wpinv_get_invoice( $invoice_id ) ) {
1482
            $user_id = $invoice->get_user_id();
1483
            $secret = sanitize_text_field( $_GET['_wpipay'] );
1484
            
1485 View Code Duplication
            if ( $secret === md5( $user_id . '::' . $invoice->get_email() . '::' . $invoice_key ) ) { // valid invoice link
1486
                $redirect_to = remove_query_arg( '_wpipay', get_permalink() );
1487
                
1488
                wpinv_guest_redirect( $redirect_to, $user_id );
1489
                wpinv_die();
1490
            }
1491
        }
1492
    }
1493
}
1494
add_action( 'wpinv_check_pay_for_invoice', 'wpinv_handle_pay_via_invoice_link' );
1495
1496
function wpinv_set_payment_transaction_id( $invoice_id = 0, $transaction_id = '' ) {
1497
    $invoice_id = is_object( $invoice_id ) && !empty( $invoice_id->ID ) ? $invoice_id : $invoice_id;
1498
    
1499
    if ( empty( $invoice_id ) && $invoice_id > 0 ) {
1500
        return false;
1501
    }
1502
    
1503
    if ( empty( $transaction_id ) ) {
1504
        $transaction_id = $invoice_id;
1505
    }
1506
1507
    $transaction_id = apply_filters( 'wpinv_set_payment_transaction_id', $transaction_id, $invoice_id );
1508
    
1509
    return wpinv_update_invoice_meta( $invoice_id, '_wpinv_transaction_id', $transaction_id );
1510
}
1511
1512
function wpinv_invoice_status_label( $status, $status_display = '' ) {
1513
    if ( empty( $status_display ) ) {
1514
        $status_display = wpinv_status_nicename( $status );
1515
    }
1516
    
1517
    switch ( $status ) {
1518
        case 'publish' :
1519
        case 'wpi-renewal' :
1520
            $class = 'label-success';
1521
        break;
1522
        case 'pending' :
1523
            $class = 'label-primary';
1524
        break;
1525
        case 'wpi-processing' :
1526
            $class = 'label-warning';
1527
        break;
1528
        case 'wpi-onhold' :
1529
            $class = 'label-info';
1530
        break;
1531
        case 'wpi-cancelled' :
1532
        case 'wpi-failed' :
1533
            $class = 'label-danger';
1534
        break;
1535
        default:
1536
            $class = 'label-default';
1537
        break;
1538
    }
1539
    
1540
    $label = '<span class="label label-inv-' . $status . ' ' . $class . '">' . $status_display . '</span>';
1541
    
1542
    return apply_filters( 'wpinv_invoice_status_label', $label, $status, $status_display );
1543
}
1544
1545
function wpinv_format_invoice_number( $number ) {
1546
    $padd  = wpinv_get_option( 'invoice_number_padd' );
1547
    
1548
    // TODO maintain old invoice numbers if invoice number settings not saved. Should be removed before stable release.
1549
    if ( $padd === '' || $padd === false || $padd === NULL ) {
1550
        return wp_sprintf( __( 'WPINV-%d', 'invoicing' ), $number );
1551
    }
1552
    
1553
    $prefix  = wpinv_get_option( 'invoice_number_prefix' );
1554
    $postfix = wpinv_get_option( 'invoice_number_postfix' );
1555
    
1556
    $padd = absint( $padd );
1557
    $formatted_number = absint( $number );
1558
    
1559
    if ( $padd > 0 ) {
1560
        $formatted_number = zeroise( $formatted_number, $padd );
1561
    }    
1562
1563
    $formatted_number = $prefix . $formatted_number . $postfix;
1564
1565
    return apply_filters( 'wpinv_format_invoice_number', $formatted_number, $number, $prefix, $postfix, $padd );
1566
}