Test Failed
Push — master ( 0da4e2...1a9fa4 )
by Esteban De La Fuente
03:30
created

Currency::getCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Enum;
26
27
/**
28
 * Enum con monedas en estándar ISO 4217.
29
 */
30
enum Currency: string
31
{
32
    /**
33
     * Pesos chilenos.
34
     */
35
    case CLP = 'CLP';
36
37
    /**
38
     * Unidad de Fomento de Chile (UF).
39
     */
40
    case CLF = 'CLF';
41
42
    /**
43
     * Unidad Tributaria Mensual de Chile.
44
     */
45
    case UTM = 'UTM';
46
47
    /**
48
     * Unidad Tributaria Anual de Chile.
49
     */
50
    case UTA = 'UTA';
51
52
    /**
53
     * Dólar de Estados Unidos.
54
     */
55
    case USD = 'USD';
56
57
    /**
58
     * Euro.
59
     */
60
    case EUR = 'EUR';
61
62
    /**
63
     * I love Bitcoin <3
64
     */
65
    case BTC = 'BTC';
66
67
    /**
68
     * Peso argentino.
69
     */
70
    case ARS = 'ARS';
71
72
    /**
73
     * Libra esterlina.
74
     */
75
    case GBP = 'GBP';
76
77
    /**
78
     * Corona sueca.
79
     */
80
    case SEK = 'SEK';
81
82
    /**
83
     * Dólar de Hong Kong.
84
     */
85
    case HKD = 'HKD';
86
87
    /**
88
     * Rand sudafricano.
89
     */
90
    case ZAR = 'ZAR';
91
92
    /**
93
     * Peso colombiano.
94
     */
95
    case COP = 'COP';
96
97
    /**
98
     * Peso mexicano.
99
     */
100
    case MXN = 'MXN';
101
102
    /**
103
     * Bolívar venezolano.
104
     */
105
    case VES = 'VES';
106
107
    /**
108
     * Dólar de Singapur.
109
     */
110
    case SGD = 'SGD';
111
112
    /**
113
     * Rupia india.
114
     */
115
    case INR = 'INR';
116
117
    /**
118
     * Nuevo dólar taiwanés.
119
     */
120
    case TWD = 'TWD';
121
122
    /**
123
     * Dirham de Emiratos Árabes Unidos.
124
     */
125
    case AED = 'AED';
126
127
    /**
128
     * Won surcoreano.
129
     */
130
    case KRW = 'KRW';
131
132
    /**
133
     * Zloty polaco.
134
     */
135
    case PLN = 'PLN';
136
137
    /**
138
     * Corona checa.
139
     */
140
    case CZK = 'CZK';
141
142
    /**
143
     * Forint húngaro.
144
     */
145
    case HUF = 'HUF';
146
147
    /**
148
     * Baht tailandés.
149
     */
150
    case THB = 'THB';
151
152
    /**
153
     * Lira turca.
154
     */
155
    case TRY = 'TRY';
156
157
    /**
158
     * Ringgit malayo.
159
     */
160
    case MYR = 'MYR';
161
162
    /**
163
     * Rublo ruso.
164
     */
165
    case RUB = 'RUB';
166
167
    /**
168
     * Rupia indonesia.
169
     */
170
    case IDR = 'IDR';
171
172
    /**
173
     * Grivna ucraniana.
174
     */
175
    case UAH = 'UAH';
176
177
    /**
178
     * Shekel israelí.
179
     */
180
    case ILS = 'ILS';
181
182
    /**
183
     * Peso filipino.
184
     */
185
    case PHP = 'PHP';
186
187
    /**
188
     * Riyal saudí.
189
     */
190
    case SAR = 'SAR';
191
192
    /**
193
     * Rupia pakistaní.
194
     */
195
    case PKR = 'PKR';
196
197
    /**
198
     * Dong vietnamita.
199
     */
200
    case VND = 'VND';
201
202
    /**
203
     * Libra egipcia.
204
     */
205
    case EGP = 'EGP';
206
207
    /**
208
     * Leu rumano.
209
     */
210
    case RON = 'RON';
211
212
    /**
213
     * Corona islandesa.
214
     */
215
    case ISK = 'ISK';
216
217
    /**
218
     * Rial iraní.
219
     */
220
    case IRR = 'IRR';
221
222
    /**
223
     * Colón costarricense.
224
     */
225
    case CRC = 'CRC';
226
227
    /**
228
     * Balboa panameño.
229
     */
230
    case PAB = 'PAB';
231
232
    /**
233
     * Guaraní paraguayo.
234
     */
235
    case PYG = 'PYG';
236
237
    /**
238
     * Sol peruano.
239
     */
240
    case PEN = 'PEN';
241
242
    /**
243
     * Peso uruguayo.
244
     */
245
    case UYU = 'UYU';
246
247
    /**
248
     * Dólar australiano.
249
     */
250
    case AUD = 'AUD';
251
252
    /**
253
     * Boliviano.
254
     */
255
    case BOB = 'BOB';
256
257
    /**
258
     * Yuan chino.
259
     */
260
    case CNY = 'CNY';
261
262
    /**
263
     * Real brasileño.
264
     */
265
    case BRL = 'BRL';
266
267
    /**
268
     * Corona danesa.
269
     */
270
    case DKK = 'DKK';
271
272
    /**
273
     * Dólar canadiense.
274
     */
275
    case CAD = 'CAD';
276
277
    /**
278
     * Yen japonés.
279
     */
280
    case JPY = 'JPY';
281
282
    /**
283
     * Franco suizo.
284
     */
285
    case CHF = 'CHF';
286
287
    /**
288
     * Corona noruega.
289
     */
290
    case NOK = 'NOK';
291
292
    /**
293
     * Dólar neozelandés.
294
     */
295
    case NZD = 'NZD';
296
297
    /**
298
     * Monedas no especificadas.
299
     *
300
     * En estricto rigor ISO 4217 define XXX como "Sin divisa".
301
     */
302
    case XXX = 'XXX';
303
304
    /**
305
     * Nombres de las monedas.
306
     *
307
     * Si un nombre no está definido se entregará el código estándar ISO 4217.
308
     *
309
     * @var array<string, array<string, string>>
310
     */
311
    private const NAMES = [
312
        // Nombres de monedas en español.
313
        'es' => [
314
            self::CLP->value => 'Peso chileno',
315
            self::CLF->value => 'Unidad de fomento de Chile',
316
            self::UTM->value => 'Unidad tributaria mensual de Chile',
317
            self::UTA->value => 'Unidad tributaria anual de Chile',
318
            self::USD->value => 'Dólar estadounidense',
319
            self::EUR->value => 'Euro',
320
            self::BTC->value => 'Bitcoin',
321
            self::ARS->value => 'Peso argentino',
322
            self::GBP->value => 'Libra esterlina',
323
            self::SEK->value => 'Corona sueca',
324
            self::HKD->value => 'Dólar de Hong Kong',
325
            self::ZAR->value => 'Rand sudafricano',
326
            self::COP->value => 'Peso colombiano',
327
            self::MXN->value => 'Peso mexicano',
328
            self::VES->value => 'Bolívar venezolano',
329
            self::SGD->value => 'Dólar de Singapur',
330
            self::INR->value => 'Rupia india',
331
            self::TWD->value => 'Nuevo dólar taiwanés',
332
            self::AED->value => 'Dirham de Emiratos Árabes Unidos',
333
            self::KRW->value => 'Won surcoreano',
334
            self::PLN->value => 'Zloty polaco',
335
            self::CZK->value => 'Corona checa',
336
            self::HUF->value => 'Forint húngaro',
337
            self::THB->value => 'Baht tailandés',
338
            self::TRY->value => 'Lira turca',
339
            self::MYR->value => 'Ringgit malayo',
340
            self::RUB->value => 'Rublo ruso',
341
            self::IDR->value => 'Rupia indonesia',
342
            self::UAH->value => 'Grivna ucraniana',
343
            self::ILS->value => 'Shekel israelí',
344
            self::PHP->value => 'Peso filipino',
345
            self::SAR->value => 'Riyal saudí',
346
            self::PKR->value => 'Rupia pakistaní',
347
            self::VND->value => 'Dong vietnamita',
348
            self::EGP->value => 'Libra egipcia',
349
            self::RON->value => 'Leu rumano',
350
            self::ISK->value => 'Corona islandesa',
351
            self::IRR->value => 'Rial iraní',
352
            self::CRC->value => 'Colón costarricense',
353
            self::PAB->value => 'Balboa panameño',
354
            self::PYG->value => 'Guaraní paraguayo',
355
            self::PEN->value => 'Sol peruano',
356
            self::UYU->value => 'Peso uruguayo',
357
            self::AUD->value => 'Dólar australiano',
358
            self::BOB->value => 'Boliviano',
359
            self::CNY->value => 'Yuan chino',
360
            self::BRL->value => 'Real brasileño',
361
            self::DKK->value => 'Corona danesa',
362
            self::CAD->value => 'Dólar canadiense',
363
            self::JPY->value => 'Yen japonés',
364
            self::CHF->value => 'Franco suizo',
365
            self::NOK->value => 'Corona noruega',
366
            self::NZD->value => 'Dólar neozelandés',
367
            self::XXX->value => 'Sin divisa',
368
        ],
369
        // Nombres de monedas en Inglés.
370
        'en' => [
371
            self::CLP->value => 'Chilean Peso',
372
            self::CLF->value => 'Chilean Unit of Account (UF)',
373
            self::UTM->value => 'Monthly Tax Unit of Chile',
374
            self::UTA->value => 'Annual Tax Unit of Chile',
375
            self::USD->value => 'United States Dollar',
376
            self::EUR->value => 'Euro',
377
            self::BTC->value => 'Bitcoin',
378
            self::ARS->value => 'Argentine Peso',
379
            self::GBP->value => 'British Pound',
380
            self::SEK->value => 'Swedish Krona',
381
            self::HKD->value => 'Hong Kong Dollar',
382
            self::ZAR->value => 'South African Rand',
383
            self::COP->value => 'Colombian Peso',
384
            self::MXN->value => 'Mexican Peso',
385
            self::VES->value => 'Venezuelan Bolívar',
386
            self::SGD->value => 'Singapore Dollar',
387
            self::INR->value => 'Indian Rupee',
388
            self::TWD->value => 'New Taiwan Dollar',
389
            self::AED->value => 'United Arab Emirates Dirham',
390
            self::KRW->value => 'South Korean Won',
391
            self::PLN->value => 'Polish Zloty',
392
            self::CZK->value => 'Czech Koruna',
393
            self::HUF->value => 'Hungarian Forint',
394
            self::THB->value => 'Thai Baht',
395
            self::TRY->value => 'Turkish Lira',
396
            self::MYR->value => 'Malaysian Ringgit',
397
            self::RUB->value => 'Russian Ruble',
398
            self::IDR->value => 'Indonesian Rupiah',
399
            self::UAH->value => 'Ukrainian Hryvnia',
400
            self::ILS->value => 'Israeli Shekel',
401
            self::PHP->value => 'Philippine Peso',
402
            self::SAR->value => 'Saudi Riyal',
403
            self::PKR->value => 'Pakistani Rupee',
404
            self::VND->value => 'Vietnamese Dong',
405
            self::EGP->value => 'Egyptian Pound',
406
            self::RON->value => 'Romanian Leu',
407
            self::ISK->value => 'Icelandic Krona',
408
            self::IRR->value => 'Iranian Rial',
409
            self::CRC->value => 'Costa Rican Colón',
410
            self::PAB->value => 'Panamanian Balboa',
411
            self::PYG->value => 'Paraguayan Guarani',
412
            self::PEN->value => 'Peruvian Sol',
413
            self::UYU->value => 'Uruguayan Peso',
414
            self::AUD->value => 'Australian Dollar',
415
            self::BOB->value => 'Bolivian Boliviano',
416
            self::CNY->value => 'Chinese Yuan',
417
            self::BRL->value => 'Brazilian Real',
418
            self::DKK->value => 'Danish Krone',
419
            self::CAD->value => 'Canadian Dollar',
420
            self::JPY->value => 'Japanese Yen',
421
            self::CHF->value => 'Swiss Franc',
422
            self::NOK->value => 'Norwegian Krone',
423
            self::NZD->value => 'New Zealand Dollar',
424
            self::XXX->value => 'No Currency',
425
        ],
426
    ];
427
428
    /**
429
     * Símbolos de las monedas.
430
     *
431
     * @var array<string, string>
432
     */
433
    private const SYMBOLS = [
434
        self::CLP->value => '$',
435
        self::CLF->value => 'UF',
436
        self::UTM->value => 'UTM',
437
        self::UTA->value => 'UTA',
438
        self::USD->value => '$',
439
        self::EUR->value => '€',
440
        self::BTC->value => '₿',
441
        self::ARS->value => '$',
442
        self::GBP->value => '£',
443
        self::SEK->value => 'kr',
444
        self::HKD->value => 'HK$',
445
        self::ZAR->value => 'R',
446
        self::COP->value => '$',
447
        self::MXN->value => '$',
448
        self::VES->value => 'Bs.',
449
        self::SGD->value => 'S$',
450
        self::INR->value => '₹',
451
        self::TWD->value => 'NT$',
452
        self::AED->value => 'د.إ',
453
        self::KRW->value => '₩',
454
        self::PLN->value => 'zł',
455
        self::CZK->value => 'Kč',
456
        self::HUF->value => 'Ft',
457
        self::THB->value => '฿',
458
        self::TRY->value => '₺',
459
        self::MYR->value => 'RM',
460
        self::RUB->value => '₽',
461
        self::IDR->value => 'Rp',
462
        self::UAH->value => '₴',
463
        self::ILS->value => '₪',
464
        self::PHP->value => '₱',
465
        self::SAR->value => '﷼',
466
        self::PKR->value => '₨',
467
        self::VND->value => '₫',
468
        self::EGP->value => '£',
469
        self::RON->value => 'lei',
470
        self::ISK->value => 'kr',
471
        self::IRR->value => '﷼',
472
        self::CRC->value => '₡',
473
        self::PAB->value => 'B/.',
474
        self::PYG->value => '₲',
475
        self::PEN->value => 'S/',
476
        self::UYU->value => '$U',
477
        self::AUD->value => 'A$',
478
        self::BOB->value => 'Bs.',
479
        self::CNY->value => '¥',
480
        self::BRL->value => 'R$',
481
        self::DKK->value => 'kr',
482
        self::CAD->value => 'C$',
483
        self::JPY->value => '¥',
484
        self::CHF->value => 'CHF',
485
        self::NOK->value => 'kr',
486
        self::NZD->value => 'NZ$',
487
        self::XXX->value => '',
488
    ];
489
490
    /**
491
     * Cantidad de decimales que cada moneda puede tener.
492
     *
493
     * Si un decimal no está definido se entregará "2" por defecto.
494
     *
495
     * @var array<string, int>
496
     */
497
    private const DECIMALS = [
498
        self::CLP->value => 0,
499
        self::UTM->value => 0,
500
        self::UTA->value => 0,
501
        self::BTC->value => 8,
502
        self::KRW->value => 0,
503
        self::VND->value => 0,
504
        self::ISK->value => 0,
505
        self::PYG->value => 0,
506
        self::JPY->value => 0,
507
    ];
508
509
    /**
510
     * Separadores de decimal de las monedas.
511
     *
512
     * Si no está definido el separador se entregará "." por defecto.
513
     *
514
     * @var array <string, string>
515
     */
516
    private const DECIMAL_SEPARATORS = [
517
        self::CLP->value => ',',
518
        self::CLF->value => ',',
519
        self::UTM->value => ',',
520
        self::UTA->value => ',',
521
    ];
522
523
    /**
524
     * Separadores de miles de las monedas.
525
     *
526
     * Si no está definido el separador se entregará "," por defecto.
527
     *
528
     * @var array <string, string>
529
     */
530
    private const THOUSANDS_SEPARATORS = [
531
        self::CLP->value => '.',
532
        self::CLF->value => '.',
533
        self::UTM->value => '.',
534
        self::UTA->value => '.',
535
    ];
536
537
    /**
538
     * Plantillas para el renderizado de un monto de las monedas.
539
     *
540
     * Si no existe una plantilla se entregará usando la plantilla estándar:
541
     *
542
     *   `{{symbol}} {{amount}}`
543
     *
544
     * @var array <string, string>
545
     */
546
    private const TEMPLATES = [
547
        self::CLF->value => '{{amount}} {{symbol}}',
548
        self::UTM->value => '{{amount}} {{symbol}}',
549
        self::UTA->value => '{{amount}} {{symbol}}',
550
        self::EUR->value => '{{amount}} {{symbol}}',
551
        self::JPY->value => '{{symbol}}{{amount}}',
552
        self::GBP->value => '{{symbol}}{{amount}}',
553
        self::CHF->value => '{{amount}} {{symbol}}',
554
        self::CNY->value => '{{symbol}}{{amount}}',
555
        self::SEK->value => '{{amount}} {{symbol}}',
556
        self::DKK->value => '{{amount}} {{symbol}}',
557
        self::PLN->value => '{{amount}} {{symbol}}',
558
        self::CZK->value => '{{amount}} {{symbol}}',
559
        self::HUF->value => '{{amount}} {{symbol}}',
560
        self::THB->value => '{{symbol}}{{amount}}',
561
        self::VND->value => '{{amount}}{{symbol}}',
562
        self::KRW->value => '{{symbol}}{{amount}}',
563
    ];
564
565
    /**
566
     * Entrega el código de la moneda en estándar ISO 4217.
567
     *
568
     * @return string
569
     */
570
    public function getCode(): string
571
    {
572
        return $this->name;
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Derafu\Lib\Core\Enum\Currency. Did you maybe forget to declare it?
Loading history...
573
    }
574
575
    /**
576
     * Entrega el nombre de la moneda.
577
     *
578
     * @param string $language
579
     * @return string
580
     */
581
    public function getName(string $language = 'es'): string
582
    {
583
        $name = self::NAMES[$language][$this->value] ?? null;
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Currency::NAMES was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
584
585
        if ($name !== null) {
586
            return $name;
587
        }
588
589
        if ($language !== 'en') {
590
            return $this->getName('en');
591
        }
592
593
        return $this->getCode();
594
    }
595
596
    /**
597
     * Entrega el símbolo de la moneda.
598
     *
599
     * @return string
600
     */
601
    public function getSymbol(): string
602
    {
603
        return self::SYMBOLS[$this->value];
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Currency::SYMBOLS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
604
    }
605
606
    /**
607
     * Entrega la cantidad de decimales de la moneda.
608
     *
609
     * @return int
610
     */
611
    public function getDecimals(): int
612
    {
613
        return self::DECIMALS[$this->value] ?? 2;
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Currency::DECIMALS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
614
    }
615
616
    /**
617
     * Entrega el separador de decimal que usa la moneda.
618
     *
619
     * @return string
620
     */
621
    public function getDecimalSeparator(): string
622
    {
623
        return self::DECIMAL_SEPARATORS[$this->value] ?? '.';
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Currency::DECIMAL_SEPARATORS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
624
    }
625
626
    /**
627
     * Entrega el separado de miles que usa la moneda.
628
     *
629
     * @return string
630
     */
631
    public function getThousandsSeparator(): string
632
    {
633
        return self::THOUSANDS_SEPARATORS[$this->value] ?? ',';
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Cur...y::THOUSANDS_SEPARATORS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
634
    }
635
636
    /**
637
     * Valida si un monto es correcto para la moneda según sus decimales.
638
     *
639
     * @param int|float $amount
640
     * @return bool
641
     */
642
    public function isValidAmount(int|float $amount): bool
643
    {
644
        $decimals = $this->getDecimals();
645
        $factor = pow(10, $decimals);
646
647
        return (floor($amount * $factor) === $amount * $factor);
648
    }
649
650
    /**
651
     * Aproxima el monto según los decimales que la moneda tiene.
652
     *
653
     * @param int|float $amount
654
     * @return int|float
655
     */
656
    public function round(int|float $amount): int|float
657
    {
658
        $decimals = $this->getDecimals();
659
660
        $roundedAmount = round((float) $amount, $decimals);
661
662
        return $decimals === 0 ? (int) $roundedAmount : $roundedAmount;
663
    }
664
665
    /**
666
     * Formatea como string el monto de una moneda.
667
     *
668
     * Redondea a los decimales de la moneda y le da formanto usando el
669
     * separador decimal y de miles de la moneda.
670
     *
671
     * @param int|float $amount
672
     * @return string
673
     */
674
    public function format(int|float $amount): string
675
    {
676
        $roundedAmount = $this->round($amount);
677
678
        return number_format(
679
            (float) $roundedAmount,
680
            $this->getDecimals(),
681
            $this->getDecimalSeparator(),
682
            $this->getThousandsSeparator()
683
        );
684
    }
685
686
    /**
687
     * Renderiza el monto de la moneda usando su plantilla.
688
     *
689
     * Entrega un string con el monto aproximado a los decimales de la moneda y
690
     * el símbolo en el formato en que se usa en la moneda.
691
     *
692
     * @param int|float $amount
693
     * @return string
694
     */
695
    public function render(int|float $amount): string
696
    {
697
        $template = $this->getTemplate();
698
699
        $formatedAmount = $this->format($amount);
700
701
        return str_replace(
702
            ['{{symbol}}', '{{amount}}'],
703
            [$this->getSymbol(), $formatedAmount],
704
            $template
705
        );
706
    }
707
708
    /**
709
     * Entrega la plantilla que se debe usar para renderizar un monto de la
710
     * moneda.
711
     *
712
     * @return string
713
     */
714
    public function getTemplate(): string
715
    {
716
        return self::TEMPLATES[$this->value] ?? '{{symbol}} {{amount}}';
0 ignored issues
show
Bug introduced by
The constant Derafu\Lib\Core\Enum\Currency::TEMPLATES was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
717
    }
718
719
    /**
720
     * Devuelve un array con la información completa de la moneda.
721
     *
722
     * @return array<string, mixed>
723
     */
724
    public function toArray(): array
725
    {
726
        return [
727
            'code' => $this->getCode(),
728
            'name' => $this->getName(),
729
            'symbol' => $this->getSymbol(),
730
            'decimals' => $this->getDecimals(),
731
            'decimal_separator' => $this->getDecimalSeparator(),
732
            'thousands_separator' => $this->getThousandsSeparator(),
733
            'template' => $this->getTemplate(),
734
        ];
735
    }
736
}
737