Passed
Pull Request — master (#375)
by Brian
104:55
created

WPInv_Ajax::payment_form_validate_discount()   F

Complexity

Conditions 31
Paths 318

Size

Total Lines 161
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 31
eloc 82
nc 318
nop 1
dl 0
loc 161
rs 1.8583
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
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
class WPInv_Ajax {
15
    public static function init() {
16
        add_action( 'init', array( __CLASS__, 'define_ajax' ), 0 );
17
        add_action( 'template_redirect', array( __CLASS__, 'do_wpinv_ajax' ), 0 );
18
        self::add_ajax_events();
19
    }
20
21
    public static function define_ajax() {
22
        if ( !empty( $_GET['wpinv-ajax'] ) ) {
23
            if ( ! defined( 'DOING_AJAX' ) ) {
24
                define( 'DOING_AJAX', true );
25
            }
26
            if ( ! defined( 'WC_DOING_AJAX' ) ) {
27
                define( 'WC_DOING_AJAX', true );
28
            }
29
            // Turn off display_errors during AJAX events to prevent malformed JSON
30
            if ( ! WP_DEBUG || ( WP_DEBUG && ! WP_DEBUG_DISPLAY ) ) {
31
                /** @scrutinizer ignore-unhandled */ @ini_set( 'display_errors', 0 );
32
            }
33
            $GLOBALS['wpdb']->hide_errors();
34
        }
35
    }
36
    
37
    public static function do_wpinv_ajax() {
38
        global $wp_query;
39
40
        if ( !empty( $_GET['wpinv-ajax'] ) ) {
41
            $wp_query->set( 'wpinv-ajax', sanitize_text_field( $_GET['wpinv-ajax'] ) );
42
        }
43
44
        if ( $action = $wp_query->get( 'wpinv-ajax' ) ) {
45
            self::wpinv_ajax_headers();
46
            do_action( 'wpinv_ajax_' . sanitize_text_field( $action ) );
47
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
48
        }
49
    }
50
    
51
    private static function wpinv_ajax_headers() {
52
        send_origin_headers();
53
        /** @scrutinizer ignore-unhandled */ @header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
54
        /** @scrutinizer ignore-unhandled */ @header( 'X-Robots-Tag: noindex' );
55
        send_nosniff_header();
56
        nocache_headers();
57
        status_header( 200 );
58
    }
59
    
60
    public static function add_ajax_events() {
61
        $ajax_events = array(
62
            'add_note' => false,
63
            'delete_note' => false,
64
            'get_states_field' => true,
65
            'checkout' => false,
66
            'payment_form'     => true,
67
            'get_payment_form' => true,
68
            'get_payment_form_states_field' => true,
69
            'add_invoice_item' => false,
70
            'remove_invoice_item' => false,
71
            'create_invoice_item' => false,
72
            'get_billing_details' => false,
73
            'admin_recalculate_totals' => false,
74
            'admin_apply_discount' => false,
75
            'admin_remove_discount' => false,
76
            'check_email' => false,
77
            'run_tool' => false,
78
            'apply_discount' => true,
79
            'remove_discount' => true,
80
            'buy_items' => true,
81
            'payment_form_refresh_prices' => true,
82
        );
83
84
        foreach ( $ajax_events as $ajax_event => $nopriv ) {
85
            add_action( 'wp_ajax_wpinv_' . $ajax_event, array( __CLASS__, $ajax_event ) );
86
            add_action( 'wp_ajax_getpaid_' . $ajax_event, array( __CLASS__, $ajax_event ) );
87
            
88
            if ( !defined( 'WPI_AJAX_' . strtoupper( $nopriv ) ) ) {
89
                define( 'WPI_AJAX_' . strtoupper( $nopriv ), 1 );
90
            }
91
92
            if ( $nopriv ) {
93
                add_action( 'wp_ajax_nopriv_wpinv_' . $ajax_event, array( __CLASS__, $ajax_event ) );
94
                add_action( 'wp_ajax_nopriv_getpaid_' . $ajax_event, array( __CLASS__, $ajax_event ) );
95
96
                add_action( 'wpinv_ajax_' . $ajax_event, array( __CLASS__, $ajax_event ) );
97
            }
98
        }
99
    }
100
    
101
    public static function add_note() {
102
        check_ajax_referer( 'add-invoice-note', '_nonce' );
103
104
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
105
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
106
        }
107
108
        $post_id   = absint( $_POST['post_id'] );
109
        $note      = wp_kses_post( trim( stripslashes( $_POST['note'] ) ) );
110
        $note_type = sanitize_text_field( $_POST['note_type'] );
111
112
        $is_customer_note = $note_type == 'customer' ? 1 : 0;
113
114
        if ( $post_id > 0 ) {
115
            $note_id = wpinv_insert_payment_note( $post_id, $note, $is_customer_note );
116
117
            if ( $note_id > 0 && !is_wp_error( $note_id ) ) {
118
                wpinv_get_invoice_note_line_item( $note_id );
119
            }
120
        }
121
122
        die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
123
    }
124
125
    public static function delete_note() {
126
        check_ajax_referer( 'delete-invoice-note', '_nonce' );
127
128
        if ( !wpinv_current_user_can_manage_invoicing() ) {
129
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
130
        }
131
132
        $note_id = (int)$_POST['note_id'];
133
134
        if ( $note_id > 0 ) {
135
            wp_delete_comment( $note_id, true );
136
        }
137
138
        die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
139
    }
140
    
141
    public static function get_states_field() {
142
        echo wpinv_get_states_field();
143
        
144
        die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
145
    }
146
    
147
    public static function checkout() {
148
        if ( ! defined( 'WPINV_CHECKOUT' ) ) {
149
            define( 'WPINV_CHECKOUT', true );
150
        }
151
152
        wpinv_process_checkout();
153
        die(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
154
    }
155
    
156
    public static function add_invoice_item() {
157
        global $wpi_userID, $wpinv_ip_address_country;
158
        check_ajax_referer( 'invoice-item', '_nonce' );
159
        if ( !wpinv_current_user_can_manage_invoicing() ) {
160
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
161
        }
162
        
163
        $item_id    = sanitize_text_field( $_POST['item_id'] );
164
        $invoice_id = absint( $_POST['invoice_id'] );
165
        
166
        if ( !is_numeric( $invoice_id ) || !is_numeric( $item_id ) ) {
167
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
168
        }
169
        
170
        $invoice    = wpinv_get_invoice( $invoice_id );
171
        if ( empty( $invoice ) ) {
172
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
173
        }
174
        
175
        if ( $invoice->is_paid() || $invoice->is_refunded() ) {
176
            die(); // Don't allow modify items for paid invoice.
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
177
        }
178
        
179
        if ( !empty( $_POST['user_id'] ) ) {
180
            $wpi_userID = absint( $_POST['user_id'] ); 
181
        }
182
183
        $item = new WPInv_Item( $item_id );
184
        if ( !( !empty( $item ) && $item->post_type == 'wpi_item' ) ) {
185
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
186
        }
187
        
188
        // Validate item before adding to invoice because recurring item must be paid individually.
189
        if ( !empty( $invoice->cart_details ) ) {
190
            $valid = true;
191
            
192
            if ( $recurring_item = $invoice->get_recurring() ) {
193
                if ( $recurring_item != $item_id ) {
194
                    $valid = false;
195
                }
196
            } else if ( wpinv_is_recurring_item( $item_id ) ) {
197
                $valid = false;
198
            }
199
            
200
            if ( !$valid ) {
201
                $response               = array();
202
                $response['success']    = false;
203
                $response['msg']        = __( 'You can not add item because recurring item must be paid individually!', 'invoicing' );
204
                wp_send_json( $response );
205
            }
206
        }
207
        
208
        $checkout_session = wpinv_get_checkout_session();
209
        
210
        $data                   = array();
211
        $data['invoice_id']     = $invoice_id;
212
        $data['cart_discounts'] = $invoice->get_discounts( true );
213
        
214
        wpinv_set_checkout_session( $data );
215
        
216
        $quantity = wpinv_item_quantities_enabled() && !empty($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : 1;
217
218
        $args = array(
219
            'id'            => $item_id,
220
            'quantity'      => $quantity,
221
            'item_price'    => $item->get_price(),
222
            'custom_price'  => '',
223
            'tax'           => 0.00,
224
            'discount'      => 0,
225
            'meta'          => array(),
226
            'fees'          => array()
227
        );
228
229
        $invoice->add_item( $item_id, $args );
230
        $invoice->save();
231
        
232
        if ( empty( $_POST['country'] ) ) {
233
            $_POST['country'] = !empty($invoice->country) ? $invoice->country : wpinv_get_default_country();
234
        }
235
        if ( empty( $_POST['state'] ) ) {
236
            $_POST['state'] = $invoice->state;
237
        }
238
         
239
        $invoice->country   = sanitize_text_field( $_POST['country'] );
240
        $invoice->state     = sanitize_text_field( $_POST['state'] );
241
        
242
        $invoice->set( 'country', sanitize_text_field( $_POST['country'] ) );
243
        $invoice->set( 'state', sanitize_text_field( $_POST['state'] ) );
244
        
245
        $wpinv_ip_address_country = $invoice->country;
246
247
        $invoice->recalculate_totals(true);
248
        
249
        $response                       = array();
250
        $response['success']            = true;
251
        $response['data']['items']      = wpinv_admin_get_line_items( $invoice );
252
        $response['data']['subtotal']   = $invoice->get_subtotal();
253
        $response['data']['subtotalf']  = $invoice->get_subtotal(true);
254
        $response['data']['tax']        = $invoice->get_tax();
255
        $response['data']['taxf']       = $invoice->get_tax(true);
256
        $response['data']['discount']   = $invoice->get_discount();
257
        $response['data']['discountf']  = $invoice->get_discount(true);
258
        $response['data']['total']      = $invoice->get_total();
259
        $response['data']['totalf']     = $invoice->get_total(true);
260
        
261
        wpinv_set_checkout_session($checkout_session);
262
        
263
        wp_send_json( $response );
264
    }
265
266
267
    public static function remove_invoice_item() {
268
        global $wpi_userID, $wpinv_ip_address_country;
269
        
270
        check_ajax_referer( 'invoice-item', '_nonce' );
271
        if ( !wpinv_current_user_can_manage_invoicing() ) {
272
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
273
        }
274
        
275
        $item_id    = sanitize_text_field( $_POST['item_id'] );
276
        $invoice_id = absint( $_POST['invoice_id'] );
277
        $cart_index = isset( $_POST['index'] ) && $_POST['index'] >= 0 ? $_POST['index'] : false;
278
        
279
        if ( !is_numeric( $invoice_id ) || !is_numeric( $item_id ) ) {
280
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
281
        }
282
283
        $invoice    = wpinv_get_invoice( $invoice_id );
284
        if ( empty( $invoice ) ) {
285
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
286
        }
287
        
288
        if ( $invoice->is_paid() || $invoice->is_refunded() ) {
289
            die(); // Don't allow modify items for paid invoice.
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
290
        }
291
        
292
        if ( !empty( $_POST['user_id'] ) ) {
293
            $wpi_userID = absint( $_POST['user_id'] ); 
294
        }
295
296
        $item       = new WPInv_Item( $item_id );
297
        if ( !( !empty( $item ) && $item->post_type == 'wpi_item' ) ) {
298
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
299
        }
300
        
301
        $checkout_session = wpinv_get_checkout_session();
302
        
303
        $data                   = array();
304
        $data['invoice_id']     = $invoice_id;
305
        $data['cart_discounts'] = $invoice->get_discounts( true );
306
        
307
        wpinv_set_checkout_session( $data );
308
309
        $args = array(
310
            'id'         => $item_id,
311
            'quantity'   => 1,
312
            'cart_index' => $cart_index
313
        );
314
315
        $invoice->remove_item( $item_id, $args );
316
        $invoice->save();
317
        
318
        if ( empty( $_POST['country'] ) ) {
319
            $_POST['country'] = !empty($invoice->country) ? $invoice->country : wpinv_get_default_country();
320
        }
321
        if ( empty( $_POST['state'] ) ) {
322
            $_POST['state'] = $invoice->state;
323
        }
324
         
325
        $invoice->country   = sanitize_text_field( $_POST['country'] );
326
        $invoice->state     = sanitize_text_field( $_POST['state'] );
327
        
328
        $invoice->set( 'country', sanitize_text_field( $_POST['country'] ) );
329
        $invoice->set( 'state', sanitize_text_field( $_POST['state'] ) );
330
        
331
        $wpinv_ip_address_country = $invoice->country;
332
        
333
        $invoice->recalculate_totals(true);
334
        
335
        $response                       = array();
336
        $response['success']            = true;
337
        $response['data']['items']      = wpinv_admin_get_line_items( $invoice );
338
        $response['data']['subtotal']   = $invoice->get_subtotal();
339
        $response['data']['subtotalf']  = $invoice->get_subtotal(true);
340
        $response['data']['tax']        = $invoice->get_tax();
341
        $response['data']['taxf']       = $invoice->get_tax(true);
342
        $response['data']['discount']   = $invoice->get_discount();
343
        $response['data']['discountf']  = $invoice->get_discount(true);
344
        $response['data']['total']      = $invoice->get_total();
345
        $response['data']['totalf']     = $invoice->get_total(true);
346
        
347
        wpinv_set_checkout_session($checkout_session);
348
        
349
        wp_send_json( $response );
350
    }
351
    
352
    public static function create_invoice_item() {
353
        check_ajax_referer( 'invoice-item', '_nonce' );
354
        if ( !wpinv_current_user_can_manage_invoicing() ) {
355
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
356
        }
357
        
358
        $invoice_id = absint( $_POST['invoice_id'] );
359
360
        // Find the item
361
        if ( !is_numeric( $invoice_id ) ) {
362
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
363
        }        
364
        
365
        $invoice     = wpinv_get_invoice( $invoice_id );
366
        if ( empty( $invoice ) ) {
367
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
368
        }
369
        
370
        // Validate item before adding to invoice because recurring item must be paid individually.
371
        if ( !empty( $invoice->cart_details ) && $invoice->get_recurring() ) {
372
            $response               = array();
373
            $response['success']    = false;
374
            $response['msg']        = __( 'You can not add item because recurring item must be paid individually!', 'invoicing' );
375
            wp_send_json( $response );
376
        }        
377
        
378
        $save_item = wp_unslash( $_POST['_wpinv_quick'] );
379
        
380
        $meta               = array();
381
        $meta['type']       = !empty($save_item['type']) ? sanitize_text_field($save_item['type']) : 'custom';
382
        $meta['price']      = !empty($save_item['price']) ? wpinv_sanitize_amount( $save_item['price'] ) : 0;
383
        $meta['vat_rule']   = !empty($save_item['vat_rule']) ? sanitize_text_field($save_item['vat_rule']) : 'digital';
384
        $meta['vat_class']  = !empty($save_item['vat_class']) ? sanitize_text_field($save_item['vat_class']) : '_standard';
385
        
386
        $data                   = array();
387
        $data['post_title']     = sanitize_text_field($save_item['name']);
388
        $data['post_status']    = 'publish';
389
        $data['post_excerpt']   = ! empty( $save_item['excerpt'] ) ? wp_kses_post( $save_item['excerpt'] ) : '';
390
        $data['meta']           = $meta;
391
        
392
        $item = new WPInv_Item();
393
        $item->create( $data );
394
        
395
        if ( !empty( $item ) ) {
396
            $_POST['item_id']   = $item->ID;
397
            $_POST['qty']       = !empty($save_item['qty']) && $save_item['qty'] > 0 ? (int)$save_item['qty'] : 1;
398
            
399
            self::add_invoice_item();
400
        }
401
        die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
402
    }
403
    
404
    public static function get_billing_details() {
405
        check_ajax_referer( 'get-billing-details', '_nonce' );
406
        
407
        if ( !wpinv_current_user_can_manage_invoicing() ) {
408
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
409
        }
410
411
        $user_id            = (int)$_POST['user_id'];
412
        $billing_details    = wpinv_get_user_address($user_id);
413
        $billing_details    = apply_filters( 'wpinv_fill_billing_details', $billing_details, $user_id );
414
        
415
        if (isset($billing_details['user_id'])) {
416
            unset($billing_details['user_id']);
417
        }
418
        
419
        if (isset($billing_details['email'])) {
420
            unset($billing_details['email']);
421
        }
422
423
        $response                               = array();
424
        $response['success']                    = true;
425
        $response['data']['billing_details']    = $billing_details;
426
        
427
        wp_send_json( $response );
428
    }
429
    
430
    public static function admin_recalculate_totals() {
431
        global $wpi_userID, $wpinv_ip_address_country;
432
        
433
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
434
        if ( !wpinv_current_user_can_manage_invoicing() ) {
435
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
436
        }
437
        
438
        $invoice_id = absint( $_POST['invoice_id'] );        
439
        $invoice    = wpinv_get_invoice( $invoice_id );
440
        if ( empty( $invoice ) ) {
441
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
442
        }
443
444
        $checkout_session = wpinv_get_checkout_session();
445
446
        $data                   = array();
447
        $data['invoice_id']     = $invoice_id;
448
        $data['cart_discounts'] = $invoice->get_discounts( true );
449
450
        wpinv_set_checkout_session( $data );
451
        
452
        if ( !empty( $_POST['user_id'] ) ) {
453
            $wpi_userID = absint( $_POST['user_id'] ); 
454
        }
455
        
456
        if ( empty( $_POST['country'] ) ) {
457
            $_POST['country'] = !empty($invoice->country) ? $invoice->country : wpinv_get_default_country();
458
        }
459
460
        $disable_taxes = 0;
461
        if ( ! empty( $_POST['disable_taxes'] ) ) {
462
            $disable_taxes = 1;
463
        }
464
        $invoice->set( 'disable_taxes', $disable_taxes );
465
466
        $invoice->country = sanitize_text_field( $_POST['country'] );
467
        $invoice->set( 'country', sanitize_text_field( $_POST['country'] ) );
468
        if ( isset( $_POST['state'] ) ) {
469
            $invoice->state = sanitize_text_field( $_POST['state'] );
470
            $invoice->set( 'state', sanitize_text_field( $_POST['state'] ) );
471
        }
472
        
473
        $wpinv_ip_address_country = $invoice->country;
474
        
475
        $invoice = $invoice->recalculate_totals(true);
476
        
477
        $response                       = array();
478
        $response['success']            = true;
479
        $response['data']['items']      = wpinv_admin_get_line_items( $invoice );
480
        $response['data']['subtotal']   = $invoice->get_subtotal();
481
        $response['data']['subtotalf']  = $invoice->get_subtotal(true);
482
        $response['data']['tax']        = $invoice->get_tax();
483
        $response['data']['taxf']       = $invoice->get_tax(true);
484
        $response['data']['discount']   = $invoice->get_discount();
485
        $response['data']['discountf']  = $invoice->get_discount(true);
486
        $response['data']['total']      = $invoice->get_total();
487
        $response['data']['totalf']     = $invoice->get_total(true);
488
        
489
        wpinv_set_checkout_session($checkout_session);
490
491
        wp_send_json( $response );
492
    }
493
    
494
    public static function admin_apply_discount() {
495
        global $wpi_userID;
496
        
497
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
498
        if ( !wpinv_current_user_can_manage_invoicing() ) {
499
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
500
        }
501
        
502
        $invoice_id = absint( $_POST['invoice_id'] );
503
        $discount_code = sanitize_text_field( $_POST['code'] );
504
        if ( empty( $invoice_id ) || empty( $discount_code ) ) {
505
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
506
        }
507
        
508
        $invoice = wpinv_get_invoice( $invoice_id );
509
        if ( empty( $invoice ) || ( !empty( $invoice ) && ( $invoice->is_paid() || $invoice->is_refunded() ) ) ) {
510
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
511
        }
512
        
513
        $checkout_session = wpinv_get_checkout_session();
514
        
515
        $data                   = array();
516
        $data['invoice_id']     = $invoice_id;
517
        $data['cart_discounts'] = $invoice->get_discounts( true );
518
        
519
        wpinv_set_checkout_session( $data );
520
        
521
        $response               = array();
522
        $response['success']    = false;
523
        $response['msg']        = __( 'This discount is invalid.', 'invoicing' );
524
        $response['data']['code'] = $discount_code;
525
        
526
        if ( wpinv_is_discount_valid( $discount_code, $invoice->get_user_id() ) ) {
527
            $discounts = wpinv_set_cart_discount( $discount_code );
0 ignored issues
show
Unused Code introduced by
The assignment to $discounts is dead and can be removed.
Loading history...
528
            
529
            $response['success'] = true;
530
            $response['msg'] = __( 'Discount has been applied successfully.', 'invoicing' );
531
        }  else {
532
            $errors = wpinv_get_errors();
533
            if ( !empty( $errors['wpinv-discount-error'] ) ) {
534
                $response['msg'] = $errors['wpinv-discount-error'];
535
            }
536
            wpinv_unset_error( 'wpinv-discount-error' );
537
        }
538
        
539
        wpinv_set_checkout_session($checkout_session);
540
        
541
        wp_send_json( $response );
542
    }
543
    
544
    public static function admin_remove_discount() {
545
        global $wpi_userID;
546
        
547
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
548
        if ( !wpinv_current_user_can_manage_invoicing() ) {
549
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
550
        }
551
        
552
        $invoice_id = absint( $_POST['invoice_id'] );
553
        $discount_code = sanitize_text_field( $_POST['code'] );
554
        if ( empty( $invoice_id ) || empty( $discount_code ) ) {
555
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
556
        }
557
        
558
        $invoice = wpinv_get_invoice( $invoice_id );
559
        if ( empty( $invoice ) || ( !empty( $invoice ) && ( $invoice->is_paid() || $invoice->is_refunded() ) ) ) {
560
            die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
561
        }
562
        
563
        $checkout_session = wpinv_get_checkout_session();
564
        
565
        $data                   = array();
566
        $data['invoice_id']     = $invoice_id;
567
        $data['cart_discounts'] = $invoice->get_discounts( true );
568
        
569
        wpinv_set_checkout_session( $data );
570
        
571
        $response               = array();
572
        $response['success']    = false;
573
        $response['msg']        = NULL;
574
        
575
        $discounts  = wpinv_unset_cart_discount( $discount_code );
0 ignored issues
show
Unused Code introduced by
The assignment to $discounts is dead and can be removed.
Loading history...
576
        $response['success'] = true;
577
        $response['msg'] = __( 'Discount has been removed successfully.', 'invoicing' );
578
        
579
        wpinv_set_checkout_session($checkout_session);
580
        
581
        wp_send_json( $response );
582
    }
583
    
584
    public static function check_email() {
585
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
586
        if ( !wpinv_current_user_can_manage_invoicing() ) {
587
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
588
        }
589
        
590
        $email = sanitize_text_field( $_POST['email'] );
591
        
592
        $response = array();
593
        if ( is_email( $email ) && email_exists( $email ) && $user_data = get_user_by( 'email', $email ) ) {
594
            $user_id            = $user_data->ID;
595
            $user_login         = $user_data->user_login;
596
            $display_name       = $user_data->display_name ? $user_data->display_name : $user_login;
0 ignored issues
show
Unused Code introduced by
The assignment to $display_name is dead and can be removed.
Loading history...
597
            $billing_details    = wpinv_get_user_address($user_id);
598
            $billing_details    = apply_filters( 'wpinv_fill_billing_details', $billing_details, $user_id );
599
            
600
            if (isset($billing_details['user_id'])) {
601
                unset($billing_details['user_id']);
602
            }
603
            
604
            if (isset($billing_details['email'])) {
605
                unset($billing_details['email']);
606
            }
607
            
608
            $response['success']                    = true;
609
            $response['data']['id']                 = $user_data->ID;
610
            $response['data']['name']               = $user_data->user_email;
611
            $response['data']['billing_details']    = $billing_details;
612
        }
613
        
614
        wp_send_json( $response );
615
    }
616
    
617
    public static function run_tool() {
618
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
619
        if ( !wpinv_current_user_can_manage_invoicing() ) {
620
            die(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
621
        }
622
        
623
        $tool = sanitize_text_field( $_POST['tool'] );
624
        
625
        do_action( 'wpinv_run_tool' );
626
        
627
        if ( !empty( $tool ) ) {
628
            do_action( 'wpinv_tool_' . $tool );
629
        }
630
    }
631
    
632
    public static function apply_discount() {
633
        global $wpi_userID;
634
        
635
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
636
        
637
        $response = array();
638
        
639
        if ( isset( $_POST['code'] ) ) {
640
            $discount_code = sanitize_text_field( $_POST['code'] );
641
642
            $response['success']        = false;
643
            $response['msg']            = '';
644
            $response['data']['code']   = $discount_code;
645
            
646
            $invoice = wpinv_get_invoice_cart();
647
            if ( empty( $invoice->ID ) ) {
648
                $response['msg'] = __( 'Invalid checkout request.', 'invoicing' );
649
                wp_send_json( $response );
650
            }
651
652
            $wpi_userID = $invoice->get_user_id();
653
654
            if ( wpinv_is_discount_valid( $discount_code, $wpi_userID ) ) {
655
                $discount       = wpinv_get_discount_by_code( $discount_code );
656
                $discounts      = wpinv_set_cart_discount( $discount_code );
657
                $amount         = wpinv_format_discount_rate( wpinv_get_discount_type( $discount->ID ), wpinv_get_discount_amount( $discount->ID ) );
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
658
                $total          = wpinv_get_cart_total( null, $discounts );
0 ignored issues
show
Unused Code introduced by
The assignment to $total is dead and can be removed.
Loading history...
659
                $cart_totals    = wpinv_recalculate_tax( true );
660
            
661
                if ( !empty( $cart_totals ) ) {
662
                    $response['success']        = true;
663
                    $response['data']           = $cart_totals;
664
                    $response['data']['code']   = $discount_code;
665
                } else {
666
                    $response['success']        = false;
667
                }
668
            } else {
669
                $errors = wpinv_get_errors();
670
                $response['msg']  = $errors['wpinv-discount-error'];
671
                wpinv_unset_error( 'wpinv-discount-error' );
672
            }
673
674
            // Allow for custom discount code handling
675
            $response = apply_filters( 'wpinv_ajax_discount_response', $response );
676
        }
677
        
678
        wp_send_json( $response );
679
    }
680
    
681
    public static function remove_discount() {
682
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
683
        
684
        $response = array();
685
        
686
        if ( isset( $_POST['code'] ) ) {
687
            $discount_code  = sanitize_text_field( $_POST['code'] );
688
            $discounts      = wpinv_unset_cart_discount( $discount_code );
689
            $total          = wpinv_get_cart_total( null, $discounts );
0 ignored issues
show
Unused Code introduced by
The assignment to $total is dead and can be removed.
Loading history...
690
            $cart_totals    = wpinv_recalculate_tax( true );
691
            
692
            if ( !empty( $cart_totals ) ) {
693
                $response['success']        = true;
694
                $response['data']           = $cart_totals;
695
                $response['data']['code']   = $discount_code;
696
            } else {
697
                $response['success']        = false;
698
            }
699
            
700
            // Allow for custom discount code handling
701
            $response = apply_filters( 'wpinv_ajax_discount_response', $response );
702
        }
703
        
704
        wp_send_json( $response );
705
    }
706
707
    /**
708
     * Retrieves the markup for a payment form.
709
     */
710
    public static function get_payment_form() {
711
712
        // Check nonce.
713
        if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], 'getpaid_ajax_form' ) ) {
714
            _e( 'Error: Reload the page and try again.', 'invoicing' );
715
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
716
        }
717
718
        // Is the request set up correctly?
719
		if ( empty( $_GET['form'] ) && empty( $_GET['item'] ) ) {
720
			echo aui()->alert(
721
				array(
722
					'type'    => 'warning',
723
					'content' => __( 'No payment form or item provided', 'invoicing' ),
724
				)
725
            );
726
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
727
        }
728
729
        // Payment form or button?
730
		if ( ! empty( $_GET['form'] ) ) {
731
            echo getpaid_display_payment_form( $_GET['form'] );
732
		} else if( $_GET['invoice'] ) {
733
		    echo getpaid_display_invoice_payment_form( $_GET['invoice'] );
734
        } else {
735
			$items = getpaid_convert_items_to_array( $_GET['item'] );
736
		    echo getpaid_display_item_payment_form( $items );
737
        }
738
        
739
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
740
741
    }
742
743
    /**
744
     * Payment forms.
745
     *
746
     * @since 1.0.18
747
     */
748
    public static function payment_form() {
749
        global $invoicing, $wpi_checkout_id, $cart_total;
750
751
        // Check nonce.
752
        check_ajax_referer( 'getpaid_form_nonce' );
753
754
        // ... form fields...
755
        if ( empty( $_POST['getpaid_payment_form_submission'] ) ) {
756
            _e( 'Error: Reload the page and try again.', 'invoicing' );
757
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
758
        }
759
760
        // Load the submission.
761
        $submission = new GetPaid_Payment_Form_Submission();
762
763
        // Do we have an error?
764
        if ( ! empty( $submission->last_error ) ) {
765
            echo $submission->last_error;
766
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
767
        }
768
769
        // We need a billing email.
770
        if ( ! $submission->has_billing_email() || ! is_email( $submission->get_billing_email() ) ) {
771
            wp_send_json_error( __( 'Provide a valid billing email.', 'invoicing' ) );
772
        }
773
774
        // Prepare items.
775
        $items            = $submission->get_items();
776
        $prepared_items   = array();
777
778
        if ( ! empty( $items ) ) {
779
780
            foreach( $items as $item_id => $item ) {
781
782
                if ( $item->can_purchase() ) {
783
                    $prepared_items[] = array(
784
                        'id'           => $item_id,
785
                        'item_price'   => $item->get_price(),
786
                        'custom_price' => $item->get_price(),
787
                        'name'         => $item->get_name(),
788
                        'quantity'     => $item->get_quantity(),
789
                    );
790
                }
791
792
            }
793
794
        }
795
796
        if ( empty( $prepared_items ) ) {
797
            wp_send_json_error( __( 'You have not selected any items.', 'invoicing' ) );
798
        }
799
800
        if ( $submission->has_recurring && 1 != count( $prepared_items ) ) {
801
            wp_send_json_error( __( 'Recurring items should be bought individually.', 'invoicing' ) );
802
        }
803
804
        // Prepare the submission details.
805
        $prepared = array(
806
            'billing_email'                    => sanitize_email( $submission->get_billing_email() ),
807
            __( 'Billing Email', 'invoicing' ) => sanitize_email( $submission->get_billing_email() ),
808
            __( 'Form Id', 'invoicing' )       => absint( $submission->payment_form->get_id() ),
809
        );
810
811
        // Address fields.
812
        $address_fields = array();
813
814
        // Add discount code.
815
        if ( $submission->has_discount_code() ) {
816
            $address_fields['discount'] = array( $submission->get_discount_code() );
817
        }
818
819
        // Are all required fields provided?
820
        $data = $submission->get_data();
821
822
        foreach ( $submission->payment_form->get_elements() as $field ) {
823
824
            if ( ! empty( $field['premade'] ) ) {
825
                continue;
826
            }
827
828
            if ( ! $submission->is_required_field_set( $field ) ) {
829
                wp_send_json_error( __( 'Fill all required fields.', 'invoicing' ) );
830
            }
831
832
            if ( $field['type'] == 'address' ) {
833
834
                foreach ( $field['fields'] as $address_field ) {
835
836
                    if ( empty( $address_field['visible'] ) ) {
837
                        continue;
838
                    }
839
840
                    if ( ! empty( $address_field['required'] ) && empty( $data[ $address_field['name'] ] ) ) {
841
                        wp_send_json_error( __( 'Some required fields have not been filled.', 'invoicing' ) );
842
                    }
843
844
                    if ( isset( $data[ $address_field['name'] ] ) ) {
845
                        $label = str_replace( 'wpinv_', '', $address_field['name'] );
846
                        $address_fields[ $label ] = wpinv_clean( $data[ $address_field['name'] ] );
847
                    }
848
849
                }
850
851
            } else if ( isset( $data[ $field['id'] ] ) ) {
852
                $label = $field['id'];
853
854
                if ( isset( $field['label'] ) ) {
855
                    $label = $field['label'];
856
                }
857
858
                $prepared[ wpinv_clean( $label ) ] = wpinv_clean( $data[ $field['id'] ] );
859
            }
860
861
        }
862
863
        // (Maybe) create the user.
864
        $user = get_user_by( 'email', $prepared['billing_email'] );
865
866
        if ( empty( $user ) ) {
867
            $user = wpinv_create_user( $prepared['billing_email'] );
868
        }
869
870
        if ( is_wp_error( $user ) ) {
871
            wp_send_json_error( $user->get_error_message() );
872
        }
873
874
        if ( is_numeric( $user ) ) {
875
            $user = get_user_by( 'id', $user );
876
        }
877
878
        // Create the invoice.
879
        if ( ! $submission->has_invoice() ) {
880
881
            $invoice = wpinv_insert_invoice(
882
                array(
883
                    'status'        => 'wpi-pending',
884
                    'created_via'   => 'payment_form',
885
                    'user_id'       => $user->ID,
886
                    'cart_details'  => $prepared_items,
887
                    'user_info'     => $address_fields,
888
                ),
889
                true
890
            );
891
892
        } else {
893
894
            $invoice = $submission->get_invoice();
895
896
            if ( $invoice->is_paid() ) {
897
                wp_send_json_error( __( 'This invoice has already been paid for.', 'invoicing' ) );
898
            }
899
900
            $invoice = wpinv_update_invoice(
901
                array(
902
                    'ID'            => $submission->get_invoice()->ID,
903
                    'status'        => 'wpi-pending',
904
                    'cart_details'  => $prepared_items,
905
                    'user_info'     => $address_fields,
906
                ),
907
                true
908
            );
909
910
        }
911
912
        if ( is_wp_error( $invoice ) ) {
913
            wp_send_json_error( $invoice->get_error_message() );
914
        }
915
916
        if ( empty( $invoice ) ) {
917
            wp_send_json_error( __( 'Could not create your invoice.', 'invoicing' ) );
918
        }
919
920
        unset( $prepared['billing_email'] );
921
        update_post_meta( $invoice->ID, 'payment_form_data', $prepared );
922
923
        $wpi_checkout_id = $invoice->ID;
924
        $cart_total = wpinv_price(
925
            wpinv_format_amount(
926
                wpinv_get_cart_total( $invoice->get_cart_details(), NULL, $invoice ) ),
927
                $invoice->get_currency()
928
        );
929
930
        $data                   = array();
931
        $data['invoice_id']     = $invoice->ID;
932
        $data['cart_discounts'] = $invoice->get_discounts( true );
933
934
        wpinv_set_checkout_session( $data );
935
        add_filter( 'wp_redirect', array( $invoicing->form_elements, 'send_redirect_response' ) );
936
        add_action( 'wpinv_pre_send_back_to_checkout', array( $invoicing->form_elements, 'checkout_error' ) );
937
        
938
        if ( ! defined( 'WPINV_CHECKOUT' ) ) {
939
            define( 'WPINV_CHECKOUT', true );
940
        }
941
942
        wpinv_process_checkout();
943
944
        $invoicing->form_elements->checkout_error();
945
946
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
947
    }
948
949
    /**
950
     * Payment forms.
951
     *
952
     * @since 1.0.18
953
     */
954
    public static function get_payment_form_states_field() {
955
        global $invoicing;
956
957
        if ( empty( $_GET['country'] ) || empty( $_GET['form'] ) ) {
958
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
959
        }
960
961
        $elements = $invoicing->form_elements->get_form_elements( $_GET['form'] );
962
963
        if ( empty( $elements ) ) {
964
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
965
        }
966
967
        $address_fields = array();
968
        foreach ( $elements as $element ) {
969
            if ( 'address' === $element['type'] ) {
970
                $address_fields = $element;
971
                break;
972
            }
973
        }
974
975
        if ( empty( $address_fields ) ) {
976
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
977
        }
978
979
        foreach( $address_fields['fields'] as $address_field ) {
980
981
            if ( 'wpinv_state' == $address_field['name'] ) {
982
983
                $label = $address_field['label'];
984
985
                if ( ! empty( $address_field['required'] ) ) {
986
                    $label .= "<span class='text-danger'> *</span>";
987
                }
988
989
                $states = wpinv_get_country_states( $_GET['country'] );
990
991
                if ( ! empty( $states ) ) {
992
993
                    $html = aui()->select(
994
                            array(
995
                                'options'          => $states,
996
                                'name'             => esc_attr( $address_field['name'] ),
997
                                'id'               => esc_attr( $address_field['name'] ),
998
                                'placeholder'      => esc_attr( $address_field['placeholder'] ),
999
                                'required'         => (bool) $address_field['required'],
1000
                                'no_wrap'          => true,
1001
                                'label'            => wp_kses_post( $label ),
1002
                                'select2'          => false,
1003
                            )
1004
                        );
1005
1006
                } else {
1007
1008
                    $html = aui()->input(
1009
                            array(
1010
                                'name'       => esc_attr( $address_field['name'] ),
1011
                                'id'         => esc_attr( $address_field['name'] ),
1012
                                'required'   => (bool) $address_field['required'],
1013
                                'label'      => wp_kses_post( $label ),
1014
                                'no_wrap'    => true,
1015
                                'type'       => 'text',
1016
                            )
1017
                        );
1018
1019
                }
1020
1021
                wp_send_json_success( str_replace( 'sr-only', '', $html ) );
1022
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1023
1024
            }
1025
1026
        }
1027
    
1028
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1029
    }
1030
1031
    /**
1032
     * Refresh prices.
1033
     *
1034
     * @since 1.0.19
1035
     */
1036
    public static function payment_form_refresh_prices() {
1037
1038
        // Check nonce.
1039
        check_ajax_referer( 'getpaid_form_nonce' );
1040
1041
        // ... form fields...
1042
        if ( empty( $_POST['getpaid_payment_form_submission'] ) ) {
1043
            _e( 'Error: Reload the page and try again.', 'invoicing' );
1044
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1045
        }
1046
1047
        // Load the submission.
1048
        $submission = new GetPaid_Payment_Form_Submission();
1049
1050
        // Do we have an error?
1051
        if ( ! empty( $submission->last_error ) ) {
1052
            echo $submission->last_error;
1053
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1054
        }
1055
1056
        // Prepare the result.
1057
        $result = array(
1058
            'submission_id' => $submission->id,
1059
            'has_recurring' => $submission->has_recurring,
1060
            'is_free'       => $submission->get_payment_details(),
1061
            'totals'        => array(
1062
                'subtotal'  => wpinv_price( wpinv_format_amount( $submission->subtotal_amount ), $submission->get_currency() ),
1063
                'discount'  => wpinv_price( wpinv_format_amount( $submission->get_total_discount() ), $submission->get_currency() ),
1064
                'fees'      => wpinv_price( wpinv_format_amount( $submission->get_total_fees() ), $submission->get_currency() ),
1065
                'tax'       => wpinv_price( wpinv_format_amount( $submission->get_total_tax() ), $submission->get_currency() ),
1066
                'total'     => wpinv_price( wpinv_format_amount( $submission->get_total() ), $submission->get_currency() ),
1067
            ),
1068
        );
1069
1070
        // Add items.
1071
        $items = $submission->get_items();
1072
        if ( ! empty( $items ) ) {
1073
            $result['items'] = array();
1074
1075
            foreach( $items as $item_id => $item ) {
1076
                $result['items']["$item_id"] = wpinv_price( wpinv_format_amount( $item->get_price() * $item->get_qantity() ) );
1077
            }
1078
        }
1079
1080
        // Add invoice.
1081
        if ( $submission->has_invoice() ) {
1082
            $result['invoice'] = $submission->get_invoice()->ID;
1083
        }
1084
1085
        // Add discount code.
1086
        if ( $submission->has_discount_code() ) {
1087
            $result['discount_code'] = $submission->get_discount_code();
1088
        }
1089
1090
        // Filter the result.
1091
        $result = apply_filters( 'getpaid_payment_form_ajax_refresh_prices', $result, $submission );
1092
1093
        wp_send_json_success( $result );
1094
    }
1095
1096
    /**
1097
     * Lets users buy items via ajax.
1098
     *
1099
     * @since 1.0.0
1100
     */
1101
    public static function buy_items() {
1102
        $user_id = get_current_user_id();
1103
1104
        if ( empty( $user_id ) ) { // If not logged in then lets redirect to the login page
1105
            wp_send_json( array(
1106
                'success' => wp_login_url( wp_get_referer() )
0 ignored issues
show
Bug introduced by
It seems like wp_get_referer() can also be of type false; however, parameter $redirect of wp_login_url() 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

1106
                'success' => wp_login_url( /** @scrutinizer ignore-type */ wp_get_referer() )
Loading history...
1107
            ) );
1108
        } else {
1109
            // Only check nonce if logged in as it could be cached when logged out.
1110
            if ( ! isset( $_POST['wpinv_buy_nonce'] ) || ! wp_verify_nonce( $_POST['wpinv_buy_nonce'], 'wpinv_buy_items' ) ) {
1111
                wp_send_json( array(
1112
                    'error' => __( 'Security checks failed.', 'invoicing' )
1113
                ) );
1114
                wp_die();
1115
            }
1116
1117
            // allow to set a custom price through post_id
1118
            $items = $_POST['items'];
1119
            $related_post_id = isset( $_POST['post_id'] ) ? (int)$_POST['post_id'] : 0;
1120
            $custom_item_price = $related_post_id ? abs( get_post_meta( $related_post_id, '_wpi_custom_price', true ) ) : 0;
1121
1122
            $cart_items = array();
1123
            if ( $items ) {
1124
                $items = explode( ',', $items );
1125
1126
                foreach( $items as $item ) {
1127
                    $item_id = $item;
1128
                    $quantity = 1;
1129
1130
                    if ( strpos( $item, '|' ) !== false ) {
1131
                        $item_parts = explode( '|', $item );
1132
                        $item_id = $item_parts[0];
1133
                        $quantity = $item_parts[1];
1134
                    }
1135
1136
                    if ( $item_id && $quantity ) {
1137
                        $cart_items_arr = array(
1138
                            'id'            => (int)$item_id,
1139
                            'quantity'      => (int)$quantity
1140
                        );
1141
1142
                        // If there is a related post id then add it to meta
1143
                        if ( $related_post_id ) {
1144
                            $cart_items_arr['meta'] = array(
1145
                                'post_id'   => $related_post_id
1146
                            );
1147
                        }
1148
1149
                        // If there is a custom price then set it.
1150
                        if ( $custom_item_price ) {
1151
                            $cart_items_arr['custom_price'] = $custom_item_price;
1152
                        }
1153
1154
                        $cart_items[] = $cart_items_arr;
1155
                    }
1156
                }
1157
            }
1158
1159
            /**
1160
             * Filter the wpinv_buy shortcode cart items on the fly.
1161
             *
1162
             * @param array $cart_items The cart items array.
1163
             * @param int $related_post_id The related post id if any.
1164
             * @since 1.0.0
1165
             */
1166
            $cart_items = apply_filters( 'wpinv_buy_cart_items', $cart_items, $related_post_id );
1167
1168
            // Make sure its not in the cart already, if it is then redirect to checkout.
1169
            $cart_invoice = wpinv_get_invoice_cart();
1170
1171
            if ( isset( $cart_invoice->items ) && !empty( $cart_invoice->items ) && !empty( $cart_items ) && serialize( $cart_invoice->items ) == serialize( $cart_items ) ) {
1172
                wp_send_json( array(
1173
                    'success' =>  $cart_invoice->get_checkout_payment_url()
1174
                ) );
1175
                wp_die();
1176
            }
1177
1178
            // Check if user has invoice with same items waiting to be paid.
1179
            $user_invoices = wpinv_get_users_invoices( $user_id , 10 , false , 'wpi-pending' );
1180
            if ( !empty( $user_invoices ) ) {
1181
                foreach( $user_invoices as $user_invoice ) {
1182
                    $user_cart_details = array();
1183
                    $invoice  = wpinv_get_invoice( $user_invoice->ID );
1184
                    $cart_details = $invoice->get_cart_details();
1185
1186
                    if ( !empty( $cart_details ) ) {
1187
                        foreach ( $cart_details as $invoice_item ) {
1188
                            $ii_arr = array();
1189
                            $ii_arr['id'] = (int)$invoice_item['id'];
1190
                            $ii_arr['quantity'] = (int)$invoice_item['quantity'];
1191
1192
                            if (isset( $invoice_item['meta'] ) && !empty( $invoice_item['meta'] ) ) {
1193
                                $ii_arr['meta'] = $invoice_item['meta'];
1194
                            }
1195
1196
                            if ( isset( $invoice_item['custom_price'] ) && !empty( $invoice_item['custom_price'] ) ) {
1197
                                $ii_arr['custom_price'] = $invoice_item['custom_price'];
1198
                            }
1199
1200
                            $user_cart_details[] = $ii_arr;
1201
                        }
1202
                    }
1203
1204
                    if ( !empty( $user_cart_details ) && serialize( $cart_items ) == serialize( $user_cart_details ) ) {
1205
                        wp_send_json( array(
1206
                            'success' =>  $invoice->get_checkout_payment_url()
1207
                        ) );
1208
                        wp_die();
1209
                    }
1210
                }
1211
            }
1212
1213
            // Create invoice and send user to checkout
1214
            if ( !empty( $cart_items ) ) {
1215
                $invoice_data = array(
1216
                    'status'        =>  'wpi-pending',
1217
                    'created_via'   =>  'wpi',
1218
                    'user_id'       =>  $user_id,
1219
                    'cart_details'  =>  $cart_items,
1220
                );
1221
1222
                $invoice = wpinv_insert_invoice( $invoice_data, true );
1223
1224
                if ( !empty( $invoice ) && isset( $invoice->ID ) ) {
1225
                    wp_send_json( array(
1226
                        'success' =>  $invoice->get_checkout_payment_url()
0 ignored issues
show
Bug introduced by
The method get_checkout_payment_url() does not exist on WP_Error. ( Ignorable by Annotation )

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

1226
                        'success' =>  $invoice->/** @scrutinizer ignore-call */ get_checkout_payment_url()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1227
                    ) );
1228
                } else {
1229
                    wp_send_json( array(
1230
                        'error' => __( 'Invoice failed to create', 'invoicing' )
1231
                    ) );
1232
                }
1233
            } else {
1234
                wp_send_json( array(
1235
                    'error' => __( 'Items not valid.', 'invoicing' )
1236
                ) );
1237
            }
1238
        }
1239
1240
        wp_die();
1241
    }
1242
}
1243
1244
WPInv_Ajax::init();