@@ -323,7 +323,7 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_
323
323
/* }}} */
324
324
325
325
static void _const_string (string * str , zstr name , zval * value , char * indent TSRMLS_DC );
326
- static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , char * indent TSRMLS_DC );
326
+ static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * closure , char * indent TSRMLS_DC );
327
327
static void _property_string (string * str , zend_property_info * prop , zstr prop_name , char * indent TSRMLS_DC );
328
328
static void _class_string (string * str , zend_class_entry * ce , zval * obj , char * indent TSRMLS_DC );
329
329
static void _extension_string (string * str , zend_module_entry * module , char * indent TSRMLS_DC );
@@ -489,7 +489,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
489
489
&& ((mptr -> common .fn_flags & ZEND_ACC_PRIVATE ) == 0 || mptr -> common .scope == ce ))
490
490
{
491
491
string_printf (str , "\n" );
492
- _function_string (str , mptr , ce , sub_indent .string TSRMLS_CC );
492
+ _function_string (str , mptr , ce , NULL , sub_indent .string TSRMLS_CC );
493
493
}
494
494
zend_hash_move_forward_ex (& ce -> function_table , & pos );
495
495
}
@@ -595,7 +595,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
595
595
}
596
596
597
597
string_printf (& dyn , "\n" );
598
- _function_string (& dyn , mptr , ce , sub_indent .string TSRMLS_CC );
598
+ _function_string (& dyn , mptr , ce , NULL , sub_indent .string TSRMLS_CC );
599
599
count ++ ;
600
600
_free_function (closure TSRMLS_CC );
601
601
}
@@ -767,7 +767,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
767
767
/* }}} */
768
768
769
769
/* {{{ _function_string */
770
- static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , char * indent TSRMLS_DC )
770
+ static void _function_string (string * str , zend_function * fptr , zend_class_entry * scope , zval * closure , char * indent TSRMLS_DC )
771
771
{
772
772
string param_indent ;
773
773
zend_function * overwrites ;
@@ -782,7 +782,8 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
782
782
string_printf (str , "%s%v\n" , indent , fptr -> op_array .doc_comment .v );
783
783
}
784
784
785
- string_printf (str , fptr -> common .scope ? "%sMethod [ " : "%sFunction [ " , indent );
785
+ string_write (str , indent , strlen (indent ));
786
+ string_printf (str , closure ? "Closure [ " : (fptr -> common .scope ? "Method [ " : "Function [ " ));
786
787
string_printf (str , (fptr -> type == ZEND_USER_FUNCTION ) ? "<user" : "<internal" );
787
788
if (fptr -> common .fn_flags & ZEND_ACC_DEPRECATED ) {
788
789
string_printf (str , ", deprecated" );
@@ -858,6 +859,28 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
858
859
}
859
860
string_init (& param_indent );
860
861
string_printf (& param_indent , "%s " , indent );
862
+ if (closure ) {
863
+ const zend_function * closure_fptr = zend_get_closure_method_def (closure TSRMLS_CC );
864
+ if (closure_fptr -> type == ZEND_USER_FUNCTION && closure_fptr -> op_array .static_variables ) {
865
+ HashTable * static_variables = closure_fptr -> op_array .static_variables ;
866
+ HashPosition pos ;
867
+ uint key_len ;
868
+ zstr key ;
869
+ ulong num_index , index = 0 ;
870
+ int count = zend_hash_num_elements (static_variables );
871
+ if (count ) {
872
+ string_printf (str , "\n" );
873
+ string_printf (str , "%s - Static Parameters [%d] {\n" , indent , count );
874
+ zend_hash_internal_pointer_reset_ex (static_variables , & pos );
875
+ while (index ++ < count ) {
876
+ zend_hash_get_current_key_ex (static_variables , & key , & key_len , & num_index , 0 , & pos );
877
+ string_printf (str , "%s Parameter #%d [ $%v ]\n" , indent , index ++ , key );
878
+ zend_hash_move_forward_ex (static_variables , & pos );
879
+ }
880
+ string_printf (str , "%s }\n" , indent );
881
+ }
882
+ }
883
+ }
861
884
_function_parameter_string (str , fptr , param_indent .string TSRMLS_CC );
862
885
string_free (& param_indent );
863
886
string_printf (str , "%s}\n" , indent );
@@ -1062,7 +1085,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
1062
1085
continue ;
1063
1086
}
1064
1087
1065
- _function_string (str , fptr , NULL , " " TSRMLS_CC );
1088
+ _function_string (str , fptr , NULL , NULL , " " TSRMLS_CC );
1066
1089
func ++ ;
1067
1090
}
1068
1091
string_printf (str , "%s }\n" , indent );
@@ -1465,6 +1488,7 @@ ZEND_METHOD(reflection_function, __construct)
1465
1488
{
1466
1489
zval * name ;
1467
1490
zval * object ;
1491
+ zval * closure = NULL ;
1468
1492
unsigned int lcname_len ;
1469
1493
zstr lcname ;
1470
1494
reflection_object * intern ;
@@ -1473,28 +1497,34 @@ ZEND_METHOD(reflection_function, __construct)
1473
1497
int name_len ;
1474
1498
zend_uchar type ;
1475
1499
1476
- if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "t" , & name_str , & name_len , & type ) == FAILURE ) {
1477
- return ;
1478
- }
1479
-
1480
1500
object = getThis ();
1481
1501
intern = (reflection_object * ) zend_object_store_get_object (object TSRMLS_CC );
1482
1502
if (intern == NULL ) {
1483
1503
return ;
1484
1504
}
1485
- lcname = zend_u_str_case_fold (type , name_str , name_len , 1 , & lcname_len );
1486
- if (zend_u_hash_find (EG (function_table ), type , lcname , lcname_len + 1 , (void * * )& fptr ) == FAILURE ) {
1505
+
1506
+ if (zend_parse_parameters_ex (ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS () TSRMLS_CC , "O" , & closure , zend_ce_closure ) == SUCCESS ) {
1507
+ fptr = zend_get_closure_invoke_method (closure TSRMLS_CC );
1508
+ Z_ADDREF_P (closure );
1509
+ } else if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "t" , & name_str , & name_len , & type ) == SUCCESS ) {
1510
+ lcname = zend_u_str_case_fold (type , name_str , name_len , 1 , & lcname_len );
1511
+ if (zend_u_hash_find (EG (function_table ), type , lcname , lcname_len + 1 , (void * * )& fptr ) == FAILURE ) {
1512
+ efree (lcname .v );
1513
+ zend_throw_exception_ex (reflection_exception_ptr , 0 TSRMLS_CC ,
1514
+ "Function %R() does not exist" , type , name_str );
1515
+ return ;
1516
+ }
1487
1517
efree (lcname .v );
1488
- zend_throw_exception_ex (reflection_exception_ptr , 0 TSRMLS_CC ,
1489
- "Function %R() does not exist" , type , name_str );
1518
+ } else {
1490
1519
return ;
1491
1520
}
1492
- efree ( lcname . v );
1521
+
1493
1522
MAKE_STD_ZVAL (name );
1494
1523
ZVAL_TEXT (name , fptr -> common .function_name , 1 );
1495
1524
zend_ascii_hash_update (Z_OBJPROP_P (object ), "name" , sizeof ("name" ), (void * * ) & name , sizeof (zval * ), NULL );
1496
1525
intern -> ptr = fptr ;
1497
1526
intern -> ref_type = REF_TYPE_FUNCTION ;
1527
+ intern -> obj = closure ;
1498
1528
intern -> ce = NULL ;
1499
1529
}
1500
1530
/* }}} */
@@ -1510,23 +1540,36 @@ ZEND_METHOD(reflection_function, __toString)
1510
1540
METHOD_NOTSTATIC_NUMPARAMS (reflection_function_abstract_ptr , 0 );
1511
1541
GET_REFLECTION_OBJECT_PTR (fptr );
1512
1542
string_init (& str );
1513
- _function_string (& str , fptr , intern -> ce , "" TSRMLS_CC );
1543
+ _function_string (& str , fptr , intern -> ce , intern -> obj , "" TSRMLS_CC );
1514
1544
RETURN_U_STRINGL (ZEND_U_CONVERTER (UG (output_encoding_conv )), str .string , str .len - 1 , ZSTR_AUTOFREE );
1515
1545
}
1516
1546
/* }}} */
1517
1547
1518
1548
/* {{{ proto public string ReflectionFunction::getName() U
1519
1549
Returns this function's name */
1520
- ZEND_METHOD (reflection , function_getName )
1550
+ ZEND_METHOD (reflection_function , getName )
1521
1551
{
1522
1552
METHOD_NOTSTATIC_NUMPARAMS (reflection_function_abstract_ptr , 0 );
1523
1553
_default_get_entry (getThis (), "name" , sizeof ("name" ), return_value TSRMLS_CC );
1524
1554
}
1525
1555
/* }}} */
1526
1556
1557
+ /* {{{ proto public bool ReflectionFunction::isClosure() U
1558
+ Returns whether this is a closure */
1559
+ ZEND_METHOD (reflection_function , isClosure )
1560
+ {
1561
+ reflection_object * intern ;
1562
+ zend_function * fptr ;
1563
+
1564
+ METHOD_NOTSTATIC_NUMPARAMS (reflection_function_abstract_ptr , 0 );
1565
+ GET_REFLECTION_OBJECT_PTR (fptr );
1566
+ RETURN_BOOL (intern -> obj );
1567
+ }
1568
+ /* }}} */
1569
+
1527
1570
/* {{{ proto public bool ReflectionFunction::isInternal() U
1528
1571
Returns whether this is an internal function */
1529
- ZEND_METHOD (reflection , function_isInternal )
1572
+ ZEND_METHOD (reflection_function , isInternal )
1530
1573
{
1531
1574
reflection_object * intern ;
1532
1575
zend_function * fptr ;
@@ -2468,7 +2511,7 @@ ZEND_METHOD(reflection_method, __toString)
2468
2511
METHOD_NOTSTATIC_NUMPARAMS (reflection_method_ptr , 0 );
2469
2512
GET_REFLECTION_OBJECT_PTR (mptr );
2470
2513
string_init (& str );
2471
- _function_string (& str , mptr , intern -> ce , "" TSRMLS_CC );
2514
+ _function_string (& str , mptr , intern -> ce , intern -> obj , "" TSRMLS_CC );
2472
2515
RETURN_U_STRINGL (ZEND_U_CONVERTER (UG (output_encoding_conv )), str .string , str .len - 1 , ZSTR_AUTOFREE );
2473
2516
}
2474
2517
/* }}} */
@@ -5013,6 +5056,7 @@ ZEND_END_ARG_INFO()
5013
5056
static const zend_function_entry reflection_function_abstract_functions [] = {
5014
5057
ZEND_ME (reflection , __clone , NULL , ZEND_ACC_PRIVATE |ZEND_ACC_FINAL )
5015
5058
PHP_ABSTRACT_ME (reflection_function , __toString , NULL )
5059
+ ZEND_ME (reflection_function , isClosure , NULL , 0 )
5016
5060
ZEND_ME (reflection_function , isInternal , NULL , 0 )
5017
5061
ZEND_ME (reflection_function , isUserDefined , NULL , 0 )
5018
5062
ZEND_ME (reflection_function , getName , NULL , 0 )
0 commit comments