Browse Source

ext/intl: Add IntlNumberRangeFormatter class.

to format an interval of two numbers with a given
skeleton, locale, collapse type and identity fallback

close GH-19232
pull/19977/head
Bogdan Ungureanu 3 months ago
committed by David Carlier
parent
commit
6ef4a87c18
No known key found for this signature in database GPG Key ID: 2FB76A8CE6CD2B41
  1. 5
      NEWS
  2. 5
      UPGRADING
  3. 2
      ext/intl/config.m4
  4. 3
      ext/intl/config.w32
  5. 4
      ext/intl/php_intl.c
  6. 61
      ext/intl/rangeformatter/rangeformatter.stub.php
  7. 148
      ext/intl/rangeformatter/rangeformatter_arginfo.h
  8. 239
      ext/intl/rangeformatter/rangeformatter_class.cpp
  9. 59
      ext/intl/rangeformatter/rangeformatter_class.h
  10. 484
      ext/intl/tests/rangeformatter/basic.phpt
  11. 28
      ext/intl/tests/rangeformatter/rangeformatter_clone.phpt
  12. 87
      ext/intl/tests/rangeformatter/rangeformatter_errors.phpt
  13. 39
      ext/intl/tests/rangeformatter/rangeformatter_fraction_skeleton.phpt
  14. 26
      ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt
  15. 24
      ext/intl/tests/rangeformatter/rangeformatter_with_empty_skeleton.phpt

5
NEWS

@ -2,4 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.6.0alpha1
- Intl:
. Added IntlNumberRangeFormatter class to format an interval of two numbers
with a given skeleton, locale, collapse type and identity fallback.
(BogdanUngureanu)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>

5
UPGRADING

@ -23,6 +23,11 @@ PHP 8.6 UPGRADE NOTES
2. New Features
========================================
- Intl:
. Added IntlNumberRangeFormatter class to format an interval of two numbers with a given skeleton, locale, IntlNumberRangeFormatter::COLLAPSE_AUTO, IntlNumberRangeFormatter::COLLAPSE_NONE, IntlNumberRangeFormatter::COLLAPSE_UNIT, IntlNumberRangeFormatter::COLLAPSE_ALL collapse and
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY and
IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE identity fallbacks.
It is supported from icu 63.
========================================
3. Changes in SAPI modules
========================================

2
ext/intl/config.m4

@ -60,6 +60,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

3
ext/intl/config.w32

@ -63,6 +63,9 @@ if (PHP_INTL != "no") {
normalizer_class.cpp \
normalizer_normalize.cpp \
", "intl");
ADD_SOURCES(configure_module_dirname + "/rangeformatter", "\
rangeformatter_class.cpp \
", "intl");
ADD_SOURCES(configure_module_dirname + "/dateformat", "\
dateformat.c \
dateformat_class.c \

4
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"
@ -189,6 +190,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( );

61
ext/intl/rangeformatter/rangeformatter.stub.php

@ -0,0 +1,61 @@
<?php
/** @generate-class-entries */
/**
* @not-serializable
* @strict-properties
*/
final class IntlNumberRangeFormatter {
#if U_ICU_VERSION_MAJOR_NUM >= 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 {}
}

148
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;
}

239
ext/intl/rangeformatter/rangeformatter_class.cpp

@ -0,0 +1,239 @@
/*
+----------------------------------------------------------------------+
| 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 <bogdanungureanu21@gmail.com> |
+----------------------------------------------------------------------+
*/
extern "C" {
#include "php.h"
#include "zend_API.h"
#include "../intl_common.h"
}
#if U_ICU_VERSION_MAJOR_NUM >= 63
#include <unicode/numberrangeformatter.h>
#include <unicode/unumberrangeformatter.h>
#include <unicode/numberformatter.h>
#include <unicode/unistr.h>
#include "../intl_convertcpp.h"
#endif
extern "C" {
#include "../intl_error.h"
#include "../php_intl.h"
#include "../intl_data.h"
#include "rangeformatter_arginfo.h"
#include "rangeformatter_class.h"
#include "intl_convert.h"
}
#if U_ICU_VERSION_MAJOR_NUM >= 63
using icu::number::NumberRangeFormatter;
using icu::number::NumberFormatter;
using icu::number::UnlocalizedNumberFormatter;
using icu::number::LocalizedNumberRangeFormatter;
using icu::UnicodeString;
using icu::MeasureUnit;
#endif
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<IntlNumberRangeFormatter_object*>(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();
#else
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 (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)) {
// override error level and use exceptions
const bool old_use_exception = INTL_G(use_exceptions);
const zend_long old_error_level = INTL_G(error_level);
INTL_G(use_exceptions) = true;
INTL_G(error_level) = 0;
intl_error_set(NULL, status, "Failed to create the number skeleton");
INTL_G(use_exceptions) = old_use_exception;
INTL_G(error_level) = old_error_level;
}
LocalizedNumberRangeFormatter* nrf = new LocalizedNumberRangeFormatter(
NumberRangeFormatter::with()
.locale(locale)
.numberFormatterBoth(nf)
.collapse(static_cast<UNumberRangeCollapse>(collapse))
.identityFallback(static_cast<UNumberRangeIdentityFallback>(identityFallback))
);
zend_object* obj = IntlNumberRangeFormatter_object_create(class_entry_IntlNumberRangeFormatter);
RANGEFORMATTER_OBJECT(php_intl_numberrangeformatter_fetch_object(obj)) = nrf;
RETURN_OBJ(obj);
#endif
}
U_CFUNC PHP_METHOD(IntlNumberRangeFormatter, format)
{
#if U_ICU_VERSION_MAJOR_NUM < 63
zend_throw_error(NULL, "IntlNumberRangeFormatter is not available in ICU 62 and earlier");
RETURN_THROWS();
#else
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);
// override error level and use exceptions
const bool old_use_exception = INTL_G(use_exceptions);
const zend_long old_error_level = INTL_G(error_level);
INTL_G(use_exceptions) = true;
INTL_G(error_level) = 0;
if (U_FAILURE(error)) {
intl_error_set(NULL, error, "Failed to format number range");
}
zend_string *ret = intl_charFromString(result, &error);
if (U_FAILURE(error)) {
intl_error_set(NULL, error, "Failed to convert result to UTF-8");
}
INTL_G(use_exceptions) = old_use_exception;
INTL_G(error_level) = old_error_level;
RETVAL_NEW_STR(ret);
#endif
}
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;
}

59
ext/intl/rangeformatter/rangeformatter_class.h

@ -0,0 +1,59 @@
/*
+----------------------------------------------------------------------+
| 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 <bogdanungureanu21@gmail.com> |
+----------------------------------------------------------------------+
*/
#ifndef RANGEFORMATTER_CLASS_H
#define RANGEFORMATTER_CLASS_H
#if U_ICU_VERSION_MAJOR_NUM >= 63
#include <unicode/numberrangeformatter.h>
#ifdef __cplusplus
using icu::number::LocalizedNumberRangeFormatter;
#else
typedef void LocalizedNumberRangeFormatter;
#endif
#endif // U_ICU_VERSION_MAJOR_NUM >= 63
typedef struct {
// error handling
intl_error error;
// formatter handling
#if U_ICU_VERSION_MAJOR_NUM >= 63
LocalizedNumberRangeFormatter* unumrf;
#else
void* unumrf;
#endif
} 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

484
ext/intl/tests/rangeformatter/basic.phpt

@ -0,0 +1,484 @@
--TEST--
Basic test for IntlNumberRangeFormatter
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
die('skip for ICU < 63.0');
}
?>
--FILE--
<?php
$languages = ['en_US', 'RO', 'JA'];
$identityFallbacks = [
'IDENTITY_FALLBACK_SINGLE_VALUE' => 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));
var_dump($nrf->format(5, 5.1));
var_dump($nrf->format(5.1, 6));
}
}
}
?>
--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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(13) "5 m – 5.1 m"
string(13) "5.1 m – 6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(13) "5 m – 5.1 m"
string(13) "5.1 m – 6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(13) "5 m – 5.1 m"
string(13) "5.1 m – 6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(13) "5 m – 5.1 m"
string(13) "5.1 m – 6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5–5.1 m"
string(9) "5.1–6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(11) "5 m - 5,1 m"
string(11) "5,1 m - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(11) "5 m - 5,1 m"
string(11) "5,1 m - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(11) "5 m - 5,1 m"
string(11) "5,1 m - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(11) "5 m - 5,1 m"
string(11) "5,1 m - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5 - 5,1 m"
string(9) "5,1 - 6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(13) "5 m ~ 5.1 m"
string(13) "5.1 m ~ 6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(13) "5 m ~ 5.1 m"
string(13) "5.1 m ~ 6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(13) "5 m ~ 5.1 m"
string(13) "5.1 m ~ 6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(13) "5 m ~ 5.1 m"
string(13) "5.1 m ~ 6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 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"
string(9) "5~5.1 m"
string(9) "5.1~6 m"

28
ext/intl/tests/rangeformatter/rangeformatter_clone.phpt

@ -0,0 +1,28 @@
--TEST--
Test IntlNumberRangeFormatter cannot be cloned
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
die('skip for ICU < 63.0');
}
?>
--FILE--
<?php
$formatter = IntlNumberRangeFormatter::createFromSkeleton(
'measure-unit/length-meter',
'en_US',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE
);
try {
$clonedFormatter = clone $formatter;
} catch(Error $error) {
echo $error->getMessage();
}
?>
--EXPECT--
Trying to clone an uncloneable object of class IntlNumberRangeFormatter

87
ext/intl/tests/rangeformatter/rangeformatter_errors.phpt

@ -0,0 +1,87 @@
--TEST--
errors for IntlNumberRangeFormatter
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
die('skip for ICU < 63.0');
}
?>
--FILE--
<?php
try {
$nrf = IntlNumberRangeFormatter::createFromSkeleton(
'invalid skeleton here',
'ro',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE
);
} catch (IntlException $exception) {
echo $exception->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--
IntlNumberRangeFormatter::createFromSkeleton(): 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

39
ext/intl/tests/rangeformatter/rangeformatter_fraction_skeleton.phpt

@ -0,0 +1,39 @@
--TEST--
Test precision skeleton with IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
die('skip for ICU < 63.0');
}
?>
--FILE--
<?php
$precisions = ['.##', '.#'];
foreach ($precisions as $precision) {
echo 'Approximate with ' . $precision . PHP_EOL;
$nrf = IntlNumberRangeFormatter::createFromSkeleton(
$precision,
'en_GB',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY
);
var_dump($nrf->format(5.1, 5.2));
var_dump($nrf->format(5.01, 5.02));
var_dump($nrf->format(5.001, 5.002));
}
?>
--EXPECT--
Approximate with .##
string(9) "5.1–5.2"
string(11) "5.01–5.02"
string(2) "~5"
Approximate with .#
string(9) "5.1–5.2"
string(2) "~5"
string(2) "~5"

26
ext/intl/tests/rangeformatter/rangeformatter_icu63_compatibility.phpt

@ -0,0 +1,26 @@
--TEST--
Test IntlNumberRangeFormatter::createFromSkeleton throws error for ICU < 63
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') >= 0) {
die('skip for ICU > 63.0');
}
?>
--FILE--
<?php
try {
$formatter = IntlNumberRangeFormatter::createFromSkeleton(
'measure-unit/length-meter',
'en_US',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE
);
} catch (Error $error) {
echo $error->getMessage();
}
?>
--EXPECT--
IntlNumberRangeFormatter is not available in ICU 62 and earlier

24
ext/intl/tests/rangeformatter/rangeformatter_with_empty_skeleton.phpt

@ -0,0 +1,24 @@
--TEST--
Test an empty skeleton with IntlNumberRangeFormatter
--EXTENSIONS--
intl
--SKIPIF--
<?php
if (version_compare(INTL_ICU_VERSION, '63.0') < 0) {
die('skip for ICU < 63.0');
}
?>
--FILE--
<?php
$nrf = IntlNumberRangeFormatter::createFromSkeleton(
'',
'en_GB',
IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY
);
var_dump($nrf->format(5.1, 5.2));
?>
--EXPECT--
string(9) "5.1–5.2"
Loading…
Cancel
Save