GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( a61686...de9c1a )
by Xaf
26s
created

Iban::fromBbanAndCountry()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 8
nc 1
nop 2
1
<?php
2
3
namespace IbanGenerator;
4
5
use IbanGenerator\Bban\BbanInterface;
6
use IbanGenerator\Bban\SpainBban;
7
use InvalidArgumentException;
8
9
class Iban
10
{
11
    /**
12
     * @var BbanInterface
13
     */
14
    private $bban;
15
16
    /**
17
     * @var string
18
     */
19
    private $countryCode;
20
21
    /**
22
     * @var string
23
     */
24
    private $checkDigits;
25
26
    /**
27
     * @var array
28
     */
29
    private static $countriesSupported = [
30
        'ES' => SpainBban::class,
31
    ];
32
33
    /**
34
     * Iban constructor.
35
     *
36
     * @param string $countryCode
37
     * @param string $checkDigits
38
     * @param BbanInterface $bban
39
     *
40
     * @throws InvalidArgumentException
41
     */
42
    public function __construct($countryCode, $checkDigits, BbanInterface $bban)
43
    {
44
        $countryCode = strtoupper($countryCode);
45
        static::validateCountryCodeFormat($countryCode);
0 ignored issues
show
Bug introduced by
Since validateCountryCodeFormat() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateCountryCodeFormat() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
46
        static::validateCheckDigitsFormat($checkDigits);
0 ignored issues
show
Bug introduced by
Since validateCheckDigitsFormat() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateCheckDigitsFormat() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
47
        static::validateControlDigit($countryCode, $checkDigits, $bban);
0 ignored issues
show
Bug introduced by
Since validateControlDigit() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateControlDigit() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
48
        $this->countryCode = $countryCode;
49
        $this->checkDigits = $checkDigits;
50
        $this->bban = $bban;
51
    }
52
53
    /**
54
     * @param string $iban
55
     *
56
     * @throws InvalidArgumentException
57
     *
58
     * @return static
59
     */
60
    public static function fromString($iban)
61
    {
62
        if (! preg_match('/^[0-9A-Z]{16,34}$/', $iban)) {
63
            throw new InvalidArgumentException('Iban should be between 16 and 34 characters');
64
        }
65
66
        $countryCode = substr($iban, 0, 2);
67
        $checkDigits = substr($iban, 2, 2);
68
        $bbanString = substr($iban, 4);
69
70
        self::validateSupportedCountry($countryCode);
71
        $bbanClass = self::$countriesSupported[$countryCode];
72
73
        /**
74
         * @var BbanInterface
75
         */
76
        $bban = $bbanClass::fromString($bbanString);
77
78
        return new static($countryCode, $checkDigits, $bban);
79
    }
80
81
    /**
82
     * @param BbanInterface $bban
83
     * @param string $countryCode
84
     *
85
     * @throws InvalidArgumentException
86
     *
87
     * @return static
88
     */
89
    public static function fromBbanAndCountry(BbanInterface $bban, $countryCode)
90
    {
91
        static::validateCountryCodeFormat($countryCode);
0 ignored issues
show
Bug introduced by
Since validateCountryCodeFormat() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateCountryCodeFormat() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
92
        static::validateCountryCodeFormat($countryCode);
0 ignored issues
show
Bug introduced by
Since validateCountryCodeFormat() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateCountryCodeFormat() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
93
        static::validateSupportedCountry($countryCode);
0 ignored issues
show
Bug introduced by
Since validateSupportedCountry() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of validateSupportedCountry() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
94
95
        $checksum = self::validateChecksum($countryCode, '00', $bban);
96
        $checkDigit = 98 - (int) $checksum;
97
        $checkDigit = str_pad($checkDigit, 2, 0, STR_PAD_LEFT);
98
99
        return new static($countryCode, $checkDigit, $bban);
100
    }
101
102
    /**
103
     * @return string
104
     */
105
    public function countryCode()
106
    {
107
        return $this->countryCode;
108
    }
109
110
    /**
111
     * @return string
112
     */
113
    public function ibanCheckDigits()
114
    {
115
        return $this->checkDigits;
116
    }
117
118
    /**
119
     * @return string
120
     */
121
    public function bankCode()
122
    {
123
        return $this->bban->bankCode();
124
    }
125
126
    /**
127
     * @return string
128
     */
129
    public function branchCode()
130
    {
131
        return $this->bban->branchCode();
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    public function countryCheckDigits()
138
    {
139
        return $this->bban->checkDigits();
140
    }
141
142
    /**
143
     * @return string
144
     */
145
    public function accountNumber()
146
    {
147
        return $this->bban->accountNumber();
148
    }
149
150
    /**
151
     * @return string
152
     */
153
    public function __toString()
154
    {
155
        $bbanString = $this->bban;
156
157
        return $this->countryCode . $this->checkDigits . $bbanString;
158
    }
159
160
    /**
161
     * @param $countryCode
162
     *
163
     * @throws InvalidArgumentException
164
     */
165
    private static function validateCountryCodeFormat($countryCode)
166
    {
167
        if (! preg_match('/^[A-Z]{2}$/', $countryCode)) {
168
            throw new InvalidArgumentException('The country code should be 2 letters');
169
        }
170
    }
171
172
    /**
173
     * @param $checkDigits
174
     *
175
     * @throws InvalidArgumentException
176
     */
177
    private static function validateCheckDigitsFormat($checkDigits)
178
    {
179
        if (! preg_match('/^[\d]{2}$/', $checkDigits)) {
180
            throw new InvalidArgumentException('The IBAN checksum must be 2 numeric characters');
181
        }
182
    }
183
184
    /**
185
     * @param string $countryCode
186
     * @param string $checkDigits
187
     * @param BbanInterface $bban
188
     *
189
     * @throws InvalidArgumentException
190
     */
191
    private static function validateControlDigit(
192
        $countryCode,
193
        $checkDigits,
194
        BbanInterface $bban
195
    ) {
196
        $checksum = self::validateChecksum($countryCode, $checkDigits, $bban);
197
198
        if ($checksum !== '01') {
199
            throw new InvalidArgumentException('The IBAN checksum digits are not valid');
200
        }
201
    }
202
203
    /**
204
     * @param $countryCode
205
     *
206
     * @throws InvalidArgumentException
207
     */
208
    private static function validateSupportedCountry($countryCode)
209
    {
210
        if (!array_key_exists($countryCode, self::$countriesSupported)) {
211
            throw new InvalidArgumentException(
212
                sprintf(
213
                    'The country code %s is not supported',
214
                    $countryCode
215
                )
216
            );
217
        }
218
    }
219
220
    /**
221
     * @param $countryCode
222
     * @param $checkDigits
223
     * @param BbanInterface $bban
224
     *
225
     * @return string
226
     */
227
    private static function validateChecksum($countryCode, $checkDigits, BbanInterface $bban)
228
    {
229
        $rearranged = (string) $bban . $countryCode . $checkDigits;
230
        $digitsList = str_split($rearranged);
231
232
        $digitsList = array_map(['self', 'digitToInt'], $digitsList);
233
        $stringToCompute = implode('', $digitsList);
234
235
        $checksum = bcmod($stringToCompute, '97');
236
237
        return str_pad($checksum, 2, 0, STR_PAD_LEFT);
238
    }
239
240
    /**
241
     * @param string $value
242
     *
243
     * @return int
244
     */
245
    private static function digitToInt($value)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
246
    {
247
        if (is_numeric($value)) {
248
            return (int) $value;
249
        }
250
251
        return ord($value) - 55;
252
    }
253
}
254