getpaid_sanitize_recurring_period()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 4
nop 2
dl 0
loc 14
rs 10
c 0
b 0
f 0
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 );
0 ignored issues
show
Bug introduced by
It seems like $price can also be of type false; however, parameter $amount of wpinv_price() does only seem to accept double, 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

185
    $price = wpinv_price( /** @scrutinizer ignore-type */ $price );
Loading history...
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
introduced by
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
}