Browse Source

- MFH Bug #36141 Add ReflectionClass::newInstanceArgs($args)

PHP-5.1
Marcus Boerger 21 years ago
parent
commit
cb4bb6e389
  1. 1
      NEWS
  2. 78
      ext/reflection/php_reflection.c
  3. 160
      ext/reflection/tests/007.phpt

1
NEWS

@ -11,6 +11,7 @@ PHP NEWS
- Added "consumed" stream filter. (Marcus)
- Added new mysqli constants for BIT and NEW_DECIMAL field types:
MYSQLI_TYPE_NEWDECIMAL and MYSQLI_TYPE_BIT. FR #36007. (Georg)
- Added ReflectionClass::newInstanceArgs($args). (Marcus)
- Fixed imagecolorallocate() and imagecolorallocatelapha() to return FALSE
on error. (Pierre)
- Fixed bug #36134 (DirectoryIterator constructor failed to detect empty

78
ext/reflection/php_reflection.c

@ -3179,8 +3179,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;
@ -3198,6 +3196,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;
@ -3223,6 +3223,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(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s 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(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %c", 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, &params 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 %c'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(reflection_exception_ptr, 0 TSRMLS_CC, "Class %c does not have a constructor, so you cannot pass any constructor arguments", ce->name);
}
}
/* }}} */
@ -4076,6 +4149,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)

160
ext/reflection/tests/007.phpt

@ -0,0 +1,160 @@
--TEST--
ReflectionClass::newInstance[Args]
--FILE--
<?php
function test($class)
{
echo "====>$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===
<?php exit(0); ?>
--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===
Loading…
Cancel
Save