Passed
Pull Request — master (#47)
by Kiran
04:17
created

WPInv_API   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 179
Duplicated Lines 7.82 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 14
loc 179
rs 8.2769
c 0
b 0
f 0
wmc 41
lcom 0
cbo 1

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
B insert_invoice() 0 30 5
A send_status() 0 3 1
C set_billing_details() 14 47 9
A set_discount() 0 15 3
C set_items() 0 65 17
B set_invoice_meta() 0 8 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WPInv_API often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WPInv_API, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
 
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
class WPInv_API {
15
    protected $post_type = 'wpi_invoice';
16
    
17
    public function __construct( $params = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $params 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...
18
    }
19
    public function insert_invoice( $data ) {
20
        global $wpdb;
21
        //wpinv_transaction_query( 'start' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
22
23
        try {
24
            if ( empty( $data['invoice'] ) ) {
25
                throw new WPInv_API_Exception( 'wpinv_api_missing_invoice_data', sprintf( __( 'No %1$s data specified to create %1$s', 'invoicing' ), 'invoice' ), 400 );
26
            }
27
28
            $data = apply_filters( 'wpinv_api_create_invoice_data', $data['invoice'], $this );
29
30
            $invoice = wpinv_insert_invoice( $data, true );
31
            if ( empty( $invoice->ID ) || is_wp_error( $invoice ) ) {
32
                throw new WPInv_API_Exception( 'wpinv_api_cannot_create_invoice', sprintf( __( 'Cannot create invoice: %s', 'invoicing' ), implode( ', ', $invoice->get_error_messages() ) ), 400 );
33
            }
34
35
            // HTTP 201 Created
36
            $this->send_status( 201 );
37
38
            do_action( 'wpinv_api_create_invoice', $invoice->ID, $data, $this );
39
40
            //wpinv_transaction_query( 'commit' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
41
42
            return wpinv_get_invoice( $invoice->ID );
43
        } catch ( WPInv_API_Exception $e ) {
44
            //wpinv_transaction_query( 'rollback' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
45
46
            return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
47
        }
48
    }
49
    
50
    public function send_status( $code ) {
51
        status_header( $code );
52
    }
53
    
54
    protected function set_billing_details( $invoice, $data ) {
55
        $address_fields = array(
56
            'user_id',
57
            'first_name',
58
            'last_name',
59
            'company',
60
            'vat_number',
61
            'email',
62
            'phone',
63
            'address',
64
            'city',
65
            'state',
66
            'country',
67
            'zip',
68
        );
69
70
        $billing_details = array();
0 ignored issues
show
Unused Code introduced by
$billing_details is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
71
        $user_id = $invoice->get_user_id();
72
        
73
        foreach ( $address_fields as $field ) {
74
            if ( isset( $data['billing_details'][ $field ] ) ) {
75
                $value = sanitize_text_field( $data['billing_details'][ $field ] );
76
                
77 View Code Duplication
                if ( $field == 'country' && empty( $value ) ) {
78
                    if ( !empty( $invoice->country ) ) {
79
                        $value = $invoice->country;
80
                    } else {
81
                        $value = wpinv_default_billing_country( '', $user_id );
82
                    }
83
                }
84
                
85 View Code Duplication
                if ( $field == 'state' && empty( $value ) ) {
86
                    if ( !empty( $invoice->state ) ) {
87
                        $value = $invoice->state;
88
                    } else {
89
                        $value = wpinv_get_default_state();
90
                    }
91
                }
92
                
93
                $invoice->set( $field, $value );
94
                
95
                update_post_meta( $invoice->ID, '_wpinv_' . $field, $value );
96
            }
97
        }
98
        
99
        return $invoice;
100
    }
101
    
102
    protected function set_discount( $invoice, $data ) {
103
        if ( isset( $data['discount'] ) ) {
104
            $invoice->set( 'discount', wpinv_round_amount( $data['discount'] ) );
105
            
106
            update_post_meta( $invoice->ID, '_wpinv_discount', wpinv_round_amount( $data['discount'] ) );
107
            
108
            if ( isset( $data['discount_code'] ) ) {
109
                $invoice->set( 'discount_code', $data['discount_code'] );
110
                
111
                update_post_meta( $invoice->ID, '_wpinv_discount_code', $data['discount_code'] );
112
            }
113
        }
114
        
115
        return $invoice;
116
    }
117
    
118
    protected function set_items( $invoice, $data ) {
119
        if ( !empty( $data['items'] ) && is_array( $data['items'] ) ) {
120
            $items_array = array();
121
           
122
            if ( !empty( $invoice->country ) ) {
123
                $country = $invoice->country;
124
            } else if ( !empty( $data['billing_details']['country'] ) ) {
125
                $country = $data['billing_details']['country'];
126
            } else {
127
                $country = wpinv_default_billing_country( '', $invoice->get_user_id() );
128
            }
129
            
130
            if ( !empty( $invoice->state ) ) {
131
                $state = $invoice->state;
132
            } else if ( !empty( $data['billing_details']['state'] ) ) {
133
                $state = $data['billing_details']['state'];
134
            } else {
135
                $state = wpinv_get_default_state();
136
            }
137
            
138
            $_POST['country']   = $country;
139
            $_POST['state']     = $state;
140
            
141
            $rate = wpinv_get_tax_rate( $country, $state, 'global' );
0 ignored issues
show
Unused Code introduced by
$rate is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
142
            
143
            $total_tax = 0;
144
            foreach ( $data['items'] as $item ) {
145
                $id                 = isset( $item['id'] ) ? sanitize_text_field( $item['id'] ) : '';
146
                $title              = isset( $item['title'] ) ? sanitize_text_field( $item['title'] ) : '';
147
                $desc               = isset( $item['description'] ) ? sanitize_text_field( $item['description'] ) : '';
148
                $amount             = isset( $item['amount'] ) ? wpinv_round_amount( $item['amount'] ) : 0;
149
                
150
                if ( !empty( $item['vat_rates_class'] ) ) {
151
                    $vat_rates_class = $item['vat_rates_class'];
152
                } else {
153
                    $vat_rates_class = '_standard';
154
                }
155
                $vat_rate = wpinv_get_tax_rate( $country, $state, $id );
156
                
157
                $tax = $amount > 0 ? ( $amount * 0.01 * (float)$vat_rate ) : 0;
158
                $total_tax += $tax;
159
                
160
                $items_array[] = array(
161
                    'id'                => $id,
162
                    'title'             => esc_html( $title ),
163
                    'description'       => esc_html( $desc ),
164
                    'amount'            => $amount > 0 ? wpinv_round_amount( $amount ) : 0,
165
                    'subtotal'          => $amount > 0 ? wpinv_round_amount( $amount ) : 0,
166
                    'vat_rates_class'   => $vat_rates_class,
167
                    'vat_rate'          => $vat_rate,
168
                    'tax'               => $tax > 0 ? wpinv_round_amount( $tax ) : 0,
169
                );
170
            }
171
172
            update_post_meta( $invoice->ID, '_wpinv_tax', wpinv_round_amount( $total_tax ) );
173
            $invoice->set( 'tax', wpinv_round_amount( $total_tax ) );
174
            
175
            $items_array = apply_filters( 'wpinv_save_invoice_items', $items_array, $data['items'], $invoice );
176
            
177
            $invoice->set( 'items', $items_array );
178
            update_post_meta( $invoice->ID, '_wpinv_items', $items_array );
179
        }
180
        
181
        return $invoice;
182
    }
183
    
184
    protected function set_invoice_meta( $invoice_id, $invoice_meta ) {
185
        foreach ( $invoice_meta as $meta_key => $meta_value ) {
186
187
            if ( is_string( $meta_key) && ! is_protected_meta( $meta_key ) && is_scalar( $meta_value ) ) {
188
                update_post_meta( $invoice_id, $meta_key, $meta_value );
189
            }
190
        }
191
    }
192
}
193
194
195
class WPInv_API_Exception extends Exception {
196
    protected $error_code;
197
198
    public function __construct( $error_code, $error_message, $http_status_code ) {
199
        $this->error_code = $error_code;
200
        parent::__construct( $error_message, $http_status_code );
201
    }
202
203
    public function getErrorCode() {
204
        return $this->error_code;
205
    }
206
}