diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af3e900..1f372c4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 --- diff --git a/Countries.php b/Countries.php index 6a4ef2c1..fd17c3f0 100644 --- a/Countries.php +++ b/Countries.php @@ -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 + */ + public static function getNumericCodes(): array + { + return self::readEntry(['Alpha2ToNumeric'], 'meta'); + } + public static function getAlpha3Code(string $alpha2Code): string { return self::readEntry(['Alpha2ToAlpha3', $alpha2Code], 'meta'); @@ -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 { @@ -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. * diff --git a/Data/Generator/RegionDataGenerator.php b/Data/Generator/RegionDataGenerator.php index fecda261..b03f5661 100644 --- a/Data/Generator/RegionDataGenerator.php +++ b/Data/Generator/RegionDataGenerator.php @@ -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. * @@ -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, ]; } @@ -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 @@ -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; + } } diff --git a/Resources/data/regions/meta.php b/Resources/data/regions/meta.php index 94e4faf8..8548a28f 100644 --- a/Resources/data/regions/meta.php +++ b/Resources/data/regions/meta.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + return [ 'Regions' => [ 'AD', @@ -754,4 +763,578 @@ 'ZMB' => 'ZM', 'ZWE' => 'ZW', ], + 'Alpha2ToNumeric' => [ + 'AA' => '958', + 'AD' => '020', + 'AE' => '784', + 'AF' => '004', + 'AG' => '028', + 'AI' => '660', + 'AL' => '008', + 'AM' => '051', + 'AO' => '024', + 'AQ' => '010', + 'AR' => '032', + 'AS' => '016', + 'AT' => '040', + 'AU' => '036', + 'AW' => '533', + 'AX' => '248', + 'AZ' => '031', + 'BA' => '070', + 'BB' => '052', + 'BD' => '050', + 'BE' => '056', + 'BF' => '854', + 'BG' => '100', + 'BH' => '048', + 'BI' => '108', + 'BJ' => '204', + 'BL' => '652', + 'BM' => '060', + 'BN' => '096', + 'BO' => '068', + 'BQ' => '535', + 'BR' => '076', + 'BS' => '044', + 'BT' => '064', + 'BV' => '074', + 'BW' => '072', + 'BY' => '112', + 'BZ' => '084', + 'CA' => '124', + 'CC' => '166', + 'CD' => '180', + 'CF' => '140', + 'CG' => '178', + 'CH' => '756', + 'CI' => '384', + 'CK' => '184', + 'CL' => '152', + 'CM' => '120', + 'CN' => '156', + 'CO' => '170', + 'CR' => '188', + 'CU' => '192', + 'CV' => '132', + 'CW' => '531', + 'CX' => '162', + 'CY' => '196', + 'CZ' => '203', + 'DE' => '276', + 'DJ' => '262', + 'DK' => '208', + 'DM' => '212', + 'DO' => '214', + 'DZ' => '012', + 'EC' => '218', + 'EE' => '233', + 'EG' => '818', + 'EH' => '732', + 'ER' => '232', + 'ES' => '724', + 'ET' => '231', + 'FI' => '246', + 'FJ' => '242', + 'FK' => '238', + 'FM' => '583', + 'FO' => '234', + 'FR' => '250', + 'GA' => '266', + 'GB' => '826', + 'GD' => '308', + 'GE' => '268', + 'GF' => '254', + 'GG' => '831', + 'GH' => '288', + 'GI' => '292', + 'GL' => '304', + 'GM' => '270', + 'GN' => '324', + 'GP' => '312', + 'GQ' => '226', + 'GR' => '300', + 'GS' => '239', + 'GT' => '320', + 'GU' => '316', + 'GW' => '624', + 'GY' => '328', + 'HK' => '344', + 'HM' => '334', + 'HN' => '340', + 'HR' => '191', + 'HT' => '332', + 'HU' => '348', + 'ID' => '360', + 'IE' => '372', + 'IL' => '376', + 'IM' => '833', + 'IN' => '356', + 'IO' => '086', + 'IQ' => '368', + 'IR' => '364', + 'IS' => '352', + 'IT' => '380', + 'JE' => '832', + 'JM' => '388', + 'JO' => '400', + 'JP' => '392', + 'KE' => '404', + 'KG' => '417', + 'KH' => '116', + 'KI' => '296', + 'KM' => '174', + 'KN' => '659', + 'KP' => '408', + 'KR' => '410', + 'KW' => '414', + 'KY' => '136', + 'KZ' => '398', + 'LA' => '418', + 'LB' => '422', + 'LC' => '662', + 'LI' => '438', + 'LK' => '144', + 'LR' => '430', + 'LS' => '426', + 'LT' => '440', + 'LU' => '442', + 'LV' => '428', + 'LY' => '434', + 'MA' => '504', + 'MC' => '492', + 'MD' => '498', + 'ME' => '499', + 'MF' => '663', + 'MG' => '450', + 'MH' => '584', + 'MK' => '807', + 'ML' => '466', + 'MM' => '104', + 'MN' => '496', + 'MO' => '446', + 'MP' => '580', + 'MQ' => '474', + 'MR' => '478', + 'MS' => '500', + 'MT' => '470', + 'MU' => '480', + 'MV' => '462', + 'MW' => '454', + 'MX' => '484', + 'MY' => '458', + 'MZ' => '508', + 'NA' => '516', + 'NC' => '540', + 'NE' => '562', + 'NF' => '574', + 'NG' => '566', + 'NI' => '558', + 'NL' => '528', + 'NO' => '578', + 'NP' => '524', + 'NR' => '520', + 'NU' => '570', + 'NZ' => '554', + 'OM' => '512', + 'PA' => '591', + 'PE' => '604', + 'PF' => '258', + 'PG' => '598', + 'PH' => '608', + 'PK' => '586', + 'PL' => '616', + 'PM' => '666', + 'PN' => '612', + 'PR' => '630', + 'PS' => '275', + 'PT' => '620', + 'PW' => '585', + 'PY' => '600', + 'QA' => '634', + 'QM' => '959', + 'QN' => '960', + 'QP' => '962', + 'QQ' => '963', + 'QR' => '964', + 'QS' => '965', + 'QT' => '966', + 'QV' => '968', + 'QW' => '969', + 'QX' => '970', + 'QY' => '971', + 'QZ' => '972', + 'RE' => '638', + 'RO' => '642', + 'RS' => '688', + 'RU' => '643', + 'RW' => '646', + 'SA' => '682', + 'SB' => '090', + 'SC' => '690', + 'SD' => '729', + 'SE' => '752', + 'SG' => '702', + 'SH' => '654', + 'SI' => '705', + 'SJ' => '744', + 'SK' => '703', + 'SL' => '694', + 'SM' => '674', + 'SN' => '686', + 'SO' => '706', + 'SR' => '740', + 'SS' => '728', + 'ST' => '678', + 'SV' => '222', + 'SX' => '534', + 'SY' => '760', + 'SZ' => '748', + 'TC' => '796', + 'TD' => '148', + 'TF' => '260', + 'TG' => '768', + 'TH' => '764', + 'TJ' => '762', + 'TK' => '772', + 'TL' => '626', + 'TM' => '795', + 'TN' => '788', + 'TO' => '776', + 'TR' => '792', + 'TT' => '780', + 'TV' => '798', + 'TW' => '158', + 'TZ' => '834', + 'UA' => '804', + 'UG' => '800', + 'UM' => '581', + 'US' => '840', + 'UY' => '858', + 'UZ' => '860', + 'VA' => '336', + 'VC' => '670', + 'VE' => '862', + 'VG' => '092', + 'VI' => '850', + 'VN' => '704', + 'VU' => '548', + 'WF' => '876', + 'WS' => '882', + 'XC' => '975', + 'XD' => '976', + 'XE' => '977', + 'XF' => '978', + 'XG' => '979', + 'XH' => '980', + 'XI' => '981', + 'XJ' => '982', + 'XL' => '984', + 'XM' => '985', + 'XN' => '986', + 'XO' => '987', + 'XP' => '988', + 'XQ' => '989', + 'XR' => '990', + 'XS' => '991', + 'XT' => '992', + 'XU' => '993', + 'XV' => '994', + 'XW' => '995', + 'XX' => '996', + 'XY' => '997', + 'XZ' => '998', + 'YE' => '887', + 'YT' => '175', + 'ZA' => '710', + 'ZM' => '894', + 'ZW' => '716', + ], + 'NumericToAlpha2' => [ + '_958' => 'AA', + '_020' => 'AD', + '_784' => 'AE', + '_004' => 'AF', + '_028' => 'AG', + '_660' => 'AI', + '_008' => 'AL', + '_051' => 'AM', + '_024' => 'AO', + '_010' => 'AQ', + '_032' => 'AR', + '_016' => 'AS', + '_040' => 'AT', + '_036' => 'AU', + '_533' => 'AW', + '_248' => 'AX', + '_031' => 'AZ', + '_070' => 'BA', + '_052' => 'BB', + '_050' => 'BD', + '_056' => 'BE', + '_854' => 'BF', + '_100' => 'BG', + '_048' => 'BH', + '_108' => 'BI', + '_204' => 'BJ', + '_652' => 'BL', + '_060' => 'BM', + '_096' => 'BN', + '_068' => 'BO', + '_535' => 'BQ', + '_076' => 'BR', + '_044' => 'BS', + '_064' => 'BT', + '_074' => 'BV', + '_072' => 'BW', + '_112' => 'BY', + '_084' => 'BZ', + '_124' => 'CA', + '_166' => 'CC', + '_180' => 'CD', + '_140' => 'CF', + '_178' => 'CG', + '_756' => 'CH', + '_384' => 'CI', + '_184' => 'CK', + '_152' => 'CL', + '_120' => 'CM', + '_156' => 'CN', + '_170' => 'CO', + '_188' => 'CR', + '_192' => 'CU', + '_132' => 'CV', + '_531' => 'CW', + '_162' => 'CX', + '_196' => 'CY', + '_203' => 'CZ', + '_276' => 'DE', + '_262' => 'DJ', + '_208' => 'DK', + '_212' => 'DM', + '_214' => 'DO', + '_012' => 'DZ', + '_218' => 'EC', + '_233' => 'EE', + '_818' => 'EG', + '_732' => 'EH', + '_232' => 'ER', + '_724' => 'ES', + '_231' => 'ET', + '_246' => 'FI', + '_242' => 'FJ', + '_238' => 'FK', + '_583' => 'FM', + '_234' => 'FO', + '_250' => 'FR', + '_266' => 'GA', + '_826' => 'GB', + '_308' => 'GD', + '_268' => 'GE', + '_254' => 'GF', + '_831' => 'GG', + '_288' => 'GH', + '_292' => 'GI', + '_304' => 'GL', + '_270' => 'GM', + '_324' => 'GN', + '_312' => 'GP', + '_226' => 'GQ', + '_300' => 'GR', + '_239' => 'GS', + '_320' => 'GT', + '_316' => 'GU', + '_624' => 'GW', + '_328' => 'GY', + '_344' => 'HK', + '_334' => 'HM', + '_340' => 'HN', + '_191' => 'HR', + '_332' => 'HT', + '_348' => 'HU', + '_360' => 'ID', + '_372' => 'IE', + '_376' => 'IL', + '_833' => 'IM', + '_356' => 'IN', + '_086' => 'IO', + '_368' => 'IQ', + '_364' => 'IR', + '_352' => 'IS', + '_380' => 'IT', + '_832' => 'JE', + '_388' => 'JM', + '_400' => 'JO', + '_392' => 'JP', + '_404' => 'KE', + '_417' => 'KG', + '_116' => 'KH', + '_296' => 'KI', + '_174' => 'KM', + '_659' => 'KN', + '_408' => 'KP', + '_410' => 'KR', + '_414' => 'KW', + '_136' => 'KY', + '_398' => 'KZ', + '_418' => 'LA', + '_422' => 'LB', + '_662' => 'LC', + '_438' => 'LI', + '_144' => 'LK', + '_430' => 'LR', + '_426' => 'LS', + '_440' => 'LT', + '_442' => 'LU', + '_428' => 'LV', + '_434' => 'LY', + '_504' => 'MA', + '_492' => 'MC', + '_498' => 'MD', + '_499' => 'ME', + '_663' => 'MF', + '_450' => 'MG', + '_584' => 'MH', + '_807' => 'MK', + '_466' => 'ML', + '_104' => 'MM', + '_496' => 'MN', + '_446' => 'MO', + '_580' => 'MP', + '_474' => 'MQ', + '_478' => 'MR', + '_500' => 'MS', + '_470' => 'MT', + '_480' => 'MU', + '_462' => 'MV', + '_454' => 'MW', + '_484' => 'MX', + '_458' => 'MY', + '_508' => 'MZ', + '_516' => 'NA', + '_540' => 'NC', + '_562' => 'NE', + '_574' => 'NF', + '_566' => 'NG', + '_558' => 'NI', + '_528' => 'NL', + '_578' => 'NO', + '_524' => 'NP', + '_520' => 'NR', + '_570' => 'NU', + '_554' => 'NZ', + '_512' => 'OM', + '_591' => 'PA', + '_604' => 'PE', + '_258' => 'PF', + '_598' => 'PG', + '_608' => 'PH', + '_586' => 'PK', + '_616' => 'PL', + '_666' => 'PM', + '_612' => 'PN', + '_630' => 'PR', + '_275' => 'PS', + '_620' => 'PT', + '_585' => 'PW', + '_600' => 'PY', + '_634' => 'QA', + '_959' => 'QM', + '_960' => 'QN', + '_962' => 'QP', + '_963' => 'QQ', + '_964' => 'QR', + '_965' => 'QS', + '_966' => 'QT', + '_968' => 'QV', + '_969' => 'QW', + '_970' => 'QX', + '_971' => 'QY', + '_972' => 'QZ', + '_638' => 'RE', + '_642' => 'RO', + '_688' => 'RS', + '_643' => 'RU', + '_646' => 'RW', + '_682' => 'SA', + '_090' => 'SB', + '_690' => 'SC', + '_729' => 'SD', + '_752' => 'SE', + '_702' => 'SG', + '_654' => 'SH', + '_705' => 'SI', + '_744' => 'SJ', + '_703' => 'SK', + '_694' => 'SL', + '_674' => 'SM', + '_686' => 'SN', + '_706' => 'SO', + '_740' => 'SR', + '_728' => 'SS', + '_678' => 'ST', + '_222' => 'SV', + '_534' => 'SX', + '_760' => 'SY', + '_748' => 'SZ', + '_796' => 'TC', + '_148' => 'TD', + '_260' => 'TF', + '_768' => 'TG', + '_764' => 'TH', + '_762' => 'TJ', + '_772' => 'TK', + '_626' => 'TL', + '_795' => 'TM', + '_788' => 'TN', + '_776' => 'TO', + '_792' => 'TR', + '_780' => 'TT', + '_798' => 'TV', + '_158' => 'TW', + '_834' => 'TZ', + '_804' => 'UA', + '_800' => 'UG', + '_581' => 'UM', + '_840' => 'US', + '_858' => 'UY', + '_860' => 'UZ', + '_336' => 'VA', + '_670' => 'VC', + '_862' => 'VE', + '_092' => 'VG', + '_850' => 'VI', + '_704' => 'VN', + '_548' => 'VU', + '_876' => 'WF', + '_882' => 'WS', + '_975' => 'XC', + '_976' => 'XD', + '_977' => 'XE', + '_978' => 'XF', + '_979' => 'XG', + '_980' => 'XH', + '_981' => 'XI', + '_982' => 'XJ', + '_984' => 'XL', + '_985' => 'XM', + '_986' => 'XN', + '_987' => 'XO', + '_988' => 'XP', + '_989' => 'XQ', + '_990' => 'XR', + '_991' => 'XS', + '_992' => 'XT', + '_993' => 'XU', + '_994' => 'XV', + '_995' => 'XW', + '_996' => 'XX', + '_997' => 'XY', + '_998' => 'XZ', + '_887' => 'YE', + '_175' => 'YT', + '_710' => 'ZA', + '_894' => 'ZM', + '_716' => 'ZW', + ], ]; diff --git a/Tests/CountriesTest.php b/Tests/CountriesTest.php index f35932e5..d2654ece 100644 --- a/Tests/CountriesTest.php +++ b/Tests/CountriesTest.php @@ -525,6 +525,294 @@ class CountriesTest extends ResourceBundleTestCase 'ZW' => 'ZWE', ]; + private const ALPHA2_TO_NUMERIC = [ + 'AA' => '958', + 'AD' => '020', + 'AE' => '784', + 'AF' => '004', + 'AG' => '028', + 'AI' => '660', + 'AL' => '008', + 'AM' => '051', + 'AO' => '024', + 'AQ' => '010', + 'AR' => '032', + 'AS' => '016', + 'AT' => '040', + 'AU' => '036', + 'AW' => '533', + 'AX' => '248', + 'AZ' => '031', + 'BA' => '070', + 'BB' => '052', + 'BD' => '050', + 'BE' => '056', + 'BF' => '854', + 'BG' => '100', + 'BH' => '048', + 'BI' => '108', + 'BJ' => '204', + 'BL' => '652', + 'BM' => '060', + 'BN' => '096', + 'BO' => '068', + 'BQ' => '535', + 'BR' => '076', + 'BS' => '044', + 'BT' => '064', + 'BV' => '074', + 'BW' => '072', + 'BY' => '112', + 'BZ' => '084', + 'CA' => '124', + 'CC' => '166', + 'CD' => '180', + 'CF' => '140', + 'CG' => '178', + 'CH' => '756', + 'CI' => '384', + 'CK' => '184', + 'CL' => '152', + 'CM' => '120', + 'CN' => '156', + 'CO' => '170', + 'CR' => '188', + 'CU' => '192', + 'CV' => '132', + 'CW' => '531', + 'CX' => '162', + 'CY' => '196', + 'CZ' => '203', + 'DE' => '276', + 'DJ' => '262', + 'DK' => '208', + 'DM' => '212', + 'DO' => '214', + 'DZ' => '012', + 'EC' => '218', + 'EE' => '233', + 'EG' => '818', + 'EH' => '732', + 'ER' => '232', + 'ES' => '724', + 'ET' => '231', + 'FI' => '246', + 'FJ' => '242', + 'FK' => '238', + 'FM' => '583', + 'FO' => '234', + 'FR' => '250', + 'GA' => '266', + 'GB' => '826', + 'GD' => '308', + 'GE' => '268', + 'GF' => '254', + 'GG' => '831', + 'GH' => '288', + 'GI' => '292', + 'GL' => '304', + 'GM' => '270', + 'GN' => '324', + 'GP' => '312', + 'GQ' => '226', + 'GR' => '300', + 'GS' => '239', + 'GT' => '320', + 'GU' => '316', + 'GW' => '624', + 'GY' => '328', + 'HK' => '344', + 'HM' => '334', + 'HN' => '340', + 'HR' => '191', + 'HT' => '332', + 'HU' => '348', + 'ID' => '360', + 'IE' => '372', + 'IL' => '376', + 'IM' => '833', + 'IN' => '356', + 'IO' => '086', + 'IQ' => '368', + 'IR' => '364', + 'IS' => '352', + 'IT' => '380', + 'JE' => '832', + 'JM' => '388', + 'JO' => '400', + 'JP' => '392', + 'KE' => '404', + 'KG' => '417', + 'KH' => '116', + 'KI' => '296', + 'KM' => '174', + 'KN' => '659', + 'KP' => '408', + 'KR' => '410', + 'KW' => '414', + 'KY' => '136', + 'KZ' => '398', + 'LA' => '418', + 'LB' => '422', + 'LC' => '662', + 'LI' => '438', + 'LK' => '144', + 'LR' => '430', + 'LS' => '426', + 'LT' => '440', + 'LU' => '442', + 'LV' => '428', + 'LY' => '434', + 'MA' => '504', + 'MC' => '492', + 'MD' => '498', + 'ME' => '499', + 'MF' => '663', + 'MG' => '450', + 'MH' => '584', + 'MK' => '807', + 'ML' => '466', + 'MM' => '104', + 'MN' => '496', + 'MO' => '446', + 'MP' => '580', + 'MQ' => '474', + 'MR' => '478', + 'MS' => '500', + 'MT' => '470', + 'MU' => '480', + 'MV' => '462', + 'MW' => '454', + 'MX' => '484', + 'MY' => '458', + 'MZ' => '508', + 'NA' => '516', + 'NC' => '540', + 'NE' => '562', + 'NF' => '574', + 'NG' => '566', + 'NI' => '558', + 'NL' => '528', + 'NO' => '578', + 'NP' => '524', + 'NR' => '520', + 'NU' => '570', + 'NZ' => '554', + 'OM' => '512', + 'PA' => '591', + 'PE' => '604', + 'PF' => '258', + 'PG' => '598', + 'PH' => '608', + 'PK' => '586', + 'PL' => '616', + 'PM' => '666', + 'PN' => '612', + 'PR' => '630', + 'PS' => '275', + 'PT' => '620', + 'PW' => '585', + 'PY' => '600', + 'QA' => '634', + 'QM' => '959', + 'QN' => '960', + 'QP' => '962', + 'QQ' => '963', + 'QR' => '964', + 'QS' => '965', + 'QT' => '966', + 'QV' => '968', + 'QW' => '969', + 'QX' => '970', + 'QY' => '971', + 'QZ' => '972', + 'RE' => '638', + 'RO' => '642', + 'RS' => '688', + 'RU' => '643', + 'RW' => '646', + 'SA' => '682', + 'SB' => '090', + 'SC' => '690', + 'SD' => '729', + 'SE' => '752', + 'SG' => '702', + 'SH' => '654', + 'SI' => '705', + 'SJ' => '744', + 'SK' => '703', + 'SL' => '694', + 'SM' => '674', + 'SN' => '686', + 'SO' => '706', + 'SR' => '740', + 'SS' => '728', + 'ST' => '678', + 'SV' => '222', + 'SX' => '534', + 'SY' => '760', + 'SZ' => '748', + 'TC' => '796', + 'TD' => '148', + 'TF' => '260', + 'TG' => '768', + 'TH' => '764', + 'TJ' => '762', + 'TK' => '772', + 'TL' => '626', + 'TM' => '795', + 'TN' => '788', + 'TO' => '776', + 'TR' => '792', + 'TT' => '780', + 'TV' => '798', + 'TW' => '158', + 'TZ' => '834', + 'UA' => '804', + 'UG' => '800', + 'UM' => '581', + 'US' => '840', + 'UY' => '858', + 'UZ' => '860', + 'VA' => '336', + 'VC' => '670', + 'VE' => '862', + 'VG' => '092', + 'VI' => '850', + 'VN' => '704', + 'VU' => '548', + 'WF' => '876', + 'WS' => '882', + 'XC' => '975', + 'XD' => '976', + 'XE' => '977', + 'XF' => '978', + 'XG' => '979', + 'XH' => '980', + 'XI' => '981', + 'XJ' => '982', + 'XL' => '984', + 'XM' => '985', + 'XN' => '986', + 'XO' => '987', + 'XP' => '988', + 'XQ' => '989', + 'XR' => '990', + 'XS' => '991', + 'XT' => '992', + 'XU' => '993', + 'XV' => '994', + 'XW' => '995', + 'XX' => '996', + 'XY' => '997', + 'XZ' => '998', + 'YE' => '887', + 'YT' => '175', + 'ZA' => '710', + 'ZM' => '894', + 'ZW' => '716', + ]; + public function testGetCountryCodes() { $this->assertSame(self::COUNTRIES, Countries::getCountryCodes()); @@ -665,4 +953,43 @@ public function testGetAlpha3Names($displayLocale) $alpha2Names = Countries::getNames($displayLocale); $this->assertSame(array_values($alpha2Names), array_values($names)); } + + public function testGetNumericCodes() + { + $this->assertSame(self::ALPHA2_TO_NUMERIC, Countries::getNumericCodes()); + } + + public function testGetNumericCode() + { + foreach (self::COUNTRIES as $country) { + $this->assertSame(self::ALPHA2_TO_NUMERIC[$country], Countries::getNumericCode($country)); + } + } + + public function testNumericCodeExists() + { + $this->assertTrue(Countries::numericCodeExists('250')); + $this->assertTrue(Countries::numericCodeExists('982')); + $this->assertTrue(Countries::numericCodeExists('716')); + $this->assertTrue(Countries::numericCodeExists('036')); + $this->assertFalse(Countries::numericCodeExists('667')); + } + + public function testGetAlpha2FromNumeric() + { + $alpha2Lookup = array_flip(self::ALPHA2_TO_NUMERIC); + + foreach (self::ALPHA2_TO_NUMERIC as $numeric) { + $this->assertSame($alpha2Lookup[$numeric], Countries::getAlpha2FromNumeric($numeric)); + } + } + + public function testNumericCodesDoNotContainDenyListItems() + { + $numericCodes = Countries::getNumericCodes(); + + $this->assertArrayNotHasKey('EZ', $numericCodes); + $this->assertArrayNotHasKey('XA', $numericCodes); + $this->assertArrayNotHasKey('ZZ', $numericCodes); + } }