Completed
Push — master ( f690c5...ceb8bd )
by Hannes
02:10
created

PrintingVisitor   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 0
Metric Value
dl 0
loc 178
rs 9.68
c 0
b 0
f 0
wmc 34
lcom 1
cbo 15

28 Methods

Rating   Name   Duplication   Size   Complexity  
A setOutput() 0 4 1
A beforeDate() 0 5 1
A beforeImmediateDate() 0 4 1
A beforeText() 0 4 1
A beforePayeeBgcNumber() 0 4 1
A beforePayeeBankgiro() 0 6 1
A beforePayerNumber() 0 4 1
A beforeAccount() 0 9 1
A beforeInterval() 0 4 1
A beforeAmount() 0 14 3
A beforeStateId() 0 10 3
A assertAttribute() 0 6 3
A beforeOpening() 0 4 1
A afterOpening() 0 4 1
A beforeCreateMandateRequest() 0 4 1
A afterCreateMandateRequest() 0 4 1
A beforeDeleteMandateRequest() 0 4 1
A afterDeleteMandateRequest() 0 4 1
A beforeAcceptDigitalMandateRequest() 0 4 1
A afterAcceptDigitalMandateRequest() 0 4 1
A beforeRejectDigitalMandateRequest() 0 4 1
A afterRejectDigitalMandateRequest() 0 4 1
A beforeUpdateMandateRequest() 0 4 1
A afterUpdateMandateRequest() 0 4 1
A beforeIncomingPaymentRequest() 0 4 1
A afterIncomingPaymentRequest() 0 4 1
A beforeOutgoingPaymentRequest() 0 4 1
A afterOutgoingPaymentRequest() 0 4 1
1
<?php
2
/**
3
 * This file is part of byrokrat\autogiro.
4
 *
5
 * byrokrat\autogiro is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as published
7
 * by the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * byrokrat\autogiro is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with byrokrat\autogiro. If not, see <http://www.gnu.org/licenses/>.
17
 *
18
 * Copyright 2016-18 Hannes Forsgård
19
 */
20
21
declare(strict_types = 1);
22
23
namespace byrokrat\autogiro\Writer;
24
25
use byrokrat\autogiro\Visitor\Visitor;
26
use byrokrat\autogiro\Exception\RuntimeException;
27
use byrokrat\autogiro\Exception\LogicException;
28
use byrokrat\autogiro\Tree\Node;
29
use byrokrat\autogiro\Tree\Date;
30
use byrokrat\autogiro\Tree\Text;
31
use byrokrat\autogiro\Tree\Number;
32
use byrokrat\autogiro\Tree\PayeeBankgiro;
33
use byrokrat\autogiro\Tree\Account;
34
use byrokrat\autogiro\Tree\Amount;
35
use byrokrat\autogiro\Tree\Interval;
36
use byrokrat\autogiro\Tree\StateId;
37
use byrokrat\amount\Currency\SEK;
38
use byrokrat\banking\AccountNumber;
39
use byrokrat\id\IdInterface;
40
use byrokrat\id\PersonalId;
41
use byrokrat\id\OrganizationId;
42
43
/**
44
 * Visitor that generates files to bgc from parse trees
45
 */
46
class PrintingVisitor extends Visitor
47
{
48
    /**
49
     * End-of-line chars used when generating files
50
     */
51
    const EOL = "\r\n";
52
53
    /**
54
     * @var Output
55
     */
56
    private $output;
57
58
    public function setOutput(Output $output): void
59
    {
60
        $this->output = $output;
61
    }
62
63
    public function beforeDate(Date $node): void
64
    {
65
        $this->assertAttribute($node, 'date', \DateTimeInterface::CLASS);
66
        $this->output->write($node->getAttribute('date')->format('Ymd'));
67
    }
68
69
    public function beforeImmediateDate(): void
70
    {
71
        $this->output->write('GENAST  ');
72
    }
73
74
    public function beforeText(Text $node): void
75
    {
76
        $this->output->write($node->getValue());
77
    }
78
79
    public function beforePayeeBgcNumber(Number $node): void
80
    {
81
        $this->output->write(str_pad($node->getValue(), 6, '0', STR_PAD_LEFT));
82
    }
83
84
    public function beforePayeeBankgiro(PayeeBankgiro $node): void
85
    {
86
        $this->assertAttribute($node, 'account', AccountNumber::CLASS);
87
        $number = $node->getAttribute('account')->getSerialNumber() . $node->getAttribute('account')->getCheckDigit();
88
        $this->output->write(str_pad($number, 10, '0', STR_PAD_LEFT));
89
    }
90
91
    public function beforePayerNumber(Number $node): void
92
    {
93
        $this->output->write(str_pad($node->getValue(), 16, '0', STR_PAD_LEFT));
94
    }
95
96
    public function beforeAccount(Account $node): void
97
    {
98
        $this->assertAttribute($node, 'account', AccountNumber::CLASS);
99
        $number = $node->getAttribute('account')->getSerialNumber() . $node->getAttribute('account')->getCheckDigit();
100
        $this->output->write(
101
            $node->getAttribute('account')->getClearingNumber()
102
            . str_pad($number, 12, '0', STR_PAD_LEFT)
103
        );
104
    }
105
106
    public function beforeInterval(Interval $node): void
107
    {
108
        $this->output->write($node->getValue());
109
    }
110
111
    public function beforeAmount(Amount $node): void
112
    {
113
        $this->assertAttribute($node, 'amount', SEK::CLASS);
114
115
        $amount = $node->getAttribute('amount');
116
117
        if ($amount->isGreaterThan(new SEK('9999999999.99')) || $amount->isLessThan(new SEK('-9999999999.99'))) {
118
            throw new RuntimeException('Amount must be between 9999999999.99 and -9999999999.99');
119
        }
120
121
        $this->output->write(
122
            str_pad($amount->getSignalString(), 12, '0', STR_PAD_LEFT)
123
        );
124
    }
125
126
    public function beforeStateId(StateId $node): void
127
    {
128
        $this->assertAttribute($node, 'id', IdInterface::CLASS);
129
        if ($node->getAttribute('id') instanceof PersonalId) {
130
            $this->output->write($node->getAttribute('id')->format('Ymdsk'));
131
        }
132
        if ($node->getAttribute('id') instanceof OrganizationId) {
133
            $this->output->write($node->getAttribute('id')->format('00Ssk'));
134
        }
135
    }
136
137
    private function assertAttribute(Node $node, string $attr, string $classname): void
138
    {
139
        if (!$node->hasAttribute($attr) || !$node->getAttribute($attr) instanceof $classname) {
140
            throw new LogicException("Failing attribute '$attr' in {$node->getName()}");
141
        }
142
    }
143
144
    public function beforeOpening(): void
145
    {
146
        $this->output->write('01');
147
    }
148
149
    public function afterOpening(): void
150
    {
151
        $this->output->write(self::EOL);
152
    }
153
154
    public function beforeCreateMandateRequest(): void
155
    {
156
        $this->output->write('04');
157
    }
158
159
    public function afterCreateMandateRequest(): void
160
    {
161
        $this->output->write(self::EOL);
162
    }
163
164
    public function beforeDeleteMandateRequest(): void
165
    {
166
        $this->output->write('03');
167
    }
168
169
    public function afterDeleteMandateRequest(): void
170
    {
171
        $this->output->write(self::EOL);
172
    }
173
174
    public function beforeAcceptDigitalMandateRequest(): void
175
    {
176
        $this->output->write('04');
177
    }
178
179
    public function afterAcceptDigitalMandateRequest(): void
180
    {
181
        $this->output->write(self::EOL);
182
    }
183
184
    public function beforeRejectDigitalMandateRequest(): void
185
    {
186
        $this->output->write('04');
187
    }
188
189
    public function afterRejectDigitalMandateRequest(): void
190
    {
191
        $this->output->write(self::EOL);
192
    }
193
194
    public function beforeUpdateMandateRequest(): void
195
    {
196
        $this->output->write('05');
197
    }
198
199
    public function afterUpdateMandateRequest(): void
200
    {
201
        $this->output->write(self::EOL);
202
    }
203
204
    public function beforeIncomingPaymentRequest(): void
205
    {
206
        $this->output->write('82');
207
    }
208
209
    public function afterIncomingPaymentRequest(): void
210
    {
211
        $this->output->write(self::EOL);
212
    }
213
214
    public function beforeOutgoingPaymentRequest(): void
215
    {
216
        $this->output->write('32');
217
    }
218
219
    public function afterOutgoingPaymentRequest(): void
220
    {
221
        $this->output->write(self::EOL);
222
    }
223
}
224