Passed
Pull Request — master (#68)
by Kiran
04:03
created

wpinv-discount-functions.php ➔ wpinv_is_discount_used()   D

Complexity

Conditions 21
Paths 283

Size

Total Lines 63
Code Lines 37

Duplication

Lines 7
Ratio 11.11 %

Importance

Changes 0
Metric Value
cc 21
eloc 37
nc 283
nop 3
dl 7
loc 63
rs 4.4804
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
function wpinv_get_discount_types() {
15
    $discount_types = array(
16
                        'percent'   => __( 'Percentage', 'invoicing' ),
17
                        'flat'     => __( 'Flat Amount', 'invoicing' ),
18
                    );
19
    return (array)apply_filters( 'wpinv_discount_types', $discount_types );
20
}
21
22
function wpinv_get_discount_type_name( $type = '' ) {
23
    $types = wpinv_get_discount_types();
24
    return isset( $types[ $type ] ) ? $types[ $type ] : '';
25
}
26
27 View Code Duplication
function wpinv_delete_discount( $data ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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( ! current_user_can( 'manage_options' ) ) {
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 View Code Duplication
function wpinv_activate_discount( $data ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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( ! current_user_can( 'manage_options' ) ) {
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 View Code Duplication
function wpinv_deactivate_discount( $data ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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( ! current_user_can( 'manage_options' ) ) {
61
        wp_die( __( 'You do not have permission to create discount codes', 'invoicing' ), array( 'response' => 403 ) );
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']     = 'gd_discount_code';
87
        $args['meta_value']   = $args['s'];
88
        $args['meta_compare'] = 'LIKE';
89
        unset( $args['s'] );
90
        $discounts = get_posts( $args );
91
    }
92
93
    if( $discounts ) {
94
        return $discounts;
95
    }
96
97
    return false;
98
}
99
100
function wpinv_has_active_discounts() {
101
    $has_active = false;
102
103
    $discounts  = wpinv_get_discounts();
104
105
    if ( $discounts) {
106
        foreach ( $discounts as $discount ) {
107
            if ( wpinv_is_discount_active( $discount->ID ) ) {
108
                $has_active = true;
109
                break;
110
            }
111
        }
112
    }
113
    return $has_active;
114
}
115
116
function wpinv_get_discount( $discount_id = 0 ) {
117
    if( empty( $discount_id ) ) {
118
        return false;
119
    }
120
    
121
    if ( get_post_type( $discount_id ) != 'wpi_discount' ) {
122
        return false;
123
    }
124
125
    $discount = get_post( $discount_id );
126
127
    return $discount;
128
}
129
130
function wpinv_get_discount_by_code( $code = '' ) {
131
    if( empty( $code ) || ! is_string( $code ) ) {
132
        return false;
133
    }
134
135
    return wpinv_get_discount_by( 'code', $code );
136
}
137
138
function wpinv_get_discount_by( $field = '', $value = '' ) {
139
    if( empty( $field ) || empty( $value ) ) {
140
        return false;
141
    }
142
143
    if( ! is_string( $field ) ) {
144
        return false;
145
    }
146
147
    switch( strtolower( $field ) ) {
148
149
        case 'code':
150
            $meta_query     = array();
151
            $meta_query[]   = array(
152
                'key'     => '_wpi_discount_code',
153
                'value'   => $value,
154
                'compare' => '='
155
            );
156
            
157
            $discount = wpinv_get_discounts( array(
158
                'posts_per_page' => 1,
159
                'post_status'    => 'any',
160
                'meta_query'     => $meta_query,
161
            ) );
162
            
163
            if( $discount ) {
164
                $discount = $discount[0];
165
            }
166
167
            break;
168
169
        case 'id':
170
            $discount = wpinv_get_discount( $value );
171
172
            break;
173
174
        case 'name':
175
            $discount = get_posts( array(
176
                'post_type'      => 'wpi_discount',
177
                'name'           => $value,
178
                'posts_per_page' => 1,
179
                'post_status'    => 'any'
180
            ) );
181
182
            if( $discount ) {
183
                $discount = $discount[0];
184
            }
185
186
            break;
187
188
        default:
189
            return false;
190
    }
191
192
    if( ! empty( $discount ) ) {
193
        return $discount;
194
    }
195
196
    return false;
197
}
198
199
function wpinv_store_discount( $post_id, $data, $post, $update = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $update is not used and could be removed.

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

Loading history...
200
    $meta = array(
201
        'code'              => isset( $data['code'] )             ? sanitize_text_field( $data['code'] )              : '',
202
        'type'              => isset( $data['type'] )             ? sanitize_text_field( $data['type'] )              : 'percent',
203
        'amount'            => isset( $data['amount'] )           ? wpinv_sanitize_amount( $data['amount'] )          : '',
204
        'start'             => isset( $data['start'] )            ? sanitize_text_field( $data['start'] )             : '',
205
        'expiration'        => isset( $data['expiration'] )       ? sanitize_text_field( $data['expiration'] )        : '',
206
        'min_total'         => isset( $data['min_total'] )        ? wpinv_sanitize_amount( $data['min_total'] )       : '',
207
        'max_total'         => isset( $data['max_total'] )        ? wpinv_sanitize_amount( $data['max_total'] )       : '',
208
        'max_uses'          => isset( $data['max_uses'] )         ? absint( $data['max_uses'] )                       : '',
209
        'items'             => isset( $data['items'] )            ? $data['items']                                    : array(),
210
        'excluded_items'    => isset( $data['excluded_items'] )   ? $data['excluded_items']                           : array(),
211
        'is_recurring'      => isset( $data['recurring'] )        ? (bool)$data['recurring']                          : false,
212
        'is_single_use'     => isset( $data['single_use'] )       ? (bool)$data['single_use']                         : false,
213
        'uses'              => isset( $data['uses'] )             ? (int)$data['uses']                                : false,
214
    );
215
    
216
    $start_timestamp        = strtotime( $meta['start'] );
217
218
    if ( !empty( $meta['start'] ) ) {
219
        $meta['start']      = date( 'Y-m-d H:i:s', $start_timestamp );
220
    }
221
        
222
    if ( $meta['type'] == 'percent' && (float)$meta['amount'] > 100 ) {
223
        $meta['amount'] = 100;
224
    }
225
226
    if ( !empty( $meta['expiration'] ) ) {
227
        $meta['expiration'] = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d', strtotime( $meta['expiration'] ) ) . ' 23:59:59' ) );
228
        $end_timestamp      = strtotime( $meta['expiration'] );
229
230
        if ( !empty( $meta['start'] ) && $start_timestamp > $end_timestamp ) {
231
            $meta['expiration'] = $meta['start']; // Set the expiration date to the start date if start is later than expiration date.
232
        }
233
    }
234
    
235
    if ( $meta['uses'] === false ) {
236
        unset( $meta['uses'] );
237
    }
238
    
239 View Code Duplication
    if ( ! empty( $meta['items'] ) ) {
240
        foreach ( $meta['items'] as $key => $item ) {
241
            if ( 0 === intval( $item ) ) {
242
                unset( $meta['items'][ $key ] );
243
            }
244
        }
245
    }
246
    
247 View Code Duplication
    if ( ! empty( $meta['excluded_items'] ) ) {
248
        foreach ( $meta['excluded_items'] as $key => $item ) {
249
            if ( 0 === intval( $item ) ) {
250
                unset( $meta['excluded_items'][ $key ] );
251
            }
252
        }
253
    }
254
    
255
    $meta = apply_filters( 'wpinv_update_discount', $meta, $post_id, $post );
256
    
257
    do_action( 'wpinv_pre_update_discount', $meta, $post_id, $post );
258
    
259
    foreach( $meta as $key => $value ) {
260
        update_post_meta( $post_id, '_wpi_discount_' . $key, $value );
261
    }
262
    
263
    do_action( 'wpinv_post_update_discount', $meta, $post_id, $post );
264
    
265
    return $post_id;
266
}
267
268
function wpinv_remove_discount( $discount_id = 0 ) {
269
    do_action( 'wpinv_pre_delete_discount', $discount_id );
270
271
    wp_delete_post( $discount_id, true );
272
273
    do_action( 'wpinv_post_delete_discount', $discount_id );
274
}
275
276
function wpinv_update_discount_status( $code_id = 0, $new_status = 'publish' ) {
277
    $discount = wpinv_get_discount(  $code_id );
278
279
    if ( $discount ) {
280
        do_action( 'wpinv_pre_update_discount_status', $code_id, $new_status, $discount->post_status );
281
282
        wp_update_post( array( 'ID' => $code_id, 'post_status' => $new_status ) );
283
284
        do_action( 'wpinv_post_update_discount_status', $code_id, $new_status, $discount->post_status );
285
286
        return true;
287
    }
288
289
    return false;
290
}
291
292
function wpinv_discount_exists( $code_id ) {
293
    if ( wpinv_get_discount(  $code_id ) ) {
294
        return true;
295
    }
296
297
    return false;
298
}
299
300
function wpinv_is_discount_active( $code_id = null ) {
301
    $discount = wpinv_get_discount(  $code_id );
302
    $return   = false;
303
304
    if ( $discount ) {
305
        if ( wpinv_is_discount_expired( $code_id ) ) {
306
            if( defined( 'DOING_AJAX' ) ) {
307
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is expired.', 'invoicing' ) );
308
            }
309
        } elseif ( $discount->post_status == 'publish' ) {
310
            $return = true;
311
        } else {
312
            if( defined( 'DOING_AJAX' ) ) {
313
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active.', 'invoicing' ) );
314
            }
315
        }
316
    }
317
318
    return apply_filters( 'wpinv_is_discount_active', $return, $code_id );
319
}
320
321
function wpinv_get_discount_code( $code_id = null ) {
322
    $code = get_post_meta( $code_id, '_wpi_discount_code', true );
323
324
    return apply_filters( 'wpinv_get_discount_code', $code, $code_id );
325
}
326
327
function wpinv_get_discount_start_date( $code_id = null ) {
328
    $start_date = get_post_meta( $code_id, '_wpi_discount_start', true );
329
330
    return apply_filters( 'wpinv_get_discount_start_date', $start_date, $code_id );
331
}
332
333
function wpinv_get_discount_expiration( $code_id = null ) {
334
    $expiration = get_post_meta( $code_id, '_wpi_discount_expiration', true );
335
336
    return apply_filters( 'wpinv_get_discount_expiration', $expiration, $code_id );
337
}
338
339
function wpinv_get_discount_max_uses( $code_id = null ) {
340
    $max_uses = get_post_meta( $code_id, '_wpi_discount_max_uses', true );
341
342
    return (int) apply_filters( 'wpinv_get_discount_max_uses', $max_uses, $code_id );
343
}
344
345
function wpinv_get_discount_uses( $code_id = null ) {
346
    $uses = get_post_meta( $code_id, '_wpi_discount_uses', true );
347
348
    return (int) apply_filters( 'wpinv_get_discount_uses', $uses, $code_id );
349
}
350
351
function wpinv_get_discount_min_total( $code_id = null ) {
352
    $min_total = get_post_meta( $code_id, '_wpi_discount_min_total', true );
353
354
    return (float) apply_filters( 'wpinv_get_discount_min_total', $min_total, $code_id );
355
}
356
357
function wpinv_get_discount_max_total( $code_id = null ) {
358
    $max_total = get_post_meta( $code_id, '_wpi_discount_max_total', true );
359
360
    return (float) apply_filters( 'wpinv_get_discount_max_total', $max_total, $code_id );
361
}
362
363
function wpinv_get_discount_amount( $code_id = null ) {
364
    $amount = get_post_meta( $code_id, '_wpi_discount_amount', true );
365
366
    return (float) apply_filters( 'wpinv_get_discount_amount', $amount, $code_id );
367
}
368
369
function wpinv_get_discount_type( $code_id = null, $name = false ) {
370
    $type = strtolower( get_post_meta( $code_id, '_wpi_discount_type', true ) );
371
    
372
    if ( $name ) {
373
        $name = wpinv_get_discount_type_name( $type );
374
        
375
        return apply_filters( 'wpinv_get_discount_type_name', $name, $code_id );
376
    }
377
378
    return apply_filters( 'wpinv_get_discount_type', $type, $code_id );
379
}
380
381
function wpinv_discount_status( $status ) {
382
    switch( $status ){
383
        case 'expired' :
384
            $name = __( 'Expired', 'invoicing' );
385
            break;
386
        case 'publish' :
387
        case 'active' :
388
            $name = __( 'Active', 'invoicing' );
389
            break;
390
        default :
391
            $name = __( 'Inactive', 'invoicing' );
392
            break;
393
    }
394
    return $name;
395
}
396
397 View Code Duplication
function wpinv_get_discount_excluded_items( $code_id = null ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
398
    $excluded_items = get_post_meta( $code_id, '_wpi_discount_excluded_items', true );
399
400
    if ( empty( $excluded_items ) || ! is_array( $excluded_items ) ) {
401
        $excluded_items = array();
402
    }
403
404
    return (array) apply_filters( 'wpinv_get_discount_excluded_items', $excluded_items, $code_id );
405
}
406
407 View Code Duplication
function wpinv_get_discount_item_reqs( $code_id = null ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
    $item_reqs = get_post_meta( $code_id, '_wpi_discount_items', true );
409
410
    if ( empty( $item_reqs ) || ! is_array( $item_reqs ) ) {
411
        $item_reqs = array();
412
    }
413
414
    return (array) apply_filters( 'wpinv_get_discount_item_reqs', $item_reqs, $code_id );
415
}
416
417
function wpinv_get_discount_item_condition( $code_id = 0 ) {
418
    return get_post_meta( $code_id, '_wpi_discount_item_condition', true );
419
}
420
421
function wpinv_is_discount_not_global( $code_id = 0 ) {
422
    return (bool) get_post_meta( $code_id, '_wpi_discount_is_not_global', true );
423
}
424
425
function wpinv_is_discount_expired( $code_id = null ) {
426
    $discount = wpinv_get_discount(  $code_id );
427
    $return   = false;
428
429 View Code Duplication
    if ( $discount ) {
430
        $expiration = wpinv_get_discount_expiration( $code_id );
431
        if ( $expiration ) {
432
            $expiration = strtotime( $expiration );
433
            if ( $expiration < current_time( 'timestamp' ) ) {
434
                // Discount is expired
435
                wpinv_update_discount_status( $code_id, 'pending' );
436
                $return = true;
437
            }
438
        }
439
    }
440
441
    return apply_filters( 'wpinv_is_discount_expired', $return, $code_id );
442
}
443
444
function wpinv_is_discount_started( $code_id = null ) {
445
    $discount = wpinv_get_discount(  $code_id );
446
    $return   = false;
447
448
    if ( $discount ) {
449
        $start_date = wpinv_get_discount_start_date( $code_id );
450
451 View Code Duplication
        if ( $start_date ) {
452
            $start_date = strtotime( $start_date );
453
454
            if ( $start_date < current_time( 'timestamp' ) ) {
455
                // Discount has past the start date
456
                $return = true;
457
            } else {
458
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
459
            }
460
        } else {
461
            // No start date for this discount, so has to be true
462
            $return = true;
463
        }
464
    }
465
466
    return apply_filters( 'wpinv_is_discount_started', $return, $code_id );
467
}
468
469
function wpinv_check_discount_dates( $code_id = null ) {
470
    $discount = wpinv_get_discount(  $code_id );
471
    $return   = false;
472
473
    if ( $discount ) {
474
        $start_date = wpinv_get_discount_start_date( $code_id );
475
476 View Code Duplication
        if ( $start_date ) {
477
            $start_date = strtotime( $start_date );
478
479
            if ( $start_date < current_time( 'timestamp' ) ) {
480
                // Discount has past the start date
481
                $return = true;
482
            } else {
483
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
484
            }
485
        } else {
486
            // No start date for this discount, so has to be true
487
            $return = true;
488
        }
489
        
490 View Code Duplication
        if ( $return ) {
491
            $expiration = wpinv_get_discount_expiration( $code_id );
492
            
493
            if ( $expiration ) {
494
                $expiration = strtotime( $expiration );
495
                if ( $expiration < current_time( 'timestamp' ) ) {
496
                    // Discount is expired
497
                    wpinv_update_discount_status( $code_id, 'pending' );
498
                    $return = true;
499
                }
500
            }
501
        }
502
    }
503
    
504
    return apply_filters( 'wpinv_check_discount_dates', $return, $code_id );
505
}
506
507
function wpinv_is_discount_maxed_out( $code_id = null ) {
508
    $discount = wpinv_get_discount(  $code_id );
509
    $return   = false;
510
511
    if ( $discount ) {
512
        $uses = wpinv_get_discount_uses( $code_id );
513
        // Large number that will never be reached
514
        $max_uses = wpinv_get_discount_max_uses( $code_id );
515
        // Should never be greater than, but just in case
516 View Code Duplication
        if ( $uses >= $max_uses && ! empty( $max_uses ) ) {
517
            // Discount is maxed out
518
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount has reached its maximum usage.', 'invoicing' ) );
519
            $return = true;
520
        }
521
    }
522
523
    return apply_filters( 'wpinv_is_discount_maxed_out', $return, $code_id );
524
}
525
526 View Code Duplication
function wpinv_discount_is_min_met( $code_id = null ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
527
    $discount = wpinv_get_discount( $code_id );
528
    $return   = false;
529
530
    if ( $discount ) {
531
        $min         = (float)wpinv_get_discount_min_total( $code_id );
532
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
533
534
        if ( !$min > 0 || $cart_amount >= $min ) {
535
            // Minimum has been met
536
            $return = true;
537
        } else {
538
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Minimum invoice of %s not met.', 'invoicing' ), wpinv_price( wpinv_format_amount( $min ) ) ) );
539
        }
540
    }
541
542
    return apply_filters( 'wpinv_is_discount_min_met', $return, $code_id );
543
}
544
545 View Code Duplication
function wpinv_discount_is_max_met( $code_id = null ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
546
    $discount = wpinv_get_discount( $code_id );
547
    $return   = false;
548
549
    if ( $discount ) {
550
        $max         = (float)wpinv_get_discount_max_total( $code_id );
551
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
552
553
        if ( !$max > 0 || $cart_amount <= $max ) {
554
            // Minimum has been met
555
            $return = true;
556
        } else {
557
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Maximum invoice of %s not met.', 'invoicing' ), wpinv_price( wpinv_format_amount( $max ) ) ) );
558
        }
559
    }
560
561
    return apply_filters( 'wpinv_is_discount_max_met', $return, $code_id );
562
}
563
564
function wpinv_discount_is_single_use( $code_id = 0 ) {
565
    $single_use = get_post_meta( $code_id, '_wpi_discount_is_single_use', true );
566
    return (bool) apply_filters( 'wpinv_is_discount_single_use', $single_use, $code_id );
567
}
568
569
function wpinv_discount_is_recurring( $code_id = 0, $code = false ) {
570
    if ( $code ) {
571
        $discount = wpinv_get_discount_by_code( $code_id );
572
        
573
        if ( !empty( $discount ) ) {
574
            $code_id = $discount->ID;
575
        }
576
    }
577
    
578
    $recurring = get_post_meta( $code_id, '_wpi_discount_is_recurring', true );
579
    
580
    return (bool) apply_filters( 'wpinv_is_discount_recurring', $recurring, $code_id, $code );
581
}
582
583
function wpinv_discount_item_reqs_met( $code_id = null ) {
584
    $item_reqs    = wpinv_get_discount_item_reqs( $code_id );
585
    $condition    = wpinv_get_discount_item_condition( $code_id );
586
    $excluded_ps  = wpinv_get_discount_excluded_items( $code_id );
587
    $cart_items   = wpinv_get_cart_contents();
588
    $cart_ids     = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
589
    $ret          = false;
590
591
    if ( empty( $item_reqs ) && empty( $excluded_ps ) ) {
592
        $ret = true;
593
    }
594
595
    // Normalize our data for item requirements, exclusions and cart data
596
    // First absint the items, then sort, and reset the array keys
597
    $item_reqs = array_map( 'absint', $item_reqs );
598
    asort( $item_reqs );
599
    $item_reqs = array_values( $item_reqs );
600
601
    $excluded_ps  = array_map( 'absint', $excluded_ps );
602
    asort( $excluded_ps );
603
    $excluded_ps  = array_values( $excluded_ps );
604
605
    $cart_ids     = array_map( 'absint', $cart_ids );
606
    asort( $cart_ids );
607
    $cart_ids     = array_values( $cart_ids );
608
609
    // Ensure we have requirements before proceeding
610
    if ( !$ret && ! empty( $item_reqs ) ) {
611
        switch( $condition ) {
612 View Code Duplication
            case 'all' :
613
                // Default back to true
614
                $ret = true;
615
616
                foreach ( $item_reqs as $item_id ) {
617
                    if ( !wpinv_item_in_cart( $item_id ) ) {
618
                        wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
619
                        $ret = false;
620
                        break;
621
                    }
622
                }
623
624
                break;
625
626 View Code Duplication
            default : // Any
627
                foreach ( $item_reqs as $item_id ) {
628
                    if ( wpinv_item_in_cart( $item_id ) ) {
629
                        $ret = true;
630
                        break;
631
                    }
632
                }
633
634
                if( ! $ret ) {
635
                    wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
636
                }
637
638
                break;
639
        }
640
    } else {
641
        $ret = true;
642
    }
643
644 View Code Duplication
    if( ! empty( $excluded_ps ) ) {
645
        // Check that there are items other than excluded ones in the cart
646
        if( $cart_ids == $excluded_ps ) {
647
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not valid for the cart contents.', 'invoicing' ) );
648
            $ret = false;
649
        }
650
    }
651
652
    return (bool) apply_filters( 'wpinv_is_discount_item_req_met', $ret, $code_id, $condition );
653
}
654
655
function wpinv_is_discount_used( $code = null, $user = '', $code_id = 0 ) {
656
    global $wpi_checkout_id;
657
    
658
    $return = false;
659
660
    if ( empty( $code_id ) ) {
661
        $code_id = wpinv_get_discount_id_by_code( $code );
662
        
663
        if( empty( $code_id ) ) {
664
            return false; // No discount was found
665
        }
666
    }
667
668
    if ( wpinv_discount_is_single_use( $code_id ) ) {
669
        $payments = array();
670
671
        $user_id = 0;
672
        if ( is_int( $user ) ) {
673
            $user_id = absint( $user );
674
        } else if ( is_email( $user ) && $user_data = get_user_by( 'email', $user ) ) {
675
            $user_id = $user_data->ID;
676
        } else if ( $user_data = get_user_by( 'login', $user ) ) {
677
            $user_id = $user_data->ID;
678
        } else if ( absint( $user ) > 0 ) {
679
            $user_id = absint( $user );
680
        }
681
682
        if ( !empty( $user_id ) ) {
683
            $query    = array( 'user' => $user_id, 'limit' => false );
684
            $payments = wpinv_get_invoices( $query ); // Get all payments with matching user id
685
        }
686
687
        if ( $payments ) {
688
            foreach ( $payments as $payment ) {
689
                // Don't count discount used for current invoice chekcout.
690
                if ( !empty( $wpi_checkout_id ) && $wpi_checkout_id == $payment->ID ) {
691
                    continue;
692
                }
693
                
694
                if ( $payment->has_status( array( 'wpi-cancelled', 'wpi-failed' ) ) ) {
695
                    continue;
696
                }
697
698
                $discounts = $payment->get_discounts( true );
699
                if ( empty( $discounts ) ) {
700
                    continue;
701
                }
702
703
                $discounts = $discounts && !is_array( $discounts ) ? explode( ',', $discounts ) : $discounts;
704
705 View Code Duplication
                if ( !empty( $discounts ) && is_array( $discounts ) ) {
706
                    if ( in_array( strtolower( $code ), array_map( 'strtolower', $discounts ) ) ) {
707
                        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has already been redeemed.', 'invoicing' ) );
708
                        $return = true;
709
                        break;
710
                    }
711
                }
712
            }
713
        }
714
    }
715
716
    return apply_filters( 'wpinv_is_discount_used', $return, $code, $user );
717
}
718
719
function wpinv_is_discount_valid( $code = '', $user = '', $set_error = true ) {
720
    $return      = false;
721
    $discount_id = wpinv_get_discount_id_by_code( $code );
722
    $user        = trim( $user );
723
724
    if ( wpinv_get_cart_contents() ) {
725
        if ( $discount_id ) {
726
            if (
727
                wpinv_is_discount_active( $discount_id ) &&
728
                wpinv_check_discount_dates( $discount_id ) &&
729
                !wpinv_is_discount_maxed_out( $discount_id ) &&
730
                !wpinv_is_discount_used( $code, $user, $discount_id ) &&
731
                wpinv_discount_is_min_met( $discount_id ) &&
732
                wpinv_discount_is_max_met( $discount_id ) &&
733
                wpinv_discount_item_reqs_met( $discount_id )
734
            ) {
735
                $return = true;
736
            }
737
        } elseif( $set_error ) {
738
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is invalid.', 'invoicing' ) );
739
        }
740
    }
741
742
    return apply_filters( 'wpinv_is_discount_valid', $return, $discount_id, $code, $user );
743
}
744
745
function wpinv_get_discount_id_by_code( $code ) {
746
    $discount = wpinv_get_discount_by_code( $code );
747
    if( $discount ) {
748
        return $discount->ID;
749
    }
750
    return false;
751
}
752
753
function wpinv_get_discounted_amount( $code, $base_price ) {
754
    $amount      = $base_price;
0 ignored issues
show
Unused Code introduced by
$amount is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
755
    $discount_id = wpinv_get_discount_id_by_code( $code );
756
757
    if( $discount_id ) {
758
        $type        = wpinv_get_discount_type( $discount_id );
759
        $rate        = wpinv_get_discount_amount( $discount_id );
760
761
        if ( $type == 'flat' ) {
762
            // Set amount
763
            $amount = $base_price - $rate;
764
            if ( $amount < 0 ) {
765
                $amount = 0;
766
            }
767
768
        } else {
769
            // Percentage discount
770
            $amount = $base_price - ( $base_price * ( $rate / 100 ) );
771
        }
772
773
    } else {
774
775
        $amount = $base_price;
776
777
    }
778
779
    return apply_filters( 'wpinv_discounted_amount', $amount );
780
}
781
782 View Code Duplication
function wpinv_increase_discount_usage( $code ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
783
784
    $id   = wpinv_get_discount_id_by_code( $code );
785
    $uses = wpinv_get_discount_uses( $id );
786
787
    if ( $uses ) {
788
        $uses++;
789
    } else {
790
        $uses = 1;
791
    }
792
793
    update_post_meta( $id, '_wpi_discount_uses', $uses );
794
795
    do_action( 'wpinv_discount_increase_use_count', $uses, $id, $code );
796
797
    return $uses;
798
799
}
800
801 View Code Duplication
function wpinv_decrease_discount_usage( $code ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
802
803
    $id   = wpinv_get_discount_id_by_code( $code );
804
    $uses = wpinv_get_discount_uses( $id );
805
806
    if ( $uses ) {
807
        $uses--;
808
    }
809
810
    if ( $uses < 0 ) {
811
        $uses = 0;
812
    }
813
814
    update_post_meta( $id, '_wpi_discount_uses', $uses );
815
816
    do_action( 'wpinv_discount_decrease_use_count', $uses, $id, $code );
817
818
    return $uses;
819
820
}
821
822
function wpinv_format_discount_rate( $type, $amount ) {
823
    if ( $type == 'flat' ) {
824
        return wpinv_price( wpinv_format_amount( $amount ) );
825
    } else {
826
        return $amount . '%';
827
    }
828
}
829
830
function wpinv_set_cart_discount( $code = '' ) {    
831
    if ( wpinv_multiple_discounts_allowed() ) {
832
        // Get all active cart discounts
833
        $discounts = wpinv_get_cart_discounts();
834
    } else {
835
        $discounts = false; // Only one discount allowed per purchase, so override any existing
836
    }
837
838
    if ( $discounts ) {
839
        $key = array_search( strtolower( $code ), array_map( 'strtolower', $discounts ) );
840
        if( false !== $key ) {
841
            unset( $discounts[ $key ] ); // Can't set the same discount more than once
842
        }
843
        $discounts[] = $code;
844
    } else {
845
        $discounts = array();
846
        $discounts[] = $code;
847
    }
848
    $discounts = array_values( $discounts );
849
    
850
    $data = wpinv_get_checkout_session();
851 View Code Duplication
    if ( empty( $data ) ) {
852
        $data = array();
853
    } else {
854
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
855
            $payment_meta['user_info']['discount']  = implode( ',', $discounts );
856
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
857
        }
858
    }
859
    $data['cart_discounts'] = $discounts;
860
    
861
    wpinv_set_checkout_session( $data );
862
    
863
    return $discounts;
864
}
865
866
function wpinv_unset_cart_discount( $code = '' ) {    
867
    $discounts = wpinv_get_cart_discounts();
868
869
    if ( $code && !empty( $discounts ) && in_array( $code, $discounts ) ) {
870
        $key = array_search( $code, $discounts );
871
        unset( $discounts[ $key ] );
872
            
873
        $data = wpinv_get_checkout_session();
874
        $data['cart_discounts'] = $discounts;
875 View Code Duplication
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
876
            $payment_meta['user_info']['discount']  = !empty( $discounts ) ? implode( ',', $discounts ) : '';
877
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
878
        }
879
        
880
        wpinv_set_checkout_session( $data );
881
    }
882
883
    return $discounts;
884
}
885
886
function wpinv_unset_all_cart_discounts() {
887
    $data = wpinv_get_checkout_session();
888
    
889
    if ( !empty( $data ) && isset( $data['cart_discounts'] ) ) {
890
        unset( $data['cart_discounts'] );
891
        
892
         wpinv_set_checkout_session( $data );
893
         return true;
894
    }
895
    
896
    return false;
897
}
898
899
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.

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

Loading history...
900
    $session = wpinv_get_checkout_session();
901
    
902
    $discounts = !empty( $session['cart_discounts'] ) ? $session['cart_discounts'] : false;
903
    return $discounts;
904
}
905
906
function wpinv_cart_has_discounts( $items = array() ) {
907
    $ret = false;
908
909
    if ( wpinv_get_cart_discounts( $items ) ) {
910
        $ret = true;
911
    }
912
    
913
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
52% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
914
    $invoice = wpinv_get_invoice_cart();
915
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
916
        $ret = true;
917
    }
918
    */
919
920
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
921
}
922
923 View Code Duplication
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.

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

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
924
    $amount = 0.00;
925
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
926
927
    if ( $items ) {
928
        $discounts = wp_list_pluck( $items, 'discount' );
929
930
        if ( is_array( $discounts ) ) {
931
            $discounts = array_map( 'floatval', $discounts );
932
            $amount    = array_sum( $discounts );
933
        }
934
    }
935
936
    return apply_filters( 'wpinv_get_cart_discounted_amount', $amount );
937
}
938
939
function wpinv_get_cart_items_discount_amount( $items = array(), $discount = false ) {
940
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
941
    
942
    if ( empty( $discount ) || empty( $items ) ) {
943
        return 0;
944
    }
945
946
    $amount = 0;
947
    
948
    foreach ( $items as $item ) {
949
        $amount += wpinv_get_cart_item_discount_amount( $item, $discount );
950
    }
951
    
952
    $amount = wpinv_round_amount( $amount );
953
954
    return $amount;
955
}
956
957
function wpinv_get_cart_item_discount_amount( $item = array(), $discount = false ) {
958
    global $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
959
    
960
    $amount = 0;
961
962
    if ( empty( $item ) || empty( $item['id'] ) ) {
963
        return $amount;
964
    }
965
966
    if ( empty( $item['quantity'] ) ) {
967
        return $amount;
968
    }
969
970
    if ( empty( $item['options'] ) ) {
971
        $item['options'] = array();
972
    }
973
974
    $price            = wpinv_get_cart_item_price( $item['id'], $item, $item['options'] );
975
    $discounted_price = $price;
976
977
    $discounts = false === $discount ? wpinv_get_cart_discounts() : $discount;
978
    if ( empty( $discounts ) ) {
979
        return $amount;
980
    }
981
982
    if ( $discounts ) {
983
        if ( is_array( $discounts ) ) {
984
            $discounts = array_values( $discounts );
985
        } else {
986
            $discounts = explode( ',', $discounts );
987
        }
988
    }
989
990
    if( $discounts ) {
991
        foreach ( $discounts as $discount ) {
992
            $code_id = wpinv_get_discount_id_by_code( $discount );
993
994
            // Check discount exists
995
            if( ! $code_id ) {
996
                continue;
997
            }
998
999
            $reqs           = wpinv_get_discount_item_reqs( $code_id );
1000
            $excluded_items = wpinv_get_discount_excluded_items( $code_id );
1001
1002
            // Make sure requirements are set and that this discount shouldn't apply to the whole cart
1003
            if ( !empty( $reqs ) && wpinv_is_discount_not_global( $code_id ) ) {
1004
                foreach ( $reqs as $item_id ) {
1005
                    if ( $item_id == $item['id'] && ! in_array( $item['id'], $excluded_items ) ) {
1006
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1007
                    }
1008
                }
1009
            } else {
1010
                // This is a global cart discount
1011
                if ( !in_array( $item['id'], $excluded_items ) ) {
1012
                    if ( 'flat' === wpinv_get_discount_type( $code_id ) ) {
1013
                        $items_subtotal    = 0.00;
1014
                        $cart_items        = wpinv_get_cart_contents();
1015
                        
1016
                        foreach ( $cart_items as $cart_item ) {
1017
                            if ( ! in_array( $cart_item['id'], $excluded_items ) ) {
1018
                                $options = !empty( $cart_item['options'] ) ? $cart_item['options'] : array();
1019
                                $item_price      = wpinv_get_cart_item_price( $cart_item['id'], $cart_item, $options );
1020
                                $items_subtotal += $item_price * $cart_item['quantity'];
1021
                            }
1022
                        }
1023
1024
                        $subtotal_percent  = ( ( $price * $item['quantity'] ) / $items_subtotal );
1025
                        $code_amount       = wpinv_get_discount_amount( $code_id );
1026
                        $discounted_amount = $code_amount * $subtotal_percent;
1027
                        $discounted_price -= $discounted_amount;
1028
1029
                        $wpinv_flat_discount_total += round( $discounted_amount, wpinv_currency_decimal_filter() );
1030
1031
                        if ( $wpinv_is_last_cart_item && $wpinv_flat_discount_total < $code_amount ) {
1032
                            $adjustment = $code_amount - $wpinv_flat_discount_total;
1033
                            $discounted_price -= $adjustment;
1034
                        }
1035
                    } else {
1036
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1037
                    }
1038
                }
1039
            }
1040
        }
1041
1042
        $amount = ( $price - apply_filters( 'wpinv_get_cart_item_discounted_amount', $discounted_price, $discounts, $item, $price ) );
1043
1044
        if ( 'flat' !== wpinv_get_discount_type( $code_id ) ) {
0 ignored issues
show
Bug introduced by
The variable $code_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1045
            $amount = $amount * $item['quantity'];
1046
        }
1047
    }
1048
1049
    return $amount;
1050
}
1051
1052
function wpinv_cart_discounts_html( $items = array() ) {
1053
    echo wpinv_get_cart_discounts_html( $items );
1054
}
1055
1056
function wpinv_get_cart_discounts_html( $items = array(), $discounts = false ) {
1057
    global $wpi_cart_columns;
1058
    
1059
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
1060
    
1061
    if ( !$discounts ) {
1062
        $discounts = wpinv_get_cart_discounts( $items );
0 ignored issues
show
Security Bug introduced by
It seems like $items defined by !empty($items) ? $items ..._cart_content_details() on line 1059 can also be of type false; however, wpinv_get_cart_discounts() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1063
    }
1064
1065
    if ( !$discounts ) {
1066
        return;
1067
    }
1068
    
1069
    $discounts = is_array( $discounts ) ? $discounts : array( $discounts );
1070
    
1071
    $html = '';
1072
1073
    foreach ( $discounts as $discount ) {
1074
        $discount_id    = wpinv_get_discount_id_by_code( $discount );
1075
        $discount_value = wpinv_get_discount_amount( $discount_id );
1076
        $rate           = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), $discount_value );
1077
        $amount         = wpinv_get_cart_items_discount_amount( $items, $discount );
0 ignored issues
show
Security Bug introduced by
It seems like $items defined by !empty($items) ? $items ..._cart_content_details() on line 1059 can also be of type false; however, wpinv_get_cart_items_discount_amount() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1078
        $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> ';
1079
        
1080
        $html .= '<tr class="wpinv_cart_footer_row wpinv_cart_discount_row">';
1081
        ob_start();
1082
        do_action( 'wpinv_checkout_table_discount_first', $items );
1083
        $html .= ob_get_clean();
1084
        $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>';
1085
        ob_start();
1086
        do_action( 'wpinv_checkout_table_discount_last', $items );
1087
        $html .= ob_get_clean();
1088
        $html .= '</tr>';
1089
    }
1090
1091
    return apply_filters( 'wpinv_get_cart_discounts_html', $html, $discounts, $rate );
0 ignored issues
show
Bug introduced by
The variable $rate does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1092
}
1093
1094
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.

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

Loading history...
1095
    $discounts = wpinv_get_cart_discounts();
1096
1097
    if ( empty( $discounts ) ) {
1098
        return false;
1099
    }
1100
1101
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1102
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1103
1104
    if ( $echo ) {
1105
        echo $amount;
1106
    }
1107
1108
    return $amount;
1109
}
1110
1111
function wpinv_remove_cart_discount() {
1112
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1113
        return;
1114
    }
1115
1116
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1117
1118
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1119
1120
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1121
1122
    wp_redirect( wpinv_get_checkout_uri() ); wpinv_die();
1123
}
1124
add_action( 'wpinv_remove_cart_discount', 'wpinv_remove_cart_discount' );
1125
1126
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.

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

Loading history...
1127
    $discounts = wpinv_get_cart_discounts();
1128
1129
    if ( !$discounts ) {
1130
        return;
1131
    }
1132
1133
    foreach ( $discounts as $discount ) {
1134
        if ( !wpinv_is_discount_valid( $discount ) ) {
1135
            wpinv_unset_cart_discount( $discount );
1136
        }
1137
    }
1138
}
1139
add_action( 'wpinv_post_remove_from_cart', 'wpinv_maybe_remove_cart_discount' );
1140
1141
function wpinv_multiple_discounts_allowed() {
1142
    $ret = wpinv_get_option( 'allow_multiple_discounts', false );
1143
    return (bool) apply_filters( 'wpinv_multiple_discounts_allowed', $ret );
1144
}
1145
1146
function wpinv_listen_for_cart_discount() {
1147
    global $wpi_session;
1148
    
1149
    if ( empty( $_REQUEST['discount'] ) || is_array( $_REQUEST['discount'] ) ) {
1150
        return;
1151
    }
1152
1153
    $code = preg_replace('/[^a-zA-Z0-9-_]+/', '', $_REQUEST['discount'] );
1154
1155
    $wpi_session->set( 'preset_discount', $code );
1156
}
1157
//add_action( 'init', 'wpinv_listen_for_cart_discount', 0 );
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1158
1159
function wpinv_apply_preset_discount() {
1160
    global $wpi_session;
1161
    
1162
    $code = $wpi_session->get( 'preset_discount' );
1163
1164
    if ( !$code ) {
1165
        return;
1166
    }
1167
1168
    if ( !wpinv_is_discount_valid( $code, '', false ) ) {
1169
        return;
1170
    }
1171
    
1172
    $code = apply_filters( 'wpinv_apply_preset_discount', $code );
1173
1174
    wpinv_set_cart_discount( $code );
1175
1176
    $wpi_session->set( 'preset_discount', null );
1177
}
1178
//add_action( 'init', 'wpinv_apply_preset_discount', 999 );
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1179
1180
function wpinv_get_discount_label( $code, $echo = true ) {
1181
    $label = wp_sprintf( __( 'Discount%1$s', 'invoicing' ), ( $code != '' && $code != 'none' ? ' (<code>' . $code . '</code>)': '' ) );
1182
    $label = apply_filters( 'wpinv_get_discount_label', $label, $code );
1183
1184
    if ( $echo ) {
1185
        echo $label;
1186
    } else {
1187
        return $label;
1188
    }
1189
}
1190
1191
function wpinv_cart_discount_label( $code, $rate, $echo = true ) {
1192
    $label = wp_sprintf( __( '%1$s Discount: %2$s', 'invoicing' ), $rate, $code );
1193
    $label = apply_filters( 'wpinv_cart_discount_label', $label, $code, $rate );
1194
1195
    if ( $echo ) {
1196
        echo $label;
1197
    } else {
1198
        return $label;
1199
    }
1200
}
1201
1202
function wpinv_check_delete_discount( $check, $post, $force_delete ) {
0 ignored issues
show
Unused Code introduced by
The parameter $force_delete is not used and could be removed.

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

Loading history...
1203
    if ( $post->post_type == 'wpi_discount' && wpinv_get_discount_uses( $post->ID ) > 0 ) {
1204
        return true;
1205
    }
1206
    
1207
    return $check;
1208
}
1209
add_filter( 'pre_delete_post', 'wpinv_check_delete_discount', 10, 3 );
1210
1211
function wpinv_checkout_form_validate_discounts() {
1212
    $discounts = wpinv_get_cart_discounts();
1213
    
1214
    if ( !empty( $discounts ) ) {
1215
        $invalid = false;
1216
        
1217
        foreach ( $discounts as $key => $code ) {
1218
            if ( !wpinv_is_discount_valid( $code, get_current_user_id() ) ) {
1219
                $invalid = true;
1220
                
1221
                wpinv_unset_cart_discount( $code );
1222
            }
1223
        }
1224
        
1225
        if ( $invalid ) {
1226
            $errors = wpinv_get_errors();
1227
            $error  = !empty( $errors['wpinv-discount-error'] ) ? $errors['wpinv-discount-error'] . ' ' : '';
1228
            $error  .= __( 'The discount has been removed from cart.', 'invoicing' );
1229
            wpinv_set_error( 'wpinv-discount-error', $error );
1230
            
1231
            wpinv_recalculate_tax( true );
1232
        }
1233
    }
1234
}
1235
add_action( 'wpinv_before_checkout_form', 'wpinv_checkout_form_validate_discounts', -10 );
1236
1237
function wpinv_discount_amount() {
1238
    $output = 0.00;
1239
    
1240
    return apply_filters( 'wpinv_discount_amount', $output );
1241
}