Completed
Pull Request — master (#78)
by David
07:10
created

VatCalculator::setCompany()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Mpociot\VatCalculator;
4
5
use Illuminate\Contracts\Config\Repository;
6
use Mpociot\VatCalculator\Exceptions\VATCheckUnavailableException;
7
use SoapClient;
8
use SoapFault;
9
10
class VatCalculator
11
{
12
    /**
13
     * VAT Service check URL provided by the EU.
14
     */
15
    const VAT_SERVICE_URL = 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
16
17
    /**
18
     * We're using the free ip2c service to lookup IP 2 country.
19
     */
20
    const GEOCODE_SERVICE_URL = 'http://ip2c.org/';
21
22
    protected $soapClient;
23
24
    /**
25
     * All available tax rules and their exceptions.
26
     *
27
     * Taken from: http://ec.europa.eu/taxation_customs/resources/documents/taxation/vat/how_vat_works/rates/vat_rates_en.pdf
28
     *
29
     * @var array
30
     */
31
    protected $taxRules = [
32
        'AT' => [ // Austria
33
            'rate'       => 0.20,
34
            'exceptions' => [
35
                'Jungholz'   => 0.19,
36
                'Mittelberg' => 0.19,
37
            ],
38
        ],
39
        'BE' => [ // Belgium
40
            'rate' => 0.21,
41
        ],
42
        'BG' => [ // Bulgaria
43
            'rate' => 0.20,
44
        ],
45
        'CY' => [ // Cyprus
46
            'rate' => 0.19,
47
        ],
48
        'CZ' => [ // Czech Republic
49
            'rate' => 0.21,
50
        ],
51
        'DE' => [ // Germany
52
            'rate'       => 0.19,
53
            'exceptions' => [
54
                'Heligoland'            => 0,
55
                'Büsingen am Hochrhein' => 0,
56
            ],
57
        ],
58
        'DK' => [ // Denmark
59
            'rate' => 0.25,
60
        ],
61
        'EE' => [ // Estonia
62
            'rate' => 0.20,
63
        ],
64
        'EL' => [ // Hellenic Republic (Greece)
65
            'rate'       => 0.24,
66
            'exceptions' => [
67
                'Mount Athos' => 0,
68
            ],
69
        ],
70
        'ES' => [ // Spain
71
            'rate'       => 0.21,
72
            'exceptions' => [
73
                'Canary Islands' => 0,
74
                'Ceuta'          => 0,
75
                'Melilla'        => 0,
76
            ],
77
        ],
78
        'FI' => [ // Finland
79
            'rate' => 0.24,
80
        ],
81
        'FR' => [ // France
82
            'rate'       => 0.20,
83
            'exceptions' => [
84
                // Overseas France
85
                'Reunion'    => 0.085,
86
                'Martinique' => 0.085,
87
                'Guadeloupe' => 0.085,
88
                'Guyane'     => 0,
89
                'Mayotte'    => 0,
90
            ],
91
        ],
92
        'GB' => [ // United Kingdom
93
            'rate'       => 0.20,
94
            'exceptions' => [
95
                // UK RAF Bases in Cyprus are taxed at Cyprus rate
96
                'Akrotiri' => 0.19,
97
                'Dhekelia' => 0.19,
98
            ],
99
        ],
100
        'GR' => [ // Greece
101
            'rate'       => 0.24,
102
            'exceptions' => [
103
                'Mount Athos' => 0,
104
            ],
105
        ],
106
        'HR' => [ // Croatia
107
            'rate' => 0.25,
108
        ],
109
        'HU' => [ // Hungary
110
            'rate' => 0.27,
111
        ],
112
        'IE' => [ // Ireland
113
            'rate' => 0.23,
114
        ],
115
        'IT' => [ // Italy
116
            'rate'       => 0.22,
117
            'exceptions' => [
118
                'Campione d\'Italia' => 0,
119
                'Livigno'            => 0,
120
            ],
121
        ],
122
        'LT' => [ // Lithuania
123
            'rate' => 0.21,
124
        ],
125
        'LU' => [ // Luxembourg
126
            'rate' => 0.17,
127
        ],
128
        'LV' => [ // Latvia
129
            'rate' => 0.21,
130
        ],
131
        'MT' => [ // Malta
132
            'rate' => 0.18,
133
        ],
134
        'NL' => [ // Netherlands
135
            'rate' => 0.21,
136
            'rates' => [
137
                'high' => 0.21,
138
                'low' => 0.09,
139
            ],
140
        ],
141
        'PL' => [ // Poland
142
            'rate' => 0.23,
143
        ],
144
        'PT' => [ // Portugal
145
            'rate'       => 0.23,
146
            'exceptions' => [
147
                'Azores'  => 0.18,
148
                'Madeira' => 0.22,
149
            ],
150
        ],
151
        'RO' => [ // Romania
152
            'rate' => 0.19,
153
        ],
154
        'SE' => [ // Sweden
155
            'rate' => 0.25,
156
        ],
157
        'SI' => [ // Slovenia
158
            'rate' => 0.22,
159
        ],
160
        'SK' => [ // Slovakia
161
            'rate' => 0.20,
162
        ],
163
164
        // Countries associated with EU countries that have a special VAT rate
165
        'MC' => [ // Monaco France
166
            'rate' => 0.20,
167
        ],
168
        'IM' => [ // Isle of Man - United Kingdom
169
            'rate' => 0.20,
170
        ],
171
172
        // Non-EU with their own VAT requirements
173
        'CH' => [ // Switzerland
174
            'rate' => 0.077,
175
            'rates' => [
176
                'high' => 0.077,
177
                'low' => 0.025,
178
            ],
179
        ],
180
        'TR' => [ // Turkey
181
            'rate' => 0.18,
182
        ],
183
        'NO' => [ // Norway
184
            'rate' => 0.25,
185
        ],
186
    ];
187
188
    /**
189
     * All possible postal code exceptions.
190
     *
191
     * @var array
192
     */
193
    protected $postalCodeExceptions = [
194
        'AT' => [
195
            [
196
                'postalCode' => '/^6691$/',
197
                'code'       => 'AT',
198
                'name'       => 'Jungholz',
199
            ],
200
            [
201
                'postalCode' => '/^699[123]$/',
202
                'city'       => '/\bmittelberg\b/i',
203
                'code'       => 'AT',
204
                'name'       => 'Mittelberg',
205
            ],
206
        ],
207
        'CH' => [
208
            [
209
                'postalCode' => '/^8238$/',
210
                'code'       => 'DE',
211
                'name'       => 'Büsingen am Hochrhein',
212
            ],
213
            [
214
                'postalCode' => '/^6911$/',
215
                'code'       => 'IT',
216
                'name'       => "Campione d'Italia",
217
            ],
218
            // The Italian city of Domodossola has a Swiss post office also
219
            [
220
                'postalCode' => '/^3907$/',
221
                'code'       => 'IT',
222
            ],
223
        ],
224
        'DE' => [
225
            [
226
                'postalCode' => '/^87491$/',
227
                'code'       => 'AT',
228
                'name'       => 'Jungholz',
229
            ],
230
            [
231
                'postalCode' => '/^8756[789]$/',
232
                'city'       => '/\bmittelberg\b/i',
233
                'code'       => 'AT',
234
                'name'       => 'Mittelberg',
235
            ],
236
            [
237
                'postalCode' => '/^78266$/',
238
                'code'       => 'DE',
239
                'name'       => 'Büsingen am Hochrhein',
240
            ],
241
            [
242
                'postalCode' => '/^27498$/',
243
                'code'       => 'DE',
244
                'name'       => 'Heligoland',
245
            ],
246
        ],
247
        'ES' => [
248
            [
249
                'postalCode' => '/^(5100[1-5]|5107[0-1]|51081)$/',
250
                'code'       => 'ES',
251
                'name'       => 'Ceuta',
252
            ],
253
            [
254
                'postalCode' => '/^(5200[0-6]|5207[0-1]|52081)$/',
255
                'code'       => 'ES',
256
                'name'       => 'Melilla',
257
            ],
258
            [
259
                'postalCode' => '/^(35\d{3}|38\d{3})$/',
260
                'code'       => 'ES',
261
                'name'       => 'Canary Islands',
262
            ],
263
        ],
264
        'FR' => [
265
            [
266
                'postalCode' => '/^971\d{2,}$/',
267
                'code'       => 'FR',
268
                'name'       => 'Guadeloupe',
269
            ],
270
            [
271
                'postalCode' => '/^972\d{2,}$/',
272
                'code'       => 'FR',
273
                'name'       => 'Martinique',
274
            ],
275
            [
276
                'postalCode' => '/^973\d{2,}$/',
277
                'code'       => 'FR',
278
                'name'       => 'Guyane',
279
            ],
280
            [
281
                'postalCode' => '/^974\d{2,}$/',
282
                'code'       => 'FR',
283
                'name'       => 'Reunion',
284
            ],
285
            [
286
                'postalCode' => '/^976\d{2,}$/',
287
                'code'       => 'FR',
288
                'name'       => 'Mayotte',
289
            ],
290
        ],
291
        'GB' => [
292
            // Akrotiri
293
            [
294
                'postalCode' => '/^BFPO57|BF12AT$/',
295
                'code'       => 'CY',
296
            ],
297
            // Dhekelia
298
            [
299
                'postalCode' => '/^BFPO58|BF12AU$/',
300
                'code'       => 'CY',
301
            ],
302
        ],
303
        'GR' => [
304
            [
305
                'postalCode' => '/^63086$/',
306
                'code'       => 'GR',
307
                'name'       => 'Mount Athos',
308
            ],
309
        ],
310
        'IT' => [
311
            [
312
                'postalCode' => '/^22060$/',
313
                'city'       => '/\bcampione\b/i',
314
                'code'       => 'IT',
315
                'name'       => "Campione d'Italia",
316
            ],
317
            [
318
                'postalCode' => '/^23030$/',
319
                'city'       => '/\blivigno\b/i',
320
                'code'       => 'IT',
321
                'name'       => 'Livigno',
322
            ],
323
        ],
324
        'PT' => [
325
            [
326
                'postalCode' => '/^9[0-4]\d{2,}$/',
327
                'code'       => 'PT',
328
                'name'       => 'Madeira',
329
            ],
330
            [
331
                'postalCode' => '/^9[5-9]\d{2,}$/',
332
                'code'       => 'PT',
333
                'name'       => 'Azores',
334
            ],
335
        ],
336
    ];
337
338
    /**
339
     * @var float
340
     */
341
    protected $netPrice = 0.0;
342
343
    /**
344
     * @var string
345
     */
346
    protected $countryCode;
347
348
    /**
349
     * @var string
350
     */
351
    protected $postalCode;
352
353
    /**
354
     * @var Repository
355
     */
356
    protected $config;
357
358
    /**
359
     * @var float
360
     */
361
    protected $taxValue = 0;
362
363
    /**
364
     * @var float
365
     */
366
    protected $taxRate = 0;
367
368
    /**
369
     * The calculate net + tax value.
370
     *
371
     * @var float
372
     */
373
    protected $value = 0;
374
375
    /**
376
     * @var bool
377
     */
378
    protected $company = false;
379
380
    /**
381
     * @var string
382
     */
383
    protected $businessCountryCode;
384
385
    /**
386
     * @param \Illuminate\Contracts\Config\Repository
387
     */
388
    public function __construct($config = null)
389
    {
390
        $this->config = $config;
391
392
        $businessCountryKey = 'vat_calculator.business_country_code';
393
        if (isset($this->config) && $this->config->has($businessCountryKey)) {
394
            $this->setBusinessCountryCode($this->config->get($businessCountryKey, ''));
395
        }
396
    }
397
398
    /**
399
     * Finds the client IP address.
400
     *
401
     * @return mixed
402
     */
403
    private function getClientIP()
404
    {
405
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
406
            $clientIpAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
407
        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR']) {
408
            $clientIpAddress = $_SERVER['REMOTE_ADDR'];
409
        } else {
410
            $clientIpAddress = '';
411
        }
412
413
        return $clientIpAddress;
414
    }
415
416
    /**
417
     * Returns the ISO 3166-1 alpha-2 two letter
418
     * country code for the client IP. If the
419
     * IP can't be resolved it returns false.
420
     *
421
     * @return bool|string
422
     */
423
    public function getIPBasedCountry()
424
    {
425
        $ip = $this->getClientIP();
426
        $url = self::GEOCODE_SERVICE_URL.$ip;
427
        $result = file_get_contents($url);
428
        switch ($result[0]) {
429
            case '1':
430
                $data = explode(';', $result);
431
432
                return $data[1];
433
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
434
            default:
435
                return false;
436
        }
437
    }
438
439
    /**
440
     * Determines if you need to collect VAT for the given country code.
441
     *
442
     * @param $countryCode
443
     *
444
     * @return bool
445
     */
446
    public function shouldCollectVAT($countryCode)
447
    {
448
        $taxKey = 'vat_calculator.rules.'.strtoupper($countryCode);
449
450
        return isset($this->taxRules[strtoupper($countryCode)]) || (isset($this->config) && $this->config->has($taxKey));
451
    }
452
453
    /**
454
     * Calculate the VAT based on the net price, country code and indication if the
455
     * customer is a company or not.
456
     *
457
     * @param int|float   $netPrice    The net price to use for the calculation
458
     * @param null|string $countryCode The country code to use for the rate lookup
459
     * @param null|string $postalCode  The postal code to use for the rate exception lookup
460
     * @param null|bool   $company
461
     * @param null|string $type        The type can be low or high
462
     *
463
     * @return float
464
     */
465
    public function calculate($netPrice, $countryCode = null, $postalCode = null, $company = null, $type = null)
466
    {
467
        if ($countryCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $countryCode of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
468
            $this->setCountryCode($countryCode);
469
        }
470
        if ($postalCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $postalCode of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
471
            $this->setPostalCode($postalCode);
472
        }
473
        if (!is_null($company) && $company !== $this->isCompany()) {
474
            $this->setCompany($company);
475
        }
476
        $this->netPrice = floatval($netPrice);
477
        $this->taxRate = $this->getTaxRateForLocation($this->getCountryCode(), $this->getPostalCode(), $this->isCompany(), $type);
478
        $this->taxValue = $this->taxRate * $this->netPrice;
479
        $this->value = $this->netPrice + $this->taxValue;
480
481
        return $this->value;
482
    }
483
484
    /**
485
     * Calculate the net price on the gross price, country code and indication if the
486
     * customer is a company or not.
487
     *
488
     * @param int|float   $gross       The gross price to use for the calculation
489
     * @param null|string $countryCode The country code to use for the rate lookup
490
     * @param null|string $postalCode  The postal code to use for the rate exception lookup
491
     * @param null|bool   $company
492
     * @param null|string $type        The type can be low or high
493
     *
494
     * @return float
495
     */
496
    public function calculateNet($gross, $countryCode = null, $postalCode = null, $company = null, $type = null)
497
    {
498
        if ($countryCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $countryCode of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
499
            $this->setCountryCode($countryCode);
500
        }
501
        if ($postalCode) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $postalCode of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
502
            $this->setPostalCode($postalCode);
503
        }
504
        if (!is_null($company) && $company !== $this->isCompany()) {
505
            $this->setCompany($company);
506
        }
507
508
        $this->value = floatval($gross);
509
        $this->taxRate = $this->getTaxRateForLocation($this->getCountryCode(), $this->getPostalCode(), $this->isCompany(), $type);
510
        $this->taxValue = $this->taxRate > 0 ? $this->value / (1 + $this->taxRate) * $this->taxRate : 0;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->taxRate > 0 ? $th...e) * $this->taxRate : 0 can also be of type integer. However, the property $taxValue is declared as type double. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
511
        $this->netPrice = $this->value - $this->taxValue;
512
513
        return $this->netPrice;
514
    }
515
516
    /**
517
     * @return float
518
     */
519
    public function getNetPrice()
520
    {
521
        return $this->netPrice;
522
    }
523
524
    /**
525
     * @return string
526
     */
527
    public function getCountryCode()
528
    {
529
        return strtoupper($this->countryCode);
530
    }
531
532
    /**
533
     * @param mixed $countryCode
534
     */
535
    public function setCountryCode($countryCode)
536
    {
537
        $this->countryCode = $countryCode;
538
    }
539
540
    /**
541
     * @return string
542
     */
543
    public function getPostalCode()
544
    {
545
        return $this->postalCode;
546
    }
547
548
    /**
549
     * @param mixed $postalCode
550
     */
551
    public function setPostalCode($postalCode)
552
    {
553
        $this->postalCode = $postalCode;
554
    }
555
556
    /**
557
     * @return float
558
     */
559
    public function getTaxRate()
560
    {
561
        return $this->taxRate;
562
    }
563
564
    /**
565
     * @return bool
566
     */
567
    public function isCompany()
568
    {
569
        return $this->company;
570
    }
571
572
    /**
573
     * @param bool $company
574
     */
575
    public function setCompany($company)
576
    {
577
        $this->company = $company;
578
    }
579
580
    /**
581
     * @param string $businessCountryCode
582
     */
583
    public function setBusinessCountryCode($businessCountryCode)
584
    {
585
        $this->businessCountryCode = $businessCountryCode;
586
    }
587
588
    /**
589
     * Returns the tax rate for the given country code.
590
     * This method is used to allow backwards compatibility.
591
     *
592
     * @param $countryCode
593
     * @param bool $company
594
     * @param string $type
595
     *
596
     * @return float
597
     */
598
    public function getTaxRateForCountry($countryCode, $company = false, $type = null)
599
    {
600
        return $this->getTaxRateForLocation($countryCode, null, $company, $type);
601
    }
602
603
    /**
604
     * Returns the tax rate for the given country code.
605
     * If a postal code is provided, it will try to lookup the different
606
     * postal code exceptions that are possible.
607
     *
608
     * @param string      $countryCode
609
     * @param string|null $postalCode
610
     * @param bool|false  $company
611
     * @param string|null $type
612
     *
613
     * @return float
614
     */
615
    public function getTaxRateForLocation($countryCode, $postalCode = null, $company = false, $type = null)
616
    {
617
        if ($company && strtoupper($countryCode) !== strtoupper($this->businessCountryCode)) {
618
            return 0;
619
        }
620
        $taxKey = 'vat_calculator.rules.'.strtoupper($countryCode);
621
        if (isset($this->config) && $this->config->has($taxKey)) {
622
            return $this->config->get($taxKey, 0);
623
        }
624
625
        if (isset($this->postalCodeExceptions[$countryCode]) && $postalCode !== null) {
626
            foreach ($this->postalCodeExceptions[$countryCode] as $postalCodeException) {
627
                if (!preg_match($postalCodeException['postalCode'], $postalCode)) {
628
                    continue;
629
                }
630
                if (isset($postalCodeException['name'])) {
631
                    return $this->taxRules[$postalCodeException['code']]['exceptions'][$postalCodeException['name']];
632
                }
633
634
                return $this->taxRules[$postalCodeException['code']]['rate'];
635
            }
636
        }
637
638
        if ($type !== null) {
639
            return isset($this->taxRules[strtoupper($countryCode)]['rates'][$type]) ? $this->taxRules[strtoupper($countryCode)]['rates'][$type] : 0;
640
        }
641
642
        return isset($this->taxRules[strtoupper($countryCode)]['rate']) ? $this->taxRules[strtoupper($countryCode)]['rate'] : 0;
643
    }
644
645
    /**
646
     * @return float
647
     */
648
    public function getTaxValue()
649
    {
650
        return $this->taxValue;
651
    }
652
653
    /**
654
     * @param $vatNumber
655
     * @param $requestorVatNumber
656
     *
657
     * @throws VATCheckUnavailableException
658
     *
659
     * @return bool
660
     */
661
    public function isValidVATNumber($vatNumber, $requestorVatNumber = null)
662
    {
663
        $details = self::getVATDetails($vatNumber, $requestorVatNumber);
664
665
        if ($details) {
666
            return $details->valid;
667
        } else {
668
            return false;
669
        }
670
    }
671
672
    /**
673
     * @param $vatNumber
674
     * @param $requestorVat
675
     *
676
     * @throws VATCheckUnavailableException
677
     *
678
     * @return object|false
679
     */
680
    public function getVATDetails($vatNumber, $requestorVat = null)
681
    {
682
        $vatNumber = str_replace([' ', '-', '.', ','], '', trim($vatNumber));
683
        $countryCode = substr($vatNumber, 0, 2);
684
        $vatNumber = substr($vatNumber, 2);
685
686
        if(!$requestorVat) {
687
            $requestorVat = $this->config->get('vat_calculator.business_vat_number');
688
        }
689
690
        $requestorCountryCode = substr($requestorVat, 0, 2);
691
        $requestorVatNumber = substr($requestorVat, 2);
692
693
        $this->initSoapClient();
694
        $client = $this->soapClient;
695
        if ($client) {
696
            try {
697
                $result = $client->checkVatApprox([
698
                    'countryCode' => $countryCode,
699
                    'vatNumber' => $vatNumber,
700
                    'requesterCountryCode' => $requestorCountryCode,
701
                    'requesterVatNumber' => $requestorVatNumber
702
                ]);
703
704
                // ensure backwards compatibility when moving from checkVat service to checkVatApprox service
705
                $result->name = $result->traderName;
706
                $result->address = $result->traderAddress;
707
708
                return $result;
709
            } catch (SoapFault $e) {
710 View Code Duplication
                if (isset($this->config) && $this->config->get('vat_calculator.forward_soap_faults')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
711
                    throw new VATCheckUnavailableException($e->getMessage(), $e->getCode(), $e->getPrevious());
712
                }
713
714
                return false;
715
            }
716
        }
717
        throw new VATCheckUnavailableException('The VAT check service is currently unavailable. Please try again later.');
718
    }
719
720
    /**
721
     * @throws VATCheckUnavailableException
722
     *
723
     * @return void
724
     */
725
    public function initSoapClient()
726
    {
727
        if (is_object($this->soapClient) || $this->soapClient === false) {
728
            return;
729
        }
730
        try {
731
            $this->soapClient = new SoapClient(self::VAT_SERVICE_URL);
732
        } catch (SoapFault $e) {
733 View Code Duplication
            if (isset($this->config) && $this->config->get('vat_calculator.forward_soap_faults')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
734
                throw new VATCheckUnavailableException($e->getMessage(), $e->getCode(), $e->getPrevious());
735
            }
736
737
            $this->soapClient = false;
738
        }
739
    }
740
741
    /**
742
     * @param SoapClient $soapClient
743
     */
744
    public function setSoapClient($soapClient)
745
    {
746
        $this->soapClient = $soapClient;
747
    }
748
}
749