LocaleService::getNamesFromGuilds()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service;
4
5
use Akaunting\Money\Currency;
6
use Akaunting\Money\Money;
7
use Illuminate\Support\Collection;
8
use Mcamara\LaravelLocalization\LaravelLocalization;
9
use Rinvex\Country\CountryLoader;
10
use Siak\Tontine\Model\Guild;
11
use NumberFormatter;
12
13
use function array_merge;
14
use function route;
15
use function strtoupper;
16
17
class LocaleService
18
{
19
    /**
20
     * @var Currency
21
     */
22
    private $currency;
23
24
    /**
25
     * @var NumberFormatter
26
     */
27
    private $formatter = null;
28
29
    public function __construct(private LaravelLocalization $localization,
30
        private string $countriesDataDir, private string $currenciesDataDir)
31
    {}
32
33
    /**
34
     * Set the currency to be used for money
35
     *
36
     * @param string $currency
37
     *
38
     * @return void
39
     */
40
    public function setCurrency(string $currency)
41
    {
42
        $this->currency = new Currency(strtoupper($currency));
43
    }
44
45
    /**
46
     * Get the currency name
47
     *
48
     * @return string
49
     */
50
    public function getCurrencyName(): string
51
    {
52
        return $this->currency?->getName() ?? '';
53
    }
54
55
    /**
56
     * Get the currency symbol
57
     *
58
     * @return string
59
     */
60
    public function getCurrencySymbol(): string
61
    {
62
        return $this->currency?->getSymbol() ?? '';
63
    }
64
65
    /**
66
     * @param bool $withEmpty
67
     *
68
     * @return array
69
     */
70
    public function getCountries(bool $withEmpty = true): array
71
    {
72
        $locale = $this->localization->getCurrentLocale();
73
        $countries = include($this->countriesDataDir . "/{$locale}/country.php");
74
        // Append an empty item to the array.
75
        return !$withEmpty ? $countries : array_merge(['' => ''], $countries);
76
    }
77
78
    /**
79
     * @param string $code
80
     *
81
     * @return array
82
     */
83
    public function getCountryCurrencies(string $code): array
84
    {
85
        $country = CountryLoader::country($code, false);
86
        $locale = $this->localization->getCurrentLocale();
87
        $localizedCurrencies = include($this->currenciesDataDir . "/{$locale}/currency.php");
88
89
        $currencies = [];
90
        foreach($country['currency'] ?? [] as $currency)
91
        {
92
            $currencyCode = $currency['iso_4217_code'];
93
            $currencies[$currencyCode] = $localizedCurrencies[$currencyCode];
94
        }
95
        return $currencies;
96
    }
97
98
    /**
99
     * Get the names of countries and currencies
100
     *
101
     * @param array $countries
102
     * @param array $currencies
103
     *
104
     * @return array
105
     */
106
    public function getNames(array $countries, array $currencies): array
107
    {
108
        $locale = $this->localization->getCurrentLocale();
109
        $localizedCountries = include $this->countriesDataDir . "/{$locale}/country.php";
110
        $localizedCurrencies = include $this->currenciesDataDir . "/{$locale}/currency.php";
111
112
        $countryNames = [];
113
        foreach($countries as $code)
114
        {
115
            if(isset($localizedCountries[$code]))
116
            {
117
                $countryNames[$code] = $localizedCountries[$code];
118
            }
119
        }
120
        $currencyNames = [];
121
        foreach($currencies as $code)
122
        {
123
            if(isset($localizedCurrencies[$code]))
124
            {
125
                $currencyNames[$code] = $localizedCurrencies[$code];
126
            }
127
        }
128
        return [$countryNames, $currencyNames];
129
    }
130
131
    /**
132
     * Get the names of countries and currencies from a guild
133
     *
134
     * @param Guild $guild
135
     *
136
     * @return array
137
     */
138
    public function getNameFromGuild(Guild $guild): array
139
    {
140
        [$countries, $currencies] = $this->getNames([$guild->country_code], [$guild->currency_code]);
141
        return [$countries[$guild->country_code] ?? '', $currencies[$guild->currency_code] ?? ''];
142
    }
143
144
    /**
145
     * Get the names of countries and currencies from a collection of guilds
146
     *
147
     * @param Collection $guilds
148
     *
149
     * @return array
150
     */
151
    public function getNamesFromGuilds(Collection $guilds): array
152
    {
153
        $countryCodes = $guilds->pluck('country_code')->toArray();
154
        $currencyCodes = $guilds->pluck('currency_code')->toArray();
155
        return $this->getNames($countryCodes, $currencyCodes);
156
    }
157
158
    /**
159
     * @return string
160
     */
161
    private function _locale(): string
162
    {
163
        $locales = ['en' => 'en_GB', 'fr' => 'fr_FR'];
164
        return $locales[$this->localization->getCurrentLocale()] ?? 'en_GB';
165
    }
166
167
    /**
168
     * @return NumberFormatter
169
     */
170
    private function makeDecimalFormatter(): NumberFormatter
171
    {
172
        $formatter = new NumberFormatter($this->_locale(), NumberFormatter::DECIMAL);
173
        $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS,
174
            $this->currency->getPrecision());
175
        return $formatter;
176
    }
177
178
    /**
179
     * @param bool $fixedPrecision
180
     *
181
     * @return NumberFormatter
182
     */
183
    private function decimalFormatter(bool $fixedPrecision = false): NumberFormatter
184
    {
185
        $this->formatter ??= $this->makeDecimalFormatter();
186
        $this->formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS,
187
            $fixedPrecision ? $this->currency->getPrecision() : 0);
188
        return $this->formatter;
189
    }
190
191
    /**
192
     * Get a formatted amount.
193
     *
194
     * @param int $amount
195
     * @param bool $showSymbol
196
     * @param bool $fixedPrecision
197
     *
198
     * @return string
199
     */
200
    public function formatMoney(int $amount, bool $showSymbol = false,
201
        bool $fixedPrecision = true): string
202
    {
203
        $money = new Money($amount, $this->currency);
204
        return $showSymbol ? $money->formatLocale($this->_locale()) :
205
            $this->decimalFormatter($fixedPrecision)->format($money->getValue());
206
    }
207
208
    /**
209
     * @param float $amount
210
     *
211
     * @return int
212
     */
213
    public function convertMoneyToInt(float $amount): int
214
    {
215
        return (int)(new Money($amount, $this->currency, true))->getAmount();
216
    }
217
218
    /**
219
     * @param int $amount
220
     *
221
     * @return float
222
     */
223
    public function getMoneyValue(int $amount): float
224
    {
225
        return (new Money($amount, $this->currency, false))->getValue();
226
    }
227
228
    /**
229
     * Get the translated URL for a route
230
     *
231
     * @param string $name
232
     * @param array $attributes
233
     *
234
     * @return string
235
     */
236
    public function route(string $name, array $attributes = []): string
237
    {
238
        $locale = $this->localization->getCurrentLocale();
239
        return $this->localization->getLocalizedUrl($locale, route($name, $attributes));
240
    }
241
}
242