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

AbstractAccessKey::loadFromKey()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 18
cts 18
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Brazanation\Documents\Sped;
4
5
use Brazanation\Documents\AbstractDocument;
6
use Brazanation\Documents\Cnpj;
7
use Brazanation\Documents\DigitCalculator;
8
9
/**
10
 * Class SpedAccessKey
11
 *
12
 * @package Brazanation\Documents
13
 * @property int $state
14
 * @property \DateTime $generatedAt
15
 * @property Cnpj $cnpj
16
 * @property int $model
17
 * @property int $sequence
18
 * @property int $invoiceNumber
19
 * @property int $controlNumber
20
 */
21
abstract class AbstractAccessKey extends AbstractDocument
22
{
23
    const LABEL = 'SpedAccessKey';
24
25
    const LENGTH = 44;
26
27
    const REGEX = '/([\d]{4})/';
28
29
    const MASK = '$1 ';
30
31
    protected $state;
32
33
    protected $generatedAt;
34
35
    protected $cnpj;
36
37
    protected $model;
38
39
    protected $sequence;
40
41
    protected $invoiceNumber;
42
43
    protected $controlNumber;
44
45
    /**
46
     * SpedAccessKey constructor.
47
     *
48
     * @param $accessKey
49
     */
50 81
    public function __construct($accessKey)
51
    {
52 81
        $accessKey = preg_replace('/\D/', '', $accessKey);
53 81
        parent::__construct($accessKey, static::LENGTH, 1, static::LABEL);
54 16
        $this->loadFromKey($accessKey);
55 16
    }
56
57 16
    private function loadFromKey($accessKey)
58
    {
59 16
        $startPosition = 0;
60 16
        $this->state = substr($accessKey, $startPosition, 2);
61
62 16
        $startPosition += 2;
63 16
        $this->generatedAt = \DateTime::createFromFormat('ymd H:i:s', substr($accessKey, $startPosition, 4) . '01 00:00:00');
64
65 16
        $startPosition += 4;
66 16
        $this->cnpj = new Cnpj(substr($accessKey, $startPosition, 14));
67
68 16
        $startPosition += 14;
69 16
        $this->model = new Model(substr($accessKey, $startPosition, 2));
70
71 16
        $startPosition += 2;
72 16
        $this->sequence = substr($accessKey, $startPosition, 3);
73
74 16
        $startPosition += 3;
75 16
        $this->invoiceNumber = substr($accessKey, $startPosition, 9);
76
77 16
        $startPosition += 9;
78 16
        $this->controlNumber = substr($accessKey, $startPosition, 9);
79
80 16
        $startPosition += 9;
81 16
        $this->digit = substr($accessKey, $startPosition, 1);
82 16
    }
83
84
    /**
85
     * Generates a valid Sped Access Key.
86
     *
87
     * @param int       $state         IBGE state code.
88
     * @param \DateTime $generatedAt   Year and month when invoice was created.
89
     * @param Cnpj      $cnpj          Cnpj from issuer.
90
     * @param Model     $model         Document model.
91
     * @param int       $sequence      Invoice sequence.
92
     * @param int       $invoiceNumber Invoice number.
93
     * @param int       $controlNumber Control number.
94
     *
95
     * @return AbstractAccessKey
96
     */
97 5
    protected static function generateKey(
98
        $state,
99
        \DateTime $generatedAt,
100
        Cnpj $cnpj,
101
        Model $model,
102
        $sequence,
103
        $invoiceNumber,
104
        $controlNumber
105
    ) {
106 5
        $yearMonth = $generatedAt->format('ym');
107 5
        $sequence = str_pad($sequence, 3, 0, STR_PAD_LEFT);
108 5
        $invoiceNumber = str_pad($invoiceNumber, 9, 0, STR_PAD_LEFT);
109 5
        $controlNumber = str_pad($controlNumber, 9, 0, STR_PAD_LEFT);
110
111 5
        $baseNumber = "{$state}{$yearMonth}{$cnpj}{$model}{$sequence}{$invoiceNumber}{$controlNumber}";
112
113 5
        $digit = self::calculateDigitFrom($baseNumber);
114
115 5
        $instance = new static("{$baseNumber}{$digit}");
116 5
        $instance->generatedAt = $generatedAt;
117
118 5
        return $instance;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124 5
    public function format()
125
    {
126 5
        return trim(preg_replace(self::REGEX, self::MASK, "{$this}"));
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132 61
    public function calculateDigit($baseNumber)
133
    {
134 61
        return self::calculateDigitFrom($baseNumber);
135
    }
136
137
    /**
138
     * Calculate check digit from base number.
139
     *
140
     * It is static because is used from generate static method.
141
     *
142
     * @param string $baseNumber Base numeric section to be calculate your digit.
143
     *
144
     * @return string
145
     */
146 61
    public static function calculateDigitFrom($baseNumber)
147
    {
148 61
        $calculator = new DigitCalculator($baseNumber);
149 61
        $calculator->useComplementaryInsteadOfModule();
150 61
        $calculator->withModule(DigitCalculator::MODULE_11);
151 61
        $digit = $calculator->calculate();
152
153 61
        return "{$digit}";
154
    }
155
}
156