diff --git a/NEWS b/NEWS index 286fb43b22de0..98f8efa4fadfd 100644 --- a/NEWS +++ b/NEWS @@ -94,6 +94,8 @@ PHP NEWS (David Carlier) . Added null bytes presence in locale inputs for Locale class. (David Carlier) . Added grapheme_levenshtein() function. (Yuya Hamada) + . Added Locale::addLikelySubtags/Locale::minimizeSubtags to handle + adding/removing likely subtags to a locale. (David Carlier) - MySQLi: . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice). diff --git a/UPGRADING b/UPGRADING index 9eb9694233fce..04bc66c4890c4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -178,6 +178,8 @@ PHP 8.5 UPGRADE NOTES NumberFormatter::CURRENCY_PLURAL, NumberFormatter::CASH_CURRENCY, and NumberFormatter::CURRENCY_STANDARD for various currency-related number formats. + . Added Locale::addLikelySubtags and Locale::minimizeSubtags to + handle likely tags on a given locale. - XSL: . The $namespace argument of XSLTProcessor::getParameter(), diff --git a/ext/intl/locale/locale.stub.php b/ext/intl/locale/locale.stub.php index fcda8f68409ce..03813ecaf194f 100644 --- a/ext/intl/locale/locale.stub.php +++ b/ext/intl/locale/locale.stub.php @@ -138,4 +138,14 @@ public static function acceptFromHttp(string $header): string|false {} * @alias locale_is_right_to_left */ public static function isRightToLeft(string $locale): bool {} + + /** + * @alias locale_add_likely_subtags + */ + public static function addLikelySubtags(string $locale): string|false {} + + /** + * @alias locale_minimize_subtags + */ + public static function minimizeSubtags(string $locale): string|false {} } diff --git a/ext/intl/locale/locale_arginfo.h b/ext/intl/locale/locale_arginfo.h index 40426a1aa9e78..79a16452e2975 100644 --- a/ext/intl/locale/locale_arginfo.h +++ b/ext/intl/locale/locale_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: f09cfd61f3e20576c7f6d5da17a6d9c009d6ab64 */ + * Stub hash: ff1f75bd34a52f57210734e2f5e29efb87566137 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Locale_getDefault, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -66,6 +66,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Locale_isRightToLeft, 0, 1 ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Locale_addLikelySubtags, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Locale_minimizeSubtags arginfo_class_Locale_addLikelySubtags + ZEND_FUNCTION(locale_get_default); ZEND_FUNCTION(locale_set_default); ZEND_FUNCTION(locale_get_primary_language); @@ -85,6 +91,8 @@ ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_accept_from_http); ZEND_FUNCTION(locale_is_right_to_left); +ZEND_FUNCTION(locale_add_likely_subtags); +ZEND_FUNCTION(locale_minimize_subtags); static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("getDefault", zif_locale_get_default, arginfo_class_Locale_getDefault, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) @@ -106,6 +114,8 @@ static const zend_function_entry class_Locale_methods[] = { ZEND_RAW_FENTRY("canonicalize", zif_locale_canonicalize, arginfo_class_Locale_canonicalize, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("acceptFromHttp", zif_locale_accept_from_http, arginfo_class_Locale_acceptFromHttp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_RAW_FENTRY("isRightToLeft", zif_locale_is_right_to_left, arginfo_class_Locale_isRightToLeft, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) + ZEND_RAW_FENTRY("addLikelySubtags", zif_locale_add_likely_subtags, arginfo_class_Locale_addLikelySubtags, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) + ZEND_RAW_FENTRY("minimizeSubtags", zif_locale_minimize_subtags, arginfo_class_Locale_minimizeSubtags, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, NULL) ZEND_FE_END }; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index 684f84c7e323a..6f5158fcb46bb 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1639,3 +1639,49 @@ PHP_FUNCTION(locale_is_right_to_left) RETURN_BOOL(uloc_isRightToLeft(locale)); } + +PHP_FUNCTION(locale_add_likely_subtags) +{ + char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = 0; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t maximized_locale_len = uloc_addLikelySubtags(locale, maximized_locale, sizeof(maximized_locale), &status); + INTL_CHECK_STATUS(status, "locale_add_likely_subtags: invalid locale"); + if (maximized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(maximized_locale, maximized_locale_len); +} + +PHP_FUNCTION(locale_minimize_subtags) +{ + char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = 0; + size_t locale_len; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH(locale, locale_len) + ZEND_PARSE_PARAMETERS_END(); + + if (!locale_len) { + locale = (char *)intl_locale_get_default(); + } + + int32_t minimized_locale_len = uloc_minimizeSubtags(locale, minimized_locale, sizeof(minimized_locale), &status); + INTL_CHECK_STATUS(status, "locale_minimize_subtags: invalid locale"); + if (minimized_locale_len < 0) { + RETURN_FALSE; + } + + RETURN_STRINGL(minimized_locale, minimized_locale_len); +} diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index a6a56a88dda2e..dfb05a2b50ac5 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -505,6 +505,10 @@ function locale_accept_from_http(string $header): string|false {} function locale_is_right_to_left(string $locale): bool {} +function locale_add_likely_subtags(string $locale): string|false {} + +function locale_minimize_subtags(string $locale): string|false {} + /* msgformat */ function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index d5a7f30506710..b710084910733 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 70b621ef9169fd3b913347adc0baf3626584a2c3 */ + * Stub hash: 0d5b028a1ab8f35e8ee1b51ce3141b6ef782af28 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") @@ -578,6 +578,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_locale_is_right_to_left, 0, 1, _ ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_locale_add_likely_subtags, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_locale_minimize_subtags arginfo_locale_add_likely_subtags + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_msgfmt_create, 0, 2, MessageFormatter, 1) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) @@ -934,6 +940,8 @@ ZEND_FUNCTION(locale_canonicalize); ZEND_FUNCTION(locale_lookup); ZEND_FUNCTION(locale_accept_from_http); ZEND_FUNCTION(locale_is_right_to_left); +ZEND_FUNCTION(locale_add_likely_subtags); +ZEND_FUNCTION(locale_minimize_subtags); ZEND_FUNCTION(msgfmt_create); ZEND_FUNCTION(msgfmt_format); ZEND_FUNCTION(msgfmt_format_message); @@ -1123,6 +1131,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(locale_lookup, arginfo_locale_lookup) ZEND_FE(locale_accept_from_http, arginfo_locale_accept_from_http) ZEND_FE(locale_is_right_to_left, arginfo_locale_is_right_to_left) + ZEND_FE(locale_add_likely_subtags, arginfo_locale_add_likely_subtags) + ZEND_FE(locale_minimize_subtags, arginfo_locale_minimize_subtags) ZEND_FE(msgfmt_create, arginfo_msgfmt_create) ZEND_FE(msgfmt_format, arginfo_msgfmt_format) ZEND_FE(msgfmt_format_message, arginfo_msgfmt_format_message) diff --git a/ext/intl/tests/locale_subtags.phpt b/ext/intl/tests/locale_subtags.phpt new file mode 100644 index 0000000000000..0c454706225b5 --- /dev/null +++ b/ext/intl/tests/locale_subtags.phpt @@ -0,0 +1,35 @@ +--TEST-- +Locale::addLikelySubtags/Locale::minimizeSubtags usage +--EXTENSIONS-- +intl +--FILE-- + strlen($locale)); +var_dump(Locale::addLikelySubtags($max) === $max); +var_dump(Locale::minimizeSubtags($locale) === $locale); +var_dump(Locale::addLikelySubtags("%%%invalid%%%locale%%%")); +var_dump(intl_get_error_message()); +var_dump(Locale::minimizeSubtags("%%%Invalid%%%maximized%%%locale%%%")); +var_dump(intl_get_error_message()); +var_dump(Locale::addLikelySubTags(str_repeat($locale, 1024))); +var_dump(intl_get_error_message()); +var_dump(Locale::minimizeSubTags(str_repeat($max, 1024))); +var_dump(intl_get_error_message()); +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +string(67) "locale_add_likely_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(65) "locale_minimize_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(%d) "locale_add_likely_subtags: invalid locale: %s" +bool(false) +string(%d) "locale_minimize_subtags: invalid locale: %s"