Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#1188)
by mazen
03:12
created

IBAN::validate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 27
c 0
b 0
f 0
ccs 14
cts 14
cp 1
rs 9.7998
cc 4
nc 3
nop 1
crap 4
1
<?php
2
3
/*
4
 * This file is part of Respect/Validation.
5
 *
6
 * (c) Alexandre Gomes Gaigalas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the "LICENSE.md"
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Respect\Validation\Rules;
15
16
use function is_string;
17
use function str_replace;
18
use function strtoupper;
19
use function strlen;
20
use function preg_match;
21
use function substr;
22
use function preg_replace_callback;
23
use function strpos;
24
use function bcmod;
25
26
/**
27
 * Validates wether the input is a valid IBAN or not
28
 *
29
 * @author Mazen Touati <[email protected]>
30
 */
31
final class IBAN extends AbstractRule
32
{
33
    private const COUNTRIES_CODES = [
34
        'AL' => '28',
35
        'AD' => '24',
36
        'AT' => '20',
37
        'AZ' => '28',
38
        'BH' => '22',
39
        'BE' => '16',
40
        'BA' => '20',
41
        'BR' => '29',
42
        'BG' => '22',
43
        'CR' => '21',
44
        'HR' => '21',
45
        'CY' => '28',
46
        'CZ' => '24',
47
        'DK' => '18',
48
        'DO' => '28',
49
        'EE' => '20',
50
        'FO' => '18',
51
        'FI' => '18',
52
        'FR' => '27',
53
        'GE' => '22',
54
        'DE' => '22',
55
        'GI' => '23',
56
        'GR' => '27',
57
        'GL' => '18',
58
        'GT' => '28',
59
        'HU' => '28',
60
        'IS' => '26',
61
        'IE' => '22',
62
        'IL' => '23',
63
        'IT' => '27',
64
        'JO' => '30',
65
        'KZ' => '20',
66
        'KW' => '30',
67
        'LV' => '21',
68
        'LB' => '28',
69
        'LI' => '21',
70
        'LT' => '20',
71
        'LU' => '20',
72
        'MK' => '19',
73
        'MT' => '31',
74
        'MR' => '27',
75
        'MU' => '30',
76
        'MD' => '24',
77
        'MC' => '27',
78
        'ME' => '22',
79
        'NL' => '18',
80
        'NO' => '15',
81
        'PK' => '24',
82
        'PL' => '28',
83
        'PS' => '29',
84
        'PT' => '25',
85
        'QA' => '29',
86
        'XK' => '20',
87
        'RO' => '24',
88
        'LC' => '32',
89
        'SM' => '27',
90
        'ST' => '25',
91
        'SA' => '24',
92
        'RS' => '22',
93
        'SC' => '31',
94
        'SK' => '24',
95
        'SI' => '19',
96
        'ES' => '24',
97
        'SE' => '24',
98
        'CH' => '21',
99
        'TL' => '23',
100
        'TN' => '24',
101
        'TR' => '26',
102
        'UA' => '29',
103
        'AE' => '23',
104
        'GB' => '22',
105
        'VG' => '24',
106
    ];
107
108
    private const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 16
    public function validate($input): bool
114
    {
115
116 16
        $iban = $this->validateStructure($input);
117
118 16
        if ($iban === false) {
119 7
            return false;
120
        }
121
122 10
        $countryCode = substr($iban, 0, 2);
123
124 10
        if (!isset(self::COUNTRIES_CODES[$countryCode]) || self::COUNTRIES_CODES[$countryCode] != strlen($iban)) {
125 6
            return false;
126
        }
127
128 5
        $checkSum = substr($iban, 2, 2);
129 5
        $account = substr($iban, 4);
130
131 5
        $reArrangedIBAN = $account.$countryCode.$checkSum;
132
133
        $integerIBAN = preg_replace_callback('/[A-Z]/', function ($match) {
134 5
            return strpos(self::ALPHABET, $match[0]) + 10;
135 5
        }, $reArrangedIBAN);
136
137 5
        $remainder = (int)bcmod($integerIBAN, '97');
138
139 5
        return $remainder === 1;
140
    }
141
142
    /**
143
     * Makes sure that the input is adhering to the IBAN structure
144
     *
145
     * @param  string $input Suggested IBAN to test
146
     *
147
     * @return bool|string Return false on failure or a sanitized IBAN
148
     */
149 16
    private function validateStructure($input)
150
    {
151 16
        if (!is_string($input)) {
0 ignored issues
show
introduced by
The condition is_string($input) is always true.
Loading history...
152 4
            return false;
153
        }
154
155 12
        $iban = str_replace(' ', '', strtoupper($input));
156
157 12
        if (!preg_match('/[A-Z0-9]{15,}/', $iban)) {
158 3
            return false;
159
        }
160
161 10
        return $iban;
162
    }
163
}
164