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

Modulo11   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 88.89%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
c 1
b 0
f 0
lcom 1
cbo 0
dl 0
loc 114
ccs 32
cts 36
cp 0.8889
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A validate() 0 8 1
A calculateDigits() 0 9 2
A calculateDigit() 0 14 3
A calculate() 0 15 3
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
}