Passed
Push — master ( 2290f0...52e80f )
by Mr
02:27
created

Money::makeEmpty()   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 0
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
class Money implements MoneyInterface
18
{
19
    protected ?PhpMoney $money;
20
21
    /** @param static $comparator */
22 1
    public function equals($comparator): bool
23
    {
24 1
        Assertion::isInstanceOf($comparator, static::class);
25 1
        return $this->toNative() === $comparator->toNative();
26
    }
27
28 16
    public function getAmount(): string
29
    {
30 16
        $this->assertNotEmpty();
31 16
        return $this->money->getAmount();
0 ignored issues
show
Bug introduced by
The method getAmount() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

31
        return $this->money->/** @scrutinizer ignore-call */ getAmount();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
32
    }
33
34 22
    public function getCurrency(): string
35
    {
36 22
        $this->assertNotEmpty();
37 22
        return $this->money->getCurrency()->getCode();
38
    }
39
40
    /** @return static */
41 4
    public function multiply($multiplier, int $roundingMode = self::ROUND_HALF_UP): self
42
    {
43 4
        $this->assertNotEmpty();
44 2
        Assertion::numeric($multiplier, 'Multipler must be numeric.');
45 2
        $multiplied = $this->money->multiply($multiplier, $roundingMode);
46 2
        return new static($multiplied);
47
    }
48
49
    /** @return static */
50 4
    public function divide($divisor, int $roundingMode = self::ROUND_HALF_UP): self
51
    {
52 4
        $this->assertNotEmpty();
53 2
        Assertion::numeric($divisor, 'Divider must be numeric.');
54 2
        Assertion::notEq(0, $divisor, 'Divisor must not be zero.');
55 2
        $divided = $this->money->divide($divisor, $roundingMode);
56 2
        return new static($divided);
57
    }
58
59
    /** @return static */
60 2
    public function percentage($percentage, int $roundingMode = self::ROUND_HALF_UP): self
61
    {
62 2
        $this->assertNotEmpty();
63 1
        return $this->multiply($percentage)->divide(100, $roundingMode);
64
    }
65
66
    /** @return static */
67 5
    public function add(MoneyInterface $money): self
68
    {
69 5
        $this->assertNotEmpty();
70 4
        $this->assertSameCurrency($money);
71 3
        Assertion::false($money->isEmpty(), 'Comparand must not be empty.');
72 3
        $added = $this->money->add(
73 3
            static::asBaseMoney($money->getAmount(), $money->getCurrency())
74
        );
75 3
        return new static($added);
76
    }
77
78
    /** @return static */
79 4
    public function subtract(MoneyInterface $money): self
80
    {
81 4
        $this->assertNotEmpty();
82 3
        $this->assertSameCurrency($money);
83 2
        Assertion::false($money->isEmpty(), 'Comparand must not be empty.');
84 2
        $subtracted = $this->money->subtract(
85 2
            static::asBaseMoney($money->getAmount(), $money->getCurrency())
86
        );
87 2
        return new static($subtracted);
88
    }
89
90
    /** @return static */
91 19
    public static function makeEmpty(): self
92
    {
93 19
        return new static;
94
    }
95
96 37
    public function isEmpty(): bool
97
    {
98 37
        return $this->money === null;
99
    }
100
101 5
    public function isZero(): bool
102
    {
103 5
        $this->assertNotEmpty();
104 4
        return $this->money->isZero();
105
    }
106
107 2
    public function isPositive(): bool
108
    {
109 2
        $this->assertNotEmpty();
110 1
        return $this->money->isPositive();
111
    }
112
113 2
    public function isNegative(): bool
114
    {
115 2
        $this->assertNotEmpty();
116 1
        return $this->money->isNegative();
117
    }
118
119 4
    public function isLessThanOrEqual(MoneyInterface $money): bool
120
    {
121 4
        $this->assertNotEmpty();
122 3
        $this->assertSameCurrency($money);
123 1
        Assertion::false($money->isEmpty(), 'Comparand must not be empty.');
124 1
        return $this->money->lessThanOrEqual(
125 1
            static::asBaseMoney($money->getAmount(), $money->getCurrency())
126
        );
127
    }
128
129 5
    public function isGreaterThanOrEqual(MoneyInterface $money): bool
130
    {
131 5
        $this->assertNotEmpty();
132 4
        $this->assertSameCurrency($money);
133 2
        Assertion::false($money->isEmpty(), 'Comparand must not be empty.');
134 2
        return $this->money->greaterThanOrEqual(
135 2
            static::asBaseMoney($money->getAmount(), $money->getCurrency())
136
        );
137
    }
138
139
    /**
140
     * @param null|string $value
141
     * @return static
142
     */
143 30
    public static function fromNative($value): self
144
    {
145 30
        Assertion::nullOrString($value, 'Must be a string.');
146 30
        if ($value === null) {
147 3
            return new static;
148
        }
149
150 30
        if (!preg_match('/^(?<amount>-?\d+)\s?(?<currency>[a-z][a-z0-9]*)$/i', $value, $matches)) {
151 1
            throw new InvalidArgumentException('Invalid amount.');
152
        }
153
154 30
        return new static(static::asBaseMoney($matches['amount'], $matches['currency']));
155
    }
156
157
    /** @return static */
158 16
    public static function zero($currency = null): self
159
    {
160 16
        Assertion::regex($currency, '/^[a-z][a-z0-9]*$/i', 'Invalid currency.');
161 16
        return static::fromNative('0'.(string)$currency);
162
    }
163
164 12
    public function toNative(): ?string
165
    {
166 12
        return !$this->isEmpty() ? $this->getAmount().$this->getCurrency() : null;
167
    }
168
169 8
    public function __toString(): string
170
    {
171 8
        return (string)$this->toNative();
172
    }
173
174 30
    protected static function asBaseMoney(string $amount, string $currency): PhpMoney
175
    {
176 30
        return new PhpMoney($amount, new PhpCurrency($currency));
177
    }
178
179 36
    protected function assertNotEmpty(): void
180
    {
181 36
        Assertion::false($this->isEmpty(), 'Money is empty.');
182 24
    }
183
184 14
    protected function assertSameCurrency(MoneyInterface $money): void
185
    {
186 14
        Assertion::eq($this->getCurrency(), $money->getCurrency(), 'Currencies must be identical.');
187 8
    }
188
189 39
    final protected function __construct(?PhpMoney $money = null)
190
    {
191 39
        $this->money = $money;
192 39
    }
193
}
194