Skip to content

Commit a100450

Browse files
authored
ext/intl: Call DateTimeInterface::getTimestamp() directly (#17487)
1 parent b8ee4c2 commit a100450

File tree

4 files changed

+25
-29
lines changed

4 files changed

+25
-29
lines changed

ext/intl/common/common_date.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,11 @@ U_CFUNC TimeZone *timezone_convert_datetimezone(int type,
9494
}
9595
/* }}} */
9696

97-
U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
97+
U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz,
9898
intl_error *err, const char *func)
9999
{
100-
zval retval;
101-
zval zfuncname;
102100
char *message;
101+
php_date_obj *datetime = php_date_obj_from_obj(obj);
103102

104103
if (err && U_FAILURE(err->code)) {
105104
return FAILURE;
@@ -109,35 +108,35 @@ U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
109108
*millis = ZEND_NAN;
110109
}
111110
if (tz) {
112-
*tz = NULL;
111+
*tz = nullptr;
113112
}
114113

115114
if (millis) {
116-
php_date_obj *datetime;
117-
118-
ZVAL_STRING(&zfuncname, "getTimestamp");
119-
if (call_user_function(NULL, z, &zfuncname, &retval, 0, NULL)
120-
!= SUCCESS || Z_TYPE(retval) != IS_LONG) {
121-
spprintf(&message, 0, "%s: error calling ::getTimeStamp() on the "
122-
"object", func);
123-
intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR,
124-
message, 1);
115+
auto getTimestampMethod = static_cast<zend_function *>(zend_hash_str_find_ptr(&obj->ce->function_table, ZEND_STRL("gettimestamp")));
116+
zval retval;
117+
118+
ZEND_ASSERT(getTimestampMethod && "DateTimeInterface is sealed and thus must have this method");
119+
zend_call_known_function(getTimestampMethod, obj, obj->ce, &retval, 0, nullptr, nullptr);
120+
121+
/* An exception has occurred */
122+
if (Z_TYPE(retval) == IS_UNDEF) {
123+
return FAILURE;
124+
}
125+
// TODO: Remove this when DateTimeInterface::getTimestamp() no longer has a tentative return type
126+
if (Z_TYPE(retval) != IS_LONG) {
127+
spprintf(&message, 0, "%s: %s::getTimestamp() did not return an int", func, ZSTR_VAL(obj->ce->name));
128+
intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, message, 1);
125129
efree(message);
126-
zval_ptr_dtor(&zfuncname);
127130
return FAILURE;
128131
}
129132

130-
datetime = Z_PHPDATE_P(z);
131133
*millis = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval) + (datetime->time->us / 1000);
132-
zval_ptr_dtor(&zfuncname);
133134
}
134135

135136
if (tz) {
136-
php_date_obj *datetime;
137-
datetime = Z_PHPDATE_P(z);
138137
if (!datetime->time) {
139138
spprintf(&message, 0, "%s: the %s object is not properly "
140-
"initialized", func, ZSTR_VAL(Z_OBJCE_P(z)->name));
139+
"initialized", func, ZSTR_VAL(obj->ce->name));
141140
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
142141
message, 1);
143142
efree(message);
@@ -198,7 +197,7 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func)
198197
break;
199198
case IS_OBJECT:
200199
if (instanceof_function(Z_OBJCE_P(z), php_date_get_interface_ce())) {
201-
intl_datetime_decompose(z, &rv, NULL, err, func);
200+
intl_datetime_decompose(Z_OBJ_P(z), &rv, nullptr, err, func);
202201
} else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr)) {
203202
Calendar_object *co = Z_INTL_CALENDAR_P(z);
204203
if (co->ucal == NULL) {

ext/intl/common/common_date.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ U_CDECL_END
2929
using icu::TimeZone;
3030

3131
U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func);
32-
U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
33-
intl_error *err, const char *func);
32+
U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, intl_error *err, const char *func);
3433

3534
#endif
3635

ext/intl/dateformat/dateformat_format_object.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ static bool valid_format(zval *z) {
6464

6565
U_CFUNC PHP_FUNCTION(datefmt_format_object)
6666
{
67-
zval *object,
68-
*format = NULL;
67+
zend_object *object;
68+
zval *format = NULL;
6969
char *locale_str = NULL;
7070
size_t locale_len;
7171
bool pattern = false;
@@ -78,7 +78,7 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object)
7878
timeStyle = DateFormat::kDefault;
7979

8080
ZEND_PARSE_PARAMETERS_START(1, 3)
81-
Z_PARAM_OBJECT(object)
81+
Z_PARAM_OBJ(object)
8282
Z_PARAM_OPTIONAL
8383
Z_PARAM_ZVAL(format)
8484
Z_PARAM_STRING_OR_NULL(locale_str, locale_len)
@@ -149,9 +149,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object)
149149
timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative);
150150
}
151151

152-
zend_class_entry *instance_ce = Z_OBJCE_P(object);
152+
zend_class_entry *instance_ce = object->ce;
153153
if (instanceof_function(instance_ce, Calendar_ce_ptr)) {
154-
Calendar *obj_cal = calendar_fetch_native_calendar(Z_OBJ_P(object));
154+
Calendar *obj_cal = calendar_fetch_native_calendar(object);
155155
if (obj_cal == NULL) {
156156
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
157157
"datefmt_format_object: bad IntlCalendar instance: "

ext/intl/tests/dateformat_formatObject_error.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ bool(false)
3434

3535
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad IntlCalendar instance: not initialized properly in %s on line %d
3636
bool(false)
37-
38-
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: error calling ::getTimeStamp() on the object in %s on line %d
3937
Object of type B (inheriting DateTime) has not been correctly initialized by calling parent::__construct() in its constructor
4038

4139
Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the date/time format type is invalid in %s on line %d

0 commit comments

Comments
 (0)