Passed
Push — master ( 3b9ce6...298e9b )
by Hannes
02:09
created

ImportXmlMandateConsole::processMandate()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 102
Code Lines 66

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 66
nc 4
nop 2
dl 0
loc 102
rs 8.7418
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of byrokrat\giroapp.
4
 *
5
 * byrokrat\giroapp 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\giroapp 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\giroapp. If not, see <http://www.gnu.org/licenses/>.
17
 *
18
 * Copyright 2016-20 Hannes Forsgård
19
 */
20
21
declare(strict_types = 1);
22
23
namespace byrokrat\giroapp\Console;
24
25
use byrokrat\giroapp\CommandBus\AddDonor;
26
use byrokrat\giroapp\CommandBus\UpdateAttribute;
27
use byrokrat\giroapp\CommandBus\UpdateName;
28
use byrokrat\giroapp\CommandBus\UpdatePostalAddress;
29
use byrokrat\giroapp\CommandBus\UpdateState;
30
use byrokrat\giroapp\DependencyInjection;
31
use byrokrat\giroapp\Domain\MandateSources;
32
use byrokrat\giroapp\Domain\NewDonor;
33
use byrokrat\giroapp\Domain\PostalAddress;
34
use byrokrat\giroapp\Domain\State\NewMandate;
35
use byrokrat\giroapp\Event\LogEvent;
36
use byrokrat\giroapp\Filesystem\FilesystemInterface;
37
use byrokrat\giroapp\Filesystem\Sha256File;
38
use byrokrat\giroapp\Validator;
39
use byrokrat\giroapp\Xml\XmlMandate;
40
use byrokrat\giroapp\Xml\XmlMandateParser;
41
use byrokrat\giroapp\Xml\XmlObject;
42
use Money\Money;
43
use Symfony\Component\Console\Command\Command;
44
use Symfony\Component\Console\Input\InputArgument;
45
use Symfony\Component\Console\Input\InputInterface;
46
use Symfony\Component\Console\Output\OutputInterface;
47
use Symfony\Component\Console\Helper\QuestionHelper;
48
use Streamer\Stream;
49
50
final class ImportXmlMandateConsole implements ConsoleInterface
51
{
52
    use DependencyInjection\AccountFactoryProperty,
53
        DependencyInjection\CommandBusProperty,
54
        DependencyInjection\DispatcherProperty,
55
        DependencyInjection\DonorRepositoryProperty,
56
        DependencyInjection\IdFactoryProperty;
57
58
    /** @var FilesystemInterface */
59
    private $filesystem;
60
61
    /** @var XmlMandateParser */
62
    private $xmlMandateParser;
63
64
    public function __construct(FilesystemInterface $filesystem, XmlMandateParser $xmlMandateParser)
65
    {
66
        $this->filesystem = $filesystem;
67
        $this->xmlMandateParser = $xmlMandateParser;
68
    }
69
70
    public function configure(Command $command): void
71
    {
72
        $command
73
            ->setName('import-xml-mandate')
74
            ->setDescription('Import an xml formatted mandate')
75
            ->setHelp('Import one or more xml formatted mandates from autogirot')
76
            ->addArgument(
77
                'path',
78
                InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
79
                'One or more paths to import'
80
            )
81
        ;
82
    }
83
84
    public function execute(InputInterface $input, OutputInterface $output): void
85
    {
86
        $files = [];
87
88
        $paths = (array)$input->getArgument('path');
89
90
        if (empty($paths) && defined('STDIN')) {
91
            $files[] = new Sha256File('STDIN', (new Stream(STDIN))->getContent());
92
        }
93
94
        foreach ($paths as $path) {
95
            if ($this->filesystem->isFile($path)) {
96
                $files[] = $this->filesystem->readFile($path);
97
                continue;
98
            }
99
100
            foreach ($this->filesystem->readDir($path) as $file) {
101
                $files[] = $file;
102
            }
103
        }
104
105
        $inputReader = new Helper\InputReader($input, $output, new QuestionHelper);
106
107
        foreach ($files as $file) {
108
            $this->dispatcher->dispatch(new LogEvent("Importing from XML file {$file->getFilename()}"));
109
110
            $xmlObject = XmlObject::fromString($file->getContent());
111
112
            foreach ($this->xmlMandateParser->parseXml($xmlObject) as $xmlMandate) {
0 ignored issues
show
Bug introduced by
It seems like $xmlObject can also be of type null; however, parameter $xmlRoot of byrokrat\giroapp\Xml\XmlMandateParser::parseXml() does only seem to accept byrokrat\giroapp\Xml\XmlObject, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
            foreach ($this->xmlMandateParser->parseXml(/** @scrutinizer ignore-type */ $xmlObject) as $xmlMandate) {
Loading history...
113
                $this->dispatcher->dispatch(new LogEvent("Importing new mandate"));
114
                $this->processMandate($xmlMandate, $inputReader);
115
            }
116
        }
117
    }
118
119
    private function processMandate(XmlMandate $xmlMandate, Helper\InputReader $inputReader): void
120
    {
121
        $inputReader->readOptionalInput(
122
            'donorId',
123
            $xmlMandate->donorId->format('CS-sk'),
124
            new Validator\ValidatorCollection(
125
                new Validator\IdValidator,
126
                new Validator\CallbackValidator(function (string $value) use (&$xmlMandate) {
127
                    $xmlMandate->donorId = $this->idFactory->createId($value);
128
                })
129
            )
130
        );
131
132
        $xmlMandate->payerNumber = $inputReader->readOptionalInput(
133
            'payer-number',
134
            $xmlMandate->payerNumber ?: $xmlMandate->donorId->format('Ssk'),
135
            new Validator\PayerNumberValidator
136
        );
137
138
        $inputReader->readOptionalInput(
139
            'account',
140
            $xmlMandate->account->prettyprint(),
141
            new Validator\ValidatorCollection(
142
                new Validator\AccountValidator,
143
                new Validator\CallbackValidator(function (string $value) use (&$xmlMandate) {
144
                    $xmlMandate->account = $this->accountFactory->createAccount($value);
145
                })
146
            )
147
        );
148
149
        $xmlMandate->name = $inputReader->readOptionalInput(
150
            'name',
151
            $xmlMandate->name,
152
            new Validator\ValidatorCollection(
153
                new Validator\StringValidator,
154
                new Validator\NotEmptyValidator
155
            )
156
        );
157
158
        $xmlMandate->address['line1'] = $inputReader->readOptionalInput(
159
            'address1',
160
            $xmlMandate->address['line1'],
161
            new Validator\StringValidator
162
        );
163
164
        $xmlMandate->address['line2'] = $inputReader->readOptionalInput(
165
            'address2',
166
            $xmlMandate->address['line2'],
167
            new Validator\StringValidator
168
        );
169
170
        $xmlMandate->address['line3'] = $inputReader->readOptionalInput(
171
            'address3',
172
            $xmlMandate->address['line3'],
173
            new Validator\StringValidator
174
        );
175
176
        $xmlMandate->address['postalCode'] = $inputReader->readOptionalInput(
177
            'postal-code',
178
            $xmlMandate->address['postalCode'],
179
            new Validator\PostalCodeValidator
180
        );
181
182
        $xmlMandate->address['postalCity'] = $inputReader->readOptionalInput(
183
            'postal-city',
184
            $xmlMandate->address['postalCity'],
185
            new Validator\StringValidator
186
        );
187
188
        foreach ($xmlMandate->attributes as $attrKey => $attrValue) {
189
            $xmlMandate->attributes[$attrKey] =
190
                $inputReader->readOptionalInput("attribute.$attrKey", $attrValue, new Validator\StringValidator);
191
        }
192
193
        $this->commandBus->handle(
194
            new AddDonor(
195
                new NewDonor(
196
                    MandateSources::MANDATE_SOURCE_ONLINE_FORM,
197
                    $xmlMandate->payerNumber,
198
                    $xmlMandate->account,
199
                    $xmlMandate->donorId,
200
                    Money::SEK('0')
201
                )
202
            )
203
        );
204
205
        $donor = $this->donorRepository->requireByPayerNumber($xmlMandate->payerNumber);
206
207
        $this->commandBus->handle(new UpdateState($donor, NewMandate::getStateId(), 'Mandate added from xml'));
208
209
        $this->commandBus->handle(new UpdateName($donor, $xmlMandate->name));
210
211
        $this->commandBus->handle(new UpdatePostalAddress($donor, new PostalAddress(
212
            $xmlMandate->address['line1'],
213
            $xmlMandate->address['line2'],
214
            $xmlMandate->address['line3'],
215
            $xmlMandate->address['postalCode'],
216
            $xmlMandate->address['postalCity'],
217
        )));
218
219
        foreach ($xmlMandate->attributes as $attrKey => $attrValue) {
220
            $this->commandBus->handle(new UpdateAttribute($donor, $attrKey, $attrValue));
221
        }
222
    }
223
}
224