diff --git a/ext/intl/common/common_date.cpp b/ext/intl/common/common_date.cpp index 2a52b7e63be5c..e4f442a8195ad 100644 --- a/ext/intl/common/common_date.cpp +++ b/ext/intl/common/common_date.cpp @@ -94,12 +94,11 @@ U_CFUNC TimeZone *timezone_convert_datetimezone(int type, } /* }}} */ -U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz, +U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, intl_error *err, const char *func) { - zval retval; - zval zfuncname; char *message; + php_date_obj *datetime = php_date_obj_from_obj(obj); if (err && U_FAILURE(err->code)) { return FAILURE; @@ -109,35 +108,35 @@ U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz, *millis = ZEND_NAN; } if (tz) { - *tz = NULL; + *tz = nullptr; } if (millis) { - php_date_obj *datetime; - - ZVAL_STRING(&zfuncname, "getTimestamp"); - if (call_user_function(NULL, z, &zfuncname, &retval, 0, NULL) - != SUCCESS || Z_TYPE(retval) != IS_LONG) { - spprintf(&message, 0, "%s: error calling ::getTimeStamp() on the " - "object", func); - intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, - message, 1); + auto getTimestampMethod = static_cast(zend_hash_str_find_ptr(&obj->ce->function_table, ZEND_STRL("gettimestamp"))); + zval retval; + + ZEND_ASSERT(getTimestampMethod && "DateTimeInterface is sealed and thus must have this method"); + zend_call_known_function(getTimestampMethod, obj, obj->ce, &retval, 0, nullptr, nullptr); + + /* An exception has occurred */ + if (Z_TYPE(retval) == IS_UNDEF) { + return FAILURE; + } + // TODO: Remove this when DateTimeInterface::getTimestamp() no longer has a tentative return type + if (Z_TYPE(retval) != IS_LONG) { + spprintf(&message, 0, "%s: %s::getTimestamp() did not return an int", func, ZSTR_VAL(obj->ce->name)); + intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, message, 1); efree(message); - zval_ptr_dtor(&zfuncname); return FAILURE; } - datetime = Z_PHPDATE_P(z); *millis = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval) + (datetime->time->us / 1000); - zval_ptr_dtor(&zfuncname); } if (tz) { - php_date_obj *datetime; - datetime = Z_PHPDATE_P(z); if (!datetime->time) { spprintf(&message, 0, "%s: the %s object is not properly " - "initialized", func, ZSTR_VAL(Z_OBJCE_P(z)->name)); + "initialized", func, ZSTR_VAL(obj->ce->name)); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); efree(message); @@ -198,7 +197,7 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func) break; case IS_OBJECT: if (instanceof_function(Z_OBJCE_P(z), php_date_get_interface_ce())) { - intl_datetime_decompose(z, &rv, NULL, err, func); + intl_datetime_decompose(Z_OBJ_P(z), &rv, nullptr, err, func); } else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr)) { Calendar_object *co = Z_INTL_CALENDAR_P(z); if (co->ucal == NULL) { diff --git a/ext/intl/common/common_date.h b/ext/intl/common/common_date.h index c5818106ba3dc..e9fac3a02bd57 100644 --- a/ext/intl/common/common_date.h +++ b/ext/intl/common/common_date.h @@ -29,8 +29,7 @@ U_CDECL_END using icu::TimeZone; U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func); -U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz, - intl_error *err, const char *func); +U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, intl_error *err, const char *func); #endif diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index c5dc9acd9d58b..81490c62fd5e2 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -64,8 +64,8 @@ static bool valid_format(zval *z) { U_CFUNC PHP_FUNCTION(datefmt_format_object) { - zval *object, - *format = NULL; + zend_object *object; + zval *format = NULL; char *locale_str = NULL; size_t locale_len; bool pattern = false; @@ -78,7 +78,7 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) timeStyle = DateFormat::kDefault; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_OBJECT(object) + Z_PARAM_OBJ(object) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(format) Z_PARAM_STRING_OR_NULL(locale_str, locale_len) @@ -149,9 +149,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); } - zend_class_entry *instance_ce = Z_OBJCE_P(object); + zend_class_entry *instance_ce = object->ce; if (instanceof_function(instance_ce, Calendar_ce_ptr)) { - Calendar *obj_cal = calendar_fetch_native_calendar(Z_OBJ_P(object)); + Calendar *obj_cal = calendar_fetch_native_calendar(object); if (obj_cal == NULL) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad IntlCalendar instance: " diff --git a/ext/intl/tests/dateformat_formatObject_error.phpt b/ext/intl/tests/dateformat_formatObject_error.phpt index 839cb27d317c9..f2444a5955167 100644 --- a/ext/intl/tests/dateformat_formatObject_error.phpt +++ b/ext/intl/tests/dateformat_formatObject_error.phpt @@ -34,8 +34,6 @@ bool(false) Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad IntlCalendar instance: not initialized properly in %s on line %d bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: error calling ::getTimeStamp() on the object in %s on line %d Object of type B (inheriting DateTime) has not been correctly initialized by calling parent::__construct() in its constructor Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the date/time format type is invalid in %s on line %d