*/ public static function statuses(): array { return [ self::STATUS_OFFICIAL, self::STATUS_RESERVED, self::STATUS_TRANSITIONAL, self::STATUS_DELETED, self::STATUS_USER_ASSIGNED, self::STATUS_EXCEPTIONALLY_RESERVED, ]; } public static function normaliseAlpha2(string $code): string { $normalised = strtoupper(trim($code)); if (! preg_match('/^[A-Z]{2}$/', $normalised)) { throw new InvalidArgumentException('ISO 3166-1 alpha-2 codes must contain exactly two letters.'); } return $normalised; } public static function normaliseAlpha3(string $code): string { $normalised = strtoupper(trim($code)); if (! preg_match('/^[A-Z]{3}$/', $normalised)) { throw new InvalidArgumentException('ISO 3166-1 alpha-3 codes must contain exactly three letters.'); } return $normalised; } public static function normaliseNumeric(string|int $code): string { $normalised = str_pad((string) $code, 3, '0', STR_PAD_LEFT); if (! preg_match('/^\d{3}$/', $normalised)) { throw new InvalidArgumentException('ISO 3166-1 numeric codes must contain exactly three digits.'); } return $normalised; } public static function normaliseSubdivisionCode(string $countryAlpha2, string $subdivisionCode): string { $country = self::normaliseAlpha2($countryAlpha2); $code = strtoupper(trim($subdivisionCode)); if (str_starts_with($code, $country . '-')) { return $code; } if (! preg_match('/^[A-Z0-9]{1,6}$/', $code)) { throw new InvalidArgumentException('ISO 3166-2 subdivision codes must contain 1 to 6 letters or numbers after the country prefix.'); } return $country . '-' . $code; } public static function flagEmoji(string $alpha2): string { $alpha2 = self::normaliseAlpha2($alpha2); $base = 127397; return mb_chr($base + ord($alpha2[0]), 'UTF-8') . mb_chr($base + ord($alpha2[1]), 'UTF-8'); } }