Passed
Push — master ( 1f5936...ef809d )
by Alec
05:25
created

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