Issues (88)

src/Traits/IbanTrait.php (1 issue)

1
<?php
2
3
/**
4
 * This file is part of Dimtrovich/Validation.
5
 *
6
 * (c) 2023 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace Dimtrovich\Validation\Traits;
13
14
/**
15
 * @credit <a href="https://github.com/milwad-dev/laravel-validate">milwad/laravel-validate - Milwad\LaravelValidate\Traits\IbanTrait</a>
16
 */
17
trait IbanTrait
18
{
19
    /**
20
     * Set value of $countries property.
21
     *
22
     * @return void
23
     */
24
    private function setCountries(?array $countries)
25
    {
26
        if (empty($countries)) {
27 2
            $this->countries = [];
0 ignored issues
show
Bug Best Practice introduced by
The property countries does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
28
29 2
            return;
30
        }
31
32
        if (is_array($countries[0])) {
33
            $countries = $countries[0];
34
        }
35
36
        foreach ($countries as $country) {
37
            $this->countries[] = $country;
38
        }
39
    }
40
41
    /**
42
     * Check IBAN is valid.
43
     */
44
    private function isIbanValid(string $iban): bool
45
    {
46
        if (! $this->checkIbanFormat($iban)) {
47 2
            return false;
48
        }
49
50
        // Connect Iban title with value (code) ex: 8330001234567NO .
51 2
        $parsedIban = substr($iban, 4) . substr($iban, 0, 4);
52
53
        // Replace iban value with character map.
54 2
        $parsedIban = strtr($parsedIban, $this->characterMap);
55
56 2
        return bcmod($parsedIban, '97') === '1';
57
    }
58
59
    /**
60
     * Check IBAN format is valid.
61
     */
62
    private function checkIbanFormat(string $iban): bool
63
    {
64
        if (empty($iban)) {
65
            return false;
66
        }
67
68 2
        $ibanCountryCode = $this->getIbanCountryCode($iban);
69
70
        return ! (empty($this->checkIfBcmodIsAvailable())
71
            || ! $this->twoFirstCharactersValid($ibanCountryCode)
72
            || ! $this->isCountriesValid($ibanCountryCode)
73 2
            || ! $this->isIbanLengthValid($iban, $ibanCountryCode));
74
    }
75
76
    /**
77
     * Get IBAN country code.
78
     */
79
    private function getIbanCountryCode(string $iban): string
80
    {
81 2
        return substr($iban, 0, 2);
82
    }
83
84
    /**
85
     * Check if bcmod function is available.
86
     */
87
    private function checkIfBcmodIsAvailable(): bool
88
    {
89 2
        return function_exists('bcmod');
90
    }
91
92
    /**
93
     * Check two first character's validity.
94
     */
95
    private function twoFirstCharactersValid(string $countryCode): bool
96
    {
97 2
        return ! empty($countryCode) && ctype_alpha($countryCode);
98
    }
99
100
    /**
101
     * Check countries of the IBAN.
102
     */
103
    private function isCountriesValid(string $ibanCountryCode): bool
104
    {
105
        if (empty($this->countries)) {
106 2
            return true;
107
        }
108
109
        foreach ($this->countries as $country) {
110
            if ($this->isCountryValid($country, $ibanCountryCode)) {
111
                return true;
112
            }
113
        }
114
115
        return false;
116
    }
117
118
    /**
119
     * Check country of the IBAN.
120
     */
121
    private function isCountryValid(string $country, string $ibanCountryCode): bool
122
    {
123
        return ! empty($country)
124
            && isset($this->ibanLengthByCountry[$country])
125
            && $ibanCountryCode === $country;
126
    }
127
128
    /**
129
     * Check country of the IBAN.
130
     */
131
    private function isIbanLengthValid(string $iban, string $ibanCountryCode): bool
132
    {
133 2
        return strlen($iban) === $this->ibanLengthByCountry[$ibanCountryCode];
134
    }
135
}
136