[PHP-CVS] [php-src] master: ext/intl: Add IntlDatePatternGenerator skeleton methods (#23078)

[email protected] (Weilin Du via GitHub)
Newsgroups php.cvs
Message-ID <[email protected]>
Author: Weilin Du (LamentXU123)
Committer: GitHub (web-flow)
Pusher: LamentXU123
Date: 2026-08-07T15:03:05+08:00

Commit: https://github.com/php/php-src/commit/e1a82e151daf114c30c693384e234fe7ad6b7c9d
Raw diff: https://github.com/php/php-src/commit/e1a82e151daf114c30c693384e234fe7ad6b7c9d.diff

ext/intl: Add IntlDatePatternGenerator skeleton methods (#23078)

This add missing Skeleton functions similar to #23049 and #23017 for
IntlDatePatternGenerator. This adds IntlDatePatternGenerator::getSkeleton()
and IntlDatePatternGenerator::getBaseSkeleton()

Co-authored-by: David CARLIER <[email protected]>

Changed paths:
  A  ext/intl/tests/datepatterngenerator_get_skeleton.phpt
  A  ext/intl/tests/datepatterngenerator_skeleton_error.phpt
  M  NEWS
  M  UPGRADING
  M  ext/intl/dateformat/datepatterngenerator.stub.php
  M  ext/intl/dateformat/datepatterngenerator_arginfo.h
  M  ext/intl/dateformat/datepatterngenerator_methods.cpp


Diff:

diff --git a/NEWS b/NEWS
index 7bad8e58adcb..cc4ff914844c 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,8 @@ PHP                                                                        NEWS
   . Added gmp_powm_sec(). (Weilin Du)
 
 - Intl:
+  . Added static methods IntlDatePatternGenerator::getSkeleton() and
+    IntlDatePatternGenerator::getBaseSkeleton(). (Weilin Du)
   . Fixed Collator::sort(), collator_sort(), Collator::asort(), and
     collator_asort() to report UTF-8/UTF-16 conversion errors through the intl
     error handler instead of emitting a warning and continuing with an empty
diff --git a/UPGRADING b/UPGRADING
index d6ed37ef49b6..25a405e1521d 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -327,6 +327,9 @@ PHP 8.6 UPGRADE NOTES
     on official Windows builds using MPIR.
 
 - Intl:
+  . Added the static methods IntlDatePatternGenerator::getSkeleton() and
+    IntlDatePatternGenerator::getBaseSkeleton() to generate the unique skeleton
+    and base skeleton for a date/time pattern.
   . Added Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue(),
     with the alias of locale_get_display_keyword() and
     locale_get_display_keyword_value() respectively.
@@ -506,6 +509,8 @@ PHP 8.6 UPGRADE NOTES
 - Intl:
   . grapheme_strrev()
     RFC: https://wiki.php.net/rfc/grapheme_strrev
+  . IntlDatePatternGenerator::getSkeleton()
+  . IntlDatePatternGenerator::getBaseSkeleton()
   . Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue()
     RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue
   . SpoofChecker::areBidiConfusable()
diff --git a/ext/intl/dateformat/datepatterngenerator.stub.php b/ext/intl/dateformat/datepatterngenerator.stub.php
index a9ce7c146312..b97e8d9a86a4 100644
--- a/ext/intl/dateformat/datepatterngenerator.stub.php
+++ b/ext/intl/dateformat/datepatterngenerator.stub.php
@@ -10,4 +10,8 @@ public function __construct(?string $locale = null) {}
     public static function create(?string $locale = null): ?IntlDatePatternGenerator {}
 
     public function getBestPattern(string $skeleton): string|false {}
+
+    public static function getSkeleton(string $pattern): string|false {}
+
+    public static function getBaseSkeleton(string $pattern): string|false {}
 }
diff --git a/ext/intl/dateformat/datepatterngenerator_arginfo.h b/ext/intl/dateformat/datepatterngenerator_arginfo.h
index 01debdbe5fa6..acf6a4695929 100644
--- a/ext/intl/dateformat/datepatterngenerator_arginfo.h
+++ b/ext/intl/dateformat/datepatterngenerator_arginfo.h
@@ -1,5 +1,5 @@
 /* This is a generated file, edit datepatterngenerator.stub.php instead.
- * Stub hash: 4456b13f7ed59847bbf129cd45b0d1f63ce70108 */
+ * Stub hash: cea997295023d9f6f6451150bf19867e7dac8c90 */
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDatePatternGenerator___construct, 0, 0, 0)
 	ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 1, "null")
@@ -13,14 +13,24 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_IntlDatePatternGenerator_g
 	ZEND_ARG_TYPE_INFO(0, skeleton, IS_STRING, 0)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_IntlDatePatternGenerator_getSkeleton, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
+	ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0)
+ZEND_END_ARG_INFO()
+
+#define arginfo_class_IntlDatePatternGenerator_getBaseSkeleton arginfo_class_IntlDatePatternGenerator_getSkeleton
+
 ZEND_METHOD(IntlDatePatternGenerator, __construct);
 ZEND_METHOD(IntlDatePatternGenerator, create);
 ZEND_METHOD(IntlDatePatternGenerator, getBestPattern);
+ZEND_METHOD(IntlDatePatternGenerator, getSkeleton);
+ZEND_METHOD(IntlDatePatternGenerator, getBaseSkeleton);
 
 static const zend_function_entry class_IntlDatePatternGenerator_methods[] = {
 	ZEND_ME(IntlDatePatternGenerator, __construct, arginfo_class_IntlDatePatternGenerator___construct, ZEND_ACC_PUBLIC)
 	ZEND_ME(IntlDatePatternGenerator, create, arginfo_class_IntlDatePatternGenerator_create, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
 	ZEND_ME(IntlDatePatternGenerator, getBestPattern, arginfo_class_IntlDatePatternGenerator_getBestPattern, ZEND_ACC_PUBLIC)
+	ZEND_ME(IntlDatePatternGenerator, getSkeleton, arginfo_class_IntlDatePatternGenerator_getSkeleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+	ZEND_ME(IntlDatePatternGenerator, getBaseSkeleton, arginfo_class_IntlDatePatternGenerator_getBaseSkeleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
 	ZEND_FE_END
 };
 
diff --git a/ext/intl/dateformat/datepatterngenerator_methods.cpp b/ext/intl/dateformat/datepatterngenerator_methods.cpp
index f22be1c21fc1..24943d4ec9b4 100644
--- a/ext/intl/dateformat/datepatterngenerator_methods.cpp
+++ b/ext/intl/dateformat/datepatterngenerator_methods.cpp
@@ -118,7 +118,8 @@ U_CFUNC PHP_METHOD( IntlDatePatternGenerator, getBestPattern )
 
 	INTL_METHOD_CHECK_STATUS(dtpgo, "Skeleton is not a valid UTF-8 string");
 
-	UnicodeString skeleton = dtpgo->dtpg->getSkeleton(skeleton_uncleaned, DTPATTERNGEN_ERROR_CODE(dtpgo));
+	UnicodeString skeleton = DateTimePatternGenerator::staticGetSkeleton(
+		skeleton_uncleaned, DTPATTERNGEN_ERROR_CODE(dtpgo));
 
 	INTL_METHOD_CHECK_STATUS(dtpgo, "Error getting cleaned skeleton");
 
@@ -132,3 +133,49 @@ U_CFUNC PHP_METHOD( IntlDatePatternGenerator, getBestPattern )
 
 	RETVAL_STR(u8str);
 }
+
+template <typename F>
+static void dtpg_get_skeleton(INTERNAL_FUNCTION_PARAMETERS, F&& skeletonfn, const char *errmsg)
+{
+	zend_string *pattern_str;
+	UnicodeString pattern;
+	UErrorCode status = U_ZERO_ERROR;
+
+	intl_error_reset(NULL);
+
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_STR(pattern_str)
+	ZEND_PARSE_PARAMETERS_END();
+
+	intl_stringFromChar(pattern, ZSTR_VAL(pattern_str), ZSTR_LEN(pattern_str), &status);
+
+	INTL_CHECK_STATUS(status, "Pattern is not a valid UTF-8 string");
+
+	UnicodeString result = skeletonfn(pattern, status);
+
+	INTL_CHECK_STATUS(status, errmsg);
+
+	zend_string *u8str = intl_charFromString(result, &status);
+
+	INTL_CHECK_STATUS(status, "Error converting result to UTF-8");
+
+	RETVAL_STR(u8str);
+}
+
+U_CFUNC PHP_METHOD(IntlDatePatternGenerator, getSkeleton)
+{
+	dtpg_get_skeleton(INTERNAL_FUNCTION_PARAM_PASSTHRU,
+		[](const UnicodeString &pattern, UErrorCode &status) {
+			return DateTimePatternGenerator::staticGetSkeleton(pattern, status);
+		},
+		"Error getting skeleton");
+}
+
+U_CFUNC PHP_METHOD(IntlDatePatternGenerator, getBaseSkeleton)
+{
+	dtpg_get_skeleton(INTERNAL_FUNCTION_PARAM_PASSTHRU,
+		[](const UnicodeString &pattern, UErrorCode &status) {
+			return DateTimePatternGenerator::staticGetBaseSkeleton(pattern, status);
+		},
+		"Error getting base skeleton");
+}
diff --git a/ext/intl/tests/datepatterngenerator_get_skeleton.phpt b/ext/intl/tests/datepatterngenerator_get_skeleton.phpt
new file mode 100644
index 000000000000..de425fc1667a
--- /dev/null
+++ b/ext/intl/tests/datepatterngenerator_get_skeleton.phpt
@@ -0,0 +1,48 @@
+--TEST--
+IntlDatePatternGenerator::getSkeleton() and getBaseSkeleton()
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+
+var_dump(IntlDatePatternGenerator::getSkeleton("dd/MMM"));
+var_dump(IntlDatePatternGenerator::getSkeleton("MMM-dd"));
+var_dump(IntlDatePatternGenerator::getBaseSkeleton("dd/MMM"));
+var_dump(IntlDatePatternGenerator::getBaseSkeleton("MMM-dd"));
+var_dump(IntlDatePatternGenerator::getSkeleton(""));
+var_dump(IntlDatePatternGenerator::getBaseSkeleton(""));
+
+$patterns = [
+    "'at' HH:mm",
+    "y年M月d日",
+    "yyyy-MM-dd",
+    "MMMMM",
+    "MMM",
+    "HH:mm:ss zzz dd/MM/y",
+    "'at HH:mm",
+];
+
+foreach ($patterns as $pattern) {
+    printf(
+        "%s => [%s] [%s]\n",
+        $pattern,
+        IntlDatePatternGenerator::getSkeleton($pattern),
+        IntlDatePatternGenerator::getBaseSkeleton($pattern),
+    );
+}
+
+?>
+--EXPECT--
+string(5) "MMMdd"
+string(5) "MMMdd"
+string(4) "MMMd"
+string(4) "MMMd"
+string(0) ""
+string(0) ""
+'at' HH:mm => [HHmm] [Hm]
+y年M月d日 => [yMd] [yMd]
+yyyy-MM-dd => [yyyyMMdd] [yMd]
+MMMMM => [MMMMM] [MMMMM]
+MMM => [MMM] [MMM]
+HH:mm:ss zzz dd/MM/y => [yMMddHHmmsszzz] [yMdHmsz]
+'at HH:mm => [] []
diff --git a/ext/intl/tests/datepatterngenerator_skeleton_error.phpt b/ext/intl/tests/datepatterngenerator_skeleton_error.phpt
new file mode 100644
index 000000000000..06a351ecd1bc
--- /dev/null
+++ b/ext/intl/tests/datepatterngenerator_skeleton_error.phpt
@@ -0,0 +1,18 @@
+--TEST--
+IntlDatePatternGenerator::getSkeleton() and getBaseSkeleton(): errors
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+
+foreach (["getSkeleton", "getBaseSkeleton"] as $method) {
+    var_dump(IntlDatePatternGenerator::$method("dd/MMM\x80"));
+    echo intl_get_error_message(), "\n";
+}
+
+?>
+--EXPECT--
+bool(false)
+IntlDatePatternGenerator::getSkeleton(): Pattern is not a valid UTF-8 string: U_INVALID_CHAR_FOUND
+bool(false)
+IntlDatePatternGenerator::getBaseSkeleton(): Pattern is not a valid UTF-8 string: U_INVALID_CHAR_FOUND
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.