@ -192,11 +192,18 @@ typedef struct _parameter_reference {
zend_function * fptr ;
} parameter_reference ;
typedef enum {
REF_TYPE_OTHER , /* Must be 0 */
REF_TYPE_FUNCTION ,
REF_TYPE_PARAMETER ,
REF_TYPE_PROPERTY ,
} reflection_type_t ;
/* Struct for reflection objects */
typedef struct {
zend_object zo ;
void * ptr ;
unsigned int free_ptr : 1 ;
reflection_type_t ref_type ;
zval * obj ;
zend_class_entry * ce ;
} reflection_object ;
@ -224,33 +231,45 @@ static void reflection_register_implement(zend_class_entry *class_entry, zend_cl
class_entry - > interfaces [ num_interfaces - 1 ] = interface_entry ;
}
static void reflection_free_objects_storage ( void * object TSRMLS_DC )
static void _free_function ( zend_function * fptr TSRMLS_DC ) /* { { { */
{
reflection_object * intern = ( reflection_object * ) object ;
if ( intern - > free_ptr & & intern - > ptr ) {
efree ( intern - > ptr ) ;
intern - > ptr = NULL ;
}
if ( intern - > obj ) {
zval_ptr_dtor ( & intern - > obj ) ;
if ( fptr
& & fptr - > type = = ZEND_INTERNAL_FUNCTION
& & ( fptr - > internal_function . fn_flags & ZEND_ACC_CALL_VIA_HANDLER ) ! = 0
) {
efree ( fptr - > internal_function . function_name ) ;
efree ( fptr ) ;
}
zend_objects_free_object_storage ( object TSRMLS_CC ) ;
}
/* }}} */
static void reflection_objects_clone ( void * object , void * * object_clone TSRMLS_DC )
static void reflection_free_objects_storage ( void * object TSRMLS_DC )
{
reflection_object * intern = ( reflection_object * ) object ;
reflection_object * * intern_clone = ( reflection_object * * ) object_clon e;
parameter_reference * referenc e;
* intern_clone = emalloc ( sizeof ( reflection_object ) ) ;
zend_object_std_init ( & ( * intern_clone ) - > zo , intern - > zo . ce TSRMLS_CC ) ;
( * intern_clone ) - > ptr = intern - > ptr ;
( * intern_clone ) - > free_ptr = intern - > free_ptr ;
( * intern_clone ) - > obj = intern - > obj ;
if ( intern - > ptr ) {
switch ( intern - > ref_type ) {
case REF_TYPE_PARAMETER :
reference = ( parameter_reference * ) intern - > ptr ;
_free_function ( reference - > fptr TSRMLS_CC ) ;
efree ( intern - > ptr ) ;
break ;
case REF_TYPE_FUNCTION :
_free_function ( intern - > ptr TSRMLS_CC ) ;
break ;
case REF_TYPE_PROPERTY :
efree ( intern - > ptr ) ;
break ;
case REF_TYPE_OTHER :
break ;
}
}
intern - > ptr = NULL ;
if ( intern - > obj ) {
zval_add_ref ( & intern - > obj ) ;
zval_ptr_dtor ( & intern - > obj ) ;
}
zend_objects_free_object_storage ( object TSRMLS_CC ) ;
}
static zend_object_value reflection_objects_new ( zend_class_entry * class_type TSRMLS_DC )
@ -259,16 +278,12 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
zend_object_value retval ;
reflection_object * intern ;
intern = emalloc ( sizeof ( reflection_object ) ) ;
intern = ecalloc ( 1 , sizeof ( reflection_object ) ) ;
intern - > zo . ce = class_type ;
intern - > zo . guards = NULL ;
intern - > ptr = NULL ;
intern - > obj = NULL ;
intern - > free_ptr = 0 ;
zend_object_std_init ( & intern - > zo , class_type TSRMLS_CC ) ;
zend_hash_copy ( intern - > zo . properties , & class_type - > default_properties , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp , sizeof ( zval * ) ) ;
retval . handle = zend_objects_store_put ( intern , NULL , reflection_free_objects_storage , reflection_objects_clone TSRMLS_CC ) ;
retval . handle = zend_objects_store_put ( intern , NULL , reflection_free_objects_storage , NULL TSRMLS_CC ) ;
retval . handlers = & reflection_object_handlers ;
return retval ;
}
@ -536,9 +551,20 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
zend_hash_get_current_key_ex ( & ce - > function_table , & key , & key_len , & num_index , 0 , & pos ) ! = HASH_KEY_IS_STRING | |
zend_binary_strcasecmp ( key , key_len - 1 , mptr - > common . function_name , len ) = = 0 ) {
zend_function * closure ;
/* see if this is a closure */
if ( ce = = zend_ce_closure & & obj & & ( len = = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) & &
memcmp ( mptr - > common . function_name , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) = = 0 & &
( closure = zend_get_closure_invoke_method ( obj TSRMLS_CC ) ) ! = NULL
) {
mptr = closure ;
} else {
closure = NULL ;
}
string_printf ( & dyn , " \n " ) ;
_function_string ( & dyn , mptr , ce , sub_indent . string TSRMLS_CC ) ;
count + + ;
_free_function ( closure TSRMLS_CC ) ;
}
}
zend_hash_move_forward_ex ( & ce - > function_table , & pos ) ;
@ -1039,7 +1065,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR
reflection_instantiate ( reflection_class_ptr , object TSRMLS_CC ) ;
intern = ( reflection_object * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
intern - > ptr = ce ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_OTHER ;
intern - > ce = ce ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
}
@ -1068,7 +1094,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
MAKE_STD_ZVAL ( name ) ;
ZVAL_STRINGL ( name , module - > name , name_len , 1 ) ;
intern - > ptr = module ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_OTHER ;
intern - > ce = NULL ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
}
@ -1095,7 +1121,7 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
reference - > required = required ;
reference - > fptr = fptr ;
intern - > ptr = reference ;
intern - > free_ptr = 1 ;
intern - > ref_type = REF_TYPE_PARAMETER ;
intern - > ce = fptr - > common . scope ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
}
@ -1113,7 +1139,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS
reflection_instantiate ( reflection_function_ptr , object TSRMLS_CC ) ;
intern = ( reflection_object * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
intern - > ptr = function ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_FUNCTION ;
intern - > ce = NULL ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
}
@ -1133,7 +1159,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
reflection_instantiate ( reflection_method_ptr , object TSRMLS_CC ) ;
intern = ( reflection_object * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
intern - > ptr = method ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_FUNCTION ;
intern - > ce = ce ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " class " , sizeof ( " class " ) , ( void * * ) & classname , sizeof ( zval * ) , NULL ) ;
@ -1180,7 +1206,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
reference - > prop = * prop ;
reference - > ignore_visibility = 0 ;
intern - > ptr = reference ;
intern - > free_ptr = 1 ;
intern - > ref_type = REF_TYPE_PROPERTY ;
intern - > ce = ce ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " class " , sizeof ( " class " ) , ( void * * ) & classname , sizeof ( zval * ) , NULL ) ;
@ -1411,7 +1437,7 @@ ZEND_METHOD(reflection_function, __construct)
ZVAL_STRING ( name , fptr - > common . function_name , 1 ) ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
intern - > ptr = fptr ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_FUNCTION ;
intern - > ce = NULL ;
}
/* }}} */
@ -1890,18 +1916,37 @@ ZEND_METHOD(reflection_parameter, __construct)
convert_to_string_ex ( method ) ;
lcname_len = Z_STRLEN_PP ( method ) ;
lcname = zend_str_tolower_dup ( Z_STRVAL_PP ( method ) , lcname_len ) ;
if ( zend_hash_find ( & ce - > function_table , lcname , lcname_len + 1 , ( void * * ) & fptr ) = = FAILURE ) {
if ( ce = = zend_ce_closure & & Z_TYPE_PP ( classref ) = = IS_OBJECT & &
( lcname_len = = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) & &
memcmp ( lcname , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) = = 0 & &
( fptr = zend_get_closure_invoke_method ( * classref TSRMLS_CC ) ) ! = NULL
) {
/* nothign to do */
} else if ( zend_hash_find ( & ce - > function_table , lcname , lcname_len + 1 , ( void * * ) & fptr ) = = FAILURE ) {
efree ( lcname ) ;
zend_throw_exception_ex ( reflection_exception_ptr , 0 TSRMLS_CC ,
" Method %s::%s() does not exist " , Z_STRVAL_PP ( classref ) , Z_TYPE_PP ( method ) , Z_STRVAL_PP ( method ) ) ;
" Method %s::%s() does not exist " , ce - > name , Z_STRVAL_PP ( method ) ) ;
return ;
}
efree ( lcname ) ;
}
break ;
case IS_OBJECT : {
ce = Z_OBJCE_P ( reference ) ;
if ( instanceof_function ( ce , zend_ce_closure TSRMLS_CC ) ) {
fptr = zend_get_closure_invoke_method ( reference TSRMLS_CC ) ;
} else if ( zend_hash_find ( & ce - > function_table , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) , ( void * * ) & fptr ) = = FAILURE ) {
zend_throw_exception_ex ( reflection_exception_ptr , 0 TSRMLS_CC ,
" Method %s::%s() does not exist " , ce - > name , ZEND_INVOKE_FUNC_NAME ) ;
return ;
}
}
break ;
default :
_DO_THROW ( " The parameter class is expected to be either a string or an array(class, method) " ) ;
_DO_THROW ( " The parameter class is expected to be either a string, an array(class, method) or a callable object " ) ;
/* returns out of this function */
}
@ -1943,8 +1988,9 @@ ZEND_METHOD(reflection_parameter, __construct)
ref - > offset = ( zend_uint ) position ;
ref - > required = fptr - > common . required_num_args ;
ref - > fptr = fptr ;
/ / TODO : copy fptr
intern - > ptr = ref ;
intern - > free_ptr = 1 ;
intern - > ref_type = REF_TYPE_PARAMETER ;
intern - > ce = ce ;
}
/* }}} */
@ -2207,7 +2253,7 @@ ZEND_METHOD(reflection_method, export)
ZEND_METHOD ( reflection_method , __construct )
{
zval * name , * classname ;
zval * object ;
zval * object , * orig_obj ;
reflection_object * intern ;
char * lcname ;
zend_class_entry * * pce ;
@ -2217,7 +2263,11 @@ ZEND_METHOD(reflection_method, __construct)
int name_len , tmp_len ;
zval ztmp ;
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " zs " , & classname , & name_str , & name_len ) = = FAILURE ) {
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " o " , & classname ) = = SUCCESS ) {
name_str = ZEND_INVOKE_FUNC_NAME ;
name_len = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ;
orig_obj = classname ;
} else if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " zs " , & classname , & name_str , & name_len ) = = FAILURE ) {
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & name_str , & name_len ) = = FAILURE ) {
return ;
}
@ -2230,6 +2280,11 @@ ZEND_METHOD(reflection_method, __construct)
ZVAL_STRINGL ( classname , name_str , tmp_len , 1 ) ;
name_len = name_len - ( tmp_len + 2 ) ;
name_str = tmp + 2 ;
orig_obj = NULL ;
} else if ( Z_TYPE_P ( classname ) = = IS_OBJECT ) {
orig_obj = classname ;
} else {
orig_obj = NULL ;
}
object = getThis ( ) ;
@ -2275,7 +2330,12 @@ ZEND_METHOD(reflection_method, __construct)
lcname = zend_str_tolower_dup ( name_str , name_len ) ;
if ( zend_hash_find ( & ce - > function_table , lcname , name_len + 1 , ( void * * ) & mptr ) = = FAILURE ) {
if ( ce = = zend_ce_closure & & orig_obj & & ( name_len = = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) & &
memcmp ( lcname , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) = = 0 & &
( mptr = zend_get_closure_invoke_method ( orig_obj TSRMLS_CC ) ) ! = NULL
) {
/* do nothing, mptr already set */
} else if ( zend_hash_find ( & ce - > function_table , lcname , name_len + 1 , ( void * * ) & mptr ) = = FAILURE ) {
efree ( lcname ) ;
zend_throw_exception_ex ( reflection_exception_ptr , 0 TSRMLS_CC ,
" Method %s::%s() does not exist " , ce - > name , name_str ) ;
@ -2287,7 +2347,7 @@ ZEND_METHOD(reflection_method, __construct)
ZVAL_STRING ( name , mptr - > common . function_name , 1 ) ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
intern - > ptr = mptr ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_FUNCTION ;
intern - > ce = ce ;
}
/* }}} */
@ -2792,7 +2852,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
intern - > ptr = * ce ;
}
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_OTHER ;
}
/* }}} */
@ -3139,7 +3199,13 @@ ZEND_METHOD(reflection_class, getMethod)
GET_REFLECTION_OBJECT_PTR ( ce ) ;
lc_name = zend_str_tolower_dup ( name , name_len ) ;
if ( zend_hash_find ( & ce - > function_table , lc_name , name_len + 1 , ( void * * ) & mptr ) = = SUCCESS ) {
if ( ce = = zend_ce_closure & & intern - > obj & & ( name_len = = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) & &
memcmp ( lc_name , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) = = 0 & &
( mptr = zend_get_closure_invoke_method ( intern - > obj TSRMLS_CC ) ) ! = NULL
) {
reflection_method_factory ( ce , mptr , return_value TSRMLS_CC ) ;
efree ( lc_name ) ;
} else if ( zend_hash_find ( & ce - > function_table , lc_name , name_len + 1 , ( void * * ) & mptr ) = = SUCCESS ) {
reflection_method_factory ( ce , mptr , return_value TSRMLS_CC ) ;
efree ( lc_name ) ;
} else {
@ -3152,19 +3218,36 @@ ZEND_METHOD(reflection_class, getMethod)
/* }}} */
/* {{{ _addmethod */
static int _addmethod ( zend_function * mptr TSRMLS_DC , int num_args , va_list args , zend_hash_key * hash_key )
static void _addmethod ( zend_function * mptr , zend_class_entry * ce , zval * retval , long filter , zval * obj TSRMLS_DC )
{
zval * method ;
zend_class_entry * ce = * va_arg ( args , zend_class_entry * * ) ;
zval * retval = va_arg ( args , zval * ) ;
long filter = va_arg ( args , long ) ;
uint len = strlen ( mptr - > common . function_name ) ;
zend_function * closure ;
if ( mptr - > common . fn_flags & filter ) {
ALLOC_ZVAL ( method ) ;
if ( ce = = zend_ce_closure & & obj & & ( len = = sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) & &
memcmp ( mptr - > common . function_name , ZEND_INVOKE_FUNC_NAME , sizeof ( ZEND_INVOKE_FUNC_NAME ) - 1 ) = = 0 & &
( closure = zend_get_closure_invoke_method ( obj TSRMLS_CC ) ) ! = NULL
) {
mptr = closure ;
}
reflection_method_factory ( ce , mptr , method TSRMLS_CC ) ;
add_next_index_zval ( retval , method ) ;
}
return 0 ;
}
/* }}} */
/* {{{ _addmethod */
static int _addmethod_va ( zend_function * mptr TSRMLS_DC , int num_args , va_list args , zend_hash_key * hash_key )
{
zend_class_entry * ce = * va_arg ( args , zend_class_entry * * ) ;
zval * retval = va_arg ( args , zval * ) ;
long filter = va_arg ( args , long ) ;
zval * obj = va_arg ( args , zval * ) ;
_addmethod ( mptr , ce , retval , filter , obj TSRMLS_CC ) ;
return ZEND_HASH_APPLY_KEEP ;
}
/* }}} */
@ -3190,7 +3273,14 @@ ZEND_METHOD(reflection_class, getMethods)
GET_REFLECTION_OBJECT_PTR ( ce ) ;
array_init ( return_value ) ;
zend_hash_apply_with_arguments ( & ce - > function_table TSRMLS_CC , ( apply_func_args_t ) _addmethod , 3 , & ce , return_value , filter ) ;
zend_hash_apply_with_arguments ( & ce - > function_table TSRMLS_CC , ( apply_func_args_t ) _addmethod_va , 4 , & ce , return_value , filter , intern - > obj ) ;
if ( intern - > obj & & instanceof_function ( ce , zend_ce_closure ) ) {
zend_function * closure = zend_get_closure_invoke_method ( intern - > obj TSRMLS_CC ) ;
if ( closure ) {
_addmethod ( closure , ce , return_value , filter , intern - > obj TSRMLS_CC ) ;
_free_function ( closure TSRMLS_CC ) ;
}
}
}
/* }}} */
@ -4027,7 +4117,7 @@ ZEND_METHOD(reflection_property, __construct)
reference - > prop = * property_info ;
reference - > ignore_visibility = 0 ;
intern - > ptr = reference ;
intern - > free_ptr = 1 ;
intern - > ref_type = REF_TYPE_PROPERTY ;
intern - > ce = ce ;
}
/* }}} */
@ -4347,7 +4437,7 @@ ZEND_METHOD(reflection_extension, __construct)
ZVAL_STRING ( name , module - > name , 1 ) ;
zend_hash_update ( Z_OBJPROP_P ( object ) , " name " , sizeof ( " name " ) , ( void * * ) & name , sizeof ( zval * ) , NULL ) ;
intern - > ptr = module ;
intern - > free_ptr = 0 ;
intern - > ref_type = REF_TYPE_OTHER ;
intern - > ce = NULL ;
}
/* }}} */