Passed
Pull Request — master (#57)
by Kiran
04:16
created

WPInv_Item::is_editable()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 4
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
// Exit if accessed directly
3
if ( ! defined( 'ABSPATH' ) ) exit;
4
5
class WPInv_Item {
6
    public $ID = 0;
7
    private $price;
8
    private $vat_rule;
9
    private $vat_class;
10
    private $type;
11
12
    public $post_author = 0;
13
    public $post_date = '0000-00-00 00:00:00';
14
    public $post_date_gmt = '0000-00-00 00:00:00';
15
    public $post_content = '';
16
    public $post_title = '';
17
    public $post_excerpt = '';
18
    public $post_status = 'publish';
19
    public $comment_status = 'open';
20
    public $ping_status = 'open';
21
    public $post_password = '';
22
    public $post_name = '';
23
    public $to_ping = '';
24
    public $pinged = '';
25
    public $post_modified = '0000-00-00 00:00:00';
26
    public $post_modified_gmt = '0000-00-00 00:00:00';
27
    public $post_content_filtered = '';
28
    public $post_parent = 0;
29
    public $guid = '';
30
    public $menu_order = 0;
31
    public $post_mime_type = '';
32
    public $comment_count = 0;
33
    public $filter;
34
35
36
    public function __construct( $_id = false, $_args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_args is not used and could be removed.

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

Loading history...
37
        $item = WP_Post::get_instance( $_id );
38
        return $this->setup_item( $item );
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
39
    }
40
41
    private function setup_item( $item ) {
42
        if( ! is_object( $item ) ) {
43
            return false;
44
        }
45
46
        if( ! is_a( $item, 'WP_Post' ) ) {
47
            return false;
48
        }
49
50
        if( 'wpi_item' !== $item->post_type ) {
51
            return false;
52
        }
53
54
        foreach ( $item as $key => $value ) {
55
            switch ( $key ) {
56
                default:
0 ignored issues
show
Unused Code introduced by
default: $this->{$key} = $value; break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
57
                    $this->$key = $value;
58
                    break;
59
            }
60
        }
61
62
        return true;
63
    }
64
65
    public function __get( $key ) {
66
        if ( method_exists( $this, 'get_' . $key ) ) {
67
            return call_user_func( array( $this, 'get_' . $key ) );
68
        } else {
69
            return new WP_Error( 'wpinv-item-invalid-property', sprintf( __( 'Can\'t get property %s', 'invoicing' ), $key ) );
70
        }
71
    }
72
73
    public function create( $data = array(), $wp_error = false ) {
74
        if ( $this->ID != 0 ) {
75
            return false;
76
        }
77
78
        $defaults = array(
79
            'post_type'   => 'wpi_item',
80
            'post_status' => 'draft',
81
            'post_title'  => __( 'New Invoice Item', 'invoicing' )
82
        );
83
84
        $args = wp_parse_args( $data, $defaults );
85
86
        do_action( 'wpinv_item_pre_create', $args );
87
88
        $id = wp_insert_post( $args, $wp_error );
89
        if ($wp_error && is_wp_error($id)) {
90
            return $id;
91
        }
92
        if ( !$id ) {
93
            return false;
94
        }
95
        
96
        $item = WP_Post::get_instance( $id );
97
        
98 View Code Duplication
        if (!empty($item) && !empty($data['meta'])) {
99
            $this->ID = $item->ID;
100
            $this->save_metas($data['meta']);
101
        }
102
        
103
        // Set custom id if not set.
104
        if ( empty( $data['meta']['custom_id'] ) && !$this->get_custom_id() ) {
105
            $this->save_metas( array( 'custom_id' => $id ) );
106
        }
107
108
        do_action( 'wpinv_item_create', $id, $args );
109
110
        return $this->setup_item( $item );
111
    }
112
    
113
    public function update( $data = array(), $wp_error = false ) {
114
        if ( !$this->ID > 0 ) {
115
            return false;
116
        }
117
        
118
        $data['ID'] = $this->ID;
119
120
        do_action( 'wpinv_item_pre_update', $data );
121
        
122
        $id = wp_update_post( $data, $wp_error );
123
        if ($wp_error && is_wp_error($id)) {
124
            return $id;
125
        }
126
        
127
        if ( !$id ) {
128
            return false;
129
        }
130
131
        $item = WP_Post::get_instance( $id );
132 View Code Duplication
        if (!empty($item) && !empty($data['meta'])) {
133
            $this->ID = $item->ID;
134
            $this->save_metas($data['meta']);
0 ignored issues
show
Documentation introduced by
$data['meta'] is of type integer, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
135
        }
136
        
137
        // Set custom id if not set.
138
        if ( empty( $data['meta']['custom_id'] ) && !$this->get_custom_id() ) {
139
            $this->save_metas( array( 'custom_id' => $id ) );
140
        }
141
142
        do_action( 'wpinv_item_update', $id, $data );
143
144
        return $this->setup_item( $item );
145
    }
146
147
    public function get_ID() {
148
        return $this->ID;
149
    }
150
151
    public function get_name() {
152
        return get_the_title( $this->ID );
153
    }
154
    
155
    public function get_summary() {
156
        return get_the_excerpt( $this->ID );
157
    }
158
159
    public function get_price() {
160
        if ( ! isset( $this->price ) ) {
161
            $this->price = get_post_meta( $this->ID, '_wpinv_price', true );
162
            
163
            if ( $this->price ) {
164
                $this->price = wpinv_sanitize_amount( $this->price );
165
            } else {
166
                $this->price = 0;
167
            }
168
        }
169
        
170
        return apply_filters( 'wpinv_get_item_price', $this->price, $this->ID );
171
    }
172
    
173
    public function get_the_price() {
174
        $item_price = wpinv_price( wpinv_format_amount( $this->price ) );
175
        
176
        return apply_filters( 'wpinv_get_the_item_price', $item_price, $this->ID );
177
    }
178
    
179 View Code Duplication
    public function get_vat_rule() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
        global $wpinv_euvat;
181
        
182
        if( !isset( $this->vat_rule ) ) {
183
            $this->vat_rule = get_post_meta( $this->ID, '_wpinv_vat_rule', true );
184
185
            if ( empty( $this->vat_rule ) ) {        
186
                $this->vat_rule = $wpinv_euvat->allow_vat_rules() ? 'digital' : 'physical';
187
            }
188
        }
189
        
190
        return apply_filters( 'wpinv_get_item_vat_rule', $this->vat_rule, $this->ID );
191
    }
192
    
193 View Code Duplication
    public function get_vat_class() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
        if( !isset( $this->vat_class ) ) {
195
            $this->vat_class = get_post_meta( $this->ID, '_wpinv_vat_class', true );
196
197
            if ( empty( $this->vat_class ) ) {        
198
                $this->vat_class = '_standard';
199
            }
200
        }
201
        
202
        return apply_filters( 'wpinv_get_item_vat_class', $this->vat_class, $this->ID );
203
    }
204
205 View Code Duplication
    public function get_type() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
        if( ! isset( $this->type ) ) {
207
            $this->type = get_post_meta( $this->ID, '_wpinv_type', true );
208
209
            if ( empty( $this->type ) ) {
210
                $this->type = 'custom';
211
            }
212
        }
213
214
        return apply_filters( 'wpinv_get_item_type', $this->type, $this->ID );
215
    }
216
    
217
    public function get_custom_id() {
218
        $custom_id = get_post_meta( $this->ID, '_wpinv_custom_id', true );
219
220
        return apply_filters( 'wpinv_get_item_custom_id', $custom_id, $this->ID );
221
    }
222
    
223
    public function get_custom_name() {
224
        $custom_name = get_post_meta( $this->ID, '_wpinv_custom_name', true );
225
226
        return apply_filters( 'wpinv_get_item_custom_name', $custom_name, $this->ID );
227
    }
228
    
229
    public function get_custom_singular_name() {
230
        $custom_singular_name = get_post_meta( $this->ID, '_wpinv_custom_singular_name', true );
231
232
        return apply_filters( 'wpinv_get_item_custom_singular_name', $custom_singular_name, $this->ID );
233
    }
234
    
235
    public function is_recurring() {
236
        $is_recurring = get_post_meta( $this->ID, '_wpinv_is_recurring', true );
237
238
        return (bool)apply_filters( 'wpinv_is_recurring_item', $is_recurring, $this->ID );
239
240
    }
241
    
242 View Code Duplication
    public function get_recurring_period( $full = false ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
        $period = get_post_meta( $this->ID, '_wpinv_recurring_period', true );
244
        
245
        if ( !in_array( $period, array( 'D', 'W', 'M', 'Y' ) ) ) {
246
            $period = 'D';
247
        }
248
        
249
        if ( $full ) {
250
            switch( $period ) {
251
                case 'D':
252
                    $period = 'day';
253
                break;
254
                case 'W':
255
                    $period = 'week';
256
                break;
257
                case 'M':
258
                    $period = 'month';
259
                break;
260
                case 'Y':
261
                    $period = 'year';
262
                break;
263
            }
264
        }
265
266
        return apply_filters( 'wpinv_item_recurring_period', $period, $full, $this->ID );
267
268
    }
269
    
270
    public function get_recurring_interval() {
271
        $interval = (int)get_post_meta( $this->ID, '_wpinv_recurring_interval', true );
272
        
273
        if ( !$interval > 0 ) {
274
            $interval = 1;
275
        }
276
277
        return apply_filters( 'wpinv_item_recurring_interval', $interval, $this->ID );
278
279
    }
280
    
281
    public function get_recurring_limit() {
282
        $limit = get_post_meta( $this->ID, '_wpinv_recurring_limit', true );
283
284
        return (int)apply_filters( 'wpinv_item_recurring_limit', $limit, $this->ID );
285
286
    }
287
    
288
    public function has_free_trial() {
289
        $free_trial = get_post_meta( $this->ID, '_wpinv_free_trial', true );
290
        $free_trial = $this->is_recurring() && !empty( $free_trial ) ? true : false;
291
292
        return (bool)apply_filters( 'wpinv_item_has_free_trial', $free_trial, $this->ID );
293
294
    }
295
    
296 View Code Duplication
    public function get_trial_period( $full = false ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
        $period = get_post_meta( $this->ID, '_wpinv_trial_period', true );
298
        
299
        if ( !in_array( $period, array( 'D', 'W', 'M', 'Y' ) ) ) {
300
            $period = 'D';
301
        }
302
        
303
        if ( $full ) {
304
            switch( $period ) {
305
                case 'D':
306
                    $period = 'day';
307
                break;
308
                case 'W':
309
                    $period = 'week';
310
                break;
311
                case 'M':
312
                    $period = 'month';
313
                break;
314
                case 'Y':
315
                    $period = 'year';
316
                break;
317
            }
318
        }
319
320
        return apply_filters( 'wpinv_item_trial_period', $period, $full, $this->ID );
321
322
    }
323
    
324
    public function get_trial_interval() {
325
        $interval = absint( get_post_meta( $this->ID, '_wpinv_trial_interval', true ) );
326
        
327
        if ( !$interval > 0 ) {
328
            $interval = 1;
329
        }
330
331
        return apply_filters( 'wpinv_item_trial_interval', $interval, $this->ID );
332
333
    }
334
335
    public function is_free() {
336
        $is_free = false;
337
        
338
        $price = get_post_meta( $this->ID, '_wpinv_price', true );
339
340
        if ( (float)$price == 0 ) {
341
            $is_free = true;
342
        }
343
344
        return (bool) apply_filters( 'wpinv_is_free_item', $is_free, $this->ID );
345
346
    }
347
    
348
    public function is_package() {
349
        $is_package = $this->get_type() == 'package' ? true : false;
350
351
        return (bool) apply_filters( 'wpinv_is_package_item', $is_package, $this->ID );
352
353
    }
354
    
355
    public function is_editable() {
356
        $editable = get_post_meta( $this->ID, '_wpinv_editable', true );
357
358
        $is_editable = $editable === 0 || $editable === '0' ? false : true;
359
360
        return (bool) apply_filters( 'wpinv_item_is_editable', $is_editable, $this->ID );
361
    }
362
    
363
    public function save_metas( $metas = array() ) {
364
        if ( empty( $metas ) ) {
365
            return false;
366
        }
367
        
368
        foreach ( $metas as $meta_key => $meta_value ) {
369
            $meta_key = strpos($meta_key, '_wpinv_') !== 0 ? '_wpinv_' . $meta_key : $meta_key;
370
            
371
            $this->update_meta($meta_key, $meta_value);
372
        }
373
374
        return true;
375
    }
376
377
    public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
378
        if ( empty( $meta_key ) ) {
379
            return false;
380
        }
381
        
382
        $meta_value = apply_filters( 'wpinv_update_item_meta_' . $meta_key, $meta_value, $this->ID );
383
384
        return update_post_meta( $this->ID, $meta_key, $meta_value, $prev_value );
385
    }
386
    
387
    public function get_fees( $type = 'fee', $item_id = 0 ) {
388
        global $wpi_session;
389
        
390
        $fees = $wpi_session->get( 'wpi_cart_fees' );
391
392
        if ( ! wpinv_get_cart_contents() ) {
393
            // We can only get item type fees when the cart is empty
394
            $type = 'custom';
395
        }
396
397
        if ( ! empty( $fees ) && ! empty( $type ) && 'all' !== $type ) {
398
            foreach( $fees as $key => $fee ) {
399 View Code Duplication
                if( ! empty( $fee['type'] ) && $type != $fee['type'] ) {
400
                    unset( $fees[ $key ] );
401
                }
402
            }
403
        }
404
405
        if ( ! empty( $fees ) && ! empty( $item_id ) ) {
406
            // Remove fees that don't belong to the specified Item
407
            foreach ( $fees as $key => $fee ) {
408
                if ( (int) $item_id !== (int)$fee['custom_id'] ) {
409
                    unset( $fees[ $key ] );
410
                }
411
            }
412
        }
413
414
        if ( ! empty( $fees ) ) {
415
            // Remove fees that belong to a specific item but are not in the cart
416
            foreach( $fees as $key => $fee ) {
417
                if( empty( $fee['custom_id'] ) ) {
418
                    continue;
419
                }
420
421
                if ( !wpinv_item_in_cart( $fee['custom_id'] ) ) {
422
                    unset( $fees[ $key ] );
423
                }
424
            }
425
        }
426
427
        return ! empty( $fees ) ? $fees : array();
428
    }
429
    
430
    public function can_purchase() {
431
        $can_purchase = true;
432
433
        if ( !current_user_can( 'edit_post', $this->ID ) && $this->post_status != 'publish' ) {
434
            $can_purchase = false;
435
        }
436
437
        return (bool)apply_filters( 'wpinv_can_purchase_item', $can_purchase, $this );
438
    }
439
}
440