Issues (11)

src/Algo/LUAlgorithm.php (1 issue)

1
<?php
2
3
namespace LeKoala\Tin\Algo;
4
5
use LeKoala\Tin\Util\DateUtil;
6
use LeKoala\Tin\Util\NumberUtil;
7
use LeKoala\Tin\Util\StringUtil;
8
use LeKoala\Tin\Exception\NegativeNumberException;
9
10
/**
11
 * Luxembourg
12
 */
13
class LUAlgorithm extends TINAlgorithm
14
{
15
    const LENGTH_1 = 13;
16
    const PATTERN_1 = "(1[89]|20)\\d{2}(0[1-9]|1[012])(0[1-9]|[1-2][0-9]|3[0-1])\\d{5}";
17
    private static $D = [
18
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
19
        [1, 2, 3, 4, 0, 6, 7, 8, 9, 5],
20
21
        [2, 3, 4, 0, 1, 7, 8, 9, 5, 6],
22
        [3, 4, 0, 1, 2, 8, 9, 5, 6, 7],
23
        [4, 0, 1, 2, 3, 9, 5, 6, 7, 8],
24
        [5, 9, 8, 7, 6, 0, 4, 3, 2, 1],
25
        [6, 5, 9, 8, 7, 1, 0, 4, 3, 2],
26
        [7, 6, 5, 9, 8, 2, 1, 0, 4, 3],
27
        [8, 7, 6, 5, 9, 3, 2, 1, 0, 4],
28
        [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
29
    ];
30
    private static $P = [
31
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
32
        [1, 5, 7, 6, 2, 8, 3, 0, 9, 4],
33
        [5, 8, 0, 3, 7, 9, 6, 1, 4, 2],
34
        [8, 9, 1, 6, 0, 4, 3, 5, 2, 7],
35
        [9, 4, 5, 3, 1, 2, 6, 8, 7, 0],
36
        [4, 2, 8, 6, 5, 7, 3, 9, 0, 1],
37
        [2, 7, 9, 3, 8, 0, 6, 4, 1, 5],
38
        [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]
39
    ];
40
41
    public function validate(string $tin)
42
    {
43
        if (!$this->isFollowLength1($tin)) {
44
            return StatusCode::INVALID_LENGTH;
45
        }
46
        if (!$this->isFollowPattern1($tin) || !$this->isValidDate($tin)) {
47
            return StatusCode::INVALID_PATTERN;
48
        }
49
        if (!$this->isFollowRules($tin)) {
50
            return StatusCode::INVALID_SYNTAX;
51
        }
52
        return StatusCode::VALID;
53
    }
54
55
    public function isFollowRules(string $tin)
56
    {
57
        return $this->isFollowLuxembourgRule1($tin) && $this->isFollowLuxembourgRule2($tin);
58
    }
59
60
    public function isFollowLength1(string $tin)
61
    {
62
        return StringUtil::isFollowLength($tin, self::LENGTH_1);
63
    }
64
65
    public function isFollowPattern1(string $tin)
66
    {
67
        return StringUtil::isFollowPattern($tin, self::PATTERN_1);
68
    }
69
70
    public function isFollowLuxembourgRule1(string $tin)
71
    {
72
        $c1 = StringUtil::digitAt($tin, 0);
73
        $c2 = StringUtil::digitAt($tin, 1);
74
        $c3 = StringUtil::digitAt($tin, 2);
75
        $c4 = StringUtil::digitAt($tin, 3);
76
        $c5 = StringUtil::digitAt($tin, 4);
77
        $c6 = StringUtil::digitAt($tin, 5);
78
        $c7 = StringUtil::digitAt($tin, 6);
79
        $c8 = StringUtil::digitAt($tin, 7);
80
        $c9 = StringUtil::digitAt($tin, 8);
81
        $c10 = StringUtil::digitAt($tin, 9);
82
        $c11 = StringUtil::digitAt($tin, 10);
83
        $c12 = StringUtil::digitAt($tin, 11);
84
        try {
85
            $sum = $c2 + $c4 + $c6 + $c8 + $c10 + $c12
86
                + NumberUtil::sumDigit($c1 * 2)
87
                + NumberUtil::sumDigit($c3 * 2)
88
                + NumberUtil::sumDigit($c5 * 2)
89
                + NumberUtil::sumDigit($c7 * 2)
90
                + NumberUtil::sumDigit($c9 * 2)
91
                + NumberUtil::sumDigit($c11 * 2);
92
            $remainderBy10 = $sum % 10;
93
            return $remainderBy10 == 0;
94
        } catch (NegativeNumberException $e) {
95
            return false;
96
        }
97
    }
98
99
    public function isFollowLuxembourgRule2(string $tin)
100
    {
101
        $listNumbers = [];
102
        for ($i = 12; $i >= 0; $i--) {
103
            if ($i != 11) {
104
                $listNumbers[] = StringUtil::digitAt($tin, $i);
105
            }
106
        }
107
        $check = 0;
108
        for ($j = 0; $j < count($listNumbers); $j++) {
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...
109
            $item = $listNumbers[$j];
110
            $p = self::$P[$j % 8][$item];
111
            $check = self::$D[$check][$p];
112
        }
113
        return $check == 0;
114
    }
115
116
    private function isValidDate(string $tin)
117
    {
118
        $year = intval(StringUtil::substring($tin, 0, 4));
119
        $month = intval(StringUtil::substring($tin, 4, 6));
120
        $day = intval(StringUtil::substring($tin, 6, 8));
121
        return DateUtil::validate($year, $month, $day);
122
    }
123
}
124