Passed
Push — master ( 8e8ce5...b0770b )
by Brian
04:08
created

getpaid_get_invoice_meta()   F

Complexity

Conditions 18
Paths 384

Size

Total Lines 147
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 18
eloc 68
c 1
b 0
f 1
nc 384
nop 1
dl 0
loc 147
rs 1.7333

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 invoice functions.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Retrieves the current invoice.
13
 */
14
function getpaid_get_current_invoice_id() {
15
16
    // Ensure that we have an invoice key.
17
    if ( empty( $_GET['invoice_key'] ) ) {
18
        return 0;
19
    }
20
21
    // Retrieve an invoice using the key.
22
    $invoice = new WPInv_Invoice( $_GET['invoice_key'] );
23
24
    // Compare the invoice key and the parsed key.
25
    if ( $invoice->get_id() != 0 && $invoice->get_key() == $_GET['invoice_key'] ) {
26
        return $invoice->get_id();
27
    }
28
29
    return 0;
30
}
31
32
/**
33
 * Checks if the current user cna view an invoice.
34
 */
35
function wpinv_user_can_view_invoice( $invoice ) {
36
    $invoice = new WPInv_Invoice( $invoice );
37
38
    // Abort if the invoice does not exist.
39
    if ( 0 == $invoice->get_id() ) {
40
        return false;
41
    }
42
43
    // Don't allow trash, draft status
44
    if ( $invoice->is_draft() ) {
45
        return false;
46
    }
47
48
    // If users are not required to login to check out, compare the invoice keys.
49
    if ( ! wpinv_require_login_to_checkout() && isset( $_GET['invoice_key'] ) && trim( $_GET['invoice_key'] ) == $invoice->get_key() ) {
50
        return true;
51
    }
52
53
    // Always enable for admins..
54
    if ( wpinv_current_user_can_manage_invoicing() || current_user_can( 'view_invoices', $invoice->get_id() ) ) { // Admin user
55
        return true;
56
    }
57
58
    // Else, ensure that this is their invoice.
59
    if ( is_user_logged_in() && $invoice->get_user_id() == get_current_user_id() ) {
60
        return true;
61
    }
62
63
    return apply_filters( 'wpinv_current_user_can_view_invoice', false, $invoice );
64
}
65
66
/**
67
 * Checks if the current user cna view an invoice receipt.
68
 */
69
function wpinv_can_view_receipt( $invoice ) {
70
	return (bool) apply_filters( 'wpinv_can_view_receipt', wpinv_user_can_view_invoice( $invoice ), $invoice );
71
}
72
73
/**
74
 * Returns an array of all invoice post types.
75
 *
76
 * @return array
77
 */
78
function getpaid_get_invoice_post_types() {
79
    $post_types = array(
80
        'wpi_quote'   => __( 'Quote', 'invoicing' ),
81
        'wpi_invoice' => __( 'Invoice', 'invoicing' ),
82
    );
83
84
    // Ensure the quotes addon is installed.
85
    if ( ! defined( 'WPINV_QUOTES_VERSION' ) ) {
86
        unset( $post_types['wpi_quote'] );
87
    }
88
89
    return apply_filters( 'getpaid_invoice_post_types', $post_types );
90
}
91
92
/**
93
 * Checks if this is an invocing post type.
94
 *
95
 *
96
 * @param string $post_type The post type to check for.
97
 */
98
function getpaid_is_invoice_post_type( $post_type ) {
99
    return is_scalar( $post_type ) && ! empty( $post_type ) && array_key_exists( $post_type, getpaid_get_invoice_post_types() );
100
}
101
102
/**
103
 * Creates a new invoice.
104
 *
105
 * @param  array $data   An array of invoice properties.
106
 * @param  bool  $wp_error       Whether to return false or WP_Error on failure.
107
 * @return int|WP_Error|WPInv_Invoice The value 0 or WP_Error on failure. The WPInv_Invoice object on success.
108
 */
109
function wpinv_create_invoice( $data = array(), $deprecated = null, $wp_error = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $deprecated is not used and could be removed. ( Ignorable by Annotation )

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

109
function wpinv_create_invoice( $data = array(), /** @scrutinizer ignore-unused */ $deprecated = null, $wp_error = false ) {

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

Loading history...
110
    $data[ 'invoice_id' ] = 0;
111
    return wpinv_insert_invoice( $data, $wp_error );
112
}
113
114
/**
115
 * Updates an existing invoice.
116
 *
117
 * @param  array $data   An array of invoice properties.
118
 * @param  bool  $wp_error       Whether to return false or WP_Error on failure.
119
 * @return int|WP_Error|WPInv_Invoice The value 0 or WP_Error on failure. The WPInv_Invoice object on success.
120
 */
121
function wpinv_update_invoice( $data = array(), $wp_error = false ) {
122
123
    // Backwards compatibility.
124
    if ( ! empty( $data['ID'] ) ) {
125
        $data['invoice_id'] = $data['ID'];
126
    }
127
128
    // Do we have an invoice id?
129
    if ( empty( $data['invoice_id'] ) ) {
130
        return $wp_error ? new WP_Error( 'invalid_invoice_id', __( 'Invalid invoice ID.', 'invoicing' ) ) : 0;
131
    }
132
133
    // Retrieve the invoice.
134
    $invoice = wpinv_get_invoice( $data['invoice_id'] );
135
136
    // And abort if it does not exist.
137
    if ( empty( $invoice ) ) {
138
        return $wp_error ? new WP_Error( 'missing_invoice', __( 'Invoice not found.', 'invoicing' ) ) : 0;
139
    }
140
141
    // Do not update totals for paid / refunded invoices.
142
    if ( $invoice->is_paid() || $invoice->is_refunded() ) {
143
144
        if ( ! empty( $data['items'] ) || ! empty( $data['cart_details'] ) ) {
145
            return $wp_error ? new WP_Error( 'paid_invoice', __( 'You can not update cart items for invoices that have already been paid for.', 'invoicing' ) ) : 0;
146
        }
147
148
    }
149
150
    return wpinv_insert_invoice( $data, $wp_error );
151
152
}
153
154
/**
155
 * Create/Update an invoice
156
 *
157
 * @param  array $data   An array of invoice properties.
158
 * @param  bool  $wp_error       Whether to return false or WP_Error on failure.
159
 * @return int|WP_Error|WPInv_Invoice The value 0 or WP_Error on failure. The WPInv_Invoice object on success.
160
 */
161
function wpinv_insert_invoice( $data = array(), $wp_error = false ) {
162
163
    // Ensure that we have invoice data.
164
    if ( empty( $data ) ) {
165
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type WPInv_Invoice|WP_Error|integer.
Loading history...
166
    }
167
168
    // The invoice id will be provided when updating an invoice.
169
    $data['invoice_id'] = ! empty( $data['invoice_id'] ) ? (int) $data['invoice_id'] : false;
170
171
    // Retrieve the invoice.
172
    $invoice = new WPInv_Invoice( $data['invoice_id'] );
173
174
    // Do we have an error?
175
    if ( ! empty( $invoice->last_error ) ) {
176
        return $wp_error ? new WP_Error( 'invalid_invoice_id', $invoice->last_error ) : 0;
177
    }
178
179
    // Backwards compatibility (billing address).
180
    if ( ! empty( $data['user_info'] ) ) {
181
182
        foreach ( $data['user_info'] as $key => $value ) {
183
184
            if ( $key == 'discounts' ) {
185
                $value = (array) $value;
186
                $data[ 'discount_code' ] = empty( $value ) ? null : $value[0];
187
            } else {
188
                $data[ $key ] = $value;
189
            }
190
191
        }
192
193
    }
194
195
    // Backwards compatibility.
196
    if ( ! empty( $data['payment_details'] ) ) {
197
198
        foreach ( $data['payment_details'] as $key => $value ) {
199
            $data[ $key ] = $value;
200
        }
201
202
    }
203
204
    // Set up the owner of the invoice.
205
    $user_id = ! empty( $data['user_id'] ) ? wpinv_clean( $data['user_id'] ) : get_current_user_id();
206
207
    // Make sure the user exists.
208
    if ( ! get_userdata( $user_id ) ) {
209
        return $wp_error ? new WP_Error( 'wpinv_invalid_user', __( 'There is no user with that ID.', 'invoicing' ) ) : 0;
210
    }
211
212
    $address = wpinv_get_user_address( $user_id );
213
214
    foreach ( $address as $key => $value ) {
215
216
        if ( $value == '' ) {
217
            $address[ $key ] = null;
218
        } else {
219
            $address[ $key ] = wpinv_clean( $value );
220
        }
221
222
    }
223
224
    // Load new data.
225
    $invoice->set_props(
226
227
        array(
228
229
            // Basic info.
230
            'template'             => isset( $data['template'] ) ? wpinv_clean( $data['template'] ) : null,
231
            'email_cc'             => isset( $data['email_cc'] ) ? wpinv_clean( $data['email_cc'] ) : null,
232
            'date_created'         => isset( $data['created_date'] ) ? wpinv_clean( $data['created_date'] ) : null,
233
            'due_date'             => isset( $data['due_date'] ) ? wpinv_clean( $data['due_date'] ) : null,
234
            'date_completed'       => isset( $data['date_completed'] ) ? wpinv_clean( $data['date_completed'] ) : null,
235
            'number'               => isset( $data['number'] ) ? wpinv_clean( $data['number'] ) : null,
236
            'key'                  => isset( $data['key'] ) ? wpinv_clean( $data['key'] ) : null,
237
            'status'               => isset( $data['status'] ) ? wpinv_clean( $data['status'] ) : null,
238
            'post_type'            => isset( $data['post_type'] ) ? wpinv_clean( $data['post_type'] ) : null,
239
            'user_ip'              => isset( $data['ip'] ) ? wpinv_clean( $data['ip'] ) : wpinv_get_ip(),
240
            'parent_id'            => isset( $data['parent'] ) ? intval( $data['parent'] ) : null,
241
            'mode'                 => isset( $data['mode'] ) ? wpinv_clean( $data['mode'] ) : null,
242
            'description'          => isset( $data['description'] ) ? wp_kses_post( $data['description'] ) : null,
243
244
            // Payment info.
245
            'disable_taxes'        => ! empty( $data['disable_taxes'] ),
246
            'currency'             => isset( $data['currency'] ) ? wpinv_clean( $data['currency'] ) : wpinv_get_currency(),
247
            'gateway'              => isset( $data['gateway'] ) ? wpinv_clean( $data['gateway'] ) : null,
248
            'transaction_id'       => isset( $data['transaction_id'] ) ? wpinv_clean( $data['transaction_id'] ) : null,
249
            'discount_code'        => isset( $data['discount_code'] ) ? wpinv_clean( $data['discount_code'] ) : null,
250
            'payment_form'         => isset( $data['payment_form'] ) ? intval( $data['payment_form'] ) : null,
251
            'submission_id'        => isset( $data['submission_id'] ) ? wpinv_clean( $data['submission_id'] ) : null,
252
            'subscription_id'      => isset( $data['subscription_id'] ) ? wpinv_clean( $data['subscription_id'] ) : null,
253
            'is_viewed'            => isset( $data['is_viewed'] ) ? wpinv_clean( $data['is_viewed'] ) : null,
254
            'fees'                 => isset( $data['fees'] ) ? wpinv_clean( $data['fees'] ) : null,
255
            'discounts'            => isset( $data['discounts'] ) ? wpinv_clean( $data['discounts'] ) : null,
256
            'taxes'                => isset( $data['taxes'] ) ? wpinv_clean( $data['taxes'] ) : null,
257
258
259
            // Billing details.
260
            'user_id'              => $data['user_id'],
261
            'first_name'           => isset( $data['first_name'] ) ? wpinv_clean( $data['first_name'] ) : $address['first_name'],
262
            'last_name'            => isset( $data['last_name'] ) ? wpinv_clean( $data['last_name'] ) : $address['last_name'],
263
            'address'              => isset( $data['address'] ) ? wpinv_clean( $data['address'] ) : $address['address'] ,
264
            'vat_number'           => isset( $data['vat_number'] ) ? wpinv_clean( $data['vat_number'] ) : $address['vat_number'],
265
            'company'              => isset( $data['company'] ) ? wpinv_clean( $data['company'] ) : $address['company'],
266
            'zip'                  => isset( $data['zip'] ) ? wpinv_clean( $data['zip'] ) : $address['zip'],
267
            'state'                => isset( $data['state'] ) ? wpinv_clean( $data['state'] ) : $address['state'],
268
            'city'                 => isset( $data['city'] ) ? wpinv_clean( $data['city'] ) : $address['city'],
269
            'country'              => isset( $data['country'] ) ? wpinv_clean( $data['country'] ) : $address['country'],
270
            'phone'                => isset( $data['phone'] ) ? wpinv_clean( $data['phone'] ) : $address['phone'],
271
            'address_confirmed'    => ! empty( $data['address_confirmed'] ),
272
273
        )
274
275
    );
276
277
    // Backwards compatibililty.
278
    if ( ! empty( $data['cart_details'] ) && is_array( $data['cart_details'] ) ) {
279
        $data['items'] = array();
280
281
        foreach( $data['cart_details'] as $_item ) {
282
283
            // Ensure that we have an item id.
284
            if ( empty(  $_item['id']  ) ) {
285
                continue;
286
            }
287
288
            // Retrieve the item.
289
            $item = new GetPaid_Form_Item(  $_item['id']  );
290
291
            // Ensure that it is purchasable.
292
            if ( ! $item->can_purchase() ) {
293
                continue;
294
            }
295
296
            // Set quantity.
297
            if ( ! empty( $_item['quantity'] ) && is_numeric( $_item['quantity'] ) ) {
298
                $item->set_quantity( $_item['quantity'] );
299
            }
300
301
            // Set price.
302
            if ( isset( $_item['item_price'] ) ) {
303
                $item->set_price( $_item['item_price'] );
304
            }
305
306
            if ( isset( $_item['custom_price'] ) ) {
307
                $item->set_price( $_item['custom_price'] );
308
            }
309
310
            // Set name.
311
            if ( ! empty( $_item['name'] ) ) {
312
                $item->set_name( $_item['name'] );
313
            }
314
315
            // Set description.
316
            if ( isset( $_item['description'] ) ) {
317
                $item->set_custom_description( $_item['description'] );
318
            }
319
320
            // Set meta.
321
            if ( isset( $_item['meta'] ) && is_array( $_item['meta'] ) ) {
322
323
                $item->set_item_meta( $_item['meta'] );
324
325
                if ( isset( $_item['meta']['description'] ) ) {
326
                    $item->set_custom_description( $_item['meta']['description'] );
327
                }
328
329
            }
330
331
            $data['items'][] = $item;
332
333
        }
334
    }
335
336
    // Add invoice items.
337
    if ( ! empty( $data['items'] ) && is_array( $data['items'] ) ) {
338
339
        $invoice->set_items( array() );
340
341
        foreach ( $data['items'] as $item ) {
342
343
            if ( is_object( $item ) && is_a( $item, 'GetPaid_Form_Item' ) && $item->can_purchase() ) {
344
                $invoice->add_item( $item );
345
            }
346
347
        }
348
349
    }
350
351
    // Save the invoice.
352
    $invoice->recalculate_total();
353
    $invoice->save();
354
355
    if ( ! $invoice->get_id() ) {
356
        return $wp_error ? new WP_Error( 'wpinv_insert_invoice_error', __( 'An error occured when saving your invoice.', 'invoicing' ) ) : 0;
357
    }
358
359
    // Add private note.
360
    if ( ! empty( $data['private_note'] ) ) {
361
        $invoice->add_note( $data['private_note'] );
362
    }
363
364
    // User notes.
365
    if ( !empty( $data['user_note'] ) ) {
366
        $invoice->add_note( $data['user_note'], true );
367
    }
368
369
    // Created via.
370
    if ( isset( $data['created_via'] ) ) {
371
        update_post_meta( $invoice->get_id(), 'wpinv_created_via', $data['created_via'] );
372
    }
373
374
    // Backwards compatiblity.
375
    if ( $invoice->is_quote() ) {
376
377
        if ( isset( $data['valid_until'] ) ) {
378
            update_post_meta( $invoice->get_id(), 'wpinv_quote_valid_until', $data['valid_until'] );
379
        }
380
381
    }
382
383
    return $invoice;
384
}
385
386
/**
387
 * Retrieves an invoice.
388
 *
389
 * @param int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object.
390
 * @param $bool $deprecated
0 ignored issues
show
Documentation Bug introduced by
The doc comment $bool at position 0 could not be parsed: Unknown type name '$bool' at position 0 in $bool.
Loading history...
391
 * @return WPInv_Invoice|null
392
 */
393
function wpinv_get_invoice( $invoice = 0, $deprecated = false ) {
394
395
    // If we are retrieving the invoice from the cart...
396
    if ( $deprecated && empty( $invoice ) ) {
397
        $invoice = (int) getpaid_get_current_invoice_id();
398
    }
399
400
    // Retrieve the invoice.
401
    if ( ! is_a( $invoice, 'WPInv_Invoice' ) ) {
402
        $invoice = new WPInv_Invoice( $invoice );
403
    }
404
405
    // Check if it exists.
406
    if ( $invoice->exists() ) {
407
        return $invoice;
408
    }
409
410
    return null;
411
}
412
413
/**
414
 * Retrieves several invoices.
415
 *
416
 * @param array $args Args to search for.
417
 * @return WPInv_Invoice[]|int[]|object
418
 */
419
function wpinv_get_invoices( $args ) {
420
421
    // Prepare args.
422
    $args = wp_parse_args(
423
        $args,
424
        array(
425
            'status'   => array_keys( wpinv_get_invoice_statuses() ),
426
            'type'     => 'wpi_invoice',
427
            'limit'    => get_option( 'posts_per_page' ),
428
            'return'   => 'objects',
429
        )
430
    );
431
432
    // Map params to wp_query params.
433
    $map_legacy = array(
434
        'numberposts'    => 'limit',
435
        'post_type'      => 'type',
436
        'post_status'    => 'status',
437
        'post_parent'    => 'parent',
438
        'author'         => 'user',
439
        'posts_per_page' => 'limit',
440
        'paged'          => 'page',
441
        'post__not_in'   => 'exclude',
442
        'post__in'       => 'include',
443
    );
444
445
    foreach ( $map_legacy as $to => $from ) {
446
        if ( isset( $args[ $from ] ) ) {
447
            $args[ $to ] = $args[ $from ];
448
            unset( $args[ $from ] );
449
        }
450
    }
451
452
    // Backwards compatibility.
453
    if ( ! empty( $args['email'] ) && empty( $args['user'] ) ) {
454
        $args['user'] = $args['email'];
455
        unset( $args['email'] );
456
    }
457
458
    // Handle cases where the user is set as an email.
459
    if ( ! empty( $args['author'] ) && is_email( $args['author'] ) ) {
460
        $user = get_user_by( 'email', $args['user'] );
461
462
        if ( $user ) {
463
            $args['author'] = $user->user_email;
464
        }
465
466
    }
467
468
    // We only want invoice ids.
469
    $args['fields'] = 'ids';
470
471
    // Show all posts.
472
    $paginate = true;
473
    if ( isset( $args['paginate'] ) ) {
474
475
        $paginate = $args['paginate'];
476
        $args['no_found_rows'] = empty( $args['paginate'] );
477
        unset( $args['paginate'] );
478
479
    }
480
481
    // Whether to return objects or fields.
482
    $return = $args['return'];
483
    unset( $args['return'] );
484
485
    // Get invoices.
486
    $invoices = new WP_Query( apply_filters( 'wpinv_get_invoices_args', $args ) );
487
488
    // Prepare the results.
489
    if ( 'objects' === $return ) {
490
        $results = array_map( 'wpinv_get_invoice', $invoices->posts );
491
    } elseif ( 'self' === $return ) {
492
        return $invoices;
493
    } else {
494
        $results = $invoices->posts;
495
    }
496
497
    if ( $paginate ) {
498
        return (object) array(
499
            'invoices'      => $results,
500
            'total'         => $invoices->found_posts,
501
            'max_num_pages' => $invoices->max_num_pages,
502
        );
503
    }
504
505
    return $results;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $results returns an array which contains values of type WP_Post which are incompatible with the documented value type WPInv_Invoice|integer.
Loading history...
506
507
}
508
509
/**
510
 * Retrieves an invoice's id from a transaction id.
511
 *
512
 * @param string $transaction_id The transaction id to check.
513
 * @return int Invoice id on success or 0 on failure
514
 */
515
function wpinv_get_id_by_transaction_id( $transaction_id ) {
516
    return WPInv_Invoice::get_invoice_id_by_field( $transaction_id, 'transaction_id' );
517
}
518
519
/**
520
 * Retrieves an invoice's id from the invoice number.
521
 *
522
 * @param string $invoice_number The invoice number to check.
523
 * @return int Invoice id on success or 0 on failure
524
 */
525
function wpinv_get_id_by_invoice_number( $invoice_number ) {
526
    return WPInv_Invoice::get_invoice_id_by_field( $invoice_number, 'number' );
527
}
528
529
/**
530
 * Retrieves an invoice's id from the invoice key.
531
 *
532
 * @param string $invoice_key The invoice key to check.
533
 * @return int Invoice id on success or 0 on failure
534
 */
535
function wpinv_get_invoice_id_by_key( $invoice_key ) {
536
    return WPInv_Invoice::get_invoice_id_by_field( $invoice_key, 'key' );
537
}
538
539
/**
540
 * Retrieves an invoice's notes.
541
 *
542
 * @param int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object.
543
 * @param string $type Optionally filter by type i.e customer|system
544
 * @return array|null
545
 */
546
function wpinv_get_invoice_notes( $invoice = 0, $type = '' ) {
547
548
    // Prepare the invoice.
549
    $invoice = wpinv_get_invoice( $invoice );
550
    if ( empty( $invoice ) ) {
551
        return NULL;
552
    }
553
554
    // Fetch notes.
555
    $notes = getpaid_notes()->get_invoice_notes( $invoice->get_id(), $type );
556
557
    // Filter the notes.
558
    return apply_filters( 'wpinv_invoice_notes', $notes, $invoice->get_id(), $type );
559
}
560
561
/**
562
 * Returns an array of columns to display on the invoices page.
563
 *
564
 * @param string $post_type
565
 */
566
function wpinv_get_user_invoices_columns( $post_type = 'wpi_invoice' ) {
567
568
    $label   = getpaid_get_post_type_label( $post_type, false );
569
    $label   = empty( $label ) ? __( 'Invoice', 'invoicing' ) : sanitize_text_field( $label );
570
    $columns = array(
571
572
            'invoice-number'  => array(
573
                'title' => $label,
574
                'class' => 'text-left'
575
            ),
576
577
            'created-date'    => array(
578
                'title' => __( 'Created Date', 'invoicing' ),
579
                'class' => 'text-left'
580
            ),
581
582
            'payment-date'    => array(
583
                'title' => __( 'Payment Date', 'invoicing' ),
584
                'class' => 'text-left'
585
            ),
586
587
            'invoice-status'  => array(
588
                'title' => __( 'Status', 'invoicing' ),
589
                'class' => 'text-center'
590
            ),
591
592
            'invoice-total'   => array(
593
                'title' => __( 'Total', 'invoicing' ),
594
                'class' => 'text-right'
595
            ),
596
597
            'invoice-actions' => array(
598
                'title' => '&nbsp;',
599
                'class' => 'text-center'
600
            ),
601
602
        );
603
604
    return apply_filters( 'wpinv_user_invoices_columns', $columns, $post_type );
605
}
606
607
/**
608
 * Displays the invoice receipt.
609
 */
610
function wpinv_payment_receipt() {
611
612
    // Find the invoice.
613
    $invoice_id = getpaid_get_current_invoice_id();
614
    $invoice = new WPInv_Invoice( $invoice_id );
615
616
    // Abort if non was found.
617
    if ( empty( $invoice_id ) || $invoice->is_draft() ) {
618
619
        return aui()->alert(
620
            array(
621
                'type'    => 'warning',
622
                'content' => __( 'We could not find your invoice', 'invoicing' ),
623
            )
624
        );
625
626
    }
627
628
    // Can the user view this invoice?
629
    if ( ! wpinv_can_view_receipt( $invoice_id ) ) {
630
631
        return aui()->alert(
632
            array(
633
                'type'    => 'warning',
634
                'content' => __( 'You are not allowed to view this receipt', 'invoicing' ),
635
            )
636
        );
637
638
    }
639
640
    // Load the template.
641
    return wpinv_get_template_html( 'invoice-receipt.php', compact( 'invoice' ) );
642
643
}
644
645
/**
646
 * Displays the invoice history.
647
 */
648
function getpaid_invoice_history( $user_id = 0, $post_type = 'wpi_invoice' ) {
649
650
    // Ensure that we have a user id.
651
    if ( empty( $user_id ) || ! is_numeric( $user_id ) ) {
652
        $user_id = get_current_user_id();
653
    }
654
655
    $label = getpaid_get_post_type_label( $post_type );
656
    $label = empty( $label ) ? __( 'Invoices', 'invoicing' ) : sanitize_text_field( $label );
657
658
    // View user id.
659
    if ( empty( $user_id ) ) {
660
661
        return aui()->alert(
662
            array(
663
                'type'    => 'warning',
664
                'content' => sprintf(
665
                    __( 'You must be logged in to view your %s.', 'invoicing' ),
666
                    strtolower( $label )
667
                )
668
            )
669
        );
670
671
    }
672
673
    // Fetch invoices.
674
    $invoices = wpinv_get_invoices(
675
676
        array(
677
            'page'      => ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1,
678
            'user'      => $user_id,
679
            'paginate'  => true,
680
            'type'      => $post_type,
681
            'status'    => array_keys( wpinv_get_invoice_statuses( false, false, $post_type ) ),
682
        )
683
684
    );
685
686
    if ( empty( $invoices->total ) ) {
687
688
        return aui()->alert(
689
            array(
690
                'type'    => 'info',
691
                'content' => sprintf(
692
                    __( 'No %s found.', 'invoicing' ),
693
                    strtolower( $label )
694
                )
695
            )
696
        );
697
698
    }
699
700
    // Load the template.
701
    return wpinv_get_template_html( 'invoice-history.php', compact( 'invoices', 'post_type' ) );
702
703
}
704
705
/**
706
 * Formats an invoice number given an invoice type.
707
 */
708
function wpinv_format_invoice_number( $number, $type = '' ) {
709
710
    // Allow other plugins to overide this.
711
    $check = apply_filters( 'wpinv_pre_format_invoice_number', null, $number, $type );
712
    if ( null !== $check ) {
713
        return $check;
714
    }
715
716
    // Ensure that we have a numeric number.
717
    if ( ! is_numeric( $number ) ) {
718
        return $number;
719
    }
720
721
    // Format the number.
722
    $padd             = absint( (int) wpinv_get_option( 'invoice_number_padd', 5 ) );
723
    $prefix           = sanitize_text_field( (string) wpinv_get_option( 'invoice_number_prefix', 'INV-' ) );
724
    $prefix           = sanitize_text_field( apply_filters( 'getpaid_invoice_type_prefix', $prefix, $type ) );
725
    $postfix          = sanitize_text_field( (string) wpinv_get_option( 'invoice_number_postfix' ) );
726
    $postfix          = sanitize_text_field( apply_filters( 'getpaid_invoice_type_postfix', $postfix, $type ) );
727
    $formatted_number = zeroise( absint( $number ), $padd );
728
729
    // Add the prefix and post fix.
730
    $formatted_number = $prefix . $formatted_number . $postfix;
731
732
    return apply_filters( 'wpinv_format_invoice_number', $formatted_number, $number, $prefix, $postfix, $padd );
733
}
734
735
/**
736
 * Returns the next invoice number.
737
 *
738
 * @param string $type.
739
 * @return int|null|bool
740
 */
741
function wpinv_get_next_invoice_number( $type = '' ) {
742
743
    // Allow plugins to overide this.
744
    $check = apply_filters( 'wpinv_get_pre_next_invoice_number', null, $type );
745
    if ( null !== $check ) {
746
        return $check;
747
    }
748
749
    // Ensure sequential invoice numbers is active.
750
    if ( ! wpinv_sequential_number_active() ) {
751
        return false;
752
    }
753
754
    // Retrieve the current number and the start number.
755
    $number = (int) get_option( 'wpinv_last_invoice_number', 0 );
756
    $start  = absint( (int) wpinv_get_option( 'invoice_sequence_start', 1 ) );
757
758
    // Ensure that we are starting at a positive integer.
759
    $start  = max( $start, 1 );
760
761
    // If this is the first invoice, use the start number.
762
    $number = max( $start, $number );
763
764
    // Format the invoice number.
765
    $formatted_number = wpinv_format_invoice_number( $number, $type );
766
767
    // Ensure that this number is unique.
768
    $invoice_id = WPInv_Invoice::get_invoice_id_by_field( $formatted_number, 'number' );
769
770
    // We found a match. Nice.
771
    if ( empty( $invoice_id ) ) {
772
        update_option( 'wpinv_last_invoice_number', $number );
773
        return apply_filters( 'wpinv_get_next_invoice_number', $number );
774
    }
775
776
    update_option( 'wpinv_last_invoice_number', $number + 1 );
777
    return wpinv_get_next_invoice_number( $type );
778
779
}
780
781
/**
782
 * The prefix used for invoice paths.
783
 */
784
function wpinv_post_name_prefix( $post_type = 'wpi_invoice' ) {
785
    return apply_filters( 'wpinv_post_name_prefix', 'inv-', $post_type );
786
}
787
788
function wpinv_generate_post_name( $post_ID ) {
789
    $prefix = wpinv_post_name_prefix( get_post_type( $post_ID ) );
790
    $post_name = sanitize_title( $prefix . $post_ID );
791
792
    return apply_filters( 'wpinv_generate_post_name', $post_name, $post_ID, $prefix );
793
}
794
795
/**
796
 * Checks if an invoice was viewed by the customer.
797
 *
798
 * @param int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object.
799
 */
800
function wpinv_is_invoice_viewed( $invoice ) {
801
    $invoice = new WPInv_Invoice( $invoice );
802
    return (bool) $invoice->get_is_viewed();
803
}
804
805
/**
806
 * Marks an invoice as viewed.
807
 *
808
 * @param int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object.
809
 */
810
function getpaid_maybe_mark_invoice_as_viewed( $invoice ) {
811
    $invoice = new WPInv_Invoice( $invoice );
812
813
    if ( get_current_user_id() == $invoice->get_user_id() && ! $invoice->get_is_viewed() ) {
814
        $invoice->set_is_viewed( true );
815
        $invoice->save();
816
    }
817
818
}
819
add_action( 'wpinv_invoice_print_before_display', 'getpaid_maybe_mark_invoice_as_viewed' );
820
add_action( 'wpinv_before_receipt', 'getpaid_maybe_mark_invoice_as_viewed' );
821
822
/**
823
 * Processes an invoice refund.
824
 *
825
 * @param WPInv_Invoice $invoice
826
 * @param array $status_transition
827
 * @todo: descrease customer/store earnings
828
 */
829
function getpaid_maybe_process_refund( $invoice, $status_transition ) {
830
831
    if ( empty( $status_transition['from'] ) || ! in_array( $status_transition['from'], array( 'publish', 'wpi-processing', 'wpi-renewal' ) ) ) {
832
        return;
833
    }
834
835
    $discount_code = $invoice->get_discount_code();
836
    if ( ! empty( $discount_code ) ) {
837
        $discount = wpinv_get_discount_obj( $discount_code );
838
839
        if ( $discount->exists() ) {
840
            $discount->increase_usage( -1 );
841
        }
842
843
    }
844
845
    do_action( 'wpinv_pre_refund_invoice', $invoice, $invoice->get_id() );
846
    do_action( 'wpinv_refund_invoice', $invoice, $invoice->get_id() );
847
    do_action( 'wpinv_post_refund_invoice', $invoice, $invoice->get_id() );
848
}
849
add_action( 'getpaid_invoice_status_wpi-refunded', 'getpaid_maybe_process_refund', 10, 2 );
850
851
852
/**
853
 * Processes invoice payments.
854
 *
855
 * @param int $invoice_id
856
 */
857
function getpaid_process_invoice_payment( $invoice_id ) {
858
859
    // Fetch the invoice.
860
    $invoice = new WPInv_Invoice( $invoice_id );
861
862
    // We only want to do this once.
863
    if ( 1 ==  get_post_meta( $invoice->get_id(), 'wpinv_processed_payment', true ) ) {
864
        return;
865
    }
866
867
    update_post_meta( $invoice->get_id(), 'wpinv_processed_payment', 1 );
868
869
    // Fires when processing a payment.
870
    do_action( 'getpaid_process_payment', $invoice );
871
872
    // Fire an action for each invoice item.
873
    foreach( $invoice->get_items() as $item ) {
874
        do_action( 'getpaid_process_item_payment', $item, $invoice );
875
    }
876
877
    // Increase discount usage.
878
    $discount_code = $invoice->get_discount_code();
879
    if ( ! empty( $discount_code ) && ! $invoice->is_renewal() ) {
880
        $discount = wpinv_get_discount_obj( $discount_code );
881
882
        if ( $discount->exists() ) {
883
            $discount->increase_usage();
884
        }
885
886
    }
887
888
    // Record reverse vat.
889
    if ( 'invoice' == $invoice->get_type() && wpinv_use_taxes() && ! $invoice->get_disable_taxes() ) {
890
891
        $taxes = $invoice->get_total_tax();
892
        if ( empty( $taxes ) && GetPaid_Payment_Form_Submission_Taxes::is_eu_transaction( $invoice->get_country() ) ) {
893
            $invoice->add_note( __( 'VAT was reverse charged', 'invoicing' ), false, false, true );
894
        }
895
896
    }
897
898
}
899
add_action( 'getpaid_invoice_payment_status_changed', 'getpaid_process_invoice_payment' );
900
901
/**
902
 * Returns an array of invoice item columns
903
 *
904
 * @param int|WPInv_Invoice $invoice
905
 * @return array
906
 */
907
function getpaid_invoice_item_columns( $invoice ) {
908
909
    // Prepare the invoice.
910
    $invoice = new WPInv_Invoice( $invoice );
911
912
    // Abort if there is no invoice.
913
    if ( 0 == $invoice->get_id() ) {
914
        return array();
915
    }
916
917
    // Line item columns.
918
    $columns = apply_filters(
919
        'getpaid_invoice_item_columns',
920
        array(
921
            'name'     => __( 'Item', 'invoicing' ),
922
            'price'    => __( 'Price', 'invoicing' ),
923
            'tax_rate' => __( 'Tax Rate', 'invoicing' ),
924
            'quantity' => __( 'Quantity', 'invoicing' ),
925
            'subtotal' => __( 'Item Subtotal', 'invoicing' ),
926
        ),
927
        $invoice
928
    );
929
930
    // Quantities.
931
    if ( isset( $columns[ 'quantity' ] ) ) {
932
933
        if ( 'hours' == $invoice->get_template() ) {
934
            $columns[ 'quantity' ] = __( 'Hours', 'invoicing' );
935
        }
936
937
        if ( ! wpinv_item_quantities_enabled() || 'amount' == $invoice->get_template() ) {
938
            unset( $columns[ 'quantity' ] );
939
        }
940
941
    }
942
943
944
    // Price.
945
    if ( isset( $columns[ 'price' ] ) ) {
946
947
        if ( 'amount' == $invoice->get_template() ) {
948
            $columns[ 'price' ] = __( 'Amount', 'invoicing' );
949
        }
950
951
        if ( 'hours' == $invoice->get_template() ) {
952
            $columns[ 'price' ] = __( 'Rate', 'invoicing' );
953
        }
954
955
    }
956
957
958
    // Sub total.
959
    if ( isset( $columns[ 'subtotal' ] ) ) {
960
961
        if ( 'amount' == $invoice->get_template() ) {
962
            unset( $columns[ 'subtotal' ] );
963
        }
964
965
    }
966
967
    // Tax rates.
968
    if ( isset( $columns[ 'tax_rate' ] ) ) {
969
970
        if ( 0 == $invoice->get_tax() ) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $invoice->get_tax() of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
971
            unset( $columns[ 'tax_rate' ] );
972
        }
973
974
    }
975
976
    return $columns;
977
}
978
979
/**
980
 * Returns an array of invoice totals rows
981
 *
982
 * @param int|WPInv_Invoice $invoice
983
 * @return array
984
 */
985
function getpaid_invoice_totals_rows( $invoice ) {
986
987
    // Prepare the invoice.
988
    $invoice = new WPInv_Invoice( $invoice );
989
990
    // Abort if there is no invoice.
991
    if ( 0 == $invoice->get_id() ) {
992
        return array();
993
    }
994
995
    $totals = apply_filters(
996
        'getpaid_invoice_totals_rows',
997
        array(
998
            'subtotal' => __( 'Subtotal', 'invoicing' ),
999
            'tax'      => __( 'Tax', 'invoicing' ),
1000
            'fee'      => __( 'Fee', 'invoicing' ),
1001
            'discount' => __( 'Discount', 'invoicing' ),
1002
            'total'    => __( 'Total', 'invoicing' ),
1003
        ),
1004
        $invoice
1005
    );
1006
1007
    if ( ( $invoice->get_disable_taxes() || ! wpinv_use_taxes() ) && isset( $totals['tax'] ) ) {
1008
        unset( $totals['tax'] );
1009
    }
1010
1011
    if ( 0 == $invoice->get_total_fees() && isset( $totals['fee'] ) ) {
1012
        unset( $totals['fee'] );
1013
    }
1014
1015
    if ( 0 == $invoice->get_total_discount() && isset( $totals['discount'] ) ) {
1016
        unset( $totals['discount'] );
1017
    }
1018
1019
    return $totals;
1020
}
1021
1022
/**
1023
 * This function is called whenever an invoice is created.
1024
 *
1025
 * @param WPInv_Invoice $invoice
1026
 */
1027
function getpaid_new_invoice( $invoice ) {
1028
1029
    if ( ! $invoice->get_status() ) {
1030
        return;
1031
    }
1032
1033
    // Add an invoice created note.
1034
    $invoice->add_note(
1035
        sprintf(
1036
            __( '%s created with the status "%s".', 'invoicing' ),
1037
            ucfirst( $invoice->get_invoice_quote_type() ),
1038
            wpinv_status_nicename( $invoice->get_status(), $invoice  )
1039
        )
1040
    );
1041
1042
}
1043
add_action( 'getpaid_new_invoice', 'getpaid_new_invoice' );
1044
1045
/**
1046
 * This function updates invoice caches.
1047
 *
1048
 * @param WPInv_Invoice $invoice
1049
 */
1050
function getpaid_update_invoice_caches( $invoice ) {
1051
1052
    // Cache invoice number.
1053
    wp_cache_set( $invoice->get_number(), $invoice->get_id(), "getpaid_invoice_numbers_to_invoice_ids" );
1054
1055
    // Cache invoice key.
1056
    wp_cache_set( $invoice->get_key(), $invoice->get_id(), "getpaid_invoice_keys_to_invoice_ids" );
1057
1058
    // (Maybe) cache transaction id.
1059
    $transaction_id = $invoice->get_transaction_id();
1060
1061
    if ( ! empty( $transaction_id ) ) {
1062
        wp_cache_set( $transaction_id, $invoice->get_id(), "getpaid_invoice_transaction_ids_to_invoice_ids" );
1063
    }
1064
1065
}
1066
add_action( 'getpaid_new_invoice', 'getpaid_update_invoice_caches', 5 );
1067
add_action( 'getpaid_update_invoice', 'getpaid_update_invoice_caches', 5 );
1068
1069
/**
1070
 * Duplicates an invoice.
1071
 *
1072
 * Please note that this function does not save the duplicated invoice.
1073
 *
1074
 * @param  WPInv_Invoice $old_invoice The invoice to duplicate
1075
 * @return WPInv_Invoice The new invoice.
1076
 */
1077
function getpaid_duplicate_invoice( $old_invoice ) {
1078
1079
    // Create the new invoice.
1080
    $invoice = new WPInv_Invoice();
1081
    $invoice->set_props(
1082
1083
        array(
1084
1085
            // Basic info.
1086
            'template'             => $old_invoice->get_template(),
1087
            'email_cc'             => $old_invoice->get_email_cc(),
1088
            'post_type'            => $old_invoice->get_post_type(),
1089
            'user_ip'              => $old_invoice->get_user_ip(),
1090
            'parent_id'            => $old_invoice->get_parent_id(),
1091
            'mode'                 => $old_invoice->get_mode(),
1092
            'description'          => $old_invoice->get_description(),
1093
            'created_via'          => $old_invoice->get_created_via(),
1094
1095
            // Payment info.
1096
            'disable_taxes'        => $old_invoice->get_disable_taxes(),
1097
            'currency'             => $old_invoice->get_currency(),
1098
            'gateway'              => $old_invoice->get_gateway(),
1099
            'discount_code'        => $old_invoice->get_discount_code(),
1100
            'payment_form'         => $old_invoice->get_payment_form(),
1101
            'submission_id'        => $old_invoice->get_submission_id(),
1102
            'subscription_id'      => $old_invoice->get_subscription_id(),
1103
            'fees'                 => $old_invoice->get_fees(),
1104
            'discounts'            => $old_invoice->get_discounts(),
1105
            'taxes'                => $old_invoice->get_taxes(),
1106
            'items'                => $old_invoice->get_items(),
1107
1108
            // Billing details.
1109
            'user_id'              => $old_invoice->get_user_id(),
1110
            'first_name'           => $old_invoice->get_first_name(),
1111
            'last_name'            => $old_invoice->get_last_name(),
1112
            'address'              => $old_invoice->get_address(),
1113
            'vat_number'           => $old_invoice->get_vat_number(),
1114
            'company'              => $old_invoice->get_company(),
1115
            'zip'                  => $old_invoice->get_zip(),
1116
            'state'                => $old_invoice->get_state(),
1117
            'city'                 => $old_invoice->get_city(),
1118
            'country'              => $old_invoice->get_country(),
1119
            'phone'                => $old_invoice->get_phone(),
1120
            'address_confirmed'    => $old_invoice->get_address_confirmed(),
1121
1122
        )
1123
1124
    );
1125
1126
    // Recalculate totals.
1127
    $invoice->recalculate_total();
1128
1129
    return $invoice;
1130
}
1131
1132
/**
1133
 * Retrieves invoice meta fields.
1134
 *
1135
 * @param WPInv_Invoice $invoice
1136
 * @return array
1137
 */
1138
function getpaid_get_invoice_meta( $invoice ) {
1139
1140
    // Load the invoice meta.
1141
    $meta = array(
1142
1143
        'number' => array(
1144
            'label' => sprintf(
1145
                __( '%s Number', 'invoicing' ),
1146
                ucfirst( $invoice->get_invoice_quote_type() )
1147
            ),
1148
            'value' => sanitize_text_field( $invoice->get_number() ),
1149
        ),
1150
1151
        'status' => array(
1152
            'label' => sprintf(
1153
                __( '%s Status', 'invoicing' ),
1154
                ucfirst( $invoice->get_invoice_quote_type() )
1155
            ),
1156
            'value' => $invoice->get_status_label_html(),
1157
        ),
1158
1159
        'date' => array(
1160
            'label' => sprintf(
1161
                __( '%s Date', 'invoicing' ),
1162
                ucfirst( $invoice->get_invoice_quote_type() )
1163
            ),
1164
            'value' => getpaid_format_date( $invoice->get_created_date() ),
1165
        ),
1166
1167
        'date_paid' => array(
1168
            'label' => __( 'Paid On', 'invoicing' ),
1169
            'value' => getpaid_format_date( $invoice->get_completed_date() ),
1170
        ),
1171
1172
        'gateway'   => array(
1173
            'label' => __( 'Payment Method', 'invoicing' ),
1174
            'value' => sanitize_text_field( $invoice->get_gateway_title() ),
1175
        ),
1176
1177
        'transaction_id' => array(
1178
            'label' => __( 'Transaction ID', 'invoicing' ),
1179
            'value' => sanitize_text_field( $invoice->get_transaction_id() ),
1180
        ),
1181
1182
        'due_date'  => array(
1183
            'label' => __( 'Due Date', 'invoicing' ),
1184
            'value' => getpaid_format_date( $invoice->get_due_date() ),
1185
        ),
1186
1187
        'vat_number' => array(
1188
            'label' => __( 'VAT Number', 'invoicing' ),
1189
            'value' => sanitize_text_field( $invoice->get_vat_number() ),
1190
        ),
1191
1192
    );
1193
1194
    $additional_meta = get_post_meta( $invoice->get_id(), 'additional_meta_data', true );
1195
1196
    if ( ! empty( $additional_meta ) ) {
1197
1198
        foreach ( $additional_meta as $label => $value ) {
1199
            $meta[ sanitize_key( $label ) ] = array(
1200
                'label' => esc_html( $label ),
1201
                'value' => esc_html( $value ),
1202
            );
1203
        }
1204
1205
    }
1206
    // If it is not paid, remove the date of payment.
1207
    if ( ! $invoice->is_paid() && ! $invoice->is_refunded() ) {
1208
        unset( $meta[ 'date_paid' ] );
1209
        unset( $meta[ 'transaction_id' ] );
1210
    }
1211
1212
    if ( ! $invoice->is_paid() || 'none' == $invoice->get_gateway() ) {
1213
        unset( $meta[ 'gateway' ] );
1214
    }
1215
1216
    // Only display the due date if due dates are enabled.
1217
    if ( ! $invoice->needs_payment() || ! wpinv_get_option( 'overdue_active' ) ) {
1218
        unset( $meta[ 'due_date' ] );
1219
    }
1220
1221
    // Only display the vat number if taxes are enabled.
1222
    if ( ! wpinv_use_taxes() ) {
1223
        unset( $meta[ 'vat_number' ] );
1224
    }
1225
1226
    // Link to the parent invoice.
1227
    if ( $invoice->get_parent_id() > 0 ) {
1228
1229
        $meta[ 'parent' ] = array(
1230
1231
            'label' => sprintf(
1232
                __( 'Parent %s', 'invoicing' ),
1233
                ucfirst( $invoice->get_invoice_quote_type() )
1234
            ),
1235
1236
            'value' => wpinv_invoice_link( $invoice->get_parent_id() ),
1237
1238
        );
1239
1240
    }
1241
1242
    
1243
    if ( $invoice->is_recurring() ) {
1244
1245
        $subscription = getpaid_get_invoice_subscriptions( $invoice );
1246
        if ( ! empty ( $subscription ) && ! is_array( $subscription ) && $subscription->exists() ) {
1247
1248
            // Display the renewal date.
1249
            if ( $subscription->is_active() && 'cancelled' != $subscription->get_status() ) {
1250
1251
                $meta[ 'renewal_date' ] = array(
1252
                    'label' => __( 'Renews On', 'invoicing' ),
1253
                    'value' => getpaid_format_date( $subscription->get_expiration() ),
1254
                );
1255
1256
            }
1257
1258
            if ( $invoice->is_parent() ) {
1259
1260
                // Display the recurring amount.
1261
                $meta[ 'recurring_total' ] = array(
1262
1263
                    'label' => __( 'Recurring Amount', 'invoicing' ),
1264
                    'value' => wpinv_price( $subscription->get_recurring_amount(), $invoice->get_currency() ),
1265
1266
                );
1267
1268
            }
1269
1270
        }
1271
    }
1272
1273
    // Add the invoice total to the meta.
1274
    $meta[ 'invoice_total' ] = array(
1275
1276
        'label' => __( 'Total Amount', 'invoicing' ),
1277
        'value' => wpinv_price( $invoice->get_total(), $invoice->get_currency() ),
1278
1279
    );
1280
1281
    // Provide a way for third party plugins to filter the meta.
1282
    $meta = apply_filters( 'getpaid_invoice_meta_data', $meta, $invoice );
1283
1284
    return $meta;
1285
1286
}
1287
1288
/**
1289
 * Returns an array of valid invoice status classes.
1290
 *
1291
 * @return array
1292
 */
1293
function getpaid_get_invoice_status_classes() {
1294
1295
	return apply_filters(
1296
		'getpaid_get_invoice_status_classes',
1297
		array(
1298
            'wpi-quote-declined' => 'badge-danger',
1299
            'wpi-failed'         => 'badge-danger',
1300
			'wpi-processing'     => 'badge-info',
1301
			'wpi-onhold'         => 'badge-warning',
1302
			'wpi-quote-accepted' => 'badge-success',
1303
			'publish'            => 'badge-success',
1304
			'wpi-renewal'        => 'badge-primary',
1305
            'wpi-cancelled'      => 'badge-secondary',
1306
            'wpi-pending'        => 'badge-dark',
1307
            'wpi-quote-pending'  => 'badge-dark',
1308
            'wpi-refunded'       => 'badge-secondary',
1309
		)
1310
	);
1311
1312
}
1313
1314
/**
1315
 * Returns an invoice's tax rate percentage.
1316
 *
1317
 * @param WPInv_Invoice $invoice
1318
 * @param GetPaid_Form_Item $item
1319
 * @return float
1320
 */
1321
function getpaid_get_invoice_tax_rate( $invoice, $item ) {
1322
1323
    $rates   = getpaid_get_item_tax_rates( $item, $invoice->get_country(), $invoice->get_state() );
1324
	$rates   = getpaid_filter_item_tax_rates( $item, $rates );
1325
    $rates   = wp_list_pluck( $rates, 'rate' );
1326
1327
    return array_sum( $rates );
1328
1329
}
1330