Completed
Push — master ( dc2855...0a5beb )
by z38
03:37
created

IBAN::asDom()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Z38\SwissPayment;
4
5
use DOMDocument;
6
7
/**
8
 * IBAN
9
 */
10
class IBAN implements AccountInterface
11
{
12
    const MAX_LENGTH = 34;
13
    const PATTERN = '/^[A-Z]{2,2}[0-9]{2,2}[A-Z0-9]{1,30}$/';
14
15
    /**
16
     * @var string
17
     */
18
    protected $iban;
19
20
    /**
21
     * Constructor
22
     *
23
     * @param string $iban
24
     *
25
     * @throws \InvalidArgumentException When the IBAN does contain invalid characters or the checksum calculation fails.
26
     */
27 8
    public function __construct($iban)
28
    {
29 8
        $cleanedIban = str_replace(' ', '', strtoupper($iban));
30 8
        if (!preg_match(self::PATTERN, $cleanedIban)) {
31 1
            throw new \InvalidArgumentException('IBAN is not properly formatted.');
32
        }
33 7
        if (!self::check($cleanedIban)) {
34 1
            throw new \InvalidArgumentException('IBAN has an invalid checksum.');
35
        }
36
37 6
        $this->iban = $cleanedIban;
38 6
    }
39
40
    /**
41
     * Format the IBAN either in a human-readable manner
42
     *
43
     * @return string The formatted IBAN
44
     */
45 1
    public function format()
46
    {
47 1
        $parts = str_split($this->iban, 4);
48
49 1
        return implode(' ', $parts);
50
    }
51
52
    /**
53
     * Normalize the IBAN
54
     *
55
     * @return string The normalized IBAN
56
     */
57 3
    public function normalize()
58
    {
59 3
        return $this->iban;
60
    }
61
62
    /**
63
     * Gets the country
64
     *
65
     * @return string A ISO 3166-1 alpha-2 country code
66
     */
67 6
    public function getCountry()
68
    {
69 6
        return substr($this->iban, 0, 2);
70
    }
71
72
    /**
73
     * Checks whether the checksum of an IBAN is correct
74
     *
75
     * @param string $iban
76
     *
77
     * @return bool true if checksum is correct, false otherwise
78
     */
79 3
    protected static function check($iban)
80
    {
81 3
        $chars = str_split(substr($iban, 4).substr($iban, 0, 4));
82 3
        $length = count($chars);
83 3
        for ($i = 0; $i < $length; $i++) {
84 3
            $code = ord($chars[$i]);
85 3
            if ($code >= 65 && $code <= 90) { // A-Z
86 3
                $chars[$i] = $code - 65 + 10;
87 3
            }
88 3
        }
89 3
        $prepared = implode($chars);
90
91 3
        $r = '';
92 3
        $rLength = 0;
93 3
        $i = 0;
94 3
        $length = strlen($prepared);
95 3
        while ($i < $length) {
96 3
            $d = $r.substr($prepared, $i, 9 - $rLength);
97 3
            $i += 9 - $rLength;
98 3
            $r = $d % 97;
99 3
            $rLength = 1 + ($r >= 10);
100 3
        }
101
102 3
        return ($r == 1);
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 2
    public function asDom(DOMDocument $doc)
109
    {
110 2
        $xml = $doc->createElement('Id');
111 2
        $xml->appendChild($doc->createElement('IBAN', $this->normalize()));
112
113 2
        return $xml;
114
    }
115
116
    /**
117
     * Returns a string representation.
118
     *
119
     * @return string The string representation.
120
     */
121 3
    public function __toString()
122
    {
123 3
        return $this->format();
124
    }
125
}
126