Completed
Push — master ( e992db...e06598 )
by Ronan
12:16
created

Isin::validate()   C

Complexity

Conditions 9
Paths 73

Size

Total Lines 49
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 49
rs 5.7447
cc 9
eloc 32
nc 73
nop 1
1
<?php
2
3
namespace IsoCodes;
4
5
/**
6
 * Class Isin.
7
 */
8
class Isin implements IsoCodeInterface
9
{
10
    /**
11
     * Validate an ISIN (International Securities Identification Number, ISO 6166).
12
     *
13
     * @see https://en.wikipedia.org/wiki/International_Securities_Identification_Number#Examples
14
     *
15
     * @param string $isin ISIN to be validated
16
     *
17
     * @return bool true if ISIN is valid
18
     */
19
    public static function validate($isin)
20
    {
21
        $isin = strtoupper($isin);
22
        if (!preg_match('/^[A-Z]{2}[A-Z0-9]{9}[0-9]$/i', $isin)) {
23
            return false;
24
        }
25
26
        $base10 = $rightmost = '';
27
        $left = $right = [];
28
29
        $payload = substr($isin, 0, 11);
30
        $length = strlen($payload);
31
32
        // Converting letters to digits
33
        for ($i = 0; $i < $length; ++$i) {
34
            $digit = substr($payload, $i, 1);
35
            $base10 .= (string) base_convert($digit, 36, 10);
36
        }
37
        $checksum = substr($isin, 11, 1);
38
        $base10 = strrev($base10);
39
        $length = strlen($base10);
40
41
        // distinguishing leftmost from rightmost
42
        for ($i = $length - 1; $i >= 0; --$i) {
43
            $digit = substr($base10, $i, 1);
44
            $rightmost = 'left';
45
            if ((($length - $i) % 2) == 0) {
46
                $left[] = $digit;
47
            } else {
48
                $right[] = $digit;
49
                $rightmost = 'right';
50
            }
51
        }
52
53
        // Multiply the group containing the rightmost character
54
        $simple = ('left' === $rightmost) ? $right : $left;
55
        $doubled = ('left' === $rightmost) ? $left : $right;
56
        for ($i = 0; $i < count($doubled); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
57
            $digit = $doubled[$i] * 2;
58
            if ($digit > 9) {
59
                $digit = array_sum(str_split($digit));
60
            }
61
            $doubled[$i] = $digit;
62
        }
63
        $tot = array_sum($simple) + array_sum($doubled);
64
        $moduled = 10 - ($tot % 10);
65
66
        return (int) $moduled === (int) $checksum;
67
    }
68
}
69