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

wpinv_check_discount_dates()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

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

61
        wp_die( __( 'You do not have permission to create discount codes', 'invoicing' ), /** @scrutinizer ignore-type */ array( 'response' => 403 ) );
Loading history...
62
    }
63
64
    $id = absint( $data['discount'] );
65
    wpinv_update_discount_status( $id, 'pending' );
66
}
67
add_action( 'wpinv_deactivate_discount', 'wpinv_deactivate_discount' );
68
69
function wpinv_get_discounts( $args = array() ) {
70
    $defaults = array(
71
        'post_type'      => 'wpi_discount',
72
        'posts_per_page' => 20,
73
        'paged'          => null,
74
        'post_status'    => array( 'publish', 'pending', 'draft', 'expired' )
75
    );
76
77
    $args = wp_parse_args( $args, $defaults );
78
79
    $discounts = get_posts( $args );
80
81
    if ( $discounts ) {
82
        return $discounts;
83
    }
84
85
    if( ! $discounts && ! empty( $args['s'] ) ) {
86
        $args['meta_key']     = '_wpi_discount_code';
87
        $args['meta_value']   = $args['s'];
88
        $args['meta_compare'] = 'LIKE';
89
        unset( $args['s'] );
90
        $discounts = get_posts( $args );
91
    }
92
93
    if( $discounts ) {
94
        return $discounts;
95
    }
96
97
    return false;
98
}
99
100
function wpinv_get_all_discounts( $args = array() ) {
101
102
    $args = wp_parse_args( $args, array(
103
        'status'         => array( 'publish' ),
104
        'limit'          => get_option( 'posts_per_page' ),
105
        'page'           => 1,
106
        'exclude'        => array(),
107
        'orderby'        => 'date',
108
        'order'          => 'DESC',
109
        'type'           => array_keys( wpinv_get_discount_types() ),
110
        'meta_query'     => array(),
111
        'return'         => 'objects',
112
        'paginate'       => false,
113
    ) );
114
115
    $wp_query_args = array(
116
        'post_type'      => 'wpi_discount',
117
        'post_status'    => $args['status'],
118
        'posts_per_page' => $args['limit'],
119
        'meta_query'     => $args['meta_query'],
120
        'fields'         => 'ids',
121
        'orderby'        => $args['orderby'],
122
        'order'          => $args['order'],
123
        'paged'          => absint( $args['page'] ),
124
    );
125
126
    if ( ! empty( $args['exclude'] ) ) {
127
        $wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
128
    }
129
130
    if ( ! $args['paginate' ] ) {
131
        $wp_query_args['no_found_rows'] = true;
132
    }
133
134
    if ( ! empty( $args['search'] ) ) {
135
136
        $wp_query_args['meta_query'][] = array(
137
            'key'     => '_wpi_discount_code',
138
            'value'   => $args['search'],
139
            'compare' => 'LIKE',
140
        );
141
142
    }
143
    
144
    if ( ! empty( $args['type'] ) ) {
145
        $types = wpinv_parse_list( $args['type'] );
146
        $wp_query_args['meta_query'][] = array(
147
            'key'     => '_wpi_discount_type',
148
            'value'   => implode( ',', $types ),
149
            'compare' => 'IN',
150
        );
151
    }
152
153
    $wp_query_args = apply_filters('wpinv_get_discount_args', $wp_query_args, $args);
154
155
    // Get results.
156
    $discounts = new WP_Query( $wp_query_args );
157
158
    if ( 'objects' === $args['return'] ) {
159
        $return = array_map( 'get_post', $discounts->posts );
160
    } elseif ( 'self' === $args['return'] ) {
161
        return $discounts;
162
    } else {
163
        $return = $discounts->posts;
164
    }
165
166
    if ( $args['paginate' ] ) {
167
        return (object) array(
168
            'discounts'      => $return,
169
            'total'         => $discounts->found_posts,
170
            'max_num_pages' => $discounts->max_num_pages,
171
        );
172
    } else {
173
        return $return;
174
    }
175
176
}
177
178
function wpinv_has_active_discounts() {
179
    $has_active = false;
180
181
    $discounts  = wpinv_get_discounts();
182
183
    if ( $discounts) {
184
        foreach ( $discounts as $discount ) {
185
            if ( wpinv_is_discount_active( $discount->ID ) ) {
186
                $has_active = true;
187
                break;
188
            }
189
        }
190
    }
191
    return $has_active;
192
}
193
194
function wpinv_get_discount( $discount_id = 0 ) {
195
    if( empty( $discount_id ) ) {
196
        return false;
197
    }
198
    
199
    if ( get_post_type( $discount_id ) != 'wpi_discount' ) {
200
        return false;
201
    }
202
203
    $discount = get_post( $discount_id );
204
205
    return $discount;
206
}
207
208
/**
209
 * Fetches a discount object.
210
 * 
211
 * @param int|array|string|WPInv_Discount $discount discount data, object, ID or code.
212
 * @since 1.0.14
213
 * @return WPInv_Discount
214
 */
215
function wpinv_get_discount_obj( $discount = 0 ) {
216
    return new WPInv_Discount( $discount );
217
}
218
219
/**
220
 * Fetch a discount from the db/cache using its discount code.
221
 * 
222
 * @param string $code The discount code.
223
 * @return bool|WP_Post
224
 */
225
function wpinv_get_discount_by_code( $code = '' ) {
226
    return wpinv_get_discount_by( 'code', $code );
227
}
228
229
/**
230
 * Fetch a discount from the db/cache using a given field.
231
 * 
232
 * @param string $field The field to query against: 'ID', 'discount_code', 'code', 'name'
233
 * @param string|int $value The field value
234
 * @return bool|WP_Post
235
 */
236
function wpinv_get_discount_by( $field = '', $value = '' ) {
237
    $data = WPInv_Discount::get_data_by( $field, $value );
238
    if( empty( $data ) ) {
239
        return false;
240
    }
241
242
    return get_post( $data['ID'] );
243
}
244
245
/**
246
 * Updates a discount in the database.
247
 * 
248
 * @param int $post_id The discount's ID.
249
 * @param array $data The discount's properties.
250
 * @return bool
251
 */
252
function wpinv_store_discount( $post_id, $data ) {
253
254
    // Sanitize data.
255
    if( isset( $data['single_use'] ) ) {
256
        $data['is_single_use'] = (bool) $data['single_use'];
257
        unset( $data['single_use'] );
258
    } else {
259
        $data['is_single_use'] = false;
260
    }
261
262
    if( isset( $data['recurring'] ) ) {
263
        $data['is_recurring'] = (bool) $data['recurring'];
264
        unset( $data['recurring'] );
265
    }
266
267
    // Fetch existing data.
268
    $existing_data = WPInv_Discount::get_data_by( 'id', $post_id );
269
    if( empty( $existing_data ) ) {
270
        return false;
271
    }
272
273
    // Merge it into the new data and save.
274
    $data          = wp_parse_args( $data, $existing_data );
0 ignored issues
show
Security Variable Injection introduced by
$data can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and wpinv_store_discount() is called
    in includes/admin/admin-meta-boxes.php on line 379
  2. Enters via parameter $data
    in includes/wpinv-discount-functions.php on line 252

Used in variable context

  1. wp_parse_args() is called
    in includes/wpinv-discount-functions.php on line 261
  2. Enters via parameter $args
    in wordpress/wp-includes/functions.php on line 4294
  3. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 4300
  4. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4865
  5. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4866

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

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

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

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

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

filter:
    dependency_paths: ["lib/*"]

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

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

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

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

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

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

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

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

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

Loading history...
851
    $session = wpinv_get_checkout_session();
852
    
853
    $discounts = !empty( $session['cart_discounts'] ) ? $session['cart_discounts'] : false;
854
    return $discounts;
855
}
856
857
function wpinv_cart_has_discounts( $items = array() ) {
858
    $ret = false;
859
860
    if ( wpinv_get_cart_discounts( $items ) ) {
861
        $ret = true;
862
    }
863
    
864
    /*
865
    $invoice = wpinv_get_invoice_cart();
866
    if ( !empty( $invoice ) && ( $invoice->get_discount() > 0 || $invoice->get_discount_code() ) ) {
867
        $ret = true;
868
    }
869
    */
870
871
    return apply_filters( 'wpinv_cart_has_discounts', $ret );
872
}
873
874
function wpinv_get_cart_discounted_amount( $items = array(), $discounts = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $discounts is not used and could be removed. ( Ignorable by Annotation )

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

874
function wpinv_get_cart_discounted_amount( $items = array(), /** @scrutinizer ignore-unused */ $discounts = false ) {

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

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

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

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

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

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

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

1045
function wpinv_display_cart_discount( /** @scrutinizer ignore-unused */ $formatted = false, $echo = false ) {

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

Loading history...
1046
    $discounts = wpinv_get_cart_discounts();
1047
1048
    if ( empty( $discounts ) ) {
1049
        return false;
1050
    }
1051
1052
    $discount_id  = wpinv_get_discount_id_by_code( $discounts[0] );
1053
    $amount       = wpinv_format_discount_rate( wpinv_get_discount_type( $discount_id ), wpinv_get_discount_amount( $discount_id ) );
1054
1055
    if ( $echo ) {
1056
        echo $amount;
1057
    }
1058
1059
    return $amount;
1060
}
1061
1062
function wpinv_remove_cart_discount() {
1063
    if ( !isset( $_GET['discount_id'] ) || ! isset( $_GET['discount_code'] ) ) {
1064
        return;
1065
    }
1066
1067
    do_action( 'wpinv_pre_remove_cart_discount', absint( $_GET['discount_id'] ) );
1068
1069
    wpinv_unset_cart_discount( urldecode( $_GET['discount_code'] ) );
1070
1071
    do_action( 'wpinv_post_remove_cart_discount', absint( $_GET['discount_id'] ) );
1072
1073
    wp_redirect( wpinv_get_checkout_uri() ); wpinv_die();
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_checkout_uri() can also be of type false; however, parameter $location of wp_redirect() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

1073
    wp_redirect( /** @scrutinizer ignore-type */ wpinv_get_checkout_uri() ); wpinv_die();
Loading history...
1074
}
1075
add_action( 'wpinv_remove_cart_discount', 'wpinv_remove_cart_discount' );
1076
1077
function wpinv_maybe_remove_cart_discount( $cart_key = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $cart_key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

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