Completed
Pull Request — master (#26)
by Jean-Louis
02:13
created

PaymentInformation::asDom()   D

Complexity

Conditions 13
Paths 330

Size

Total Lines 65
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 51
CRAP Score 13.001

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 65
ccs 51
cts 52
cp 0.9808
rs 4.415
cc 13
eloc 45
nc 330
nop 1
crap 13.001

How to fix   Long Method    Complexity   

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
namespace Z38\SwissPayment\PaymentInformation;
4
5
use Z38\SwissPayment\BIC;
6
use Z38\SwissPayment\FinancialInstitutionInterface;
7
use Z38\SwissPayment\IBAN;
8
use Z38\SwissPayment\IID;
9
use Z38\SwissPayment\Money;
10
use Z38\SwissPayment\Text;
11
use Z38\SwissPayment\TransactionInformation\CreditTransfer;
12
13
/**
14
 * PaymentInformation contains a group of transactions as well as details about the debtor
15
 */
16
class PaymentInformation
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $id;
22
23
    /**
24
     * @var array
25
     */
26
    protected $transactions;
27
28
    /**
29
     * @var bool
30
     */
31
    protected $batchBooking;
32
33
    /**
34
     * @var string|null
35
     */
36
    protected $serviceLevel;
37
38
    /**
39
     * @var string|null
40
     */
41
    protected $localInstrument;
42
43
    /**
44
     * @var CategoryPurposeCode|null
45
     */
46
    protected $categoryPurpose;
47
48
    /**
49
     * @var \DateTime
50
     */
51
    protected $executionDate;
52
53
    /**
54
     * @var string
55
     */
56
    protected $debtorName;
57
58
    /**
59
     * @var FinancialInstitutionInterface
60
     */
61
    protected $debtorAgent;
62
63
    /**
64
     * @var IBAN
65
     */
66
    protected $debtorIBAN;
67
68
    /**
69
     * Constructor
70
     *
71
     * @param string  $id          Identifier of this group (should be unique within a message)
72
     * @param string  $debtorName  Name of the debtor
73
     * @param BIC|IID $debtorAgent BIC or IID of the debtor's financial institution
74
     * @param IBAN    $debtorIBAN  IBAN of the debtor's account
75
     *
76
     * @throws \InvalidArgumentException When any of the inputs contain invalid characters or are too long.
77
     */
78 4
    public function __construct($id, $debtorName, FinancialInstitutionInterface $debtorAgent, IBAN $debtorIBAN)
79
    {
80 4
        if (!$debtorAgent instanceof BIC && !$debtorAgent instanceof IID) {
81 1
            throw new \InvalidArgumentException('The debtor agent must be an instance of BIC or IID.');
82
        }
83
84 3
        $this->id = Text::assertIdentifier($id);
85 3
        $this->transactions = [];
86 3
        $this->batchBooking = true;
87 3
        $this->executionDate = new \DateTime();
88 3
        $this->debtorName = Text::assert($debtorName, 70);
89 3
        $this->debtorAgent = $debtorAgent;
90 3
        $this->debtorIBAN = $debtorIBAN;
91 3
    }
92
93
    /**
94
     * Adds a single transaction to this payment
95
     *
96
     * @param CreditTransfer $transaction The transaction to be added
97
     *
98
     * @return PaymentInformation This payment instruction
99
     */
100 3
    public function addTransaction(CreditTransfer $transaction)
101
    {
102 3
        $this->transactions[] = $transaction;
103
104 3
        return $this;
105
    }
106
107
    /**
108
     * Gets the number of transactions
109
     *
110
     * @return int Number of transactions
111
     */
112 2
    public function getTransactionCount()
113
    {
114 2
        return count($this->transactions);
115
    }
116
117
    /**
118
     * Gets the sum of transactions
119
     *
120
     * @return Money\Mixed Sum of transactions
121
     */
122 2
    public function getTransactionSum()
123
    {
124 2
        $sum = new Money\Mixed(0);
125
126 2
        foreach ($this->transactions as $transaction) {
127 2
            $sum = $sum->plus($transaction->getAmount());
128 2
        }
129
130 2
        return $sum;
131
    }
132
133
    /**
134
     * Sets the required execution date.
135
     * Where appropriate, the value data is automatically modified to the next possible banking/Post Office working day.
136
     *
137
     * @param \DateTime $executionDate
138
     *
139
     * @return PaymentInformation This payment instruction
140
     */
141
    public function setExecutionDate(\DateTime $executionDate)
142
    {
143
        $this->executionDate = $executionDate;
144
145
        return $this;
146
    }
147
148
    /**
149
     * Sets the batch booking option.
150
     * It is recommended that one payment instruction is created for each currency transferred.
151
     *
152
     * @param bool $batchBooking
153
     *
154
     * @return PaymentInformation This payment instruction
155
     */
156
    public function setBatchBooking($batchBooking)
157
    {
158
        $this->batchBooking = boolval($batchBooking);
159
160
        return $this;
161
    }
162
163
    /**
164
     * Checks whether the payment type information is included on B- or C-level
165
     *
166
     * @return bool true if it is included on B-level
167
     */
168 4
    public function hasPaymentTypeInformation()
169
    {
170 4
        return ($this->localInstrument !== null || $this->serviceLevel !== null || $this->categoryPurpose !== null);
171
    }
172
173
    /**
174
     * Gets the local instrument
175
     *
176
     * @return string|null The local instrument
177
     */
178
    public function getLocalInstrument()
179
    {
180
        return $this->localInstrument;
181
    }
182
183
    /**
184
     * Gets the service level
185
     *
186
     * @return string|null The service level
187
     */
188
    public function getServiceLevel()
189
    {
190
        return $this->serviceLevel;
191
    }
192
193
    /**
194
     * Sets the category purpose
195
     *
196
     * @param CategoryPurposeCode $categoryPurpose The category purpose
197
     *
198
     * @return PaymentInformation This payment instruction
199
     */
200 3
    public function setCategoryPurpose(CategoryPurposeCode $categoryPurpose)
201
    {
202 3
        $this->categoryPurpose = $categoryPurpose;
203
204 3
        return $this;
205
    }
206
207
    /**
208
     * Builds a DOM tree of this payment instruction
209
     *
210
     * @param \DOMDocument $doc
211
     *
212
     * @return \DOMElement The built DOM tree
213
     */
214 5
    public function asDom(\DOMDocument $doc)
215
    {
216 5
        $root = $doc->createElement('PmtInf');
217
218 5
        $root->appendChild(Text::xml($doc, 'PmtInfId', $this->id));
219 5
        $root->appendChild($doc->createElement('PmtMtd', 'TRF'));
220 5
        $root->appendChild($doc->createElement('BtchBookg', ($this->batchBooking ? 'true' : 'false')));
221
222 5
        if ($this->hasPaymentTypeInformation()) {
223 5
            $paymentType = $doc->createElement('PmtTpInf');
224 5
            $localInstrument = $this->localInstrument ?: $this->inferLocalInstrument();
225 5
            if ($localInstrument !== null) {
226 3
                $localInstrumentNode = $doc->createElement('LclInstrm');
227 3
                $localInstrumentNode->appendChild($doc->createElement('Prtry', $localInstrument));
228 3
                $paymentType->appendChild($localInstrumentNode);
229 3
            }
230 5
            $serviceLevel = $this->serviceLevel ?: $this->inferServiceLevel();
231 5
            if ($serviceLevel !== null) {
232 4
                $serviceLevelNode = $doc->createElement('SvcLvl');
233 4
                $serviceLevelNode->appendChild($doc->createElement('Cd', $serviceLevel));
234 4
                $paymentType->appendChild($serviceLevelNode);
235 4
            }
236 5
            if ($this->categoryPurpose !== null) {
237 3
                $categoryPurposeNode = $doc->createElement('CtgyPurp');
238 3
                $categoryPurposeNode->appendChild($this->categoryPurpose->asDom($doc));
239 3
                $paymentType->appendChild($categoryPurposeNode);
240 3
            }
241 5
            $root->appendChild($paymentType);
242 5
        }
243
244 5
        $root->appendChild($doc->createElement('ReqdExctnDt', $this->executionDate->format('Y-m-d')));
245
246 5
        $debtor = $doc->createElement('Dbtr');
247 5
        $debtor->appendChild(Text::xml($doc, 'Nm', $this->debtorName));
248 5
        $root->appendChild($debtor);
249
250 5
        $debtorAccount = $doc->createElement('DbtrAcct');
251 5
        $debtorAccountId = $doc->createElement('Id');
252 5
        $debtorAccountId->appendChild($doc->createElement('IBAN', $this->debtorIBAN->normalize()));
253 5
        $debtorAccount->appendChild($debtorAccountId);
254 5
        $root->appendChild($debtorAccount);
255
256 5
        $debtorAgent = $doc->createElement('DbtrAgt');
257 5
        $debtorAgent->appendChild($this->debtorAgent->asDom($doc));
258 5
        $root->appendChild($debtorAgent);
259
260 5
        if($this->serviceLevel === "SEPA"){
261 4
            $chargeBearer = $doc->createElement("ChrgBr", "SLEV");
262 4
            $root->appendChild($chargeBearer);
263 4
        }
264
265 5
        foreach ($this->transactions as $transaction) {
266 5
            if ($this->hasPaymentTypeInformation()) {
267 5
                if ($transaction->getLocalInstrument() !== $localInstrument) {
0 ignored issues
show
Bug introduced by
The variable $localInstrument does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
268
                    throw new \LogicException('You can not set the local instrument on B- and C-level.');
269
                }
270 5
                if ($transaction->getServiceLevel() !== $serviceLevel) {
0 ignored issues
show
Bug introduced by
The variable $serviceLevel does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
271 1
                    throw new \LogicException('You can not set the service level on B- and C-level.');
272
                }
273 4
            }
274 4
            $root->appendChild($transaction->asDom($doc, $this));
275 4
        }
276
277 4
        return $root;
278
    }
279
280 2
    private function inferServiceLevel()
281
    {
282 2
        if (!count($this->transactions)) {
283
            return null;
284
        }
285
286 2
        return $this->transactions[0]->getServiceLevel();
287
    }
288
289 2
    private function inferLocalInstrument()
290
    {
291 2
        if (!count($this->transactions)) {
292
            return null;
293
        }
294
295 2
        return $this->transactions[0]->getLocalInstrument();
296
    }
297
}
298