Lines
100.00%
66 / 66
Functions and Methods
100.00%
3 / 3
Classes and Traits
100.00%
1 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| VubMailParser | 100.00% | 66 / 66 | 100.00% | 3 / 3 | 22 | 100.00% | 1 / 1 | |||
| bankDomains | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| supports | 100.00% | 10 / 10 | 100.00% | 1 / 1 | 6 | |||||
| parse | 100.00% | 55 / 55 | 100.00% | 1 / 1 | 15 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Tomaj\BankMailsParser\Parser\Vub; | |
| 6 | ||
| 7 | use Tomaj\BankMailsParser\Exception\InvalidEmailFormatException; | |
| 8 | use Tomaj\BankMailsParser\MailContent; | |
| 9 | use Tomaj\BankMailsParser\Parser\BankDate; | |
| 10 | use Tomaj\BankMailsParser\Parser\ParserInterface; | |
| 11 | use Tomaj\BankMailsParser\Parser\ParsesBankMail; | |
| 12 | ||
| 13 | final readonly class VubMailParser implements ParserInterface | |
| 14 | { | |
| 15 | use ParsesBankMail; | |
| 16 | ||
| 17 | /** | |
| 18 | * @return list<string> | |
| 19 | */ | |
| 20 | #[\Override] | |
| 21 | public function bankDomains(): array | |
| 22 | { | |
| 23 | return ['vub.sk']; | |
| 24 | } | |
| 25 | ||
| 26 | #[\Override] | |
| 27 | public function supports(string $content, ?string $sender = null, ?string $subject = null): bool | |
| 28 | { | |
| 29 | return $this->supportsQuietly(function () use ($content): bool { | |
| 30 | $content = $this->withoutByteOrderMark($content); | |
| 31 | $hasDate = $this->matched($this->field('D(?:á|a)?tum', ':'), $content); | |
| 32 | $hasSource = $this->matched($this->field('Z[ \t\x{00A0}\x{2009}\x{202F}]*(?:(?:ú|u)?čtu|tu)', ':'), $content); | |
| 33 | $hasDestination = $this->matched($this->field('Na[ \t\x{00A0}\x{2009}\x{202F}]+(?:účet|et)', ':'), $content); | |
| 34 | $hasStatus = $this->matched($this->field('(?:Stav|SIGN)', ':'), $content); | |
| 35 | $hasAmount = $this->matched($this->field('Suma', ':'), $content); | |
| 36 | $hasVs = $this->matched($this->field('VS', ':'), $content); | |
| 37 | ||
| 38 | return $hasDate && $hasSource && $hasDestination && $hasStatus && $hasAmount && $hasVs; | |
| 39 | }); | |
| 40 | } | |
| 41 | ||
| 42 | public function parse(string $content): MailContent | |
| 43 | { | |
| 44 | $content = $this->requireUniformLineBreaks($content); | |
| 45 | $signals = 0; | |
| 46 | ||
| 47 | $transactionDate = null; | |
| 48 | if ($this->matched($this->field('D(?:á|a)?tum:', '(.*)$'), $content, $result)) { | |
| 49 | ++$signals; | |
| 50 | $transactionDate = BankDate::parseFirst(mb_trim($this->group($result, 1), " \t\n\r\0\x0B\u{00A0}\u{2009}\u{202F}"), ['!j.n.Y', '!Y-m-d', '!j.n.Y G:i'], BankDate::bratislava()); | |
| 51 | } | |
| 52 | ||
| 53 | $ownAccountNumber = null; | |
| 54 | if ($this->matched($this->field('Na[ \t\x{00A0}\x{2009}\x{202F}]+(?:účet|et):', '([A-Z0-9 \x{00A0}\x{2009}\x{202F}\t]*)'), $content, $result)) { | |
| 55 | $account = $this->normalizeAccount($this->group($result, 1)); | |
| 56 | if ($account !== '') { | |
| 57 | ++$signals; | |
| 58 | $ownAccountNumber = $account; | |
| 59 | } | |
| 60 | } | |
| 61 | ||
| 62 | $accountNumber = null; | |
| 63 | if ($this->matched($this->field('Z[ \t\x{00A0}\x{2009}\x{202F}]*(?:(?:ú|u)?čtu|tu):', '([A-Z0-9 \x{00A0}\x{2009}\x{202F}\t]*)'), $content, $result)) { | |
| 64 | $account = $this->normalizeAccount($this->group($result, 1)); | |
| 65 | if ($account !== '') { | |
| 66 | ++$signals; | |
| 67 | $accountNumber = $account; | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | $money = null; | |
| 72 | if ($this->matched($this->field('Suma:', '(.*)$'), $content, $result)) { | |
| 73 | ++$signals; | |
| 74 | $raw = trim(str_replace(["\u{00A0}", "\u{2009}", "\u{202F}", "\t"], ' ', $this->group($result, 1))); | |
| 75 | if ($raw !== '' && preg_match('/^(-?\d(?:[\d \x{00A0}\x{2009}\x{202F}\t.,]*\d)?)(?:[ \t]*([A-Z]{3}))?$/u', $raw, $amount) === 1) { | |
| 76 | $currency = $amount[2] ?? 'EUR'; | |
| 77 | $money = $this->moneyOrNull($amount[1], $currency, ','); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | $vs = null; | |
| 82 | if ($this->matched($this->field('VS:', '([0-9]+)'), $content, $result)) { | |
| 83 | ++$signals; | |
| 84 | $vs = $this->paymentSymbol($this->group($result, 1)); | |
| 85 | } | |
| 86 | ||
| 87 | $ks = null; | |
| 88 | if ($this->matched($this->field('KS:', '([0-9]+)'), $content, $result)) { | |
| 89 | ++$signals; | |
| 90 | $ks = $this->paymentSymbol($this->group($result, 1)); | |
| 91 | } | |
| 92 | ||
| 93 | $ss = null; | |
| 94 | if ($this->matched($this->field('(?:ŠS|SS|S):', '([0-9]+)'), $content, $result)) { | |
| 95 | ++$signals; | |
| 96 | $ss = $this->paymentSymbol($this->group($result, 1)); | |
| 97 | } | |
| 98 | ||
| 99 | $sign = null; | |
| 100 | if ($this->matched($this->field('SIGN:', '(.*)$'), $content, $result)) { | |
| 101 | ++$signals; | |
| 102 | $value = mb_trim($this->group($result, 1), " \t\n\r\0\x0B\u{00A0}\u{2009}\u{202F}"); | |
| 103 | if ($value !== '') { | |
| 104 | $sign = $value; | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | if ($signals < 2) { | |
| 109 | throw InvalidEmailFormatException::malformedContent(self::class, 'No VÚB fields found'); | |
| 110 | } | |
| 111 | ||
| 112 | return new MailContent( | |
| 113 | money: $money, | |
| 114 | transactionDate: $transactionDate, | |
| 115 | accountNumber: $accountNumber, | |
| 116 | ownAccountNumber: $ownAccountNumber, | |
| 117 | vs: $vs, | |
| 118 | ss: $ss, | |
| 119 | ks: $ks, | |
| 120 | sign: $sign, | |
| 121 | ); | |
| 122 | } | |
| 123 | } |