NISSValidatorHelper::checkFormat()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 4
c 2
b 0
f 0
dl 0
loc 8
rs 10
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Helip\NISS\Helpers;
4
5
use Helip\NISS\Exception\InvalidControlNumberException;
6
use Helip\NISS\Exception\InvalidFormatException;
7
use Helip\NISS\Exception\InvalidNissExceptionInterface;
8
9
/**
10
 * NISSValidatorHelper
11
 *
12
 * This class provides static methods for validating Belgian National Identification
13
 * Numbers (NISS), including NISS BIS and TER.
14
 */
15
class NISSValidatorHelper
16
{
17
    /**
18
     * Check if a NISS number is valid.
19
     * Check the length and the control number.
20
     *
21
     * @param string $niss (11 digits only)
22
     *
23
     * @return bool
24
     */
25
    public static function isValid(string $niss): bool
26
    {
27
        try {
28
29
            self::assertValid($niss);
30
        } catch (InvalidNissExceptionInterface $e) {
31
            return false;
32
        }
33
        return true;
34
    }
35
36
    /**
37
     * Assert that a NISS number is valid, throwing an exception if it is not.
38
     * 
39
     * @param string $niss (11 digits only)
40
     * 
41
     * @throws InvalidArgumentException
42
     */
43
    public static function assertValid(string $niss): void
44
    {
45
        $niss = self::clean($niss);
46
47
        self::checkFormat($niss);
48
        self::checkControlNumberRange($niss);
49
        self::checkControlNumber($niss);
50
    }
51
52
    /**
53
     * Clean a NISS number removing all non numeric characters.
54
     *
55
     * @param string $niss
56
     *
57
     * @return string
58
     */
59
    public static function clean(string $niss): string
60
    {
61
        // remove all non numeric characters
62
        return preg_replace('/[^0-9]/', '', $niss);
63
    }
64
65
    private static function checkFormat(string $niss): void
66
    {
67
        if (strlen($niss) !== 11) {
68
            throw new InvalidFormatException('NISS must be 11 digits long');
69
        }
70
71
        if ($niss === '00000000000') {
72
            throw new InvalidFormatException('NISS cannot be 00000000000');
73
        }
74
    }
75
76
    private static function checkControlNumber(string $niss): void
77
    {
78
        // Get the niss without the control number (first 9 digits)
79
        $numberWithoutControlNumber = substr($niss, 0, 9);
80
81
        // Get the control number (last 2 digits)
82
        $controlNumber = (int) substr($niss, 9, 2);
83
84
        // Check that the check digits are between 0 and 97
85
        $expectedCheckDigits = (int) (97 - (int) $numberWithoutControlNumber % 97);
86
87
        // Get the niss whith a 2 in front of the number (born after 1999)
88
        $numberWithTwo = '2' . $numberWithoutControlNumber;
89
90
        // Check that the check digits are between 0 and 97 (born after 1999)
91
        $expectedCheckDigitsWithTwo = (int) (97 - (int) $numberWithTwo % 97);
92
93
        if ($controlNumber != $expectedCheckDigits && $controlNumber != $expectedCheckDigitsWithTwo) {
94
            throw new InvalidControlNumberException();
95
        }
96
    }
97
98
    private static function checkControlNumberRange(string $niss): void
99
    {
100
        // Check that the control number is between 0 and 97
101
        $controlNumber = (int) substr($niss, 9, 2);
102
        if ($controlNumber < 0 || $controlNumber > 97) {
103
            throw new InvalidControlNumberException();
104
        }
105
    }
106
}
107