Passed
Pull Request — master (#217)
by Patrik
03:45
created

wpinv-discount-functions.php ➔ wpinv_apply_preset_discount()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A wpinv-discount-functions.php ➔ wpinv_check_delete_discount() 0 7 3
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']     = '_wpi_discount_code';
87
        $args['meta_value']   = $args['s'];
88
        $args['meta_compare'] = 'LIKE';
89
        unset( $args['s'] );
90
        $discounts = get_posts( $args );
91
    }
92
93
    if( $discounts ) {
94
        return $discounts;
95
    }
96
97
    return false;
98
}
99
100
function wpinv_has_active_discounts() {
101
    $has_active = false;
102
103
    $discounts  = wpinv_get_discounts();
104
105
    if ( $discounts) {
106
        foreach ( $discounts as $discount ) {
107
            if ( wpinv_is_discount_active( $discount->ID ) ) {
108
                $has_active = true;
109
                break;
110
            }
111
        }
112
    }
113
    return $has_active;
114
}
115
116
function wpinv_get_discount( $discount_id = 0 ) {
117
    if( empty( $discount_id ) ) {
118
        return false;
119
    }
120
    
121
    if ( get_post_type( $discount_id ) != 'wpi_discount' ) {
122
        return false;
123
    }
124
125
    $discount = get_post( $discount_id );
126
127
    return $discount;
128
}
129
130
function wpinv_get_discount_by_code( $code = '' ) {
131
    if( empty( $code ) || ! is_string( $code ) ) {
132
        return false;
133
    }
134
135
    return wpinv_get_discount_by( 'code', $code );
136
}
137
138
function wpinv_get_discount_by( $field = '', $value = '' ) {
139
    if( empty( $field ) || empty( $value ) ) {
140
        return false;
141
    }
142
143
    if( ! is_string( $field ) ) {
144
        return false;
145
    }
146
147
    switch( strtolower( $field ) ) {
148
149
        case 'code':
150
            $meta_query     = array();
151
            $meta_query[]   = array(
152
                'key'     => '_wpi_discount_code',
153
                'value'   => $value,
154
                'compare' => '='
155
            );
156
            
157
            $discount = wpinv_get_discounts( array(
158
                'posts_per_page' => 1,
159
                'post_status'    => 'any',
160
                'meta_query'     => $meta_query,
161
            ) );
162
            
163
            if( $discount ) {
164
                $discount = $discount[0];
165
            }
166
167
            break;
168
169
        case 'id':
170
            $discount = wpinv_get_discount( $value );
171
172
            break;
173
174
        case 'name':
175
            $discount = get_posts( array(
176
                'post_type'      => 'wpi_discount',
177
                'name'           => $value,
178
                'posts_per_page' => 1,
179
                'post_status'    => 'any'
180
            ) );
181
182
            if( $discount ) {
183
                $discount = $discount[0];
184
            }
185
186
            break;
187
188
        default:
189
            return false;
190
    }
191
192
    if( ! empty( $discount ) ) {
193
        return $discount;
194
    }
195
196
    return false;
197
}
198
199
function wpinv_store_discount( $post_id, $data, $post, $update = false ) {
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
    if ( $meta['type'] == 'percent' && (float)$meta['amount'] > 100 ) {
217
        $meta['amount'] = 100;
218
    }
219
220
    if ( !empty( $meta['start'] ) ) {
221
        $meta['start']      = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['start'] ) );
222
    }
223
224
    if ( !empty( $meta['expiration'] ) ) {
225
        $meta['expiration'] = date_i18n( 'Y-m-d H:i:s', strtotime( $meta['expiration'] ) );
226
227
        if ( !empty( $meta['start'] ) && strtotime( $meta['start'] ) > strtotime( $meta['expiration'] ) ) {
228
            $meta['expiration'] = $meta['start'];
229
        }
230
    }
231
    
232
    if ( $meta['uses'] === false ) {
233
        unset( $meta['uses'] );
234
    }
235
    
236 View Code Duplication
    if ( ! empty( $meta['items'] ) ) {
237
        foreach ( $meta['items'] as $key => $item ) {
238
            if ( 0 === intval( $item ) ) {
239
                unset( $meta['items'][ $key ] );
240
            }
241
        }
242
    }
243
    
244 View Code Duplication
    if ( ! empty( $meta['excluded_items'] ) ) {
245
        foreach ( $meta['excluded_items'] as $key => $item ) {
246
            if ( 0 === intval( $item ) ) {
247
                unset( $meta['excluded_items'][ $key ] );
248
            }
249
        }
250
    }
251
    
252
    $meta = apply_filters( 'wpinv_update_discount', $meta, $post_id, $post );
253
    
254
    do_action( 'wpinv_pre_update_discount', $meta, $post_id, $post );
255
    
256
    foreach( $meta as $key => $value ) {
257
        update_post_meta( $post_id, '_wpi_discount_' . $key, $value );
258
    }
259
    
260
    do_action( 'wpinv_post_update_discount', $meta, $post_id, $post );
261
    
262
    return $post_id;
263
}
264
265
function wpinv_remove_discount( $discount_id = 0 ) {
266
    do_action( 'wpinv_pre_delete_discount', $discount_id );
267
268
    wp_delete_post( $discount_id, true );
269
270
    do_action( 'wpinv_post_delete_discount', $discount_id );
271
}
272
273
function wpinv_update_discount_status( $code_id = 0, $new_status = 'publish' ) {
274
    $discount = wpinv_get_discount(  $code_id );
275
276
    if ( $discount ) {
277
        do_action( 'wpinv_pre_update_discount_status', $code_id, $new_status, $discount->post_status );
278
279
        wp_update_post( array( 'ID' => $code_id, 'post_status' => $new_status ) );
280
281
        do_action( 'wpinv_post_update_discount_status', $code_id, $new_status, $discount->post_status );
282
283
        return true;
284
    }
285
286
    return false;
287
}
288
289
function wpinv_discount_exists( $code_id ) {
290
    if ( wpinv_get_discount(  $code_id ) ) {
291
        return true;
292
    }
293
294
    return false;
295
}
296
297
function wpinv_is_discount_active( $code_id = null ) {
298
    $discount = wpinv_get_discount(  $code_id );
299
    $return   = false;
300
301
    if ( $discount ) {
302
        if ( wpinv_is_discount_expired( $code_id ) ) {
303
            if( defined( 'DOING_AJAX' ) ) {
304
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is expired.', 'invoicing' ) );
305
            }
306
        } elseif ( $discount->post_status == 'publish' ) {
307
            $return = true;
308
        } else {
309
            if( defined( 'DOING_AJAX' ) ) {
310
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active.', 'invoicing' ) );
311
            }
312
        }
313
    }
314
315
    return apply_filters( 'wpinv_is_discount_active', $return, $code_id );
316
}
317
318
function wpinv_get_discount_code( $code_id = null ) {
319
    $code = get_post_meta( $code_id, '_wpi_discount_code', true );
320
321
    return apply_filters( 'wpinv_get_discount_code', $code, $code_id );
322
}
323
324
function wpinv_get_discount_start_date( $code_id = null ) {
325
    $start_date = get_post_meta( $code_id, '_wpi_discount_start', true );
326
327
    return apply_filters( 'wpinv_get_discount_start_date', $start_date, $code_id );
328
}
329
330
function wpinv_get_discount_expiration( $code_id = null ) {
331
    $expiration = get_post_meta( $code_id, '_wpi_discount_expiration', true );
332
333
    return apply_filters( 'wpinv_get_discount_expiration', $expiration, $code_id );
334
}
335
336
function wpinv_get_discount_max_uses( $code_id = null ) {
337
    $max_uses = get_post_meta( $code_id, '_wpi_discount_max_uses', true );
338
339
    return (int) apply_filters( 'wpinv_get_discount_max_uses', $max_uses, $code_id );
340
}
341
342
function wpinv_get_discount_uses( $code_id = null ) {
343
    $uses = get_post_meta( $code_id, '_wpi_discount_uses', true );
344
345
    return (int) apply_filters( 'wpinv_get_discount_uses', $uses, $code_id );
346
}
347
348
function wpinv_get_discount_min_total( $code_id = null ) {
349
    $min_total = get_post_meta( $code_id, '_wpi_discount_min_total', true );
350
351
    return (float) apply_filters( 'wpinv_get_discount_min_total', $min_total, $code_id );
352
}
353
354
function wpinv_get_discount_max_total( $code_id = null ) {
355
    $max_total = get_post_meta( $code_id, '_wpi_discount_max_total', true );
356
357
    return (float) apply_filters( 'wpinv_get_discount_max_total', $max_total, $code_id );
358
}
359
360
function wpinv_get_discount_amount( $code_id = null ) {
361
    $amount = get_post_meta( $code_id, '_wpi_discount_amount', true );
362
363
    return (float) apply_filters( 'wpinv_get_discount_amount', $amount, $code_id );
364
}
365
366
function wpinv_get_discount_type( $code_id = null, $name = false ) {
367
    $type = strtolower( get_post_meta( $code_id, '_wpi_discount_type', true ) );
368
    
369
    if ( $name ) {
370
        $name = wpinv_get_discount_type_name( $type );
371
        
372
        return apply_filters( 'wpinv_get_discount_type_name', $name, $code_id );
373
    }
374
375
    return apply_filters( 'wpinv_get_discount_type', $type, $code_id );
376
}
377
378
function wpinv_discount_status( $status ) {
379
    switch( $status ){
380
        case 'expired' :
381
            $name = __( 'Expired', 'invoicing' );
382
            break;
383
        case 'publish' :
384
        case 'active' :
385
            $name = __( 'Active', 'invoicing' );
386
            break;
387
        default :
388
            $name = __( 'Inactive', 'invoicing' );
389
            break;
390
    }
391
    return $name;
392
}
393
394 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...
395
    $excluded_items = get_post_meta( $code_id, '_wpi_discount_excluded_items', true );
396
397
    if ( empty( $excluded_items ) || ! is_array( $excluded_items ) ) {
398
        $excluded_items = array();
399
    }
400
401
    return (array) apply_filters( 'wpinv_get_discount_excluded_items', $excluded_items, $code_id );
402
}
403
404 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...
405
    $item_reqs = get_post_meta( $code_id, '_wpi_discount_items', true );
406
407
    if ( empty( $item_reqs ) || ! is_array( $item_reqs ) ) {
408
        $item_reqs = array();
409
    }
410
411
    return (array) apply_filters( 'wpinv_get_discount_item_reqs', $item_reqs, $code_id );
412
}
413
414
function wpinv_get_discount_item_condition( $code_id = 0 ) {
415
    return get_post_meta( $code_id, '_wpi_discount_item_condition', true );
416
}
417
418
function wpinv_is_discount_not_global( $code_id = 0 ) {
419
    return (bool) get_post_meta( $code_id, '_wpi_discount_is_not_global', true );
420
}
421
422
function wpinv_is_discount_expired( $code_id = null ) {
423
    $discount = wpinv_get_discount(  $code_id );
424
    $return   = false;
425
426 View Code Duplication
    if ( $discount ) {
427
        $expiration = wpinv_get_discount_expiration( $code_id );
428
        if ( $expiration ) {
429
            $expiration = strtotime( $expiration );
430
            if ( $expiration < current_time( 'timestamp' ) ) {
431
                // Discount is expired
432
                wpinv_update_discount_status( $code_id, 'pending' );
433
                $return = true;
434
            }
435
        }
436
    }
437
438
    return apply_filters( 'wpinv_is_discount_expired', $return, $code_id );
439
}
440
441
function wpinv_is_discount_started( $code_id = null ) {
442
    $discount = wpinv_get_discount(  $code_id );
443
    $return   = false;
444
445
    if ( $discount ) {
446
        $start_date = wpinv_get_discount_start_date( $code_id );
447
448 View Code Duplication
        if ( $start_date ) {
449
            $start_date = strtotime( $start_date );
450
451
            if ( $start_date < current_time( 'timestamp' ) ) {
452
                // Discount has past the start date
453
                $return = true;
454
            } else {
455
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
456
            }
457
        } else {
458
            // No start date for this discount, so has to be true
459
            $return = true;
460
        }
461
    }
462
463
    return apply_filters( 'wpinv_is_discount_started', $return, $code_id );
464
}
465
466
function wpinv_check_discount_dates( $code_id = null ) {
467
    $discount = wpinv_get_discount(  $code_id );
468
    $return   = false;
469
470
    if ( $discount ) {
471
        $start_date = wpinv_get_discount_start_date( $code_id );
472
473 View Code Duplication
        if ( $start_date ) {
474
            $start_date = strtotime( $start_date );
475
476
            if ( $start_date < current_time( 'timestamp' ) ) {
477
                // Discount has past the start date
478
                $return = true;
479
            } else {
480
                wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not active yet.', 'invoicing' ) );
481
            }
482
        } else {
483
            // No start date for this discount, so has to be true
484
            $return = true;
485
        }
486
        
487 View Code Duplication
        if ( $return ) {
488
            $expiration = wpinv_get_discount_expiration( $code_id );
489
            
490
            if ( $expiration ) {
491
                $expiration = strtotime( $expiration );
492
                if ( $expiration < current_time( 'timestamp' ) ) {
493
                    // Discount is expired
494
                    wpinv_update_discount_status( $code_id, 'pending' );
495
                    $return = true;
496
                }
497
            }
498
        }
499
    }
500
    
501
    return apply_filters( 'wpinv_check_discount_dates', $return, $code_id );
502
}
503
504
function wpinv_is_discount_maxed_out( $code_id = null ) {
505
    $discount = wpinv_get_discount(  $code_id );
506
    $return   = false;
507
508
    if ( $discount ) {
509
        $uses = wpinv_get_discount_uses( $code_id );
510
        // Large number that will never be reached
511
        $max_uses = wpinv_get_discount_max_uses( $code_id );
512
        // Should never be greater than, but just in case
513 View Code Duplication
        if ( $uses >= $max_uses && ! empty( $max_uses ) ) {
514
            // Discount is maxed out
515
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount has reached its maximum usage.', 'invoicing' ) );
516
            $return = true;
517
        }
518
    }
519
520
    return apply_filters( 'wpinv_is_discount_maxed_out', $return, $code_id );
521
}
522
523 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...
524
    $discount = wpinv_get_discount( $code_id );
525
    $return   = false;
526
527
    if ( $discount ) {
528
        $min         = (float)wpinv_get_discount_min_total( $code_id );
529
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
530
531
        if ( !$min > 0 || $cart_amount >= $min ) {
532
            // Minimum has been met
533
            $return = true;
534
        } else {
535
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Minimum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $min ) ) ) );
536
        }
537
    }
538
539
    return apply_filters( 'wpinv_is_discount_min_met', $return, $code_id );
540
}
541
542 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...
543
    $discount = wpinv_get_discount( $code_id );
544
    $return   = false;
545
546
    if ( $discount ) {
547
        $max         = (float)wpinv_get_discount_max_total( $code_id );
548
        $cart_amount = (float)wpinv_get_cart_discountable_subtotal( $code_id );
549
550
        if ( !$max > 0 || $cart_amount <= $max ) {
551
            // Minimum has been met
552
            $return = true;
553
        } else {
554
            wpinv_set_error( 'wpinv-discount-error', sprintf( __( 'Maximum invoice amount should be %s', 'invoicing' ), wpinv_price( wpinv_format_amount( $max ) ) ) );
555
        }
556
    }
557
558
    return apply_filters( 'wpinv_is_discount_max_met', $return, $code_id );
559
}
560
561
function wpinv_discount_is_single_use( $code_id = 0 ) {
562
    $single_use = get_post_meta( $code_id, '_wpi_discount_is_single_use', true );
563
    return (bool) apply_filters( 'wpinv_is_discount_single_use', $single_use, $code_id );
564
}
565
566
function wpinv_discount_is_recurring( $code_id = 0, $code = false ) {
567
    if ( $code ) {
568
        $discount = wpinv_get_discount_by_code( $code_id );
569
        
570
        if ( !empty( $discount ) ) {
571
            $code_id = $discount->ID;
572
        }
573
    }
574
    
575
    $recurring = get_post_meta( $code_id, '_wpi_discount_is_recurring', true );
576
    
577
    return (bool) apply_filters( 'wpinv_is_discount_recurring', $recurring, $code_id, $code );
578
}
579
580
function wpinv_discount_item_reqs_met( $code_id = null ) {
581
    $item_reqs    = wpinv_get_discount_item_reqs( $code_id );
582
    $condition    = wpinv_get_discount_item_condition( $code_id );
583
    $excluded_ps  = wpinv_get_discount_excluded_items( $code_id );
584
    $cart_items   = wpinv_get_cart_contents();
585
    $cart_ids     = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
586
    $ret          = false;
587
588
    if ( empty( $item_reqs ) && empty( $excluded_ps ) ) {
589
        $ret = true;
590
    }
591
592
    // Normalize our data for item requirements, exclusions and cart data
593
    // First absint the items, then sort, and reset the array keys
594
    $item_reqs = array_map( 'absint', $item_reqs );
595
    asort( $item_reqs );
596
    $item_reqs = array_values( $item_reqs );
597
598
    $excluded_ps  = array_map( 'absint', $excluded_ps );
599
    asort( $excluded_ps );
600
    $excluded_ps  = array_values( $excluded_ps );
601
602
    $cart_ids     = array_map( 'absint', $cart_ids );
603
    asort( $cart_ids );
604
    $cart_ids     = array_values( $cart_ids );
605
606
    // Ensure we have requirements before proceeding
607
    if ( !$ret && ! empty( $item_reqs ) ) {
608
        switch( $condition ) {
609 View Code Duplication
            case 'all' :
610
                // Default back to true
611
                $ret = true;
612
613
                foreach ( $item_reqs as $item_id ) {
614
                    if ( !wpinv_item_in_cart( $item_id ) ) {
615
                        wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
616
                        $ret = false;
617
                        break;
618
                    }
619
                }
620
621
                break;
622
623 View Code Duplication
            default : // Any
624
                foreach ( $item_reqs as $item_id ) {
625
                    if ( wpinv_item_in_cart( $item_id ) ) {
626
                        $ret = true;
627
                        break;
628
                    }
629
                }
630
631
                if( ! $ret ) {
632
                    wpinv_set_error( 'wpinv-discount-error', __( 'The item requirements for this discount are not met.', 'invoicing' ) );
633
                }
634
635
                break;
636
        }
637
    } else {
638
        $ret = true;
639
    }
640
641 View Code Duplication
    if( ! empty( $excluded_ps ) ) {
642
        // Check that there are items other than excluded ones in the cart
643
        if( $cart_ids == $excluded_ps ) {
644
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is not valid for the cart contents.', 'invoicing' ) );
645
            $ret = false;
646
        }
647
    }
648
649
    return (bool) apply_filters( 'wpinv_is_discount_item_req_met', $ret, $code_id, $condition );
650
}
651
652
function wpinv_is_discount_used( $code = null, $user = '', $code_id = 0 ) {
653
    global $wpi_checkout_id;
654
    
655
    $return = false;
656
657
    if ( empty( $code_id ) ) {
658
        $code_id = wpinv_get_discount_id_by_code( $code );
659
        
660
        if( empty( $code_id ) ) {
661
            return false; // No discount was found
662
        }
663
    }
664
665
    if ( wpinv_discount_is_single_use( $code_id ) ) {
666
        $payments = array();
667
668
        $user_id = 0;
669
        if ( is_int( $user ) ) {
670
            $user_id = absint( $user );
671
        } else if ( is_email( $user ) && $user_data = get_user_by( 'email', $user ) ) {
672
            $user_id = $user_data->ID;
673
        } else if ( $user_data = get_user_by( 'login', $user ) ) {
674
            $user_id = $user_data->ID;
675
        } else if ( absint( $user ) > 0 ) {
676
            $user_id = absint( $user );
677
        }
678
679
        if ( !empty( $user_id ) ) {
680
            $query    = array( 'user' => $user_id, 'limit' => false );
681
            $payments = wpinv_get_invoices( $query ); // Get all payments with matching user id
682
        }
683
684
        if ( $payments ) {
685
            foreach ( $payments as $payment ) {
686
                // Don't count discount used for current invoice chekcout.
687
                if ( !empty( $wpi_checkout_id ) && $wpi_checkout_id == $payment->ID ) {
688
                    continue;
689
                }
690
                
691
                if ( $payment->has_status( array( 'wpi-cancelled', 'wpi-failed' ) ) ) {
692
                    continue;
693
                }
694
695
                $discounts = $payment->get_discounts( true );
696
                if ( empty( $discounts ) ) {
697
                    continue;
698
                }
699
700
                $discounts = $discounts && !is_array( $discounts ) ? explode( ',', $discounts ) : $discounts;
701
702 View Code Duplication
                if ( !empty( $discounts ) && is_array( $discounts ) ) {
703
                    if ( in_array( strtolower( $code ), array_map( 'strtolower', $discounts ) ) ) {
704
                        wpinv_set_error( 'wpinv-discount-error', __( 'This discount has already been redeemed.', 'invoicing' ) );
705
                        $return = true;
706
                        break;
707
                    }
708
                }
709
            }
710
        }
711
    }
712
713
    return apply_filters( 'wpinv_is_discount_used', $return, $code, $user );
714
}
715
716
function wpinv_is_discount_valid( $code = '', $user = '', $set_error = true ) {
717
    $return      = false;
718
    $discount_id = wpinv_get_discount_id_by_code( $code );
719
    $user        = trim( $user );
720
721
    if ( wpinv_get_cart_contents() ) {
722
        if ( $discount_id ) {
723
            if (
724
                wpinv_is_discount_active( $discount_id ) &&
725
                wpinv_check_discount_dates( $discount_id ) &&
726
                !wpinv_is_discount_maxed_out( $discount_id ) &&
727
                !wpinv_is_discount_used( $code, $user, $discount_id ) &&
728
                wpinv_discount_is_min_met( $discount_id ) &&
729
                wpinv_discount_is_max_met( $discount_id ) &&
730
                wpinv_discount_item_reqs_met( $discount_id )
731
            ) {
732
                $return = true;
733
            }
734
        } elseif( $set_error ) {
735
            wpinv_set_error( 'wpinv-discount-error', __( 'This discount is invalid.', 'invoicing' ) );
736
        }
737
    }
738
739
    return apply_filters( 'wpinv_is_discount_valid', $return, $discount_id, $code, $user );
740
}
741
742
function wpinv_get_discount_id_by_code( $code ) {
743
    $discount = wpinv_get_discount_by_code( $code );
744
    if( $discount ) {
745
        return $discount->ID;
746
    }
747
    return false;
748
}
749
750
function wpinv_get_discounted_amount( $code, $base_price ) {
751
    $amount      = $base_price;
0 ignored issues
show
Unused Code introduced by
$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...
752
    $discount_id = wpinv_get_discount_id_by_code( $code );
753
754
    if( $discount_id ) {
755
        $type        = wpinv_get_discount_type( $discount_id );
756
        $rate        = wpinv_get_discount_amount( $discount_id );
757
758
        if ( $type == 'flat' ) {
759
            // Set amount
760
            $amount = $base_price - $rate;
761
            if ( $amount < 0 ) {
762
                $amount = 0;
763
            }
764
765
        } else {
766
            // Percentage discount
767
            $amount = $base_price - ( $base_price * ( $rate / 100 ) );
768
        }
769
770
    } else {
771
772
        $amount = $base_price;
773
774
    }
775
776
    return apply_filters( 'wpinv_discounted_amount', $amount );
777
}
778
779 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...
780
781
    $id   = wpinv_get_discount_id_by_code( $code );
782
    $uses = wpinv_get_discount_uses( $id );
783
784
    if ( $uses ) {
785
        $uses++;
786
    } else {
787
        $uses = 1;
788
    }
789
790
    update_post_meta( $id, '_wpi_discount_uses', $uses );
791
792
    do_action( 'wpinv_discount_increase_use_count', $uses, $id, $code );
793
794
    return $uses;
795
796
}
797
798 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...
799
800
    $id   = wpinv_get_discount_id_by_code( $code );
801
    $uses = wpinv_get_discount_uses( $id );
802
803
    if ( $uses ) {
804
        $uses--;
805
    }
806
807
    if ( $uses < 0 ) {
808
        $uses = 0;
809
    }
810
811
    update_post_meta( $id, '_wpi_discount_uses', $uses );
812
813
    do_action( 'wpinv_discount_decrease_use_count', $uses, $id, $code );
814
815
    return $uses;
816
817
}
818
819
function wpinv_format_discount_rate( $type, $amount ) {
820
    if ( $type == 'flat' ) {
821
        return wpinv_price( wpinv_format_amount( $amount ) );
822
    } else {
823
        return $amount . '%';
824
    }
825
}
826
827
function wpinv_set_cart_discount( $code = '' ) {    
828
    if ( wpinv_multiple_discounts_allowed() ) {
829
        // Get all active cart discounts
830
        $discounts = wpinv_get_cart_discounts();
831
    } else {
832
        $discounts = false; // Only one discount allowed per purchase, so override any existing
833
    }
834
835
    if ( $discounts ) {
836
        $key = array_search( strtolower( $code ), array_map( 'strtolower', $discounts ) );
837
        if( false !== $key ) {
838
            unset( $discounts[ $key ] ); // Can't set the same discount more than once
839
        }
840
        $discounts[] = $code;
841
    } else {
842
        $discounts = array();
843
        $discounts[] = $code;
844
    }
845
    $discounts = array_values( $discounts );
846
    
847
    $data = wpinv_get_checkout_session();
848 View Code Duplication
    if ( empty( $data ) ) {
849
        $data = array();
850
    } else {
851
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
852
            $payment_meta['user_info']['discount']  = implode( ',', $discounts );
853
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
854
        }
855
    }
856
    $data['cart_discounts'] = $discounts;
857
    
858
    wpinv_set_checkout_session( $data );
859
    
860
    return $discounts;
861
}
862
863
function wpinv_unset_cart_discount( $code = '' ) {    
864
    $discounts = wpinv_get_cart_discounts();
865
866
    if ( $code && !empty( $discounts ) && in_array( $code, $discounts ) ) {
867
        $key = array_search( $code, $discounts );
868
        unset( $discounts[ $key ] );
869
            
870
        $data = wpinv_get_checkout_session();
871
        $data['cart_discounts'] = $discounts;
872 View Code Duplication
        if ( !empty( $data['invoice_id'] ) && $payment_meta = wpinv_get_invoice_meta( $data['invoice_id'] ) ) {
873
            $payment_meta['user_info']['discount']  = !empty( $discounts ) ? implode( ',', $discounts ) : '';
874
            update_post_meta( $data['invoice_id'], '_wpinv_payment_meta', $payment_meta );
875
        }
876
        
877
        wpinv_set_checkout_session( $data );
878
    }
879
880
    return $discounts;
881
}
882
883
function wpinv_unset_all_cart_discounts() {
884
    $data = wpinv_get_checkout_session();
885
    
886
    if ( !empty( $data ) && isset( $data['cart_discounts'] ) ) {
887
        unset( $data['cart_discounts'] );
888
        
889
         wpinv_set_checkout_session( $data );
890
         return true;
891
    }
892
    
893
    return false;
894
}
895
896
function wpinv_get_cart_discounts( $items = array() ) {
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...
897
    $session = wpinv_get_checkout_session();
898
    
899
    $discounts = !empty( $session['cart_discounts'] ) ? $session['cart_discounts'] : false;
900
    return $discounts;
901
}
902
903
function wpinv_cart_has_discounts( $items = array() ) {
904
    $ret = false;
905
906
    if ( wpinv_get_cart_discounts( $items ) ) {
907
        $ret = true;
908
    }
909
    
910
    /*
911
    $invoice = wpinv_get_invoice_cart();
912
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
913
        $ret = true;
914
    }
915
    */
916
917
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
918
}
919
920 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...
921
    $amount = 0.00;
922
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
923
924
    if ( $items ) {
925
        $discounts = wp_list_pluck( $items, 'discount' );
926
927
        if ( is_array( $discounts ) ) {
928
            $discounts = array_map( 'floatval', $discounts );
929
            $amount    = array_sum( $discounts );
930
        }
931
    }
932
933
    return apply_filters( 'wpinv_get_cart_discounted_amount', $amount );
934
}
935
936
function wpinv_get_cart_items_discount_amount( $items = array(), $discount = false ) {
937
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
938
    
939
    if ( empty( $discount ) || empty( $items ) ) {
940
        return 0;
941
    }
942
943
    $amount = 0;
944
    
945
    foreach ( $items as $item ) {
946
        $amount += wpinv_get_cart_item_discount_amount( $item, $discount );
947
    }
948
    
949
    $amount = wpinv_round_amount( $amount );
950
951
    return $amount;
952
}
953
954
function wpinv_get_cart_item_discount_amount( $item = array(), $discount = false ) {
955
    global $wpinv_is_last_cart_item, $wpinv_flat_discount_total;
956
    
957
    $amount = 0;
958
959
    if ( empty( $item ) || empty( $item['id'] ) ) {
960
        return $amount;
961
    }
962
963
    if ( empty( $item['quantity'] ) ) {
964
        return $amount;
965
    }
966
967
    if ( empty( $item['options'] ) ) {
968
        $item['options'] = array();
969
    }
970
971
    $price            = wpinv_get_cart_item_price( $item['id'], $item, $item['options'] );
972
    $discounted_price = $price;
973
974
    $discounts = false === $discount ? wpinv_get_cart_discounts() : $discount;
975
    if ( empty( $discounts ) ) {
976
        return $amount;
977
    }
978
979
    if ( $discounts ) {
980
        if ( is_array( $discounts ) ) {
981
            $discounts = array_values( $discounts );
982
        } else {
983
            $discounts = explode( ',', $discounts );
984
        }
985
    }
986
987
    if( $discounts ) {
988
        foreach ( $discounts as $discount ) {
989
            $code_id = wpinv_get_discount_id_by_code( $discount );
990
991
            // Check discount exists
992
            if( ! $code_id ) {
993
                continue;
994
            }
995
996
            $reqs           = wpinv_get_discount_item_reqs( $code_id );
997
            $excluded_items = wpinv_get_discount_excluded_items( $code_id );
998
999
            // Make sure requirements are set and that this discount shouldn't apply to the whole cart
1000
            if ( !empty( $reqs ) && wpinv_is_discount_not_global( $code_id ) ) {
1001
                foreach ( $reqs as $item_id ) {
1002
                    if ( $item_id == $item['id'] && ! in_array( $item['id'], $excluded_items ) ) {
1003
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1004
                    }
1005
                }
1006
            } else {
1007
                // This is a global cart discount
1008
                if ( !in_array( $item['id'], $excluded_items ) ) {
1009
                    if ( 'flat' === wpinv_get_discount_type( $code_id ) ) {
1010
                        $items_subtotal    = 0.00;
1011
                        $cart_items        = wpinv_get_cart_contents();
1012
                        
1013
                        foreach ( $cart_items as $cart_item ) {
1014
                            if ( ! in_array( $cart_item['id'], $excluded_items ) ) {
1015
                                $options = !empty( $cart_item['options'] ) ? $cart_item['options'] : array();
1016
                                $item_price      = wpinv_get_cart_item_price( $cart_item['id'], $cart_item, $options );
1017
                                $items_subtotal += $item_price * $cart_item['quantity'];
1018
                            }
1019
                        }
1020
1021
                        $subtotal_percent  = ( ( $price * $item['quantity'] ) / $items_subtotal );
1022
                        $code_amount       = wpinv_get_discount_amount( $code_id );
1023
                        $discounted_amount = $code_amount * $subtotal_percent;
1024
                        $discounted_price -= $discounted_amount;
1025
1026
                        $wpinv_flat_discount_total += round( $discounted_amount, wpinv_currency_decimal_filter() );
1027
1028
                        if ( $wpinv_is_last_cart_item && $wpinv_flat_discount_total < $code_amount ) {
1029
                            $adjustment = $code_amount - $wpinv_flat_discount_total;
1030
                            $discounted_price -= $adjustment;
1031
                        }
1032
                    } else {
1033
                        $discounted_price -= $price - wpinv_get_discounted_amount( $discount, $price );
1034
                    }
1035
                }
1036
            }
1037
        }
1038
1039
        $amount = ( $price - apply_filters( 'wpinv_get_cart_item_discounted_amount', $discounted_price, $discounts, $item, $price ) );
1040
1041
        if ( 'flat' !== wpinv_get_discount_type( $code_id ) ) {
0 ignored issues
show
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...
1042
            $amount = $amount * $item['quantity'];
1043
        }
1044
    }
1045
1046
    return $amount;
1047
}
1048
1049
function wpinv_cart_discounts_html( $items = array() ) {
1050
    echo wpinv_get_cart_discounts_html( $items );
1051
}
1052
1053
function wpinv_get_cart_discounts_html( $items = array(), $discounts = false ) {
1054
    global $wpi_cart_columns;
1055
    
1056
    $items  = !empty( $items ) ? $items : wpinv_get_cart_content_details();
1057
    
1058
    if ( !$discounts ) {
1059
        $discounts = wpinv_get_cart_discounts( $items );
0 ignored issues
show
Security Bug introduced by
It seems like $items defined by !empty($items) ? $items ..._cart_content_details() on line 1056 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...
1060
    }
1061
1062
    if ( !$discounts ) {
1063
        return;
1064
    }
1065
    
1066
    $discounts = is_array( $discounts ) ? $discounts : array( $discounts );
1067
    
1068
    $html = '';
1069
1070
    foreach ( $discounts as $discount ) {
1071
        $discount_id    = wpinv_get_discount_id_by_code( $discount );
1072
        $discount_value = wpinv_get_discount_amount( $discount_id );
1073
        $rate           = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), $discount_value );
1074
        $amount         = wpinv_get_cart_items_discount_amount( $items, $discount );
0 ignored issues
show
Security Bug introduced by
It seems like $items defined by !empty($items) ? $items ..._cart_content_details() on line 1056 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...
1075
        $remove_btn     = '<a title="' . esc_attr__( 'Remove discount', 'invoicing' ) . '" data-code="' . $discount . '" data-value="' . $discount_value . '" class="wpi-discount-remove" href="javascript:void(0);">[<i class="fa fa-times" aria-hidden="true"></i>]</a> ';
1076
        
1077
        $html .= '<tr class="wpinv_cart_footer_row wpinv_cart_discount_row">';
1078
        ob_start();
1079
        do_action( 'wpinv_checkout_table_discount_first', $items );
1080
        $html .= ob_get_clean();
1081
        $html .= '<td class="wpinv_cart_discount_label text-right" colspan="' . $wpi_cart_columns . '">' . $remove_btn . '<strong>' . wpinv_cart_discount_label( $discount, $rate, false ) . '</strong></td><td class="wpinv_cart_discount text-right"><span data-discount="' . $amount . '" class="wpinv_cart_discount_amount">&ndash;' . wpinv_price( wpinv_format_amount( $amount ) ) . '</span></td>';
1082
        ob_start();
1083
        do_action( 'wpinv_checkout_table_discount_last', $items );
1084
        $html .= ob_get_clean();
1085
        $html .= '</tr>';
1086
    }
1087
1088
    return apply_filters( 'wpinv_get_cart_discounts_html', $html, $discounts, $rate );
0 ignored issues
show
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...
1089
}
1090
1091
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...
1092
    $discounts = wpinv_get_cart_discounts();
1093
1094
    if ( empty( $discounts ) ) {
1095
        return false;
1096
    }
1097
1098
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1099
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1100
1101
    if ( $echo ) {
1102
        echo $amount;
1103
    }
1104
1105
    return $amount;
1106
}
1107
1108
function wpinv_remove_cart_discount() {
1109
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1110
        return;
1111
    }
1112
1113
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1114
1115
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1116
1117
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1118
1119
    wp_redirect( wpinv_get_checkout_uri() ); wpinv_die();
1120
}
1121
add_action( 'wpinv_remove_cart_discount', 'wpinv_remove_cart_discount' );
1122
1123
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...
1124
    $discounts = wpinv_get_cart_discounts();
1125
1126
    if ( !$discounts ) {
1127
        return;
1128
    }
1129
1130
    foreach ( $discounts as $discount ) {
1131
        if ( !wpinv_is_discount_valid( $discount ) ) {
1132
            wpinv_unset_cart_discount( $discount );
1133
        }
1134
    }
1135
}
1136
add_action( 'wpinv_post_remove_from_cart', 'wpinv_maybe_remove_cart_discount' );
1137
1138
function wpinv_multiple_discounts_allowed() {
1139
    $ret = wpinv_get_option( 'allow_multiple_discounts', false );
1140
    return (bool) apply_filters( 'wpinv_multiple_discounts_allowed', $ret );
1141
}
1142
1143
function wpinv_get_discount_label( $code, $echo = true ) {
1144
    $label = wp_sprintf( __( 'Discount%1$s', 'invoicing' ), ( $code != '' && $code != 'none' ? ' (<code>' . $code . '</code>)': '' ) );
1145
    $label = apply_filters( 'wpinv_get_discount_label', $label, $code );
1146
1147
    if ( $echo ) {
1148
        echo $label;
1149
    } else {
1150
        return $label;
1151
    }
1152
}
1153
1154
function wpinv_cart_discount_label( $code, $rate, $echo = true ) {
1155
    $label = wp_sprintf( __( 'Discount: %s', 'invoicing' ), $code );
1156
    $label = apply_filters( 'wpinv_cart_discount_label', $label, $code, $rate );
1157
1158
    if ( $echo ) {
1159
        echo $label;
1160
    } else {
1161
        return $label;
1162
    }
1163
}
1164
1165
function wpinv_check_delete_discount( $check, $post, $force_delete ) {
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...
1166
    if ( $post->post_type == 'wpi_discount' && wpinv_get_discount_uses( $post->ID ) > 0 ) {
1167
        return true;
1168
    }
1169
    
1170
    return $check;
1171
}
1172
add_filter( 'pre_delete_post', 'wpinv_check_delete_discount', 10, 3 );
1173
1174
function wpinv_checkout_form_validate_discounts() {
1175
    global $wpi_checkout_id;
1176
    
1177
    $discounts = wpinv_get_cart_discounts();
1178
    
1179
    if ( !empty( $discounts ) ) {
1180
        $invalid = false;
1181
        
1182
        foreach ( $discounts as $key => $code ) {
1183
            if ( !wpinv_is_discount_valid( $code, (int)wpinv_get_user_id( $wpi_checkout_id ) ) ) {
1184
                $invalid = true;
1185
                
1186
                wpinv_unset_cart_discount( $code );
1187
            }
1188
        }
1189
        
1190
        if ( $invalid ) {
1191
            $errors = wpinv_get_errors();
1192
            $error  = !empty( $errors['wpinv-discount-error'] ) ? $errors['wpinv-discount-error'] . ' ' : '';
1193
            $error  .= __( 'The discount has been removed from cart.', 'invoicing' );
1194
            wpinv_set_error( 'wpinv-discount-error', $error );
1195
            
1196
            wpinv_recalculate_tax( true );
1197
        }
1198
    }
1199
}
1200
add_action( 'wpinv_before_checkout_form', 'wpinv_checkout_form_validate_discounts', -10 );
1201
1202
function wpinv_discount_amount() {
1203
    $output = 0.00;
1204
    
1205
    return apply_filters( 'wpinv_discount_amount', $output );
1206
}