Passed
Push — master ( ae3eec...84a4a3 )
by Brian
10:54
created

WPInv_Ajax::delete_note()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 0
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Contains the ajax handlers.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * WPInv_Ajax class.
13
 */
14
class WPInv_Ajax {
15
16
    /**
17
	 * Hook in ajax handlers.
18
	 */
19
	public static function init() {
20
		add_action( 'init', array( __CLASS__, 'define_ajax' ), 0 );
21
		add_action( 'template_redirect', array( __CLASS__, 'do_wpinv_ajax' ), 0 );
22
		self::add_ajax_events();
23
    }
24
25
    /**
26
	 * Set GetPaid AJAX constant and headers.
27
	 */
28
	public static function define_ajax() {
29
30
		if ( ! empty( $_GET['wpinv-ajax'] ) ) {
31
			getpaid_maybe_define_constant( 'DOING_AJAX', true );
32
			getpaid_maybe_define_constant( 'WPInv_DOING_AJAX', true );
33
			if ( ! WP_DEBUG || ( WP_DEBUG && ! WP_DEBUG_DISPLAY ) ) {
34
				/** @scrutinizer ignore-unhandled */ @ini_set( 'display_errors', 0 );
35
			}
36
			$GLOBALS['wpdb']->hide_errors();
37
		}
38
39
    }
40
    
41
    /**
42
	 * Send headers for GetPaid Ajax Requests.
43
	 *
44
	 * @since 1.0.18
45
	 */
46
	private static function wpinv_ajax_headers() {
47
		if ( ! headers_sent() ) {
48
			send_origin_headers();
49
			send_nosniff_header();
50
			nocache_headers();
51
			header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
52
			header( 'X-Robots-Tag: noindex' );
53
			status_header( 200 );
54
		}
55
    }
56
    
57
    /**
58
	 * Check for GetPaid Ajax request and fire action.
59
	 */
60
	public static function do_wpinv_ajax() {
61
		global $wp_query;
62
63
		if ( ! empty( $_GET['wpinv-ajax'] ) ) {
64
			$wp_query->set( 'wpinv-ajax', sanitize_text_field( wp_unslash( $_GET['wpinv-ajax'] ) ) );
0 ignored issues
show
Bug introduced by
It seems like wp_unslash($_GET['wpinv-ajax']) can also be of type array; however, parameter $str of sanitize_text_field() 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

64
			$wp_query->set( 'wpinv-ajax', sanitize_text_field( /** @scrutinizer ignore-type */ wp_unslash( $_GET['wpinv-ajax'] ) ) );
Loading history...
65
		}
66
67
		$action = $wp_query->get( 'wpinv-ajax' );
68
69
		if ( $action ) {
70
			self::wpinv_ajax_headers();
71
			$action = sanitize_text_field( $action );
72
			do_action( 'wpinv_ajax_' . $action );
73
			wp_die();
74
		}
75
76
    }
77
78
    /**
79
	 * Hook in ajax methods.
80
	 */
81
    public static function add_ajax_events() {
82
83
        // array( 'event' => is_frontend )
84
        $ajax_events = array(
85
            'add_note'                    => false,
86
            'delete_note'                 => false,
87
            'get_states_field'            => true,
88
            'get_aui_states_field'        => true,
89
            'payment_form'                => true,
90
            'get_payment_form'            => true,
91
            'get_payment_form_states_field' => true,
92
            'get_invoicing_items'         => false,
93
            'get_customers'               => false,
94
            'get_invoice_items'           => false,
95
            'add_invoice_items'           => false,
96
            'admin_add_invoice_item'      => false,
97
            'recalculate_full_prices'     => false,
98
            'edit_invoice_item'           => false,
99
            'create_invoice_item'         => false,
100
            'remove_invoice_item'         => false,
101
            'get_billing_details'         => false,
102
            'recalculate_invoice_totals'  => false,
103
            'check_new_user_email'        => false,
104
            'run_tool'                    => false,
105
            'payment_form_refresh_prices' => true,
106
        );
107
108
        foreach ( $ajax_events as $ajax_event => $nopriv ) {
109
            add_action( 'wp_ajax_wpinv_' . $ajax_event, array( __CLASS__, $ajax_event ) );
110
            add_action( 'wp_ajax_getpaid_' . $ajax_event, array( __CLASS__, $ajax_event ) );
111
112
            if ( $nopriv ) {
113
                add_action( 'wp_ajax_nopriv_wpinv_' . $ajax_event, array( __CLASS__, $ajax_event ) );
114
                add_action( 'wp_ajax_nopriv_getpaid_' . $ajax_event, array( __CLASS__, $ajax_event ) );
115
                add_action( 'wpinv_ajax_' . $ajax_event, array( __CLASS__, $ajax_event ) );
116
            }
117
        }
118
    }
119
    
120
    public static function add_note() {
121
        check_ajax_referer( 'add-invoice-note', '_nonce' );
122
123
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
124
            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...
125
        }
126
127
        $post_id   = absint( $_POST['post_id'] );
128
        $note      = wp_kses_post( trim( stripslashes( $_POST['note'] ) ) );
129
        $note_type = sanitize_text_field( $_POST['note_type'] );
130
131
        $is_customer_note = $note_type == 'customer' ? 1 : 0;
132
133
        if ( $post_id > 0 ) {
134
            $note_id = wpinv_insert_payment_note( $post_id, $note, $is_customer_note );
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_insert_payment_note() has been deprecated. ( Ignorable by Annotation )

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

134
            $note_id = /** @scrutinizer ignore-deprecated */ wpinv_insert_payment_note( $post_id, $note, $is_customer_note );
Loading history...
135
136
            if ( $note_id > 0 && !is_wp_error( $note_id ) ) {
137
                wpinv_get_invoice_note_line_item( $note_id );
138
            }
139
        }
140
141
        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...
142
    }
143
144
    public static function delete_note() {
145
        check_ajax_referer( 'delete-invoice-note', '_nonce' );
146
147
        if ( !wpinv_current_user_can_manage_invoicing() ) {
148
            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...
149
        }
150
151
        $note_id = (int)$_POST['note_id'];
152
153
        if ( $note_id > 0 ) {
154
            wp_delete_comment( $note_id, true );
155
        }
156
157
        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...
158
    }
159
    
160
    public static function get_states_field() {
161
        echo wpinv_get_states_field();
162
        
163
        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...
164
    }
165
166
    /**
167
     * Retrieves a given user's billing address.
168
     */
169
    public static function get_billing_details() {
170
171
        // Verify nonce.
172
        check_ajax_referer( 'wpinv-nonce' );
173
174
        // Can the user manage the plugin?
175
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
176
            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...
177
        }
178
179
        // Do we have a user id?
180
        $user_id = $_GET['user_id'];
181
182
        if ( empty( $user_id ) || ! is_numeric( $user_id ) ) {
183
            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...
184
        }
185
186
        // Fetch the billing details.
187
        $billing_details    = wpinv_get_user_address( $user_id );
188
        $billing_details    = apply_filters( 'wpinv_ajax_billing_details', $billing_details, $user_id );
189
190
        // unset the user id and email.
191
        $to_ignore = array( 'user_id', 'email' );
192
193
        foreach ( $to_ignore as $key ) {
194
            if ( isset( $billing_details[ $key ] ) ) {
195
                unset( $billing_details[ $key ] );
196
            }
197
        }
198
199
        wp_send_json_success( $billing_details );
200
201
    }
202
203
    /**
204
     * Checks if a new users email is valid.
205
     */
206
    public static function check_new_user_email() {
207
208
        // Verify nonce.
209
        check_ajax_referer( 'wpinv-nonce' );
210
211
        // Can the user manage the plugin?
212
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
213
            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...
214
        }
215
216
        // We need an email address.
217
        if ( empty( $_GET['email'] ) ) {
218
            _e( "Provide the new user's email address", 'invoicing' );
219
            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...
220
        }
221
222
        // Ensure the email is valid.
223
        $email = sanitize_text_field( $_GET['email'] );
224
        if ( ! is_email( $email ) ) {
225
            _e( 'Invalid email address', 'invoicing' );
226
            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...
227
        }
228
229
        // And it does not exist.
230
        $id = email_exists( $email );
231
        if ( $id ) {
232
            wp_send_json_success( compact( 'id' ) );
233
        }
234
235
        wp_send_json_success( true );
236
    }
237
    
238
    public static function run_tool() {
239
        check_ajax_referer( 'wpinv-nonce', '_nonce' );
240
        if ( !wpinv_current_user_can_manage_invoicing() ) {
241
            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...
242
        }
243
        
244
        $tool = sanitize_text_field( $_POST['tool'] );
245
        
246
        do_action( 'wpinv_run_tool' );
247
        
248
        if ( !empty( $tool ) ) {
249
            do_action( 'wpinv_tool_' . $tool );
250
        }
251
    }
252
253
    /**
254
     * Retrieves the markup for a payment form.
255
     */
256
    public static function get_payment_form() {
257
258
        // Check nonce.
259
        check_ajax_referer( 'getpaid_form_nonce' );
260
261
        // Is the request set up correctly?
262
		if ( empty( $_GET['form'] ) && empty( $_GET['item'] ) ) {
263
			echo aui()->alert(
264
				array(
265
					'type'    => 'warning',
266
					'content' => __( 'No payment form or item provided', 'invoicing' ),
267
				)
268
            );
269
            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...
270
        }
271
272
        // Payment form or button?
273
		if ( ! empty( $_GET['form'] ) ) {
274
            $form = urldecode( $_GET['form'] );
275
276
            if ( false !== strpos( $form, '|' ) ) {
277
                $form_pos = strpos( $form, '|' );
278
                $_items   = getpaid_convert_items_to_array( substr( $form, $form_pos + 1 ) );
279
                $form     = substr( $form, 0, $form_pos );
280
281
                // Retrieve appropriate payment form.
282
                $payment_form = new GetPaid_Payment_Form( $form );
283
                $payment_form = $payment_form->exists() ? $payment_form : new GetPaid_Payment_Form( wpinv_get_default_payment_form() );
284
285
                $items    = array();
286
                $item_ids = array();
287
288
                foreach ( $_items as $item_id => $qty ) {
289
                    if ( ! in_array( $item_id, $item_ids ) ) {
290
                        $item = new GetPaid_Form_Item( $item_id );
291
                        $item->set_quantity( $qty );
292
293
                        if ( 0 == $qty ) {
294
                            $item->set_allow_quantities( true );
295
                            $item->set_is_required( false );
296
                        }
297
298
                        $item_ids[] = $item->get_id();
299
                        $items[]    = $item;
300
                    }
301
                }
302
303
                if ( ! $payment_form->is_default() ) {
304
305
                    foreach ( $payment_form->get_items() as $item ) {
306
                        if ( ! in_array( $item->get_id(), $item_ids ) ) {
307
                            $item_ids[] = $item->get_id();
308
                            $items[]    = $item;
309
                        }
310
                    }
311
312
                }
313
314
                $payment_form->set_items( $items );
315
                add_filter( 'wpinv_force_default_payment_form', '__return_true' );
316
                $payment_form->display();
317
                remove_filter( 'wpinv_force_default_payment_form', '__return_true' );
318
319
            } else {
320
                getpaid_display_payment_form( $form );
321
            }
322
323
		} else if( ! empty( $_GET['invoice'] ) ) {
324
		    getpaid_display_invoice_payment_form( urldecode( $_GET['invoice'] ) );
325
        } else {
326
			$items = getpaid_convert_items_to_array( urldecode( $_GET['item'] ) );
327
		    getpaid_display_item_payment_form( $items );
328
        }
329
330
        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...
331
332
    }
333
334
    /**
335
     * Payment forms.
336
     *
337
     * @since 1.0.18
338
     */
339
    public static function payment_form() {
340
341
        // Check nonce.
342
        check_ajax_referer( 'getpaid_form_nonce' );
343
344
        // ... form fields...
345
        if ( empty( $_POST['getpaid_payment_form_submission'] ) ) {
346
            _e( 'Error: Reload the page and try again.', 'invoicing' );
347
            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...
348
        }
349
350
        // Process the payment form.
351
        $checkout_class = apply_filters( 'getpaid_checkout_class', 'GetPaid_Checkout' );
352
        $checkout       = new $checkout_class( new GetPaid_Payment_Form_Submission() );
353
        $checkout->process_checkout();
354
355
        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...
356
    }
357
358
    /**
359
     * Payment forms.
360
     *
361
     * @since 1.0.18
362
     */
363
    public static function get_payment_form_states_field() {
364
365
        if ( empty( $_GET['country'] ) || empty( $_GET['form'] ) ) {
366
            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...
367
        }
368
369
        $elements = getpaid_get_payment_form_elements( $_GET['form'] );
370
371
        if ( empty( $elements ) ) {
372
            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...
373
        }
374
375
        $address_fields = array();
376
        foreach ( $elements as $element ) {
377
            if ( 'address' === $element['type'] ) {
378
                $address_fields = $element;
379
                break;
380
            }
381
        }
382
383
        if ( empty( $address_fields ) ) {
384
            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...
385
        }
386
387
        foreach ( $address_fields['fields'] as $address_field ) {
388
389
            if ( 'wpinv_state' == $address_field['name'] ) {
390
391
                $wrap_class  = getpaid_get_form_element_grid_class( $address_field );
392
                $wrap_class  = esc_attr( "$wrap_class getpaid-address-field-wrapper" );
393
                $placeholder = empty( $address_field['placeholder'] ) ? '' : esc_attr( $address_field['placeholder'] );
394
                $description = empty( $address_field['description'] ) ? '' : wp_kses_post( $address_field['description'] );
395
                $value       = is_user_logged_in() ? get_user_meta( get_current_user_id(), '_wpinv_state', true ) : '';
396
                $label       = empty( $address_field['label'] ) ? '' : wp_kses_post( $address_field['label'] );
397
398
                if ( ! empty( $address_field['required'] ) ) {
399
                    $label .= "<span class='text-danger'> *</span>";
400
                }
401
402
                $html = getpaid_get_states_select_markup (
403
                    sanitize_text_field( $_GET['country'] ),
404
                    $value,
405
                    $placeholder,
406
                    $label,
407
                    $description,
408
                    ! empty( $address_field['required'] ),
409
                    $wrap_class,
410
                    wpinv_clean( $_GET['name'] )
411
                );
412
413
                wp_send_json_success( $html );
414
                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...
415
416
            }
417
418
        }
419
    
420
        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...
421
    }
422
423
    /**
424
     * Recalculates invoice totals.
425
     */
426
    public static function recalculate_invoice_totals() {
427
428
        // Verify nonce.
429
        check_ajax_referer( 'wpinv-nonce' );
430
431
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
432
            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...
433
        }
434
435
        // We need an invoice.
436
        if ( empty( $_POST['post_id'] ) ) {
437
            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...
438
        }
439
440
        // Fetch the invoice.
441
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
442
443
        // Ensure it exists.
444
        if ( ! $invoice->get_id() ) {
445
            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...
446
        }
447
448
        // Maybe set the country, state, currency.
449
        foreach ( array( 'country', 'state', 'currency', 'vat_number', 'discount_code' ) as $key ) {
450
            if ( isset( $_POST[ $key ] ) ) {
451
                $method = "set_$key";
452
                $invoice->$method( sanitize_text_field( $_POST[ $key ] ) );
453
            }
454
        }
455
456
        // Maybe disable taxes.
457
        $invoice->set_disable_taxes( ! empty( $_POST['taxes'] ) );
458
459
        // Discount code.
460
        if ( ! $invoice->is_paid() && ! $invoice->is_refunded() ) {
461
            $discount = new WPInv_Discount( $invoice->get_discount_code() );
462
            if ( $discount->exists() ) {
463
                $invoice->add_discount( getpaid_calculate_invoice_discount( $invoice, $discount ) );
464
            } else {
465
                $invoice->remove_discount( 'discount_code' );
466
            }
467
        }
468
469
        // Recalculate totals.
470
        $invoice->recalculate_total();
471
472
        $total        = wpinv_price( $invoice->get_total(), $invoice->get_currency() );
473
        $suscriptions = getpaid_get_invoice_subscriptions( $invoice );
474
        if ( is_a( $suscriptions, 'WPInv_Subscription' ) && $invoice->is_recurring() && $invoice->is_parent() && $invoice->get_total() != $invoice->get_recurring_total() ) {
475
            $recurring_total = wpinv_price( $invoice->get_recurring_total(), $invoice->get_currency() );
476
            $total          .= '<small class="form-text text-muted">' . sprintf( __( 'Recurring Price: %s', 'invoicing' ), $recurring_total ) . '</small>';
477
        }
478
479
        $totals = array(
480
            'subtotal' => wpinv_price( $invoice->get_subtotal(), $invoice->get_currency() ),
481
            'discount' => wpinv_price( $invoice->get_total_discount(), $invoice->get_currency() ),
482
            'tax'      => wpinv_price( $invoice->get_total_tax(), $invoice->get_currency() ),
483
            'total'    => $total,
484
        );
485
486
        $totals = apply_filters( 'getpaid_invoice_totals', $totals, $invoice );
487
488
        wp_send_json_success( compact( 'totals' ) );
489
    }
490
491
    /**
492
     * Get items belonging to a given invoice.
493
     */
494
    public static function get_invoice_items() {
495
496
        // Verify nonce.
497
        check_ajax_referer( 'wpinv-nonce' );
498
499
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
500
            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...
501
        }
502
503
        // We need an invoice and items.
504
        if ( empty( $_POST['post_id'] ) ) {
505
            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...
506
        }
507
508
        // Fetch the invoice.
509
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
510
511
        // Ensure it exists.
512
        if ( ! $invoice->get_id() ) {
513
            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...
514
        }
515
516
        // Return an array of invoice items.
517
        $items = array();
518
519
        foreach ( $invoice->get_items() as $item ) {
520
            $items[] = $item->prepare_data_for_invoice_edit_ajax(  $invoice->get_currency(), $invoice->is_renewal()  );
521
        }
522
523
        wp_send_json_success( compact( 'items' ) );
524
    }
525
526
    /**
527
     * Edits an invoice item.
528
     */
529
    public static function edit_invoice_item() {
530
531
        // Verify nonce.
532
        check_ajax_referer( 'wpinv-nonce' );
533
534
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
535
            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...
536
        }
537
538
        // We need an invoice and item details.
539
        if ( empty( $_POST['post_id'] ) || empty( $_POST['data'] ) ) {
540
            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...
541
        }
542
543
        // Fetch the invoice.
544
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
545
546
        // Ensure it exists and its not been paid for.
547
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
548
            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...
549
        }
550
551
        // Format the data.
552
        $data = wp_unslash( wp_list_pluck( $_POST['data'], 'value', 'field' ) );
553
554
        // Ensure that we have an item id.
555
        if ( empty( $data['id'] ) ) {
556
            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...
557
        }
558
559
        // Abort if the invoice does not have the specified item.
560
        $item = $invoice->get_item( (int) $data['id'] );
561
562
        if ( empty( $item ) ) {
563
            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...
564
        }
565
566
        // Update the item.
567
        $item->set_price( getpaid_standardize_amount( $data['price'] ) );
568
        $item->set_name( sanitize_text_field( $data['name'] ) );
569
        $item->set_description( wp_kses_post( $data['description'] ) );
570
        $item->set_quantity( floatval( $data['quantity'] ) );
571
572
        // Add it to the invoice.
573
        $error = $invoice->add_item( $item );
574
        $alert = false;
575
        if ( is_wp_error( $error ) ) {
576
            $alert = $error->get_error_message();
577
        }
578
579
        // Update totals.
580
        $invoice->recalculate_total();
581
582
        // Save the invoice.
583
        $invoice->save();
584
585
        // Return an array of invoice items.
586
        $items = array();
587
588
        foreach ( $invoice->get_items() as $item ) {
589
            $items[] = $item->prepare_data_for_invoice_edit_ajax(  $invoice->get_currency()  );
590
        }
591
592
        wp_send_json_success( compact( 'items', 'alert' ) );
593
    }
594
595
    /**
596
     * Creates an invoice item.
597
     */
598
    public static function create_invoice_item() {
599
600
        // Verify nonce.
601
        check_ajax_referer( 'wpinv-nonce' );
602
603
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
604
            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...
605
        }
606
607
        // We need an invoice and item details.
608
        if ( empty( $_POST['invoice_id'] ) || empty( $_POST['_wpinv_quick'] ) ) {
609
            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...
610
        }
611
612
        // Fetch the invoice.
613
        $invoice = new WPInv_Invoice( trim( $_POST['invoice_id'] ) );
614
615
        // Ensure it exists and its not been paid for.
616
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
617
            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...
618
        }
619
620
        // Format the data.
621
        $data = wp_unslash( $_POST['_wpinv_quick'] );
622
623
        $item = new WPInv_Item();
624
        $item->set_price( getpaid_standardize_amount( $data['price'] ) );
625
        $item->set_name( sanitize_text_field( $data['name'] ) );
626
        $item->set_description( wp_kses_post( $data['description'] ) );
627
        $item->set_type( sanitize_text_field( $data['type'] ) );
628
        $item->set_vat_rule( sanitize_text_field( $data['vat_rule'] ) );
629
        $item->set_vat_class( sanitize_text_field( $data['vat_class'] ) );
630
        $item->set_status( 'publish' );
631
        $item->save();
632
633
        if ( ! $item->exists() ) {
634
            $alert = __( 'Could not create invoice item. Please try again.', 'invoicing' );
635
            wp_send_json_success( compact( 'alert' ) );
636
        }
637
638
        $item = new GetPaid_Form_Item( $item->get_id() );
639
        $item->set_quantity( floatval( $data['qty'] ) );
640
641
        // Add it to the invoice.
642
        $error = $invoice->add_item( $item );
643
        $alert = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $alert is dead and can be removed.
Loading history...
644
645
        if ( is_wp_error( $error ) ) {
646
            $alert = $error->get_error_message();
647
            wp_send_json_success( compact( 'alert' ) );
648
         }
649
650
        // Update totals.
651
        $invoice->recalculate_total();
652
653
        // Save the invoice.
654
        $invoice->save();
655
656
        // Save the invoice.
657
        $invoice->recalculate_total();
658
        $invoice->save();
659
        ob_start();
660
        GetPaid_Meta_Box_Invoice_Items::output_row( GetPaid_Meta_Box_Invoice_Items::get_columns( $invoice ), $item, $invoice );
661
        $row = ob_get_clean();
662
        wp_send_json_success( compact( 'row' ) );
663
    }
664
665
    /**
666
     * Deletes an invoice item.
667
     */
668
    public static function remove_invoice_item() {
669
670
        // Verify nonce.
671
        check_ajax_referer( 'wpinv-nonce' );
672
673
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
674
            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...
675
        }
676
677
        // We need an invoice and an item.
678
        if ( empty( $_POST['post_id'] ) || empty( $_POST['item_id'] ) ) {
679
            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...
680
        }
681
682
        // Fetch the invoice.
683
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
684
685
        // Ensure it exists and its not been paid for.
686
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
687
            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...
688
        }
689
690
        // Abort if the invoice does not have the specified item.
691
        $item = $invoice->get_item( (int) $_POST['item_id'] );
692
693
        if ( empty( $item ) ) {
694
            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...
695
        }
696
697
        $invoice->remove_item( (int) $_POST['item_id'] );
698
699
        // Update totals.
700
        $invoice->recalculate_total();
701
702
        // Save the invoice.
703
        $invoice->save();
704
705
        // Return an array of invoice items.
706
        $items = array();
707
708
        foreach ( $invoice->get_items() as $item ) {
709
            $items[] = $item->prepare_data_for_invoice_edit_ajax(  $invoice->get_currency()  );
710
        }
711
712
        wp_send_json_success( compact( 'items' ) );
713
    }
714
715
    /**
716
     * Adds an item to an invoice.
717
     */
718
    public static function recalculate_full_prices() {
719
720
        // Verify nonce.
721
        check_ajax_referer( 'wpinv-nonce' );
722
723
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
724
            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...
725
        }
726
727
        // We need an invoice and item.
728
        if ( empty( $_POST['post_id'] ) ) {
729
            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...
730
        }
731
732
        // Fetch the invoice.
733
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
734
        $alert   = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $alert is dead and can be removed.
Loading history...
735
736
        // Ensure it exists and its not been paid for.
737
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
738
            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...
739
        }
740
741
        $invoice->set_items( array() );
742
743
        if ( ! empty( $_POST['getpaid_items'] ) ) {
744
745
            foreach ( $_POST['getpaid_items'] as $item_id => $args ) {
746
                $item = new GetPaid_Form_Item( $item_id );
747
748
                if ( $item->exists() ) {
749
                    $item->set_price( getpaid_standardize_amount( $args['price'] ) );
750
                    $item->set_quantity( floatval( $args['quantity'] ) );
751
                    $item->set_name( sanitize_text_field( $args['name'] ) );
752
                    $item->set_description( wp_kses_post( $args['description'] ) );
753
                    $invoice->add_item( $item );
754
                }
755
            }
756
757
        }
758
759
        $invoice->set_disable_taxes( ! empty( $_POST['disable_taxes'] ) );
760
761
        // Maybe set the country, state, currency.
762
        foreach ( array( 'wpinv_country', 'wpinv_state', 'wpinv_currency', 'wpinv_vat_number', 'wpinv_discount_code' ) as $key ) {
763
            if ( isset( $_POST[ $key ] ) ) {
764
                $_key   = str_replace( 'wpinv_', '', $key );
765
                $method = "set_$_key";
766
                $invoice->$method( sanitize_text_field( $_POST[ $key ] ) );
767
            }
768
        }
769
770
        $discount = new WPInv_Discount( $invoice->get_discount_code() );
771
        if ( $discount->exists() ) {
772
            $invoice->add_discount( getpaid_calculate_invoice_discount( $invoice, $discount ) );
773
        } else {
774
            $invoice->remove_discount( 'discount_code' );
775
        }
776
777
        // Save the invoice.
778
        $invoice->recalculate_total();
779
        $invoice->save();
780
        ob_start();
781
        GetPaid_Meta_Box_Invoice_Items::output( get_post( $invoice->get_id() ), $invoice );
782
        $table = ob_get_clean();
783
        wp_send_json_success( compact( 'table' ) );
784
    }
785
786
    /**
787
     * Adds an item to an invoice.
788
     */
789
    public static function admin_add_invoice_item() {
790
791
        // Verify nonce.
792
        check_ajax_referer( 'wpinv-nonce' );
793
794
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
795
            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...
796
        }
797
798
        // We need an invoice and item.
799
        if ( empty( $_POST['post_id'] ) || empty( $_POST['item_id'] ) ) {
800
            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...
801
        }
802
803
        // Fetch the invoice.
804
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
805
        $alert   = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $alert is dead and can be removed.
Loading history...
806
807
        // Ensure it exists and its not been paid for.
808
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
809
            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...
810
        }
811
812
        // Add the item.
813
        $item  = new GetPaid_Form_Item( (int) $_POST['item_id'] );
814
        $error = $invoice->add_item( $item );
815
816
        if ( is_wp_error( $error ) ) {
817
            $alert = $error->get_error_message();
818
            wp_send_json_success( compact( 'alert' ) );
819
        }
820
821
        // Save the invoice.
822
        $invoice->recalculate_total();
823
        $invoice->save();
824
        ob_start();
825
        GetPaid_Meta_Box_Invoice_Items::output_row( GetPaid_Meta_Box_Invoice_Items::get_columns( $invoice ), $item, $invoice );
826
        $row = ob_get_clean();
827
        wp_send_json_success( compact( 'row' ) );
828
    }
829
830
    /**
831
     * Adds a items to an invoice.
832
     */
833
    public static function add_invoice_items() {
834
835
        // Verify nonce.
836
        check_ajax_referer( 'wpinv-nonce' );
837
838
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
839
            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...
840
        }
841
842
        // We need an invoice and items.
843
        if ( empty( $_POST['post_id'] ) || empty( $_POST['items'] ) ) {
844
            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...
845
        }
846
847
        // Fetch the invoice.
848
        $invoice = new WPInv_Invoice( trim( $_POST['post_id'] ) );
849
        $alert   = false;
850
851
        // Ensure it exists and its not been paid for.
852
        if ( ! $invoice->get_id() || $invoice->is_paid() || $invoice->is_refunded() ) {
853
            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...
854
        }
855
856
        // Add the items.
857
        foreach ( $_POST['items'] as $data ) {
858
859
            $item = new GetPaid_Form_Item( $data[ 'id' ] );
860
861
            if ( is_numeric( $data[ 'qty' ] ) && (float) $data[ 'qty' ] > 0 ) {
862
                $item->set_quantity( $data[ 'qty' ] );
863
            }
864
865
            if ( $item->get_id() > 0 ) {
866
                $error = $invoice->add_item( $item );
867
868
                if ( is_wp_error( $error ) ) {
869
                    $alert = $error->get_error_message();
870
                }
871
872
            }
873
874
        }
875
876
        // Save the invoice.
877
        $invoice->recalculate_total();
878
        $invoice->save();
879
880
        // Return an array of invoice items.
881
        $items = array();
882
883
        foreach ( $invoice->get_items() as $item ) {
884
            $items[] = $item->prepare_data_for_invoice_edit_ajax( $invoice->get_currency() );
885
        }
886
887
        wp_send_json_success( compact( 'items', 'alert' ) );
888
    }
889
890
    /**
891
     * Retrieves items that should be added to an invoice.
892
     */
893
    public static function get_invoicing_items() {
894
895
        // Verify nonce.
896
        check_ajax_referer( 'wpinv-nonce' );
897
898
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
899
            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...
900
        }
901
902
        // We need a search term.
903
        if ( empty( $_GET['search'] ) ) {
904
            wp_send_json_success( array() );
905
        }
906
907
        // Retrieve items.
908
        $item_args = array(
909
            'post_type'      => 'wpi_item',
910
            'orderby'        => 'title',
911
            'order'          => 'ASC',
912
            'posts_per_page' => -1,
913
            'post_status'    => array( 'publish' ),
914
            's'              => trim( $_GET['search'] ),
915
            'meta_query'     => array(
916
                array(
917
                    'key'       => '_wpinv_type',
918
                    'compare'   => '!=',
919
                    'value'     => 'package'
920
                )
921
            )
922
        );
923
924
        $items = get_posts( apply_filters( 'getpaid_ajax_invoice_items_query_args', $item_args ) );
925
        $data  = array();
926
927
        $is_payment_form = ( ! empty( $_GET['post_id'] ) && 'wpi_payment_form' == get_post_type( $_GET['post_id'] ) );
928
929
        foreach ( $items as $item ) {
930
            $item      = new GetPaid_Form_Item( $item );
931
            $data[] = array(
932
                'id'        => (int) $item->get_id(),
933
                'text'      => strip_tags( $item->get_name() ),
934
                'form_data' => $is_payment_form ? $item->prepare_data_for_use( false ) : '',
935
            );
936
        }
937
938
        wp_send_json_success( $data );
939
940
    }
941
942
    /**
943
     * Retrieves items that should be added to an invoice.
944
     */
945
    public static function get_customers() {
946
947
        // Verify nonce.
948
        check_ajax_referer( 'wpinv-nonce' );
949
950
        if ( ! wpinv_current_user_can_manage_invoicing() ) {
951
            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...
952
        }
953
954
        // We need a search term.
955
        if ( empty( $_GET['search'] ) ) {
956
            wp_send_json_success( array() );
957
        }
958
959
        // Retrieve customers.
960
    
961
        $customer_args = array(
962
            'fields'         => array( 'ID', 'user_email', 'display_name' ),
963
            'orderby'        => 'display_name',
964
            'search'         => '*' . sanitize_text_field( $_GET['search'] ) . '*',
965
            'search_columns' => array( 'user_login', 'user_email', 'display_name' ),
966
        );
967
968
        $customers = get_users( apply_filters( 'getpaid_ajax_invoice_customers_query_args', $customer_args ) );
969
        $data      = array();
970
971
        foreach ( $customers as $customer ) {
972
            $data[] = array(
973
                'id'        => (int) $customer->ID,
974
                'text'      => strip_tags( sprintf( _x( '%1$s (%2$s)', 'user dropdown', 'invoicing' ), $customer->display_name, $customer->user_email ) ),
975
            );
976
        }
977
978
        wp_send_json_success( $data );
979
980
    }
981
982
    /**
983
     * Retrieves the states field for AUI forms.
984
     */
985
    public static function get_aui_states_field() {
986
987
        // Verify nonce.
988
        check_ajax_referer( 'wpinv-nonce' );
989
990
        // We need a country.
991
        if ( empty( $_GET['country'] ) ) {
992
            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...
993
        }
994
995
        $states = wpinv_get_country_states( sanitize_text_field( $_GET['country'] ) );
996
        $state  = isset( $_GET['state'] ) ? sanitize_text_field( $_GET['state'] ) : wpinv_get_default_state();
997
        $name   = isset( $_GET['name'] ) ? sanitize_text_field( $_GET['name'] ) : 'wpinv_state';
998
        $class  = isset( $_GET['class'] ) ? sanitize_text_field( $_GET['class'] ) : 'form-control-sm';
999
1000
        if ( empty( $states ) ) {
1001
1002
            $html = aui()->input(
1003
                array(
1004
                    'type'        => 'text',
1005
                    'id'          => 'wpinv_state',
1006
                    'name'        => $name,
1007
                    'label'       => __( 'State', 'invoicing' ),
1008
                    'label_type'  => 'vertical',
1009
                    'placeholder' => __( 'State', 'invoicing' ),
1010
                    'class'       => $class,
1011
                    'value'       => $state,
1012
                )
1013
            );
1014
1015
        } else {
1016
1017
            $html = aui()->select(
1018
                array(
1019
                    'id'          => 'wpinv_state',
1020
                    'name'        => $name,
1021
                    'label'       => __( 'State', 'invoicing' ),
1022
                    'label_type'  => 'vertical',
1023
                    'placeholder' => __( 'Select a state', 'invoicing' ),
1024
                    'class'       => $class,
1025
                    'value'       => $state,
1026
                    'options'     => $states,
1027
                    'data-allow-clear' => 'false',
1028
                    'select2'          => true,
1029
                )
1030
            );
1031
1032
        }
1033
1034
        wp_send_json_success(
1035
            array(
1036
                'html'   => $html,
1037
                'select' => ! empty ( $states )
1038
            )
1039
        );
1040
1041
    }
1042
1043
    /**
1044
     * Refresh prices.
1045
     *
1046
     * @since 1.0.19
1047
     */
1048
    public static function payment_form_refresh_prices() {
1049
1050
        // Check nonce.
1051
        check_ajax_referer( 'getpaid_form_nonce' );
1052
1053
        // ... form fields...
1054
        if ( empty( $_POST['getpaid_payment_form_submission'] ) ) {
1055
            _e( 'Error: Reload the page and try again.', 'invoicing' );
1056
            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...
1057
        }
1058
1059
        // Load the submission.
1060
        $submission = new GetPaid_Payment_Form_Submission();
1061
1062
        // Do we have an error?
1063
        if ( ! empty( $submission->last_error ) ) {
1064
            wp_send_json_error(
1065
                array(
1066
                    'code'  => $submission->last_error_code,
1067
                    'error' => $submission->last_error
1068
                )
1069
            );
1070
        }
1071
1072
        // Prepare the response.
1073
        $response = new GetPaid_Payment_Form_Submission_Refresh_Prices( $submission );
1074
1075
        // Filter the response.
1076
        $response = apply_filters( 'getpaid_payment_form_ajax_refresh_prices', $response->response, $submission );
1077
1078
        wp_send_json_success( $response );
1079
    }
1080
1081
}
1082
1083
WPInv_Ajax::init();