Converter::convert()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
rs 9.8666
cc 3
nc 3
nop 0
1
<?php
2
3
namespace GNAHotelSolutions\CurrencyConverter;
4
5
use GNAHotelSolutions\CurrencyConverter\Contracts\CurrenciesRepositoryContract;
6
7
class Converter
8
{
9
    /** @var Price */
10
    private $price;
11
12
    /** @var Currency */
13
    private $currency;
14
15
    /** @var CurrenciesRepositoryContract */
16
    private $currencies;
17
18
    /** @var Currency */
19
    private $base;
20
21
    public function __construct(Currency $baseCurrency, CurrenciesRepositoryContract $currencies)
22
    {
23
        $this->base = $baseCurrency;
24
25
        $this->currencies = $currencies;
26
    }
27
28
    public function price(): Price
29
    {
30
        return $this->price;
31
    }
32
33
    public function currency(): ?Currency
34
    {
35
        return $this->currency;
36
    }
37
38
    public function base(): Currency
39
    {
40
        return $this->base;
41
    }
42
43
    /**
44
     * Set the original price to be converted.
45
     *
46
     * @param Price $price
47
     * @return $this
48
     */
49
    public function from(Price $price): self
50
    {
51
        $this->price = $price;
52
53
        return $this;
54
    }
55
56
    /**
57
     * Set the currency that will be used for the convertion.
58
     *
59
     * @param  string|Currency $currency
60
     * @return $this
61
     */
62
    public function to($currency): self
63
    {
64
        $this->currency = $currency instanceof Currency
65
            ? $currency
66
            : $this->currencies->get(strtoupper($currency));
67
68
        return $this;
69
    }
70
71
    /**
72
     * Convert the price to the currency. It will convert to the base currency first if needed.
73
     *
74
     * @return Price
75
     */
76
    public function convert(): Price
77
    {
78
        if ($this->currency()->is($this->price->currency())) {
79
            return $this->price;
80
        }
81
82
        if ($this->base()->is($this->price->currency(), $this->currency()->name())) {
83
            $this->price = (new self($this->base(), $this->currencies))->from($this->price)->convertToBase();
84
        }
85
86
        return new Price($this->convertAmount($this->currency()), $this->currency()->name());
87
    }
88
89
    /**
90
     * Convert the amount performing different operations depending on the currency we want.
91
     *
92
     * @param $convertRatio
93
     * @return float|int
94
     */
95
    public function convertAmount(Currency $currency)
96
    {
97
        $ratio = $this->currency() && $this->currency()->is($this->base()->name())
98
            ? $this->base()->ratio() / $currency->ratio()
99
            : $currency->ratio();
100
101
        return round($this->price()->amount() * $ratio, $currency->decimals());
102
    }
103
104
    /**
105
     * Convert the current price to EUR.
106
     *
107
     * @return Price
108
     */
109
    public function convertToBase()
110
    {
111
        $this->currency = $this->base();
112
113
        $amount = $this->convertAmount($this->currencies->get($this->price->currency()));
114
115
        return new Price($amount, $this->base()->name());
116
    }
117
}
118