Completed
Push — master ( 9a2c34...266891 )
by Antonio Oertel
04:56
created

Modulo11::checkDigits()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Brazanation\Documents;
4
5
final class Modulo11
6
{
7
    /**
8
     * Number of digits to be calculated.
9
     * @var int
10
     */
11
    protected $digitsCount;
12
13
    /**
14
     * Max size of factor.
15
     * @var int
16
     */
17
    protected $maxMultiplier;
18
19
    /**
20
     * When calculated digit is equals 10 it will be converted to X.
21
     * @var bool
22
     */
23
    private $convertX;
24
25
    /**
26
     * Modulo11 constructor.
27
     *
28
     * @param int $numberOfDigits Number of digits to be calculated.
29
     * @param int $multiplierLimit Max size of factor.
30
     * @param bool $convertX When calculated digit is equals 10 it will be converted to X.
31
     */
32 12
    public function __construct($numberOfDigits, $multiplierLimit, $convertX = true)
33
    {
34 12
        assert(is_int($numberOfDigits), 'Number of digits must be integer');
35 12
        assert(is_int($multiplierLimit), 'Number of digits must be integer');
36 12
        $this->digitsCount = (int) $numberOfDigits;
37 12
        $this->maxMultiplier = (int) $multiplierLimit;
38 12
        $this->convertX = $convertX;
39 12
    }
40
41
    /**
42
     * Generic validation for many type of numbers.
43
     *
44
     * @param string $number A number to be validate.
45
     *
46
     * @return boolean
47
     */
48 12
    public function validate($number)
49
    {
50 12
        $number = preg_replace('/[^\dX]/i', '', $number);
51 12
        $baseNumber = substr($number, 0, (-1 * $this->digitsCount));
52 12
        $checkDigits = $this->calculateDigits($baseNumber);
53 12
        $digits = substr($number, (-1 * $this->digitsCount));
54 12
        return ($digits === $checkDigits);
55
    }
56
57
    /**
58
     * Calculates digits from base numbers (without last N digits).
59
     *
60
     * @param string $number Base number to be calculated.
61
     *
62
     * @return string Returns N calculated digits.
63
     */
64 12
    private function calculateDigits($number)
65
    {
66 12
        $numberOfIterations = $this->digitsCount;
67 12
        while (--$numberOfIterations >= 0) {
68 12
            $digit = $this->calculateDigit($number);
69 12
            $number .= $digit;
70
        }
71 12
        return substr($number, (-1 * $this->digitsCount));
72
    }
73
74
    /**
75
     * Calculates digit from base number (without last digit).
76
     *
77
     * @param string $number Base number to be calculated.
78
     *
79
     * @return string Returns a calculated digit.
80
     */
81 12
    private function calculateDigit($number)
82
    {
83 12
        $sum = $this->calculate($number);
84
85 12
        if ($this->convertX) {
86 12
            return (($sum * 10) % 11) % 10;
87
        }
88
89
        $digit = $sum % 11;
90
        if ($digit == 10) {
91
            $digit = 'X';
92
        }
93
        return $digit;
94
    }
95
96
    /**
97
     * Apply factor in each base number and calculates the sum of their.
98
     *
99
     * @param string $baseNumber Base number (number without N digits)
100
     *
101
     * @return int Returns the sum of base numbers with factors applied.
102
     */
103 12
    protected function calculate($baseNumber)
104
    {
105 12
        $coefficient = 2;
106 12
        $digits = str_split(strrev($baseNumber));
107
108 12
        $sum = 0;
109 12
        foreach ($digits as $digit) {
110 12
            $sum += ($coefficient * intval($digit));
111 12
            if (++$coefficient > $this->maxMultiplier) {
112 12
                $coefficient = 2;
113
            }
114
        }
115
116 12
        return $sum;
117
    }
118
}