Completed
Push — master ( 703546...76237a )
by Hannes
02:22
created

PrintingVisitor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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-19 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\Tree\Node;
28
use byrokrat\banking\AccountNumber;
29
use byrokrat\id\IdInterface;
30
use byrokrat\id\PersonalId;
31
use byrokrat\id\OrganizationId;
32
use Money\Money;
33
use Money\MoneyFormatter;
34
35
/**
36
 * Visitor that generates files to bgc from parse trees
37
 */
38
class PrintingVisitor extends Visitor
39
{
40
    const EOL = "\r\n";
41
42
    /**
43
     * @var ?Output
44
     */
45
    private $output;
46
47
    /**
48
     * @var MoneyFormatter
49
     */
50
    private $moneyFormatter;
51
52
    public function __construct(MoneyFormatter $moneyFormatter)
53
    {
54
        $this->moneyFormatter = $moneyFormatter;
55
    }
56
57
    public function setOutput(Output $output): void
58
    {
59
        $this->output = $output;
60
    }
61
62
    private function write(string $text): void
63
    {
64
        if ($this->output) {
65
            $this->output->write($text);
66
        }
67
    }
68
69
    public function beforeDate(Node $node): void
70
    {
71
        if ($node->getValue() instanceof \DateTimeInterface) {
72
            $this->write($node->getValue()->format('Ymd'));
73
        }
74
    }
75
76
    public function beforeImmediateDate(): void
77
    {
78
        $this->write('GENAST  ');
79
    }
80
81
    public function beforeText(Node $node): void
82
    {
83
        $this->write($node->getValue());
84
    }
85
86
    public function beforePayerNumber(Node $node): void
87
    {
88
        $this->write(str_pad($node->getValue(), 16, '0', STR_PAD_LEFT));
89
    }
90
91
    public function beforePayeeBgcNumber(Node $node): void
92
    {
93
        $this->write(str_pad($node->getValue(), 6, '0', STR_PAD_LEFT));
94
    }
95
96 View Code Duplication
    public function beforePayeeBankgiro(Node $node): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
97
    {
98
        if ($node->getValue() instanceof AccountNumber) {
99
            $account = $node->getValue();
100
            $this->write(
101
                str_pad($account->getSerialNumber() . $account->getCheckDigit(), 10, '0', STR_PAD_LEFT)
102
            );
103
        }
104
    }
105
106 View Code Duplication
    public function beforeAccount(Node $node): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
    {
108
        if ($node->getValue() instanceof AccountNumber) {
109
            $account = $node->getValue();
110
            $this->write(
111
                $account->getClearingNumber()
112
                . str_pad($account->getSerialNumber() . $account->getCheckDigit(), 12, '0', STR_PAD_LEFT)
113
            );
114
        }
115
    }
116
117
    public function beforeInterval(Node $node): void
118
    {
119
        if (!in_array((int)$node->getValue(), range('0', '8'))) {
120
            throw new RuntimeException('Interval must be between 0 and 8');
121
        }
122
123
        $this->write($node->getValue());
124
    }
125
126
    public function beforeRepetitions(Node $node): void
127
    {
128
        if (!ctype_digit($node->getValue()) || strlen($node->getValue()) > 3) {
129
            throw new RuntimeException("Invalid number of repitions: {$node->getValue()}");
130
        }
131
132
        $this->write(
133
            $node->getValue() ? str_pad($node->getValue(), 3, '0', STR_PAD_LEFT) : '   '
134
        );
135
    }
136
137
    public function beforeAmount(Node $node): void
138
    {
139
        $amount = $node->getValue();
140
141
        if ($amount instanceof Money) {
142
            if ($amount->getCurrency()->getCode() != 'SEK') {
143
                throw new RuntimeException('Printing visitor can only work with SEK');
144
            }
145
146
            if ($amount->greaterThan(Money::SEK('999999999999')) || $amount->lessThan(Money::SEK('-999999999999'))) {
147
                throw new RuntimeException('Amount must be between 9999999999.99 and -9999999999.99');
148
            }
149
150
            $this->write(
151
                str_pad($this->moneyFormatter->format($amount), 12, '0', STR_PAD_LEFT)
152
            );
153
        }
154
    }
155
156
    public function beforeStateId(Node $node): void
157
    {
158
        if ($node->getValue() instanceof PersonalId) {
159
            $this->write($node->getValue()->format('Ymdsk'));
160
        }
161
        if ($node->getValue() instanceof OrganizationId) {
162
            $this->write($node->getValue()->format('00Ssk'));
163
        }
164
    }
165
166
    public function beforeOpening(): void
167
    {
168
        $this->write('01');
169
    }
170
171
    public function beforeCreateMandateRequest(): void
172
    {
173
        $this->write('04');
174
    }
175
176
    public function beforeDeleteMandateRequest(): void
177
    {
178
        $this->write('03');
179
    }
180
181
    public function beforeAcceptDigitalMandateRequest(): void
182
    {
183
        $this->write('04');
184
    }
185
186
    public function beforeRejectDigitalMandateRequest(): void
187
    {
188
        $this->write('04');
189
    }
190
191
    public function beforeUpdateMandateRequest(): void
192
    {
193
        $this->write('05');
194
    }
195
196
    public function beforeIncomingPaymentRequest(): void
197
    {
198
        $this->write('82');
199
    }
200
201
    public function beforeOutgoingPaymentRequest(): void
202
    {
203
        $this->write('32');
204
    }
205
206
    public function beforeAmendmentRequest(): void
207
    {
208
        $this->write('23');
209
    }
210
211
    public function afterRecord(): void
212
    {
213
        $this->write(self::EOL);
214
    }
215
}
216