From: Marcus Boerger Date: Tue, 24 Jan 2006 20:19:49 +0000 (+0000) Subject: - Implemented #36141 Add ReflectionClass::newInstanceArgs($args) X-Git-Tag: RELEASE_1_2~373 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0e42375ded43a86794f060d17bcbd722326c9bfe;p=php - Implemented #36141 Add ReflectionClass::newInstanceArgs($args) --- diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 1e81bdf45d..c8379393c1 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -3193,8 +3193,6 @@ ZEND_METHOD(reflection_class, newInstance) METHOD_NOTSTATIC(reflection_class_ptr); GET_REFLECTION_OBJECT_PTR(ce); - object_init_ex(return_value, ce); - /* Run the constructor if there is one */ if (ce->constructor) { zval ***params; @@ -3212,6 +3210,8 @@ ZEND_METHOD(reflection_class, newInstance) RETURN_FALSE; } + object_init_ex(return_value, ce); + fci.size = sizeof(fci); fci.function_table = EG(function_table); fci.function_name = NULL; @@ -3237,6 +3237,79 @@ ZEND_METHOD(reflection_class, newInstance) zval_ptr_dtor(&retval_ptr); } efree(params); + } else if (!ZEND_NUM_ARGS()) { + object_init_ex(return_value, ce); + } else { + zend_throw_exception_ex(U_CLASS_ENTRY(reflection_exception_ptr), 0 TSRMLS_CC, "Class %v does not have a constructor, so you cannot pass any constructor arguments", ce->name); + } +} +/* }}} */ + +/* {{{ proto public stdclass ReflectionClass::newInstanceArgs(array args) + Returns an instance of this class */ +ZEND_METHOD(reflection_class, newInstanceArgs) +{ + zval *retval_ptr; + reflection_object *intern; + zend_class_entry *ce; + int argc; + HashTable *args; + + + METHOD_NOTSTATIC(reflection_class_ptr); + GET_REFLECTION_OBJECT_PTR(ce); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|h", &args) == FAILURE) { + return; + } + argc = args->nNumOfElements; + + /* Run the constructor if there is one */ + if (ce->constructor) { + zval ***params; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + + if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) { + zend_throw_exception_ex(U_CLASS_ENTRY(reflection_exception_ptr), 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name); + return; + } + + params = safe_emalloc(sizeof(zval **), argc, 0); + zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, ¶ms TSRMLS_CC); + params -= argc; + + object_init_ex(return_value, ce); + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = NULL; + fci.symbol_table = NULL; + fci.object_pp = &return_value; + fci.retval_ptr_ptr = &retval_ptr; + fci.param_count = argc; + fci.params = params; + fci.no_separation = 1; + + fcc.initialized = 1; + fcc.function_handler = ce->constructor; + fcc.calling_scope = EG(scope); + fcc.object_pp = &return_value; + + if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { + efree(params); + zval_ptr_dtor(&retval_ptr); + zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name); + RETURN_NULL(); + } + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } + efree(params); + } else if (!ZEND_NUM_ARGS()) { + object_init_ex(return_value, ce); + } else { + zend_throw_exception_ex(U_CLASS_ENTRY(reflection_exception_ptr), 0 TSRMLS_CC, "Class %v does not have a constructor, so you cannot pass any constructor arguments", ce->name); } } /* }}} */ @@ -4094,6 +4167,7 @@ static zend_function_entry reflection_class_functions[] = { ZEND_ME(reflection_class, getModifiers, NULL, 0) ZEND_ME(reflection_class, isInstance, NULL, 0) ZEND_ME(reflection_class, newInstance, NULL, 0) + ZEND_ME(reflection_class, newInstanceArgs, NULL, 0) ZEND_ME(reflection_class, getParentClass, NULL, 0) ZEND_ME(reflection_class, isSubclassOf, NULL, 0) ZEND_ME(reflection_class, getStaticProperties, NULL, 0) diff --git a/ext/reflection/tests/007.phpt b/ext/reflection/tests/007.phpt new file mode 100755 index 0000000000..004158ccff --- /dev/null +++ b/ext/reflection/tests/007.phpt @@ -0,0 +1,160 @@ +--TEST-- +ReflectionClass::newInstance[Args] +--FILE-- +$class\n"; + try + { + $ref = new ReflectionClass($class); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + return; // only here + } + + echo "====>newInstance()\n"; + try + { + var_dump($ref->newInstance()); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "====>newInstance(25)\n"; + try + { + var_dump($ref->newInstance(25)); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "====>newInstance(25, 42)\n"; + try + { + var_dump($ref->newInstance(25, 42)); + } + catch (ReflectionException $e) + { + var_dump($e->getMessage()); + } + + echo "\n"; +} + +function __autoload($class) +{ + echo __FUNCTION__ . "($class)\n"; +} + +test('Class_does_not_exist'); + +Class NoCtor +{ +} + +test('NoCtor'); + +Class WithCtor +{ + function __construct() + { + echo __METHOD__ . "()\n"; + var_dump(func_get_args()); + } +} + +test('WithCtor'); + +Class WithCtorWithArgs +{ + function __construct($arg) + { + echo __METHOD__ . "($arg)\n"; + var_dump(func_get_args()); + } +} + +test('WithCtorWithArgs'); + +?> +===DONE=== + +--EXPECTF-- + +====>Class_does_not_exist +__autoload(Class_does_not_exist) +string(41) "Class Class_does_not_exist does not exist" +====>NoCtor +====>newInstance() +object(NoCtor)#%d (0) { +} +====>newInstance(25) +string(86) "Class NoCtor does not have a constructor, so you cannot pass any constructor arguments" +====>newInstance(25, 42) +string(86) "Class NoCtor does not have a constructor, so you cannot pass any constructor arguments" + +====>WithCtor +====>newInstance() +WithCtor::__construct() +array(0) { +} +object(WithCtor)#%d (0) { +} +====>newInstance(25) +WithCtor::__construct() +array(1) { + [0]=> + int(25) +} +object(WithCtor)#%d (0) { +} +====>newInstance(25, 42) +WithCtor::__construct() +array(2) { + [0]=> + int(25) + [1]=> + int(42) +} +object(WithCtor)#%d (0) { +} + +====>WithCtorWithArgs +====>newInstance() + +Warning: Missing argument 1 for WithCtorWithArgs::__construct() in %s007.php on line %d + +Notice: Undefined variable: arg in %s007.php on line %d +WithCtorWithArgs::__construct() +array(0) { +} +object(WithCtorWithArgs)#%d (0) { +} +====>newInstance(25) +WithCtorWithArgs::__construct(25) +array(1) { + [0]=> + int(25) +} +object(WithCtorWithArgs)#%d (0) { +} +====>newInstance(25, 42) +WithCtorWithArgs::__construct(25) +array(2) { + [0]=> + int(25) + [1]=> + int(42) +} +object(WithCtorWithArgs)#%d (0) { +} + +===DONE===