Commit 4f947157b75 for php.net
commit 4f947157b752809e1057b1e7c0268b2a0fb6be22
Author: “LamentXU123” <108666168+LamentXU123@users.noreply.github.com>
Date: Sat May 16 00:33:14 2026 +0800
ext/intl: Expose Spoofchecker restriction-level APIs on all supported ICU versions
Also fix the constant names referenced in the Spoofchecker::setAllowedChars()
error message (CASE_INSENSITIVE / ADD_CASE_MAPPINGS / SIMPLE_CASE_INSENSITIVE
rather than their USET_-prefixed counterparts).
Fix #22053
close GH-22055
diff --git a/NEWS b/NEWS
index e9392cadf7d..8eaec1a74db 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,11 @@ PHP NEWS
. Fix incorrect argument positions in out-of-bounds errors for
IntlCalendar::set(), IntlCalendar::setDate(), IntlCalendar::setDateTime(),
and IntlGregorianCalendar date/time construction. (Weilin Du)
+ . Expose Spoofchecker restriction-level APIs on all supported ICU
+ versions. (Weilin Du)
+ . Fix SpoofChecker::setAllowedChars() to report PHP constant names
+ instead of ICU USET_* names in invalid pattern option errors.
+ (Weilin Du)
- MySQLnd:
. Fix persistent free of non-persistent connect_attr key (David Carlier).
diff --git a/UPGRADING b/UPGRADING
index 466b445c2d1..b8be56f7791 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -92,6 +92,8 @@ PHP 8.4 UPGRADE NOTES
- ValueError if the integer index does not fit in a signed 32 bit integer
. IntlDateFormatter::__construct() throws a ValueError if the locale is invalid.
. NumberFormatter::__construct() throws a ValueError if the locale is invalid.
+ . SpoofChecker::setAllowedChars() now reports PHP constant names instead
+ of ICU USET_* names in invalid pattern option errors.
. MBString:
. mb_encode_numericentity() and mb_decode_numericentity() now check that
the $map is only composed of integers, if not a ValueError is thrown.
diff --git a/ext/intl/spoofchecker/spoofchecker.stub.php b/ext/intl/spoofchecker/spoofchecker.stub.php
index 0141252d478..51a9c7d3907 100644
--- a/ext/intl/spoofchecker/spoofchecker.stub.php
+++ b/ext/intl/spoofchecker/spoofchecker.stub.php
@@ -19,7 +19,6 @@ class Spoofchecker
public const int INVISIBLE = UNKNOWN;
/** @cvalue USPOOF_CHAR_LIMIT */
public const int CHAR_LIMIT = UNKNOWN;
-#if U_ICU_VERSION_MAJOR_NUM >= 58
/** @cvalue USPOOF_ASCII */
public const int ASCII = UNKNOWN;
/** @cvalue USPOOF_HIGHLY_RESTRICTIVE */
@@ -34,7 +33,6 @@ class Spoofchecker
public const int SINGLE_SCRIPT_RESTRICTIVE = UNKNOWN;
/** @cvalue USPOOF_MIXED_NUMBERS */
public const int MIXED_NUMBERS = UNKNOWN;
-#endif
#if U_ICU_VERSION_MAJOR_NUM >= 62
/** @cvalue USPOOF_HIDDEN_OVERLAY */
public const int HIDDEN_OVERLAY = UNKNOWN;
@@ -71,9 +69,7 @@ public function setAllowedLocales(string $locales): void {}
/** @tentative-return-type */
public function setChecks(int $checks): void {}
-#if U_ICU_VERSION_MAJOR_NUM >= 58
/** @tentative-return-type */
public function setRestrictionLevel(int $level): void {}
-#endif
public function setAllowedChars(string $pattern, int $patternOptions = 0): void {}
}
diff --git a/ext/intl/spoofchecker/spoofchecker_arginfo.h b/ext/intl/spoofchecker/spoofchecker_arginfo.h
index cee17335dcd..99a211b260d 100644
Binary files a/ext/intl/spoofchecker/spoofchecker_arginfo.h and b/ext/intl/spoofchecker/spoofchecker_arginfo.h differ
diff --git a/ext/intl/spoofchecker/spoofchecker_main.c b/ext/intl/spoofchecker/spoofchecker_main.c
index 0ead525aed6..13ac6739264 100644
--- a/ext/intl/spoofchecker/spoofchecker_main.c
+++ b/ext/intl/spoofchecker/spoofchecker_main.c
@@ -135,7 +135,6 @@ PHP_METHOD(Spoofchecker, setChecks)
}
/* }}} */
-#if U_ICU_VERSION_MAJOR_NUM >= 58
/* TODO Document this method on PHP.net */
/* {{{ Set the loosest restriction level allowed for strings. */
PHP_METHOD(Spoofchecker, setRestrictionLevel)
@@ -164,7 +163,6 @@ PHP_METHOD(Spoofchecker, setRestrictionLevel)
uspoof_setRestrictionLevel(co->uspoof, (URestrictionLevel)level);
}
/* }}} */
-#endif
PHP_METHOD(Spoofchecker, setAllowedChars)
{
@@ -208,9 +206,9 @@ PHP_METHOD(Spoofchecker, setAllowedChars)
#endif
pattern_option != (USET_IGNORE_SPACE|USET_CASE_INSENSITIVE) &&
pattern_option != (USET_IGNORE_SPACE|USET_ADD_CASE_MAPPINGS)) {
- zend_argument_value_error(2, "must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|(<none> or SpoofChecker::USET_CASE_INSENSITIVE or SpoofChecker::USET_ADD_CASE_MAPPINGS"
+ zend_argument_value_error(2, "must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|(<none> or SpoofChecker::CASE_INSENSITIVE or SpoofChecker::ADD_CASE_MAPPINGS"
#if U_ICU_VERSION_MAJOR_NUM >= 73
- " or SpoofChecker::USET_SIMPLE_CASE_INSENSITIVE"
+ " or SpoofChecker::SIMPLE_CASE_INSENSITIVE"
#endif
"))"
);
diff --git a/ext/intl/tests/spoofchecker_007.phpt b/ext/intl/tests/spoofchecker_007.phpt
index b5fc5814ddf..5f3dbb47f19 100644
--- a/ext/intl/tests/spoofchecker_007.phpt
+++ b/ext/intl/tests/spoofchecker_007.phpt
@@ -4,12 +4,6 @@
intl
--SKIPIF--
<?php if(!class_exists("Spoofchecker")) print 'skip'; ?>
-<?php
- $r = new ReflectionClass("SpoofChecker");
- if (false === $r->getConstant("SINGLE_SCRIPT_RESTRICTIVE")) {
- die("skip Incompatible ICU version");
- }
-?>
--FILE--
<?php
diff --git a/ext/intl/tests/spoofchecker_008.phpt b/ext/intl/tests/spoofchecker_008.phpt
index 4eb78711c2c..66e39967c78 100644
--- a/ext/intl/tests/spoofchecker_008.phpt
+++ b/ext/intl/tests/spoofchecker_008.phpt
@@ -39,6 +39,6 @@
bool(true)
bool(false)
bool(false)
-Spoofchecker::setAllowedChars(): Argument #2 ($patternOptions) must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|(<none> or SpoofChecker::USET_CASE_INSENSITIVE%s))
+Spoofchecker::setAllowedChars(): Argument #2 ($patternOptions) must be a valid pattern option, 0 or (SpoofChecker::IGNORE_SPACE|(<none> or SpoofChecker::CASE_INSENSITIVE%s))
Spoofchecker::setAllowedChars(): Argument #1 ($pattern) must be a valid regular expression character set pattern
Spoofchecker::setAllowedChars(): Argument #1 ($pattern) must be a valid regular expression character set pattern
diff --git a/ext/intl/tests/spoofchecker_supported_icu57_apis.phpt b/ext/intl/tests/spoofchecker_supported_icu57_apis.phpt
new file mode 100644
index 00000000000..56cc194991e
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_supported_icu57_apis.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Spoofchecker exposes restriction-level APIs on all supported ICU versions
+--EXTENSIONS--
+intl
+--SKIPIF--
+<?php if (!class_exists("Spoofchecker")) print 'skip'; ?>
+--FILE--
+<?php
+$r = new ReflectionClass("Spoofchecker");
+
+$ascii = $r->getConstant("ASCII");
+$singleScriptRestrictive = $r->getConstant("SINGLE_SCRIPT_RESTRICTIVE");
+$mixedNumbers = $r->getConstant("MIXED_NUMBERS");
+
+var_dump($ascii !== false);
+var_dump($singleScriptRestrictive !== false);
+var_dump($mixedNumbers !== false);
+var_dump(is_int($ascii));
+var_dump(is_int($singleScriptRestrictive));
+var_dump(is_int($mixedNumbers));
+var_dump($ascii !== $singleScriptRestrictive);
+var_dump($ascii !== $mixedNumbers);
+var_dump($singleScriptRestrictive !== $mixedNumbers);
+var_dump($r->hasMethod("setRestrictionLevel"));
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt b/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt
index 6b7e9474755..187be350f59 100644
--- a/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt
+++ b/ext/intl/tests/spoofchecker_unknown_restriction_level.phpt
@@ -5,8 +5,6 @@
--SKIPIF--
<?php
if (!class_exists("Spoofchecker")) print 'skip';
-
-if (!method_exists(new Spoofchecker(), 'setRestrictionLevel')) print 'skip ICU version < 58';
?>
--FILE--
<?php