Passed
Push — master ( 7c7ac1...5df575 )
by Mr
02:35
created

Money::percentage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/money-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 Daikon\Money\ValueObject;
10
11
use Daikon\Interop\Assertion;
12
use Daikon\Interop\InvalidArgumentException;
13
use Daikon\Money\ValueObject\MoneyInterface;
14
use Money\Currency as PhpCurrency;
15
use Money\Money as PhpMoney;
16
17
final class Money implements MoneyInterface
18
{
19
    private PhpMoney $money;
20
21
    /** @param self $comparator */
22 1
    public function equals($comparator): bool
23
    {
24 1
        Assertion::isInstanceOf($comparator, self::class);
25 1
        return $this->toNative() === $comparator->toNative();
26
    }
27
28 10
    public function getAmount(): string
29
    {
30 10
        return $this->money->getAmount();
31
    }
32
33 10
    public function getCurrency(): string
34
    {
35 10
        return $this->money->getCurrency()->getCode();
36
    }
37
38 1
    public function multiply($multiplier, int $roundingMode = self::ROUND_HALF_UP): self
39
    {
40 1
        Assertion::numeric($multiplier, 'Multipler must be numeric.');
41 1
        $multiplied = $this->money->multiply($multiplier, $roundingMode);
42 1
        return new self($multiplied);
43
    }
44
45 1
    public function divide($divisor, int $roundingMode = self::ROUND_HALF_UP): self
46
    {
47 1
        Assertion::numeric($divisor, 'Divider must be numeric.');
48 1
        $divided = $this->money->divide($divisor, $roundingMode);
49 1
        return new self($divided);
50
    }
51
52 1
    public function percentage($percentage, int $roundingMode = self::ROUND_HALF_UP): self
53
    {
54 1
        return $this->multiply($percentage)->divide(100, $roundingMode);
55
    }
56
57 3
    public function add(MoneyInterface $money): self
58
    {
59 3
        $added = $this->money->add(
60 3
            self::asBaseMoney($money->getAmount(), $money->getCurrency())
61
        );
62 3
        return new self($added);
63
    }
64
65 1
    public function subtract(MoneyInterface $money): self
66
    {
67 1
        $subtracted = $this->money->subtract(
68 1
            self::asBaseMoney($money->getAmount(), $money->getCurrency())
69
        );
70 1
        return new self($subtracted);
71
    }
72
73 1
    public function isZero(): bool
74
    {
75 1
        return $this->money->isZero();
76
    }
77
78
    public function isPositive(): bool
79
    {
80
        return $this->money->isPositive();
81
    }
82
83
    public function isNegative(): bool
84
    {
85
        return $this->money->isNegative();
86
    }
87
88
    public function isLessThanOrEqual(MoneyInterface $money): bool
89
    {
90
        return $this->money->lessThanOrEqual(
91
            self::asBaseMoney($money->getAmount(), $money->getCurrency())
92
        );
93
    }
94
95
    public function isGreaterThanOrEqual(MoneyInterface $money): bool
96
    {
97
        return $this->money->greaterThanOrEqual(
98
            self::asBaseMoney($money->getAmount(), $money->getCurrency())
99
        );
100
    }
101
102
    /** @param string $value */
103 13
    public static function fromNative($value): self
104
    {
105 13
        Assertion::string($value, 'Must be a string.');
106 13
        if (!preg_match('/^(?<amount>-?\d+)\s?(?<currency>[a-z][a-z0-9]*)$/i', $value, $matches)) {
107 1
            throw new InvalidArgumentException('Invalid amount.');
108
        }
109
110 13
        return new self(self::asBaseMoney($matches['amount'], $matches['currency']));
111
    }
112
113 7
    public static function zero($currency = null): self
114
    {
115 7
        Assertion::regex($currency, '/^[a-z][a-z0-9]*$/i', 'Invalid currency.');
116 7
        return self::fromNative('0'.(string)$currency);
117
    }
118
119 8
    public function toNative(): string
120
    {
121 8
        return $this->getAmount().$this->getCurrency();
122
    }
123
124 5
    public function __toString(): string
125
    {
126 5
        return $this->toNative();
127
    }
128
129 13
    private static function asBaseMoney(string $amount, string $currency): PhpMoney
130
    {
131 13
        return new PhpMoney($amount, new PhpCurrency($currency));
132
    }
133
134 13
    private function __construct(PhpMoney $money)
135
    {
136 13
        $this->money = $money;
137 13
    }
138
}
139