Passed
Push — master ( 1da82a...7c3e69 )
by Alec
04:39
created

MoneyFunctions::avg()   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
2
/**
3
 * User: alec
4
 * Date: 26.11.18
5
 * Time: 14:35
6
 */
7
8
namespace AlecRabbit\Money;
9
10
use AlecRabbit\Money\Contracts\CalculatorInterface;
11
12
trait MoneyFunctions
13
{
14
    /** @var CalculatorInterface */
15
    protected $calculator;
16
17
    /**
18
     * @param Money $first
19
     * @param Money ...$collection
20
     *
21
     * @return Money
22
     */
23 3
    public static function min(Money $first, Money ...$collection): Money
24
    {
25 3
        $min = $first;
26
27 3
        foreach ($collection as $money) {
28 2
            if ($money->lessThan($min)) {
29 2
                $min = $money;
30
            }
31
        }
32
33 3
        return $min;
34
    }
35
36
    /**
37
     * Checks whether the value represented by this object is less than the other.
38
     *
39
     * @param Money $other
40
     *
41
     * @return bool
42
     */
43 5
    public function lessThan(Money $other): bool
44
    {
45 5
        return $this->compare($other) === -1;
46
    }
47
48
    /**
49
     * @param Money $first
50
     * @param Money ...$collection
51
     *
52
     * @return Money
53
     */
54 3
    public static function max(Money $first, Money ...$collection): Money
55
    {
56 3
        $max = $first;
57
58 3
        foreach ($collection as $money) {
59 2
            if ($money->greaterThan($max)) {
60 2
                $max = $money;
61
            }
62
        }
63
64 3
        return $max;
65
    }
66
67
    /**
68
     * Checks whether the value represented by this object is greater than the other.
69
     *
70
     * @param Money $other
71
     *
72
     * @return bool
73
     */
74 5
    public function greaterThan(Money $other): bool
75
    {
76 5
        return $this->compare($other) === 1;
77
    }
78
79
    /**
80
     * @param Money $first
81
     * @param Money ...$collection
82
     *
83
     * @return Money
84
     */
85 6
    public static function sum(Money $first, Money ...$collection): Money
86
    {
87 6
        return $first->add(...$collection);
88
    }
89
90
    /**
91
     * Returns a new Money object that represents
92
     * the sum of this and an other Money object.
93
     *
94
     * @param Money ...$addends
95
     *
96
     * @return Money
97
     */
98 28
    public function add(Money ...$addends): Money
99
    {
100 28
        $amount = $this->getAmount();
101 28
        $calculator = $this->calculator;
102
103 28
        foreach ($addends as $addend) {
104 25
            $this->assertSameCurrency($addend);
105
106 25
            $amount = $calculator->add($amount, $addend->getAmount());
107
        }
108 28
        return new Money($amount, $this->getCurrency());
109
    }
110
111
    /**
112
     * @param Money $first
113
     * @param Money ...$collection
114
     *
115
     * @return Money
116
     */
117 5
    public static function avg(Money $first, Money ...$collection): Money
118
    {
119 5
        return $first->add(...$collection)->divide(\func_num_args());
120
    }
121
122
    /**
123
     * Returns a new Money object that represents
124
     * the divided value by the given factor.
125
     *
126
     * @param float|int|string $divisor
127
     *
128
     * @return Money
129
     */
130 16
    public function divide($divisor): Money
131
    {
132 16
        $this->assertOperand($divisor);
133
134 11
        if ($this->calculator->compare((string)$divisor, '0') === 0) {
135 1
            throw new \InvalidArgumentException('Division by zero.');
136
        }
137
138 10
        $quotient = $this->calculator->divide($this->getAmount(), $divisor);
139
        return
140 10
            $this->newInstance($quotient);
141
    }
142
143
    /**
144
     * Checks whether the value represented by this object equals to the other.
145
     *
146
     * @param Money $other
147
     *
148
     * @return bool
149
     */
150 8
    public function equals(Money $other): bool
151
    {
152 8
        return $this->isSameCurrency($other) && $this->getAmount() === $other->getAmount();
153
    }
154
155
    /**
156
     * @param Money $other
157
     *
158
     * @return bool
159
     */
160 3
    public function greaterThanOrEqual(Money $other): bool
161
    {
162 3
        return $this->compare($other) >= 0;
163
    }
164
165
    /**
166
     * @param Money $other
167
     *
168
     * @return bool
169
     */
170 3
    public function lessThanOrEqual(Money $other): bool
171
    {
172 3
        return $this->compare($other) <= 0;
173
    }
174
175
    /**
176
     * Returns a new Money object that represents
177
     * the multiplied value by the given factor.
178
     *
179
     * @param float|int|string $multiplier
180
     *
181
     * @return Money
182
     */
183 9
    public function multiply($multiplier): Money
184
    {
185 9
        $this->assertOperand($multiplier);
186
187 4
        $result = $this->calculator->multiply($this->getAmount(), $multiplier);
188
189
        return
190 4
            $this->newInstance($result);
191
    }
192
193
    /**
194
     * Returns a new Money object that represents
195
     * the remainder after dividing the value by
196
     * the given factor.
197
     *
198
     * @param Money $divisor
199
     *
200
     * @return Money
201
     */
202 4
    public function mod(Money $divisor): Money
203
    {
204 4
        $this->assertSameCurrency($divisor);
205
206 4
        $mod = $this->calculator->mod($this->getAmount(), $divisor->getAmount());
207
        return
208 4
            $this->newInstance($mod);
209
    }
210
211
    /**
212
     * @param Money $money
213
     *
214
     * @return string
215
     */
216 2
    public function ratioOf(Money $money): string
217
    {
218 2
        if ($money->isZero()) {
219 1
            throw new \InvalidArgumentException('Cannot calculate a ratio of zero.');
220
        }
221
222 1
        return $this->calculator->divide($this->getAmount(), $money->getAmount());
223
    }
224
225
    /**
226
     * Checks if the value represented by this object is zero.
227
     *
228
     * @return bool
229
     */
230 30
    public function isZero(): bool
231
    {
232 30
        return $this->calculator->compare($this->getAmount(), '0') === 0;
233
    }
234
235
    /**
236
     * Returns a new Money object that represents
237
     * the difference of this and an other Money object.
238
     *
239
     * @param Money ...$subtrahends
240
     *
241
     * @return Money
242
     */
243 20
    public function subtract(Money ...$subtrahends): Money
244
    {
245 20
        $amount = $this->getAmount();
246 20
        $calculator = $this->calculator;
247
248 20
        foreach ($subtrahends as $subtrahend) {
249 20
            $this->assertSameCurrency($subtrahend);
250
251 20
            $amount = $calculator->subtract($amount, $subtrahend->getAmount());
252
        }
253
254 20
        return new Money($amount, $this->getCurrency());
255
    }
256
257
    /**
258
     * Checks if the value represented by this object is not negative.
259
     *
260
     * @return bool
261
     */
262 6
    public function isNotNegative(): bool
263
    {
264
        return
265 6
            !$this->isNegative();
266
    }
267
268
    /**
269
     * Checks if the value represented by this object is negative.
270
     *
271
     * @return bool
272
     */
273 13
    public function isNegative(): bool
274
    {
275 13
        return $this->calculator->compare($this->getAmount(), '0') === -1;
276
    }
277
278
    /**
279
     * Checks if the value represented by this object is not zero.
280
     *
281
     * @return bool
282
     */
283 6
    public function isNotZero(): bool
284
    {
285
        return
286 6
            !$this->isZero();
287
    }
288
289
    /**
290
     * Checks if the value represented by this object is not positive.
291
     *
292
     * @return bool
293
     */
294 17
    public function isNotPositive(): bool
295
    {
296
        return
297 17
            !$this->isPositive();
298
    }
299
300
    /**
301
     * Checks if the value represented by this object is positive.
302
     *
303
     * @return bool
304
     */
305 23
    public function isPositive(): bool
306
    {
307 23
        return $this->calculator->compare($this->getAmount(), '0') === 1;
308
    }
309
310
    /**
311
     * Returns an integer less than, equal to, or greater than zero
312
     * if the value of this object is considered to be respectively
313
     * less than, equal to, or greater than the other.
314
     *
315
     * @param Money $other
316
     *
317
     * @return int
318
     */
319
    abstract public function compare(Money $other): int;
320
321
    /**
322
     * Checks whether a Money has the same Currency as this.
323
     *
324
     * @param Money $other
325
     *
326
     * @return bool
327
     */
328
    abstract public function isSameCurrency(Money $other): bool;
329
330
    /**
331
     * Returns the value represented by this object.
332
     *
333
     * @return string
334
     */
335
    abstract public function getAmount(): string;
336
337
    /**
338
     * Returns the currency of this object.
339
     *
340
     * @return Currency
341
     */
342
    abstract public function getCurrency(): Currency;
343
344
    /**
345
     * Asserts that a Money has the same currency as this.
346
     *
347
     * @param Money $other
348
     *
349
     * @throws \InvalidArgumentException If $other has a different currency
350
     */
351
    abstract protected function assertSameCurrency(Money $other): void;
352
353
    /**
354
     * Asserts that the operand is integer or float.
355
     *
356
     * @param float|int|string|object $operand
357
     *
358
     * @throws \InvalidArgumentException If $operand is neither integer nor float
359
     */
360
    abstract protected function assertOperand($operand): void;
361
362
    /**
363
     * Returns a new Money instance based on the current one using the Currency.
364
     *
365
     * @param int|string|float|null $amount
366
     *
367
     * @return Money
368
     *
369
     * @throws \InvalidArgumentException
370
     */
371
    abstract protected function newInstance($amount): Money;
372
373
}
374