Issues (850)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/wpinv-item-functions.php (1 issue)

1
<?php
2
/**
3
 * Contains item functions.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Retrieves an item by it's ID.
13
 *
14
 * @param int the item ID to retrieve.
15
 * @return WPInv_Item|false
16
 */
17
function wpinv_get_item_by_id( $id ) {
18
    $item = wpinv_get_item( $id );
19
    return empty( $item ) || $id != $item->get_id() ? false : $item;
20
}
21
22
/**
23
 * Retrieves an item by it's ID, Name, Slug or custom id.
24
 *
25
 * @return WPInv_Item|false
26
 */
27
function wpinv_get_item_by( $field = '', $value = '', $type = '' ) {
28
29
    if ( 'id' === strtolower( $field ) ) {
30
        return wpinv_get_item_by_id( $value );
31
    }
32
33
    $id = WPInv_Item::get_item_id_by_field( $value, strtolower( $field ), $type );
34
    return empty( $id ) ? false : wpinv_get_item( $id );
35
36
}
37
38
/**
39
 * Retrieves an item by it's ID, name or custom_name.
40
 *
41
 * @param int|WPInv_Item the item to retrieve.
42
 * @return WPInv_Item|false
43
 */
44
function wpinv_get_item( $item = 0 ) {
45
46
    if ( empty( $item ) ) {
47
        return false;
48
    }
49
50
    $item = new WPInv_Item( $item );
51
    return $item->exists() ? $item : false;
52
53
}
54
55
function wpinv_get_all_items( $args = array() ) {
56
57
    $args = wp_parse_args(
58
        $args,
59
        array(
60
			'status'     => array( 'publish' ),
61
			'limit'      => get_option( 'posts_per_page' ),
62
			'page'       => 1,
63
			'exclude'    => array(),
64
			'orderby'    => 'date',
65
			'order'      => 'DESC',
66
			'type'       => wpinv_item_types(),
67
			'meta_query' => array(
68
                array(
69
                    'key'     => '_wpinv_one_time',
70
                    'compare' => 'NOT EXISTS',
71
                ),
72
            ),
73
			'return'     => 'objects',
74
			'paginate'   => false,
75
        )
76
    );
77
78
    $wp_query_args = array(
79
        'post_type'      => 'wpi_item',
80
        'post_status'    => $args['status'],
81
        'posts_per_page' => $args['limit'],
82
        'meta_query'     => $args['meta_query'],
83
        'fields'         => 'ids',
84
        'orderby'        => $args['orderby'],
85
        'order'          => $args['order'],
86
        'paged'          => absint( $args['page'] ),
87
    );
88
89
    if ( ! empty( $args['exclude'] ) ) {
90
        $wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
91
    }
92
93
    if ( ! $args['paginate'] ) {
94
        $wp_query_args['no_found_rows'] = true;
95
    }
96
97
    if ( ! empty( $args['search'] ) ) {
98
        $wp_query_args['s'] = $args['search'];
99
    }
100
101
    if ( ! empty( $args['type'] ) && $args['type'] !== wpinv_item_types() ) {
102
        $types = wpinv_parse_list( $args['type'] );
103
        $wp_query_args['meta_query'][] = array(
104
            'key'     => '_wpinv_type',
105
            'value'   => implode( ',', $types ),
106
            'compare' => 'IN',
107
        );
108
    }
109
110
    $wp_query_args = apply_filters( 'wpinv_get_items_args', $wp_query_args, $args );
111
112
    // Get results.
113
    $items = new WP_Query( $wp_query_args );
114
115
    if ( 'objects' === $args['return'] ) {
116
        $return = array_map( 'wpinv_get_item_by_id', $items->posts );
117
    } elseif ( 'self' === $args['return'] ) {
118
        return $items;
119
    } else {
120
        $return = $items->posts;
121
    }
122
123
    if ( $args['paginate'] ) {
124
        return (object) array(
125
            'items'         => $return,
126
            'total'         => $items->found_posts,
127
            'max_num_pages' => $items->max_num_pages,
128
        );
129
    } else {
130
        return $return;
131
    }
132
133
}
134
135
function wpinv_is_free_item( $item_id = 0 ) {
136
    if ( empty( $item_id ) ) {
137
        return false;
138
    }
139
140
    $item = new WPInv_Item( $item_id );
141
142
    return $item->is_free();
143
}
144
145
/**
146
 * Checks whether an item is editable.
147
 *
148
 * @param WP_Post|WPInv_Item|Int $item The item to check for.
149
 */
150
function wpinv_item_is_editable( $item = 0 ) {
151
152
    // Fetch the item.
153
    $item = new WPInv_Item( $item );
154
155
    // Check if it is editable.
156
    return $item->is_editable();
157
}
158
159
function wpinv_get_item_price( $item_id = 0 ) {
160
    if ( empty( $item_id ) ) {
161
        return false;
162
    }
163
164
    $item = new WPInv_Item( $item_id );
165
166
    return $item->get_price();
167
}
168
169
/**
170
 * Checks if the provided item is recurring.
171
 *
172
 * @param WPInv_Item|int $item
173
 */
174
function wpinv_is_recurring_item( $item = 0 ) {
175
    $item = new WPInv_Item( $item );
176
    return $item->is_recurring();
177
}
178
179
function wpinv_item_price( $item_id = 0 ) {
180
    if ( empty( $item_id ) ) {
181
        return false;
182
    }
183
184
    $price = wpinv_get_item_price( $item_id );
185
    $price = wpinv_price( $price );
186
187
    return apply_filters( 'wpinv_item_price', $price, $item_id );
188
}
189
190
function wpinv_get_item_final_price( $item_id = 0, $amount_override = null ) {
191
    if ( is_null( $amount_override ) ) {
192
        $original_price = get_post_meta( $item_id, '_wpinv_price', true );
193
    } else {
194
        $original_price = $amount_override;
195
    }
196
197
    $price = $original_price;
198
199
    return apply_filters( 'wpinv_get_item_final_price', $price, $item_id );
200
}
201
202
function wpinv_item_custom_singular_name( $item_id ) {
203
    if ( empty( $item_id ) ) {
204
        return false;
205
    }
206
207
    $item = new WPInv_Item( $item_id );
208
209
    return $item->get_custom_singular_name();
210
}
211
212
function wpinv_get_item_types() {
213
    $item_types = array(
214
		'custom' => __( 'Standard', 'invoicing' ),
215
		'fee'    => __( 'Fee', 'invoicing' ),
216
	);
217
    return apply_filters( 'wpinv_get_item_types', $item_types );
218
}
219
220
function wpinv_item_types() {
221
    $item_types = wpinv_get_item_types();
222
223
    return ( ! empty( $item_types ) ? array_keys( $item_types ) : array() );
224
}
225
226
function wpinv_get_item_type( $item_id ) {
227
    if ( empty( $item_id ) ) {
228
        return false;
229
    }
230
231
    $item = new WPInv_Item( $item_id );
232
233
    return $item->get_type();
234
}
235
236
function wpinv_item_type( $item_id ) {
237
    $item_types = wpinv_get_item_types();
238
239
    $item_type = wpinv_get_item_type( $item_id );
240
241
    if ( empty( $item_type ) ) {
242
        $item_type = '-';
243
    }
244
245
    $item_type = isset( $item_types[ $item_type ] ) ? $item_types[ $item_type ] : __( $item_type, 'invoicing' );
246
247
    return apply_filters( 'wpinv_item_type', $item_type, $item_id );
248
}
249
250
function wpinv_get_random_item( $post_ids = true ) {
251
    wpinv_get_random_items( 1, $post_ids );
252
}
253
254
function wpinv_get_random_items( $num = 3, $post_ids = true ) {
255
    $args = array();
256
    if ( $post_ids ) {
257
        $args = array(
258
			'fields' => 'ids',
259
		);
260
    }
261
262
    $args = array_merge(
263
        $args,
264
        array(
265
            'post_type'  => 'wpi_item',
266
			'orderby'    => 'rand',
267
			'post_count' => $num,
268
            'meta_query' => array(
269
                array(
270
                    'key'     => '_wpinv_one_time',
271
                    'compare' => 'NOT EXISTS',
272
                ),
273
            ),
274
        )
275
    );
276
277
    $args  = apply_filters( 'wpinv_get_random_items', $args );
278
279
    return get_posts( $args );
280
}
281
282
/**
283
 * Adds additional information suffixes to an item name.
284
 *
285
 * @param WPInv_Item|int $item
286
 * @param bool $html
287
 */
288
function wpinv_get_item_suffix( $item, $html = true ) {
289
290
    $item   = new WPInv_Item( $item );
291
    $suffix = $item->is_recurring() ? ' ' . __( '(r)', 'invoicing' ) : '';
292
    $suffix = $html ? $suffix : wp_strip_all_tags( $suffix );
293
294
    return apply_filters( 'wpinv_get_item_suffix', $suffix, $item, $html );
295
}
296
297
/**
298
 * Deletes an invoicing item.
299
 *
300
 * @param WPInv_Item|int $item
301
 * @param bool $force_delete
302
 */
303
function wpinv_remove_item( $item = 0, $force_delete = false ) {
304
    $item = new WPInv_Item( $item );
305
    $item->delete( $force_delete );
306
}
307
308
/**
309
 * Create/Update an item.
310
 *
311
 * @param array $args an array of arguments to create the item.
312
 *
313
 *    Here are all the args (with defaults) that you can set/modify.
314
 *    array(
315
 *        'ID'                   => 0,           - If specified, the item with that ID will be updated.
316
 *        'parent_id'            => 0,           - Int. Parent item ID.
317
 *        'status'               => 'draft',     - String. Item status - either draft, pending or publish.
318
 *        'date_created'         => null,        - String. strtotime() compatible string.
319
 *        'date_modified'        => null,        - String. strtotime() compatible string.
320
 *        'name'                 => '',          - String. Required. Item name.
321
 *        'description'          => '',          - String. Item description.
322
 *        'author'               => 1,           - int. Owner of the item.
323
 *        'price'                => 0,           - float. Item price.
324
 *        'vat_rule'             => 'digital',   - string. VAT rule.
325
 *        'vat_class'            => '_standard', - string. VAT class.
326
 *        'type'                 => 'custom',    - string. Item type.
327
 *        'custom_id'            => null,        - string. Custom item id.
328
 *        'custom_name'          => null,        - string. Custom item name.
329
 *        'custom_singular_name' => null,        - string. Custom item singular name.
330
 *        'is_editable'          => 1,           - int|bool. Whether or not the item is editable.
331
 *        'is_dynamic_pricing'   => 0,           - int|bool. Whether or not users can update the item price.
332
 *        'minimum_price'        => 0,           - float. If dynamic, set the minimum price that a user can set..
333
 *        'is_recurring'         => 0,           - int|bool. Whether or not this item is recurring.
334
 *        'recurring_period'     => 'D',         - string. If recurring, set the recurring period as either days (D), weeks (W), months (M) or years (Y).
335
 *        'recurring_interval'   => 1,           - int. The recurring interval.
336
 *        'recurring_limit'      => 0,           - int. The recurring limit. Enter 0 for unlimited.
337
 *        'is_free_trial'        => false,       - int|bool. Whether or not this item has a free trial.
338
 *        'trial_period'         => 'D',         - string. If it has a free trial, set the trial period as either days (D), weeks (W), months (M) or years (Y).
339
 *        'trial_interval'       => 1,           - int. The trial interval.
340
 *    );
341
 * @param bool $wp_error whether or not to return a WP_Error on failure.
342
 * @return bool|WP_Error|WPInv_Item
343
 */
344
function wpinv_create_item( $args = array(), $wp_error = false ) {
345
346
    // Prepare the item.
347
    if ( ! empty( $args['custom_id'] ) && empty( $args['ID'] ) ) {
348
        $type = empty( $args['type'] ) ? 'custom' : $args['type'];
349
        $item = wpinv_get_item_by( 'custom_id', $args['custom_id'], $type );
350
351
        if ( ! empty( $item ) ) {
352
            $args['ID'] = $item->get_id();
353
        }
354
    }
355
356
    // Do we have an item?
357
    if ( ! empty( $args['ID'] ) ) {
358
        $item = new WPInv_Item( $args['ID'] );
359
    } else {
360
        $item = new WPInv_Item();
361
    }
362
363
    // Do we have an error?
364
    if ( ! empty( $item->last_error ) ) {
365
        return $wp_error ? new WP_Error( 'invalid_item', $item->last_error ) : false;
366
    }
367
368
    // Update item props.
369
    $item->set_props( $args );
370
371
    // Save the item.
372
    $item->save();
373
374
    // Do we have an error?
375
    if ( ! empty( $item->last_error ) ) {
376
        return $wp_error ? new WP_Error( 'not_saved', $item->last_error ) : false;
377
    }
378
379
    // Was the item saved?
380
    if ( ! $item->get_id() ) {
381
        return $wp_error ? new WP_Error( 'not_saved', __( 'An error occured while saving the item', 'invoicing' ) ) : false;
382
    }
383
384
    return $item;
385
386
}
387
388
/**
389
 * Updates an item.
390
 *
391
 * @see wpinv_create_item()
392
 */
393
function wpinv_update_item( $args = array(), $wp_error = false ) {
394
    return wpinv_create_item( $args, $wp_error );
395
}
396
397
/**
398
 * Sanitizes a recurring period
399
 */
400
function getpaid_sanitize_recurring_period( $period, $full = false ) {
401
402
    $periods = array(
403
        'D' => 'day',
404
        'W' => 'week',
405
        'M' => 'month',
406
        'Y' => 'year',
407
    );
408
409
    if ( ! isset( $periods[ $period ] ) ) {
410
        $period = 'D';
411
    }
412
413
    return $full ? $periods[ $period ] : $period;
414
415
}
416
417
function wpinv_item_max_buyable_quantity( $item_id ) {
418
    return apply_filters( 'wpinv_item_max_buyable_quantity', 5, $item_id );
419
}
420
421
/**
422
 * Retrieves recurring price description.
423
 *
424
 * @param WPInv_Item|GetPaid_Form_Item $item
425
 */
426
function getpaid_item_recurring_price_help_text( $item, $currency = '', $_initial_price = false, $_recurring_price = false ) {
427
428
    // Abort if it is not recurring.
429
    if ( ! $item->is_recurring() ) {
430
        return '';
431
    }
432
433
    $initial_price   = false === $_initial_price ? wpinv_price( $item->get_initial_price(), $currency ) : $_initial_price;
434
    $recurring_price = false === $_recurring_price ? wpinv_price( $item->get_recurring_price(), $currency ) : $_recurring_price;
435
    $period          = getpaid_get_subscription_period_label( $item->get_recurring_period(), $item->get_recurring_interval(), '' );
436
    $initial_class   = 'getpaid-item-initial-price';
437
    $recurring_class = 'getpaid-item-recurring-price';
438
    $bill_times      = $item->get_recurring_limit();
439
    $bill_times_less = $bill_times - 1;
440
441
    if ( ! empty( $bill_times ) ) {
442
		$bill_times = $item->get_recurring_interval() * $bill_times;
443
        $bill_times_less = getpaid_get_subscription_period_label( $item->get_recurring_period(), $bill_times - $item->get_recurring_interval() );
444
		$bill_times = getpaid_get_subscription_period_label( $item->get_recurring_period(), $bill_times );
445
	}
446
447
    if ( $item instanceof GetPaid_Form_Item && false === $_initial_price ) {
448
        $initial_price   = wpinv_price( $item->get_sub_total(), $currency );
449
        $recurring_price = wpinv_price( $item->get_recurring_sub_total(), $currency );
450
    }
451
452
    if ( wpinv_price( 0, $currency ) == $initial_price && wpinv_price( 0, $currency ) == $recurring_price ) {
453
        return __( 'Free forever', 'invoicing' );
454
    }
455
456
    // For free trial items.
457
    if ( $item->has_free_trial() ) {
458
        $trial_period = getpaid_get_subscription_period_label( $item->get_trial_period(), $item->get_trial_interval() );
459
460
        if ( wpinv_price( 0, $currency ) == $initial_price ) {
461
462
            if ( empty( $bill_times ) ) {
463
464
                return sprintf(
465
                    // translators: $1: is the trial period, $2: is the recurring price, $3: is the susbcription period
466
                    _x( 'Free for %1$s then %2$s / %3$s', 'Item subscription amount. (e.g.: Free for 1 month then $120 / year)', 'invoicing' ),
467
                    "<span class='getpaid-item-trial-period'>$trial_period</span>",
468
                    "<span class='$recurring_class'>$recurring_price</span>",
469
                    "<span class='getpaid-item-recurring-period'>$period</span>"
470
                );
471
472
            }
473
474
            return sprintf(
475
                // translators: $1: is the trial period, $2: is the recurring price, $3: is the susbcription period, $4: is the bill times
476
                _x( 'Free for %1$s then %2$s / %3$s for %4$s', 'Item subscription amount. (e.g.: Free for 1 month then $120 / year for 4 years)', 'invoicing' ),
477
                "<span class='getpaid-item-trial-period'>$trial_period</span>",
478
                "<span class='$recurring_class'>$recurring_price</span>",
479
                "<span class='getpaid-item-recurring-period'>$period</span>",
480
                "<span class='getpaid-item-recurring-bill-times'>$bill_times</span>"
481
            );
482
483
        }
484
485
        if ( empty( $bill_times ) ) {
486
487
            return sprintf(
488
                // translators: $1: is the initial price, $2: is the trial period, $3: is the recurring price, $4: is the susbcription period
489
                _x( '%1$s for %2$s then %3$s / %4$s', 'Item subscription amount. (e.g.: $7 for 1 month then $120 / year)', 'invoicing' ),
490
                "<span class='$initial_class'>$initial_price</span>",
491
                "<span class='getpaid-item-trial-period'>$trial_period</span>",
492
                "<span class='$recurring_class'>$recurring_price</span>",
493
                "<span class='getpaid-item-recurring-period'>$period</span>"
494
            );
495
496
        }
497
498
        return sprintf(
499
            // translators: $1: is the initial price, $2: is the trial period, $3: is the recurring price, $4: is the susbcription period, $4: is the susbcription bill times
500
            _x( '%1$s for %2$s then %3$s / %4$s for %5$s', 'Item subscription amount. (e.g.: $7 for 1 month then $120 / year for 5 years)', 'invoicing' ),
501
            "<span class='$initial_class'>$initial_price</span>",
502
            "<span class='getpaid-item-trial-period'>$trial_period</span>",
503
            "<span class='$recurring_class'>$recurring_price</span>",
504
            "<span class='getpaid-item-recurring-period'>$period</span>",
505
            "<span class='getpaid-item-recurring-bill-times'>$bill_times</span>"
506
        );
507
508
    }
509
510
    if ( $initial_price == $recurring_price ) {
511
512
        if ( empty( $bill_times ) ) {
513
514
            return sprintf(
515
                // translators: $1: is the recurring price, $2: is the susbcription period
516
                _x( '%1$s / %2$s', 'Item subscription amount. (e.g.: $120 / year)', 'invoicing' ),
517
                "<span class='$recurring_class'>$recurring_price</span>",
518
                "<span class='getpaid-item-recurring-period'>$period</span>"
519
            );
520
521
        }
522
523
        return sprintf(
524
            // translators: $1: is the recurring price, $2: is the susbcription period, $3: is the susbcription bill times
525
            _x( '%1$s / %2$s for %3$s', 'Item subscription amount. (e.g.: $120 / year for 5 years)', 'invoicing' ),
526
            "<span class='$recurring_class'>$recurring_price</span>",
527
            "<span class='getpaid-item-recurring-period'>$period</span>",
528
            "<span class='getpaid-item-recurring-bill-times'>$bill_times</span>"
529
        );
530
531
    }
532
533
    if ( $initial_price == wpinv_price( 0, $currency ) ) {
534
535
        if ( empty( $bill_times ) ) {
536
537
            return sprintf(
538
                // translators: $1: is the recurring period, $2: is the recurring price
539
                _x( 'Free for %1$s then %2$s / %1$s', 'Item subscription amount. (e.g.: Free for 3 months then $7 / 3 months)', 'invoicing' ),
540
                "<span class='getpaid-item-recurring-period'>$period</span>",
541
                "<span class='$recurring_class'>$recurring_price</span>"
542
            );
543
544
        }
545
546
        return sprintf(
547
            // translators: $1: is the recurring period, $2: is the recurring price, $3: is the bill times
548
            _x( 'Free for %1$s then %2$s / %1$s for %3$s', 'Item subscription amount. (e.g.: Free for 3 months then $7 / 3 months for 12 months)', 'invoicing' ),
549
            "<span class='getpaid-item-recurring-period'>$period</span>",
550
            "<span class='$recurring_class'>$recurring_price</span>",
551
            "<span class='getpaid-item-recurring-bill-times'>$bill_times_less</span>"
552
        );
553
554
    }
555
556
    if ( empty( $bill_times ) ) {
557
558
        return sprintf(
559
            // translators: $1: is the initial price, $2: is the recurring price, $3: is the susbcription period
560
            _x( 'Initial payment of %1$s then %2$s / %3$s', 'Item subscription amount. (e.g.: Initial payment of $7 then $120 / year)', 'invoicing' ),
561
            "<span class='$initial_class'>$initial_price</span>",
562
            "<span class='$recurring_class'>$recurring_price</span>",
563
            "<span class='getpaid-item-recurring-period'>$period</span>"
564
        );
565
566
    }
567
568
    return sprintf(
569
        // translators: $1: is the initial price, $2: is the recurring price, $3: is the susbcription period, $4: is the susbcription bill times
570
        _x( 'Initial payment of %1$s then %2$s / %3$s for %4$s', 'Item subscription amount. (e.g.: Initial payment of $7 then $120 / year for 4 years)', 'invoicing' ),
571
        "<span class='$initial_class'>$initial_price</span>",
572
        "<span class='$recurring_class'>$recurring_price</span>",
573
        "<span class='getpaid-item-recurring-period'>$period</span>",
574
        "<span class='getpaid-item-recurring-bill-times'>$bill_times_less</span>"
575
    );
576
577
}
578
579
/**
580
 * Check a item type's support for a given feature.
581
 *
582
 * @since 2.8.8
583
 *
584
 * @param string $item_type The item type being checked.
585
 * @param string $feature   The feature being checked.
586
 * @param int    $item_ID   The item post ID. Optional.
587
 * @return bool Whether the item type supports the given feature.
588
 */
589
function getpaid_item_type_supports( $item_type, $feature, $item_ID = 0 ) {
590
	$supports = false;
591
592
	if ( ! is_scalar( $item_type ) ) {
0 ignored issues
show
The condition is_scalar($item_type) is always true.
Loading history...
593
		return $supports;
594
	}
595
596
	switch ( $feature ) {
597
		case 'buy_now':
598
			if ( '' === $item_type || 'fee' === $item_type || 'custom' === $item_type ) {
599
				$supports = true;
600
			}
601
			break;
602
	}
603
604
	return apply_filters( 'getpaid_item_type_supports', $supports, $item_type, $feature, $item_ID );
605
}