diff options
Diffstat (limited to 'ext/reflection/php_reflection.c')
-rw-r--r-- | ext/reflection/php_reflection.c | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 0685541ad..ac0c325c7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_reflection.c,v 1.164.2.33.2.31 2006/10/18 16:35:15 johannes Exp $ */ +/* $Id: php_reflection.c,v 1.164.2.33.2.37 2007/04/12 18:39:46 johannes Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -179,7 +179,7 @@ static void string_free(string *str) /* Struct for properties */ typedef struct _property_reference { zend_class_entry *ce; - zend_property_info *prop; + zend_property_info prop; } property_reference; /* Struct for parameters */ @@ -271,7 +271,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR return retval; } -static zval * reflection_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC) +static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) { if (!object) { ALLOC_ZVAL(object); @@ -747,23 +747,27 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry string_printf(str, "static "); } - /* These are mutually exclusive */ - switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) { - case ZEND_ACC_PUBLIC: - string_printf(str, "public "); - break; - case ZEND_ACC_PRIVATE: - string_printf(str, "private "); - break; - case ZEND_ACC_PROTECTED: - string_printf(str, "protected "); - break; - default: - string_printf(str, "<visibility error> "); - break; + if (fptr->common.scope) { + /* These are mutually exclusive */ + switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) { + case ZEND_ACC_PUBLIC: + string_printf(str, "public "); + break; + case ZEND_ACC_PRIVATE: + string_printf(str, "private "); + break; + case ZEND_ACC_PROTECTED: + string_printf(str, "protected "); + break; + default: + string_printf(str, "<visibility error> "); + break; + } + string_printf(str, "method "); + } else { + string_printf(str, "function "); } - string_printf(str, fptr->common.scope ? "method " : "function "); if (fptr->op_array.return_reference) { string_printf(str, "&"); } @@ -1026,7 +1030,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR MAKE_STD_ZVAL(name); ZVAL_STRINGL(name, ce->name, ce->name_length, 1); - reflection_instanciate(reflection_class_ptr, object TSRMLS_CC); + 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; @@ -1052,7 +1056,7 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC) } free_alloca(lcname); - reflection_instanciate(reflection_extension_ptr, object TSRMLS_CC); + reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC); intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); MAKE_STD_ZVAL(name); ZVAL_STRINGL(name, module->name, name_len, 1); @@ -1076,7 +1080,7 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i } else { ZVAL_NULL(name); } - reflection_instanciate(reflection_parameter_ptr, object TSRMLS_CC); + reflection_instantiate(reflection_parameter_ptr, object TSRMLS_CC); intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); reference = (parameter_reference*) emalloc(sizeof(parameter_reference)); reference->arg_info = arg_info; @@ -1099,7 +1103,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS MAKE_STD_ZVAL(name); ZVAL_STRING(name, function->common.function_name, 1); - reflection_instanciate(reflection_function_ptr, object TSRMLS_CC); + 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; @@ -1119,7 +1123,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho MAKE_STD_ZVAL(classname); ZVAL_STRING(name, method->common.function_name, 1); ZVAL_STRINGL(classname, ce->name, ce->name_length, 1); - reflection_instanciate(reflection_method_ptr, object TSRMLS_CC); + 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; @@ -1142,14 +1146,19 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info if (!(prop->flags & ZEND_ACC_PRIVATE)) { /* we have to search the class hierarchy for this (implicit) public or protected property */ - zend_class_entry *tmp_ce = ce; - zend_property_info *tmp_info; - + zend_class_entry *tmp_ce = ce, *store_ce = ce; + zend_property_info *tmp_info = NULL; + while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, strlen(prop_name) + 1, (void **) &tmp_info) != SUCCESS) { ce = tmp_ce; - prop = tmp_info; tmp_ce = tmp_ce->parent; } + + if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */ + prop = tmp_info; + } else { /* not found, use initial value */ + ce = store_ce; + } } MAKE_STD_ZVAL(name); @@ -1157,11 +1166,11 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info ZVAL_STRING(name, prop_name, 1); ZVAL_STRINGL(classname, ce->name, ce->name_length, 1); - reflection_instanciate(reflection_property_ptr, object TSRMLS_CC); + reflection_instantiate(reflection_property_ptr, object TSRMLS_CC); intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); reference = (property_reference*) emalloc(sizeof(property_reference)); reference->ce = ce; - reference->prop = prop; + reference->prop = *prop; intern->ptr = reference; intern->free_ptr = 1; intern->ce = ce; @@ -1995,7 +2004,40 @@ ZEND_METHOD(reflection_parameter, getClass) GET_REFLECTION_OBJECT_PTR(param); if (param->arg_info->class_name) { - if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) { + /* Class name is stored as a string, we might also get "self" or "parent" + * - For "self", simply use the function scope. If scope is NULL then + * the function is global and thus self does not make any sense + * + * - For "parent", use the function scope's parent. If scope is NULL then + * the function is global and thus parent does not make any sense. + * If the parent is NULL then the class does not extend anything and + * thus parent does not make any sense, either. + * + * TODO: Think about moving these checks to the compiler or some sort of + * lint-mode. + */ + if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) { + zend_class_entry *ce= param->fptr->common.scope; + if (!ce) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Parameter uses 'self' as type hint but function is not a class member!"); + return; + } + pce= &ce; + } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) { + zend_class_entry *ce= param->fptr->common.scope; + if (!ce) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Parameter uses 'parent' as type hint but function is not a class member!"); + return; + } + if (!ce->parent) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, + "Parameter uses 'parent' as type hint although class does not have a parent!"); + return; + } + pce= &ce->parent; + } else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s does not exist", param->arg_info->class_name); return; @@ -3165,7 +3207,7 @@ static int _adddynproperty(zval **pptr, int num_args, va_list args, zend_hash_ke ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0); if (zend_get_property_info(ce, &member, 1 TSRMLS_CC) == &EG(std_property_info)) { - ALLOC_ZVAL(property); + MAKE_STD_ZVAL(property); reflection_property_factory(ce, &EG(std_property_info), property TSRMLS_CC); add_next_index_zval(retval, property); } @@ -3804,7 +3846,7 @@ ZEND_METHOD(reflection_property, __construct) reference = (property_reference*) emalloc(sizeof(property_reference)); reference->ce = ce; - reference->prop = property_info; + reference->prop = *property_info; intern->ptr = reference; intern->free_ptr = 1; intern->ce = ce; @@ -3822,7 +3864,7 @@ ZEND_METHOD(reflection_property, __toString) METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 0); GET_REFLECTION_OBJECT_PTR(ref); string_init(&str); - _property_string(&str, ref->prop, NULL, "" TSRMLS_CC); + _property_string(&str, &ref->prop, NULL, "" TSRMLS_CC); RETURN_STRINGL(str.string, str.len - 1, 0); } /* }}} */ @@ -3843,7 +3885,7 @@ static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 0); GET_REFLECTION_OBJECT_PTR(ref); - RETURN_BOOL(ref->prop->flags & mask); + RETURN_BOOL(ref->prop.flags & mask); } /* {{{ proto public bool ReflectionProperty::isPublic() @@ -3896,7 +3938,7 @@ ZEND_METHOD(reflection_property, getModifiers) METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 0); GET_REFLECTION_OBJECT_PTR(ref); - RETURN_LONG(ref->prop->flags); + RETURN_LONG(ref->prop.flags); } /* }}} */ @@ -3912,7 +3954,7 @@ ZEND_METHOD(reflection_property, getValue) METHOD_NOTSTATIC(reflection_property_ptr); GET_REFLECTION_OBJECT_PTR(ref); - if (!(ref->prop->flags & ZEND_ACC_PUBLIC)) { + if (!(ref->prop.flags & ZEND_ACC_PUBLIC)) { _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC); zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name)); @@ -3920,10 +3962,10 @@ ZEND_METHOD(reflection_property, getValue) return; } - if ((ref->prop->flags & ZEND_ACC_STATIC)) { + if ((ref->prop.flags & ZEND_ACC_STATIC)) { zend_update_class_constants(intern->ce TSRMLS_CC); - if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { - zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop->name); + if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) { + zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); /* Bails out */ } *return_value= **member; @@ -3933,7 +3975,7 @@ ZEND_METHOD(reflection_property, getValue) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { return; } - member_p = zend_read_property(Z_OBJCE_P(object), object, ref->prop->name, ref->prop->name_length, 1 TSRMLS_CC); + member_p = zend_read_property(Z_OBJCE_P(object), object, ref->prop.name, ref->prop.name_length, 1 TSRMLS_CC); *return_value= *member_p; zval_copy_ctor(return_value); INIT_PZVAL(return_value); @@ -3961,7 +4003,7 @@ ZEND_METHOD(reflection_property, setValue) METHOD_NOTSTATIC(reflection_property_ptr); GET_REFLECTION_OBJECT_PTR(ref); - if (!(ref->prop->flags & ZEND_ACC_PUBLIC)) { + if (!(ref->prop.flags & ZEND_ACC_PUBLIC)) { _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC); zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name)); @@ -3969,7 +4011,7 @@ ZEND_METHOD(reflection_property, setValue) return; } - if ((ref->prop->flags & ZEND_ACC_STATIC)) { + if ((ref->prop.flags & ZEND_ACC_STATIC)) { if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) { return; @@ -3978,8 +4020,8 @@ ZEND_METHOD(reflection_property, setValue) zend_update_class_constants(intern->ce TSRMLS_CC); prop_table = CE_STATIC_MEMBERS(intern->ce); - if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) { - zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop->name); + if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) { + zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); /* Bails out */ } if (*variable_ptr == value) { @@ -4002,13 +4044,13 @@ ZEND_METHOD(reflection_property, setValue) if (PZVAL_IS_REF(value)) { SEPARATE_ZVAL(&value); } - zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo); + zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo); } } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { return; } - zend_update_property(Z_OBJCE_P(object), object, ref->prop->name, ref->prop->name_length, value TSRMLS_CC); + zend_update_property(Z_OBJCE_P(object), object, ref->prop.name, ref->prop.name_length, value TSRMLS_CC); } } /* }}} */ @@ -4027,7 +4069,7 @@ ZEND_METHOD(reflection_property, getDeclaringClass) METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 0); GET_REFLECTION_OBJECT_PTR(ref); - if (zend_unmangle_property_name(ref->prop->name, ref->prop->name_length, &class_name, &prop_name) != SUCCESS) { + if (zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name) != SUCCESS) { RETURN_FALSE; } @@ -4055,8 +4097,8 @@ ZEND_METHOD(reflection_property, getDocComment) METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 0); GET_REFLECTION_OBJECT_PTR(ref); - if (ref->prop->doc_comment) { - RETURN_STRINGL(ref->prop->doc_comment, ref->prop->doc_comment_len, 1); + if (ref->prop.doc_comment) { + RETURN_STRINGL(ref->prop.doc_comment, ref->prop.doc_comment_len, 1); } RETURN_FALSE; } @@ -4851,7 +4893,7 @@ PHP_MINFO_FUNCTION(reflection) /* {{{ */ php_info_print_table_start(); php_info_print_table_header(2, "Reflection", "enabled"); - php_info_print_table_row(2, "Version", "$Id: php_reflection.c,v 1.164.2.33.2.31 2006/10/18 16:35:15 johannes Exp $"); + php_info_print_table_row(2, "Version", "$Id: php_reflection.c,v 1.164.2.33.2.37 2007/04/12 18:39:46 johannes Exp $"); php_info_print_table_end(); } /* }}} */ |