Passed
Push — master ( dea42c...d59b87 )
by Brian
11:32
created

WPInv_EUVat::add_class()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 1
rs 10
1
<?php
2
/**
3
 * Tax calculation and rate finding class.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
class WPInv_EUVat {
10
11
    /**
12
     * Retrieves an instance of this class.
13
     * 
14
     * @deprecated
15
     * @return WPInv_EUVat
16
     */
17
    public static function get_instance() {
18
        return new self();
19
    }
20
21
    /**
22
     * Inits tax hooks.
23
     */
24
    public function init() {
25
26
        // If this is an admin page...
27
        if ( is_admin() ) {
28
29
            // Register our scripts.
30
            add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
31
            add_action( 'wpinv_settings_sections_taxes', array( $this, 'section_vat_settings' ) );
32
            add_action( 'wpinv_settings_taxes', array( $this, 'vat_settings' ) );
33
            add_filter( 'wpinv_settings_taxes-vat_sanitize', array( $this, 'sanitize_vat_settings' ) );
34
        }
35
36
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_vat_scripts' ) );
37
        add_filter( 'wpinv_default_billing_country', array( $this, 'get_user_country' ), 10 );
38
        add_filter( 'wpinv_get_user_country', array( $this, 'set_user_country' ), 10 );
39
        add_action( 'wp_ajax_wpinv_vat_validate', array( $this, 'ajax_vat_validate' ) );
40
        add_action( 'wp_ajax_nopriv_wpinv_vat_validate', array( $this, 'ajax_vat_validate' ) );
41
42
    }
43
44
    public static function get_eu_states( $sort = true ) {
45
        $eu_states = array( 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GB', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE' );
46
        if ( $sort ) {
47
            $sort = sort( $eu_states );
48
        }
49
50
        return apply_filters( 'wpinv_get_eu_states', $eu_states, $sort );
51
    }
52
53
    public static function get_gst_countries( $sort = true ) {
54
        $gst_countries  = array( 'AU', 'NZ', 'CA', 'CN' );
55
56
        if ( $sort ) {
57
            $sort = sort( $gst_countries );
58
        }
59
60
        return apply_filters( 'wpinv_get_gst_countries', $gst_countries, $sort );
61
    }
62
63
    public static function is_eu_state( $country_code ) {
64
        $return = !empty( $country_code ) && in_array( strtoupper( $country_code ), self::get_eu_states() ) ? true : false;
65
66
        return apply_filters( 'wpinv_is_eu_state', $return, $country_code );
67
    }
68
69
    public static function is_gst_country( $country_code ) {
70
        $return = !empty( $country_code ) && in_array( strtoupper( $country_code ), self::get_gst_countries() ) ? true : false;
71
72
        return apply_filters( 'wpinv_is_gst_country', $return, $country_code );
73
    }
74
75
    public function enqueue_vat_scripts() {
76
        if( wpinv_use_taxes() && wpinv_get_option( 'apply_vat_rules' ) ) {
77
            $this->load_vat_scripts();
78
        }
79
    }
80
81
    public function load_vat_scripts(){
82
        $suffix     = '';//defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
83
84
        wp_register_script( 'wpinv-vat-validation-script', WPINV_PLUGIN_URL . 'assets/js/jsvat' . $suffix . '.js', array( 'jquery' ),  WPINV_VERSION );
85
        wp_register_script( 'wpinv-vat-script', WPINV_PLUGIN_URL . 'assets/js/euvat' . $suffix . '.js', array( 'jquery' ),  WPINV_VERSION );
86
87
        $vat_name   = $this->get_vat_name();
88
89
        $vars = array();
90
        $vars['UseTaxes'] = wpinv_use_taxes();
91
        $vars['EUStates'] = self::get_eu_states();
92
        $vars['NoRateSet'] = __( 'You have not set a rate. Do you want to continue?', 'invoicing' );
93
        $vars['EmptyCompany'] = __( 'Please enter your registered company name!', 'invoicing' );
94
        $vars['EmptyVAT'] = wp_sprintf( __( 'Please enter your %s number!', 'invoicing' ), $vat_name );
95
        $vars['TotalsRefreshed'] = wp_sprintf( __( 'The invoice totals will be refreshed to update the %s.', 'invoicing' ), $vat_name );
96
        $vars['ErrValidateVAT'] = wp_sprintf( __( 'Fail to validate the %s number!', 'invoicing' ), $vat_name );
97
        $vars['ErrResetVAT'] = wp_sprintf( __( 'Fail to reset the %s number!', 'invoicing' ), $vat_name );
98
        $vars['ErrInvalidVat'] = wp_sprintf( __( 'The %s number supplied does not have a valid format!', 'invoicing' ), $vat_name );
99
        $vars['ErrInvalidResponse'] = __( 'An invalid response has been received from the server!', 'invoicing' );
100
        $vars['ApplyVATRules'] = $vars['UseTaxes'] ? self::allow_vat_rules() : false;
101
        $vars['ErrResponse'] = __( 'The request response is invalid!', 'invoicing' );
102
        $vars['ErrRateResponse'] = __( 'The get rate request response is invalid', 'invoicing' );
103
        $vars['PageRefresh'] = __( 'The page will be refreshed in 10 seconds to show the new options.', 'invoicing' );
104
        $vars['RequestResponseNotValidJSON'] = __( 'The get rate request response is not valid JSON', 'invoicing' );
105
        $vars['GetRateRequestFailed'] = __( 'The get rate request failed: ', 'invoicing' );
106
        $vars['NoRateInformationInResponse'] = __( 'The get rate request response does not contain any rate information', 'invoicing' );
107
        $vars['RatesUpdated'] = __( 'The rates have been updated. Press the save button to record these new rates.', 'invoicing' );
108
        $vars['IPAddressInformation'] = __( 'IP Address Information', 'invoicing' );
109
        $vars['VatValidating'] = wp_sprintf( __( 'Validating %s number...', 'invoicing' ), $vat_name );
110
        $vars['VatReseting'] = __( 'Reseting...', 'invoicing' );
111
        $vars['VatValidated'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name );
112
        $vars['VatNotValidated'] = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name );
113
        $vars['ConfirmDeleteClass'] = __( 'Are you sure you wish to delete this rates class?', 'invoicing' );
114
        $vars['isFront'] = is_admin() ? false : true;
115
        $vars['baseCountry'] = wpinv_get_default_country();
116
        $vars['disableVATSameCountry'] = ( self::same_country_rule() == 'no' ? true : false );
117
        $vars['disableVATSimpleCheck'] = wpinv_get_option( 'vat_offline_check' ) ? true : false;
118
119
        wp_enqueue_script( 'wpinv-vat-validation-script' );
120
        wp_enqueue_script( 'wpinv-vat-script' );
121
        wp_localize_script( 'wpinv-vat-script', 'WPInv_VAT_Vars', $vars );
122
    }
123
124
    public static function enqueue_admin_scripts() {
125
        if( isset( $_GET['page'] ) && 'wpinv-settings' == $_GET['page'] ) {
126
            self::load_vat_scripts();
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_EUVat::load_vat_scripts() is not static, but was called statically. ( Ignorable by Annotation )

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

126
            self::/** @scrutinizer ignore-call */ 
127
                  load_vat_scripts();
Loading history...
127
        }
128
    }
129
130
    public static function section_vat_settings( $sections ) {
131
        if ( !empty( $sections ) ) {
132
            $sections['vat'] = __( 'EU VAT Settings', 'invoicing' );
133
134
            if ( self::allow_vat_classes() ) {
135
                $sections['vat_rates'] = __( 'EU VAT Rates', 'invoicing' );
136
            }
137
        }
138
        return $sections;
139
    }
140
141
    /**
142
     * @deprecated
143
     */
144
    public static function vat_rates_settings() {}
145
146
    public static function vat_settings( $settings ) {
147
        if ( !empty( $settings ) ) {
148
            $vat_settings = array();
149
            $vat_settings['vat_company_title'] = array(
150
                'id' => 'vat_company_title',
151
                'name' => '<h3>' . __( 'Your Company Details', 'invoicing' ) . '</h3>',
152
                'desc' => '',
153
                'type' => 'header',
154
                'size' => 'regular'
155
            );
156
157
            $vat_settings['vat_company_name'] = array(
158
                'id' => 'vat_company_name',
159
                'name' => __( 'Your Company Name', 'invoicing' ),
160
                'desc' => wp_sprintf(__( 'Your company name as it appears on your VAT return, you can verify it via your VAT ID on the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ),
161
                'type' => 'text',
162
                'size' => 'regular',
163
            );
164
165
            $vat_settings['vat_number'] = array(
166
                'id'   => 'vat_number',
167
                'name' => __( 'Your VAT Number', 'invoicing' ),
168
                'type' => 'vat_number',
169
                'size' => 'regular',
170
            );
171
172
            $vat_settings['vat_settings_title'] = array(
173
                'id' => 'vat_settings_title',
174
                'name' => '<h3>' . __( 'Apply VAT Settings', 'invoicing' ) . '</h3>',
175
                'desc' => '',
176
                'type' => 'header',
177
                'size' => 'regular'
178
            );
179
180
            $vat_settings['apply_vat_rules'] = array(
181
                'id' => 'apply_vat_rules',
182
                'name' => __( 'Enable VAT Rules', 'invoicing' ),
183
                'desc' => __( 'Apply VAT to consumer sales from IP addresses within the EU, even if the billing address is outside the EU.', 'invoicing' ) . '<br><font style="color:red">' . __( 'Do not disable unless you know what you are doing.', 'invoicing' ) . '</font>',
184
                'type' => 'checkbox',
185
                'std' => '1'
186
            );
187
188
            $vat_settings['vat_prevent_b2c_purchase'] = array(
189
                'id' => 'vat_prevent_b2c_purchase',
190
                'name' => __( 'Prevent EU B2C Sales', 'invoicing' ),
191
                'desc' => __( 'Enable this option if you are not registered for VAT in the EU.', 'invoicing' ),
192
                'type' => 'checkbox'
193
            );
194
195
            $vat_settings['vat_same_country_rule'] = array(
196
                'id'          => 'vat_same_country_rule',
197
                'name'        => __( 'Same Country Rule', 'invoicing' ),
198
                'desc'        => __( 'Select how you want to handle VAT charge if sales are in the same country as the base country.', 'invoicing' ),
199
                'type'        => 'select',
200
                'options'     => array(
201
                    ''          => __( 'Normal', 'invoicing' ),
202
                    'no'        => __( 'No VAT', 'invoicing' ),
203
                    'always'    => __( 'Always apply VAT', 'invoicing' ),
204
                ),
205
                'placeholder' => __( 'Select an option', 'invoicing' ),
206
                'std'         => '',
207
                'class'   => 'wpi_select2',
208
            );
209
210
            $vat_settings['vat_checkout_title'] = array(
211
                'id' => 'vat_checkout_title',
212
                'name' => '<h3>' . __( 'Checkout Fields', 'invoicing' ) . '</h3>',
213
                'desc' => '',
214
                'type' => 'header',
215
                'size' => 'regular'
216
            );
217
218
            $vat_settings['vies_validation_title'] = array(
219
                'id' => 'vies_validation_title',
220
                'name' => '<h3>' . __( 'VIES Validation', 'invoicing' ) . '</h3>',
221
                'desc' => '',
222
                'type' => 'header',
223
                'size' => 'regular'
224
            );
225
226
            $vat_settings['vat_vies_check'] = array(
227
                'id' => 'vat_vies_check',
228
                'name' => __( 'Disable VIES VAT ID Check', 'invoicing' ),
229
                'desc' => wp_sprintf( __( 'Prevent VAT numbers from being validated by the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ),
230
                'type' => 'checkbox'
231
            );
232
233
            $vat_settings['vat_disable_company_name_check'] = array(
234
                'id' => 'vat_disable_company_name_check',
235
                'name' => __( 'Disable VIES Name Check', 'invoicing' ),
236
                'desc' => wp_sprintf( __( 'Prevent company name from being validated by the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ),
237
                'type' => 'checkbox'
238
            );
239
240
            $vat_settings['vat_offline_check'] = array(
241
                'id' => 'vat_offline_check',
242
                'name' => __( 'Disable Basic Checks', 'invoicing' ),
243
                'desc' => __( 'Disable basic JS checks for correct format of VAT number. (Not Recommended)', 'invoicing' ),
244
                'type' => 'checkbox'
245
            );
246
247
248
            $settings['vat'] = $vat_settings;
249
250
        }
251
252
        return $settings;
253
    }
254
255
    /**
256
	 *
257
	 * @deprecated
258
	 */
259
    public static function maxmind_folder() {
260
        return false;
261
    }
262
263
    /**
264
	 *
265
	 * @deprecated
266
	 */
267
    public static function geoip2_download_database() {}
268
269
    /**
270
	 *
271
	 * @deprecated
272
	 */
273
    public static function geoip2_download_file() {}
274
275
    /**
276
     * @deprecated
277
     */
278
    public static function load_geoip2() {}
279
280
    /**
281
     * @deprecated
282
     */
283
    public static function geoip2_country_dbfile() {
284
        return false;
285
    }
286
287
    /**
288
     * @deprecated
289
     */
290
    public static function geoip2_city_dbfile() {
291
        return false;
292
    }
293
294
    /**
295
     * @deprecated
296
     */
297
    public static function geoip2_country_reader() {
298
        return false;
299
    }
300
301
    /**
302
     * @deprecated
303
     */
304
    public static function geoip2_city_reader() {
305
        return false;
306
    }
307
308
    /**
309
     * @deprecated
310
     */
311
    public static function geoip2_country_record() {
312
        return false;
313
    }
314
315
    /**
316
     * @deprecated
317
     */
318
    public static function geoip2_city_record() {
319
        return false;
320
    }
321
322
    /**
323
     * @deprecated
324
     */
325
    public static function geoip2_country_code() {
326
        wpinv_get_default_country();
327
    }
328
329
    /**
330
     * @deprecated
331
     */
332
    public static function get_country_by_ip() {
333
        return getpaid_get_ip_country();
334
    }
335
336
    public static function sanitize_vat_settings( $input ) {
337
        global $wpinv_options;
338
339
        $valid      = false;
340
        $message    = '';
341
342
        if ( !empty( $wpinv_options['vat_vies_check'] ) ) {
343
            if ( empty( $wpinv_options['vat_offline_check'] ) ) {
344
                $valid = self::offline_check( $input['vat_number'] );
345
            } else {
346
                $valid = true;
347
            }
348
349
            $message = $valid ? '' : __( 'VAT number not validated', 'invoicing' );
350
        } else {
351
            $result = self::check_vat( $input['vat_number'] );
352
353
            if ( empty( $result['valid'] ) ) {
354
                $valid      = false;
355
                $message    = $result['message'];
356
            } else {
357
                $valid      = ( isset( $result['company'] ) && ( $result['company'] == '---' || ( strcasecmp( trim( $result['company'] ), trim( $input['vat_company_name'] ) ) == 0 ) ) ) || !empty( $wpinv_options['vat_disable_company_name_check'] );
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $valid = (IssetNode && $..._company_name_check'])), Probably Intended Meaning: $valid = IssetNode && ($..._company_name_check']))
Loading history...
358
                $message    = $valid ? '' : __( 'The company name associated with the VAT number provided is not the same as the company name provided.', 'invoicing' );
359
            }
360
        }
361
362
        if ( $message && self::is_vat_validated() != $valid ) {
363
            add_settings_error( 'wpinv-notices', '', $message, ( $valid ? 'updated' : 'error' ) );
364
        }
365
366
        $input['vat_valid'] = $valid;
367
        return $input;
368
    }
369
370
    /**
371
     * @deprecated
372
     */
373
    public static function sanitize_vat_rates() {}
374
375
    /**
376
     * @deprecated
377
     */
378
    public static function add_class() {}
379
380
    /**
381
     * @deprecated
382
     */
383
    public static function delete_class() {}
384
385
    /**
386
     * @deprecated
387
     */
388
    public static function update_eu_rates() {}
389
390
    /**
391
     * @deprecated
392
     */
393
    public static function hide_vat_fields() {}
394
395
    public static function same_country_rule() {
396
        $same_country_rule = wpinv_get_option( 'vat_same_country_rule' );
397
398
        return apply_filters( 'wpinv_vat_same_country_rule', $same_country_rule );
399
    }
400
401
    /**
402
     * Retrieves the vat name.
403
     */
404
    public function get_vat_name() {
405
        $vat_name = wpinv_get_option( 'vat_name' );
406
        return empty( $vat_name ) ? __( 'VAT', 'invoicing' ) : sanitize_text_field( $vat_name );
407
    }
408
409
    public static function get_company_name() {
410
        $company_name = wpinv_get_option( 'vat_company_name' );
411
412
        return apply_filters( 'wpinv_get_owner_company_name', $company_name );
413
    }
414
415
    public static function get_vat_number() {
416
        $vat_number = wpinv_get_option( 'vat_number' );
417
418
        return apply_filters( 'wpinv_get_owner_vat_number', $vat_number );
419
    }
420
421
    public static function is_vat_validated() {
422
        $validated = self::get_vat_number() && wpinv_get_option( 'vat_valid' );
423
424
        return apply_filters( 'wpinv_is_owner_vat_validated', $validated );
425
    }
426
427
    public static function sanitize_vat( $vat_number, $country_code = '' ) {
428
        $vat_number = str_replace( array(' ', '.', '-', '_', ',' ), '', strtoupper( trim( $vat_number ) ) );
429
430
        if ( empty( $country_code ) ) {
431
            $country_code = substr( $vat_number, 0, 2 );
432
        }
433
434
        if ( strpos( $vat_number , $country_code ) === 0 ) {
435
            $vat = str_replace( $country_code, '', $vat_number );
436
        } else {
437
            $vat = $country_code . $vat_number;
438
        }
439
440
        $return                 = array();
441
        $return['vat']          = $vat;
442
        $return['iso']          = $country_code;
443
        $return['vat_number']   = $country_code . $vat;
444
445
        return $return;
446
    }
447
448
    public static function offline_check( $vat_number, $country_code = '', $formatted = false ) {
449
        $vat            = self::sanitize_vat( $vat_number, $country_code );
450
        $vat_number     = $vat['vat_number'];
451
        $country_code   = $vat['iso'];
452
        $regex          = array();
453
454
        switch ( $country_code ) {
455
            case 'AT':
456
                $regex[] = '/^(AT)U(\d{8})$/';                           // Austria
457
                break;
458
            case 'BE':
459
                $regex[] = '/^(BE)(0?\d{9})$/';                          // Belgium
460
                break;
461
            case 'BG':
462
                $regex[] = '/^(BG)(\d{9,10})$/';                         // Bulgaria
463
                break;
464
            case 'CH':
465
            case 'CHE':
466
                $regex[] = '/^(CHE)(\d{9})MWST$/';                       // Switzerland (Not EU)
467
                break;
468
            case 'CY':
469
                $regex[] = '/^(CY)([0-5|9]\d{7}[A-Z])$/';                // Cyprus
470
                break;
471
            case 'CZ':
472
                $regex[] = '/^(CZ)(\d{8,13})$/';                         // Czech Republic
473
                break;
474
            case 'DE':
475
                $regex[] = '/^(DE)([1-9]\d{8})$/';                       // Germany
476
                break;
477
            case 'DK':
478
                $regex[] = '/^(DK)(\d{8})$/';                            // Denmark
479
                break;
480
            case 'EE':
481
                $regex[] = '/^(EE)(10\d{7})$/';                          // Estonia
482
                break;
483
            case 'EL':
484
                $regex[] = '/^(EL)(\d{9})$/';                            // Greece
485
                break;
486
            case 'ES':
487
                $regex[] = '/^(ES)([A-Z]\d{8})$/';                       // Spain (National juridical entities)
488
                $regex[] = '/^(ES)([A-H|N-S|W]\d{7}[A-J])$/';            // Spain (Other juridical entities)
489
                $regex[] = '/^(ES)([0-9|Y|Z]\d{7}[A-Z])$/';              // Spain (Personal entities type 1)
490
                $regex[] = '/^(ES)([K|L|M|X]\d{7}[A-Z])$/';              // Spain (Personal entities type 2)
491
                break;
492
            case 'EU':
493
                $regex[] = '/^(EU)(\d{9})$/';                            // EU-type
494
                break;
495
            case 'FI':
496
                $regex[] = '/^(FI)(\d{8})$/';                            // Finland
497
                break;
498
            case 'FR':
499
                $regex[] = '/^(FR)(\d{11})$/';                           // France (1)
500
                $regex[] = '/^(FR)[(A-H)|(J-N)|(P-Z)](\d{10})$/';        // France (2)
501
                $regex[] = '/^(FR)\d[(A-H)|(J-N)|(P-Z)](\d{9})$/';       // France (3)
502
                $regex[] = '/^(FR)[(A-H)|(J-N)|(P-Z)]{2}(\d{9})$/';      // France (4)
503
                break;
504
            case 'GB':
505
                $regex[] = '/^(GB)?(\d{9})$/';                           // UK (Standard)
506
                $regex[] = '/^(GB)?(\d{12})$/';                          // UK (Branches)
507
                $regex[] = '/^(GB)?(GD\d{3})$/';                         // UK (Government)
508
                $regex[] = '/^(GB)?(HA\d{3})$/';                         // UK (Health authority)
509
                break;
510
            case 'GR':
511
                $regex[] = '/^(GR)(\d{8,9})$/';                          // Greece
512
                break;
513
            case 'HR':
514
                $regex[] = '/^(HR)(\d{11})$/';                           // Croatia
515
                break;
516
            case 'HU':
517
                $regex[] = '/^(HU)(\d{8})$/';                            // Hungary
518
                break;
519
            case 'IE':
520
                $regex[] = '/^(IE)(\d{7}[A-W])$/';                       // Ireland (1)
521
                $regex[] = '/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/';        // Ireland (2)
522
                $regex[] = '/^(IE)(\d{7}[A-Z][AH])$/';                   // Ireland (3) (new format from 1 Jan 2013)
523
                break;
524
            case 'IT':
525
                $regex[] = '/^(IT)(\d{11})$/';                           // Italy
526
                break;
527
            case 'LV':
528
                $regex[] = '/^(LV)(\d{11})$/';                           // Latvia
529
                break;
530
            case 'LT':
531
                $regex[] = '/^(LT)(\d{9}|\d{12})$/';                     // Lithuania
532
                break;
533
            case 'LU':
534
                $regex[] = '/^(LU)(\d{8})$/';                            // Luxembourg
535
                break;
536
            case 'MT':
537
                $regex[] = '/^(MT)([1-9]\d{7})$/';                       // Malta
538
                break;
539
            case 'NL':
540
                $regex[] = '/^(NL)(\d{9})B\d{2}$/';                      // Netherlands
541
                break;
542
            case 'NO':
543
                $regex[] = '/^(NO)(\d{9})$/';                            // Norway (Not EU)
544
                break;
545
            case 'PL':
546
                $regex[] = '/^(PL)(\d{10})$/';                           // Poland
547
                break;
548
            case 'PT':
549
                $regex[] = '/^(PT)(\d{9})$/';                            // Portugal
550
                break;
551
            case 'RO':
552
                $regex[] = '/^(RO)([1-9]\d{1,9})$/';                     // Romania
553
                break;
554
            case 'RS':
555
                $regex[] = '/^(RS)(\d{9})$/';                            // Serbia (Not EU)
556
                break;
557
            case 'SI':
558
                $regex[] = '/^(SI)([1-9]\d{7})$/';                       // Slovenia
559
                break;
560
            case 'SK':
561
                $regex[] = '/^(SK)([1-9]\d[(2-4)|(6-9)]\d{7})$/';        // Slovakia Republic
562
                break;
563
            case 'SE':
564
                $regex[] = '/^(SE)(\d{10}01)$/';                         // Sweden
565
                break;
566
            default:
567
                $regex = array();
568
            break;
569
        }
570
571
        if ( empty( $regex ) ) {
572
            return false;
573
        }
574
575
        foreach ( $regex as $pattern ) {
576
            $matches = null;
577
            preg_match_all( $pattern, $vat_number, $matches );
578
579
            if ( !empty( $matches[1][0] ) && !empty( $matches[2][0] ) ) {
580
                if ( $formatted ) {
581
                    return array( 'code' => $matches[1][0], 'number' => $matches[2][0] );
582
                } else {
583
                    return true;
584
                }
585
            }
586
        }
587
588
        return false;
589
    }
590
591
    public static function vies_check( $vat_number, $country_code = '', $result = false ) {
592
        $vat            = self::sanitize_vat( $vat_number, $country_code );
593
        $vat_number     = $vat['vat'];
594
        $iso            = $vat['iso'];
595
        $response       = false;
596
597
        $url = 'http://ec.europa.eu/taxation_customs/vies/viesquer.do?ms=' . urlencode( $iso ) . '&iso=' . urlencode( $iso ) . '&vat=' . urlencode( $vat_number );
598
599
        if ( ini_get( 'allow_url_fopen' ) ) {
600
            $response = file_get_contents( $url );
601
        } else if ( function_exists( 'curl_init' ) ) {
602
            $ch = curl_init();
603
604
            curl_setopt( $ch, CURLOPT_URL, $url );
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, 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

604
            curl_setopt( /** @scrutinizer ignore-type */ $ch, CURLOPT_URL, $url );
Loading history...
605
            curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 30 );
606
            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
607
            curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
608
            curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
609
610
            $response = curl_exec( $ch );
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, 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

610
            $response = curl_exec( /** @scrutinizer ignore-type */ $ch );
Loading history...
611
612
            if ( curl_errno( $ch ) ) {
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_errno() does only seem to accept resource, 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

612
            if ( curl_errno( /** @scrutinizer ignore-type */ $ch ) ) {
Loading history...
613
                wpinv_error_log( curl_error( $ch ), 'VIES CHECK ERROR' );
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_error() does only seem to accept resource, 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

613
                wpinv_error_log( curl_error( /** @scrutinizer ignore-type */ $ch ), 'VIES CHECK ERROR' );
Loading history...
614
                $response = '';
615
            }
616
617
            curl_close( $ch );
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, 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

617
            curl_close( /** @scrutinizer ignore-type */ $ch );
Loading history...
618
        } else {
619
            wpinv_error_log( 'To use VIES CHECK you must have allow_url_fopen is ON or cURL installed & active on your server.', 'VIES CHECK ERROR' );
620
        }
621
622
        if ( empty( $response ) ) {
623
            return $result;
624
        }
625
626
        if ( preg_match( '/invalid VAT number/i', $response ) ) {
627
            return false;
628
        } else if ( preg_match( '/valid VAT number/i', $response, $matches ) ) {
629
            $content = explode( "valid VAT number", htmlentities( $response ) );
630
631
            if ( !empty( $content[1] ) ) {
632
                preg_match_all( '/<tr>(.*?)<td.*?>(.*?)<\/td>(.*?)<\/tr>/si', html_entity_decode( $content[1] ), $matches );
633
634
                if ( !empty( $matches[2] ) && $matches[3] ) {
635
                    $return = array();
636
637
                    foreach ( $matches[2] as $key => $label ) {
638
                        $label = trim( $label );
639
640
                        switch ( strtolower( $label ) ) {
641
                            case 'member state':
642
                                $return['state'] = trim( strip_tags( $matches[3][$key] ) );
643
                            break;
644
                            case 'vat number':
645
                                $return['number'] = trim( strip_tags( $matches[3][$key] ) );
646
                            break;
647
                            case 'name':
648
                                $return['company'] = trim( strip_tags( $matches[3][$key] ) );
649
                            break;
650
                            case 'address':
651
                                $address           = str_replace( array( "<br><br>", "<br /><br />", "<br/><br/>" ), "<br>", html_entity_decode( trim( $matches[3][$key] ) ) );
652
                                $return['address'] = trim( strip_tags( $address, '<br>' ) );
653
                            break;
654
                            case 'consultation number':
655
                                $return['consultation'] = trim( strip_tags( $matches[3][$key] ) );
656
                            break;
657
                        }
658
                    }
659
660
                    if ( !empty( $return ) ) {
661
                        return $return;
662
                    }
663
                }
664
            }
665
666
            return true;
667
        } else {
668
            return $result;
669
        }
670
    }
671
672
    public static function check_vat( $vat_number, $country_code = '' ) {
673
        $vat_name           = getpaid_vat_name();
674
675
        $return             = array();
676
        $return['valid']    = false;
677
        $return['message']  = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name );
678
679
        if ( !wpinv_get_option( 'vat_offline_check' ) && !self::offline_check( $vat_number, $country_code ) ) {
680
            return $return;
681
        }
682
683
        $response = self::vies_check( $vat_number, $country_code );
684
685
        if ( $response ) {
686
            $return['valid']    = true;
687
688
            if ( is_array( $response ) ) {
689
                $return['company'] = isset( $response['company'] ) ? $response['company'] : '';
690
                $return['address'] = isset( $response['address'] ) ? $response['address'] : '';
691
                $return['message'] = $return['company'] . '<br/>' . $return['address'];
692
            }
693
        } else {
694
            $return['valid']    = false;
695
            $return['message']  = wp_sprintf( __( 'Fail to validate the %s number: EU Commission VAT server (VIES) check fails.', 'invoicing' ), $vat_name );
696
        }
697
698
        return $return;
699
    }
700
701
    /**
702
     * @deprecated
703
     */
704
    public static function request_euvatrates() {
705
        return array();
706
    }
707
708
    public static function requires_vat( $requires_vat = false, $user_id = 0, $is_digital = null ) {
709
        global $wpi_item_id, $wpi_country;
710
711
        if ( !empty( $_POST['wpinv_country'] ) ) {
712
            $country_code = trim( $_POST['wpinv_country'] );
713
        } else if ( !empty( $_POST['country'] ) ) {
714
            $country_code = trim( $_POST['country'] );
715
        } else if ( !empty( $wpi_country ) ) {
716
            $country_code = $wpi_country;
717
        } else {
718
            $country_code = self::get_user_country( '', $user_id );
719
        }
720
721
        if ( $is_digital === null && $wpi_item_id ) {
722
            $is_digital = $wpi_item_id ? self::item_has_digital_rule( $wpi_item_id ) : self::allow_vat_rules();
723
        }
724
725
        if ( !empty( $country_code ) ) {
726
            $requires_vat = ( self::is_eu_state( $country_code ) && ( self::is_eu_state( wpinv_get_default_country() ) || $is_digital ) ) || ( self::is_gst_country( $country_code ) && self::is_gst_country( wpinv_get_default_country() ) );
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: $requires_vat = (self::i...get_default_country())), Probably Intended Meaning: $requires_vat = self::is...get_default_country()))
Loading history...
727
        }
728
729
        return apply_filters( 'wpinv_requires_vat', $requires_vat, $user_id );
730
    }
731
732
    public static function tax_label( $label = '' ) {
733
        global $wpi_requires_vat;
734
735
        if ( !( $wpi_requires_vat !== 0 && $wpi_requires_vat ) ) {
736
            $wpi_requires_vat = self::requires_vat( 0, false );
737
        }
738
739
        return $wpi_requires_vat ? __( self::get_vat_name(), 'invoicing' ) : ( $label ? $label : __( 'Tax', 'invoicing' ) );
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_EUVat::get_vat_name() is not static, but was called statically. ( Ignorable by Annotation )

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

739
        return $wpi_requires_vat ? __( self::/** @scrutinizer ignore-call */ get_vat_name(), 'invoicing' ) : ( $label ? $label : __( 'Tax', 'invoicing' ) );
Loading history...
740
    }
741
742
    public static function standard_rates_label() {
743
        return __( 'Standard Rates', 'invoicing' );
744
    }
745
746
    public static function get_rate_classes( $with_desc = false ) {
747
        $rate_classes_option = get_option( '_wpinv_vat_rate_classes', true );
748
        $classes = maybe_unserialize( $rate_classes_option );
749
750
        if ( empty( $classes ) || !is_array( $classes ) ) {
751
            $classes = array();
752
        }
753
754
        $rate_classes = array();
755
        if ( !array_key_exists( '_standard', $classes ) ) {
756
            if ( $with_desc ) {
757
                $rate_classes['_standard'] = array( 'name' => self::standard_rates_label(), 'desc' => __( 'EU member states standard VAT rates', 'invoicing' ) );
758
            } else {
759
                $rate_classes['_standard'] = self::standard_rates_label();
760
            }
761
        }
762
763
        foreach ( $classes as $key => $class ) {
764
            $name = !empty( $class['name'] ) ? __( $class['name'], 'invoicing' ) : $key;
765
            $desc = !empty( $class['desc'] ) ? __( $class['desc'], 'invoicing' ) : '';
766
767
            if ( $with_desc ) {
768
                $rate_classes[$key] = array( 'name' => $name, 'desc' => $desc );
769
            } else {
770
                $rate_classes[$key] = $name;
771
            }
772
        }
773
774
        return $rate_classes;
775
    }
776
777
    public static function get_all_classes() {
778
        $classes            = self::get_rate_classes();
779
        $classes['_exempt'] = __( 'Exempt (0%)', 'invoicing' );
780
781
        return apply_filters( 'wpinv_vat_get_all_classes', $classes );
782
    }
783
784
    public static function get_class_desc( $rate_class ) {
785
        $rate_classes = self::get_rate_classes( true );
786
787
        if ( !empty( $rate_classes ) && isset( $rate_classes[$rate_class] ) && isset( $rate_classes[$rate_class]['desc'] ) ) {
788
            return $rate_classes[$rate_class]['desc'];
789
        }
790
791
        return '';
792
    }
793
794
    public static function get_vat_groups() {
795
        $vat_groups = array(
796
            'standard'      => 'Standard',
797
            'reduced'       => 'Reduced',
798
            'superreduced'  => 'Super Reduced',
799
            'parking'       => 'Parking',
800
            'increased'     => 'Increased'
801
        );
802
803
        return apply_filters( 'wpinv_get_vat_groups', $vat_groups );
804
    }
805
806
    public static function get_rules() {
807
        $vat_rules = array(
808
            'digital' => __( 'Digital Product', 'invoicing' ),
809
            'physical' => __( 'Physical Product', 'invoicing' ),
810
            '_exempt' => __( 'Tax-Free Product', 'invoicing' ),
811
        );
812
        return apply_filters( 'wpinv_get_vat_rules', $vat_rules );
813
    }
814
815
    public static function get_vat_rates( $class ) {
816
        if ( $class === '_standard' ) {
817
            return GetPaid_Tax::get_all_tax_rates();
818
        }
819
820
        $rates = self::get_non_standard_rates();
821
822
        return array_key_exists( $class, $rates ) ? $rates[$class] : array();
823
    }
824
825
    public static function get_non_standard_rates() {
826
        $option = get_option( 'wpinv_vat_rates', array());
827
        return is_array( $option ) ? $option : array();
828
    }
829
830
    public static function allow_vat_rules() {
831
        return ( wpinv_use_taxes() && wpinv_get_option( 'apply_vat_rules' ) ? true : false );
832
    }
833
834
    public static function allow_vat_classes() {
835
        return false; // TODO
836
        return ( wpinv_get_option( 'vat_allow_classes' ) ? true : false );
0 ignored issues
show
Unused Code introduced by
return wpinv_get_option(...lasses') ? true : false 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...
837
    }
838
839
    public static function get_item_class( $postID ) {
840
        $class = get_post_meta( $postID, '_wpinv_vat_class', true );
841
842
        if ( empty( $class ) ) {
843
            $class = '_standard';
844
        }
845
846
        return apply_filters( 'wpinv_get_item_vat_class', $class, $postID );
847
    }
848
849
    public static function item_class_label( $postID ) {
850
        $vat_classes = self::get_all_classes();
851
852
        $class = self::get_item_class( $postID );
853
        $class = isset( $vat_classes[$class] ) ? $vat_classes[$class] : __( $class, 'invoicing' );
854
855
        return apply_filters( 'wpinv_item_class_label', $class, $postID );
856
    }
857
858
    public static function get_item_rule( $postID ) {
859
        $rule_type = get_post_meta( $postID, '_wpinv_vat_rule', true );
860
861
        if ( empty( $rule_type ) ) {
862
            $rule_type = self::allow_vat_rules() ? 'digital' : 'physical';
863
        }
864
865
        return apply_filters( 'wpinv_item_get_vat_rule', $rule_type, $postID );
866
    }
867
868
    public static function item_rule_label( $postID ) {
869
        $vat_rules  = self::get_rules();
870
        $vat_rule   = self::get_item_rule( $postID );
871
        $vat_rule   = isset( $vat_rules[$vat_rule] ) ? $vat_rules[$vat_rule] : $vat_rule;
872
873
        return apply_filters( 'wpinv_item_rule_label', $vat_rule, $postID );
874
    }
875
876
    public static function item_has_digital_rule( $item_id = 0 ) {
877
        return self::get_item_rule( $item_id ) == 'digital' ? true : false;
878
    }
879
880
    public static function invoice_has_digital_rule( $invoice = 0 ) {
881
        if ( !self::allow_vat_rules() ) {
882
            return false;
883
        }
884
885
        if ( empty( $invoice ) ) {
886
            return true;
887
        }
888
889
        if ( is_int( $invoice ) ) {
890
            $invoice = new WPInv_Invoice( $invoice );
891
        }
892
893
        if ( !( is_object( $invoice ) && is_a( $invoice, 'WPInv_Invoice' ) ) ) {
894
            return true;
895
        }
896
897
        $cart_items  = $invoice->get_cart_details();
898
899
        if ( !empty( $cart_items ) ) {
900
            $has_digital_rule = false;
901
902
            foreach ( $cart_items as $key => $item ) {
903
                if ( self::item_has_digital_rule( $item['id'] ) ) {
904
                    $has_digital_rule = true;
905
                    break;
906
                }
907
            }
908
        } else {
909
            $has_digital_rule = true;
910
        }
911
912
        return $has_digital_rule;
913
    }
914
915
    public static function item_is_taxable( $item_id = 0, $country = false, $state = false ) {
916
        if ( !wpinv_use_taxes() ) {
917
            return false;
918
        }
919
920
        $is_taxable = true;
921
922
        if ( !empty( $item_id ) && self::get_item_class( $item_id ) == '_exempt' ) {
923
            $is_taxable = false;
924
        }
925
926
        if ( !empty( $item_id ) && self::get_item_rule( $item_id ) == '_exempt' ) {
927
            $is_taxable = false;
928
        }
929
930
        return apply_filters( 'wpinv_item_is_taxable', $is_taxable, $item_id, $country , $state );
931
    }
932
933
    public static function find_rate( $country, $state, $rate, $class ) {
934
        global $wpi_zero_tax;
935
936
        if ( $class === '_exempt' || $wpi_zero_tax ) {
937
            return 0;
938
        }
939
940
        $tax_rates   = GetPaid_Tax::get_all_tax_rates();
941
942
        if ( $class !== '_standard' ) {
943
            $class_rates = self::get_vat_rates( $class );
944
945
            if ( is_array( $class_rates ) ) {
946
                $indexed_class_rates = array();
947
948
                foreach ( $class_rates as $key => $cr ) {
949
                    $indexed_class_rates[$cr['country']] = $cr;
950
                }
951
952
                $tax_rates = array_map( function( $tr ) use( $indexed_class_rates ) {
953
                    $tr_country = $tr['country'];
954
                    if ( !isset( $indexed_class_rates[$tr_country] ) ) {
955
                        return $tr;
956
                    }
957
                    $icr = $indexed_class_rates[$tr_country];
958
                    return ( empty( $icr['rate'] ) && $icr['rate'] !== '0' ) ? $tr : $icr;
959
960
                }, $tax_rates, $class_rates );
961
            }
962
        }
963
964
        if ( !empty( $tax_rates ) ) {
965
            foreach ( $tax_rates as $key => $tax_rate ) {
966
                if ( $country != $tax_rate['country'] )
967
                    continue;
968
969
                if ( !empty( $tax_rate['global'] ) ) {
970
                    if ( 0 !== $tax_rate['rate'] || !empty( $tax_rate['rate'] ) ) {
971
                        $rate = number_format( $tax_rate['rate'], 4 );
972
                    }
973
                } else {
974
                    if ( empty( $tax_rate['state'] ) || strtolower( $state ) != strtolower( $tax_rate['state'] ) )
975
                        continue;
976
977
                    $state_rate = $tax_rate['rate'];
978
                    if ( 0 !== $state_rate || !empty( $state_rate ) ) {
979
                        $rate = number_format( $state_rate, 4 );
980
                    }
981
                }
982
            }
983
        }
984
985
        return $rate;
986
    }
987
988
    public static function get_rate( $rate = 1, $country = '', $state = '', $item_id = 0 ) {
989
        global $wpinv_options, $wpi_item_id, $wpi_zero_tax;
990
991
        $item_id = $item_id > 0 ? $item_id : $wpi_item_id;
992
        $allow_vat_classes = self::allow_vat_classes();
993
        $class = $item_id ? self::get_item_class( $item_id ) : '_standard';
994
995
        if ( $class === '_exempt' || $wpi_zero_tax ) {
996
            return 0;
997
        } else if ( !$allow_vat_classes ) {
0 ignored issues
show
introduced by
The condition $allow_vat_classes is always false.
Loading history...
998
            $class = '_standard';
999
        }
1000
1001
        if( !empty( $_POST['wpinv_country'] ) ) {
1002
            $post_country = $_POST['wpinv_country'];
1003
        } elseif( !empty( $_POST['wpinv_country'] ) ) {
1004
            $post_country = $_POST['wpinv_country'];
1005
        } elseif( !empty( $_POST['country'] ) ) {
1006
            $post_country = $_POST['country'];
1007
        } else {
1008
            $post_country = '';
1009
        }
1010
1011
        $country        = !empty( $post_country ) ? $post_country : wpinv_default_billing_country( $country );
1012
        $base_country   = wpinv_is_base_country( $country );
1013
1014
        $requires_vat   = self::requires_vat( 0, false );
1015
        $is_digital     = self::get_item_rule( $item_id ) == 'digital' ;
1016
        $rate           = $requires_vat && isset( $wpinv_options['eu_fallback_rate'] ) ? $wpinv_options['eu_fallback_rate'] : $rate;
1017
1018
        if ( self::same_country_rule() == 'no' && $base_country ) { // Disable VAT to same country
1019
            $rate = 0;
1020
        } else if ( $requires_vat ) {
1021
            $vat_number = self::get_user_vat_number( '', 0, true );
1022
            $vat_info   = self::current_vat_data();
1023
1024
            if ( is_array( $vat_info ) ) {
1025
                $vat_number = isset( $vat_info['number'] ) && !empty( $vat_info['valid'] ) ? $vat_info['number'] : "";
1026
            }
1027
1028
            if ( $country == 'UK' ) {
1029
                $country = 'GB';
1030
            }
1031
1032
            if ( !empty( $vat_number ) ) {
1033
                $rate = 0;
1034
            } else {
1035
                $rate = self::find_rate( $country, $state, $rate, $class ); // Fix if there are no tax rated and you try to pay an invoice it does not add the fallback tax rate
1036
            }
1037
1038
            if ( empty( $vat_number ) && !$is_digital ) {
1039
                if ( $base_country ) {
1040
                    $rate = self::find_rate( $country, null, $rate, $class );
1041
                } else {
1042
                    if ( empty( $country ) && isset( $wpinv_options['eu_fallback_rate'] ) ) {
1043
                        $rate = $wpinv_options['eu_fallback_rate'];
1044
                    } else if( !empty( $country ) ) {
1045
                        $rate = self::find_rate( $country, $state, $rate, $class );
1046
                    }
1047
                }
1048
            } else if ( empty( $vat_number ) || ( self::same_country_rule() == 'always' && $base_country ) ) {
1049
                if ( empty( $country ) && isset( $wpinv_options['eu_fallback_rate'] ) ) {
1050
                    $rate = $wpinv_options['eu_fallback_rate'];
1051
                } else if( !empty( $country ) ) {
1052
                    $rate = self::find_rate( $country, $state, $rate, $class );
1053
                }
1054
            }
1055
        } else {
1056
            if ( $is_digital ) {
1057
                $ip_country_code = getpaid_get_ip_country();
1058
1059
                if ( $ip_country_code && self::is_eu_state( $ip_country_code ) ) {
1060
                    $rate = self::find_rate( $ip_country_code, '', 0, $class );
1061
                } else {
1062
                    $rate = self::find_rate( $country, $state, $rate, $class );
1063
                }
1064
            } else {
1065
                $rate = self::find_rate( $country, $state, $rate, $class );
1066
            }
1067
        }
1068
1069
        return $rate;
1070
    }
1071
1072
    public static function current_vat_data() {
1073
        return getpaid_session()->get( 'user_vat_data' );
1074
    }
1075
1076
    public static function get_user_country( $country = '', $user_id = 0 ) {
1077
        $user_address = wpinv_get_user_address( $user_id, false );
1078
1079
        $country    = empty( $user_address ) || !isset( $user_address['country'] ) || empty( $user_address['country'] ) ? $country : $user_address['country'];
1080
        $result     = apply_filters( 'wpinv_get_user_country', $country, $user_id );
1081
1082
        if ( empty( $result ) ) {
1083
            $result = getpaid_get_ip_country();
1084
        }
1085
1086
        return $result;
1087
    }
1088
1089
    public static function set_user_country( $country = '', $user_id = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $user_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

1089
    public static function set_user_country( $country = '', /** @scrutinizer ignore-unused */ $user_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...
1090
        global $wpi_userID;
1091
1092
        if ( empty($country) && !empty($wpi_userID) && get_current_user_id() != $wpi_userID ) {
1093
            $country = wpinv_get_default_country();
1094
        }
1095
1096
        return $country;
1097
    }
1098
1099
    public static function get_user_vat_number( $vat_number = '', $user_id = 0, $is_valid = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $vat_number 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

1099
    public static function get_user_vat_number( /** @scrutinizer ignore-unused */ $vat_number = '', $user_id = 0, $is_valid = false ) {

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...
1100
        global $wpi_current_id, $wpi_userID;
1101
1102
        if ( !empty( $_POST['new_user'] ) ) {
1103
            return '';
1104
        }
1105
1106
        if ( empty( $user_id ) ) {
1107
            $user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() );
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_user_id() has been deprecated. ( Ignorable by Annotation )

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

1107
            $user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? /** @scrutinizer ignore-deprecated */ wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() );
Loading history...
1108
        }
1109
1110
        $vat_number = empty( $user_id ) ? '' : get_user_meta( $user_id, '_wpinv_vat_number', true );
1111
1112
        /* TODO
1113
        if ( $is_valid && $vat_number ) {
1114
            $adddress_confirmed = empty( $user_id ) ? false : get_user_meta( $user_id, '_wpinv_adddress_confirmed', true );
1115
            if ( !$adddress_confirmed ) {
1116
                $vat_number = '';
1117
            }
1118
        }
1119
        */
1120
1121
        return apply_filters('wpinv_get_user_vat_number', $vat_number, $user_id, $is_valid );
1122
    }
1123
1124
    public static function get_user_company( $company = '', $user_id = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $company 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

1124
    public static function get_user_company( /** @scrutinizer ignore-unused */ $company = '', $user_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...
1125
        global $wpi_current_id, $wpi_userID;
1126
1127
        if ( empty( $user_id ) ) {
1128
            $user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() );
0 ignored issues
show
Deprecated Code introduced by
The function wpinv_get_user_id() has been deprecated. ( Ignorable by Annotation )

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

1128
            $user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? /** @scrutinizer ignore-deprecated */ wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() );
Loading history...
1129
        }
1130
1131
        $company = empty( $user_id ) ? "" : get_user_meta( $user_id, '_wpinv_company', true );
1132
1133
        return apply_filters( 'wpinv_user_company', $company, $user_id );
1134
    }
1135
1136
    public static function save_user_vat_details( $company = '', $vat_number = '' ) {
1137
        $save = apply_filters( 'wpinv_allow_save_user_vat_details', true );
1138
1139
        if ( is_user_logged_in() && $save ) {
1140
            $user_id = get_current_user_id();
1141
1142
            if ( !empty( $vat_number ) ) {
1143
                update_user_meta( $user_id, '_wpinv_vat_number', $vat_number );
1144
            } else {
1145
                delete_user_meta( $user_id, '_wpinv_vat_number');
1146
            }
1147
1148
            if ( !empty( $company ) ) {
1149
                update_user_meta( $user_id, '_wpinv_company', $company );
1150
            } else {
1151
                delete_user_meta( $user_id, '_wpinv_company');
1152
                delete_user_meta( $user_id, '_wpinv_vat_number');
1153
            }
1154
        }
1155
1156
        do_action('wpinv_save_user_vat_details', $company, $vat_number);
1157
    }
1158
1159
    public static function ajax_vat_validate() {
1160
        global $wpinv_options;
1161
1162
        $response               = array();
1163
        $response['success']    = false;
1164
1165
        if ( empty( $_REQUEST['_wpi_nonce'] ) || ( !empty( $_REQUEST['_wpi_nonce'] ) && !wp_verify_nonce( $_REQUEST['_wpi_nonce'], 'vat_validation' ) ) ) {
1166
            $response['error'] = __( 'Invalid security nonce', 'invoicing' );
1167
            wp_send_json( $response );
1168
        }
1169
1170
        $vat_name   = self::get_vat_name();
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_EUVat::get_vat_name() is not static, but was called statically. ( Ignorable by Annotation )

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

1170
        /** @scrutinizer ignore-call */ 
1171
        $vat_name   = self::get_vat_name();
Loading history...
1171
1172
        $company    = !empty( $_POST['company'] ) ? sanitize_text_field( $_POST['company'] ) : '';
1173
        $vat_number = !empty( $_POST['number'] ) ? sanitize_text_field( $_POST['number'] ) : '';
1174
1175
        $vat_info = getpaid_session()->get( 'user_vat_data' );
1176
        if ( !is_array( $vat_info ) || empty( $vat_info ) ) {
1177
            $vat_info = array( 'company'=> $company, 'number' => '', 'valid' => true );
1178
        }
1179
1180
        if ( empty( $vat_number ) ) {
1181
            $response['error'] = wp_sprintf( __( 'Please enter your %s number!', 'invoicing' ), $vat_name );
1182
            $vat_info['valid'] = false;
1183
            getpaid_session()->set( 'user_vat_data', $vat_info );
1184
            wp_send_json( $response );
1185
        }
1186
1187
        if ( empty( $company ) ) {
1188
            $vat_info['valid'] = false;
1189
            getpaid_session()->set( 'user_vat_data', $vat_info );
1190
1191
            $response['error'] = __( 'Please enter your registered company name!', 'invoicing' );
1192
            wp_send_json( $response );
1193
        }
1194
1195
        if ( !empty( $wpinv_options['vat_vies_check'] ) ) {
1196
            if ( empty( $wpinv_options['vat_offline_check'] ) && !self::offline_check( $vat_number ) ) {
1197
                $vat_info['valid'] = false;
1198
                getpaid_session()->set( 'user_vat_data', $vat_info );
1199
1200
                $response['error'] = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name );
1201
                wp_send_json( $response );
1202
            }
1203
1204
            $response['success'] = true;
1205
            $response['message'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name );
1206
        } else {
1207
            $result = self::check_vat( $vat_number );
1208
1209
            if ( empty( $result['valid'] ) ) {
1210
                $response['error'] = $result['message'];
1211
                wp_send_json( $response );
1212
            }
1213
1214
            $vies_company = !empty( $result['company'] ) ? $result['company'] : '';
1215
            $vies_company = apply_filters( 'wpinv_vies_company_name', $vies_company );
1216
1217
            $valid_company = $vies_company && $company && ( $vies_company == '---' || strcasecmp( trim( $vies_company ), trim( $company ) ) == 0 ) ? true : false;
1218
1219
            if ( !empty( $wpinv_options['vat_disable_company_name_check'] ) || $valid_company ) {
1220
                $response['success'] = true;
1221
                $response['message'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name );
1222
            } else {
1223
                $vat_info['valid'] = false;
1224
                getpaid_session()->set( 'user_vat_data', $vat_info );
1225
1226
                $response['success'] = false;
1227
                $response['message'] = wp_sprintf( __( 'The company name associated with the %s number provided is not the same as the company name provided.', 'invoicing' ), $vat_name );
1228
                wp_send_json( $response );
1229
            }
1230
        }
1231
1232
        wp_send_json( $response );
1233
    }
1234
1235
    /**
1236
     * Validates a vat number.
1237
     * 
1238
     * @return string
1239
     */
1240
    public static function validate_vat_number( $vat_number, $company, $country ) {
1241
        global $wpinv_options;
1242
1243
        // If we are not checking the vat number via view...
1244
        if ( ! empty( $wpinv_options['vat_vies_check'] ) ) {
1245
1246
            // Try validating via regex.
1247
            if ( empty( $wpinv_options['vat_offline_check'] ) && ! self::offline_check( $vat_number, $country ) ) {
1248
                return wp_sprintf(
1249
                    __( 'Your %s number is invalid', 'invoicing' ),
1250
                    getpaid_vat_name()
1251
                );
1252
            }
1253
1254
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
1255
        }
1256
1257
        // Validate the vat number.
1258
        $result = self::check_vat( $vat_number, $country );
1259
1260
        if ( empty( $result['valid'] ) ) {
1261
            return wp_sprintf(
1262
                __( 'Failed to validate the %s number via EU Commission VAT server (VIES).', 'invoicing' ),
1263
                getpaid_vat_name()
1264
            );
1265
        }
1266
1267
        // Validate the company.
1268
        $vies_company  = ! empty( $result['company'] ) ? $result['company'] : '';
1269
        $vies_company  = apply_filters( 'wpinv_vies_company_name', $vies_company );
1270
        $valid_company = $vies_company && $company && ( $vies_company == '---' || strcasecmp( trim( $vies_company ), trim( $company ) ) == 0 ) ? true : false;
1271
1272
        if ( ! $valid_company && ! empty( $wpinv_options['vat_disable_company_name_check'] ) ) {
1273
           return wp_sprintf(
1274
                __( 'The company name associated with the %s number provided is not the same as the company name provided.', 'invoicing' ),
1275
                getpaid_vat_name()
1276
            );
1277
        }
1278
1279
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type string.
Loading history...
1280
    }
1281
1282
}
1283
1284