121 lines
3.3 KiB
PHP
121 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\BusProNet\Utility;
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Maps BusPro's `hotel/land` token onto a lowercase ISO 3166-1 alpha-2 code.
|
|
*
|
|
* BusPro has no country vocabulary: the field is free text that has accumulated three
|
|
* conventions side by side — ISO-2 (`CH`, `NL`), the European vehicle registration codes
|
|
* (`D`, `A`, `F`, `S`, `FL`) and ISO-3 (`AUT`, `PRT`, `HRV`), with the same country often
|
|
* under several tokens. The table below is therefore part of the API contract rather than
|
|
* a derivation: consumers render a flag from it, and a wrong entry mislabels a destination
|
|
* silently, which is worse than no flag at all. An unknown token maps to null — never to a
|
|
* guess, never to an empty string.
|
|
*/
|
|
class CountryCodeMapper
|
|
{
|
|
/**
|
|
* Keys are upper-cased tokens, values lowercase ISO-2.
|
|
*
|
|
* Entries worth their explanation:
|
|
* - `IR` is Ireland, not Iran. Every row carrying it is Dublin or Carlow.
|
|
* - `SLO` is Slovakia here, not Slovenia: its only row is a Slovak company, and
|
|
* Slovenia already arrives under its own `SI`.
|
|
* - `S`, `N`, `FL` are vehicle codes (Sweden, Norway, Liechtenstein), consistent with
|
|
* the `D`/`A`/`F`/`I`/`E`/`B` in the same column.
|
|
* - `UK` is the colloquial form of the ISO `GB`.
|
|
*
|
|
* @var array<string, string>
|
|
*/
|
|
private const MAP = [
|
|
'A' => 'at',
|
|
'AT' => 'at',
|
|
'AUT' => 'at',
|
|
'B' => 'be',
|
|
'CA' => 'ca',
|
|
'CH' => 'ch',
|
|
'CZ' => 'cz',
|
|
'D' => 'de',
|
|
'DEU' => 'de',
|
|
'DK' => 'dk',
|
|
'E' => 'es',
|
|
'ES' => 'es',
|
|
'F' => 'fr',
|
|
'FI' => 'fi',
|
|
'FL' => 'li',
|
|
'FR' => 'fr',
|
|
'GR' => 'gr',
|
|
'GRE' => 'gr',
|
|
'HR' => 'hr',
|
|
'HRV' => 'hr',
|
|
'HU' => 'hu',
|
|
'I' => 'it',
|
|
'IL' => 'il',
|
|
'IR' => 'ie',
|
|
'IS' => 'is',
|
|
'IT' => 'it',
|
|
'LT' => 'lt',
|
|
'LV' => 'lv',
|
|
'MT' => 'mt',
|
|
'N' => 'no',
|
|
'NL' => 'nl',
|
|
'PL' => 'pl',
|
|
'PRT' => 'pt',
|
|
'PT' => 'pt',
|
|
'RUS' => 'ru',
|
|
'S' => 'se',
|
|
'SI' => 'si',
|
|
'SLO' => 'sk',
|
|
'UK' => 'gb',
|
|
'USA' => 'us',
|
|
'ZA' => 'za',
|
|
];
|
|
|
|
/**
|
|
* Tokens already reported in this process, so a master data file full of the same
|
|
* unknown token produces one log line rather than one per hotel.
|
|
*
|
|
* @var array<string, true>
|
|
*/
|
|
private array $reported = [];
|
|
|
|
public function __construct(
|
|
private readonly LoggerInterface $logger,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @param string|null $token the raw `hotel/land` value
|
|
*
|
|
* @return string|null lowercase ISO-2, or null when absent, empty or unmappable
|
|
*/
|
|
public function map(?string $token): ?string
|
|
{
|
|
if (null === $token) {
|
|
return null;
|
|
}
|
|
|
|
$normalized = strtoupper(trim($token));
|
|
|
|
if ('' === $normalized) {
|
|
return null;
|
|
}
|
|
|
|
if (isset(self::MAP[$normalized])) {
|
|
return self::MAP[$normalized];
|
|
}
|
|
|
|
if (false === isset($this->reported[$normalized])) {
|
|
$this->reported[$normalized] = true;
|
|
$this->logger->warning('Unmapped BusPro country token', ['token' => $token]);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|