Completed
Push — master ( 94f056...38eb88 )
by z38
02:49
created

PostalAccount::calculateCheckDigit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Z38\SwissPayment;
4
5
use DOMDocument;
6
use InvalidArgumentException;
7
8
/**
9
 * PostalAccount holds details about a PostFinance account
10
 */
11
class PostalAccount implements AccountInterface
12
{
13
    const PATTERN = '/^[0-9]{2}-[1-9][0-9]{0,5}-[0-9]$/';
14
15
    /**
16
     * @var int
17
     */
18
    protected $prefix;
19
20
    /**
21
     * @var int
22
     */
23
    protected $number;
24
25
    /**
26
     * @var int
27
     */
28
    protected $checkDigit;
29
30
    /**
31
     * Constructor
32
     *
33
     * @param string $postalAccount
34
     *
35
     * @throws InvalidArgumentException When the account number is not valid.
36
     */
37 18
    public function __construct($postalAccount)
38
    {
39 18
        if (!preg_match(self::PATTERN, $postalAccount)) {
40 5
            throw new InvalidArgumentException('Postal account number is not properly formatted.');
41
        }
42
43 13
        $parts = explode('-', $postalAccount);
44 13
        if (!self::validateCheckDigit(sprintf('%02s%06s%s', $parts[0], $parts[1], $parts[2]))) {
45 3
            throw new InvalidArgumentException('Postal account number has an invalid check digit.');
46
        }
47
48 10
        $this->prefix = (int) $parts[0];
49 10
        $this->number = (int) $parts[1];
50 10
        $this->checkDigit = (int) $parts[2];
51 10
    }
52
53
    /**
54
     * Format the postal account number
55
     *
56
     * @return string The formatted account number
57
     */
58 9
    public function format()
59
    {
60 9
        return sprintf('%02d-%d-%d', $this->prefix, $this->number, $this->checkDigit);
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 2
    public function asDom(DOMDocument $doc)
67
    {
68 2
        $root = $doc->createElement('Id');
69 2
        $other = $doc->createElement('Othr');
70 2
        $other->appendChild($doc->createElement('Id', $this->format()));
71 2
        $root->appendChild($other);
72
73 2
        return $root;
74
    }
75
76
    /**
77
     * @internal
78
     */
79 3
    public static function validateCheckDigit($number)
80
    {
81 3
        $lookup = [0, 9, 4, 6, 8, 2, 7, 1, 3, 5];
82 3
        $carry = 0;
83 3
        for ($i = 0; $i < strlen($number) - 1; $i++) {
0 ignored issues
show
Performance Best Practice introduced by
Consider avoiding function calls on each iteration of the for loop.

If you have a function call in the test part of a for loop, this function is executed on each iteration. Often such a function, can be moved to the initialization part and be cached.

// count() is called on each iteration
for ($i=0; $i < count($collection); $i++) { }

// count() is only called once
for ($i=0, $c=count($collection); $i<$c; $i++) { }
Loading history...
84 3
            $carry = $lookup[($carry + $number[$i]) % 10];
85 3
        }
86
87 3
        return (10 - $carry) % 10 === (int) $number[strlen($number) - 1];
88
    }
89
}
90