From 54f607df6c536130114056a0c7180caeced4e1da Mon Sep 17 00:00:00 2001 From: Paul Fedorow Date: Fri, 27 Oct 2023 08:48:11 +0200 Subject: [PATCH] Fix GH-11310: __debugInfo() does nothing on classes extending DateTime Makes the `__debugInfo` method work in classes that extend `DateTime` and `DateTimeImmutable`. * Implemented `__debugInfo` for `DateTime` and `DateTimeImmutable`. * Modified the `get_properties_for` handlers of `DateTime` and `DateTimeImmutable` to invoke `__debugInfo`. --- ext/date/php_date.c | 51 ++++++++++++++++++++++++++ ext/date/php_date.stub.php | 6 +++ ext/date/php_date_arginfo.h | 14 +++++-- ext/date/tests/date_debugInfo.phpt | 59 ++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 ext/date/tests/date_debugInfo.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 96c37092511fd..2ea04fa013657 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1959,6 +1959,13 @@ static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_ switch (purpose) { case ZEND_PROP_PURPOSE_DEBUG: + ZEND_ASSERT(object->ce->__debugInfo != NULL); + int is_temp = 0; + HashTable *ht = zend_std_get_debug_info(object, &is_temp); + if (ht && !is_temp) { + GC_TRY_ADDREF(ht); + } + return ht; case ZEND_PROP_PURPOSE_SERIALIZE: case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: @@ -2845,6 +2852,50 @@ PHP_METHOD(DateTimeImmutable, __serialize) } /* }}} */ +/* {{{ */ +PHP_METHOD(DateTime, __debugInfo) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(object); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + + add_common_properties(myht, &dateobj->std); + + if (dateobj->time) { + date_object_to_hash(dateobj, myht); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(DateTimeImmutable, __debugInfo) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(object); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + + add_common_properties(myht, &dateobj->std); + + if (dateobj->time) { + date_object_to_hash(dateobj, myht); + } +} +/* }}} */ + static bool date_time_is_internal_property(zend_string *name) { if ( diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index e0717fa7f4c85..c35d6f44134c0 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -344,6 +344,9 @@ public function __serialize(): array {} public function __unserialize(array $data): void {} + /** @tentative-return-type */ + public function __debugInfo(): array {} + /** @tentative-return-type */ public function __wakeup(): void {} @@ -454,6 +457,9 @@ public function __serialize(): array {} public function __unserialize(array $data): void {} + /** @tentative-return-type */ + public function __debugInfo(): array {} + /** @tentative-return-type */ public function __wakeup(): void {} diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index bbede1f39596e..ce7784aa0d2cc 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0f204ac6646be79b515189a384fce9bcea9a4f42 */ + * Stub hash: 829655ae647a8068fbad11b9608902f71a4a0d31 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0) @@ -260,6 +260,9 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateTime___unserialize arginfo_class_DateTimeInterface___unserialize +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTime___debugInfo, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + #define arginfo_class_DateTime___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime___set_state, 0, 1, DateTime, 0) @@ -336,6 +339,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateTimeImmutable___unserialize arginfo_class_DateTimeInterface___unserialize +#define arginfo_class_DateTimeImmutable___debugInfo arginfo_class_DateTime___debugInfo + #define arginfo_class_DateTimeImmutable___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable___set_state, 0, 1, DateTimeImmutable, 0) @@ -423,8 +428,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateTimeZone_getLocation arginfo_class_DateTime_getLastErrors -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_listAbbreviations, 0, 0, IS_ARRAY, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_DateTimeZone_listAbbreviations arginfo_class_DateTime___debugInfo ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_listIdentifiers, 0, 0, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timezoneGroup, IS_LONG, 0, "DateTimeZone::ALL") @@ -550,6 +554,7 @@ ZEND_FUNCTION(date_sun_info); ZEND_METHOD(DateTime, __construct); ZEND_METHOD(DateTime, __serialize); ZEND_METHOD(DateTime, __unserialize); +ZEND_METHOD(DateTime, __debugInfo); ZEND_METHOD(DateTime, __wakeup); ZEND_METHOD(DateTime, __set_state); ZEND_METHOD(DateTime, createFromImmutable); @@ -559,6 +564,7 @@ ZEND_METHOD(DateTime, sub); ZEND_METHOD(DateTimeImmutable, __construct); ZEND_METHOD(DateTimeImmutable, __serialize); ZEND_METHOD(DateTimeImmutable, __unserialize); +ZEND_METHOD(DateTimeImmutable, __debugInfo); ZEND_METHOD(DateTimeImmutable, __wakeup); ZEND_METHOD(DateTimeImmutable, __set_state); ZEND_METHOD(DateTimeImmutable, modify); @@ -665,6 +671,7 @@ static const zend_function_entry class_DateTime_methods[] = { ZEND_ME(DateTime, __construct, arginfo_class_DateTime___construct, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __serialize, arginfo_class_DateTime___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __unserialize, arginfo_class_DateTime___unserialize, ZEND_ACC_PUBLIC) + ZEND_ME(DateTime, __debugInfo, arginfo_class_DateTime___debugInfo, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __wakeup, arginfo_class_DateTime___wakeup, ZEND_ACC_PUBLIC) ZEND_ME(DateTime, __set_state, arginfo_class_DateTime___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DateTime, createFromImmutable, arginfo_class_DateTime_createFromImmutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -692,6 +699,7 @@ static const zend_function_entry class_DateTimeImmutable_methods[] = { ZEND_ME(DateTimeImmutable, __construct, arginfo_class_DateTimeImmutable___construct, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __serialize, arginfo_class_DateTimeImmutable___serialize, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __unserialize, arginfo_class_DateTimeImmutable___unserialize, ZEND_ACC_PUBLIC) + ZEND_ME(DateTimeImmutable, __debugInfo, arginfo_class_DateTimeImmutable___debugInfo, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __wakeup, arginfo_class_DateTimeImmutable___wakeup, ZEND_ACC_PUBLIC) ZEND_ME(DateTimeImmutable, __set_state, arginfo_class_DateTimeImmutable___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME_MAPPING(createFromFormat, date_create_immutable_from_format, arginfo_class_DateTimeImmutable_createFromFormat, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) diff --git a/ext/date/tests/date_debugInfo.phpt b/ext/date/tests/date_debugInfo.phpt new file mode 100644 index 0000000000000..0ee5a5043b667 --- /dev/null +++ b/ext/date/tests/date_debugInfo.phpt @@ -0,0 +1,59 @@ +--TEST-- +Bug GH-11310: __debugInfo() does nothing on classes extending DateTime +--INI-- +date.timezone=UTC +--FILE-- + '42', 'parent' => count(parent::__debugInfo())]; + } +} + +class MyDateTimeImmutable extends DateTimeImmutable { + public function __debugInfo(): array { + return ['child' => '42', 'parent' => count(parent::__debugInfo())]; + } +} + +class MyDateTimeZone extends DateTimeZone { + public function __debugInfo(): array { + return ['child' => '42', 'parent' => count(parent::__debugInfo())]; + } +} + +var_dump(new DateTime('2023-10-26 21:23:05')); +var_dump(new DateTimeImmutable('2023-10-26 21:23:05')); +var_dump(new MyDateTime('2023-10-26 21:23:05')); +var_dump(new MyDateTimeImmutable('2023-10-26 21:23:05')); +?> +--EXPECT-- +object(DateTime)#1 (3) { + ["date"]=> + string(26) "2023-10-26 21:23:05.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} +object(DateTimeImmutable)#1 (3) { + ["date"]=> + string(26) "2023-10-26 21:23:05.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} +object(MyDateTime)#1 (2) { + ["child"]=> + string(2) "42" + ["parent"]=> + int(3) +} +object(MyDateTimeImmutable)#1 (2) { + ["child"]=> + string(2) "42" + ["parent"]=> + int(3) +}