Passed
Push — master ( 365cfc...8e997c )
by Mr
04:36
created

BitcoinMoneyParser   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 51
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 51
ccs 0
cts 37
cp 0
rs 10
c 0
b 0
f 0
wmc 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
B parse() 0 41 9
A __construct() 0 3 1
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the ngutech/bitcoin-interop project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace NGUtech\Bitcoin\Service;
10
11
use Money\Currencies;
12
use Money\Currency;
13
use Money\Exception\ParserException;
14
use Money\Money;
15
use Money\MoneyParser;
16
17
final class BitcoinMoneyParser implements MoneyParser
18
{
19
    private Currencies $currencies;
20
21
    public function __construct(Currencies $currencies)
22
    {
23
        $this->currencies = $currencies;
24
    }
25
26
    /** @param null|Currency $forceCurrency */
27
    public function parse($money, $forceCurrency = null)
28
    {
29
        if (is_string($money) === false) {
30
            throw new ParserException('Formatted raw money should be string, e.g. ₿0.1');
31
        }
32
33
        $regex = '/^(?<amount>-?(?<symbol>[₿฿Ƀ])?\d+(?:\.\d+)?)\s?(?<currency>BTC|XBT)?$/u';
34
        if (!preg_match($regex, $money, $matches)) {
35
            throw new ParserException('Value cannot be parsed as Bitcoin.');
36
        }
37
38
        if (!isset($matches['symbol']) && !isset($matches['currency'])) {
39
            throw new ParserException('Value currency cannot be parsed as Bitcoin.');
40
        }
41
42
        $currency = $forceCurrency ?: new Currency($matches['currency'] ?? BitcoinCurrencies::BTC);
43
44
        $amount = preg_replace('/[₿฿Ƀ]/u', '', $matches['amount']);
45
        $subunit = $this->currencies->subunitFor($currency);
46
        $decimalSeparator = strpos($amount, '.');
47
48
        if (false !== $decimalSeparator) {
49
            $amount = rtrim($amount, '0');
50
            $lengthAmount = strlen($amount);
51
            $amount = str_replace('.', '', $amount);
52
            $amount .= str_pad('', ($lengthAmount - $decimalSeparator - $subunit - 1) * -1, '0');
53
        } else {
54
            $amount .= str_pad('', $subunit, '0');
55
        }
56
57
        if (substr($amount, 0, 1) === '-') {
58
            $amount = '-'.ltrim(substr($amount, 1), '0');
59
        } else {
60
            $amount = ltrim($amount, '0');
61
        }
62
63
        if ('' === $amount) {
64
            $amount = '0';
65
        }
66
67
        return new Money($amount, $currency);
68
    }
69
}
70