diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 90861b49c68f0..2ef8513d74f15 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -822,7 +822,7 @@ static HashTable *spl_array_get_properties_for(zval *object, zend_prop_purpose p return ht; } /* }}} */ -static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */ +static inline HashTable* spl_array_get_debug_info(zval *obj) /* {{{ */ { zval *storage; zend_string *zname; @@ -834,11 +834,9 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */ } if (intern->ar_flags & SPL_ARRAY_IS_SELF) { - *is_temp = 0; - return intern->std.properties; + return zend_array_dup(intern->std.properties); } else { HashTable *debug_info; - *is_temp = 1; debug_info = zend_new_array(zend_hash_num_elements(intern->std.properties) + 1); zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref); @@ -1883,6 +1881,18 @@ SPL_METHOD(Array, __unserialize) } /* }}} */ +/* {{{ proto void Array::__debugInfo() */ +SPL_METHOD(Array, __debugInfo) +{ + HashTable *ht; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_array_get_debug_info(getThis())); +} /* }}} */ + /* {{{ arginfo and function table */ ZEND_BEGIN_ARG_INFO_EX(arginfo_array___construct, 0, 0, 0) ZEND_ARG_INFO(0, input) @@ -1957,6 +1967,7 @@ static const zend_function_entry spl_funcs_ArrayObject[] = { SPL_ME(Array, serialize, arginfo_array_void, ZEND_ACC_PUBLIC) SPL_ME(Array, __unserialize, arginfo_array_unserialize, ZEND_ACC_PUBLIC) SPL_ME(Array, __serialize, arginfo_array_void, ZEND_ACC_PUBLIC) + SPL_ME(Array, __debugInfo, arginfo_array_void, ZEND_ACC_PUBLIC) /* ArrayObject specific */ SPL_ME(Array, getIterator, arginfo_array_void, ZEND_ACC_PUBLIC) SPL_ME(Array, exchangeArray, arginfo_array_exchangeArray, ZEND_ACC_PUBLIC) @@ -1986,6 +1997,7 @@ static const zend_function_entry spl_funcs_ArrayIterator[] = { SPL_ME(Array, serialize, arginfo_array_void, ZEND_ACC_PUBLIC) SPL_ME(Array, __unserialize, arginfo_array_unserialize, ZEND_ACC_PUBLIC) SPL_ME(Array, __serialize, arginfo_array_void, ZEND_ACC_PUBLIC) + SPL_ME(Array, __debugInfo, arginfo_array_void, ZEND_ACC_PUBLIC) /* ArrayIterator specific */ SPL_ME(Array, rewind, arginfo_array_void, ZEND_ACC_PUBLIC) SPL_ME(Array, current, arginfo_array_void, ZEND_ACC_PUBLIC) @@ -2023,7 +2035,6 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.count_elements = spl_array_object_count_elements; spl_handler_ArrayObject.get_properties_for = spl_array_get_properties_for; - spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info; spl_handler_ArrayObject.get_gc = spl_array_get_gc; spl_handler_ArrayObject.read_property = spl_array_read_property; spl_handler_ArrayObject.write_property = spl_array_write_property; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index d7995bd7fac7f..d42e6367c2f3e 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -598,7 +598,7 @@ static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, s } /* }}} */ -static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_temp) /* {{{ */ +static inline HashTable *spl_filesystem_object_get_debug_info(zval *object) /* {{{ */ { spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(object); zval tmp; @@ -608,8 +608,6 @@ static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_tem size_t path_len; char stmp[2]; - *is_temp = 1; - if (!intern->std.properties) { rebuild_object_properties(&intern->std); } @@ -1421,6 +1419,16 @@ SPL_METHOD(SplFileInfo, getPathInfo) } /* }}} */ +/* {{{ proto void SplFileInfo::__debugInfo() */ +SPL_METHOD(SplFileInfo, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_filesystem_object_get_debug_info(getThis())); +} /* }}} */ + /* {{{ proto SplFileInfo::_bad_state_ex(void) */ SPL_METHOD(SplFileInfo, _bad_state_ex) { @@ -1947,6 +1955,7 @@ static const zend_function_entry spl_SplFileInfo_functions[] = { SPL_ME(SplFileInfo, openFile, arginfo_info_openFile, ZEND_ACC_PUBLIC) SPL_ME(SplFileInfo, setFileClass, arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC) SPL_ME(SplFileInfo, setInfoClass, arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC) + SPL_ME(SplFileInfo, __debugInfo, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) SPL_ME(SplFileInfo, _bad_state_ex, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) SPL_MA(SplFileInfo, __toString, SplFileInfo, getPathname, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC) PHP_FE_END @@ -3143,7 +3152,6 @@ PHP_MINIT_FUNCTION(spl_directory) spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std); spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast; - spl_filesystem_object_handlers.get_debug_info = spl_filesystem_object_get_debug_info; spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object; spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage; spl_ce_SplFileInfo->serialize = zend_class_serialize_deny; diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index a0eb06a97aa49..ce5504da7e560 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -492,7 +492,7 @@ static int spl_dllist_object_count_elements(zval *object, zend_long *count) /* { } /* }}} */ -static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp) /* {{{{ */ +static inline HashTable* spl_dllist_object_get_debug_info(zval *obj) /* {{{{ */ { spl_dllist_object *intern = Z_SPLDLLIST_P(obj); spl_ptr_llist_element *current = intern->llist->head, *next; @@ -500,7 +500,6 @@ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp) /* { zend_string *pnstr; int i = 0; HashTable *debug_info; - *is_temp = 1; if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -1344,6 +1343,16 @@ SPL_METHOD(SplDoublyLinkedList, add) } } /* }}} */ +/* {{{ proto void SplDoublyLinkedList::__debugInfo() */ +SPL_METHOD(SplDoublyLinkedList, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_dllist_object_get_debug_info(getThis())); +} /* }}} */ + /* {{{ iterator handler table */ static const zend_object_iterator_funcs spl_dllist_it_funcs = { spl_dllist_it_dtor, @@ -1425,6 +1434,7 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = { SPL_ME(SplDoublyLinkedList, isEmpty, arginfo_dllist_void, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC) SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void, ZEND_ACC_PUBLIC) + SPL_ME(SplDoublyLinkedList, __debugInfo, arginfo_dllist_void, ZEND_ACC_PUBLIC) /* Countable */ SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC) /* ArrayAccess */ @@ -1459,7 +1469,6 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ spl_handler_SplDoublyLinkedList.offset = XtOffsetOf(spl_dllist_object, std); spl_handler_SplDoublyLinkedList.clone_obj = spl_dllist_object_clone; spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements; - spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info; spl_handler_SplDoublyLinkedList.get_gc = spl_dllist_object_get_gc; spl_handler_SplDoublyLinkedList.dtor_obj = zend_objects_destroy_object; spl_handler_SplDoublyLinkedList.free_obj = spl_dllist_object_free_storage; diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 8191c2901d6d7..4aea640c71ece 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -501,15 +501,13 @@ static int spl_heap_object_count_elements(zval *object, zend_long *count) /* {{{ } /* }}} */ -static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp) { /* {{{ */ +static inline HashTable* spl_heap_object_get_debug_info(zend_class_entry *ce, zval *obj) { /* {{{ */ spl_heap_object *intern = Z_SPLHEAP_P(obj); zval tmp, heap_array; zend_string *pnstr; HashTable *debug_info; int i; - *is_temp = 1; - if (!intern->std.properties) { rebuild_object_properties(&intern->std); } @@ -571,18 +569,6 @@ static HashTable *spl_pqueue_object_get_gc(zval *obj, zval **gc_data, int *gc_da } /* }}} */ -static HashTable* spl_heap_object_get_debug_info(zval *obj, int *is_temp) /* {{{ */ -{ - return spl_heap_object_get_debug_info_helper(spl_ce_SplHeap, obj, is_temp); -} -/* }}} */ - -static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp) /* {{{ */ -{ - return spl_heap_object_get_debug_info_helper(spl_ce_SplPriorityQueue, obj, is_temp); -} -/* }}} */ - /* {{{ proto int SplHeap::count() Return the number of elements in the heap. */ SPL_METHOD(SplHeap, count) @@ -1065,6 +1051,26 @@ SPL_METHOD(SplPriorityQueue, current) } /* }}} */ +/* {{{ proto void SplHeap::__debugInfo() */ +SPL_METHOD(SplHeap, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplHeap, getThis())); +} /* }}} */ + +/* {{{ proto void SplPriorityQueue::__debugInfo() */ +SPL_METHOD(SplPriorityQueue, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplPriorityQueue, getThis())); +} /* }}} */ + /* iterator handler table */ static const zend_object_iterator_funcs spl_heap_it_funcs = { spl_heap_it_dtor, @@ -1183,6 +1189,7 @@ static const zend_function_entry spl_funcs_SplPriorityQueue[] = { SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, isCorrupted, arginfo_splheap_void, ZEND_ACC_PUBLIC) + SPL_ME(SplPriorityQueue, __debugInfo, arginfo_splheap_void, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -1199,6 +1206,7 @@ static const zend_function_entry spl_funcs_SplHeap[] = { SPL_ME(SplHeap, valid, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, recoverFromCorruption, arginfo_splheap_void, ZEND_ACC_PUBLIC) SPL_ME(SplHeap, isCorrupted, arginfo_splheap_void, ZEND_ACC_PUBLIC) + SPL_ME(SplHeap, __debugInfo, arginfo_splheap_void, ZEND_ACC_PUBLIC) ZEND_FENTRY(compare, NULL, NULL, ZEND_ACC_PROTECTED|ZEND_ACC_ABSTRACT) PHP_FE_END }; @@ -1212,7 +1220,6 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ spl_handler_SplHeap.offset = XtOffsetOf(spl_heap_object, std); spl_handler_SplHeap.clone_obj = spl_heap_object_clone; spl_handler_SplHeap.count_elements = spl_heap_object_count_elements; - spl_handler_SplHeap.get_debug_info = spl_heap_object_get_debug_info; spl_handler_SplHeap.get_gc = spl_heap_object_get_gc; spl_handler_SplHeap.dtor_obj = zend_objects_destroy_object; spl_handler_SplHeap.free_obj = spl_heap_object_free_storage; @@ -1234,7 +1241,6 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ spl_handler_SplPriorityQueue.offset = XtOffsetOf(spl_heap_object, std); spl_handler_SplPriorityQueue.clone_obj = spl_heap_object_clone; spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements; - spl_handler_SplPriorityQueue.get_debug_info = spl_pqueue_object_get_debug_info; spl_handler_SplPriorityQueue.get_gc = spl_pqueue_object_get_gc; spl_handler_SplPriorityQueue.dtor_obj = zend_objects_destroy_object; spl_handler_SplPriorityQueue.free_obj = spl_heap_object_free_storage; diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index ba29e0311e493..f7dd7ef2e0742 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -279,7 +279,7 @@ static zend_object *spl_object_storage_clone(zval *zobject) } /* }}} */ -static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{ */ +static inline HashTable* spl_object_storage_debug_info(zval *obj) /* {{{ */ { spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(obj); spl_SplObjectStorageElement *element; @@ -289,8 +289,6 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{ zend_string *zname; HashTable *debug_info; - *is_temp = 1; - props = Z_OBJPROP_P(obj); debug_info = zend_new_array(zend_hash_num_elements(props) + 1); @@ -945,6 +943,17 @@ SPL_METHOD(SplObjectStorage, __unserialize) object_properties_load(&intern->std, Z_ARRVAL_P(members_zv)); } +/* {{{ proto array SplObjectStorage::__debugInfo() */ +SPL_METHOD(SplObjectStorage, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_ARR(spl_object_storage_debug_info(getThis())); +} +/* }}} */ + ZEND_BEGIN_ARG_INFO(arginfo_Object, 0) ZEND_ARG_INFO(0, object) ZEND_END_ARG_INFO(); @@ -983,6 +992,7 @@ static const zend_function_entry spl_funcs_SplObjectStorage[] = { SPL_ME(SplObjectStorage, getInfo, arginfo_splobject_void,0) SPL_ME(SplObjectStorage, setInfo, arginfo_setInfo, 0) SPL_ME(SplObjectStorage, getHash, arginfo_getHash, 0) + SPL_ME(SplObjectStorage, __debugInfo, arginfo_splobject_void,0) /* Countable */ SPL_ME(SplObjectStorage, count, arginfo_splobject_void,0) /* Iterator */ @@ -1301,9 +1311,10 @@ static const zend_function_entry spl_funcs_MultipleIterator[] = { SPL_ME(MultipleIterator, getFlags, arginfo_splobject_void, 0) SPL_ME(MultipleIterator, setFlags, arginfo_MultipleIterator_setflags, 0) SPL_ME(MultipleIterator, attachIterator, arginfo_MultipleIterator_attachIterator, 0) - SPL_MA(MultipleIterator, detachIterator, SplObjectStorage, detach, arginfo_MultipleIterator_detachIterator, 0) - SPL_MA(MultipleIterator, containsIterator, SplObjectStorage, contains, arginfo_MultipleIterator_containsIterator, 0) - SPL_MA(MultipleIterator, countIterators, SplObjectStorage, count, arginfo_splobject_void, 0) + SPL_MA(MultipleIterator, detachIterator, SplObjectStorage, detach, arginfo_MultipleIterator_detachIterator, 0) + SPL_MA(MultipleIterator, containsIterator, SplObjectStorage, contains, arginfo_MultipleIterator_containsIterator, 0) + SPL_MA(MultipleIterator, countIterators, SplObjectStorage, count, arginfo_splobject_void, 0) + SPL_MA(MultipleIterator, __debugInfo, SplObjectStorage, __debugInfo, arginfo_splobject_void, 0) /* Iterator */ SPL_ME(MultipleIterator, rewind, arginfo_splobject_void, 0) SPL_ME(MultipleIterator, valid, arginfo_splobject_void, 0) @@ -1323,7 +1334,6 @@ PHP_MINIT_FUNCTION(spl_observer) memcpy(&spl_handler_SplObjectStorage, &std_object_handlers, sizeof(zend_object_handlers)); spl_handler_SplObjectStorage.offset = XtOffsetOf(spl_SplObjectStorage, std); - spl_handler_SplObjectStorage.get_debug_info = spl_object_storage_debug_info; spl_handler_SplObjectStorage.compare_objects = spl_object_storage_compare_objects; spl_handler_SplObjectStorage.clone_obj = spl_object_storage_clone; spl_handler_SplObjectStorage.get_gc = spl_object_storage_get_gc; diff --git a/ext/spl/tests/bug69264.phpt b/ext/spl/tests/bug69264.phpt new file mode 100644 index 0000000000000..2f5251d1770ad --- /dev/null +++ b/ext/spl/tests/bug69264.phpt @@ -0,0 +1,112 @@ +--TEST-- +Bug #69264 (__debugInfo() ignored while extending SPL classes) +--FILE-- + 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyDoublyLinkedList extends SplDoublyLinkedList { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyObjectStorage extends SplObjectStorage { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyMultipleIterator extends MultipleIterator { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyArrayObject extends ArrayObject { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyArrayIterator extends ArrayIterator { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyMaxHeap extends SplMaxHeap { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +class MyPriorityQueue extends SplPriorityQueue { + public function __debugInfo() { + return ['child' => 42, 'parent' => count(parent::__debugInfo())]; + } +} + +var_dump( + new MyFileInfo(__FILE__), + new MyDoublyLinkedList(), + new MyObjectStorage(), + new MyMultipleIterator(), + new MyArrayObject(), + new MyArrayIterator(), + new MyMaxHeap(), + new MyPriorityQueue(), +); +?> +--EXPECTF-- +object(MyFileInfo)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(2) +} +object(MyDoublyLinkedList)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(2) +} +object(MyObjectStorage)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(1) +} +object(MyMultipleIterator)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(1) +} +object(MyArrayObject)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(1) +} +object(MyArrayIterator)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(1) +} +object(MyMaxHeap)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(3) +} +object(MyPriorityQueue)#%d (2) { + ["child"]=> + int(42) + ["parent"]=> + int(3) +}