diff --git a/NEWS b/NEWS index e25c7e87a939..8f7ee70f1809 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ PHP NEWS throwing a ValueError. (Marc Bennewitz) - Intl: + . Added Collator::getRules() and collator_get_rules(). (Weilin Du) . Added IntlRelativeDateTimeFormatter for locale-aware relative date and time formatting, with enums for styles, capitalization contexts, and units. (Weilin Du) diff --git a/UPGRADING b/UPGRADING index dbfa42b9b171..3fc13d5391bd 100644 --- a/UPGRADING +++ b/UPGRADING @@ -116,6 +116,11 @@ PHP 8.7 UPGRADE NOTES . Added Transliterator::toRules() and transliterator_to_rules() to export rules that can be used to recreate a transliterator. The optional $escapeUnprintable argument escapes unprintable characters when true. + . Added Collator::getRules() and collator_get_rules() to retrieve collation + tailoring rules as a UTF-8 string. These describe locale-specific adjustments + to the root collation order; the full root/UCA rules are not included. An + empty string is returned if no tailoring rules are available, or false if + the rules cannot be converted to UTF-8. ======================================== 7. New Classes and Interfaces diff --git a/ext/intl/collator/collator.stub.php b/ext/intl/collator/collator.stub.php index e41684c691e0..f6f465ede698 100644 --- a/ext/intl/collator/collator.stub.php +++ b/ext/intl/collator/collator.stub.php @@ -137,6 +137,9 @@ public function setStrength(int $strength): true {} */ public function getLocale(int $type): string|false {} + /** @alias collator_get_rules */ + public function getRules(): string|false {} + /** * @tentative-return-type * @alias collator_get_error_code diff --git a/ext/intl/collator/collator_arginfo.h b/ext/intl/collator/collator_arginfo.h index bf8345cd8be0..837249cb9edd 100644 --- a/ext/intl/collator/collator_arginfo.h +++ b/ext/intl/collator/collator_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit collator.stub.php instead. - * Stub hash: cbe3c5f4c35d93f90c3e7164bdfc4e2fefc88c83 */ + * Stub hash: e848695e9e3ae3bc8d0829570edbf855c5e50e23 */ #include "zend_constants.h" @@ -47,6 +47,9 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Collator_getLoca ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_Collator_getRules, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_Collator_getErrorCode, 0, 0, MAY_BE_LONG|MAY_BE_FALSE) ZEND_END_ARG_INFO() @@ -68,6 +71,7 @@ ZEND_FUNCTION(collator_set_attribute); ZEND_FUNCTION(collator_get_strength); ZEND_FUNCTION(collator_set_strength); ZEND_FUNCTION(collator_get_locale); +ZEND_FUNCTION(collator_get_rules); ZEND_FUNCTION(collator_get_error_code); ZEND_FUNCTION(collator_get_error_message); ZEND_FUNCTION(collator_get_sort_key); @@ -84,6 +88,7 @@ static const zend_function_entry class_Collator_methods[] = { ZEND_RAW_FENTRY("getStrength", zif_collator_get_strength, arginfo_class_Collator_getStrength, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setStrength", zif_collator_set_strength, arginfo_class_Collator_setStrength, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getLocale", zif_collator_get_locale, arginfo_class_Collator_getLocale, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getRules", zif_collator_get_rules, arginfo_class_Collator_getRules, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getErrorCode", zif_collator_get_error_code, arginfo_class_Collator_getErrorCode, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getErrorMessage", zif_collator_get_error_message, arginfo_class_Collator_getErrorMessage, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getSortKey", zif_collator_get_sort_key, arginfo_class_Collator_getSortKey, ZEND_ACC_PUBLIC, NULL, NULL) diff --git a/ext/intl/collator/collator_locale.cpp b/ext/intl/collator/collator_locale.cpp index 2d346f439c9d..d09dba29a0a8 100644 --- a/ext/intl/collator/collator_locale.cpp +++ b/ext/intl/collator/collator_locale.cpp @@ -59,3 +59,28 @@ U_CFUNC PHP_FUNCTION( collator_get_locale ) RETVAL_STRINGL( locale_name, strlen(locale_name) ); } /* }}} */ + +/* {{{ Gets the collation tailoring rules. */ +U_CFUNC PHP_FUNCTION(collator_get_rules) +{ + COLLATOR_METHOD_INIT_VARS + + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", + &object, Collator_ce_ptr) == FAILURE) { + RETURN_THROWS(); + } + + COLLATOR_METHOD_FETCH_OBJECT; + + if (collator_check_initialized(co) == FAILURE) { + RETURN_THROWS(); + } + + int32_t rules_len; + const UChar *rules = ucol_getRules(co->ucoll, &rules_len); + zend_string *result = intl_convert_utf16_to_utf8(rules, rules_len, COLLATOR_ERROR_CODE_P(co)); + COLLATOR_CHECK_STATUS(co, "Error converting collation rules to UTF-8"); + + RETURN_STR(result); +} +/* }}} */ diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index a6a519e50f65..e132a4f670ce 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -308,6 +308,8 @@ function collator_asort(Collator $object, array &$array, int $flags = Collator:: function collator_get_locale(Collator $object, int $type): string|false {} +function collator_get_rules(Collator $object): string|false {} + function collator_get_error_code(Collator $object): int|false {} function collator_get_error_message(Collator $object): string|false {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index a1b95671d275..a360a0be99ee 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 php_intl.stub.php instead. - * Stub hash: c54e9724edabab5a6531e535f2226f512a904c8e */ + * Stub hash: 53be664062cb2b55770f3493e201c0401c9ef519 */ #include "zend_attributes.h" #include "zend_constants.h" @@ -252,14 +252,16 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_locale, 0, 2, MAY_B ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_error_code, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_rules, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, object, Collator, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_error_message, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_error_code, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, object, Collator, 0) ZEND_END_ARG_INFO() +#define arginfo_collator_get_error_message arginfo_collator_get_rules + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_collator_get_sort_key, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, object, Collator, 0) ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) @@ -893,6 +895,7 @@ ZEND_FUNCTION(collator_sort); ZEND_FUNCTION(collator_sort_with_sort_keys); ZEND_FUNCTION(collator_asort); ZEND_FUNCTION(collator_get_locale); +ZEND_FUNCTION(collator_get_rules); ZEND_FUNCTION(collator_get_error_code); ZEND_FUNCTION(collator_get_error_message); ZEND_FUNCTION(collator_get_sort_key); @@ -1088,6 +1091,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(collator_sort_with_sort_keys, arginfo_collator_sort_with_sort_keys) ZEND_FE(collator_asort, arginfo_collator_asort) ZEND_FE(collator_get_locale, arginfo_collator_get_locale) + ZEND_FE(collator_get_rules, arginfo_collator_get_rules) ZEND_FE(collator_get_error_code, arginfo_collator_get_error_code) ZEND_FE(collator_get_error_message, arginfo_collator_get_error_message) ZEND_FE(collator_get_sort_key, arginfo_collator_get_sort_key) diff --git a/ext/intl/tests/collator_get_rules.phpt b/ext/intl/tests/collator_get_rules.phpt new file mode 100644 index 000000000000..b23af2cc622b --- /dev/null +++ b/ext/intl/tests/collator_get_rules.phpt @@ -0,0 +1,26 @@ +--TEST-- +Collator::getRules() returns collation tailoring rules as UTF-8 +--EXTENSIONS-- +intl +--FILE-- +getRules()); +var_dump(collator_get_rules($root)); + +$collator = new Collator('de_DE@collation=phonebook'); +$rules = $collator->getRules(); +var_dump(is_string($rules) && $rules !== ''); +var_dump(preg_match('/\x{00E4}/u', $rules)); +var_dump(collator_get_rules($collator) === $rules); + +unset($collator); +var_dump(preg_match('/\x{00E4}/u', $rules)); +?> +--EXPECT-- +string(0) "" +string(0) "" +bool(true) +int(1) +bool(true) +int(1) diff --git a/ext/intl/tests/collator_get_rules_error.phpt b/ext/intl/tests/collator_get_rules_error.phpt new file mode 100644 index 000000000000..121b8fa0de8f --- /dev/null +++ b/ext/intl/tests/collator_get_rules_error.phpt @@ -0,0 +1,38 @@ +--TEST-- +Collator::getRules() resets errors and rejects unconstructed objects +--EXTENSIONS-- +intl +--FILE-- + $c->getRules(), collator_get_rules(...)] as $getRules) { + $collator = new Collator('root'); + var_dump($collator->getAttribute(-1)); + var_dump(intl_get_error_code() === U_ILLEGAL_ARGUMENT_ERROR); + var_dump($getRules($collator)); + var_dump(intl_get_error_message()); + var_dump($collator->getErrorMessage()); + + try { + $getRules(new UnconstructedCollator()); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} +?> +--EXPECT-- +bool(false) +bool(true) +string(0) "" +string(12) "U_ZERO_ERROR" +string(12) "U_ZERO_ERROR" +Object not initialized +bool(false) +bool(true) +string(0) "" +string(12) "U_ZERO_ERROR" +string(12) "U_ZERO_ERROR" +Object not initialized