Completed
Pull Request — master (#24)
by Antonio Oertel
02:26
created

AbstractDocument::__get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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