Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
ListCurrenciesHandler
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
1 / 1
 handle
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace App\Currency\Application\Query;
6
7use Collator;
8use Symfony\Component\Intl\Currencies;
9
10class ListCurrenciesHandler
11{
12    private const LOCALE = 'es';
13
14    /**
15     * Active ISO-4217 currencies with Spanish names + minor-unit exponents, from
16     * ICU/CLDR. getNames() also returns withdrawn currencies (e.g. CSD, ROL), so
17     * each code is filtered through isValidInAnyCountry() — legal tender + active
18     * today — which drops historical codes, precious metals and fund/test codes.
19     * Sorted by localized name (accent-aware) so the client renders it as-is.
20     *
21     * @return list<array{code: string, name: string, minorUnits: int}>
22     */
23    public function handle(ListCurrenciesQuery $_query): array
24    {
25        $currencies = [];
26        foreach (Currencies::getNames(self::LOCALE) as $code => $name) {
27            if (!Currencies::isValidInAnyCountry($code)) {
28                continue;
29            }
30
31            $currencies[] = [
32                'code' => $code,
33                'name' => $name,
34                'minorUnits' => Currencies::getFractionDigits($code),
35            ];
36        }
37
38        $collator = new Collator(self::LOCALE);
39        usort(
40            $currencies,
41            static fn (array $a, array $b): int => (int) $collator->compare($a['name'], $b['name']),
42        );
43
44        return $currencies;
45    }
46}