Passed
Branch master (50908e)
by Stiofan
07:01
created

wpinv-item-functions.php ➔ wpinv_update_item()   F

Complexity

Conditions 28
Paths 1288

Size

Total Lines 75

Duplication

Lines 12
Ratio 16 %

Importance

Changes 0
Metric Value
cc 28
nc 1288
nop 2
dl 12
loc 75
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
// Exit if accessed directly
3
if ( ! defined( 'ABSPATH' ) ) exit;
4
5
function wpinv_get_item_by_id( $id ) {
6
    return wpinv_get_item_by( 'id', $id );
7
}
8
9
function wpinv_get_item_by( $field = '', $value = '', $type = '' ) {
10
    if( empty( $field ) || empty( $value ) ) {
11
        return false;
12
    }
13
    
14
    $posts = array();
15
16
    switch( strtolower( $field ) ) {
17
        case 'id':
18
            $item = new WPInv_Item( $value );
19
20
            if ( !empty( $item ) && $item->post_type == 'wpi_item' ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Item. Since you implemented __get, consider adding a @property annotation.
Loading history...
21
                return $item;
22
            }
23
            return false;
24
25
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
26
27
        case 'slug':
28
        case 'name':
29
            $posts = get_posts( array(
30
                'post_type'      => 'wpi_item',
31
                'name'           => $value,
32
                'posts_per_page' => 1,
33
                'post_status'    => 'any'
34
            ) );
35
36
            break;
37
        case 'custom_id':
38
            if ( empty( $value ) || empty( $type ) ) {
39
                return false;
40
            }
41
            
42
            $meta_query = array();
43
            $meta_query[] = array(
44
                'key'   => '_wpinv_type',
45
                'value' => $type,
46
            );
47
            $meta_query[] = array(
48
                'key'   => '_wpinv_custom_id',
49
                'value' => $value,
50
            );
51
            
52
            $args = array(
53
                'post_type'      => 'wpi_item',
54
                'posts_per_page' => 1,
55
                'post_status'    => 'any',
56
                'orderby'        => 'ID',
57
                'order'          => 'ASC',
58
                'meta_query'     => array( $meta_query )
59
            );
60
            
61
            $posts = get_posts( $args );
62
63
            break;
64
65
        default:
66
            return false;
67
    }
68
    
69
    if ( !empty( $posts[0] ) ) {
70
        $item = new WPInv_Item( $posts[0]->ID );
71
72
        if ( !empty( $item ) && $item->post_type == 'wpi_item' ) {
73
            return $item;
74
        }
75
    }
76
77
    return false;
78
}
79
80
function wpinv_get_item( $item = 0 ) {
81
    if ( is_numeric( $item ) ) {
82
        $item = get_post( $item );
83
        if ( ! $item || 'wpi_item' !== $item->post_type )
0 ignored issues
show
introduced by
$item is of type WP_Post, thus it always evaluated to true.
Loading history...
84
            return null;
85
        return $item;
86
    }
87
88
    $args = array(
89
        'post_type'   => 'wpi_item',
90
        'name'        => $item,
91
        'numberposts' => 1
92
    );
93
94
    $item = get_posts($args);
95
96
    if ( $item ) {
97
        return $item[0];
98
    }
99
100
    return null;
101
}
102
103
function wpinv_get_all_items( $args = array() ) {
104
105
    $args = wp_parse_args( $args, array(
106
        'status'         => array( 'publish' ),
107
        'limit'          => get_option( 'posts_per_page' ),
108
        'page'           => 1,
109
        'exclude'        => array(),
110
        'orderby'        => 'date',
111
        'order'          => 'DESC',
112
        'type'           => wpinv_item_types(),
113
        'meta_query'     => array(),
114
        'return'         => 'objects',
115
        'paginate'       => false,
116
    ) );
117
118
    $wp_query_args = array(
119
        'post_type'      => 'wpi_item',
120
        'post_status'    => $args['status'],
121
        'posts_per_page' => $args['limit'],
122
        'meta_query'     => $args['meta_query'],
123
        'fields'         => 'ids',
124
        'orderby'        => $args['orderby'],
125
        'order'          => $args['order'],
126
        'paged'          => absint( $args['page'] ),
127
    );
128
129
    if ( ! empty( $args['exclude'] ) ) {
130
        $wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
131
    }
132
133
    if ( ! $args['paginate' ] ) {
134
        $wp_query_args['no_found_rows'] = true;
135
    }
136
137
    if ( ! empty( $args['search'] ) ) {
138
        $wp_query_args['s'] = $args['search'];
139
    }
140
141
    if ( ! empty( $args['type'] ) && $args['type'] !== wpinv_item_types() ) {
142
        $types = wpinv_parse_list( $args['type'] );
143
        $wp_query_args['meta_query'][] = array(
144
            'key'     => '_wpinv_type',
145
            'value'   => implode( ',', $types ),
146
            'compare' => 'IN',
147
        );
148
    }
149
150
    $wp_query_args = apply_filters('wpinv_get_items_args', $wp_query_args, $args);
151
152
    // Get results.
153
    $items = new WP_Query( $wp_query_args );
154
155
    if ( 'objects' === $args['return'] ) {
156
        $return = array_map( 'wpinv_get_item_by_id', $items->posts );
157
    } elseif ( 'self' === $args['return'] ) {
158
        return $items;
159
    } else {
160
        $return = $items->posts;
161
    }
162
163
    if ( $args['paginate' ] ) {
164
        return (object) array(
165
            'items'      => $return,
166
            'total'         => $items->found_posts,
167
            'max_num_pages' => $items->max_num_pages,
168
        );
169
    } else {
170
        return $return;
171
    }
172
173
}
174
175
function wpinv_is_free_item( $item_id = 0 ) {
176
    if( empty( $item_id ) ) {
177
        return false;
178
    }
179
180
    $item = new WPInv_Item( $item_id );
181
    
182
    return $item->is_free();
183
}
184
185
function wpinv_item_is_editable( $item = 0 ) {
186
    if ( !empty( $item ) && is_a( $item, 'WP_Post' ) ) {
187
        $item = $item->ID;
188
    }
189
        
190
    if ( empty( $item ) ) {
191
        return true;
192
    }
193
194
    $item = new WPInv_Item( $item );
195
    
196
    return (bool) $item->is_editable();
197
}
198
199
function wpinv_get_item_price( $item_id = 0 ) {
200
    if( empty( $item_id ) ) {
201
        return false;
202
    }
203
204
    $item = new WPInv_Item( $item_id );
205
    
206
    return $item->get_price();
207
}
208
209
function wpinv_is_recurring_item( $item_id = 0 ) {
210
    if( empty( $item_id ) ) {
211
        return false;
212
    }
213
214
    $item = new WPInv_Item( $item_id );
215
    
216
    return $item->is_recurring();
217
}
218
219
function wpinv_item_price( $item_id = 0 ) {
220
    if( empty( $item_id ) ) {
221
        return false;
222
    }
223
224
    $price = wpinv_get_item_price( $item_id );
225
    $price = wpinv_price( wpinv_format_amount( $price ) );
226
    
227
    return apply_filters( 'wpinv_item_price', $price, $item_id );
228
}
229
230
function wpinv_item_show_price( $item_id = 0, $echo = true ) {
231
    if ( empty( $item_id ) ) {
232
        $item_id = get_the_ID();
233
    }
234
235
    $price = wpinv_item_price( $item_id );
236
237
    $price           = apply_filters( 'wpinv_item_price', wpinv_sanitize_amount( $price ), $item_id );
238
    $formatted_price = '<span class="wpinv_price" id="wpinv_item_' . $item_id . '">' . $price . '</span>';
239
    $formatted_price = apply_filters( 'wpinv_item_price_after_html', $formatted_price, $item_id, $price );
240
241
    if ( $echo ) {
242
        echo $formatted_price;
243
    } else {
244
        return $formatted_price;
245
    }
246
}
247
248
function wpinv_get_item_final_price( $item_id = 0, $amount_override = null ) {
249
    if ( is_null( $amount_override ) ) {
250
        $original_price = get_post_meta( $item_id, '_wpinv_price', true );
251
    } else {
252
        $original_price = $amount_override;
253
    }
254
    
255
    $price = $original_price;
256
257
    return apply_filters( 'wpinv_get_item_final_price', $price, $item_id );
258
}
259
260
function wpinv_item_custom_singular_name( $item_id ) {
261
    if( empty( $item_id ) ) {
262
        return false;
263
    }
264
265
    $item = new WPInv_Item( $item_id );
266
    
267
    return $item->get_custom_singular_name();
268
}
269
270
function wpinv_get_item_types() {
271
    $item_types = array(
272
            'custom'    => __( 'Standard', 'invoicing' ),
273
            'fee'       => __( 'Fee', 'invoicing' ),
274
        );
275
    return apply_filters( 'wpinv_get_item_types', $item_types );
276
}
277
278
function wpinv_item_types() {
279
    $item_types = wpinv_get_item_types();
280
    
281
    return ( !empty( $item_types ) ? array_keys( $item_types ) : array() );
282
}
283
284
function wpinv_get_item_type( $item_id ) {
285
    if( empty( $item_id ) ) {
286
        return false;
287
    }
288
289
    $item = new WPInv_Item( $item_id );
290
    
291
    return $item->get_type();
292
}
293
294
function wpinv_item_type( $item_id ) {
295
    $item_types = wpinv_get_item_types();
296
    
297
    $item_type = wpinv_get_item_type( $item_id );
298
    
299
    if ( empty( $item_type ) ) {
300
        $item_type = '-';
301
    }
302
    
303
    $item_type = isset( $item_types[$item_type] ) ? $item_types[$item_type] : __( $item_type, 'invoicing' );
304
305
    return apply_filters( 'wpinv_item_type', $item_type, $item_id );
306
}
307
308
function wpinv_record_item_in_log( $item_id = 0, $file_id, $user_info, $ip, $invoice_id ) {
309
    global $wpinv_logs;
310
    
311
    if ( empty( $wpinv_logs ) ) {
312
        return false;
313
    }
314
315
    $log_data = array(
316
        'post_parent'	=> $item_id,
317
        'log_type'		=> 'wpi_item'
318
    );
319
320
    $user_id = isset( $user_info['user_id'] ) ? $user_info['user_id'] : (int) -1;
321
322
    $log_meta = array(
323
        'user_info'	=> $user_info,
324
        'user_id'	=> $user_id,
325
        'file_id'	=> (int)$file_id,
326
        'ip'		=> $ip,
327
        'invoice_id'=> $invoice_id,
328
    );
329
330
    $wpinv_logs->insert_log( $log_data, $log_meta );
331
}
332
333
function wpinv_remove_item_logs_on_delete( $item_id = 0 ) {
334
    if ( 'wpi_item' !== get_post_type( $item_id ) )
335
        return;
336
337
    global $wpinv_logs;
338
    
339
    if ( empty( $wpinv_logs ) ) {
340
        return false;
341
    }
342
343
    // Remove all log entries related to this item
344
    $wpinv_logs->delete_logs( $item_id );
345
}
346
add_action( 'delete_post', 'wpinv_remove_item_logs_on_delete' );
347
348
function wpinv_get_random_item( $post_ids = true ) {
349
    wpinv_get_random_items( 1, $post_ids );
350
}
351
352
function wpinv_get_random_items( $num = 3, $post_ids = true ) {
353
    if ( $post_ids ) {
354
        $args = array( 'post_type' => 'wpi_item', 'orderby' => 'rand', 'post_count' => $num, 'fields' => 'ids' );
355
    } else {
356
        $args = array( 'post_type' => 'wpi_item', 'orderby' => 'rand', 'post_count' => $num );
357
    }
358
    
359
    $args  = apply_filters( 'wpinv_get_random_items', $args );
360
    
361
    return get_posts( $args );
362
}
363
364
function wpinv_get_item_token( $url = '' ) {
365
    $args    = array();
366
    $hash    = apply_filters( 'wpinv_get_url_token_algorithm', 'sha256' );
367
    $secret  = apply_filters( 'wpinv_get_url_token_secret', hash( $hash, wp_salt() ) );
368
369
    $parts   = parse_url( $url );
370
    $options = array();
371
372
    if ( isset( $parts['query'] ) ) {
373
        wp_parse_str( $parts['query'], $query_args );
374
375
        if ( ! empty( $query_args['o'] ) ) {
376
            $options = explode( ':', rawurldecode( $query_args['o'] ) );
377
378
            if ( in_array( 'ip', $options ) ) {
379
                $args['ip'] = wpinv_get_ip();
380
            }
381
382
            if ( in_array( 'ua', $options ) ) {
383
                $ua = wpinv_get_user_agent();
384
                $args['user_agent'] = rawurlencode( $ua );
385
            }
386
        }
387
    }
388
389
    $args = apply_filters( 'wpinv_get_url_token_args', $args, $url, $options );
390
391
    $args['secret'] = $secret;
392
    $args['token']  = false;
393
394
    $url   = add_query_arg( $args, $url );
395
    $parts = parse_url( $url );
396
397
    if ( ! isset( $parts['path'] ) ) {
398
        $parts['path'] = '';
399
    }
400
401
    $token = md5( $parts['path'] . '?' . $parts['query'] );
402
403
    return $token;
404
}
405
406
function wpinv_validate_url_token( $url = '' ) {
407
    $ret   = false;
408
    $parts = parse_url( $url );
409
410
    if ( isset( $parts['query'] ) ) {
411
        wp_parse_str( $parts['query'], $query_args );
412
413
        $allowed = apply_filters( 'wpinv_url_token_allowed_params', array(
414
            'item',
415
            'ttl',
416
            'token'
417
        ) );
418
419
        $remove = array();
420
421
        foreach( $query_args as $key => $value ) {
422
            if( false === in_array( $key, $allowed ) ) {
423
                $remove[] = $key;
424
            }
425
        }
426
427
        if( ! empty( $remove ) ) {
428
            $url = remove_query_arg( $remove, $url );
429
        }
430
431
        if ( isset( $query_args['ttl'] ) && current_time( 'timestamp' ) > $query_args['ttl'] ) {
432
            wp_die( apply_filters( 'wpinv_item_link_expired_text', __( 'Sorry but your item link has expired.', 'invoicing' ) ), __( 'Error', 'invoicing' ), array( 'response' => 403 ) );
433
        }
434
435
        if ( isset( $query_args['token'] ) && $query_args['token'] == wpinv_get_item_token( $url ) ) {
436
            $ret = true;
437
        }
438
439
    }
440
441
    return apply_filters( 'wpinv_validate_url_token', $ret, $url, $query_args );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $query_args does not seem to be defined for all execution paths leading up to this point.
Loading history...
442
}
443
444
function wpinv_item_in_cart( $item_id = 0, $options = array() ) {
445
    $cart_items = wpinv_get_cart_contents();
446
447
    $ret = false;
448
449
    if ( is_array( $cart_items ) ) {
450
        foreach ( $cart_items as $item ) {
451
            if ( $item['id'] == $item_id ) {
452
                $ret = true;
453
                break;
454
            }
455
        }
456
    }
457
458
    return (bool) apply_filters( 'wpinv_item_in_cart', $ret, $item_id, $options );
459
}
460
461
function wpinv_get_cart_item_tax( $item_id = 0, $subtotal = '', $options = array() ) {
462
    $tax = 0;
463
    if ( ! wpinv_item_is_tax_exclusive( $item_id ) ) {
464
        $country = !empty( $_POST['country'] ) ? $_POST['country'] : false;
465
        $state   = isset( $_POST['state'] ) ? $_POST['state'] : '';
466
467
        $tax = wpinv_calculate_tax( $subtotal, $country, $state, $item_id );
468
    }
469
470
    return apply_filters( 'wpinv_get_cart_item_tax', $tax, $item_id, $subtotal, $options );
471
}
472
473
function wpinv_cart_item_price( $item ) {
474
    $item_id    = isset( $item['id'] ) ? $item['id'] : 0;
475
    $price      = isset( $item['item_price'] ) ? wpinv_round_amount( $item['item_price'] ) : 0;
476
    $tax        = wpinv_price( wpinv_format_amount( $item['tax'] ) );
477
    
478
    if ( !wpinv_is_free_item( $item_id ) && !wpinv_item_is_tax_exclusive( $item_id ) ) {
479
        if ( wpinv_prices_show_tax_on_checkout() && !wpinv_prices_include_tax() ) {
480
            $price += $tax;
481
        }
482
        
483
        if( !wpinv_prices_show_tax_on_checkout() && wpinv_prices_include_tax() ) {
484
            $price -= $tax;
485
        }        
486
    }
487
488
    $price = wpinv_price( wpinv_format_amount( $price ) );
489
490
    return apply_filters( 'wpinv_cart_item_price_label', $price, $item );
491
}
492
493
function wpinv_cart_item_subtotal( $item ) {
494
    $subtotal   = isset( $item['subtotal'] ) ? $item['subtotal'] : 0;
495
    $subtotal   = wpinv_price( wpinv_format_amount( $subtotal ) );
496
497
    return apply_filters( 'wpinv_cart_item_subtotal_label', $subtotal, $item );
498
}
499
500
function wpinv_cart_item_tax( $item ) {
501
    $tax        = '';
502
    $tax_rate   = '';
503
    
504
    if ( isset( $item['tax'] ) && $item['tax'] > 0 && $item['subtotal'] > 0 ) {
505
        $tax      = wpinv_price( wpinv_format_amount( $item['tax'] ) );
506
        $tax_rate = !empty( $item['vat_rate'] ) ? $item['vat_rate'] : ( $item['tax'] / $item['subtotal'] ) * 100;
507
        $tax_rate = $tax_rate > 0 ? (float)wpinv_round_amount( $tax_rate, 4 ) : '';
508
        $tax_rate = $tax_rate != '' ? ' <small class="tax-rate normal small">(' . $tax_rate . '%)</small>' : '';
509
    }
510
    
511
    $tax        = $tax . $tax_rate;
512
    
513
    if ( $tax === '' ) {
514
        $tax = 0; // Zero tax
515
    }
516
517
    return apply_filters( 'wpinv_cart_item_tax_label', $tax, $item );
518
}
519
520
function wpinv_get_cart_item_price( $item_id = 0, $cart_item = array(), $options = array(), $remove_tax_from_inclusive = false ) {
521
    $price = 0;
522
    
523
    // Set custom price
524
    if ( isset( $cart_item['custom_price'] ) && $cart_item['custom_price'] !== '' ) {
525
        $price = $cart_item['custom_price'];
526
    } else {
527
        $variable_prices = wpinv_has_variable_prices( $item_id );
528
529
        if ( $variable_prices ) {
0 ignored issues
show
introduced by
The condition $variable_prices is always false.
Loading history...
530
            $prices = wpinv_get_variable_prices( $item_id );
0 ignored issues
show
Bug introduced by
The function wpinv_get_variable_prices was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

530
            $prices = /** @scrutinizer ignore-call */ wpinv_get_variable_prices( $item_id );
Loading history...
531
532
            if ( $prices ) {
533
                if( ! empty( $options ) ) {
534
                    $price = isset( $prices[ $options['price_id'] ] ) ? $prices[ $options['price_id'] ]['amount'] : false;
535
                } else {
536
                    $price = false;
537
                }
538
            }
539
        }
540
541
        if( ! $variable_prices || false === $price ) {
0 ignored issues
show
introduced by
The condition $variable_prices is always false.
Loading history...
542
            if($cart_item['item_price'] > 0){
543
                $price = $cart_item['item_price'];
544
            } else {
545
                // Get the standard Item price if not using variable prices
546
                $price = wpinv_get_item_price( $item_id );
547
            }
548
        }
549
    }
550
551
    if ( $remove_tax_from_inclusive && wpinv_prices_include_tax() ) {
552
        $price -= wpinv_get_cart_item_tax( $item_id, $price, $options );
553
    }
554
555
    return apply_filters( 'wpinv_cart_item_price', $price, $item_id, $cart_item, $options, $remove_tax_from_inclusive );
556
}
557
558
function wpinv_get_cart_item_price_id( $item = array() ) {
559
    if( isset( $item['item_number'] ) ) {
560
        $price_id = isset( $item['item_number']['options']['price_id'] ) ? $item['item_number']['options']['price_id'] : null;
561
    } else {
562
        $price_id = isset( $item['options']['price_id'] ) ? $item['options']['price_id'] : null;
563
    }
564
    return $price_id;
565
}
566
567
function wpinv_get_cart_item_price_name( $item = array() ) {
568
    $price_id = (int)wpinv_get_cart_item_price_id( $item );
569
    $prices   = wpinv_get_variable_prices( $item['id'] );
0 ignored issues
show
Bug introduced by
The function wpinv_get_variable_prices was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

569
    $prices   = /** @scrutinizer ignore-call */ wpinv_get_variable_prices( $item['id'] );
Loading history...
570
    $name     = ! empty( $prices[ $price_id ] ) ? $prices[ $price_id ]['name'] : '';
571
    return apply_filters( 'wpinv_get_cart_item_price_name', $name, $item['id'], $price_id, $item );
572
}
573
574
function wpinv_get_cart_item_name( $item = array() ) {
575
    $item_title = !empty( $item['name'] ) ? $item['name'] : get_the_title( $item['id'] );
576
577
    if ( empty( $item_title ) ) {
578
        $item_title = $item['id'];
579
    }
580
581
    /*
582
    if ( wpinv_has_variable_prices( $item['id'] ) && false !== wpinv_get_cart_item_price_id( $item ) ) {
583
        $item_title .= ' - ' . wpinv_get_cart_item_price_name( $item );
584
    }
585
    */
586
587
    return apply_filters( 'wpinv_get_cart_item_name', $item_title, $item['id'], $item );
588
}
589
590
function wpinv_has_variable_prices( $item_id = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $item_id 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

590
function wpinv_has_variable_prices( /** @scrutinizer ignore-unused */ $item_id = 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...
591
    return false;
592
}
593
594
function wpinv_get_item_position_in_cart( $item_id = 0, $options = array() ) {
595
    $cart_items = wpinv_get_cart_contents();
596
597
    if ( !is_array( $cart_items ) ) {
598
        return false; // Empty cart
599
    } else {
600
        foreach ( $cart_items as $position => $item ) {
601
            if ( $item['id'] == $item_id ) {
602
                if ( isset( $options['price_id'] ) && isset( $item['options']['price_id'] ) ) {
603
                    if ( (int) $options['price_id'] == (int) $item['options']['price_id'] ) {
604
                        return $position;
605
                    }
606
                } else {
607
                    return $position;
608
                }
609
            }
610
        }
611
    }
612
613
    return false; // Not found
614
}
615
616
function wpinv_get_cart_item_quantity( $item ) {
617
    if ( wpinv_item_quantities_enabled() ) {
618
        $quantity = !empty( $item['quantity'] ) && (int)$item['quantity'] > 0 ? absint( $item['quantity'] ) : 1;
619
    } else {
620
        $quantity = 1;
621
    }
622
    
623
    if ( $quantity < 1 ) {
624
        $quantity = 1;
625
    }
626
    
627
    return apply_filters( 'wpinv_get_cart_item_quantity', $quantity, $item );
628
}
629
630
function wpinv_get_item_suffix( $item, $html = true ) {
631
    if ( empty( $item ) ) {
632
        return NULL;
633
    }
634
    
635
    if ( is_int( $item ) ) {
636
        $item = new WPInv_Item( $item );
637
    }
638
    
639
    if ( !( is_object( $item ) && is_a( $item, 'WPInv_Item' ) ) ) {
640
        return NULL;
641
    }
642
    
643
    $suffix = $item->is_recurring() ? ' <span class="wpi-suffix">' . __( '(r)', 'invoicing' ) . '</span>' : '';
644
    
645
    if ( !$html && $suffix ) {
646
        $suffix = strip_tags( $suffix );
647
    }
648
    
649
    return apply_filters( 'wpinv_get_item_suffix', $suffix, $item, $html );
650
}
651
652
function wpinv_remove_item( $item = 0, $force_delete = false ) {
653
    if ( empty( $item ) ) {
654
        return NULL;
655
    }
656
    
657
    if ( is_int( $item ) ) {
658
        $item = new WPInv_Item( $item );
659
    }
660
    
661
    if ( !( is_object( $item ) && is_a( $item, 'WPInv_Item' ) ) ) {
662
        return NULL;
663
    }
664
    
665
    do_action( 'wpinv_pre_delete_item', $item );
666
667
    wp_delete_post( $item->ID, $force_delete );
668
669
    do_action( 'wpinv_post_delete_item', $item );
670
}
671
672
function wpinv_can_delete_item( $post_id ) {
673
    $return = wpinv_current_user_can_manage_invoicing() ? true : false;
674
    
675
    if ( $return && wpinv_item_in_use( $post_id ) ) {
676
        $return = false; // Don't delete item already use in invoices.
677
    }
678
    
679
    return apply_filters( 'wpinv_can_delete_item', $return, $post_id );
680
}
681
682
function wpinv_admin_action_delete() {
683
    $screen = get_current_screen();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $screen is correct as get_current_screen() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
684
    
685
    if ( !empty( $screen->post_type ) && $screen->post_type == 'wpi_item' && !empty( $_REQUEST['post'] ) && is_array( $_REQUEST['post'] ) ) {
686
        $post_ids = array();
687
        
688
        foreach ( $_REQUEST['post'] as $post_id ) {
689
            if ( !wpinv_can_delete_item( $post_id ) ) {
690
                continue;
691
            }
692
            
693
            $post_ids[] = $post_id;
694
        }
695
        
696
        $_REQUEST['post'] = $post_ids;
697
    }
698
}
699
add_action( 'admin_action_trash', 'wpinv_admin_action_delete', -10 );
700
add_action( 'admin_action_delete', 'wpinv_admin_action_delete', -10 );
701
702
function wpinv_check_delete_item( $check, $post, $force_delete ) {
703
    if ( $post->post_type == 'wpi_item' ) {
704
        if ( $force_delete && !wpinv_can_delete_item( $post->ID ) ) {
705
            return true;
706
        }
707
    }
708
    
709
    return $check;
710
}
711
add_filter( 'pre_delete_post', 'wpinv_check_delete_item', 10, 3 );
712
713
function wpinv_item_in_use( $item_id ) {
714
    global $wpdb, $wpi_items_in_use;
715
    
716
    if ( !$item_id > 0 ) {
717
        return false;
718
    }
719
    
720
    if ( !empty( $wpi_items_in_use ) ) {
721
        if ( isset( $wpi_items_in_use[$item_id] ) ) {
722
            return $wpi_items_in_use[$item_id];
723
        }
724
    } else {
725
        $wpi_items_in_use = array();
726
    }
727
    
728
    $statuses   = array_keys( wpinv_get_invoice_statuses( true, true ) );
729
    
730
    $query  = "SELECT p.ID FROM " . $wpdb->posts . " AS p INNER JOIN " . $wpdb->postmeta . " AS pm ON p.ID = pm.post_id WHERE p.post_type = 'wpi_invoice' AND p.post_status IN( '" . implode( "','", $statuses ) . "' ) AND pm.meta_key = '_wpinv_item_ids' AND FIND_IN_SET( '" . (int)$item_id . "', pm.meta_value )";
731
    $in_use = $wpdb->get_var( $query ) > 0 ? true : false;
732
    
733
    $wpi_items_in_use[$item_id] = $in_use;
734
    
735
    return $in_use;
736
}
737
738
function wpinv_create_item( $args = array(), $wp_error = false, $force_update = false ) {
739
    // Set some defaults
740
    $defaults = array(
741
        'type'                 => 'custom',                                                // Optional. Item type. Default 'custom'.
742
        'title'                => '',                                                      // Required. Item title.
743
        'custom_id'            => 0,                                                       // Optional. Any integer or non numeric id. Must be unique within item type.
744
        'price'                => '0.00',                                                  // Optional. Item price. Default '0.00'.
745
        'status'               => 'pending',                                               // Optional. pending, publish
746
        'custom_name'          => '',                                                      // Optional. Plural sub title for item.
747
        'custom_singular_name' => '',                                                      // Optional. Singular sub title for item.
748
        'vat_rule'             => 'digital',                                               // Optional. digital => Digital item, physical => Physical item
749
        'editable'             => true,                                                    // Optional. Item editable from Items list page? Default true.
750
        'excerpt'              => '',                                                      // Optional. Item short description
751
        /* Recurring item fields */
752
        'is_recurring'         => 0,                                                       // Optional. 1 => Allow recurring or 0 => Don't allow recurring
753
        'recurring_period'     => 'M',                                                     // Optional. D => Daily, W => Weekly, M => Monthly, Y => Yearly
754
        'recurring_interval'   => 0,                                                       // Optional. Integer value between 1 - 90.
755
        'recurring_limit'      => 0,                                                       // Optional. Any integer number. 0 for recurring forever until cancelled.
756
        'free_trial'           => 0,                                                       // Optional. 1 => Allow free trial or 0 => Don't free trial
757
        'trial_period'         => 'M',                                                     // Optional. D => Daily, W => Weekly, M => Monthly, Y => Yearly
758
        'trial_interval'       => 0,                                                       // Optional. Any integer number.
759
        'minimum_price'        => '0.00',                                                  // Optional. Minimum allowed prices for items with dynamic pricing.
760
        'dynamic_pricing'      => 0,                                                       // Optional. Whether or not the item supports dynamic prices.
761
    );
762
763
    $data = wp_parse_args( $args, $defaults );
764
765
    if ( empty( $data['type'] ) ) {
766
        $data['type'] = 'custom';
767
    }
768
769
    if ( !empty( $data['custom_id'] ) ) {
770
        $item = wpinv_get_item_by( 'custom_id', $data['custom_id'], $data['type'] );
771
    } else {
772
        $item = NULL;
773
    }
774
775
    if ( !empty( $item ) ) {
776
        if ( $force_update ) {
777
            if ( empty( $args['ID'] ) ) {
778
                $args['ID'] = $item->ID;
779
            }
780
            return wpinv_update_item( $args, $wp_error );
781
        }
782
783
        return $item;
784
    }
785
786
    $meta                           = array();
787
    $meta['type']                   = $data['type'];
788
    $meta['custom_id']              = $data['custom_id'];
789
    $meta['custom_singular_name']   = $data['custom_singular_name'];
790
    $meta['custom_name']            = $data['custom_name'];
791
    $meta['price']                  = wpinv_round_amount( $data['price'] );
792
    $meta['editable']               = (int)$data['editable'];
793
    $meta['vat_rule']               = $data['vat_rule'];
794
    $meta['vat_class']              = '_standard';
795
    $meta['dynamic_pricing']        = (int) $data['dynamic_pricing'];
796
    $meta['minimum_price']          = wpinv_round_amount( $data['minimum_price'] );
797
    
798
    if ( !empty( $data['is_recurring'] ) ) {
799
        $meta['is_recurring']       = $data['is_recurring'];
800
        $meta['recurring_period']   = $data['recurring_period'];
801
        $meta['recurring_interval'] = absint( $data['recurring_interval'] );
802
        $meta['recurring_limit']    = absint( $data['recurring_limit'] );
803
        $meta['free_trial']         = $data['free_trial'];
804
        $meta['trial_period']       = $data['trial_period'];
805
        $meta['trial_interval']     = absint( $data['trial_interval'] );
806
    } else {
807
        $meta['is_recurring']       = 0;
808
        $meta['recurring_period']   = '';
809
        $meta['recurring_interval'] = '';
810
        $meta['recurring_limit']    = '';
811
        $meta['free_trial']         = 0;
812
        $meta['trial_period']       = '';
813
        $meta['trial_interval']     = '';
814
    }
815
    
816
    $post_data  = array( 
817
        'post_title'    => $data['title'],
818
        'post_excerpt'  => $data['excerpt'],
819
        'post_status'   => $data['status'],
820
        'meta'          => $meta
821
    );
822
823
    $item = new WPInv_Item();
824
    $return = $item->create( $post_data, $wp_error );
825
826
    if ( $return && !empty( $item ) && !is_wp_error( $return ) ) {
827
        return $item;
828
    }
829
830
    if ( $wp_error && is_wp_error( $return ) ) {
831
        return $return;
832
    }
833
    return 0;
834
}
835
836
function wpinv_update_item( $args = array(), $wp_error = false ) {
837
    $item = !empty( $args['ID'] ) ? new WPInv_Item( $args['ID'] ) : NULL;
838
839
    if ( empty( $item ) || !( !empty( $item->post_type ) && $item->post_type == 'wpi_item' ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Item. Since you implemented __get, consider adding a @property annotation.
Loading history...
840
        if ( $wp_error ) {
841
            return new WP_Error( 'wpinv_invalid_item', __( 'Invalid item.', 'invoicing' ) );
842
        }
843
        return 0;
844
    }
845
    
846
    if ( !empty( $args['custom_id'] ) ) {
847
        $item_exists = wpinv_get_item_by( 'custom_id', $args['custom_id'], ( !empty( $args['type'] ) ? $args['type'] : $item->type ) );
0 ignored issues
show
Bug Best Practice introduced by
The property $type is declared private in WPInv_Item. Since you implement __get, consider adding a @property or @property-read.
Loading history...
848
        
849
        if ( !empty( $item_exists ) && $item_exists->ID != $args['ID'] ) {
850
            if ( $wp_error ) {
851
                return new WP_Error( 'wpinv_invalid_custom_id', __( 'Item with custom id already exists.', 'invoicing' ) );
852
            }
853
            return 0;
854
        }
855
    }
856
857
    $meta_fields = array( 
858
        'type', 
859
        'custom_id', 
860
        'custom_singular_name', 
861
        'custom_name', 
862
        'price', 
863
        'editable', 
864
        'vat_rule', 
865
        'vat_class', 
866
        'is_recurring', 
867
        'recurring_period', 
868
        'recurring_interval', 
869
        'recurring_limit', 
870
        'free_trial', 
871
        'trial_period', 
872
        'trial_interval', 
873
        'minimum_price', 
874
        'dynamic_pricing'
875
    );
876
877
    $post_data = array();
878
    if ( isset( $args['title'] ) ) { 
879
        $post_data['post_title'] = $args['title'];
880
    }
881
    if ( isset( $args['excerpt'] ) ) { 
882
        $post_data['post_excerpt'] = $args['excerpt'];
883
    }
884
    if ( isset( $args['status'] ) ) { 
885
        $post_data['post_status'] = $args['status'];
886
    }
887
    
888
    foreach ( $meta_fields as $meta_field ) {
889
        if ( isset( $args[ $meta_field ] ) ) { 
890
            $value = $args[ $meta_field ];
891
892
            switch ( $meta_field ) {
893
                case 'price':
894
                case 'minimum_price':
895
                    $value = wpinv_round_amount( $value );
896
                break;
897
                case 'recurring_interval':
898
                case 'recurring_limit':
899
                case 'trial_interval':
900
                    $value = absint( $value );
901
                break;
902
				case 'editable':
903
                    $value = (int) $value;
904
                break;
905
            }
906
907
            $post_data['meta'][ $meta_field ] = $value;
908
        };
909
    }
910
911
    if ( empty( $post_data ) ) {
912
        if ( $wp_error ) {
913
            return new WP_Error( 'wpinv_invalid_item_data', __( 'Invalid item data.', 'invoicing' ) );
914
        }
915
        return 0;
916
    }
917
    $post_data['ID'] = $args['ID'];
918
919
    $return = $item->update( $post_data, $wp_error );
920
921
    if ( $return && !empty( $item ) && !is_wp_error( $return ) ) {
922
        return $item;
923
    }
924
925
    if ( $wp_error && is_wp_error( $return ) ) {
926
        return $return;
927
    }
928
    return 0;
929
}