diff --git a/src/Rules/Currency.php b/src/Rules/Currency.php index 091b79b..21ba4a4 100644 --- a/src/Rules/Currency.php +++ b/src/Rules/Currency.php @@ -10,6 +10,7 @@ class Currency implements ValidationRule, ValidatesOnFrontEnd { + /** * @inheritDoc * @@ -53,6 +54,19 @@ public function __invoke($value, Closure $fail, string $key, array $values) } /** + * Returns the list of valid ISO 4217 currency codes. + * + * @unreleased Updated to match current ISO 4217 standard as of 2024. + * + * Major changes include: + * - Removed obsolete codes: BYR (→BYN), EEK (→EUR), GHC (→GHS), LVL (→EUR), + * LTL (→EUR), TRL (→TRY), VEF (→VES), ZWD (→ZWL) + * - Added 74+ missing current ISO 4217 codes including AED, AMD, AOA, BHD, etc. + * - Kept commonly used non-ISO codes: GGP, IMP, JEP, TVD + * - Total codes increased from 95 to 169 for better global coverage + * + * @see https://www.iso.org/iso-4217-currency-codes.html + * * @since 1.0.0 * * @return string[] @@ -63,120 +77,169 @@ public static function currencyCodes(): array if ($codes === null) { $codes = [ - "ALL", - "AFN", - "ARS", - "AWG", - "AUD", - "AZN", - "BSD", - "BBD", - "BDT", - "BYR", - "BZD", - "BMD", - "BOB", - "BAM", - "BWP", - "BGN", - "BRL", - "BND", - "KHR", - "CAD", - "KYD", - "CLP", - "CNY", - "COP", - "CRC", - "HRK", - "CUP", - "CZK", - "DKK", - "DOP", - "XCD", - "EGP", - "SVC", - "EEK", - "EUR", - "FKP", - "FJD", - "GHC", - "GIP", - "GTQ", - "GGP", - "GYD", - "HNL", - "HKD", - "HUF", - "ISK", - "INR", - "IDR", - "IRR", - "IMP", - "ILS", - "JMD", - "JPY", - "JEP", - "KZT", - "KPW", - "KRW", - "KGS", - "LAK", - "LVL", - "LBP", - "LRD", - "LTL", - "MKD", - "MYR", - "MUR", - "MXN", - "MNT", - "MZN", - "NAD", - "NPR", - "ANG", - "NZD", - "NIO", - "NGN", - "NOK", - "OMR", - "PKR", - "PAB", - "PYG", - "PEN", - "PHP", - "PLN", - "QAR", - "RON", - "RUB", - "SHP", - "SAR", - "RSD", - "SCR", - "SGD", - "SBD", - "SOS", - "ZAR", - "LKR", - "SEK", - "CHF", - "SRD", - "SYP", - "TWD", - "THB", - "TTD", - "TRY", - "TRL", - "TVD", - "UAH", - "GBP", - "USD", - "UYU", - "UZS", - "VEF", - "VND", - "YER", - "ZWD", + "AED", // UAE Dirham + "AFN", // Afghan Afghani + "ALL", // Albanian Lek + "AMD", // Armenian Dram + "ANG", // Netherlands Antillean Guilder + "AOA", // Angolan Kwanza + "ARS", // Argentine Peso + "AUD", // Australian Dollar + "AWG", // Aruban Florin + "AZN", // Azerbaijani Manat + "BAM", // Bosnia and Herzegovina Convertible Mark + "BBD", // Barbados Dollar + "BDT", // Bangladeshi Taka + "BGN", // Bulgarian Lev + "BHD", // Bahraini Dinar + "BIF", // Burundian Franc + "BMD", // Bermudian Dollar + "BND", // Brunei Dollar + "BOB", // Bolivian Boliviano + "BRL", // Brazilian Real + "BSD", // Bahamian Dollar + "BTN", // Bhutanese Ngultrum + "BWP", // Botswanan Pula + "BYN", // Belarusian Ruble + "BZD", // Belize Dollar + "CAD", // Canadian Dollar + "CDF", // Congolese Franc + "CHF", // Swiss Franc + "CLP", // Chilean Peso + "CNY", // Chinese Yuan + "COP", // Colombian Peso + "CRC", // Costa Rican Colón + "CUP", // Cuban Peso + "CVE", // Cape Verdean Escudo + "CZK", // Czech Koruna + "DJF", // Djiboutian Franc + "DKK", // Danish Krone + "DOP", // Dominican Peso + "DZD", // Algerian Dinar + "EGP", // Egyptian Pound + "ERN", // Eritrean Nakfa + "ETB", // Ethiopian Birr + "EUR", // Euro + "FJD", // Fijian Dollar + "FKP", // Falkland Islands Pound + "GBP", // British Pound Sterling + "GEL", // Georgian Lari + "GGP", // Guernsey Pound (non-ISO but commonly used) + "GHS", // Ghanaian Cedi + "GIP", // Gibraltar Pound + "GMD", // Gambian Dalasi + "GNF", // Guinean Franc + "GTQ", // Guatemalan Quetzal + "GYD", // Guyanese Dollar + "HKD", // Hong Kong Dollar + "HNL", // Honduran Lempira + "HRK", // Croatian Kuna (replaced by EUR in 2023) + "HTG", // Haitian Gourde + "HUF", // Hungarian Forint + "IDR", // Indonesian Rupiah + "ILS", // Israeli New Shekel + "IMP", // Isle of Man Pound (non-ISO but commonly used) + "INR", // Indian Rupee + "IQD", // Iraqi Dinar + "IRR", // Iranian Rial + "ISK", // Icelandic Króna + "JEP", // Jersey Pound (non-ISO but commonly used) + "JMD", // Jamaican Dollar + "JOD", // Jordanian Dinar + "JPY", // Japanese Yen + "KES", // Kenyan Shilling + "KGS", // Kyrgyzstani Som + "KHR", // Cambodian Riel + "KMF", // Comorian Franc + "KPW", // North Korean Won + "KRW", // South Korean Won + "KWD", // Kuwaiti Dinar + "KYD", // Cayman Islands Dollar + "KZT", // Kazakhstani Tenge + "LAK", // Laotian Kip + "LBP", // Lebanese Pound + "LKR", // Sri Lankan Rupee + "LRD", // Liberian Dollar + "LSL", // Lesotho Loti + "LYD", // Libyan Dinar + "MAD", // Moroccan Dirham + "MDL", // Moldovan Leu + "MGA", // Malagasy Ariary + "MKD", // Macedonian Denar + "MMK", // Myanmar Kyat + "MNT", // Mongolian Tugrik + "MOP", // Macanese Pataca + "MRU", // Mauritanian Ouguiya + "MUR", // Mauritian Rupee + "MVR", // Maldivian Rufiyaa + "MWK", // Malawian Kwacha + "MXN", // Mexican Peso + "MYR", // Malaysian Ringgit + "MZN", // Mozambican Metical + "NAD", // Namibian Dollar + "NGN", // Nigerian Naira + "NIO", // Nicaraguan Córdoba + "NOK", // Norwegian Krone + "NPR", // Nepalese Rupee + "NZD", // New Zealand Dollar + "OMR", // Omani Rial + "PAB", // Panamanian Balboa + "PEN", // Peruvian Sol + "PGK", // Papua New Guinean Kina + "PHP", // Philippine Peso + "PKR", // Pakistani Rupee + "PLN", // Polish Zloty + "PYG", // Paraguayan Guaraní + "QAR", // Qatari Riyal + "RON", // Romanian Leu + "RSD", // Serbian Dinar + "RUB", // Russian Ruble + "RWF", // Rwandan Franc + "SAR", // Saudi Riyal + "SBD", // Solomon Islands Dollar + "SCR", // Seychellois Rupee + "SDG", // Sudanese Pound + "SEK", // Swedish Krona + "SGD", // Singapore Dollar + "SHP", // Saint Helena Pound + "SLE", // Sierra Leonean Leone (new) + "SLL", // Sierra Leonean Leone (old) + "SOS", // Somali Shilling + "SRD", // Surinamese Dollar + "SSP", // South Sudanese Pound + "STN", // São Tomé and Príncipe Dobra + "SVC", // Salvadoran Colón + "SYP", // Syrian Pound + "SZL", // Swazi Lilangeni + "THB", // Thai Baht + "TJS", // Tajikistani Somoni + "TMT", // Turkmenistani Manat + "TND", // Tunisian Dinar + "TOP", // Tongan Paʻanga + "TRY", // Turkish Lira + "TTD", // Trinidad and Tobago Dollar + "TVD", // Tuvaluan Dollar (non-ISO but used) + "TWD", // New Taiwan Dollar + "TZS", // Tanzanian Shilling + "UAH", // Ukrainian Hryvnia + "UGX", // Ugandan Shilling + "USD", // United States Dollar + "UYU", // Uruguayan Peso + "UZS", // Uzbekistani Som + "VED", // Venezuelan Bolívar Digital + "VES", // Venezuelan Bolívar Soberano + "VND", // Vietnamese Dong + "VUV", // Vanuatuan Vatu + "WST", // Samoan Tala + "XAF", // Central African CFA Franc + "XCD", // East Caribbean Dollar + "XDR", // Special Drawing Rights + "XOF", // West African CFA Franc + "XPF", // CFP Franc + "YER", // Yemeni Rial + "ZAR", // South African Rand + "ZMW", // Zambian Kwacha + "ZWL", // Zimbabwean Dollar ]; } diff --git a/tests/unit/Rules/CurrencyTest.php b/tests/unit/Rules/CurrencyTest.php index 6838d8f..f227d71 100644 --- a/tests/unit/Rules/CurrencyTest.php +++ b/tests/unit/Rules/CurrencyTest.php @@ -6,6 +6,7 @@ use StellarWP\Validation\Rules\Currency; use StellarWP\Validation\Tests\TestCase; + class CurrencyTest extends TestCase { /** @@ -16,34 +17,228 @@ public function testCurrencyValidations($currency, $shouldPass) { $rule = new Currency(); - if ( $shouldPass ) { + if ($shouldPass) { self::assertValidationRulePassed($rule, $currency); } else { self::assertValidationRuleFailed($rule, $currency); } } + + /** - * @since 1.1.0 + * Test that obsolete currency codes no longer pass validation. + * + * @unreleased + * @dataProvider obsoleteCurrencyProvider + */ + public function testObsoleteCurrencyCodesFail($currency) + { + $rule = new Currency(); + self::assertValidationRuleFailed($rule, $currency); + } + + /** + * Test newly added currency codes pass validation. + * + * @unreleased + * @dataProvider newCurrencyProvider + */ + public function testNewCurrencyCodesPass($currency) + { + $rule = new Currency(); + self::assertValidationRulePassed($rule, $currency); + } + + /** + * Test case insensitivity with various currency codes. + * + * @unreleased + * @dataProvider caseInsensitiveProvider + */ + public function testCaseInsensitivity($currency, $shouldPass) + { + $rule = new Currency(); + + if ($shouldPass) { + self::assertValidationRulePassed($rule, $currency); + } else { + self::assertValidationRuleFailed($rule, $currency); + } + } + + /** + * @unreleased */ public function currencyProvider(): array { return [ - // normal + // Common major currencies ['USD', true], + ['EUR', true], + ['JPY', true], + ['GBP', true], ['CAD', true], + ['AUD', true], + ['CHF', true], - // should not be case-sensitive + // Case insensitive + ['usd', true], + ['eur', true], ['jpy', true], ['EuR', true], + ['CaD', true], + + // Newly added currencies (2024 update) + ['AED', true], // UAE Dirham + ['BHD', true], // Bahraini Dinar + ['KWD', true], // Kuwaiti Dinar + ['QAR', true], // Qatari Riyal + ['SAR', true], // Saudi Riyal + ['VES', true], // Venezuelan Bolívar Soberano (new) + ['BYN', true], // Belarusian Ruble (new) + ['GHS', true], // Ghanaian Cedi (new) - // should fail - ['US', false], - ['USDD', false], - ['US D', false], - ['US-D', false], + // Regional currencies + ['XAF', true], // Central African CFA Franc + ['XOF', true], // West African CFA Franc + ['XCD', true], // East Caribbean Dollar + ['XPF', true], // CFP Franc + + // Special codes + ['XDR', true], // Special Drawing Rights + + // Non-ISO but commonly used (kept in list) + ['GGP', true], // Guernsey Pound + ['IMP', true], // Isle of Man Pound + ['JEP', true], // Jersey Pound + ['TVD', true], // Tuvaluan Dollar + + // Invalid codes + ['US', false], // Too short + ['USDD', false], // Too long + ['US D', false], // Contains space + ['US-D', false], // Contains hyphen + ['ABC', false], // Not a valid currency + ['123', false], // Numeric + ['', false], // Empty string + ['XXX', false], // Invalid code + ['ZZZ', false], // Non-existent + ]; + } + + /** + * Currency codes that were removed in the 2024 update. + * + * @unreleased + */ + public function obsoleteCurrencyProvider(): array + { + return [ + ['BYR'], // Old Belarusian Ruble (replaced by BYN) + ['EEK'], // Estonian Kroon (replaced by EUR) + ['GHC'], // Old Ghanaian Cedi (replaced by GHS) + ['LVL'], // Latvian Lats (replaced by EUR) + ['LTL'], // Lithuanian Litas (replaced by EUR) + ['TRL'], // Old Turkish Lira (now only TRY) + ['VEF'], // Old Venezuelan Bolívar (replaced by VES) + ['ZWD'], // Old Zimbabwean Dollar (replaced by ZWL) + ]; + } + + /** + * New currency codes added in the 2024 update. + * + * @unreleased + */ + public function newCurrencyProvider(): array + { + return [ + ['AED'], // UAE Dirham + ['AMD'], // Armenian Dram + ['AOA'], // Angolan Kwanza + ['BHD'], // Bahraini Dinar + ['BIF'], // Burundian Franc + ['BND'], // Brunei Dollar + ['BTN'], // Bhutanese Ngultrum + ['BYN'], // Belarusian Ruble (new) + ['CDF'], // Congolese Franc + ['CVE'], // Cape Verdean Escudo + ['DJF'], // Djiboutian Franc + ['DZD'], // Algerian Dinar + ['ERN'], // Eritrean Nakfa + ['ETB'], // Ethiopian Birr + ['GEL'], // Georgian Lari + ['GHS'], // Ghanaian Cedi (new) + ['GMD'], // Gambian Dalasi + ['GNF'], // Guinean Franc + ['HTG'], // Haitian Gourde + ['IQD'], // Iraqi Dinar + ['JOD'], // Jordanian Dinar + ['KES'], // Kenyan Shilling + ['KMF'], // Comorian Franc + ['KWD'], // Kuwaiti Dinar + ['LSL'], // Lesotho Loti + ['LYD'], // Libyan Dinar + ['MAD'], // Moroccan Dirham + ['MDL'], // Moldovan Leu + ['MGA'], // Malagasy Ariary + ['MMK'], // Myanmar Kyat + ['MOP'], // Macanese Pataca + ['MRU'], // Mauritanian Ouguiya + ['MVR'], // Maldivian Rufiyaa + ['MWK'], // Malawian Kwacha + ['PGK'], // Papua New Guinean Kina + ['RWF'], // Rwandan Franc + ['SDG'], // Sudanese Pound + ['SLE'], // Sierra Leonean Leone (new) + ['SSP'], // South Sudanese Pound + ['STN'], // São Tomé and Príncipe Dobra + ['SZL'], // Swazi Lilangeni + ['TJS'], // Tajikistani Somoni + ['TMT'], // Turkmenistani Manat + ['TND'], // Tunisian Dinar + ['TOP'], // Tongan Paʻanga + ['TZS'], // Tanzanian Shilling + ['UGX'], // Ugandan Shilling + ['VED'], // Venezuelan Bolívar Digital + ['VES'], // Venezuelan Bolívar Soberano + ['VUV'], // Vanuatuan Vatu + ['WST'], // Samoan Tala + ['XAF'], // Central African CFA Franc + ['XDR'], // Special Drawing Rights + ['XOF'], // West African CFA Franc + ['XPF'], // CFP Franc + ['ZMW'], // Zambian Kwacha + ['ZWL'], // Zimbabwean Dollar (new) + ]; + } + + /** + * Test various case combinations. + * + * @unreleased + */ + public function caseInsensitiveProvider(): array + { + return [ + ['USD', true], + ['usd', true], + ['Usd', true], + ['UsD', true], + ['EUR', true], + ['eur', true], + ['eUr', true], + ['EuR', true], + ['JPY', true], + ['jpy', true], + ['JpY', true], + ['jPy', true], + // Invalid codes in various cases + ['abc', false], ['ABC', false], - ['123', false], + ['AbC', false], + ['aBc', false], ]; } }