diff options
Diffstat (limited to 'ext/reflection')
-rw-r--r-- | ext/reflection/php_reflection.c | 47 | ||||
-rw-r--r-- | ext/reflection/tests/ReflectionMethod_basic2.phpt | 8 | ||||
-rw-r--r-- | ext/reflection/tests/bug42976.phpt | 4 | ||||
-rw-r--r-- | ext/reflection/tests/bug51905.phpt | 28 | ||||
-rw-r--r-- | ext/reflection/tests/bug51911.phpt | 22 | ||||
-rw-r--r-- | ext/reflection/tests/bug52057.phpt | 54 |
6 files changed, 139 insertions, 24 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index ae77dd2d3..a1363a943 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_reflection.c 293036 2010-01-03 09:23:27Z sebastian $ */ +/* $Id: php_reflection.c 300393 2010-06-11 23:37:55Z felipe $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -79,7 +79,7 @@ ZEND_DECLARE_MODULE_GLOBALS(reflection) #define METHOD_NOTSTATIC(ce) \ if (!this_ptr || !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) { \ - zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \ return; \ } \ @@ -97,7 +97,7 @@ ZEND_DECLARE_MODULE_GLOBALS(reflection) intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC); \ if (intern == NULL || intern->ptr == NULL) { \ RETURN_ON_EXCEPTION \ - zend_error(E_ERROR, "Internal error: Failed to retrieve the reflection object"); \ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the reflection object"); \ } \ target = intern->ptr; \ @@ -1079,7 +1079,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde /* Is there a better way of doing this? */ while (func->fname) { if (zend_hash_find(EG(function_table), func->fname, strlen(func->fname) + 1, (void**) &fptr) == FAILURE) { - zend_error(E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname); func++; continue; } @@ -1427,7 +1427,7 @@ ZEND_METHOD(reflection, export) } if (!retval_ptr) { - zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name); RETURN_FALSE; } @@ -2408,7 +2408,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) *return_value = precv->op2.u.constant; INIT_PZVAL(return_value); - if (Z_TYPE_P(return_value) != IS_CONSTANT) { + if (Z_TYPE_P(return_value) != IS_CONSTANT && Z_TYPE_P(return_value) != IS_CONSTANT_ARRAY) { zval_copy_ctor(return_value); } zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC); @@ -3002,7 +3002,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob return; } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &argument) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &argument) == FAILURE) { return; } } @@ -3384,7 +3384,9 @@ ZEND_METHOD(reflection_class, hasMethod) GET_REFLECTION_OBJECT_PTR(ce); lc_name = zend_str_tolower_dup(name, name_len); - if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) { + if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) + && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) + || zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) { efree(lc_name); RETURN_TRUE; } else { @@ -3401,6 +3403,7 @@ ZEND_METHOD(reflection_class, getMethod) reflection_object *intern; zend_class_entry *ce; zend_function *mptr; + zval obj_tmp; char *name, *lc_name; int name_len; @@ -3419,6 +3422,14 @@ ZEND_METHOD(reflection_class, getMethod) method and not the closure definition itself */ reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC); efree(lc_name); + } else 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 + && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(&obj_tmp TSRMLS_CC)) != NULL) { + /* don't assign closure_object since we only reflect the invoke handler + method and not the closure definition itself */ + reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC); + zval_dtor(&obj_tmp); + efree(lc_name); } else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) { reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC); efree(lc_name); @@ -3895,7 +3906,7 @@ ZEND_METHOD(reflection_class, newInstance) if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } - zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invocation of %s's constructor failed", ce->name); RETURN_NULL(); } if (retval_ptr) { @@ -3975,7 +3986,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs) if (retval_ptr) { zval_ptr_dtor(&retval_ptr); } - zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invocation of %s's constructor failed", ce->name); RETURN_NULL(); } if (retval_ptr) { @@ -4090,7 +4101,7 @@ ZEND_METHOD(reflection_class, isSubclassOf) if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr TSRMLS_CC)) { argument = (reflection_object *) zend_object_store_get_object(class_name TSRMLS_CC); if (argument == NULL || argument->ptr == NULL) { - zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object"); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object"); /* Bails out */ } class_ce = argument->ptr; @@ -4135,7 +4146,7 @@ ZEND_METHOD(reflection_class, implementsInterface) if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) { argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC); if (argument == NULL || argument->ptr == NULL) { - zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object"); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object"); /* Bails out */ } interface_ce = argument->ptr; @@ -4520,7 +4531,7 @@ ZEND_METHOD(reflection_property, getValue) 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); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); /* Bails out */ } MAKE_COPY_ZVAL(member, return_value); @@ -4575,7 +4586,7 @@ ZEND_METHOD(reflection_property, setValue) 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); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); /* Bails out */ } if (*variable_ptr == value) { @@ -4809,7 +4820,7 @@ ZEND_METHOD(reflection_extension, getFunctions) /* Is there a better way of doing this? */ while (func->fname) { if (zend_hash_find(EG(function_table), func->fname, strlen(func->fname) + 1, (void**) &fptr) == FAILURE) { - zend_error(E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname); func++; continue; } @@ -5285,7 +5296,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2) ZEND_ARG_INFO(0, return) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2) ZEND_ARG_INFO(0, class) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() @@ -5494,7 +5505,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", "$Revision: 293036 $"); + php_info_print_table_row(2, "Version", "$Revision: 300393 $"); php_info_print_table_end(); } /* }}} */ @@ -5508,7 +5519,7 @@ zend_module_entry reflection_module_entry = { /* {{{ */ NULL, NULL, PHP_MINFO(reflection), - "$Revision: 293036 $", + "$Revision: 300393 $", STANDARD_MODULE_PROPERTIES }; /* }}} */ diff --git a/ext/reflection/tests/ReflectionMethod_basic2.phpt b/ext/reflection/tests/ReflectionMethod_basic2.phpt index e2c23c1c1..c91af6770 100644 --- a/ext/reflection/tests/ReflectionMethod_basic2.phpt +++ b/ext/reflection/tests/ReflectionMethod_basic2.phpt @@ -153,8 +153,8 @@ __toString(): string(%d) "Method [ <internal:Reflection, ctor> public method __construct ] { - Parameters [2] { - Parameter #0 [ <optional> $class ] - Parameter #1 [ <optional> $name ] + Parameter #0 [ <required> $class ] + Parameter #1 [ <required> $name ] } } " @@ -163,8 +163,8 @@ export(): string(%d) "Method [ <internal:Reflection, ctor> public method __construct ] { - Parameters [2] { - Parameter #0 [ <optional> $class ] - Parameter #1 [ <optional> $name ] + Parameter #0 [ <required> $class ] + Parameter #1 [ <required> $name ] } } " diff --git a/ext/reflection/tests/bug42976.phpt b/ext/reflection/tests/bug42976.phpt index 3669d957d..2e4ade284 100644 --- a/ext/reflection/tests/bug42976.phpt +++ b/ext/reflection/tests/bug42976.phpt @@ -28,11 +28,11 @@ string(9) "x.changed" Warning: Parameter 1 to C::__construct() expected to be a reference, value given in %sbug42976.php on line 15 -Warning: Invocation of C's constructor failed in %sbug42976.php on line 15 +Warning: ReflectionClass::newInstance(): Invocation of C's constructor failed in %sbug42976.php on line 15 string(10) "x.original" Warning: Parameter 1 to C::__construct() expected to be a reference, value given in %sbug42976.php on line 18 -Warning: Invocation of C's constructor failed in %sbug42976.php on line 18 +Warning: ReflectionClass::newInstanceArgs(): Invocation of C's constructor failed in %sbug42976.php on line 18 string(10) "x.original" Done diff --git a/ext/reflection/tests/bug51905.phpt b/ext/reflection/tests/bug51905.phpt new file mode 100644 index 000000000..8969924e4 --- /dev/null +++ b/ext/reflection/tests/bug51905.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #51905 (ReflectionParameter fails if default value is an array with an access to self::) +--FILE-- +<?php + +class Bar { + const Y = 20; +} + +class Foo extends Bar { + const X = 12; + public function x($x = 1, $y = array(self::X), $z = parent::Y) {} +} + +$clazz = new ReflectionClass('Foo'); +$method = $clazz->getMethod('x'); +foreach ($method->getParameters() as $param) { + if ( $param->isDefaultValueAvailable()) + echo '$', $param->getName(), ' : ', var_export($param->getDefaultValue(), 1), "\n"; +} + +?> +--EXPECT-- +$x : 1 +$y : array ( + 0 => 12, +) +$z : 20 diff --git a/ext/reflection/tests/bug51911.phpt b/ext/reflection/tests/bug51911.phpt new file mode 100644 index 000000000..12eb459fb --- /dev/null +++ b/ext/reflection/tests/bug51911.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #51911 (ReflectionParameter::getDefaultValue() memory leaks with constant array) +--FILE-- +<?php + +class Foo { + const X = 1; + public function x($x = array(1)) {} +} + +$clazz = new ReflectionClass('Foo'); +$method = $clazz->getMethod('x'); +foreach ($method->getParameters() as $param) { + if ( $param->isDefaultValueAvailable()) + echo '$', $param->getName(), ' : ', var_export($param->getDefaultValue(), 1), "\n"; +} + +?> +--EXPECT-- +$x : array ( + 0 => 1, +) diff --git a/ext/reflection/tests/bug52057.phpt b/ext/reflection/tests/bug52057.phpt new file mode 100644 index 000000000..b80703571 --- /dev/null +++ b/ext/reflection/tests/bug52057.phpt @@ -0,0 +1,54 @@ +--TEST-- +Bug #52057 (ReflectionClass fails on Closure class) +--FILE-- +<?php + +$closure = function($a) { echo $a; }; + +$reflection = new ReflectionClass('closure'); +var_dump($reflection->hasMethod('__invoke')); // true + +$reflection = new ReflectionClass($closure); +var_dump($reflection->hasMethod('__invoke')); // true + +$reflection = new ReflectionObject($closure); +var_dump($reflection->hasMethod('__invoke')); // true + +$reflection = new ReflectionClass('closure'); +var_dump($h = $reflection->getMethod('__invoke')); // true +var_dump($h->class.'::'.$h->getName()); + +$reflection = new ReflectionClass($closure); +var_dump($h = $reflection->getMethod('__invoke')); // true +var_dump($h->class.'::'.$h->getName()); + +$reflection = new ReflectionObject($closure); +var_dump($h = $reflection->getMethod('__invoke')); // true +var_dump($h->class.'::'.$h->getName()); + +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +object(ReflectionMethod)#%d (2) { + ["name"]=> + string(8) "__invoke" + ["class"]=> + string(7) "Closure" +} +string(17) "Closure::__invoke" +object(ReflectionMethod)#%d (2) { + ["name"]=> + string(8) "__invoke" + ["class"]=> + string(7) "Closure" +} +string(17) "Closure::__invoke" +object(ReflectionMethod)#%d (2) { + ["name"]=> + string(8) "__invoke" + ["class"]=> + string(7) "Closure" +} +string(17) "Closure::__invoke" |