Skip to content

Commit

Permalink
feature #51073 [Intl] Add support for ISO 3166-1 numeric codes (benr77)
Browse files Browse the repository at this point in the history
This PR was merged into the 6.4 branch.

Discussion
----------

[Intl] Add support for ISO 3166-1 numeric codes

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Fix #50860
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

Add support for ISO-3166-1 numeric codes.

As well as the existing Alpha2 and Alpha3 codes, this PR adds support for the numeric country codes as per https://www.iso.org/obp/ui/#search/code/.

Commits
-------

972acf2619 [Intl] Add support for ISO-3166-1 numeric codes
  • Loading branch information
fabpot committed Aug 1, 2023
2 parents b67d8d5 + 0762236 commit b8fab9c
Show file tree
Hide file tree
Showing 5 changed files with 1,025 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGELOG
=========

6.4
---

* Add support for ISO-3166-1 numeric codes with `Countries::getNumericCode()`, `Countries::getNumericCodes()`,
`Countries::numericCodeExists()` and `Countries::getAlpha2FromNumeric()`

6.3
---

Expand Down
38 changes: 38 additions & 0 deletions Countries.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ public static function getAlpha3Codes(): array
return self::readEntry(['Alpha2ToAlpha3'], 'meta');
}

/**
* Returns all available numeric country codes (3 digits).
*
* Countries are returned as ISO 3166 numeric three-digit country codes.
*
* This list only contains "officially assigned ISO 3166-1 numeric" country codes.
*
* Returns an array with Alpha2 country codes as keys, and numeric codes as values.
*
* @return array<string, string>
*/
public static function getNumericCodes(): array
{
return self::readEntry(['Alpha2ToNumeric'], 'meta');
}

public static function getAlpha3Code(string $alpha2Code): string
{
return self::readEntry(['Alpha2ToAlpha3', $alpha2Code], 'meta');
Expand All @@ -62,6 +78,17 @@ public static function getAlpha2Code(string $alpha3Code): string
return self::readEntry(['Alpha3ToAlpha2', $alpha3Code], 'meta');
}

public static function getNumericCode(string $alpha2Code): string
{
return self::readEntry(['Alpha2ToNumeric', $alpha2Code], 'meta');
}

public static function getAlpha2FromNumeric(string $numericCode): string
{
// Use an underscore prefix to force numeric strings with leading zeros to remain as strings
return self::readEntry(['NumericToAlpha2', '_'.$numericCode], 'meta');
}

public static function exists(string $alpha2Code): bool
{
try {
Expand All @@ -84,6 +111,17 @@ public static function alpha3CodeExists(string $alpha3Code): bool
}
}

public static function numericCodeExists(string $numericCode): bool
{
try {
self::getAlpha2FromNumeric($numericCode);

return true;
} catch (MissingResourceException $e) {
return false;
}
}

/**
* Gets the country name from its alpha2 code.
*
Expand Down
71 changes: 71 additions & 0 deletions Data/Generator/RegionDataGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,33 @@ class RegionDataGenerator extends AbstractDataGenerator
'ZZ' => true, // Unknown Region
];

// @see https://en.wikipedia.org/wiki/ISO_3166-1_numeric#Withdrawn_codes
private const WITHDRAWN_CODES = [
128, // Canton and Enderbury Islands
200, // Czechoslovakia
216, // Dronning Maud Land
230, // Ethiopia
249, // France, Metropolitan
278, // German Democratic Republic
280, // Germany, Federal Republic of
396, // Johnston Island
488, // Midway Islands
530, // Netherlands Antilles
532, // Netherlands Antilles
536, // Neutral Zone
582, // Pacific Islands (Trust Territory)
590, // Panama
658, // Saint Kitts-Nevis-Anguilla
720, // Yemen, Democratic
736, // Sudan
810, // USSR
849, // United States Miscellaneous Pacific Islands
872, // Wake Island
886, // Yemen Arab Republic
890, // Yugoslavia, Socialist Federal Republic of
891, // Serbia and Montenegro
];

/**
* Collects all available language codes.
*
Expand Down Expand Up @@ -133,10 +160,21 @@ protected function generateDataForMeta(BundleEntryReaderInterface $reader, strin
$alpha3ToAlpha2 = array_flip($alpha2ToAlpha3);
asort($alpha3ToAlpha2);

$alpha2ToNumeric = $this->generateAlpha2ToNumericMapping($metadataBundle);
$numericToAlpha2 = [];
foreach ($alpha2ToNumeric as $alpha2 => $numeric) {
// Add underscore prefix to force keys with leading zeros to remain as string keys.
$numericToAlpha2['_'.$numeric] = $alpha2;
}

asort($numericToAlpha2);

return [
'Regions' => $this->regionCodes,
'Alpha2ToAlpha3' => $alpha2ToAlpha3,
'Alpha3ToAlpha2' => $alpha3ToAlpha2,
'Alpha2ToNumeric' => $alpha2ToNumeric,
'NumericToAlpha2' => $numericToAlpha2,
];
}

Expand All @@ -159,10 +197,12 @@ protected function generateRegionNames(ArrayAccessibleResourceBundle $localeBund
private function generateAlpha2ToAlpha3Mapping(array $countries, ArrayAccessibleResourceBundle $metadataBundle): array
{
$aliases = iterator_to_array($metadataBundle['alias']['territory']);

$alpha2ToAlpha3 = [];

foreach ($aliases as $alias => $data) {
$country = $data['replacement'];

if (2 === \strlen($country) && 3 === \strlen($alias) && 'overlong' === $data['reason']) {
if (isset(self::PREFERRED_ALPHA2_TO_ALPHA3_MAPPING[$country])) {
// Validate to prevent typos
Expand Down Expand Up @@ -190,4 +230,35 @@ private function generateAlpha2ToAlpha3Mapping(array $countries, ArrayAccessible

return $alpha2ToAlpha3;
}

private function generateAlpha2ToNumericMapping(ArrayAccessibleResourceBundle $metadataBundle): array
{
$aliases = iterator_to_array($metadataBundle['alias']['territory']);

$alpha2ToNumeric = [];

foreach ($aliases as $alias => $data) {
if (!is_numeric($alias)) {
continue;
}

if (\in_array($alias, self::WITHDRAWN_CODES)) {
continue;
}

if (isset(self::DENYLIST[$data['replacement']])) {
continue;
}

if ('deprecated' === $data['reason']) {
continue;
}

$alpha2ToNumeric[$data['replacement']] = (string) $alias;
}

ksort($alpha2ToNumeric);

return $alpha2ToNumeric;
}
}
Loading

0 comments on commit b8fab9c

Please sign in to comment.