Passed
Push — 1.x ( b89f0d...883fdc )
by Milwad
08:47 queued 05:39
created

ValidIban   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 211
Duplicated Lines 0 %

Importance

Changes 10
Bugs 3 Features 4
Metric Value
eloc 150
c 10
b 3
f 4
dl 0
loc 211
rs 10
wmc 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A isIbanValid() 0 8 4
A passes() 0 17 2
A message() 0 3 1
1
<?php
2
3
namespace Milwad\LaravelValidate\Rules;
4
5
use Illuminate\Contracts\Validation\Rule;
6
7
class ValidIban implements Rule
8
{
9
    /**
10
     * Character map
11
     *
12
     * @var array|int[]
13
     */
14
    private array $characterMap = [
15
        'A' => 10,
16
        'B' => 11,
17
        'C' => 12,
18
        'D' => 13,
19
        'E' => 14,
20
        'F' => 15,
21
        'G' => 16,
22
        'H' => 17,
23
        'I' => 18,
24
        'J' => 19,
25
        'K' => 20,
26
        'L' => 21,
27
        'M' => 22,
28
        'N' => 23,
29
        'O' => 24,
30
        'P' => 25,
31
        'Q' => 26,
32
        'R' => 27,
33
        'S' => 28,
34
        'T' => 29,
35
        'U' => 30,
36
        'V' => 31,
37
        'W' => 32,
38
        'X' => 33,
39
        'Y' => 34,
40
        'Z' => 35,
41
    ];
42
43
    /**
44
     * Get country code with length.
45
     *
46
     * @var array|int[]
47
     */
48
    private array $ibanLengthByCountry = [
49
        'AD' => 24, // Andorra
50
        'AE' => 23, // United Arab Emirates
51
        'AL' => 28, // Albania
52
        'AO' => 25, // Angola
53
        'AT' => 20, // Austria
54
        'AZ' => 28, // Azerbaijan
55
        'BA' => 20, // Bosnia and Herzegovina
56
        'BE' => 16, // Belgium
57
        'BF' => 28, // Burkina Faso
58
        'BG' => 22, // Bulgaria
59
        'BH' => 22, // Bahrain
60
        'BI' => 28, // Burundi
61
        'BJ' => 28, // Benin
62
        'BR' => 29, // Brazil
63
        'BY' => 28, // Belarus
64
        'CF' => 27, // Central African Republic
65
        'CG' => 27, // Congo
66
        'CH' => 21, // Switzerland
67
        'CI' => 28, // Ivory Coast
68
        'CM' => 27, // Cameroon
69
        'CR' => 22, // Costa Rica
70
        'CV' => 25, // Cape Verde
71
        'CY' => 28, // Cyprus
72
        'CZ' => 24, // Czech Republic
73
        'DE' => 22, // Germany
74
        'DJ' => 27, // Djibouti
75
        'DK' => 18, // Denmark
76
        'DO' => 28, // Dominican Republic
77
        'DZ' => 26, // Algeria
78
        'EE' => 20, // Estonia
79
        'EG' => 29, // Egypt
80
        'ES' => 24, // Spain
81
        'FI' => 18, // Finland
82
        'FO' => 18, // Faroe Islands
83
        'FR' => 27, // France
84
        'GA' => 27, // Gabon
85
        'GB' => 22, // United Kingdom
86
        'GE' => 22, // Georgia
87
        'GI' => 23, // Gibraltar
88
        'GL' => 18, // Greenland
89
        'GQ' => 27, // Equatorial Guinea
90
        'GR' => 27, // Greece
91
        'GT' => 28, // Guatemala
92
        'GW' => 25, // Guinea-Bissau
93
        'HN' => 28, // Honduras
94
        'HR' => 21, // Croatia
95
        'HU' => 28, // Hungary
96
        'IE' => 22, // Ireland
97
        'IL' => 23, // Israel
98
        'IQ' => 23, // Iraq
99
        'IR' => 26, // Iran
100
        'IS' => 26, // Iceland
101
        'IT' => 27, // Italy
102
        'JO' => 30, // Jordan
103
        'KM' => 27, // Comoros
104
        'KW' => 30, // Kuwait
105
        'KZ' => 20, // Kazakhstan
106
        'LB' => 28, // Lebanon
107
        'LC' => 32, // Saint Lucia
108
        'LI' => 21, // Liechtenstein
109
        'LT' => 20, // Lithuania
110
        'LU' => 20, // Luxembourg
111
        'LV' => 21, // Latvia
112
        'LY' => 25, // Libya
113
        'MA' => 28, // Morocco
114
        'MC' => 27, // Monaco
115
        'MD' => 24, // Moldova
116
        'ME' => 22, // Montenegro
117
        'MG' => 27, // Madagascar
118
        'MK' => 19, // North Macedonia
119
        'ML' => 28, // Mali
120
        'MN' => 20, // Mongolia
121
        'MR' => 27, // Mauritania
122
        'MT' => 31, // Malta
123
        'MU' => 30, // Mauritius
124
        'MZ' => 25, // Mozambique
125
        'NE' => 28, // Niger
126
        'NI' => 32, // Nicaragua
127
        'NL' => 18, // Netherlands
128
        'NO' => 15, // Norway
129
        'PK' => 24, // Pakistan
130
        'PL' => 28, // Poland
131
        'PS' => 29, // Palestine
132
        'PT' => 25, // Portugal
133
        'QA' => 29, // Qatar
134
        'RO' => 24, // Romania
135
        'RS' => 22, // Serbia
136
        'RU' => 33, // Russia
137
        'SA' => 24, // Saudi Arabia
138
        'SC' => 31, // Seychelles
139
        'SD' => 18, // Sudan
140
        'SE' => 24, // Sweden
141
        'SI' => 19, // Slovenia
142
        'SK' => 24, // Slovakia
143
        'SM' => 27, // San Marino
144
        'SN' => 28, // Senegal
145
        'SO' => 23, // Somalia
146
        'ST' => 25, // Sao Tome and Principe
147
        'SV' => 28, // El Salvador
148
        'TD' => 27, // Chad
149
        'TG' => 28, // Togo
150
        'TL' => 23, // Timor-Leste
151
        'TN' => 24, // Tunisia
152
        'TR' => 26, // Turkey
153
        'UA' => 29, // Ukraine
154
        'VA' => 22, // Holy See (the)
155
        'VG' => 24, // Virgin Islands, British
156
        'XK' => 20, // Kosovo
157
    ];
158
159
    /**
160
     * Country code from outside.
161
     */
162
    private string|null $country;
163
164
    public function __construct(string|null $country = null) // TODO: Add $country into the progress
165
    {
166
        $this->country = $country;
167
    }
168
169
    /**
170
     * Check IBAN.
171
     *
172
     * @param  string  $attribute
173
     * @param  mixed  $value
174
     * @return bool
175
     */
176
    public function passes($attribute, $value)
177
    {
178
        if (! $this->isIbanValid($value)) {
179
            return false;
180
        }
181
182
        /*
183
         * Connect Iban title with value (code) ex: 8330001234567NO .
184
         */
185
        $parsedIban = substr($value, 4).substr($value, 0, 4);
186
187
        /*
188
         * Replace iban value with character map.
189
         */
190
        $parsedIban = strtr($parsedIban, $this->characterMap);
191
192
        return bcmod($parsedIban, '97') === '1';
193
    }
194
195
    /**
196
     * Get the validation error message.
197
     *
198
     * @return string
199
     */
200
    public function message()
201
    {
202
        return __('validate.iban');
203
    }
204
205
    /**
206
     * Check iban is valid.
207
     *
208
     * @return bool
209
     */
210
    private function isIbanValid(string $iban)
211
    {
212
        $countryCode = substr($iban, 0, 2); // Get character of value
213
214
        return ! empty($iban)
215
            || function_exists('bcmod') // Check `bcmod` is exists
216
            || ctype_alpha(substr($iban, 0, 2)) //
217
            || strlen($iban) !== $this->ibanLengthByCountry[$countryCode];
218
    }
219
}
220