ext/intl: Refactor timezone parameter passing (#19409)

This commit is contained in:
Gina Peter Banyard 2025-08-08 21:12:43 +01:00 committed by GitHub
parent be2889411a
commit 43a91089ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 207 additions and 145 deletions

View file

@ -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

View file

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

View file

@ -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,

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

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

View file

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

View file

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

View file

@ -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 {}

View file

@ -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)

View file

@ -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"

View file

@ -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> 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<TimeZone>(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<TimeZone>(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>(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>(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();
}

View file

@ -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);