diff --git a/ext/intl/calendar/calendar.stub.php b/ext/intl/calendar/calendar.stub.php index 078ecb0c2da..56602da0ec2 100644 --- a/ext/intl/calendar/calendar.stub.php +++ b/ext/intl/calendar/calendar.stub.php @@ -90,11 +90,10 @@ class IntlCalendar private function __construct() {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type * @alias intlcal_create_instance */ - public static function createInstance($timezone = null, ?string $locale = null): ?IntlCalendar {} + public static function createInstance(IntlTimeZone|DateTimeZone|string|null $timezone = null, ?string $locale = null): ?IntlCalendar {} /** * @tentative-return-type @@ -355,11 +354,9 @@ class IntlCalendar public function setTime(float $timestamp): bool {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type - * @alias intlcal_set_time_zone */ - public function setTimeZone($timezone): bool {} + public function setTimeZone(IntlTimeZone|DateTimeZone|string|null $timezone): bool {} /** * @tentative-return-type diff --git a/ext/intl/calendar/calendar_arginfo.h b/ext/intl/calendar/calendar_arginfo.h index 9e050539b2e..415113b613a 100644 --- a/ext/intl/calendar/calendar_arginfo.h +++ b/ext/intl/calendar/calendar_arginfo.h @@ -1,11 +1,11 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c014b88c9b6aa145ea20cc1f3fd719fe9f3d6966 */ + * Stub hash: 2fc12d1fde65efbec4305f4934a3f4b25282a552 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlCalendar___construct, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlCalendar_createInstance, 0, 0, IntlCalendar, 1) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -165,7 +165,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlCalendar_set ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlCalendar_setTimeZone, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_IntlCalendar_toDateTime, 0, 0, DateTime, MAY_BE_FALSE) @@ -249,7 +249,7 @@ ZEND_FUNCTION(intlcal_set_lenient); ZEND_FUNCTION(intlcal_set_repeated_wall_time_option); ZEND_FUNCTION(intlcal_set_skipped_wall_time_option); ZEND_FUNCTION(intlcal_set_time); -ZEND_FUNCTION(intlcal_set_time_zone); +ZEND_METHOD(IntlCalendar, setTimeZone); ZEND_FUNCTION(intlcal_to_date_time); ZEND_METHOD(IntlGregorianCalendar, createFromDate); ZEND_METHOD(IntlGregorianCalendar, createFromDateTime); @@ -305,7 +305,7 @@ static const zend_function_entry class_IntlCalendar_methods[] = { ZEND_RAW_FENTRY("setRepeatedWallTimeOption", zif_intlcal_set_repeated_wall_time_option, arginfo_class_IntlCalendar_setRepeatedWallTimeOption, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setSkippedWallTimeOption", zif_intlcal_set_skipped_wall_time_option, arginfo_class_IntlCalendar_setSkippedWallTimeOption, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setTime", zif_intlcal_set_time, arginfo_class_IntlCalendar_setTime, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("setTimeZone", zif_intlcal_set_time_zone, arginfo_class_IntlCalendar_setTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(IntlCalendar, setTimeZone, arginfo_class_IntlCalendar_setTimeZone, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("toDateTime", zif_intlcal_to_date_time, arginfo_class_IntlCalendar_toDateTime, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_FE_END }; diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index d668cd66df9..c404286fe09 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -72,21 +72,21 @@ U_CFUNC PHP_METHOD(IntlCalendar, __construct) U_CFUNC PHP_FUNCTION(intlcal_create_instance) { - zval *zv_timezone = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; char *locale_str = NULL; size_t locale_len = 0; - TimeZone *timeZone; UErrorCode status = U_ZERO_ERROR; intl_error_reset(NULL); ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(zv_timezone) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) Z_PARAM_STRING_OR_NULL(locale_str, locale_len) ZEND_PARSE_PARAMETERS_END(); - timeZone = timezone_process_timezone_argument(zv_timezone, NULL); - if (timeZone == NULL) { + TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr); + if (timeZone == nullptr) { RETURN_NULL(); } @@ -296,26 +296,28 @@ U_CFUNC PHP_FUNCTION(intlcal_add) RETURN_TRUE; } +/* {{{ Set formatter's timezone. */ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone) { - zval *zv_timezone; - TimeZone *timeZone; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + CALENDAR_METHOD_INIT_VARS; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Oz!", &object, Calendar_ce_ptr, &zv_timezone) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(object, Calendar_ce_ptr) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); CALENDAR_METHOD_FETCH_OBJECT; - if (zv_timezone == NULL) { + if (timezone_object == nullptr && timezone_string == nullptr) { RETURN_TRUE; /* the method does nothing if passed null */ } - timeZone = timezone_process_timezone_argument(zv_timezone, - CALENDAR_ERROR_P(co)); - if (timeZone == NULL) { + TimeZone *timeZone = timezone_process_timezone_argument( + timezone_object, timezone_string, CALENDAR_ERROR_P(co)); + if (timeZone == nullptr) { RETURN_FALSE; } @@ -324,6 +326,34 @@ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone) RETURN_TRUE; } +U_CFUNC PHP_METHOD(IntlCalendar, setTimeZone) +{ + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + + CALENDAR_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); + + object = ZEND_THIS; + CALENDAR_METHOD_FETCH_OBJECT; + + if (timezone_object == nullptr && timezone_string == nullptr) { + RETURN_TRUE; /* the method does nothing if passed null */ + } + + TimeZone *timeZone = timezone_process_timezone_argument( + timezone_object, timezone_string, CALENDAR_ERROR_P(co)); + if (timeZone == nullptr) { + RETURN_FALSE; + } + + co->ucal->adoptTimeZone(timeZone); + + RETURN_TRUE; +} static void _php_intlcal_before_after( UBool (Calendar::*func)(const Calendar&, UErrorCode&) const, diff --git a/ext/intl/calendar/gregoriancalendar_methods.cpp b/ext/intl/calendar/gregoriancalendar_methods.cpp index 8796e01f638..0cc3a94d4c5 100644 --- a/ext/intl/calendar/gregoriancalendar_methods.cpp +++ b/ext/intl/calendar/gregoriancalendar_methods.cpp @@ -77,7 +77,8 @@ static bool set_gregorian_calendar_time_zone(GregorianCalendar *gcal, UErrorCode static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) { - zval *tz_object = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; zval args_a[6], *args = &args_a[0]; char *locale = NULL; @@ -112,15 +113,23 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool // argument parsing if (variant <= 2) { - if (zend_parse_parameters(MIN(ZEND_NUM_ARGS(), 2), - "|z!s!", &tz_object, &locale, &locale_len) == FAILURE) { - RETURN_THROWS(); - } - } - if (variant > 2 && zend_parse_parameters(ZEND_NUM_ARGS(), - "lll|lll", &largs[0], &largs[1], &largs[2], &largs[3], &largs[4], - &largs[5]) == FAILURE) { - RETURN_THROWS(); + /* These dummy variables are needed because the 2 param constructor allows trailing nulls... */ + zval *dummy1, *dummy2, *dummy3, *dummy4; + ZEND_PARSE_PARAMETERS_START(0, 6) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + Z_PARAM_STRING_OR_NULL(locale, locale_len) + Z_PARAM_ZVAL(dummy1) + Z_PARAM_ZVAL(dummy2) + Z_PARAM_ZVAL(dummy3) + Z_PARAM_ZVAL(dummy4) + ZEND_PARSE_PARAMETERS_END(); + } + if (variant > 2 + && zend_parse_parameters(ZEND_NUM_ARGS(), "lll|lll", + &largs[0], &largs[1], &largs[2], &largs[3], &largs[4], &largs[5]) == FAILURE + ) { + RETURN_THROWS(); } // instantion of ICU object @@ -134,8 +143,8 @@ static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool if (variant <= 2) { // From timezone and locale (0 to 2 arguments) - TimeZone *tz = timezone_process_timezone_argument(tz_object, NULL); - if (tz == NULL) { + TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr); + if (tz == nullptr) { // TODO: Exception should always occur already? if (!EG(exception)) { zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); diff --git a/ext/intl/dateformat/dateformat.stub.php b/ext/intl/dateformat/dateformat.stub.php index 7582af2717f..89ebc5f61c0 100644 --- a/ext/intl/dateformat/dateformat.stub.php +++ b/ext/intl/dateformat/dateformat.stub.php @@ -32,20 +32,18 @@ class IntlDateFormatter public const int TRADITIONAL = UNKNOWN; /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @param IntlCalendar|int|null $calendar */ public function __construct( ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, $calendar = null, ?string $pattern = null ) {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type * @alias datefmt_create */ @@ -53,7 +51,7 @@ class IntlDateFormatter ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, IntlCalendar|int|null $calendar = null, ?string $pattern = null ): ?IntlDateFormatter {} @@ -101,11 +99,9 @@ class IntlDateFormatter public function getTimeZone(): IntlTimeZone|false {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type - * @alias datefmt_set_timezone */ - public function setTimeZone($timezone): bool {} + public function setTimeZone(IntlTimeZone|DateTimeZone|string|null $timezone): bool {} /** * @tentative-return-type diff --git a/ext/intl/dateformat/dateformat_arginfo.h b/ext/intl/dateformat/dateformat_arginfo.h index b57cb79468f..d6d0306506f 100644 --- a/ext/intl/dateformat/dateformat_arginfo.h +++ b/ext/intl/dateformat/dateformat_arginfo.h @@ -1,11 +1,11 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 56b66b1b51220ddbff698ec4c9a6ae60f3e0bfb0 */ + * Stub hash: 160d05ec65c45b66b13eaecbef20b3c59bfb33d1 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, calendar, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -14,7 +14,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlDateFormatter ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -40,7 +40,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_IntlDateForm ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlDateFormatter_setTimeZone, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlDateFormatter_setPattern, 0, 1, _IS_BOOL, 0) @@ -100,7 +100,7 @@ ZEND_FUNCTION(datefmt_set_calendar); ZEND_FUNCTION(datefmt_get_timezone_id); ZEND_FUNCTION(datefmt_get_calendar_object); ZEND_FUNCTION(datefmt_get_timezone); -ZEND_FUNCTION(datefmt_set_timezone); +ZEND_METHOD(IntlDateFormatter, setTimeZone); ZEND_FUNCTION(datefmt_set_pattern); ZEND_FUNCTION(datefmt_get_pattern); ZEND_FUNCTION(datefmt_get_locale); @@ -124,7 +124,7 @@ static const zend_function_entry class_IntlDateFormatter_methods[] = { ZEND_RAW_FENTRY("getTimeZoneId", zif_datefmt_get_timezone_id, arginfo_class_IntlDateFormatter_getTimeZoneId, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getCalendarObject", zif_datefmt_get_calendar_object, arginfo_class_IntlDateFormatter_getCalendarObject, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getTimeZone", zif_datefmt_get_timezone, arginfo_class_IntlDateFormatter_getTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("setTimeZone", zif_datefmt_set_timezone, arginfo_class_IntlDateFormatter_setTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(IntlDateFormatter, setTimeZone, arginfo_class_IntlDateFormatter_setTimeZone, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("setPattern", zif_datefmt_set_pattern, arginfo_class_IntlDateFormatter_setPattern, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getPattern", zif_datefmt_get_pattern, arginfo_class_IntlDateFormatter_getPattern, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getLocale", zif_datefmt_get_locale, arginfo_class_IntlDateFormatter_getLocale, ZEND_ACC_PUBLIC, NULL, NULL) diff --git a/ext/intl/dateformat/dateformat_attrcpp.cpp b/ext/intl/dateformat/dateformat_attrcpp.cpp index f95cc0f8de5..13dadc9c969 100644 --- a/ext/intl/dateformat/dateformat_attrcpp.cpp +++ b/ext/intl/dateformat/dateformat_attrcpp.cpp @@ -81,21 +81,46 @@ U_CFUNC PHP_FUNCTION(datefmt_get_timezone) /* {{{ Set formatter's timezone. */ U_CFUNC PHP_FUNCTION(datefmt_set_timezone) { - zval *timezone_zv; - TimeZone *timezone; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; DATE_FORMAT_METHOD_INIT_VARS; - if ( zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Oz", &object, IntlDateFormatter_ce_ptr, &timezone_zv) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(object, IntlDateFormatter_ce_ptr) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); DATE_FORMAT_METHOD_FETCH_OBJECT; - timezone = timezone_process_timezone_argument(timezone_zv, - INTL_DATA_ERROR_P(dfo)); - if (timezone == NULL) { + TimeZone *timezone = timezone_process_timezone_argument( + timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { + RETURN_FALSE; + } + + fetch_datefmt(dfo)->adoptTimeZone(timezone); + + RETURN_TRUE; +} + +U_CFUNC PHP_METHOD(IntlDateFormatter, setTimeZone) +{ + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + + DATE_FORMAT_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); + + object = ZEND_THIS; + DATE_FORMAT_METHOD_FETCH_OBJECT; + + TimeZone *timezone = timezone_process_timezone_argument( + timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { RETURN_FALSE; } diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index 2be1d816374..d2d65bc2673 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -59,7 +59,8 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) Calendar *cal = NULL; zend_long calendar_type; bool calendar_owned; - zval *timezone_zv = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; TimeZone *timezone = NULL; bool explicit_tz; char* pattern_str = NULL; @@ -76,7 +77,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) Z_PARAM_OPTIONAL Z_PARAM_LONG(date_type) Z_PARAM_LONG(time_type) - Z_PARAM_ZVAL(timezone_zv) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(calendar_obj, Calendar_ce_ptr, calendar_long, calendar_is_null) Z_PARAM_STRING_OR_NULL(pattern_str, pattern_str_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); @@ -120,13 +121,12 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) } /* process timezone */ - explicit_tz = timezone_zv != NULL && Z_TYPE_P(timezone_zv) != IS_NULL; + explicit_tz = timezone_object != nullptr || timezone_string != nullptr; if (explicit_tz || calendar_owned ) { //we have an explicit time zone or a non-object calendar - timezone = timezone_process_timezone_argument(timezone_zv, - INTL_DATA_ERROR_P(dfo)); - if (timezone == NULL) { + timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { goto error; } } diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index 080dba6cfe2..e734b2df27b 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -341,9 +341,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo, } if (used_tz == NULL) { - zval nullzv; - ZVAL_NULL(&nullzv); - used_tz = timezone_process_timezone_argument(&nullzv, &err); + used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err); if (used_tz == NULL) { continue; } diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index af1ce6f1edb..d2ca22c6d29 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -173,8 +173,7 @@ class IntlException extends Exception /* calendar */ -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function intlcal_create_instance($timezone = null, ?string $locale = null): ?IntlCalendar {} +function intlcal_create_instance(IntlTimeZone|DateTimeZone|string|null $timezone = null, ?string $locale = null): ?IntlCalendar {} function intlcal_get_keyword_values_for_locale(string $keyword, string $locale, bool $onlyCommon): IntlIterator|false {} @@ -194,8 +193,7 @@ function intlcal_set_time(IntlCalendar $calendar, float $timestamp): bool {} function intlcal_add(IntlCalendar $calendar, int $field, int $value): bool {} -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function intlcal_set_time_zone(IntlCalendar $calendar, $timezone): bool {} +function intlcal_set_time_zone(IntlCalendar $calendar, IntlTimeZone|DateTimeZone|string|null $timezone): bool {} function intlcal_after(IntlCalendar $calendar, IntlCalendar $other): bool {} @@ -328,12 +326,11 @@ function intl_error_name(int $errorCode): string {} /* dateformat */ -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ function datefmt_create( ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, IntlCalendar|int|null $calendar = null, ?string $pattern = null ): ?IntlDateFormatter {} @@ -352,8 +349,7 @@ function datefmt_get_calendar_object(IntlDateFormatter $formatter): IntlCalendar function datefmt_get_timezone(IntlDateFormatter $formatter): IntlTimeZone|false {} -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function datefmt_set_timezone(IntlDateFormatter $formatter, $timezone): bool {} +function datefmt_set_timezone(IntlDateFormatter $formatter, IntlTimeZone|DateTimeZone|string|null $timezone): bool {} function datefmt_set_pattern(IntlDateFormatter $formatter, string $pattern): bool {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index 8f3ba504154..012e274296a 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,8 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: bd78e0b6aec5c52b13f83e3c3cc7770c942d7c20 */ + * Stub hash: 3fa507cf4ace635ae620050db9662b3979890bc1 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -40,7 +40,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_intlcal_set_time_zone, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, calendar, IntlCalendar, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_intlcal_after, 0, 2, _IS_BOOL, 0) @@ -280,7 +280,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_datefmt_create, 0, 1, IntlDateFor ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -312,7 +312,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_datefmt_set_timezone, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, formatter, IntlDateFormatter, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_datefmt_set_pattern, 0, 2, _IS_BOOL, 0) diff --git a/ext/intl/tests/dateformat_setTimeZone_error.phpt b/ext/intl/tests/dateformat_setTimeZone_error.phpt index 633d385323a..08ed8876d2f 100644 --- a/ext/intl/tests/dateformat_setTimeZone_error.phpt +++ b/ext/intl/tests/dateformat_setTimeZone_error.phpt @@ -12,17 +12,16 @@ $df = new IntlDateFormatter(NULL, 0, 0); try { $df->setTimeZone(array()); -} catch (IntlException $e) { - echo $e->getMessage() . PHP_EOL; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { $df->setTimeZone('non existing timezone'); -} catch (IntlException $e) { - echo $e->getMessage(); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> ---EXPECTF-- -Warning: Array to string conversion in %s on line %d -IntlDateFormatter::setTimeZone(): No such time zone: "Array" -IntlDateFormatter::setTimeZone(): No such time zone: "non existing timezone" +--EXPECT-- +TypeError: IntlDateFormatter::setTimeZone(): Argument #1 ($timezone) must be of type object|string|null, array given +IntlException: IntlDateFormatter::setTimeZone(): No such time zone: "non existing timezone" diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp index 0737d994231..b5aed942d1c 100644 --- a/ext/intl/timezone/timezone_class.cpp +++ b/ext/intl/timezone/timezone_class.cpp @@ -131,73 +131,85 @@ static void timezone_throw_exception_with_call_location(const char *msg, const c } /* {{{ timezone_process_timezone_argument - * TimeZone argument processor. outside_error may be NULL (for static functions/constructors) */ -U_CFUNC TimeZone *timezone_process_timezone_argument(zval *zv_timezone, - intl_error *outside_error) + * TimeZone argument processor. outside_error may be nullptr (for static functions/constructors) */ +U_CFUNC TimeZone *timezone_process_timezone_argument( + zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error) { - zval local_zv_tz; std::unique_ptr timeZone; + bool free_string = false; - if (zv_timezone == NULL || Z_TYPE_P(zv_timezone) == IS_NULL) { + if (timezone_object == nullptr && timezone_string == nullptr) { timelib_tzinfo *tzinfo = get_timezone_info(); - ZVAL_STRING(&local_zv_tz, tzinfo->name); - zv_timezone = &local_zv_tz; - } else { - ZVAL_NULL(&local_zv_tz); + timezone_string = zend_string_init(tzinfo->name, strlen(tzinfo->name), false); + free_string = true; } - if (Z_TYPE_P(zv_timezone) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(zv_timezone), TimeZone_ce_ptr)) { - TimeZone_object *to = Z_INTL_TIMEZONE_P(zv_timezone); + if (timezone_object != nullptr) { + if (instanceof_function(timezone_object->ce, TimeZone_ce_ptr)) { + const TimeZone_object *to = php_intl_timezone_fetch_object(timezone_object); - if (to->utimezone == NULL) { - timezone_throw_exception_with_call_location("passed IntlTimeZone is not " - "properly constructed", NULL); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - timeZone = std::unique_ptr(to->utimezone->clone()); - if (UNEXPECTED(timeZone == NULL)) { - timezone_throw_exception_with_call_location("could not clone TimeZone", NULL); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - } else if (Z_TYPE_P(zv_timezone) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(zv_timezone), php_date_get_timezone_ce())) { + if (UNEXPECTED(to->utimezone == nullptr)) { + timezone_throw_exception_with_call_location( + "passed IntlTimeZone is not properly constructed",nullptr); + return nullptr; + } + timeZone = std::unique_ptr(to->utimezone->clone()); + if (UNEXPECTED(timeZone == nullptr)) { + timezone_throw_exception_with_call_location("could not clone TimeZone", nullptr); + return nullptr; + } + // well, this is included by the centralized C intl part so the "smart" part can't go further + return timeZone.release(); + } else if (instanceof_function(timezone_object->ce, php_date_get_timezone_ce())) { + php_timezone_obj *tz_obj = php_timezone_obj_from_obj(timezone_object); - php_timezone_obj *tzobj = Z_PHPTIMEZONE_P(zv_timezone); - - zval_ptr_dtor_str(&local_zv_tz); - return timezone_convert_datetimezone(tzobj->type, tzobj, 0, outside_error); - } else { - UnicodeString id; - UErrorCode status = U_ZERO_ERROR; /* outside_error may be NULL */ - if (!try_convert_to_string(zv_timezone)) { - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - if (intl_stringFromChar(id, Z_STRVAL_P(zv_timezone), Z_STRLEN_P(zv_timezone), - &status) == FAILURE) { - timezone_throw_exception_with_call_location("Time zone identifier given is not a " - "valid UTF-8 string", NULL); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - timeZone = std::unique_ptr(TimeZone::createTimeZone(id)); - if (UNEXPECTED(timeZone == NULL)) { - timezone_throw_exception_with_call_location("Could not create time zone", NULL); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - if (*timeZone == TimeZone::getUnknown()) { - timezone_throw_exception_with_call_location("No such time zone: ", Z_STRVAL_P(zv_timezone)); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; + return timezone_convert_datetimezone(tz_obj->type, tz_obj, false, outside_error); + } else { + zval tmp; + zend_result status = timezone_object->handlers->cast_object(timezone_object, &tmp, IS_STRING); + if (EXPECTED(status == SUCCESS)) { + timezone_string = Z_STR(tmp); + free_string = true; + } else { + if (!EG(exception)) { + // TODO Proper type error + zend_throw_error(nullptr, "Object of class %s could not be converted to string", ZSTR_VAL(timezone_object->ce->name)); + } + return nullptr; + } } } - zval_ptr_dtor_str(&local_zv_tz); + ZEND_ASSERT(timezone_string != nullptr); + UnicodeString id; + UErrorCode status = U_ZERO_ERROR; /* outside_error may be nullptr */ + if (UNEXPECTED(intl_stringFromChar(id, ZSTR_VAL(timezone_string), ZSTR_LEN(timezone_string), &status) == FAILURE)) { + timezone_throw_exception_with_call_location("Time zone identifier given is not a valid UTF-8 string", nullptr); + if (free_string) { + zend_string_release_ex(timezone_string, false); + } + return nullptr; + } + + timeZone = std::unique_ptr(TimeZone::createTimeZone(id)); + if (UNEXPECTED(timeZone == nullptr)) { + timezone_throw_exception_with_call_location("Could not create time zone",nullptr); + if (free_string) { + zend_string_release_ex(timezone_string, false); + } + return nullptr; + } + if (UNEXPECTED(*timeZone == TimeZone::getUnknown())) { + timezone_throw_exception_with_call_location("No such time zone: ", ZSTR_VAL(timezone_string)); + if (free_string) { + zend_string_release_ex(timezone_string, false); + } + return nullptr; + } + if (free_string) { + zend_string_release_ex(timezone_string, false); + } // well, this is included by the centralized C intl part so the "smart" part can't go further return timeZone.release(); } diff --git a/ext/intl/timezone/timezone_class.h b/ext/intl/timezone/timezone_class.h index 08b78369e6f..bbfd8adcae2 100644 --- a/ext/intl/timezone/timezone_class.h +++ b/ext/intl/timezone/timezone_class.h @@ -67,7 +67,7 @@ static inline TimeZone_object *php_intl_timezone_fetch_object(zend_object *obj) } zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, zval *ret); -TimeZone *timezone_process_timezone_argument(zval *zv_timezone, intl_error *error); +TimeZone *timezone_process_timezone_argument(zend_object *timezone_object, zend_string *timezone_string, intl_error *error); void timezone_object_construct(const TimeZone *zone, zval *object, int owned);