Money::add()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace SaasReady\Helpers;
4
5
use DivisionByZeroError;
6
use SaasReady\Constants\CurrencyCode;
7
use SaasReady\Models\Currency;
0 ignored issues
show
Bug introduced by
The type SaasReady\Models\Currency was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
9
/**
10
 * Immutable Money class to store the money information
11
 *
12
 * @note $amount is storing as cents, by default you would need to do *100 for every real amount
13
 * or use self@makeFromRealAmount method to do that.
14
 */
15
final class Money
16
{
17
    public function __construct(
18
        public readonly int $amount,
19
        public readonly CurrencyCode $currencyCode
20
    ) {
21
    }
22
23
    public static function make(int $amount, CurrencyCode $currencyCode): self
24
    {
25
        return new Money($amount, $currencyCode);
26
    }
27
28
    public static function makeFromRealAmount(float $amount, CurrencyCode $currencyCode): self
29
    {
30
        return new Money($amount * 100, $currencyCode);
0 ignored issues
show
Bug introduced by
$amount * 100 of type double is incompatible with the type integer expected by parameter $amount of SaasReady\Helpers\Money::__construct(). ( Ignorable by Annotation )

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

30
        return new Money(/** @scrutinizer ignore-type */ $amount * 100, $currencyCode);
Loading history...
31
    }
32
33
    public function clone(?int $amount = null): self
34
    {
35
        return self::make($amount ?? $this->amount, $this->currencyCode);
36
    }
37
38
    public function getCurrency(): Currency
39
    {
40
        return Currency::findByCode($this->currencyCode);
41
    }
42
43
    public function add(Money $money): Money
44
    {
45
        return $this->clone(
46
            $this->amount + $money->amount
47
        );
48
    }
49
50
    public function subtract(Money $money): Money
51
    {
52
        return $this->clone(
53
            $this->amount - $money->amount
54
        );
55
    }
56
57
    public function multiply(float $rate): Money
58
    {
59
        return $this->clone(
60
            $this->amount * $rate
0 ignored issues
show
Bug introduced by
$this->amount * $rate of type double is incompatible with the type integer|null expected by parameter $amount of SaasReady\Helpers\Money::clone(). ( Ignorable by Annotation )

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

60
            /** @scrutinizer ignore-type */ $this->amount * $rate
Loading history...
61
        );
62
    }
63
64
    public function divide(float $rate): Money
65
    {
66
        if ($rate == 0) {
67
            throw new DivisionByZeroError();
68
        }
69
70
        return $this->clone(
71
            $this->amount / $rate
0 ignored issues
show
Bug introduced by
$this->amount / $rate of type double is incompatible with the type integer|null expected by parameter $amount of SaasReady\Helpers\Money::clone(). ( Ignorable by Annotation )

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

71
            /** @scrutinizer ignore-type */ $this->amount / $rate
Loading history...
72
        );
73
    }
74
75
    /**
76
     * With symbol: $1234.56
77
     * Without symbol: USD 1234.56
78
     *
79
     * With decimals: 1234.56
80
     * Without decimals: 1234
81
     */
82
    public function present(bool $withSymbol = true, bool $withDecimals = true): string
83
    {
84
        $presentedAmount = $this->presentAmountOnly($withDecimals);
85
86
        if ($withSymbol) {
87
            $currency = $this->getCurrency();
88
89
            return sprintf(
90
                '%s%s%s',
91
                $currency->symbol,
92
                $currency->space_after_symbol ? ' ' : '',
93
                $presentedAmount
94
            );
95
        }
96
97
        return $this->currencyCode->value . ' ' . $presentedAmount;
98
    }
99
100
    /**
101
     * Present the amount only - based on the configuration from Currency
102
     *
103
     * Eg: 1,234.56
104
     */
105
    public function presentAmountOnly(bool $withDecimals = true): string
106
    {
107
        $currency = $this->getCurrency();
108
109
        return number_format(
110
            $this->amount / 100,
111
            $withDecimals ? $currency->decimals : 0,
112
            $currency->decimal_separator,
113
            $currency->thousands_separator
114
        );
115
    }
116
}
117