Passed
Branch master (50908e)
by Stiofan
07:01
created

wpinv_store_discount()   F

Complexity

Conditions 28
Paths > 20000

Size

Total Lines 64
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
cc 28
eloc 38
c 4
b 0
f 1
nc 1572864
nop 4
dl 0
loc 64
rs 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
function wpinv_get_discount_types() {
15
    $discount_types = array(
16
                        'percent'   => __( 'Percentage', 'invoicing' ),
17
                        'flat'     => __( 'Flat Amount', 'invoicing' ),
18
                    );
19
    return (array)apply_filters( 'wpinv_discount_types', $discount_types );
20
}
21
22
function wpinv_get_discount_type_name( $type = '' ) {
23
    $types = wpinv_get_discount_types();
24
    return isset( $types[ $type ] ) ? $types[ $type ] : '';
25
}
26
27
function wpinv_delete_discount( $data ) {
28
    if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'wpinv_discount_nonce' ) ) {
29
        wp_die( __( 'Trying to cheat or something?', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
30
    }
31
32
    if( ! wpinv_current_user_can_manage_invoicing() ) {
33
        wp_die( __( 'You do not have permission to delete discount codes', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
34
    }
35
36
    $discount_id = $data['discount'];
37
    wpinv_remove_discount( $discount_id );
38
}
39
add_action( 'wpinv_delete_discount', 'wpinv_delete_discount' );
40
41
function wpinv_activate_discount( $data ) {
42
    if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'wpinv_discount_nonce' ) ) {
43
        wp_die( __( 'Trying to cheat or something?', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
44
    }
45
46
    if( ! wpinv_current_user_can_manage_invoicing() ) {
47
        wp_die( __( 'You do not have permission to edit discount codes', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
48
    }
49
50
    $id = absint( $data['discount'] );
51
    wpinv_update_discount_status( $id, 'publish' );
52
}
53
add_action( 'wpinv_activate_discount', 'wpinv_activate_discount' );
54
55
function wpinv_deactivate_discount( $data ) {
56
    if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'wpinv_discount_nonce' ) ) {
57
        wp_die( __( 'Trying to cheat or something?', 'invoicing' ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
58
    }
59
60
    if( ! wpinv_current_user_can_manage_invoicing() ) {
61
        wp_die( __( 'You do not have permission to create discount codes', 'invoicing' ), array( 'response' => 403 ) );
0 ignored issues
show
Bug introduced by
array('response' => 403) of type array<string,integer> is incompatible with the type integer|string expected by parameter $title of wp_die(). ( Ignorable by Annotation )

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

61
        wp_die( __( 'You do not have permission to create discount codes', 'invoicing' ), /** @scrutinizer ignore-type */ array( 'response' => 403 ) );
Loading history...
62
    }
63
64
    $id = absint( $data['discount'] );
65
    wpinv_update_discount_status( $id, 'pending' );
66
}
67
add_action( 'wpinv_deactivate_discount', 'wpinv_deactivate_discount' );
68
69
function wpinv_get_discounts( $args = array() ) {
70
    $defaults = array(
71
        'post_type'      => 'wpi_discount',
72
        'posts_per_page' => 20,
73
        'paged'          => null,
74
        'post_status'    => array( 'publish', 'pending', 'draft', 'expired' )
75
    );
76
77
    $args = wp_parse_args( $args, $defaults );
78
79
    $discounts = get_posts( $args );
80
81
    if ( $discounts ) {
82
        return $discounts;
83
    }
84
85
    if( ! $discounts && ! empty( $args['s'] ) ) {
86
        $args['meta_key']     = '_wpi_discount_code';
87
        $args['meta_value']   = $args['s'];
88
        $args['meta_compare'] = 'LIKE';
89
        unset( $args['s'] );
90
        $discounts = get_posts( $args );
91
    }
92
93
    if( $discounts ) {
94
        return $discounts;
95
    }
96
97
    return false;
98
}
99
100
function wpinv_has_active_discounts() {
101
    $has_active = false;
102
103
    $discounts  = wpinv_get_discounts();
104
105
    if ( $discounts) {
106
        foreach ( $discounts as $discount ) {
107
            if ( wpinv_is_discount_active( $discount->ID ) ) {
108
                $has_active = true;
109
                break;
110
            }
111
        }
112
    }
113
    return $has_active;
114
}
115
116
function wpinv_get_discount( $discount_id = 0 ) {
117
    if( empty( $discount_id ) ) {
118
        return false;
119
    }
120
    
121
    if ( get_post_type( $discount_id ) != 'wpi_discount' ) {
122
        return false;
123
    }
124
125
    $discount = get_post( $discount_id );
126
127
    return $discount;
128
}
129
130
function wpinv_get_discount_by_code( $code = '' ) {
131
    if( empty( $code ) || ! is_string( $code ) ) {
132
        return false;
133
    }
134
135
    return wpinv_get_discount_by( 'code', $code );
136
}
137
138
function wpinv_get_discount_by( $field = '', $value = '' ) {
139
    if( empty( $field ) || empty( $value ) ) {
140
        return false;
141
    }
142
143
    if( ! is_string( $field ) ) {
144
        return false;
145
    }
146
147
    switch( strtolower( $field ) ) {
148
149
        case 'code':
150
            $meta_query     = array();
151
            $meta_query[]   = array(
152
                'key'     => '_wpi_discount_code',
153
                'value'   => $value,
154
                'compare' => '='
155
            );
156
            
157
            $discount = wpinv_get_discounts( array(
158
                'posts_per_page' => 1,
159
                'post_status'    => 'any',
160
                'meta_query'     => $meta_query,
161
            ) );
162
            
163
            if( $discount ) {
164
                $discount = $discount[0];
165
            }
166
167
            break;
168
169
        case 'id':
170
            $discount = wpinv_get_discount( $value );
171
172
            break;
173
174
        case 'name':
175
            $discount = get_posts( array(
176
                'post_type'      => 'wpi_discount',
177
                'name'           => $value,
178
                'posts_per_page' => 1,
179
                'post_status'    => 'any'
180
            ) );
181
182
            if( $discount ) {
183
                $discount = $discount[0];
184
            }
185
186
            break;
187
188
        default:
189
            return false;
190
    }
191
192
    if( ! empty( $discount ) ) {
193
        return $discount;
194
    }
195
196
    return false;
197
}
198
199
function wpinv_store_discount( $post_id, $data, $post, $update = false ) {
200
    $meta = array(
201
        'code'              => isset( $data['code'] )             ? sanitize_text_field( $data['code'] )              : '',
202
        'type'              => isset( $data['type'] )             ? sanitize_text_field( $data['type'] )              : 'percent',
203
        'amount'            => isset( $data['amount'] )           ? wpinv_sanitize_amount( $data['amount'] )          : '',
204
        'start'             => isset( $data['start'] )            ? sanitize_text_field( $data['start'] )             : '',
205
        'expiration'        => isset( $data['expiration'] )       ? sanitize_text_field( $data['expiration'] )        : '',
206
        'min_total'         => isset( $data['min_total'] )        ? wpinv_sanitize_amount( $data['min_total'] )       : '',
207
        'max_total'         => isset( $data['max_total'] )        ? wpinv_sanitize_amount( $data['max_total'] )       : '',
208
        'max_uses'          => isset( $data['max_uses'] )         ? absint( $data['max_uses'] )                       : '',
209
        'items'             => isset( $data['items'] )            ? $data['items']                                    : array(),
210
        'excluded_items'    => isset( $data['excluded_items'] )   ? $data['excluded_items']                           : array(),
211
        'is_recurring'      => isset( $data['recurring'] )        ? (bool)$data['recurring']                          : false,
212
        'is_single_use'     => isset( $data['single_use'] )       ? (bool)$data['single_use']                         : false,
213
        'uses'              => isset( $data['uses'] )             ? (int)$data['uses']                                : false,
214
    );
215
216
    if ( $meta['type'] == 'percent' && (float)$meta['amount'] > 100 ) {
217
        $meta['amount'] = 100;
218
    }
219
220
    if ( !empty( $meta['start'] ) ) {
221
        $meta['start']      = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['start'] ) );
222
    }
223
224
    if ( !empty( $meta['expiration'] ) ) {
225
        $meta['expiration'] = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['expiration'] ) );
226
227
        if ( !empty( $meta['start'] ) && strtotime( $meta['start'] ) > strtotime( $meta['expiration'] ) ) {
228
            $meta['expiration'] = $meta['start'];
229
        }
230
    }
231
    
232
    if ( $meta['uses'] === false ) {
233
        unset( $meta['uses'] );
234
    }
235
    
236
    if ( ! empty( $meta['items'] ) ) {
237
        foreach ( $meta['items'] as $key => $item ) {
238
            if ( 0 === intval( $item ) ) {
239
                unset( $meta['items'][ $key ] );
240
            }
241
        }
242
    }
243
    
244
    if ( ! empty( $meta['excluded_items'] ) ) {
245
        foreach ( $meta['excluded_items'] as $key => $item ) {
246
            if ( 0 === intval( $item ) ) {
247
                unset( $meta['excluded_items'][ $key ] );
248
            }
249
        }
250
    }
251
    
252
    $meta = apply_filters( 'wpinv_update_discount', $meta, $post_id, $post );
253
    
254
    do_action( 'wpinv_pre_update_discount', $meta, $post_id, $post );
255
    
256
    foreach( $meta as $key => $value ) {
257
        update_post_meta( $post_id, '_wpi_discount_' . $key, $value );
258
    }
259
    
260
    do_action( 'wpinv_post_update_discount', $meta, $post_id, $post );
261
    
262
    return $post_id;
263
}
264
265
function wpinv_remove_discount( $discount_id = 0 ) {
266
    do_action( 'wpinv_pre_delete_discount', $discount_id );
267
268
    wp_delete_post( $discount_id, true );
269
270
    do_action( 'wpinv_post_delete_discount', $discount_id );
271
}
272
273
function wpinv_update_discount_status( $code_id = 0, $new_status = 'publish' ) {
274
    $discount = wpinv_get_discount(  $code_id );
275
276
    if ( $discount ) {
277
        do_action( 'wpinv_pre_update_discount_status', $code_id, $new_status, $discount->post_status );
278
279
        wp_update_post( array( 'ID' => $code_id, 'post_status' => $new_status ) );
280
281
        do_action( 'wpinv_post_update_discount_status', $code_id, $new_status, $discount->post_status );
282
283
        return true;
284
    }
285
286
    return false;
287
}
288
289
function wpinv_discount_exists( $code_id ) {
290
    if ( wpinv_get_discount(  $code_id ) ) {
291
        return true;
292
    }
293
294
    return false;
295
}
296
297
function wpinv_is_discount_active( $code_id = null ) {
298
    $discount = wpinv_get_discount(  $code_id );
299
    $return   = false;
300
301
    if ( $discount ) {
302
        if ( wpinv_is_discount_expired( $code_id ) ) {
303
            if( defined( 'DOING_AJAX' ) ) {
304
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is expired.', 'invoicing' ) );
305
            }
306
        } elseif ( $discount->post_status == 'publish' ) {
307
            $return = true;
308
        } else {
309
            if( defined( 'DOING_AJAX' ) ) {
310
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active.', 'invoicing' ) );
311
            }
312
        }
313
    }
314
315
    return apply_filters( 'wpinv_is_discount_active', $return, $code_id );
316
}
317
318
function wpinv_get_discount_code( $code_id = null ) {
319
    $code = get_post_meta( $code_id, '_wpi_discount_code', true );
320
321
    return apply_filters( 'wpinv_get_discount_code', $code, $code_id );
322
}
323
324
function wpinv_get_discount_start_date( $code_id = null ) {
325
    $start_date = get_post_meta( $code_id, '_wpi_discount_start', true );
326
327
    return apply_filters( 'wpinv_get_discount_start_date', $start_date, $code_id );
328
}
329
330
function wpinv_get_discount_expiration( $code_id = null ) {
331
    $expiration = get_post_meta( $code_id, '_wpi_discount_expiration', true );
332
333
    return apply_filters( 'wpinv_get_discount_expiration', $expiration, $code_id );
334
}
335
336
function wpinv_get_discount_max_uses( $code_id = null ) {
337
    $max_uses = get_post_meta( $code_id, '_wpi_discount_max_uses', true );
338
339
    return (int) apply_filters( 'wpinv_get_discount_max_uses', $max_uses, $code_id );
340
}
341
342
function wpinv_get_discount_uses( $code_id = null ) {
343
    $uses = get_post_meta( $code_id, '_wpi_discount_uses', true );
344
345
    return (int) apply_filters( 'wpinv_get_discount_uses', $uses, $code_id );
346
}
347
348
function wpinv_get_discount_min_total( $code_id = null ) {
349
    $min_total = get_post_meta( $code_id, '_wpi_discount_min_total', true );
350
351
    return (float) apply_filters( 'wpinv_get_discount_min_total', $min_total, $code_id );
352
}
353
354
function wpinv_get_discount_max_total( $code_id = null ) {
355
    $max_total = get_post_meta( $code_id, '_wpi_discount_max_total', true );
356
357
    return (float) apply_filters( 'wpinv_get_discount_max_total', $max_total, $code_id );
358
}
359
360
function wpinv_get_discount_amount( $code_id = null ) {
361
    $amount = get_post_meta( $code_id, '_wpi_discount_amount', true );
362
363
    return (float) apply_filters( 'wpinv_get_discount_amount', $amount, $code_id );
364
}
365
366
function wpinv_get_discount_type( $code_id = null, $name = false ) {
367
    $type = strtolower( get_post_meta( $code_id, '_wpi_discount_type', true ) );
0 ignored issues
show
Bug introduced by
It seems like get_post_meta($code_id, ...i_discount_type', true) can also be of type false; however, parameter $str of strtolower() 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

367
    $type = strtolower( /** @scrutinizer ignore-type */ get_post_meta( $code_id, '_wpi_discount_type', true ) );
Loading history...
368
    
369
    if ( $name ) {
370
        $name = wpinv_get_discount_type_name( $type );
371
        
372
        return apply_filters( 'wpinv_get_discount_type_name', $name, $code_id );
373
    }
374
375
    return apply_filters( 'wpinv_get_discount_type', $type, $code_id );
376
}
377
378
function wpinv_discount_status( $status ) {
379
    switch( $status ){
380
        case 'expired' :
381
            $name = __( 'Expired', 'invoicing' );
382
            break;
383
        case 'publish' :
384
        case 'active' :
385
            $name = __( 'Active', 'invoicing' );
386
            break;
387
        default :
388
            $name = __( 'Inactive', 'invoicing' );
389
            break;
390
    }
391
    return $name;
392
}
393
394
function wpinv_get_discount_excluded_items( $code_id = null ) {
395
    $excluded_items = get_post_meta( $code_id, '_wpi_discount_excluded_items', true );
396
397
    if ( empty( $excluded_items ) || ! is_array( $excluded_items ) ) {
398
        $excluded_items = array();
399
    }
400
401
    return (array) apply_filters( 'wpinv_get_discount_excluded_items', $excluded_items, $code_id );
402
}
403
404
function wpinv_get_discount_item_reqs( $code_id = null ) {
405
    $item_reqs = get_post_meta( $code_id, '_wpi_discount_items', true );
406
407
    if ( empty( $item_reqs ) || ! is_array( $item_reqs ) ) {
408
        $item_reqs = array();
409
    }
410
411
    return (array) apply_filters( 'wpinv_get_discount_item_reqs', $item_reqs, $code_id );
412
}
413
414
function wpinv_get_discount_item_condition( $code_id = 0 ) {
415
    return get_post_meta( $code_id, '_wpi_discount_item_condition', true );
416
}
417
418
function wpinv_is_discount_not_global( $code_id = 0 ) {
419
    return (bool) get_post_meta( $code_id, '_wpi_discount_is_not_global', true );
420
}
421
422
function wpinv_is_discount_expired( $code_id = null ) {
423
    $discount = wpinv_get_discount(  $code_id );
424
    $return   = false;
425
426
    if ( $discount ) {
427
        $expiration = wpinv_get_discount_expiration( $code_id );
428
        if ( $expiration ) {
429
            $expiration = strtotime( $expiration );
430
            if ( $expiration < current_time( 'timestamp' ) ) {
431
                // Discount is expired
432
                wpinv_update_discount_status( $code_id, 'pending' );
433
                $return = true;
434
            }
435
        }
436
    }
437
438
    return apply_filters( 'wpinv_is_discount_expired', $return, $code_id );
439
}
440
441
function wpinv_is_discount_started( $code_id = null ) {
442
    $discount = wpinv_get_discount(  $code_id );
443
    $return   = false;
444
445
    if ( $discount ) {
446
        $start_date = wpinv_get_discount_start_date( $code_id );
447
448
        if ( $start_date ) {
449
            $start_date = strtotime( $start_date );
450
451
            if ( $start_date < current_time( 'timestamp' ) ) {
452
                // Discount has past the start date
453
                $return = true;
454
            } else {
455
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
456
            }
457
        } else {
458
            // No start date for this discount, so has to be true
459
            $return = true;
460
        }
461
    }
462
463
    return apply_filters( 'wpinv_is_discount_started', $return, $code_id );
464
}
465
466
function wpinv_check_discount_dates( $code_id = null ) {
467
    $discount = wpinv_get_discount(  $code_id );
468
    $return   = false;
469
470
    if ( $discount ) {
471
        $start_date = wpinv_get_discount_start_date( $code_id );
472
473
        if ( $start_date ) {
474
            $start_date = strtotime( $start_date );
475
476
            if ( $start_date < current_time( 'timestamp' ) ) {
477
                // Discount has past the start date
478
                $return = true;
479
            } else {
480
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
481
            }
482
        } else {
483
            // No start date for this discount, so has to be true
484
            $return = true;
485
        }
486
        
487
        if ( $return ) {
488
            $expiration = wpinv_get_discount_expiration( $code_id );
489
            
490
            if ( $expiration ) {
491
                $expiration = strtotime( $expiration );
492
                if ( $expiration < current_time( 'timestamp' ) ) {
493
                    // Discount is expired
494
                    wpinv_update_discount_status( $code_id, 'pending' );
495
                    $return = true;
496
                }
497
            }
498
        }
499
    }
500
    
501
    return apply_filters( 'wpinv_check_discount_dates', $return, $code_id );
502
}
503
504
function wpinv_is_discount_maxed_out( $code_id = null ) {
505
    $discount = wpinv_get_discount(  $code_id );
506
    $return   = false;
507
508
    if ( $discount ) {
509
        $uses = wpinv_get_discount_uses( $code_id );
510
        // Large number that will never be reached
511
        $max_uses = wpinv_get_discount_max_uses( $code_id );
512
        // Should never be greater than, but just in case
513
        if ( $uses >= $max_uses && ! empty( $max_uses ) ) {
514
            // Discount is maxed out
515
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount has reached its maximum usage.', 'invoicing' ) );
516
            $return = true;
517
        }
518
    }
519
520
    return apply_filters( 'wpinv_is_discount_maxed_out', $return, $code_id );
521
}
522
523
function wpinv_discount_is_min_met( $code_id = null ) {
524
    $discount = wpinv_get_discount( $code_id );
525
    $return   = false;
526
527
    if ( $discount ) {
528
        $min         = (float)wpinv_get_discount_min_total( $code_id );
529
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
530
531
        if ( !$min > 0 || $cart_amount >= $min ) {
532
            // Minimum has been met
533
            $return = true;
534
        } else {
535
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Minimum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $min ) ) ) );
536
        }
537
    }
538
539
    return apply_filters( 'wpinv_is_discount_min_met', $return, $code_id );
540
}
541
542
function wpinv_discount_is_max_met( $code_id = null ) {
543
    $discount = wpinv_get_discount( $code_id );
544
    $return   = false;
545
546
    if ( $discount ) {
547
        $max         = (float)wpinv_get_discount_max_total( $code_id );
548
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
549
550
        if ( !$max > 0 || $cart_amount <= $max ) {
551
            // Minimum has been met
552
            $return = true;
553
        } else {
554
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Maximum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $max ) ) ) );
555
        }
556
    }
557
558
    return apply_filters( 'wpinv_is_discount_max_met', $return, $code_id );
559
}
560
561
function wpinv_discount_is_single_use( $code_id = 0 ) {
562
    $single_use = get_post_meta( $code_id, '_wpi_discount_is_single_use', true );
563
    return (bool) apply_filters( 'wpinv_is_discount_single_use', $single_use, $code_id );
564
}
565
566
function wpinv_discount_is_recurring( $code_id = 0, $code = false ) {
567
    if ( $code ) {
568
        $discount = wpinv_get_discount_by_code( $code_id );
569
        
570
        if ( !empty( $discount ) ) {
571
            $code_id = $discount->ID;
572
        }
573
    }
574
    
575
    $recurring = get_post_meta( $code_id, '_wpi_discount_is_recurring', true );
576
    
577
    return (bool) apply_filters( 'wpinv_is_discount_recurring', $recurring, $code_id, $code );
578
}
579
580
function wpinv_discount_item_reqs_met( $code_id = null ) {
581
    $item_reqs    = wpinv_get_discount_item_reqs( $code_id );
582
    $condition    = wpinv_get_discount_item_condition( $code_id );
583
    $excluded_ps  = wpinv_get_discount_excluded_items( $code_id );
584
    $cart_items   = wpinv_get_cart_contents();
585
    $cart_ids     = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
586
    $ret          = false;
587
588
    if ( empty( $item_reqs ) && empty( $excluded_ps ) ) {
589
        $ret = true;
590
    }
591
592
    // Normalize our data for item requirements, exclusions and cart data
593
    // First absint the items, then sort, and reset the array keys
594
    $item_reqs = array_map( 'absint', $item_reqs );
595
    asort( $item_reqs );
596
    $item_reqs = array_values( $item_reqs );
597
598
    $excluded_ps  = array_map( 'absint', $excluded_ps );
599
    asort( $excluded_ps );
600
    $excluded_ps  = array_values( $excluded_ps );
601
602
    $cart_ids     = array_map( 'absint', $cart_ids );
0 ignored issues
show
Bug introduced by
It seems like $cart_ids can also be of type null; however, parameter $arr1 of array_map() does only seem to accept array, 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

602
    $cart_ids     = array_map( 'absint', /** @scrutinizer ignore-type */ $cart_ids );
Loading history...
603
    asort( $cart_ids );
604
    $cart_ids     = array_values( $cart_ids );
605
606
    // Ensure we have requirements before proceeding
607
    if ( !$ret && ! empty( $item_reqs ) ) {
608
        switch( $condition ) {
609
            case 'all' :
610
                // Default back to true
611
                $ret = true;
612
613
                foreach ( $item_reqs as $item_id ) {
614
                    if ( !wpinv_item_in_cart( $item_id ) ) {
615
                        wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
616
                        $ret = false;
617
                        break;
618
                    }
619
                }
620
621
                break;
622
623
            default : // Any
624
                foreach ( $item_reqs as $item_id ) {
625
                    if ( wpinv_item_in_cart( $item_id ) ) {
626
                        $ret = true;
627
                        break;
628
                    }
629
                }
630
631
                if( ! $ret ) {
632
                    wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
633
                }
634
635
                break;
636
        }
637
    } else {
638
        $ret = true;
639
    }
640
641
    if( ! empty( $excluded_ps ) ) {
642
        // Check that there are items other than excluded ones in the cart
643
        if( $cart_ids == $excluded_ps ) {
644
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not valid for the cart contents.', 'invoicing' ) );
645
            $ret = false;
646
        }
647
    }
648
649
    return (bool) apply_filters( 'wpinv_is_discount_item_req_met', $ret, $code_id, $condition );
650
}
651
652
function wpinv_is_discount_used( $code = null, $user = '', $code_id = 0 ) {
653
    global $wpi_checkout_id;
654
    
655
    $return = false;
656
657
    if ( empty( $code_id ) ) {
658
        $code_id = wpinv_get_discount_id_by_code( $code );
659
        
660
        if( empty( $code_id ) ) {
661
            return false; // No discount was found
662
        }
663
    }
664
665
    if ( wpinv_discount_is_single_use( $code_id ) ) {
666
        $payments = array();
667
668
        $user_id = 0;
669
        if ( is_int( $user ) ) {
670
            $user_id = absint( $user );
671
        } else if ( is_email( $user ) && $user_data = get_user_by( 'email', $user ) ) {
672
            $user_id = $user_data->ID;
673
        } else if ( $user_data = get_user_by( 'login', $user ) ) {
674
            $user_id = $user_data->ID;
675
        } else if ( absint( $user ) > 0 ) {
676
            $user_id = absint( $user );
677
        }
678
679
        if ( !empty( $user_id ) ) {
680
            $query    = array( 'user' => $user_id, 'limit' => false );
681
            $payments = wpinv_get_invoices( $query ); // Get all payments with matching user id
682
        }
683
684
        if ( $payments ) {
685
            foreach ( $payments as $payment ) {
686
                // Don't count discount used for current invoice chekcout.
687
                if ( !empty( $wpi_checkout_id ) && $wpi_checkout_id == $payment->ID ) {
688
                    continue;
689
                }
690
                
691
                if ( $payment->has_status( array( 'wpi-cancelled', 'wpi-failed' ) ) ) {
692
                    continue;
693
                }
694
695
                $discounts = $payment->get_discounts( true );
696
                if ( empty( $discounts ) ) {
697
                    continue;
698
                }
699
700
                $discounts = $discounts && !is_array( $discounts ) ? explode( ',', $discounts ) : $discounts;
701
702
                if ( !empty( $discounts ) && is_array( $discounts ) ) {
703
                    if ( in_array( strtolower( $code ), array_map( 'strtolower', $discounts ) ) ) {
704
                        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has already been redeemed.', 'invoicing' ) );
705
                        $return = true;
706
                        break;
707
                    }
708
                }
709
            }
710
        }
711
    }
712
713
    return apply_filters( 'wpinv_is_discount_used', $return, $code, $user );
714
}
715
716
function wpinv_is_discount_valid( $code = '', $user = '', $set_error = true ) {
717
    $return      = false;
718
    $discount_id = wpinv_get_discount_id_by_code( $code );
719
    $user        = trim( $user );
720
721
    if ( wpinv_get_cart_contents() ) {
722
        if ( $discount_id ) {
723
            if (
724
                wpinv_is_discount_active( $discount_id ) &&
725
                wpinv_check_discount_dates( $discount_id ) &&
726
                !wpinv_is_discount_maxed_out( $discount_id ) &&
727
                !wpinv_is_discount_used( $code, $user, $discount_id ) &&
728
                wpinv_discount_is_min_met( $discount_id ) &&
729
                wpinv_discount_is_max_met( $discount_id ) &&
730
                wpinv_discount_item_reqs_met( $discount_id )
731
            ) {
732
                $return = true;
733
            }
734
        } elseif( $set_error ) {
735
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is invalid.', 'invoicing' ) );
736
        }
737
    }
738
739
    return apply_filters( 'wpinv_is_discount_valid', $return, $discount_id, $code, $user );
740
}
741
742
function wpinv_get_discount_id_by_code( $code ) {
743
    $discount = wpinv_get_discount_by_code( $code );
744
    if( $discount ) {
745
        return $discount->ID;
746
    }
747
    return false;
748
}
749
750
function wpinv_get_discounted_amount( $code, $base_price ) {
751
    $amount      = $base_price;
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
752
    $discount_id = wpinv_get_discount_id_by_code( $code );
753
754
    if( $discount_id ) {
755
        $type        = wpinv_get_discount_type( $discount_id );
756
        $rate        = wpinv_get_discount_amount( $discount_id );
757
758
        if ( $type == 'flat' ) {
759
            // Set amount
760
            $amount = $base_price - $rate;
761
            if ( $amount < 0 ) {
762
                $amount = 0;
763
            }
764
765
        } else {
766
            // Percentage discount
767
            $amount = $base_price - ( $base_price * ( $rate / 100 ) );
768
        }
769
770
    } else {
771
772
        $amount = $base_price;
773
774
    }
775
776
    return apply_filters( 'wpinv_discounted_amount', $amount );
777
}
778
779
function wpinv_increase_discount_usage( $code ) {
780
781
    $id   = wpinv_get_discount_id_by_code( $code );
782
    $uses = wpinv_get_discount_uses( $id );
783
784
    if ( $uses ) {
785
        $uses++;
786
    } else {
787
        $uses = 1;
788
    }
789
790
    update_post_meta( $id, '_wpi_discount_uses', $uses );
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type false; however, parameter $post_id of update_post_meta() does only seem to accept integer, 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

790
    update_post_meta( /** @scrutinizer ignore-type */ $id, '_wpi_discount_uses', $uses );
Loading history...
791
792
    do_action( 'wpinv_discount_increase_use_count', $uses, $id, $code );
793
794
    return $uses;
795
796
}
797
798
function wpinv_decrease_discount_usage( $code ) {
799
800
    $id   = wpinv_get_discount_id_by_code( $code );
801
    $uses = wpinv_get_discount_uses( $id );
802
803
    if ( $uses ) {
804
        $uses--;
805
    }
806
807
    if ( $uses < 0 ) {
808
        $uses = 0;
809
    }
810
811
    update_post_meta( $id, '_wpi_discount_uses', $uses );
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type false; however, parameter $post_id of update_post_meta() does only seem to accept integer, 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

811
    update_post_meta( /** @scrutinizer ignore-type */ $id, '_wpi_discount_uses', $uses );
Loading history...
812
813
    do_action( 'wpinv_discount_decrease_use_count', $uses, $id, $code );
814
815
    return $uses;
816
817
}
818
819
function wpinv_format_discount_rate( $type, $amount ) {
820
    if ( $type == 'flat' ) {
821
        return wpinv_price( wpinv_format_amount( $amount ) );
822
    } else {
823
        return $amount . '%';
824
    }
825
}
826
827
function wpinv_set_cart_discount( $code = '' ) {    
828
    if ( wpinv_multiple_discounts_allowed() ) {
829
        // Get all active cart discounts
830
        $discounts = wpinv_get_cart_discounts();
831
    } else {
832
        $discounts = false; // Only one discount allowed per purchase, so override any existing
833
    }
834
835
    if ( $discounts ) {
836
        $key = array_search( strtolower( $code ), array_map( 'strtolower', $discounts ) );
837
        if( false !== $key ) {
838
            unset( $discounts[ $key ] ); // Can't set the same discount more than once
839
        }
840
        $discounts[] = $code;
841
    } else {
842
        $discounts = array();
843
        $discounts[] = $code;
844
    }
845
    $discounts = array_values( $discounts );
846
    
847
    $data = wpinv_get_checkout_session();
848
    if ( empty( $data ) ) {
849
        $data = array();
850
    } else {
851
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
852
            $payment_meta['user_info']['discount']  = implode( ',', $discounts );
853
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
854
        }
855
    }
856
    $data['cart_discounts'] = $discounts;
857
    
858
    wpinv_set_checkout_session( $data );
859
    
860
    return $discounts;
861
}
862
863
function wpinv_unset_cart_discount( $code = '' ) {    
864
    $discounts = wpinv_get_cart_discounts();
865
866
    if ( $code && !empty( $discounts ) && in_array( $code, $discounts ) ) {
867
        $key = array_search( $code, $discounts );
868
        unset( $discounts[ $key ] );
869
            
870
        $data = wpinv_get_checkout_session();
871
        $data['cart_discounts'] = $discounts;
872
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
873
            $payment_meta['user_info']['discount']  = !empty( $discounts ) ? implode( ',', $discounts ) : '';
874
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
875
        }
876
        
877
        wpinv_set_checkout_session( $data );
878
    }
879
880
    return $discounts;
881
}
882
883
function wpinv_unset_all_cart_discounts() {
884
    $data = wpinv_get_checkout_session();
885
    
886
    if ( !empty( $data ) && isset( $data['cart_discounts'] ) ) {
887
        unset( $data['cart_discounts'] );
888
        
889
         wpinv_set_checkout_session( $data );
890
         return true;
891
    }
892
    
893
    return false;
894
}
895
896
function wpinv_get_cart_discounts( $items = array() ) {
897
    $session = wpinv_get_checkout_session();
898
    
899
    $discounts = !empty( $session['cart_discounts'] ) ? $session['cart_discounts'] : false;
900
    return $discounts;
901
}
902
903
function wpinv_cart_has_discounts( $items = array() ) {
904
    $ret = false;
905
906
    if ( wpinv_get_cart_discounts( $items ) ) {
907
        $ret = true;
908
    }
909
    
910
    /*
911
    $invoice = wpinv_get_invoice_cart();
912
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
913
        $ret = true;
914
    }
915
    */
916
917
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
918
}
919
920
function wpinv_get_cart_discounted_amount( $items = array(), $discounts = false ) {
921
    $amount = 0.00;
922
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
923
924
    if ( $items ) {
925
        $discounts = wp_list_pluck( $items, 'discount' );
926
927
        if ( is_array( $discounts ) ) {
0 ignored issues
show
introduced by
The condition is_array($discounts) is always true.
Loading history...
928
            $discounts = array_map( 'floatval', $discounts );
929
            $amount    = array_sum( $discounts );
930
        }
931
    }
932
933
    return apply_filters( 'wpinv_get_cart_discounted_amount', $amount );
934
}
935
936
function wpinv_get_cart_items_discount_amount( $items = array(), $discount = false ) {
937
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
938
    
939
    if ( empty( $discount ) || empty( $items ) ) {
940
        return 0;
941
    }
942
943
    $amount = 0;
944
    
945
    foreach ( $items as $item ) {
946
        $amount += wpinv_get_cart_item_discount_amount( $item, $discount );
947
    }
948
    
949
    $amount = wpinv_round_amount( $amount );
950
951
    return $amount;
952
}
953
954
function wpinv_get_cart_item_discount_amount( $item = array(), $discount = false ) {
955
    global $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
956
    
957
    $amount = 0;
958
959
    if ( empty( $item ) || empty( $item['id'] ) ) {
960
        return $amount;
961
    }
962
963
    if ( empty( $item['quantity'] ) ) {
964
        return $amount;
965
    }
966
967
    if ( empty( $item['options'] ) ) {
968
        $item['options'] = array();
969
    }
970
971
    $price            = wpinv_get_cart_item_price( $item['id'], $item, $item['options'] );
972
    $discounted_price = $price;
973
974
    $discounts = false === $discount ? wpinv_get_cart_discounts() : $discount;
975
    if ( empty( $discounts ) ) {
976
        return $amount;
977
    }
978
979
    if ( $discounts ) {
980
        if ( is_array( $discounts ) ) {
981
            $discounts = array_values( $discounts );
982
        } else {
983
            $discounts = explode( ',', $discounts );
984
        }
985
    }
986
987
    if( $discounts ) {
988
        foreach ( $discounts as $discount ) {
989
            $code_id = wpinv_get_discount_id_by_code( $discount );
990
991
            // Check discount exists
992
            if( ! $code_id ) {
993
                continue;
994
            }
995
996
            $reqs           = wpinv_get_discount_item_reqs( $code_id );
997
            $excluded_items = wpinv_get_discount_excluded_items( $code_id );
998
999
            // Make sure requirements are set and that this discount shouldn't apply to the whole cart
1000
            if ( !empty( $reqs ) && wpinv_is_discount_not_global( $code_id ) ) {
1001
                foreach ( $reqs as $item_id ) {
1002
                    if ( $item_id == $item['id'] && ! in_array( $item['id'], $excluded_items ) ) {
1003
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1004
                    }
1005
                }
1006
            } else {
1007
                // This is a global cart discount
1008
                if ( !in_array( $item['id'], $excluded_items ) ) {
1009
                    if ( 'flat' === wpinv_get_discount_type( $code_id ) ) {
1010
                        $items_subtotal    = 0.00;
1011
                        $cart_items        = wpinv_get_cart_contents();
1012
                        
1013
                        foreach ( $cart_items as $cart_item ) {
1014
                            if ( ! in_array( $cart_item['id'], $excluded_items ) ) {
1015
                                $options = !empty( $cart_item['options'] ) ? $cart_item['options'] : array();
1016
                                $item_price      = wpinv_get_cart_item_price( $cart_item['id'], $cart_item, $options );
1017
                                $items_subtotal += $item_price * $cart_item['quantity'];
1018
                            }
1019
                        }
1020
1021
                        $subtotal_percent  = ( ( $price * $item['quantity'] ) / $items_subtotal );
1022
                        $code_amount       = wpinv_get_discount_amount( $code_id );
1023
                        $discounted_amount = $code_amount * $subtotal_percent;
1024
                        $discounted_price -= $discounted_amount;
1025
1026
                        $wpinv_flat_discount_total += round( $discounted_amount, wpinv_currency_decimal_filter() );
1027
1028
                        if ( $wpinv_is_last_cart_item && $wpinv_flat_discount_total < $code_amount ) {
1029
                            $adjustment = $code_amount - $wpinv_flat_discount_total;
1030
                            $discounted_price -= $adjustment;
1031
                        }
1032
                    } else {
1033
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1034
                    }
1035
                }
1036
            }
1037
        }
1038
1039
        $amount = ( $price - apply_filters( 'wpinv_get_cart_item_discounted_amount', $discounted_price, $discounts, $item, $price ) );
1040
1041
        if ( 'flat' !== wpinv_get_discount_type( $code_id ) ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code_id seems to be defined by a foreach iteration on line 988. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1042
            $amount = $amount * $item['quantity'];
1043
        }
1044
    }
1045
1046
    return $amount;
1047
}
1048
1049
function wpinv_cart_discounts_html( $items = array() ) {
1050
    echo wpinv_get_cart_discounts_html( $items );
1051
}
1052
1053
function wpinv_get_cart_discounts_html( $items = array(), $discounts = false ) {
1054
    global $wpi_cart_columns;
1055
    
1056
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
1057
    
1058
    if ( !$discounts ) {
1059
        $discounts = wpinv_get_cart_discounts( $items );
1060
    }
1061
1062
    if ( !$discounts ) {
1063
        return;
1064
    }
1065
    
1066
    $discounts = is_array( $discounts ) ? $discounts : array( $discounts );
1067
    
1068
    $html = '';
1069
1070
    foreach ( $discounts as $discount ) {
1071
        $discount_id    = wpinv_get_discount_id_by_code( $discount );
1072
        $discount_value = wpinv_get_discount_amount( $discount_id );
1073
        $rate           = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), $discount_value );
1074
        $amount         = wpinv_get_cart_items_discount_amount( $items, $discount );
1075
        $remove_btn     = '<a title="' . esc_attr__( 'Remove discount', 'invoicing' ) . '" data-code="' . $discount . '" data-value="' . $discount_value . '" class="wpi-discount-remove" href="javascript:void(0);">[<i class="fa fa-times" aria-hidden="true"></i>]</a> ';
1076
        
1077
        $html .= '<tr class="wpinv_cart_footer_row wpinv_cart_discount_row">';
1078
        ob_start();
1079
        do_action( 'wpinv_checkout_table_discount_first', $items );
1080
        $html .= ob_get_clean();
1081
        $html .= '<td class="wpinv_cart_discount_label text-right" colspan="' . $wpi_cart_columns . '">' . $remove_btn . '<strong>' . wpinv_cart_discount_label( $discount, $rate, false ) . '</strong></td><td class="wpinv_cart_discount text-right"><span data-discount="' . $amount . '" class="wpinv_cart_discount_amount">&ndash;' . wpinv_price( wpinv_format_amount( $amount ) ) . '</span></td>';
1082
        ob_start();
1083
        do_action( 'wpinv_checkout_table_discount_last', $items );
1084
        $html .= ob_get_clean();
1085
        $html .= '</tr>';
1086
    }
1087
1088
    return apply_filters( 'wpinv_get_cart_discounts_html', $html, $discounts, $rate );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rate seems to be defined by a foreach iteration on line 1070. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1089
}
1090
1091
function wpinv_display_cart_discount( $formatted = false, $echo = false ) {
1092
    $discounts = wpinv_get_cart_discounts();
1093
1094
    if ( empty( $discounts ) ) {
1095
        return false;
1096
    }
1097
1098
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1099
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1100
1101
    if ( $echo ) {
1102
        echo $amount;
1103
    }
1104
1105
    return $amount;
1106
}
1107
1108
function wpinv_remove_cart_discount() {
1109
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1110
        return;
1111
    }
1112
1113
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1114
1115
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1116
1117
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1118
1119
    wp_redirect( wpinv_get_checkout_uri() ); wpinv_die();
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_checkout_uri() can also be of type false; however, parameter $location of wp_redirect() 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

1119
    wp_redirect( /** @scrutinizer ignore-type */ wpinv_get_checkout_uri() ); wpinv_die();
Loading history...
1120
}
1121
add_action( 'wpinv_remove_cart_discount', 'wpinv_remove_cart_discount' );
1122
1123
function wpinv_maybe_remove_cart_discount( $cart_key = 0 ) {
1124
    $discounts = wpinv_get_cart_discounts();
1125
1126
    if ( !$discounts ) {
1127
        return;
1128
    }
1129
1130
    foreach ( $discounts as $discount ) {
1131
        if ( !wpinv_is_discount_valid( $discount ) ) {
1132
            wpinv_unset_cart_discount( $discount );
1133
        }
1134
    }
1135
}
1136
add_action( 'wpinv_post_remove_from_cart', 'wpinv_maybe_remove_cart_discount' );
1137
1138
function wpinv_multiple_discounts_allowed() {
1139
    $ret = wpinv_get_option( 'allow_multiple_discounts', false );
1140
    return (bool) apply_filters( 'wpinv_multiple_discounts_allowed', $ret );
1141
}
1142
1143
function wpinv_get_discount_label( $code, $echo = true ) {
1144
    $label = wp_sprintf( __( 'Discount%1$s', 'invoicing' ), ( $code != '' && $code != 'none' ? ' (<code>' . $code . '</code>)': '' ) );
1145
    $label = apply_filters( 'wpinv_get_discount_label', $label, $code );
1146
1147
    if ( $echo ) {
1148
        echo $label;
1149
    } else {
1150
        return $label;
1151
    }
1152
}
1153
1154
function wpinv_cart_discount_label( $code, $rate, $echo = true ) {
1155
    $label = wp_sprintf( __( 'Discount: %s', 'invoicing' ), $code );
1156
    $label = apply_filters( 'wpinv_cart_discount_label', $label, $code, $rate );
1157
1158
    if ( $echo ) {
1159
        echo $label;
1160
    } else {
1161
        return $label;
1162
    }
1163
}
1164
1165
function wpinv_check_delete_discount( $check, $post, $force_delete ) {
1166
    if ( $post->post_type == 'wpi_discount' && wpinv_get_discount_uses( $post->ID ) > 0 ) {
1167
        return true;
1168
    }
1169
    
1170
    return $check;
1171
}
1172
add_filter( 'pre_delete_post', 'wpinv_check_delete_discount', 10, 3 );
1173
1174
function wpinv_checkout_form_validate_discounts() {
1175
    global $wpi_checkout_id;
1176
    
1177
    $discounts = wpinv_get_cart_discounts();
1178
    
1179
    if ( !empty( $discounts ) ) {
1180
        $invalid = false;
1181
        
1182
        foreach ( $discounts as $key => $code ) {
1183
            if ( !wpinv_is_discount_valid( $code, (int)wpinv_get_user_id( $wpi_checkout_id ) ) ) {
1184
                $invalid = true;
1185
                
1186
                wpinv_unset_cart_discount( $code );
1187
            }
1188
        }
1189
        
1190
        if ( $invalid ) {
1191
            $errors = wpinv_get_errors();
1192
            $error  = !empty( $errors['wpinv-discount-error'] ) ? $errors['wpinv-discount-error'] . ' ' : '';
1193
            $error  .= __( 'The discount has been removed from cart.', 'invoicing' );
1194
            wpinv_set_error( 'wpinv-discount-error', $error );
1195
            
1196
            wpinv_recalculate_tax( true );
1197
        }
1198
    }
1199
}
1200
add_action( 'wpinv_before_checkout_form', 'wpinv_checkout_form_validate_discounts', -10 );
1201
1202
function wpinv_discount_amount() {
1203
    $output = 0.00;
1204
    
1205
    return apply_filters( 'wpinv_discount_amount', $output );
1206
}