Passed
Push — master ( 32735f...12790d )
by Brian
04:58 queued 10s
created

wpinv_get_discount_by()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 2
b 0
f 0
nc 2
nop 2
dl 0
loc 7
rs 10
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_get_all_discounts( $args = array() ) {
101
102
    $args = wp_parse_args( $args, array(
103
        'status'         => array( 'publish' ),
104
        'limit'          => get_option( 'posts_per_page' ),
105
        'page'           => 1,
106
        'exclude'        => array(),
107
        'orderby'        => 'date',
108
        'order'          => 'DESC',
109
        'type'           => array_keys( wpinv_get_discount_types() ),
110
        'meta_query'     => array(),
111
        'return'         => 'objects',
112
        'paginate'       => false,
113
    ) );
114
115
    $wp_query_args = array(
116
        'post_type'      => 'wpi_discount',
117
        'post_status'    => $args['status'],
118
        'posts_per_page' => $args['limit'],
119
        'meta_query'     => $args['meta_query'],
120
        'fields'         => 'ids',
121
        'orderby'        => $args['orderby'],
122
        'order'          => $args['order'],
123
        'paged'          => absint( $args['page'] ),
124
    );
125
126
    if ( ! empty( $args['exclude'] ) ) {
127
        $wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
128
    }
129
130
    if ( ! $args['paginate' ] ) {
131
        $wp_query_args['no_found_rows'] = true;
132
    }
133
134
    if ( ! empty( $args['search'] ) ) {
135
136
        $wp_query_args['meta_query'][] = array(
137
            'key'     => '_wpi_discount_code',
138
            'value'   => $args['search'],
139
            'compare' => 'LIKE',
140
        );
141
142
    }
143
    
144
    if ( ! empty( $args['type'] ) ) {
145
        $types = wpinv_parse_list( $args['type'] );
146
        $wp_query_args['meta_query'][] = array(
147
            'key'     => '_wpi_discount_type',
148
            'value'   => implode( ',', $types ),
149
            'compare' => 'IN',
150
        );
151
    }
152
153
    $wp_query_args = apply_filters('wpinv_get_discount_args', $wp_query_args, $args);
154
155
    // Get results.
156
    $discounts = new WP_Query( $wp_query_args );
157
158
    if ( 'objects' === $args['return'] ) {
159
        $return = array_map( 'get_post', $discounts->posts );
160
    } elseif ( 'self' === $args['return'] ) {
161
        return $discounts;
162
    } else {
163
        $return = $discounts->posts;
164
    }
165
166
    if ( $args['paginate' ] ) {
167
        return (object) array(
168
            'discounts'      => $return,
169
            'total'         => $discounts->found_posts,
170
            'max_num_pages' => $discounts->max_num_pages,
171
        );
172
    } else {
173
        return $return;
174
    }
175
176
}
177
178
function wpinv_has_active_discounts() {
179
    $has_active = false;
180
181
    $discounts  = wpinv_get_discounts();
182
183
    if ( $discounts) {
184
        foreach ( $discounts as $discount ) {
185
            if ( wpinv_is_discount_active( $discount->ID ) ) {
186
                $has_active = true;
187
                break;
188
            }
189
        }
190
    }
191
    return $has_active;
192
}
193
194
function wpinv_get_discount( $discount_id = 0 ) {
195
    if( empty( $discount_id ) ) {
196
        return false;
197
    }
198
    
199
    if ( get_post_type( $discount_id ) != 'wpi_discount' ) {
200
        return false;
201
    }
202
203
    $discount = get_post( $discount_id );
204
205
    return $discount;
206
}
207
208
/**
209
 * Fetches a discount object.
210
 * 
211
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
212
 * @since 1.0.15
213
 * @return WPInv_Discount
214
 */
215
function wpinv_get_discount_obj( $discount = 0 ) {
216
    return new WPInv_Discount( $discount );
217
}
218
219
/**
220
 * Fetch a discount from the db/cache using its discount code.
221
 * 
222
 * @param string $code The discount code.
223
 * @return bool|WP_Post
224
 */
225
function wpinv_get_discount_by_code( $code = '' ) {
226
    return wpinv_get_discount_by( 'code', $code );
227
}
228
229
/**
230
 * Fetch a discount from the db/cache using a given field.
231
 * 
232
 * @param string $field The field to query against: 'ID', 'discount_code', 'code', 'name'
233
 * @param string|int $value The field value
234
 * @return bool|WP_Post
235
 */
236
function wpinv_get_discount_by( $field = '', $value = '' ) {
237
    $data = WPInv_Discount::get_data_by( $field, $value );
238
    if( empty( $data ) ) {
239
        return false;
240
    }
241
242
    return get_post( $data['ID'] );
243
}
244
245
/**
246
 * Updates a discount in the database.
247
 * 
248
 * @param int $post_id The discount's ID.
249
 * @param array $data The discount's properties.
250
 * @return bool
251
 */
252
function wpinv_store_discount( $post_id, $data, $post, $update = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $update 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

252
function wpinv_store_discount( $post_id, $data, $post, /** @scrutinizer ignore-unused */ $update = 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...
253
    $meta = array(
254
        'code'              => isset( $data['code'] )             ? sanitize_text_field( $data['code'] )              : '',
255
        'type'              => isset( $data['type'] )             ? sanitize_text_field( $data['type'] )              : 'percent',
256
        'amount'            => isset( $data['amount'] )           ? wpinv_sanitize_amount( $data['amount'] )          : '',
257
        'start'             => isset( $data['start'] )            ? sanitize_text_field( $data['start'] )             : '',
258
        'expiration'        => isset( $data['expiration'] )       ? sanitize_text_field( $data['expiration'] )        : '',
259
        'min_total'         => isset( $data['min_total'] )        ? wpinv_sanitize_amount( $data['min_total'] )       : '',
260
        'max_total'         => isset( $data['max_total'] )        ? wpinv_sanitize_amount( $data['max_total'] )       : '',
261
        'max_uses'          => isset( $data['max_uses'] )         ? absint( $data['max_uses'] )                       : '',
262
        'items'             => isset( $data['items'] )            ? $data['items']                                    : array(),
263
        'excluded_items'    => isset( $data['excluded_items'] )   ? $data['excluded_items']                           : array(),
264
        'is_recurring'      => isset( $data['recurring'] )        ? (bool)$data['recurring']                          : false,
265
        'is_single_use'     => isset( $data['single_use'] )       ? (bool)$data['single_use']                         : false,
266
        'uses'              => isset( $data['uses'] )             ? (int)$data['uses']                                : false,
267
    );
268
269
    if ( $meta['type'] == 'percent' && (float)$meta['amount'] > 100 ) {
270
        $meta['amount'] = 100;
271
    }
272
273
    if ( !empty( $meta['start'] ) ) {
274
        $meta['start']      = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['start'] ) );
275
    }
276
277
    if ( !empty( $meta['expiration'] ) ) {
278
        $meta['expiration'] = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['expiration'] ) );
279
280
        if ( !empty( $meta['start'] ) && strtotime( $meta['start'] ) > strtotime( $meta['expiration'] ) ) {
281
            $meta['expiration'] = $meta['start'];
282
        }
283
    }
284
    
285
    if ( $meta['uses'] === false ) {
286
        unset( $meta['uses'] );
287
    }
288
    
289
    if ( ! empty( $meta['items'] ) ) {
290
        foreach ( $meta['items'] as $key => $item ) {
291
            if ( 0 === intval( $item ) ) {
292
                unset( $meta['items'][ $key ] );
293
            }
294
        }
295
    }
296
    
297
    if ( ! empty( $meta['excluded_items'] ) ) {
298
        foreach ( $meta['excluded_items'] as $key => $item ) {
299
            if ( 0 === intval( $item ) ) {
300
                unset( $meta['excluded_items'][ $key ] );
301
            }
302
        }
303
    }
304
    
305
    $meta = apply_filters( 'wpinv_update_discount', $meta, $post_id, $post );
306
    
307
    do_action( 'wpinv_pre_update_discount', $meta, $post_id, $post );
308
    
309
    foreach( $meta as $key => $value ) {
310
        update_post_meta( $post_id, '_wpi_discount_' . $key, $value );
311
    }
312
    
313
    do_action( 'wpinv_post_update_discount', $meta, $post_id, $post );
314
    
315
    return $post_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $post_id returns the type integer which is incompatible with the documented return type boolean.
Loading history...
316
}
317
318
/**
319
 * Delectes a discount from the database.
320
 * 
321
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
322
 * @return bool
323
 */
324
function wpinv_remove_discount( $discount = 0 ) {
325
326
    $discount = wpinv_get_discount_obj( $discount );
327
    if( ! $discount->exists() ) {
328
        return false;
329
    }
330
331
    $discount->remove();
332
    return true;
333
}
334
335
/**
336
 * Updates a discount status.
337
 * 
338
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
339
 * @param string $new_status
340
 * @return bool
341
 */
342
function wpinv_update_discount_status( $discount = 0, $new_status = 'publish' ) {
343
    $discount = wpinv_get_discount_obj( $discount );
344
    return $discount->update_status( $new_status );
345
}
346
347
/**
348
 * Checks if a discount exists.
349
 * 
350
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
351
 * @return bool
352
 */
353
function wpinv_discount_exists( $discount ) {
354
    $discount = wpinv_get_discount_obj( $discount );
355
    return $discount->exists();
356
}
357
358
function wpinv_is_discount_active( $code_id = null ) {
359
    $discount = wpinv_get_discount(  $code_id );
360
    $return   = false;
361
362
    if ( $discount ) {
363
        if ( wpinv_is_discount_expired( $code_id ) ) {
364
            if( defined( 'DOING_AJAX' ) ) {
365
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is expired.', 'invoicing' ) );
366
            }
367
        } elseif ( $discount->post_status == 'publish' ) {
368
            $return = true;
369
        } else {
370
            if( defined( 'DOING_AJAX' ) ) {
371
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active.', 'invoicing' ) );
372
            }
373
        }
374
    }
375
376
    return apply_filters( 'wpinv_is_discount_active', $return, $code_id );
377
}
378
379
function wpinv_get_discount_code( $code_id = null ) {
380
    $code = get_post_meta( $code_id, '_wpi_discount_code', true );
381
382
    return apply_filters( 'wpinv_get_discount_code', $code, $code_id );
383
}
384
385
function wpinv_get_discount_start_date( $code_id = null ) {
386
    $start_date = get_post_meta( $code_id, '_wpi_discount_start', true );
387
388
    return apply_filters( 'wpinv_get_discount_start_date', $start_date, $code_id );
389
}
390
391
function wpinv_get_discount_expiration( $code_id = null ) {
392
    $expiration = get_post_meta( $code_id, '_wpi_discount_expiration', true );
393
394
    return apply_filters( 'wpinv_get_discount_expiration', $expiration, $code_id );
395
}
396
397
/**
398
 * Returns the number of maximum number of times a discount can been used.
399
 * 
400
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
401
 * @return int
402
 */
403
function wpinv_get_discount_max_uses( $discount = array() ) {
404
    $discount = wpinv_get_discount_obj( $discount );
405
    return (int) $discount->max_uses;
406
}
407
408
/**
409
 * Returns the number of times a discount has been used.
410
 * 
411
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
412
 * @return int
413
 */
414
function wpinv_get_discount_uses( $discount = array() ) {
415
    $discount = wpinv_get_discount_obj( $discount );
416
    return (int) $discount->uses;
417
}
418
419
/**
420
 * Returns the minimum invoice amount required to use a discount.
421
 * 
422
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
423
 * @return float
424
 */
425
function wpinv_get_discount_min_total( $discount = array() ) {
426
    $discount = wpinv_get_discount_obj( $discount );
427
    return (float) $discount->min_total;
428
}
429
430
/**
431
 * Returns the maximum invoice amount required to use a discount.
432
 * 
433
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
434
 * @return float
435
 */
436
function wpinv_get_discount_max_total( $discount = array() ) {
437
    $discount = wpinv_get_discount_obj( $discount );
438
    return (float) $discount->max_total;
439
}
440
441
/**
442
 * Returns a discount's amount.
443
 * 
444
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
445
 * @return float
446
 */
447
function wpinv_get_discount_amount( $discount = array() ) {
448
    $discount = wpinv_get_discount_obj( $discount );
449
    return (float) $discount->amount;
450
}
451
452
/**
453
 * Returns a discount's type.
454
 * 
455
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
456
 * @param bool $name 
457
 * @return string
458
 */
459
function wpinv_get_discount_type( $discount = array(), $name = false ) {
460
    $discount = wpinv_get_discount_obj( $discount );
461
462
    // Are we returning the name or just the type.
463
    if( $name ) {
464
        return $discount->type_name;
465
    }
466
467
    return $discount->type;
468
}
469
470
function wpinv_discount_status( $status ) {
471
    switch( $status ){
472
        case 'expired' :
473
            $name = __( 'Expired', 'invoicing' );
474
            break;
475
        case 'publish' :
476
        case 'active' :
477
            $name = __( 'Active', 'invoicing' );
478
            break;
479
        default :
480
            $name = __( 'Inactive', 'invoicing' );
481
            break;
482
    }
483
    return $name;
484
}
485
486
/**
487
 * Returns a discount's excluded items.
488
 * 
489
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
490
 * @return array
491
 */
492
function wpinv_get_discount_excluded_items( $discount = array() ) {
493
    $discount = wpinv_get_discount_obj( $discount );
494
    return $discount->excluded_items;
495
}
496
497
/**
498
 * Returns a discount's required items.
499
 * 
500
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
501
 * @return array
502
 */
503
function wpinv_get_discount_item_reqs( $discount = array() ) {
504
    $discount = wpinv_get_discount_obj( $discount );
505
    return $discount->items;
506
}
507
508
function wpinv_get_discount_item_condition( $code_id = 0 ) {
509
    return get_post_meta( $code_id, '_wpi_discount_item_condition', true );
510
}
511
512
function wpinv_is_discount_not_global( $code_id = 0 ) {
513
    return (bool) get_post_meta( $code_id, '_wpi_discount_is_not_global', true );
514
}
515
516
/**
517
 * Checks if a given discount has expired.
518
 * 
519
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
520
 * @return bool
521
 */
522
function wpinv_is_discount_expired( $discount = array() ) {
523
    $discount = wpinv_get_discount_obj( $discount );
524
525
    if ( $discount->is_expired() ) {
526
        $discount->update_status( 'pending' );
527
528
        if( empty( $started ) ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $started seems to never exist and therefore empty should always be true.
Loading history...
529
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount has expired.', 'invoicing' ) );
530
        }
531
        return true;
532
    }
533
534
    return false;
535
}
536
537
/**
538
 * Checks if a given discount has started.
539
 * 
540
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
541
 * @return bool
542
 */
543
function wpinv_is_discount_started( $discount = array() ) {
544
    $discount = wpinv_get_discount_obj( $discount );
545
    $started  = $discount->has_started();
546
547
    if( empty( $started ) ) {
548
        wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
549
    }
550
551
    return $started;
552
}
553
554
/**
555
 * Checks discount dates.
556
 * 
557
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
558
 * @return bool
559
 */
560
function wpinv_check_discount_dates( $discount ) {
561
    $discount = wpinv_get_discount_obj( $discount );
562
    $return   = wpinv_is_discount_started( $discount ) && ! wpinv_is_discount_expired( $discount );
563
    return apply_filters( 'wpinv_check_discount_dates', $return, $discount->ID, $discount, $discount->code );
564
}
565
566
/**
567
 * Checks if a discount is maxed out.
568
 * 
569
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
570
 * @return bool
571
 */
572
function wpinv_is_discount_maxed_out( $discount ) {
573
    $discount    = wpinv_get_discount_obj( $discount );
574
    $maxed_out   = $discount->has_exceeded_limit();
575
576
    if ( $maxed_out ) {
577
        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has reached its maximum usage.', 'invoicing' ) );
578
    }
579
580
    return $maxed_out;
581
} 
582
583
/**
584
 * Checks if an amount meets a discount's minimum amount.
585
 * 
586
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
587
 * @return bool
588
 */
589
function wpinv_discount_is_min_met( $discount ) {
590
    $discount    = wpinv_get_discount_obj( $discount );
591
    $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $discount->ID );
592
    $min_met     = $discount->is_minimum_amount_met( $cart_amount );
593
594
    if ( ! $min_met ) {
595
        wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Minimum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $discount->min_total ) ) ) );
596
    }
597
598
    return $min_met;
599
}
600
601
/**
602
 * Checks if an amount meets a discount's maximum amount.
603
 * 
604
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
605
 * @return bool
606
 */
607
function wpinv_discount_is_max_met( $discount ) {
608
    $discount    = wpinv_get_discount_obj( $discount );
609
    $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $discount->ID );
610
    $max_met     = $discount->is_maximum_amount_met( $cart_amount );
611
612
    if ( ! $max_met ) {
613
        wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Maximum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $discount->max_total ) ) ) );
614
    }
615
616
    return $max_met;
617
}
618
619
/**
620
 * Checks if a discount can only be used once per user.
621
 * 
622
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
623
 * @return bool
624
 */
625
function wpinv_discount_is_single_use( $discount ) {
626
    $discount    = wpinv_get_discount_obj( $discount );
627
    return $discount->is_single_use;
628
}
629
630
/**
631
 * Checks if a discount is recurring.
632
 * 
633
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
634
 * @param int|array|string|WPInv_Discount $code discount data, object, ID or code.
635
 * @return bool
636
 */
637
function wpinv_discount_is_recurring( $discount = 0, $code = 0 ) {
638
639
    if( ! empty( $discount ) ) {
640
        $discount    = wpinv_get_discount_obj( $discount );
641
    } else {
642
        $discount    = wpinv_get_discount_obj( $code );
643
    }
644
    
645
    return $discount->is_recurring;
646
}
647
648
function wpinv_discount_item_reqs_met( $code_id = null ) {
649
    $item_reqs    = wpinv_get_discount_item_reqs( $code_id );
650
    $condition    = wpinv_get_discount_item_condition( $code_id );
651
    $excluded_ps  = wpinv_get_discount_excluded_items( $code_id );
652
    $cart_items   = wpinv_get_cart_contents();
653
    $cart_ids     = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
654
    $ret          = false;
655
656
    if ( empty( $item_reqs ) && empty( $excluded_ps ) ) {
657
        $ret = true;
658
    }
659
660
    // Normalize our data for item requirements, exclusions and cart data
661
    // First absint the items, then sort, and reset the array keys
662
    $item_reqs = array_map( 'absint', $item_reqs );
663
    asort( $item_reqs );
664
    $item_reqs = array_values( $item_reqs );
665
666
    $excluded_ps  = array_map( 'absint', $excluded_ps );
667
    asort( $excluded_ps );
668
    $excluded_ps  = array_values( $excluded_ps );
669
670
    $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

670
    $cart_ids     = array_map( 'absint', /** @scrutinizer ignore-type */ $cart_ids );
Loading history...
671
    asort( $cart_ids );
672
    $cart_ids     = array_values( $cart_ids );
673
674
    // Ensure we have requirements before proceeding
675
    if ( !$ret && ! empty( $item_reqs ) ) {
676
        switch( $condition ) {
677
            case 'all' :
678
                // Default back to true
679
                $ret = true;
680
681
                foreach ( $item_reqs as $item_id ) {
682
                    if ( !wpinv_item_in_cart( $item_id ) ) {
683
                        wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
684
                        $ret = false;
685
                        break;
686
                    }
687
                }
688
689
                break;
690
691
            default : // Any
692
                foreach ( $item_reqs as $item_id ) {
693
                    if ( wpinv_item_in_cart( $item_id ) ) {
694
                        $ret = true;
695
                        break;
696
                    }
697
                }
698
699
                if( ! $ret ) {
700
                    wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
701
                }
702
703
                break;
704
        }
705
    } else {
706
        $ret = true;
707
    }
708
709
    if( ! empty( $excluded_ps ) ) {
710
        // Check that there are items other than excluded ones in the cart
711
        if( $cart_ids == $excluded_ps ) {
712
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not valid for the cart contents.', 'invoicing' ) );
713
            $ret = false;
714
        }
715
    }
716
717
    return (bool) apply_filters( 'wpinv_is_discount_item_req_met', $ret, $code_id, $condition );
718
}
719
720
/**
721
 * Checks if a discount has already been used by the user.
722
 * 
723
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
724
 * @param int|string $user The user id, login or email
725
 * @param int|array|string|WPInv_Discount $code_id discount data, object, ID or code.
726
 * @return bool
727
 */
728
function wpinv_is_discount_used( $discount = array(), $user = '', $code_id = array() ) {
729
    
730
    if( ! empty( $discount ) ) {
731
        $discount = wpinv_get_discount_obj( $discount );
732
    } else {
733
        $discount = wpinv_get_discount_obj( $code_id );
734
    }
735
736
    $is_used = ! $discount->is_valid_for_user( $user );
737
    $is_used = apply_filters( 'wpinv_is_discount_used', $is_used, $discount->code, $user, $discount->ID, $discount );
738
739
    if( $is_used ) {
740
        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has already been redeemed.', 'invoicing' ) );
741
    }
742
743
    return $is_used;
744
}
745
746
function wpinv_is_discount_valid( $code = '', $user = '', $set_error = true ) {
747
    $return      = false;
748
    $discount_id = wpinv_get_discount_id_by_code( $code );
749
    $user        = trim( $user );
750
751
    if ( wpinv_get_cart_contents() ) {
752
        if ( $discount_id !== false ) {
753
            if (
754
                wpinv_is_discount_active( $discount_id ) &&
755
                wpinv_check_discount_dates( $discount_id ) &&
756
                !wpinv_is_discount_maxed_out( $discount_id ) &&
757
                !wpinv_is_discount_used( $code, $user, $discount_id ) &&
758
                wpinv_discount_is_min_met( $discount_id ) &&
759
                wpinv_discount_is_max_met( $discount_id ) &&
760
                wpinv_discount_item_reqs_met( $discount_id )
761
            ) {
762
                $return = true;
763
            }
764
        } elseif( $set_error ) {
765
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is invalid.', 'invoicing' ) );
766
        }
767
    }
768
769
    return apply_filters( 'wpinv_is_discount_valid', $return, $discount_id, $code, $user );
770
}
771
772
function wpinv_get_discount_id_by_code( $code ) {
773
    $discount = wpinv_get_discount_by_code( $code );
774
    if( $discount ) {
775
        return $discount->ID;
776
    }
777
    return false;
778
}
779
780
/**
781
 * Calculates the discounted amount.
782
 * 
783
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
784
 * @param float $base_price The number of usages to increase by
785
 * @return float
786
 */
787
function wpinv_get_discounted_amount( $discount, $base_price ) {
788
    $discount = wpinv_get_discount_obj( $discount );
789
    return $discount->get_discounted_amount( $base_price );
790
}
791
792
/**
793
 * Increases a discount's usage count.
794
 * 
795
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
796
 * @param int $by The number of usages to increase by.
797
 * @return int the new number of uses.
798
 */
799
function wpinv_increase_discount_usage( $discount, $by = 1 ) {
800
    $discount   = wpinv_get_discount_obj( $discount );
801
    return $discount->increase_usage( $by );
802
}
803
804
/**
805
 * Decreases a discount's usage count.
806
 * 
807
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
808
 * @param int $by The number of usages to decrease by.
809
 * @return int the new number of uses.
810
 */
811
function wpinv_decrease_discount_usage( $discount, $by = 1 ) {
812
    $discount   = wpinv_get_discount_obj( $discount );
813
    return $discount->increase_usage( 0 - $by );
814
}
815
816
function wpinv_format_discount_rate( $type, $amount ) {
817
    if ( $type == 'flat' ) {
818
        $rate = wpinv_price( wpinv_format_amount( $amount ) );
819
    } else {
820
        $rate = $amount . '%';
821
    }
822
823
    return apply_filters( 'wpinv_format_discount_rate', $rate, $type, $amount );
824
}
825
826
function wpinv_set_cart_discount( $code = '' ) {    
827
    if ( wpinv_multiple_discounts_allowed() ) {
828
        // Get all active cart discounts
829
        $discounts = wpinv_get_cart_discounts();
830
    } else {
831
        $discounts = false; // Only one discount allowed per purchase, so override any existing
832
    }
833
834
    if ( $discounts ) {
835
        $key = array_search( strtolower( $code ), array_map( 'strtolower', $discounts ) );
836
        if( false !== $key ) {
837
            unset( $discounts[ $key ] ); // Can't set the same discount more than once
838
        }
839
        $discounts[] = $code;
840
    } else {
841
        $discounts = array();
842
        $discounts[] = $code;
843
    }
844
    $discounts = array_values( $discounts );
845
    
846
    $data = wpinv_get_checkout_session();
847
    if ( empty( $data ) ) {
848
        $data = array();
849
    } else {
850
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
851
            $payment_meta['user_info']['discount']  = implode( ',', $discounts );
852
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
853
        }
854
    }
855
    $data['cart_discounts'] = $discounts;
856
    
857
    wpinv_set_checkout_session( $data );
858
    
859
    return $discounts;
860
}
861
862
function wpinv_unset_cart_discount( $code = '' ) {    
863
    $discounts = wpinv_get_cart_discounts();
864
865
    if ( $code && !empty( $discounts ) && in_array( $code, $discounts ) ) {
866
        $key = array_search( $code, $discounts );
867
        unset( $discounts[ $key ] );
868
            
869
        $data = wpinv_get_checkout_session();
870
        $data['cart_discounts'] = $discounts;
871
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
872
            $payment_meta['user_info']['discount']  = !empty( $discounts ) ? implode( ',', $discounts ) : '';
873
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
874
        }
875
        
876
        wpinv_set_checkout_session( $data );
877
    }
878
879
    return $discounts;
880
}
881
882
function wpinv_unset_all_cart_discounts() {
883
    $data = wpinv_get_checkout_session();
884
    
885
    if ( !empty( $data ) && isset( $data['cart_discounts'] ) ) {
886
        unset( $data['cart_discounts'] );
887
        
888
         wpinv_set_checkout_session( $data );
889
         return true;
890
    }
891
    
892
    return false;
893
}
894
895
function wpinv_get_cart_discounts() {
896
    $session = wpinv_get_checkout_session();
897
    return empty( $session['cart_discounts'] ) ? false : $session['cart_discounts'];
898
}
899
900
function wpinv_cart_has_discounts( $items = array() ) {
901
    $ret = false;
902
903
    if ( wpinv_get_cart_discounts( $items ) ) {
0 ignored issues
show
Unused Code introduced by
The call to wpinv_get_cart_discounts() has too many arguments starting with $items. ( Ignorable by Annotation )

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

903
    if ( /** @scrutinizer ignore-call */ wpinv_get_cart_discounts( $items ) ) {

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

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

Loading history...
904
        $ret = true;
905
    }
906
    
907
    /*
908
    $invoice = wpinv_get_invoice_cart();
909
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
910
        $ret = true;
911
    }
912
    */
913
914
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
915
}
916
917
function wpinv_get_cart_discounted_amount( $items = array(), $discounts = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $discounts 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

917
function wpinv_get_cart_discounted_amount( $items = array(), /** @scrutinizer ignore-unused */ $discounts = 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...
918
    $amount = 0.00;
919
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
920
921
    if ( $items ) {
922
        $discounts = wp_list_pluck( $items, 'discount' );
923
924
        if ( is_array( $discounts ) ) {
0 ignored issues
show
introduced by
The condition is_array($discounts) is always true.
Loading history...
925
            $discounts = array_map( 'floatval', $discounts );
926
            $amount    = array_sum( $discounts );
927
        }
928
    }
929
930
    return apply_filters( 'wpinv_get_cart_discounted_amount', $amount );
931
}
932
933
function wpinv_get_cart_items_discount_amount( $items = array(), $discount = false ) {
934
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
935
    
936
    if ( empty( $discount ) || empty( $items ) ) {
937
        return 0;
938
    }
939
940
    $amount = 0;
941
    
942
    foreach ( $items as $item ) {
943
        $amount += wpinv_get_cart_item_discount_amount( $item, $discount );
944
    }
945
    
946
    $amount = wpinv_round_amount( $amount );
947
948
    return $amount;
949
}
950
951
function wpinv_get_cart_item_discount_amount( $item = array(), $discount = false ) {
952
    global $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
953
    
954
    $amount = 0;
955
956
    if ( empty( $item ) || empty( $item['id'] ) ) {
957
        return $amount;
958
    }
959
960
    if ( empty( $item['quantity'] ) ) {
961
        return $amount;
962
    }
963
964
    if ( empty( $item['options'] ) ) {
965
        $item['options'] = array();
966
    }
967
968
    $price            = wpinv_get_cart_item_price( $item['id'], $item, $item['options'] );
969
    $discounted_price = $price;
970
971
    $discounts = false === $discount ? wpinv_get_cart_discounts() : $discount;
972
    if ( empty( $discounts ) ) {
973
        return $amount;
974
    }
975
976
    if ( $discounts ) {
977
        if ( is_array( $discounts ) ) {
978
            $discounts = array_values( $discounts );
979
        } else {
980
            $discounts = explode( ',', $discounts );
981
        }
982
    }
983
984
    if( $discounts ) {
985
        foreach ( $discounts as $discount ) {
986
            $code_id = wpinv_get_discount_id_by_code( $discount );
987
988
            // Check discount exists
989
            if( $code_id === false ) {
990
                continue;
991
            }
992
993
            $reqs           = wpinv_get_discount_item_reqs( $code_id );
994
            $excluded_items = wpinv_get_discount_excluded_items( $code_id );
995
996
            // Make sure requirements are set and that this discount shouldn't apply to the whole cart
997
            if ( !empty( $reqs ) && wpinv_is_discount_not_global( $code_id ) ) {
998
                foreach ( $reqs as $item_id ) {
999
                    if ( $item_id == $item['id'] && ! in_array( $item['id'], $excluded_items ) ) {
1000
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1001
                    }
1002
                }
1003
            } else {
1004
                // This is a global cart discount
1005
                if ( !in_array( $item['id'], $excluded_items ) ) {
1006
                    if ( 'flat' === wpinv_get_discount_type( $code_id ) ) {
1007
                        $items_subtotal    = 0.00;
1008
                        $cart_items        = wpinv_get_cart_contents();
1009
                        
1010
                        foreach ( $cart_items as $cart_item ) {
1011
                            if ( ! in_array( $cart_item['id'], $excluded_items ) ) {
1012
                                $options = !empty( $cart_item['options'] ) ? $cart_item['options'] : array();
1013
                                $item_price      = wpinv_get_cart_item_price( $cart_item['id'], $cart_item, $options );
1014
                                $items_subtotal += $item_price * $cart_item['quantity'];
1015
                            }
1016
                        }
1017
1018
                        $subtotal_percent  = ( ( $price * $item['quantity'] ) / $items_subtotal );
1019
                        $code_amount       = wpinv_get_discount_amount( $code_id );
1020
                        $discounted_amount = $code_amount * $subtotal_percent;
1021
                        $discounted_price -= $discounted_amount;
1022
1023
                        $wpinv_flat_discount_total += round( $discounted_amount, wpinv_currency_decimal_filter() );
1024
1025
                        if ( $wpinv_is_last_cart_item && $wpinv_flat_discount_total < $code_amount ) {
1026
                            $adjustment = $code_amount - $wpinv_flat_discount_total;
1027
                            $discounted_price -= $adjustment;
1028
                        }
1029
                    } else {
1030
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1031
                    }
1032
                }
1033
            }
1034
        }
1035
1036
        $amount = ( $price - apply_filters( 'wpinv_get_cart_item_discounted_amount', $discounted_price, $discounts, $item, $price ) );
1037
1038
        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 985. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1039
            $amount = $amount * $item['quantity'];
1040
        }
1041
    }
1042
1043
    return $amount;
1044
}
1045
1046
function wpinv_cart_discounts_html( $items = array() ) {
1047
    echo wpinv_get_cart_discounts_html( $items );
1048
}
1049
1050
function wpinv_get_cart_discounts_html( $items = array(), $discounts = false ) {
1051
    global $wpi_cart_columns;
1052
    
1053
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
1054
    
1055
    if ( !$discounts ) {
1056
        $discounts = wpinv_get_cart_discounts( $items );
0 ignored issues
show
Unused Code introduced by
The call to wpinv_get_cart_discounts() has too many arguments starting with $items. ( Ignorable by Annotation )

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

1056
        $discounts = /** @scrutinizer ignore-call */ wpinv_get_cart_discounts( $items );

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

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

Loading history...
1057
    }
1058
1059
    if ( !$discounts ) {
1060
        return;
1061
    }
1062
    
1063
    $discounts = is_array( $discounts ) ? $discounts : array( $discounts );
1064
    
1065
    $html = '';
1066
1067
    foreach ( $discounts as $discount ) {
1068
        $discount_id    = wpinv_get_discount_id_by_code( $discount );
1069
        $discount_value = wpinv_get_discount_amount( $discount_id );
1070
        $rate           = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), $discount_value );
1071
        $amount         = wpinv_get_cart_items_discount_amount( $items, $discount );
1072
        $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> ';
1073
        
1074
        $html .= '<tr class="wpinv_cart_footer_row wpinv_cart_discount_row">';
1075
        ob_start();
1076
        do_action( 'wpinv_checkout_table_discount_first', $items );
1077
        $html .= ob_get_clean();
1078
        $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>';
1079
        ob_start();
1080
        do_action( 'wpinv_checkout_table_discount_last', $items );
1081
        $html .= ob_get_clean();
1082
        $html .= '</tr>';
1083
    }
1084
1085
    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 1067. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1086
}
1087
1088
function wpinv_display_cart_discount( /** @scrutinizer ignore-unused */ $formatted = false, $echo = false ) {
1089
    $discounts = wpinv_get_cart_discounts();
1090
1091
    if ( empty( $discounts ) ) {
1092
        return false;
1093
    }
1094
1095
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1096
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1097
1098
    if ( $echo ) {
1099
        echo $amount;
1100
    }
1101
1102
    return $amount;
1103
}
1104
1105
function wpinv_remove_cart_discount() {
1106
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1107
        return;
1108
    }
1109
1110
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1111
1112
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1113
1114
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1115
1116
    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

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