Passed
Push — master ( 4d9a77...ff2f8f )
by Brian
05:03
created

wpinv_vat_rates_callback()   C

Complexity

Conditions 15
Paths 12

Size

Total Lines 89
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 60
nc 12
nop 1
dl 0
loc 89
rs 5.9166
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getpaid_filter_vat_class() 0 2 2
A getpaid_get_tax_rules() 0 7 1
A getpaid_get_tax_classes() 0 8 1
A getpaid_get_tax_rule_label() 0 9 2
A getpaid_get_tax_class_label() 0 9 2

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
/**
3
 * Contains the tax functions.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Returns an array of eu states.
11
 * 
12
 * @return array
13
 */
14
function getpaid_get_eu_states() {
15
    return wpinv_get_data( 'eu-states' );
16
}
17
18
/**
19
 * Checks if a given country is an EU state.
20
 * 
21
 * @return bool
22
 */
23
function getpaid_is_eu_state( $country ) {
24
    return ! empty( $country ) && in_array( strtoupper( $country ), getpaid_get_eu_states() ) ? true : false;
25
}
26
27
/**
28
 * Returns an array of gst states.
29
 * 
30
 * @return array
31
 */
32
function getpaid_get_gst_states() {
33
    return array( 'AU', 'NZ', 'CA', 'CN' );
34
}
35
36
/**
37
 * Checks if a given country is GST country.
38
 * 
39
 * @return bool
40
 */
41
function getpaid_is_gst_country( $country ) {
42
    return ! empty( $country ) && in_array( strtoupper( $country ), getpaid_get_gst_states() ) ? true : false;
43
}
44
45
/**
46
 * Checks whether or not taxes are enabled.
47
 *
48
 * @return bool
49
 */
50
function wpinv_use_taxes() {
51
52
    $ret = wpinv_get_option( 'enable_taxes', false );
53
    return (bool) apply_filters( 'wpinv_use_taxes', ! empty( $ret ) );
54
55
}
56
57
/**
58
 * Checks whether or not an invoice is taxable.
59
 *
60
 * @param WPInv_Invoice $invoice
61
 * @return bool
62
 */
63
function wpinv_is_invoice_taxable( $invoice ) {
64
    return $invoice->is_taxable();
65
}
66
67
/**
68
 * Checks whether or not a given country is taxable.
69
 *
70
 * @param string $country
71
 * @return bool
72
 */
73
function wpinv_is_country_taxable( $country ) {
74
    $is_eu     = getpaid_is_eu_state( $country );
75
    $is_exempt = $is_eu && $country == wpinv_is_base_country( $country ) && wpinv_same_country_exempt_vat();
76
77
    return (bool) apply_filters( 'wpinv_is_country_taxable', ! $is_exempt, $country ); 
78
79
}
80
81
/**
82
 * Checks whether or not an item is taxable.
83
 *
84
 * @param WPInv_Item|GetPaid_Form_Item $item
85
 * @return bool
86
 */
87
function wpinv_is_item_taxable( $item ) {
88
    return '_exempt' != $item->get_vat_rule();
89
}
90
91
/**
92
 * Checks whether or not taxes are calculated based on the store address.
93
 *
94
 * @return bool
95
 */
96
function wpinv_use_store_address_as_tax_base() {
97
    $use_base = wpinv_get_option( 'tax_base', 'billing' ) == 'base';
98
    return (bool) apply_filters( 'wpinv_use_store_address_as_tax_base', $use_base );
99
}
100
101
/**
102
 * Checks whether or not prices include tax.
103
 *
104
 * @return bool
105
 */
106
function wpinv_prices_include_tax() {
107
    $is_inclusive = wpinv_get_option( 'prices_include_tax', 'no' ) == 'yes';
108
    return (bool) apply_filters( 'wpinv_prices_include_tax', $is_inclusive );
109
}
110
111
/**
112
 * Checks whether we should round per rate or per subtotal
113
 *
114
 * @return bool
115
 */
116
function wpinv_round_tax_per_tax_rate() {
117
    $subtotal_rounding = wpinv_get_option( 'tax_subtotal_rounding', 1 );
118
    return (bool) apply_filters( 'wpinv_round_tax_per_tax_rate', empty( $subtotal_rounding ) );
119
}
120
121
/**
122
 * Checks whether we should display individual tax rates.
123
 *
124
 * @return bool
125
 */
126
function wpinv_display_individual_tax_rates() {
127
    $individual = wpinv_get_option( 'tax_display_totals', 'single' ) == 'individual';
128
    return (bool) apply_filters( 'wpinv_display_individual_tax_rates', $individual );
129
}
130
131
/**
132
 * Retrieves the default tax rate.
133
 *
134
 * @return float
135
 */
136
function wpinv_get_default_tax_rate() {
137
    $rate = wpinv_get_option( 'tax_rate', false );
138
    return (float) apply_filters( 'wpinv_get_default_tax_rate', floatval( $rate ) );
139
}
140
141
/**
142
 * Checks if we should exempt same country vat.
143
 *
144
 * @return bool
145
 */
146
function wpinv_same_country_exempt_vat() {
147
    return 'no' == wpinv_get_option( 'vat_same_country_rule' );
148
}
149
150
/**
151
 * Retrieves an array of all tax rates.
152
 *
153
 * @return array
154
 */
155
function wpinv_get_tax_rates() {
156
    return GetPaid_Tax::get_all_tax_rates();
157
}
158
159
/**
160
 * Retrieves an item's tax rates.
161
 *
162
 * @param WPInv_Item|GetPaid_Form_Item $item
163
 * @param string $country
164
 * @param string $state
165
 * @return array
166
 */
167
function getpaid_get_item_tax_rates( $item, $country = '', $state = '' ) {
168
169
    // Abort if the item is not taxable.
170
    if ( ! wpinv_is_item_taxable( $item ) ) {
171
        return array();
172
    }
173
174
    // Maybe use the store address.
175
    if ( wpinv_use_store_address_as_tax_base() ) {
176
        $country = wpinv_get_default_country();
177
        $state   = wpinv_get_default_state();
178
    }
179
180
    // Retrieve tax rates.
181
    $tax_rates = GetPaid_Tax::get_address_tax_rates( $country, $state );
182
183
    // Fallback to the default tax rates if non were found.
184
    if ( empty( $tax_rates ) ) {
185
        $tax_rates = GetPaid_Tax::get_default_tax_rates();
186
    }
187
188
    return apply_filters( 'getpaid_get_item_tax_rates', $tax_rates, $item, $country, $state );
189
}
190
191
/**
192
 * Filters an item's tax rate.
193
 *
194
 * @param WPInv_Item|GetPaid_Form_Item $item
195
 * @param array $rates
196
 * @return array
197
 */
198
function getpaid_filter_item_tax_rates( $item, $rates ) {
199
200
    $tax_class = $item->get_vat_class();
201
202
    foreach ( $rates as $i => $rate ) {
203
204
        if ( $tax_class == '_reduced' ) {
205
            $rates[ $i ]['rate'] = empty( $rate['reduced_rate'] ) ? 0 : $rate['reduced_rate'];
206
        }
207
208
        if ( $tax_class == '_exempt' ) {
209
            $rates[ $i ]['rate'] = 0;
210
        }
211
212
    }
213
214
    return apply_filters( 'getpaid_filter_item_tax_rates', $rates, $item );
215
}
216
217
/**
218
 * Retrieves an item's taxes.
219
 *
220
 * @param float $amount
221
 * @param array $rates
222
 * @return array
223
 */
224
function getpaid_calculate_item_taxes( $amount, $rates ) {
225
226
    $is_inclusive = wpinv_prices_include_tax();
227
    $taxes        = GetPaid_Tax::calc_tax( $amount, $rates, $is_inclusive );
228
229
    return apply_filters( 'getpaid_calculate_taxes', $taxes, $amount, $rates );
230
}
231
232
/**
233
 * Prepares an item's tax.
234
 *
235
 * @param WPInv_Item|GetPaid_Form_Item $item
236
 * @param string $tax_name
237
 * @param float $tax_amount
238
 * @param float $recurring_tax_amount
239
 * @return array
240
 */
241
function getpaid_prepare_item_tax( $item, $tax_name, $tax_amount, $recurring_tax_amount ) {
242
243
    $initial_tax   = $tax_amount;
244
	$recurring_tax = 0;
245
246
    if ( $item->is_recurring() ) {
247
		$recurring_tax = $recurring_tax_amount;
248
	}
249
250
	return array(
251
		'name'          => sanitize_text_field( $tax_name ),
252
		'initial_tax'   => $initial_tax,
253
		'recurring_tax' => $recurring_tax,
254
    );
255
256
}
257
258
/**
259
 * Sanitizes a VAT number.
260
 *
261
 * @param string $vat_number
262
 * @return string
263
 */
264
function wpinv_sanitize_vat_number( $vat_number ) {
265
    return str_replace( array(' ', '.', '-', '_', ',' ), '', strtoupper( trim( $vat_number ) ) );
266
}
267
268
/**
269
 * Validates a vat number via a REGEX.
270
 *
271
 * @param string $vat_number
272
 * @return bool
273
 */
274
function wpinv_regex_validate_vat_number( $vat_number ) {
275
276
    $country    = substr( $vat_number, 0, 2 );
277
    $vatin      = substr( $vat_number, 2 );
278
    $regexes    = wpinv_get_data( 'vat-number-regexes' );
279
280
    if ( isset( $regexes[ $country ] ) ) {
281
282
        $regex = $regexes[ $country ];
283
        $regex = '/^(?:' . $regex . ')$/';
284
        return 1 === preg_match( $regex, $vatin );
285
286
    }
287
288
    // Not an EU state, use filters to validate the number.
289
    return apply_filters( 'wpinv_regex_validate_vat_number', true, $vat_number );
290
}
291
292
/**
293
 * Validates a vat number via a VIES.
294
 *
295
 * @param string $vat_number
296
 * @return bool
297
 */
298
function wpinv_vies_validate_vat_number( $vat_number ) {
299
300
    $country    = substr( $vat_number, 0, 2 );
301
    $vatin      = substr( $vat_number, 2 );
302
303
    $url        = add_query_arg(
304
        array(
305
            'ms'  => urlencode( $country ),
306
            'iso' => urlencode( $country ),
307
            'vat' => urlencode( $vatin ),
308
        ),
309
        'http://ec.europa.eu/taxation_customs/vies/viesquer.do'
310
    );
311
312
    $response   = wp_remote_get( $url );
313
    $response   = wp_remote_retrieve_body( $response );
314
315
    // Fallback gracefully if the VIES website is down.
316
    if ( empty( $response ) ) {
317
        return true;
318
    }
319
320
    return 1 !== preg_match( '/invalid VAT number/i', $response );
321
322
}
323
324
/**
325
 * Validates a vat number.
326
 *
327
 * @param string $vat_number
328
 * @param string $country
329
 * @return bool
330
 */
331
function wpinv_validate_vat_number( $vat_number, $country ) {
332
333
    // Abort if we are not validating this.
334
    if ( ! wpinv_should_validate_vat_number() || empty( $vat_number ) ) {
335
        return true;
336
    }
337
338
    // In case the vat number does not have a country code...
339
    $vat_number = wpinv_sanitize_vat_number( $vat_number );
340
    $_country   = substr( $vat_number, 0, 2 );
341
    $_country   = $_country == wpinv_country_name( $_country );
342
343
    if ( $_country ) {
344
        $vat_number = strtoupper( $country ) . $vat_number;
345
    }
346
347
    return wpinv_regex_validate_vat_number( $vat_number ) && wpinv_vies_validate_vat_number( $vat_number );
348
}
349
350
/**
351
 * Checks whether or not we should validate vat numbers.
352
 *
353
 * @return bool
354
 */
355
function wpinv_should_validate_vat_number() {
356
    $validate = wpinv_get_option( 'validate_vat_number' );
357
	return ! empty( $validate );
358
}
359
360
function wpinv_sales_tax_for_year( $year = null ) {
361
    return wpinv_price( wpinv_format_amount( wpinv_get_sales_tax_for_year( $year ) ) );
0 ignored issues
show
Bug introduced by
wpinv_format_amount(wpin...es_tax_for_year($year)) of type string is incompatible with the type double expected by parameter $amount of wpinv_price(). ( Ignorable by Annotation )

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

361
    return wpinv_price( /** @scrutinizer ignore-type */ wpinv_format_amount( wpinv_get_sales_tax_for_year( $year ) ) );
Loading history...
362
}
363
364
function wpinv_get_sales_tax_for_year( $year = null ) {
365
    global $wpdb;
366
367
    // Start at zero
368
    $tax = 0;
369
370
    if ( ! empty( $year ) ) {
371
        $args = array(
372
            'post_type'      => 'wpi_invoice',
373
            'post_status'    => array( 'publish' ),
374
            'posts_per_page' => -1,
375
            'year'           => $year,
376
            'fields'         => 'ids'
377
        );
378
379
        $payments    = get_posts( $args );
380
        $payment_ids = implode( ',', $payments );
381
382
        if ( count( $payments ) > 0 ) {
383
            $sql = "SELECT SUM( meta_value ) FROM $wpdb->postmeta WHERE meta_key = '_wpinv_tax' AND post_id IN( $payment_ids )";
384
            $tax = $wpdb->get_var( $sql );
385
        }
386
387
    }
388
389
    return apply_filters( 'wpinv_get_sales_tax_for_year', $tax, $year );
390
}
391
392
function wpinv_is_cart_taxed() {
393
    return wpinv_use_taxes();
394
}
395
396
function wpinv_prices_show_tax_on_checkout() {
397
    return false; // TODO
398
    $ret = ( wpinv_get_option( 'checkout_include_tax', false ) == 'yes' && wpinv_use_taxes() );
0 ignored issues
show
Unused Code introduced by
$ret = wpinv_get_option(...s' && wpinv_use_taxes() is not 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...
399
400
    return apply_filters( 'wpinv_taxes_on_prices_on_checkout', $ret );
401
}
402
403
function wpinv_display_tax_rate() {
404
    $ret = wpinv_use_taxes() && wpinv_get_option( 'display_tax_rate', false );
405
406
    return apply_filters( 'wpinv_display_tax_rate', $ret );
407
}
408
409
function wpinv_cart_needs_tax_address_fields() {
410
    if( !wpinv_is_cart_taxed() )
411
        return false;
412
413
    return ! did_action( 'wpinv_after_cc_fields', 'wpinv_default_cc_address_fields' );
0 ignored issues
show
Unused Code introduced by
The call to did_action() has too many arguments starting with 'wpinv_default_cc_address_fields'. ( Ignorable by Annotation )

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

413
    return ! /** @scrutinizer ignore-call */ did_action( 'wpinv_after_cc_fields', 'wpinv_default_cc_address_fields' );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
414
}
415
416
function wpinv_item_is_tax_exclusive( $item_id = 0 ) {
417
    $ret = (bool)get_post_meta( $item_id, '_wpinv_tax_exclusive', false );
418
    return apply_filters( 'wpinv_is_tax_exclusive', $ret, $item_id );
419
}
420
421
function wpinv_currency_decimal_filter( $decimals = 2 ) {
422
    $currency = wpinv_get_currency();
423
424
    switch ( $currency ) {
425
        case 'RIAL' :
426
        case 'JPY' :
427
        case 'TWD' :
428
        case 'HUF' :
429
            $decimals = 0;
430
            break;
431
    }
432
433
    return apply_filters( 'wpinv_currency_decimal_count', $decimals, $currency );
434
}
435
436
function wpinv_tax_amount() {
437
    $output = 0.00;
438
    
439
    return apply_filters( 'wpinv_tax_amount', $output );
440
}
441
442
/**
443
 * Filters the VAT rules to ensure that each item has a VAT rule.
444
 * 
445
 * @param string|bool|null $vat_rule
446
 */
447
function getpaid_filter_vat_rule( $vat_rule ) {
448
449
    if ( empty( $vat_rule ) ) {        
450
        return 'digital';
451
    }
452
453
    return $vat_rule;
454
}
455
add_filter( 'wpinv_get_item_vat_rule', 'getpaid_filter_vat_rule' );
456
457
/**
458
 * Filters the VAT class to ensure that each item has a VAT class.
459
 * 
460
 * @param string|bool|null $vat_rule
461
 */
462
function getpaid_filter_vat_class( $vat_class ) {
463
    return empty( $vat_class ) ? '_standard' : $vat_class;
464
}
465
add_filter( 'wpinv_get_item_vat_class', 'getpaid_filter_vat_class' );
466
467
/**
468
 * Returns a list of all tax classes.
469
 * 
470
 * @return array
471
 */
472
function getpaid_get_tax_classes() {
473
474
    return apply_filters(
475
        'getpaid_tax_classes',
476
        array(
477
            '_standard' => __( 'Standard Tax Rate', 'invoicing' ),
478
            '_reduced'  => __( 'Reduced Tax Rate', 'invoicing' ),
479
            '_exempt'   => __( 'Tax Exempt', 'invoicing' ),
480
        )
481
    );
482
483
}
484
485
/**
486
 * Returns a list of all tax rules.
487
 * 
488
 * @return array
489
 */
490
function getpaid_get_tax_rules() {
491
492
    return apply_filters(
493
        'getpaid_tax_rules',
494
        array(
495
            'physical' => __( 'Physical Item', 'invoicing' ),
496
            'digital'  => __( 'Digital Item', 'invoicing' ),
497
        )
498
    );
499
500
}
501
502
/**
503
 * Returns the label of a tax class.
504
 * 
505
 * @param string $tax_class
506
 * @return string
507
 */
508
function getpaid_get_tax_class_label( $tax_class ) {
509
510
    $classes = getpaid_get_tax_classes();
511
512
    if ( isset( $classes[ $tax_class ] ) ) {
513
        return sanitize_text_field( $classes[ $tax_class ] );
514
    }
515
516
    return sanitize_text_field( $tax_class );
517
518
}
519
520
/**
521
 * Returns the label of a tax rule.
522
 * 
523
 * @param string $tax_rule
524
 * @return string
525
 */
526
function getpaid_get_tax_rule_label( $tax_rule ) {
527
528
    $rules = getpaid_get_tax_rules();
529
530
    if ( isset( $rules[ $tax_rule ] ) ) {
531
        return sanitize_text_field( $rules[ $tax_rule ] );
532
    }
533
534
    return sanitize_text_field( $tax_rule );
535
536
}
537