@@ -223,6 +223,18 @@ static void _default_get_entry(zval *object, char *name, int name_len, zval *ret
223223INIT_PZVAL (return_value );
224224}
225225
226+ static void _default_lookup_entry (zval * object , char * name , int name_len , zval * * return_value TSRMLS_DC ) /* {{{ */
227+ {
228+ zval * * value ;
229+
230+ if (zend_hash_find (Z_OBJPROP_P (object ), name , name_len , (void * * ) & value ) == FAILURE ) {
231+ * return_value = NULL ;
232+ } else {
233+ * return_value = * value ;
234+ }
235+ }
236+ /* }}} */
237+
226238static void reflection_register_implement (zend_class_entry * class_entry , zend_class_entry * interface_entry TSRMLS_DC )
227239{
228240zend_uint num_interfaces = ++ class_entry -> num_interfaces ;
@@ -319,7 +331,7 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_
319331}
320332
321333static void _const_string (string * str , char * name , zval * value , char * indent TSRMLS_DC );
322- static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * closure , char * indent TSRMLS_DC );
334+ static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * prop_name , zval * closure , char * indent TSRMLS_DC );
323335static void _property_string (string * str , zend_property_info * prop , char * prop_name , char * indent TSRMLS_DC );
324336static void _class_string (string * str , zend_class_entry * ce , zval * obj , char * indent TSRMLS_DC );
325337static void _extension_string (string * str , zend_module_entry * module , char * indent TSRMLS_DC );
@@ -485,7 +497,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
485497&& ((mptr -> common .fn_flags & ZEND_ACC_PRIVATE ) == 0 || mptr -> common .scope == ce ))
486498{
487499string_printf (str , "\n" );
488- _function_string (str , mptr , ce , NULL , sub_indent .string TSRMLS_CC );
500+ _function_string (str , mptr , ce , NULL , NULL , sub_indent .string TSRMLS_CC );
489501}
490502zend_hash_move_forward_ex (& ce -> function_table , & pos );
491503}
@@ -587,7 +599,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
587599closure = NULL ;
588600}
589601string_printf (& dyn , "\n" );
590- _function_string (& dyn , mptr , ce , NULL , sub_indent .string TSRMLS_CC );
602+ _function_string (& dyn , mptr , ce , NULL , NULL , sub_indent .string TSRMLS_CC );
591603count ++ ;
592604_free_function (closure TSRMLS_CC );
593605}
@@ -744,7 +756,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
744756/* }}} */
745757
746758/* {{{ _function_string */
747- static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * closure , char * indent TSRMLS_DC )
759+ static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * prop_name , zval * closure , char * indent TSRMLS_DC )
748760{
749761string param_indent ;
750762zend_function * overwrites ;
@@ -828,7 +840,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
828840if (fptr -> op_array .return_reference ) {
829841string_printf (str , "&" );
830842}
831- string_printf (str , "%s ] {\n" , fptr -> common .function_name );
843+ string_printf (str , "%s ] {\n" , closure && prop_name ? Z_STRVAL_P ( prop_name ) : fptr -> common .function_name );
832844/* The information where a function is declared is only available for user classes */
833845if (fptr -> type == ZEND_USER_FUNCTION ) {
834846string_printf (str , "%s @@ %s %d - %d\n" , indent ,
@@ -1060,7 +1072,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
10601072continue ;
10611073}
10621074
1063- _function_string (str , fptr , NULL , NULL , " " TSRMLS_CC );
1075+ _function_string (str , fptr , NULL , NULL , NULL , " " TSRMLS_CC );
10641076func ++ ;
10651077}
10661078string_printf (str , "%s }\n" , indent );
@@ -1473,7 +1485,7 @@ ZEND_METHOD(reflection_function, __construct)
14731485}
14741486
14751487if (zend_parse_parameters_ex (ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS () TSRMLS_CC , "O" , & closure , zend_ce_closure ) == SUCCESS ) {
1476- fptr = zend_get_closure_invoke_method (closure TSRMLS_CC );
1488+ fptr = ( zend_function * ) zend_get_closure_method_def (closure TSRMLS_CC );
14771489Z_ADDREF_P (closure );
14781490} else if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "s" , & name_str , & name_len ) == SUCCESS ) {
14791491lcname = zend_str_tolower_dup (name_str , name_len );
@@ -1505,11 +1517,13 @@ ZEND_METHOD(reflection_function, __toString)
15051517reflection_object * intern ;
15061518zend_function * fptr ;
15071519string str ;
1520+ zval * name ;
15081521
15091522METHOD_NOTSTATIC_NUMPARAMS (reflection_function_abstract_ptr , 0 );
15101523GET_REFLECTION_OBJECT_PTR (fptr );
1524+ _default_lookup_entry (getThis (), "name" , sizeof ("name" ), & name TSRMLS_CC );
15111525string_init (& str );
1512- _function_string (& str , fptr , intern -> ce , intern -> obj , "" TSRMLS_CC );
1526+ _function_string (& str , fptr , intern -> ce , name , intern -> obj , "" TSRMLS_CC );
15131527RETURN_STRINGL (str .string , str .len - 1 , 0 );
15141528}
15151529/* }}} */
@@ -2418,15 +2432,45 @@ ZEND_METHOD(reflection_method, __construct)
24182432{
24192433/* do nothing, mptr already set */
24202434} else if (zend_hash_find (& ce -> function_table , lcname , name_len + 1 , (void * * ) & mptr ) == FAILURE ) {
2421- efree (lcname );
2422- zend_throw_exception_ex (reflection_exception_ptr , 0 TSRMLS_CC ,
2423- "Method %s::%s() does not exist" , ce -> name , name_str );
2424- return ;
2435+ /* Check if this is a property storing a closure */
2436+ mptr = NULL ; /* Set by closure detection again */
2437+ if (orig_obj ) {
2438+ zval * * callable , member ;
2439+ zend_property_info * property_info ;
2440+ zend_object * zobj = zend_objects_get_address (orig_obj TSRMLS_CC );
2441+
2442+ ZVAL_STRINGL (& member , name_str , name_len , 0 );
2443+ property_info = zend_get_property_info (ce , & member , 1 TSRMLS_CC );
2444+
2445+ if (property_info && zend_hash_quick_find (zobj -> properties , property_info -> name , property_info -> name_length + 1 , property_info -> h , (void * * ) & callable ) == SUCCESS ) {
2446+ zval * callable_obj ;
2447+ zend_class_entry * ce_ptr ;
2448+ zend_function * fbc ;
2449+
2450+ if (Z_TYPE_PP (callable ) == IS_OBJECT
2451+ && Z_OBJ_HANDLER_PP (callable , get_closure )
2452+ && Z_OBJ_HANDLER_PP (callable , get_closure )(* callable , & ce_ptr , & fbc , & callable_obj TSRMLS_CC ) == SUCCESS ) {
2453+ mptr = fbc ;
2454+ Z_ADDREF_PP (callable );
2455+ intern -> obj = * callable ;
2456+ }
2457+ }
2458+ }
2459+ if (!mptr ) {
2460+ efree (lcname );
2461+ zend_throw_exception_ex (reflection_exception_ptr , 0 TSRMLS_CC ,
2462+ "Method %s::%s() does not exist" , ce -> name , name_str );
2463+ return ;
2464+ }
24252465}
24262466efree (lcname );
24272467
24282468MAKE_STD_ZVAL (name );
2429- ZVAL_STRING (name , mptr -> common .function_name , 1 );
2469+ if (intern -> obj ) {
2470+ ZVAL_STRINGL (name , name_str , name_len , 1 );
2471+ } else {
2472+ ZVAL_STRING (name , mptr -> common .function_name , 1 );
2473+ }
24302474zend_hash_update (Z_OBJPROP_P (object ), "name" , sizeof ("name" ), (void * * ) & name , sizeof (zval * ), NULL );
24312475intern -> ptr = mptr ;
24322476intern -> ref_type = REF_TYPE_FUNCTION ;
@@ -2441,11 +2485,13 @@ ZEND_METHOD(reflection_method, __toString)
24412485reflection_object * intern ;
24422486zend_function * mptr ;
24432487string str ;
2488+ zval * name ;
24442489
24452490METHOD_NOTSTATIC_NUMPARAMS (reflection_method_ptr , 0 );
24462491GET_REFLECTION_OBJECT_PTR (mptr );
2492+ _default_lookup_entry (getThis (), "name" , sizeof ("name" ), & name TSRMLS_CC );
24472493string_init (& str );
2448- _function_string (& str , mptr , intern -> ce , intern -> obj , "" TSRMLS_CC );
2494+ _function_string (& str , mptr , intern -> ce , name , intern -> obj , "" TSRMLS_CC );
24492495RETURN_STRINGL (str .string , str .len - 1 , 0 );
24502496}
24512497/* }}} */
0 commit comments