Passed
Push — master ( 55b2d7...d9efa6 )
by Alec
03:49
created

Money::allocate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 05.11.18
5
 * Time: 23:51
6
 */
7
8
namespace AlecRabbit\Money;
9
10
use AlecRabbit\Money\CalculatorFactory as Factory;
11
use AlecRabbit\Money\Contracts\MoneyInterface;
12
13
/**
14
 * Money Value Object.
15
 *
16
 * @author Mathias Verraes
17
 */
18
class Money implements MoneyInterface, \JsonSerializable
19
{
20
    use MoneyFactory,
21
        MoneyFunctions;
22
23
    /** @var string */
24
    protected $amount;
25
26
    /** @var Currency */
27
    protected $currency;
28
29
    /**
30
     * @param null|int|float|string $amount
31
     * @param Currency $currency
32
     *
33
     * @throws \InvalidArgumentException If amount is not integer
34
     */
35 137
    public function __construct($amount, Currency $currency)
36
    {
37 137
        if (null === $amount) {
38 3
            $amount = 0;
39
        }
40 137
        if (!\is_numeric($amount)) {
41 2
            throw new \InvalidArgumentException('Amount must be int|float|string');
42
        }
43 135
        $this->calculator = Factory::getCalculator();
44
45 135
        $this->setAmount((string)$amount);
46 135
        $this->setCurrency($currency);
47 135
    }
48
49
    /**
50
     * @param string $amount
51
     */
52 135
    private function setAmount(string $amount): void
53
    {
54 135
        $this->amount = trim_zeros($amount);
55 135
    }
56
57
    /**
58
     * @param Currency $currency
59
     */
60 135
    private function setCurrency(Currency $currency): void
61
    {
62 135
        $this->currency = $currency;
63 135
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 7
    public function compare(Money $other): int
69
    {
70 7
        $this->assertSameCurrency($other);
71
72 7
        return $this->calculator->compare($this->amount, $other->amount);
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 42
    protected function assertSameCurrency(Money $other): void
79
    {
80 42
        if (!$this->isSameCurrency($other)) {
81 3
            throw new \InvalidArgumentException('Currencies must be identical.');
82
        }
83 42
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 50
    public function isSameCurrency(Money $other): bool
89
    {
90 50
        return $this->currency->equals($other->currency);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96 117
    public function getAmount(): string
97
    {
98 117
        return $this->amount;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 80
    public function getCurrency(): Currency
105
    {
106 80
        return $this->currency;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     *
112
     * @return array
113
     */
114 1
    public function jsonSerialize(): array
115
    {
116
        return [
117 1
            'amount' => $this->amount,
118 1
            'currency' => $this->currency,
119
        ];
120
    }
121
122
    /**
123
     * Allocate the money among N targets.
124
     *
125
     * @param int $n
126
     *
127
     * @param int|null $precision
128
     * @return Money[]
129
     *
130
     */
131 7
    public function allocateTo(int $n, ?int $precision = null): array
132
    {
133 7
        if ($n <= 0) {
134 2
            throw new \InvalidArgumentException('Number to allocateTo must be greater than zero.');
135
        }
136
137 5
        return $this->allocate(array_fill(0, $n, 1), $precision);
138
    }
139
140
    /**
141
     * Allocate the money according to a list of ratios.
142
     *
143
     * @param array $ratios
144
     *
145
     * @param int|null $precision
146
     * @return Money[]
147
     */
148 37
    public function allocate(array $ratios, ?int $precision = null): array
149
    {
150
        return
151 37
            (new AllocationCalculator($this))->compute($ratios, $precision);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157 25
    protected function assertOperand($operand): void
158
    {
159 25
        if (!\is_numeric($operand)) {
160 10
            throw new \InvalidArgumentException(
161 10
                sprintf(
162 10
                    'Operand should be a numeric value, "%s" given.',
163 10
                    typeOf($operand)
164
                )
165
            );
166
        }
167 15
    }
168
169
    /**
170
     * Returns a new Money instance based on the current one using the Currency.
171
     *
172
     * @param int|string|float|null $amount
173
     *
174
     * @return Money
175
     *
176
     * @throws \InvalidArgumentException
177
     */
178 29
    private function newInstance($amount): Money
0 ignored issues
show
Unused Code introduced by
The method newInstance() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
179
    {
180 29
        return new Money($amount, $this->currency);
181
    }
182
}
183