Passed
Pull Request — master (#257)
by
unknown
04:31
created

wpinv_check_discount_dates()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
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.14
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 ) {
253
254
    // Fetch existing data.
255
    $existing_data = WPInv_Discount::get_data_by( 'id', $post_id );
256
    if( empty( $existing_data ) ) {
257
        return false;
258
    }
259
260
    $meta = array(
261
        'code'              => isset( $data['code'] )             ? sanitize_text_field( $data['code'] )              : $existing_data['code'],
262
        'type'              => isset( $data['type'] )             ? sanitize_text_field( $data['type'] )              : $existing_data['type'],
263
        'amount'            => isset( $data['amount'] )           ? wpinv_sanitize_amount( $data['amount'] )          : $existing_data['amount'],
264
        'start'             => isset( $data['start'] )            ? sanitize_text_field( $data['start'] )             : $existing_data['start'],
265
        'expiration'        => isset( $data['expiration'] )       ? sanitize_text_field( $data['expiration'] )        : $existing_data['expiration'],
266
        'min_total'         => isset( $data['min_total'] )        ? wpinv_sanitize_amount( $data['min_total'] )       : $existing_data['min_total'],
267
        'max_total'         => isset( $data['max_total'] )        ? wpinv_sanitize_amount( $data['max_total'] )       : $existing_data['max_total'],
268
        'max_uses'          => isset( $data['max_uses'] )         ? absint( $data['max_uses'] )                       : $existing_data['max_uses'],
269
        'items'             => isset( $data['items'] )            ? $data['items']                                    : $existing_data['items'],
270
        'excluded_items'    => isset( $data['excluded_items'] )   ? $data['excluded_items']                           : $existing_data['excluded_items'],
271
        'is_recurring'      => isset( $data['recurring'] )        ? (bool)$data['recurring']                          : $existing_data['is_recurring'],
272
        'is_single_use'     => isset( $data['single_use'] )       ? (bool)$data['single_use']                         : false,
273
        'uses'              => isset( $data['uses'] )             ? (int)$data['uses']                                : $existing_data['uses'],
274
    );
275
276
    // Merge it into the new data and save.
277
    $data          = array_merge( $existing_data, $meta );
0 ignored issues
show
Bug introduced by
It seems like $existing_data can also be of type boolean; however, parameter $array1 of array_merge() 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

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

630
    $cart_ids     = array_map( 'absint', /** @scrutinizer ignore-type */ $cart_ids );
Loading history...
631
    asort( $cart_ids );
632
    $cart_ids     = array_values( $cart_ids );
633
634
    // Ensure we have requirements before proceeding
635
    if ( !$ret && ! empty( $item_reqs ) ) {
636
        switch( $condition ) {
637
            case 'all' :
638
                // Default back to true
639
                $ret = true;
640
641
                foreach ( $item_reqs as $item_id ) {
642
                    if ( !wpinv_item_in_cart( $item_id ) ) {
643
                        wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
644
                        $ret = false;
645
                        break;
646
                    }
647
                }
648
649
                break;
650
651
            default : // Any
652
                foreach ( $item_reqs as $item_id ) {
653
                    if ( wpinv_item_in_cart( $item_id ) ) {
654
                        $ret = true;
655
                        break;
656
                    }
657
                }
658
659
                if( ! $ret ) {
660
                    wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
661
                }
662
663
                break;
664
        }
665
    } else {
666
        $ret = true;
667
    }
668
669
    if( ! empty( $excluded_ps ) ) {
670
        // Check that there are items other than excluded ones in the cart
671
        if( $cart_ids == $excluded_ps ) {
672
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not valid for the cart contents.', 'invoicing' ) );
673
            $ret = false;
674
        }
675
    }
676
677
    return (bool) apply_filters( 'wpinv_is_discount_item_req_met', $ret, $code_id, $condition );
678
}
679
680
/**
681
 * Checks if a discount has already been used by the user.
682
 * 
683
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
684
 * @param int|string $user The user id, login or email
685
 * @param int|array|string|WPInv_Discount $code_id discount data, object, ID or code.
686
 * @return boll
0 ignored issues
show
Bug introduced by
The type boll was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
687
 */
688
function wpinv_is_discount_used( $discount = array(), $user = '', $code_id = array() ) {
689
    
690
    if( ! empty( $discount ) ) {
691
        $discount = wpinv_get_discount_obj( $discount );
692
    } else {
693
        $discount = wpinv_get_discount_obj( $code_id );
694
    }
695
696
    $is_used = ! $discount->is_valid_for_user( $user );
697
    $is_used = apply_filters( 'wpinv_is_discount_used', $is_used, $discount->code, $user, $discount->id, $discount );
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on WPInv_Discount. Since you implemented __get, consider adding a @property annotation.
Loading history...
698
699
    if( $is_used ) {
700
        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has already been redeemed.', 'invoicing' ) );
701
    }
702
703
    return $is_used();
704
}
705
706
function wpinv_is_discount_valid( $code = '', $user = '', $set_error = true ) {
707
    $return      = false;
708
    $discount_id = wpinv_get_discount_id_by_code( $code );
709
    $user        = trim( $user );
710
711
    if ( wpinv_get_cart_contents() ) {
712
        if ( $discount_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $discount_id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
713
            if (
714
                wpinv_is_discount_active( $discount_id ) &&
715
                wpinv_check_discount_dates( $discount_id ) &&
716
                !wpinv_is_discount_maxed_out( $discount_id ) &&
717
                !wpinv_is_discount_used( $code, $user, $discount_id ) &&
718
                wpinv_discount_is_min_met( $discount_id ) &&
719
                wpinv_discount_is_max_met( $discount_id ) &&
720
                wpinv_discount_item_reqs_met( $discount_id )
721
            ) {
722
                $return = true;
723
            }
724
        } elseif( $set_error ) {
725
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is invalid.', 'invoicing' ) );
726
        }
727
    }
728
729
    return apply_filters( 'wpinv_is_discount_valid', $return, $discount_id, $code, $user );
730
}
731
732
function wpinv_get_discount_id_by_code( $code ) {
733
    $discount = wpinv_get_discount_by_code( $code );
734
    if( $discount ) {
735
        return $discount->ID;
736
    }
737
    return false;
738
}
739
740
/**
741
 * Calculates the discounted amount.
742
 * 
743
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
744
 * @param float $base_price The number of usages to increase by
745
 * @return float
746
 */
747
function wpinv_get_discounted_amount( $discount, $base_price ) {
748
    $discount = wpinv_get_discount_obj( $discount );
749
    return $discount->get_discounted_amount( $base_price );
750
}
751
752
/**
753
 * Increases a discount's usage count.
754
 * 
755
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
756
 * @param int $by The number of usages to increase by.
757
 * @return int the new number of uses.
758
 */
759
function wpinv_increase_discount_usage( $discount, $by = 1 ) {
760
    $discount   = wpinv_get_discount_obj( $discount );
761
    return $discount->increase_usage( $by );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $discount->increase_usage($by) returns the type boolean which is incompatible with the documented return type integer.
Loading history...
762
}
763
764
/**
765
 * Decreases a discount's usage count.
766
 * 
767
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
768
 * @param int $by The number of usages to decrease by.
769
 * @return int the new number of uses.
770
 */
771
function wpinv_decrease_discount_usage( $discount, $by = 1 ) {
772
    $discount   = wpinv_get_discount_obj( $discount );
773
    return $discount->increase_usage( 0 - $by );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $discount->increase_usage(0 - $by) returns the type boolean which is incompatible with the documented return type integer.
Loading history...
774
}
775
776
function wpinv_format_discount_rate( $type, $amount ) {
777
    if ( $type == 'flat' ) {
778
        return wpinv_price( wpinv_format_amount( $amount ) );
779
    } else {
780
        return $amount . '%';
781
    }
782
}
783
784
function wpinv_set_cart_discount( $code = '' ) {    
785
    if ( wpinv_multiple_discounts_allowed() ) {
786
        // Get all active cart discounts
787
        $discounts = wpinv_get_cart_discounts();
788
    } else {
789
        $discounts = false; // Only one discount allowed per purchase, so override any existing
790
    }
791
792
    if ( $discounts ) {
793
        $key = array_search( strtolower( $code ), array_map( 'strtolower', $discounts ) );
794
        if( false !== $key ) {
795
            unset( $discounts[ $key ] ); // Can't set the same discount more than once
796
        }
797
        $discounts[] = $code;
798
    } else {
799
        $discounts = array();
800
        $discounts[] = $code;
801
    }
802
    $discounts = array_values( $discounts );
803
    
804
    $data = wpinv_get_checkout_session();
805
    if ( empty( $data ) ) {
806
        $data = array();
807
    } else {
808
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
809
            $payment_meta['user_info']['discount']  = implode( ',', $discounts );
810
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
811
        }
812
    }
813
    $data['cart_discounts'] = $discounts;
814
    
815
    wpinv_set_checkout_session( $data );
816
    
817
    return $discounts;
818
}
819
820
function wpinv_unset_cart_discount( $code = '' ) {    
821
    $discounts = wpinv_get_cart_discounts();
822
823
    if ( $code && !empty( $discounts ) && in_array( $code, $discounts ) ) {
824
        $key = array_search( $code, $discounts );
825
        unset( $discounts[ $key ] );
826
            
827
        $data = wpinv_get_checkout_session();
828
        $data['cart_discounts'] = $discounts;
829
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
830
            $payment_meta['user_info']['discount']  = !empty( $discounts ) ? implode( ',', $discounts ) : '';
831
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
832
        }
833
        
834
        wpinv_set_checkout_session( $data );
835
    }
836
837
    return $discounts;
838
}
839
840
function wpinv_unset_all_cart_discounts() {
841
    $data = wpinv_get_checkout_session();
842
    
843
    if ( !empty( $data ) && isset( $data['cart_discounts'] ) ) {
844
        unset( $data['cart_discounts'] );
845
        
846
         wpinv_set_checkout_session( $data );
847
         return true;
848
    }
849
    
850
    return false;
851
}
852
853
function wpinv_get_cart_discounts( $items = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $items 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

853
function wpinv_get_cart_discounts( /** @scrutinizer ignore-unused */ $items = array() ) {

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...
854
    $session = wpinv_get_checkout_session();
855
    
856
    $discounts = !empty( $session['cart_discounts'] ) ? $session['cart_discounts'] : false;
857
    return $discounts;
858
}
859
860
function wpinv_cart_has_discounts( $items = array() ) {
861
    $ret = false;
862
863
    if ( wpinv_get_cart_discounts( $items ) ) {
864
        $ret = true;
865
    }
866
    
867
    /*
868
    $invoice = wpinv_get_invoice_cart();
869
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
870
        $ret = true;
871
    }
872
    */
873
874
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
875
}
876
877
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

877
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...
878
    $amount = 0.00;
879
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
880
881
    if ( $items ) {
882
        $discounts = wp_list_pluck( $items, 'discount' );
883
884
        if ( is_array( $discounts ) ) {
0 ignored issues
show
introduced by
The condition is_array($discounts) is always true.
Loading history...
885
            $discounts = array_map( 'floatval', $discounts );
886
            $amount    = array_sum( $discounts );
887
        }
888
    }
889
890
    return apply_filters( 'wpinv_get_cart_discounted_amount', $amount );
891
}
892
893
function wpinv_get_cart_items_discount_amount( $items = array(), $discount = false ) {
894
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
895
    
896
    if ( empty( $discount ) || empty( $items ) ) {
897
        return 0;
898
    }
899
900
    $amount = 0;
901
    
902
    foreach ( $items as $item ) {
903
        $amount += wpinv_get_cart_item_discount_amount( $item, $discount );
904
    }
905
    
906
    $amount = wpinv_round_amount( $amount );
907
908
    return $amount;
909
}
910
911
function wpinv_get_cart_item_discount_amount( $item = array(), $discount = false ) {
912
    global $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
913
    
914
    $amount = 0;
915
916
    if ( empty( $item ) || empty( $item['id'] ) ) {
917
        return $amount;
918
    }
919
920
    if ( empty( $item['quantity'] ) ) {
921
        return $amount;
922
    }
923
924
    if ( empty( $item['options'] ) ) {
925
        $item['options'] = array();
926
    }
927
928
    $price            = wpinv_get_cart_item_price( $item['id'], $item, $item['options'] );
929
    $discounted_price = $price;
930
931
    $discounts = false === $discount ? wpinv_get_cart_discounts() : $discount;
932
    if ( empty( $discounts ) ) {
933
        return $amount;
934
    }
935
936
    if ( $discounts ) {
937
        if ( is_array( $discounts ) ) {
938
            $discounts = array_values( $discounts );
939
        } else {
940
            $discounts = explode( ',', $discounts );
941
        }
942
    }
943
944
    if( $discounts ) {
945
        foreach ( $discounts as $discount ) {
946
            $code_id = wpinv_get_discount_id_by_code( $discount );
947
948
            // Check discount exists
949
            if( ! $code_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $code_id of type false|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
950
                continue;
951
            }
952
953
            $reqs           = wpinv_get_discount_item_reqs( $code_id );
954
            $excluded_items = wpinv_get_discount_excluded_items( $code_id );
955
956
            // Make sure requirements are set and that this discount shouldn't apply to the whole cart
957
            if ( !empty( $reqs ) && wpinv_is_discount_not_global( $code_id ) ) {
958
                foreach ( $reqs as $item_id ) {
959
                    if ( $item_id == $item['id'] && ! in_array( $item['id'], $excluded_items ) ) {
960
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
961
                    }
962
                }
963
            } else {
964
                // This is a global cart discount
965
                if ( !in_array( $item['id'], $excluded_items ) ) {
966
                    if ( 'flat' === wpinv_get_discount_type( $code_id ) ) {
967
                        $items_subtotal    = 0.00;
968
                        $cart_items        = wpinv_get_cart_contents();
969
                        
970
                        foreach ( $cart_items as $cart_item ) {
971
                            if ( ! in_array( $cart_item['id'], $excluded_items ) ) {
972
                                $options = !empty( $cart_item['options'] ) ? $cart_item['options'] : array();
973
                                $item_price      = wpinv_get_cart_item_price( $cart_item['id'], $cart_item, $options );
974
                                $items_subtotal += $item_price * $cart_item['quantity'];
975
                            }
976
                        }
977
978
                        $subtotal_percent  = ( ( $price * $item['quantity'] ) / $items_subtotal );
979
                        $code_amount       = wpinv_get_discount_amount( $code_id );
980
                        $discounted_amount = $code_amount * $subtotal_percent;
981
                        $discounted_price -= $discounted_amount;
982
983
                        $wpinv_flat_discount_total += round( $discounted_amount, wpinv_currency_decimal_filter() );
984
985
                        if ( $wpinv_is_last_cart_item && $wpinv_flat_discount_total < $code_amount ) {
986
                            $adjustment = $code_amount - $wpinv_flat_discount_total;
987
                            $discounted_price -= $adjustment;
988
                        }
989
                    } else {
990
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
991
                    }
992
                }
993
            }
994
        }
995
996
        $amount = ( $price - apply_filters( 'wpinv_get_cart_item_discounted_amount', $discounted_price, $discounts, $item, $price ) );
997
998
        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 945. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
999
            $amount = $amount * $item['quantity'];
1000
        }
1001
    }
1002
1003
    return $amount;
1004
}
1005
1006
function wpinv_cart_discounts_html( $items = array() ) {
1007
    echo wpinv_get_cart_discounts_html( $items );
1008
}
1009
1010
function wpinv_get_cart_discounts_html( $items = array(), $discounts = false ) {
1011
    global $wpi_cart_columns;
1012
    
1013
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
1014
    
1015
    if ( !$discounts ) {
1016
        $discounts = wpinv_get_cart_discounts( $items );
1017
    }
1018
1019
    if ( !$discounts ) {
1020
        return;
1021
    }
1022
    
1023
    $discounts = is_array( $discounts ) ? $discounts : array( $discounts );
1024
    
1025
    $html = '';
1026
1027
    foreach ( $discounts as $discount ) {
1028
        $discount_id    = wpinv_get_discount_id_by_code( $discount );
1029
        $discount_value = wpinv_get_discount_amount( $discount_id );
1030
        $rate           = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), $discount_value );
1031
        $amount         = wpinv_get_cart_items_discount_amount( $items, $discount );
1032
        $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> ';
1033
        
1034
        $html .= '<tr class="wpinv_cart_footer_row wpinv_cart_discount_row">';
1035
        ob_start();
1036
        do_action( 'wpinv_checkout_table_discount_first', $items );
1037
        $html .= ob_get_clean();
1038
        $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>';
1039
        ob_start();
1040
        do_action( 'wpinv_checkout_table_discount_last', $items );
1041
        $html .= ob_get_clean();
1042
        $html .= '</tr>';
1043
    }
1044
1045
    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 1027. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1046
}
1047
1048
function wpinv_display_cart_discount( $formatted = false, $echo = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $formatted 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

1048
function wpinv_display_cart_discount( /** @scrutinizer ignore-unused */ $formatted = false, $echo = 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...
1049
    $discounts = wpinv_get_cart_discounts();
1050
1051
    if ( empty( $discounts ) ) {
1052
        return false;
1053
    }
1054
1055
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1056
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1057
1058
    if ( $echo ) {
1059
        echo $amount;
1060
    }
1061
1062
    return $amount;
1063
}
1064
1065
function wpinv_remove_cart_discount() {
1066
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1067
        return;
1068
    }
1069
1070
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1071
1072
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1073
1074
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1075
1076
    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

1076
    wp_redirect( /** @scrutinizer ignore-type */ wpinv_get_checkout_uri() ); wpinv_die();
Loading history...
1077
}
1078
add_action( 'wpinv_remove_cart_discount', 'wpinv_remove_cart_discount' );
1079
1080
function wpinv_maybe_remove_cart_discount( $cart_key = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $cart_key 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

1080
function wpinv_maybe_remove_cart_discount( /** @scrutinizer ignore-unused */ $cart_key = 0 ) {

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...
1081
    $discounts = wpinv_get_cart_discounts();
1082
1083
    if ( !$discounts ) {
1084
        return;
1085
    }
1086
1087
    foreach ( $discounts as $discount ) {
1088
        if ( !wpinv_is_discount_valid( $discount ) ) {
1089
            wpinv_unset_cart_discount( $discount );
1090
        }
1091
    }
1092
}
1093
add_action( 'wpinv_post_remove_from_cart', 'wpinv_maybe_remove_cart_discount' );
1094
1095
function wpinv_multiple_discounts_allowed() {
1096
    $ret = wpinv_get_option( 'allow_multiple_discounts', false );
1097
    return (bool) apply_filters( 'wpinv_multiple_discounts_allowed', $ret );
1098
}
1099
1100
function wpinv_get_discount_label( $code, $echo = true ) {
1101
    $label = wp_sprintf( __( 'Discount%1$s', 'invoicing' ), ( $code != '' && $code != 'none' ? ' (<code>' . $code . '</code>)': '' ) );
1102
    $label = apply_filters( 'wpinv_get_discount_label', $label, $code );
1103
1104
    if ( $echo ) {
1105
        echo $label;
1106
    } else {
1107
        return $label;
1108
    }
1109
}
1110
1111
function wpinv_cart_discount_label( $code, $rate, $echo = true ) {
1112
    $label = wp_sprintf( __( 'Discount: %s', 'invoicing' ), $code );
1113
    $label = apply_filters( 'wpinv_cart_discount_label', $label, $code, $rate );
1114
1115
    if ( $echo ) {
1116
        echo $label;
1117
    } else {
1118
        return $label;
1119
    }
1120
}
1121
1122
function wpinv_check_delete_discount( $check, $post ) {
1123
    if ( $post->post_type == 'wpi_discount' && wpinv_get_discount_uses( $post->ID ) > 0 ) {
1124
        return true;
1125
    }
1126
    
1127
    return $check;
1128
}
1129
add_filter( 'pre_delete_post', 'wpinv_check_delete_discount', 10, 2 );
1130
1131
function wpinv_checkout_form_validate_discounts() {
1132
    global $wpi_checkout_id;
1133
    
1134
    $discounts = wpinv_get_cart_discounts();
1135
    
1136
    if ( !empty( $discounts ) ) {
1137
        $invalid = false;
1138
        
1139
        foreach ( $discounts as $key => $code ) {
1140
            if ( !wpinv_is_discount_valid( $code, (int)wpinv_get_user_id( $wpi_checkout_id ) ) ) {
1141
                $invalid = true;
1142
                
1143
                wpinv_unset_cart_discount( $code );
1144
            }
1145
        }
1146
        
1147
        if ( $invalid ) {
1148
            $errors = wpinv_get_errors();
1149
            $error  = !empty( $errors['wpinv-discount-error'] ) ? $errors['wpinv-discount-error'] . ' ' : '';
1150
            $error  .= __( 'The discount has been removed from cart.', 'invoicing' );
1151
            wpinv_set_error( 'wpinv-discount-error', $error );
1152
            
1153
            wpinv_recalculate_tax( true );
1154
        }
1155
    }
1156
}
1157
add_action( 'wpinv_before_checkout_form', 'wpinv_checkout_form_validate_discounts', -10 );
1158
1159
function wpinv_discount_amount() {
1160
    $output = 0.00;
1161
    
1162
    return apply_filters( 'wpinv_discount_amount', $output );
1163
}