diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index d60068e5ad48..d89edf4e96e2 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -68,6 +68,7 @@ if test "$PHP_INTL" != "no"; then dateformat/datepatterngenerator_class.cpp \ dateformat/datepatterngenerator_methods.cpp \ msgformat/msgformat_helpers.cpp \ + rangeformatter/rangeformatter_class.cpp \ timezone/timezone_class.cpp \ timezone/timezone_methods.cpp \ calendar/calendar_class.cpp \ @@ -123,6 +124,7 @@ if test "$PHP_INTL" != "no"; then $ext_builddir/listformatter $ext_builddir/msgformat $ext_builddir/normalizer + $ext_builddir/rangeformatter $ext_builddir/resourcebundle $ext_builddir/spoofchecker $ext_builddir/timezone diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index dcec448c4621..c4475a548f28 100644 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -63,6 +63,9 @@ if (PHP_INTL != "no") { normalizer_class.c \ normalizer_normalize.c \ ", "intl"); + ADD_SOURCES(configure_module_dirname + "/rangeformatter", "\ + rangeformatter_class.cpp \ + ", "intl"); ADD_SOURCES(configure_module_dirname + "/dateformat", "\ dateformat.c \ dateformat_class.c \ diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 68fd2dedfba8..7a92390990d7 100644 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -42,6 +42,7 @@ #include "locale/locale_class.h" #include "listformatter/listformatter_class.h" +#include "rangeformatter/rangeformatter_class.h" #include "dateformat/dateformat.h" #include "dateformat/dateformat_class.h" @@ -161,6 +162,9 @@ PHP_MINIT_FUNCTION( intl ) /* Register 'ListFormatter' PHP class */ listformatter_register_class( ); + /* Register 'NumberRangeFormatter' PHP class */ + rangeformatter_register_class( ); + /* Register 'Normalizer' PHP class */ normalizer_register_Normalizer_class( ); diff --git a/ext/intl/rangeformatter/rangeformatter.stub.php b/ext/intl/rangeformatter/rangeformatter.stub.php new file mode 100644 index 000000000000..eae40b5a56c2 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter.stub.php @@ -0,0 +1,61 @@ += 63 + /** @cvalue UNUM_RANGE_COLLAPSE_AUTO */ + public const int COLLAPSE_AUTO = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_NONE */ + public const int COLLAPSE_NONE = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_UNIT */ + public const int COLLAPSE_UNIT = UNKNOWN; + + /** @cvalue UNUM_RANGE_COLLAPSE_ALL */ + public const int COLLAPSE_ALL = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_SINGLE_VALUE */ + public const int IDENTITY_FALLBACK_SINGLE_VALUE = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE */ + public const int IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_APPROXIMATELY */ + public const int IDENTITY_FALLBACK_APPROXIMATELY = UNKNOWN; + + /** @cvalue UNUM_IDENTITY_FALLBACK_RANGE */ + public const int IDENTITY_FALLBACK_RANGE = UNKNOWN; +#else + public const int COLLAPSE_AUTO = 0; + + public const int COLLAPSE_NONE = 1; + + public const int COLLAPSE_UNIT = 2; + + public const int COLLAPSE_ALL = 3; + + public const int IDENTITY_FALLBACK_SINGLE_VALUE = 0; + + public const int IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE = 1; + + public const int IDENTITY_FALLBACK_APPROXIMATELY = 2; + + public const int IDENTITY_FALLBACK_RANGE = 3; +#endif + + private function __construct() {} + + public static function createFromSkeleton(string $skeleton, string $locale, int $collapse, int $identityFallback): IntlNumberRangeFormatter {} + + public function format(float|int $start, float|int $end): string {} + + public function getErrorCode(): int {} + + public function getErrorMessage(): string {} +} diff --git a/ext/intl/rangeformatter/rangeformatter_arginfo.h b/ext/intl/rangeformatter/rangeformatter_arginfo.h new file mode 100644 index 000000000000..00e923702be1 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_arginfo.h @@ -0,0 +1,148 @@ +/* This is a generated file, edit the .stub.php file instead. + * Stub hash: 7029642524e32984e893e1e050a5e0bbf275c416 */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlNumberRangeFormatter___construct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_IntlNumberRangeFormatter_createFromSkeleton, 0, 4, IntlNumberRangeFormatter, 0) + ZEND_ARG_TYPE_INFO(0, skeleton, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, collapse, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, identityFallback, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_format, 0, 2, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, start, MAY_BE_DOUBLE|MAY_BE_LONG, NULL) + ZEND_ARG_TYPE_MASK(0, end, MAY_BE_DOUBLE|MAY_BE_LONG, NULL) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_getErrorCode, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_IntlNumberRangeFormatter_getErrorMessage, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_METHOD(IntlNumberRangeFormatter, __construct); +ZEND_METHOD(IntlNumberRangeFormatter, createFromSkeleton); +ZEND_METHOD(IntlNumberRangeFormatter, format); +ZEND_METHOD(IntlNumberRangeFormatter, getErrorCode); +ZEND_METHOD(IntlNumberRangeFormatter, getErrorMessage); + +static const zend_function_entry class_IntlNumberRangeFormatter_methods[] = { + ZEND_ME(IntlNumberRangeFormatter, __construct, arginfo_class_IntlNumberRangeFormatter___construct, ZEND_ACC_PRIVATE) + ZEND_ME(IntlNumberRangeFormatter, createFromSkeleton, arginfo_class_IntlNumberRangeFormatter_createFromSkeleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(IntlNumberRangeFormatter, format, arginfo_class_IntlNumberRangeFormatter_format, ZEND_ACC_PUBLIC) + ZEND_ME(IntlNumberRangeFormatter, getErrorCode, arginfo_class_IntlNumberRangeFormatter_getErrorCode, ZEND_ACC_PUBLIC) + ZEND_ME(IntlNumberRangeFormatter, getErrorMessage, arginfo_class_IntlNumberRangeFormatter_getErrorMessage, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static zend_class_entry *register_class_IntlNumberRangeFormatter(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "IntlNumberRangeFormatter", class_IntlNumberRangeFormatter_methods); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE); +#if U_ICU_VERSION_MAJOR_NUM >= 63 + + zval const_COLLAPSE_AUTO_value; + ZVAL_LONG(&const_COLLAPSE_AUTO_value, UNUM_RANGE_COLLAPSE_AUTO); + zend_string *const_COLLAPSE_AUTO_name = zend_string_init_interned("COLLAPSE_AUTO", sizeof("COLLAPSE_AUTO") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_AUTO_name, &const_COLLAPSE_AUTO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_AUTO_name); + + zval const_COLLAPSE_NONE_value; + ZVAL_LONG(&const_COLLAPSE_NONE_value, UNUM_RANGE_COLLAPSE_NONE); + zend_string *const_COLLAPSE_NONE_name = zend_string_init_interned("COLLAPSE_NONE", sizeof("COLLAPSE_NONE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_NONE_name, &const_COLLAPSE_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_NONE_name); + + zval const_COLLAPSE_UNIT_value; + ZVAL_LONG(&const_COLLAPSE_UNIT_value, UNUM_RANGE_COLLAPSE_UNIT); + zend_string *const_COLLAPSE_UNIT_name = zend_string_init_interned("COLLAPSE_UNIT", sizeof("COLLAPSE_UNIT") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_UNIT_name, &const_COLLAPSE_UNIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_UNIT_name); + + zval const_COLLAPSE_ALL_value; + ZVAL_LONG(&const_COLLAPSE_ALL_value, UNUM_RANGE_COLLAPSE_ALL); + zend_string *const_COLLAPSE_ALL_name = zend_string_init_interned("COLLAPSE_ALL", sizeof("COLLAPSE_ALL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_ALL_name, &const_COLLAPSE_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_ALL_name); + + zval const_IDENTITY_FALLBACK_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_SINGLE_VALUE_value, UNUM_IDENTITY_FALLBACK_SINGLE_VALUE); + zend_string *const_IDENTITY_FALLBACK_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_SINGLE_VALUE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_SINGLE_VALUE_name); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_value, UNUM_IDENTITY_FALLBACK_APPROXIMATELY); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY", sizeof("IDENTITY_FALLBACK_APPROXIMATELY") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_APPROXIMATELY_name); + + zval const_IDENTITY_FALLBACK_RANGE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_RANGE_value, UNUM_IDENTITY_FALLBACK_RANGE); + zend_string *const_IDENTITY_FALLBACK_RANGE_name = zend_string_init_interned("IDENTITY_FALLBACK_RANGE", sizeof("IDENTITY_FALLBACK_RANGE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_RANGE_name, &const_IDENTITY_FALLBACK_RANGE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_RANGE_name); +#endif +#if !(U_ICU_VERSION_MAJOR_NUM >= 63) + + zval const_COLLAPSE_AUTO_value; + ZVAL_LONG(&const_COLLAPSE_AUTO_value, 0); + zend_string *const_COLLAPSE_AUTO_name = zend_string_init_interned("COLLAPSE_AUTO", sizeof("COLLAPSE_AUTO") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_AUTO_name, &const_COLLAPSE_AUTO_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_AUTO_name); + + zval const_COLLAPSE_NONE_value; + ZVAL_LONG(&const_COLLAPSE_NONE_value, 1); + zend_string *const_COLLAPSE_NONE_name = zend_string_init_interned("COLLAPSE_NONE", sizeof("COLLAPSE_NONE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_NONE_name, &const_COLLAPSE_NONE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_NONE_name); + + zval const_COLLAPSE_UNIT_value; + ZVAL_LONG(&const_COLLAPSE_UNIT_value, 2); + zend_string *const_COLLAPSE_UNIT_name = zend_string_init_interned("COLLAPSE_UNIT", sizeof("COLLAPSE_UNIT") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_UNIT_name, &const_COLLAPSE_UNIT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_UNIT_name); + + zval const_COLLAPSE_ALL_value; + ZVAL_LONG(&const_COLLAPSE_ALL_value, 3); + zend_string *const_COLLAPSE_ALL_name = zend_string_init_interned("COLLAPSE_ALL", sizeof("COLLAPSE_ALL") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_COLLAPSE_ALL_name, &const_COLLAPSE_ALL_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_COLLAPSE_ALL_name); + + zval const_IDENTITY_FALLBACK_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_SINGLE_VALUE_value, 0); + zend_string *const_IDENTITY_FALLBACK_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_SINGLE_VALUE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_SINGLE_VALUE_name); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, 1); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE", sizeof("IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE_name); + + zval const_IDENTITY_FALLBACK_APPROXIMATELY_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_APPROXIMATELY_value, 2); + zend_string *const_IDENTITY_FALLBACK_APPROXIMATELY_name = zend_string_init_interned("IDENTITY_FALLBACK_APPROXIMATELY", sizeof("IDENTITY_FALLBACK_APPROXIMATELY") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_APPROXIMATELY_name, &const_IDENTITY_FALLBACK_APPROXIMATELY_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_APPROXIMATELY_name); + + zval const_IDENTITY_FALLBACK_RANGE_value; + ZVAL_LONG(&const_IDENTITY_FALLBACK_RANGE_value, 3); + zend_string *const_IDENTITY_FALLBACK_RANGE_name = zend_string_init_interned("IDENTITY_FALLBACK_RANGE", sizeof("IDENTITY_FALLBACK_RANGE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_IDENTITY_FALLBACK_RANGE_name, &const_IDENTITY_FALLBACK_RANGE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_IDENTITY_FALLBACK_RANGE_name); +#endif + + return class_entry; +} diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp new file mode 100644 index 000000000000..21a8fa71fec3 --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_class.cpp @@ -0,0 +1,220 @@ +/* + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Bogdan Ungureanu | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include +#include "../intl_convertcpp.h" + +extern "C" { + #include "php.h" + #include "zend_API.h" + #include "../intl_common.h" + #include "../intl_error.h" + #include "../php_intl.h" + #include "../intl_data.h" + #include "rangeformatter_arginfo.h" + #include "rangeformatter_class.h" + #include "intl_convert.h" +} + +using icu::number::NumberRangeFormatter; +using icu::number::NumberFormatter; +using icu::number::UnlocalizedNumberFormatter; +using icu::number::LocalizedNumberRangeFormatter; +using icu::UnicodeString; +using icu::MeasureUnit; + +static zend_object_handlers rangeformatter_handlers; +zend_class_entry *class_entry_IntlNumberRangeFormatter; + +zend_object *IntlNumberRangeFormatter_object_create(zend_class_entry *ce) +{ + IntlNumberRangeFormatter_object* intern; + + intern = reinterpret_cast(zend_object_alloc(sizeof(IntlNumberRangeFormatter_object), ce)); + zend_object_std_init(&intern->zo, ce); + object_properties_init(&intern->zo, ce); + + // Initialize rangeformatter_data structure + intl_error_init(&intern->nrf_data.error); + intern->nrf_data.unumrf = nullptr; + + intern->zo.handlers = &rangeformatter_handlers; + + return &intern->zo; +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, __construct) +{ + ZEND_PARSE_PARAMETERS_NONE(); + zend_throw_error(NULL, "Cannot directly construct %s, use createFromSkeleton method instead", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name)); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, createFromSkeleton) +{ +#if U_ICU_VERSION_MAJOR_NUM < 63 + zend_throw_error(NULL, "IntlNumberRangeFormatter is not available in ICU 62 and earlier"); + RETURN_THROWS(); +#endif + + char* skeleton; + char* locale; + size_t locale_len; + size_t skeleton_len; + zend_long collapse; + zend_long identityFallback; + + ZEND_PARSE_PARAMETERS_START(4,4) + Z_PARAM_STRING(skeleton, skeleton_len) + Z_PARAM_STRING(locale, locale_len) + Z_PARAM_LONG(collapse) + Z_PARAM_LONG(identityFallback) + ZEND_PARSE_PARAMETERS_END(); + + if (skeleton_len == 0) { + zend_argument_must_not_be_empty_error(1); + RETURN_THROWS(); + } + + if (locale_len == 0) { + locale = (char *)intl_locale_get_default(); + } + + if (locale_len > INTL_MAX_LOCALE_LEN) { + zend_argument_value_error(2, "must be no longer than %d characters", INTL_MAX_LOCALE_LEN); + RETURN_THROWS(); + } + + if (strlen(uloc_getISO3Language(locale)) == 0) { + zend_argument_value_error(2, "\"%s\" is invalid", locale); + RETURN_THROWS(); + } + + if (collapse != UNUM_RANGE_COLLAPSE_AUTO && collapse != UNUM_RANGE_COLLAPSE_NONE && collapse != UNUM_RANGE_COLLAPSE_UNIT && collapse != UNUM_RANGE_COLLAPSE_ALL) { + zend_argument_value_error(3, "must be one of IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, or IntlNumberRangeFormatter::COLLAPSE_ALL"); + RETURN_THROWS(); + } + + if (identityFallback != UNUM_IDENTITY_FALLBACK_SINGLE_VALUE && identityFallback != UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE && identityFallback != UNUM_IDENTITY_FALLBACK_APPROXIMATELY && identityFallback != UNUM_IDENTITY_FALLBACK_RANGE) { + zend_argument_value_error(4, "must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, or IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE"); + RETURN_THROWS(); + } + + UErrorCode status = U_ZERO_ERROR; + + UnicodeString skeleton_ustr(skeleton, skeleton_len); + + UnlocalizedNumberFormatter nf = NumberFormatter::forSkeleton(skeleton_ustr, status); + + if (U_FAILURE(status)) { + intl_error_set(NULL, status, "Failed to create the number skeleton"); + zend_throw_exception(IntlException_ce_ptr, "Failed to create the number skeleton", 0); + RETURN_THROWS(); + } + + LocalizedNumberRangeFormatter* nrf = new LocalizedNumberRangeFormatter( + NumberRangeFormatter::with() + .locale(locale) + .numberFormatterBoth(nf) + .collapse(static_cast(collapse)) + .identityFallback(static_cast(identityFallback)) + ); + + zend_object* obj = IntlNumberRangeFormatter_object_create(class_entry_IntlNumberRangeFormatter); + + RANGEFORMATTER_OBJECT(php_intl_numberrangeformatter_fetch_object(obj)) = nrf; + + RETURN_OBJ(obj); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format) +{ + zval *start; + zval *end; + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_NUMBER(start) + Z_PARAM_NUMBER(end) + ZEND_PARSE_PARAMETERS_END(); + + UErrorCode error = U_ZERO_ERROR; + + icu::Formattable start_formattable(Z_TYPE_P(start) == IS_DOUBLE ? Z_DVAL_P(start) : Z_LVAL_P(start)); + icu::Formattable end_formattable(Z_TYPE_P(end) == IS_DOUBLE ? Z_DVAL_P(end) : Z_LVAL_P(end)); + + UnicodeString result = RANGEFORMATTER_OBJECT(obj)->formatFormattableRange(start_formattable, end_formattable, error).toString(error); + + if (U_FAILURE(error)) { + intl_error_set(NULL, error, "Failed to format number range"); + zend_throw_exception(IntlException_ce_ptr, "Failed to format number range", 0); + RETURN_THROWS(); + } + + zend_string *ret = intl_charFromString(result, &error); + + if (U_FAILURE(error)) { + intl_error_set(NULL, error, "Failed to convert result to UTF-8"); + zend_throw_exception(IntlException_ce_ptr, "Failed to convert result to UTF-8", 0); + RETURN_THROWS(); + } + + RETVAL_NEW_STR(ret); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, getErrorCode) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + RETURN_LONG(intl_error_get_code(&obj->nrf_data.error)); +} + +U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, getErrorMessage) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + IntlNumberRangeFormatter_object* obj = Z_INTL_RANGEFORMATTER_P(ZEND_THIS); + + RETURN_STR(intl_error_get_message(&obj->nrf_data.error)); +} + +void IntlNumberRangeFormatter_object_free(zend_object *object) +{ + IntlNumberRangeFormatter_object* nfo = php_intl_numberrangeformatter_fetch_object(object); + + if (nfo->nrf_data.unumrf) { + delete nfo->nrf_data.unumrf; + nfo->nrf_data.unumrf = nullptr; + } + + intl_error_reset(&nfo->nrf_data.error); + + zend_object_std_dtor(&nfo->zo); +} + +void rangeformatter_register_class(void) +{ + class_entry_IntlNumberRangeFormatter = register_class_IntlNumberRangeFormatter(); + class_entry_IntlNumberRangeFormatter->create_object = IntlNumberRangeFormatter_object_create; + + memcpy(&rangeformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + rangeformatter_handlers.offset = XtOffsetOf(IntlNumberRangeFormatter_object, zo); + rangeformatter_handlers.free_obj = IntlNumberRangeFormatter_object_free; + rangeformatter_handlers.clone_obj = NULL; +} diff --git a/ext/intl/rangeformatter/rangeformatter_class.h b/ext/intl/rangeformatter/rangeformatter_class.h new file mode 100644 index 000000000000..cf8a08aefb4e --- /dev/null +++ b/ext/intl/rangeformatter/rangeformatter_class.h @@ -0,0 +1,54 @@ +/* + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Bogdan Ungureanu | + +----------------------------------------------------------------------+ +*/ + +#ifndef RANGEFORMATTER_CLASS_H +#define RANGEFORMATTER_CLASS_H + +#include + +#ifdef __cplusplus +using icu::number::LocalizedNumberRangeFormatter; +#else +typedef void LocalizedNumberRangeFormatter; +#endif + +typedef struct { + // error handling + intl_error error; + + // formatter handling + LocalizedNumberRangeFormatter* unumrf; +} rangeformatter_data; + +typedef struct { + rangeformatter_data nrf_data; + zend_object zo; +} IntlNumberRangeFormatter_object; + +static inline IntlNumberRangeFormatter_object *php_intl_numberrangeformatter_fetch_object(zend_object *obj) { + return (IntlNumberRangeFormatter_object *)((char*)(obj) - XtOffsetOf(IntlNumberRangeFormatter_object, zo)); +} + +#define Z_INTL_RANGEFORMATTER_P(zv) php_intl_numberrangeformatter_fetch_object(Z_OBJ_P(zv)) + +#define RANGEFORMATTER_ERROR(nfo) (nfo)->nrf_data.error +#define RANGEFORMATTER_ERROR_P(nfo) &(RANGEFORMATTER_ERROR(nfo)) + +#define RANGEFORMATTER_OBJECT(nfo) (nfo)->nrf_data.unumrf + + +void rangeformatter_register_class(void); + + +#endif \ No newline at end of file diff --git a/ext/intl/tests/rangeformatter/basic.phpt b/ext/intl/tests/rangeformatter/basic.phpt new file mode 100644 index 000000000000..70aae282614b --- /dev/null +++ b/ext/intl/tests/rangeformatter/basic.phpt @@ -0,0 +1,395 @@ +--TEST-- +Basic test for IntlNumberRangeFormatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, + 'IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + 'IDENTITY_FALLBACK_APPROXIMATELY' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, + 'IDENTITY_FALLBACK_RANGE' => IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE +]; + +$collapses = [ + 'COLLAPSE_AUTO' => IntlNumberRangeFormatter::COLLAPSE_AUTO, + 'COLLAPSE_NONE' => IntlNumberRangeFormatter::COLLAPSE_NONE, + 'COLLAPSE_UNIT' => IntlNumberRangeFormatter::COLLAPSE_UNIT, + 'COLLAPSE_ALL' => IntlNumberRangeFormatter::COLLAPSE_ALL +]; + +foreach ($languages as $language) { + foreach ($identityFallbacks as $iName => $identityFallback) { + foreach ($collapses as $cName => $collapse) { + echo PHP_EOL . $language . ' - ' . $cName . ' - ' . $iName . PHP_EOL; + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'measure-unit/length-meter', + $language, + $collapse, + $identityFallback + ); + + var_dump($nrf->format(1.1, 2.2)); + var_dump($nrf->format(100, 200)); + var_dump($nrf->format(-5, 5)); + var_dump($nrf->format(5, 5)); + var_dump($nrf->format(5.0001, 5.0001)); + + } + } +} +echo 'en_GB - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE' . PHP_EOL; +$nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'measure-unit/length-meter', + 'en_GB', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE +); + +?> +--EXPECT-- +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(4) "~5 m" +string(9) "~5.0001 m" + +en_US - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" + +en_US - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(15) "1.1 m – 2.2 m" +string(15) "100 m – 200 m" +string(12) "-5 m – 5 m" +string(11) "5 m – 5 m" +string(21) "5.0001 m – 5.0001 m" + +en_US - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" + +en_US - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1.1–2.2 m" +string(11) "100–200 m" +string(10) "-5 – 5 m" +string(7) "5–5 m" +string(17) "5.0001–5.0001 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(3) "5 m" +string(8) "5,0001 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(4) "~5 m" +string(9) "~5,0001 m" + +RO - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" + +RO - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(13) "1,1 m - 2,2 m" +string(13) "100 m - 200 m" +string(10) "-5 m - 5 m" +string(9) "5 m - 5 m" +string(19) "5,0001 m - 5,0001 m" + +RO - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" + +RO - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1,1 - 2,2 m" +string(11) "100 - 200 m" +string(8) "-5 - 5 m" +string(7) "5 - 5 m" +string(17) "5,0001 - 5,0001 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_SINGLE_VALUE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(3) "5 m" +string(8) "5.0001 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_APPROXIMATELY +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_APPROXIMATELY +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(6) "約5 m" +string(11) "約5.0001 m" + +JA - COLLAPSE_AUTO - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" + +JA - COLLAPSE_NONE - IDENTITY_FALLBACK_RANGE +string(15) "1.1 m ~ 2.2 m" +string(15) "100 m ~ 200 m" +string(12) "-5 m ~ 5 m" +string(11) "5 m ~ 5 m" +string(21) "5.0001 m ~ 5.0001 m" + +JA - COLLAPSE_UNIT - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" + +JA - COLLAPSE_ALL - IDENTITY_FALLBACK_RANGE +string(11) "1.1~2.2 m" +string(11) "100~200 m" +string(10) "-5 ~ 5 m" +string(7) "5~5 m" +string(17) "5.0001~5.0001 m" +en_GB - COLLAPSE_AUTO - IDENTITY_FALLBACK_SINGLE_VALUE diff --git a/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt b/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt new file mode 100644 index 000000000000..f8a0dd30e9da --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_clone.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test IntlNumberRangeFormatter cannot be cloned +--SKIPIF-- + +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Trying to clone an uncloneable object of class IntlNumberRangeFormatter \ No newline at end of file diff --git a/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt b/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt new file mode 100644 index 000000000000..58a62c1e26b3 --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_errors.phpt @@ -0,0 +1,87 @@ +--TEST-- +errors for IntlNumberRangeFormatter +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; +} + +echo intl_get_error_code() . PHP_EOL; +echo intl_get_error_message() . PHP_EOL; + +try { + new IntlNumberRangeFormatter(); +} catch(Error $error) { + echo $error->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro', + 34, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + 343 + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'invalid-language', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +try { + $nrf = IntlNumberRangeFormatter::createFromSkeleton( + 'invalid skeleton here', + 'ro_thisiswaytooooooooooooooooooooooooooooooooooooooooooooolongtobevaliditneedstobeatleast157characterstofailthevalidationinthelistformattercodeimplementation', + IntlNumberRangeFormatter::COLLAPSE_AUTO, + IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE + ); +} catch (ValueError $exception) { + echo $exception->getMessage() . PHP_EOL; +} + +?> +--EXPECT-- +Failed to create the number skeleton +65811 +IntlNumberRangeFormatter::createFromSkeleton(): Failed to create the number skeleton: U_NUMBER_SKELETON_SYNTAX_ERROR +Call to private IntlNumberRangeFormatter::__construct() from global scope +IntlNumberRangeFormatter::createFromSkeleton(): Argument #3 ($collapse) must be one of IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, or IntlNumberRangeFormatter::COLLAPSE_ALL +IntlNumberRangeFormatter::createFromSkeleton(): Argument #4 ($identityFallback) must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, or IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE +IntlNumberRangeFormatter::createFromSkeleton(): Argument #2 ($locale) "invalid-language" is invalid +IntlNumberRangeFormatter::createFromSkeleton(): Argument #2 ($locale) must be no longer than 156 characters \ No newline at end of file diff --git a/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt b/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt new file mode 100644 index 000000000000..5152a25c1706 --- /dev/null +++ b/ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test IntlNumberRangeFormatter::createFromSkeleton throws error for ICU < 63 +--SKIPIF-- += 0) { + die('skip for ICU > 63.0'); +} +?> +--FILE-- +getMessage(); +} +?> +--EXPECT-- +IntlNumberRangeFormatter is not available in ICU 62 and earlier \ No newline at end of file