Files
Investidor-V2/app/Services/CountryCatalogue.php
T
nala c13f250b87
tests / ci (push) Canceled after 0s
versao compilada
2026-10-15 17:37:00 +02:00

82 lines
3.0 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\In;
/** Shared ISO identifiers; independent of administrative territories and IP data. */
final class CountryCatalogue
{
/** @return list<array{code: string, name: string, name_en: string}> */
public function all(): array
{
$countries = [];
$lines = file(resource_path('data/iso3166.tab'), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines === false) {
throw new \RuntimeException('Catálogo ISO local indisponível.');
}
foreach ($lines as $line) {
if (str_starts_with($line, '#')) {
continue;
}
[$code, $english] = explode("\t", $line, 2);
$name = class_exists(\Locale::class) ? \Locale::getDisplayRegion('und_'.$code, 'pt') : $english;
$countries[] = ['code' => $code, 'name' => is_string($name) && $name !== '' ? $name : $english, 'name_en' => $english];
}
usort($countries, fn ($a, $b) => strnatcasecmp($a['name'], $b['name']));
return $countries;
}
public function rule(): In
{
return Rule::in(array_column($this->all(), 'code'));
}
/** Accept existing free-text integrations; validate ISO-shaped values without rewriting them. */
public function legacyCountryRule(): \Closure
{
$codes = array_column($this->all(), 'code');
return static function (string $attribute, mixed $value, \Closure $fail) use ($codes): void {
if (is_string($value) && preg_match('/^[a-zA-Z]{2}$/D', $value) && ! in_array($value, $codes, true)) {
$fail('Seleccione um código ISO de país válido.');
}
};
}
/**
* Exact catalogue labels for reading legacy free-text country values.
* Does not infer request origin, alter stored values or classify unmatched text.
* Only labels belonging to one ISO country are included.
*
* @return list<string> Case-folded country code and catalogue labels.
*/
public function filterValues(string $code): array
{
$countries = $this->all();
$owners = [];
$selected = [];
foreach ($countries as $country) {
foreach (array_unique([$country['code'], $country['name'], $country['name_en']]) as $label) {
$key = mb_strtolower(trim($label), 'UTF-8');
$owners[$key][$country['code']] = true;
if ($country['code'] === $code) {
$selected[$key] = true;
}
}
}
return array_values(array_filter(array_keys($selected), fn ($key) => count($owners[$key]) === 1));
}
/** @return array{code:string|null,name:string} */
public function describe(?string $code): array
{
$names = array_column($this->all(), 'name', 'code');
return isset($names[$code ?? '']) ? ['code' => $code, 'name' => $names[$code]] : ['code' => null, 'name' => 'Não informado'];
}
}