Completed
Push — master ( 9ba802...64cd16 )
by Antonio Oertel
05:26
created

AbstractDocument::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 8
cts 8
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 4
crap 1
1
<?php
2
3
namespace Brazanation\Documents;
4
5
use Brazanation\Documents\Exception\InvalidDocument as InvalidDocumentException;
6
use Brazanation\Documents\Exception\Readonly;
7
8
/**
9
 * Class AbstractDocument
10
 *
11
 * @package Brazanation\Documents
12
 *
13
 * @property string $number
14
 * @property string $digit
15
 * @property int $length
16
 * @property int $numberOfDigits
17
 * @property string $type
18
 */
19
abstract class AbstractDocument implements DigitCalculable, Formattable
20
{
21
    /**
22
     * @var string
23
     */
24
    protected $number;
25
26
    /**
27
     * @var string
28
     */
29
    protected $digit;
30
31
    /**
32
     * @var int
33
     */
34
    protected $length;
35
36
    /**
37
     * @var int
38
     */
39
    protected $numberOfDigits;
40
41
    /**
42
     * @var string
43
     */
44
    protected $type;
45
46
    /**
47
     * AbstractDocument constructor.
48
     *
49
     * @param string $number         Numeric section with checker digit.
50
     * @param int    $length         Max length of document.
51
     * @param int    $numberOfDigits Max length of checker digits.
52
     * @param string $type           Document name/type.
53
     */
54 636
    public function __construct($number, $length, $numberOfDigits, $type)
55
    {
56 636
        $this->type = (string) $type;
57 636
        $this->numberOfDigits = (int) $numberOfDigits;
58 636
        $this->length = (int) $length;
59 636
        $this->digit = $this->extractCheckerDigit($number);
60 636
        $this->validate($number);
61 436
        $this->number = $number;
62 436
    }
63
64 5
    public function __get($name)
65
    {
66 5
        return $this->$name;
67
    }
68
69
    public function __set($name, $value)
70
    {
71
        throw Readonly::notAllowed(static::class, $name);
72
    }
73
74
    /**
75
     * Check if document number is valid.
76
     *
77
     * @param string $number Numeric section with checker digit.
78
     *
79
     * @throws InvalidDocumentException when number is empty
80
     * @throws InvalidDocumentException when number is not valid
81
     */
82 636
    protected function validate($number)
83
    {
84 636
        if (empty($number)) {
85 72
            throw InvalidDocumentException::notEmpty($this->type);
86
        }
87 564
        if (!$this->isValid($number)) {
88 128
            throw InvalidDocumentException::isNotValid($this->type, $number);
89
        }
90 436
    }
91
92
    /**
93
     * Validates number is a valid.
94
     *
95
     * @param string $number Numeric section with checker digit.
96
     *
97
     * @return bool Returns true if it is a valid number, otherwise false.
98
     */
99 564
    protected function isValid($number)
100
    {
101 564
        $baseNumber = $this->extractBaseNumber($number);
102
103 564
        if (!$baseNumber) {
104 17
            return false;
105
        }
106
107 547
        $isRepeated = preg_match("/^[{$baseNumber[0]}]+$/", $baseNumber);
108
109 547
        if ($isRepeated) {
110 27
            return false;
111
        }
112
113 520
        $digit = $this->calculateDigit($baseNumber);
114
115 520
        return "$digit" === "{$this->digit}";
116
    }
117
118
    /**
119
     * Handle number to string.
120
     *
121
     * @return string
122
     */
123 435
    public function __toString()
124
    {
125 435
        return "{$this->number}";
126
    }
127
128
    /**
129
     * Extracts the base number document.
130
     *
131
     * @param string $number Number of document.
132
     *
133
     * @return string Returns only base number without checker digit.
134
     */
135 127
    protected function extractBaseNumber($number)
136
    {
137 127
        return substr($number, 0, -($this->numberOfDigits));
138
    }
139
140
    /**
141
     * Extracts the checker digit from document number.
142
     *
143
     * @param string $number Number of document.
144
     *
145
     * @return string Returns only checker digit.
146
     */
147 160
    protected function extractCheckerDigit($number)
148
    {
149 160
        return substr($number, -($this->numberOfDigits));
150
    }
151
}
152