AssetFunctions::mod()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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