summaryrefslogtreecommitdiff
path: root/ext/reflection
diff options
context:
space:
mode:
Diffstat (limited to 'ext/reflection')
-rw-r--r--ext/reflection/php_reflection.c714
-rw-r--r--ext/reflection/php_reflection.h1
-rw-r--r--ext/reflection/tests/004.phpt2
-rw-r--r--ext/reflection/tests/007.phpt14
-rw-r--r--ext/reflection/tests/017.phpt4
-rw-r--r--ext/reflection/tests/ReflectionClassConstant_basic1.phpt194
-rw-r--r--ext/reflection/tests/ReflectionClassConstant_getValue.phpt47
-rw-r--r--ext/reflection/tests/ReflectionClass_export_array_bug72222.phpt4
-rw-r--r--ext/reflection/tests/ReflectionClass_isArray.phpt24
-rw-r--r--ext/reflection/tests/ReflectionClass_newInstanceArgs_001.phpt40
-rw-r--r--ext/reflection/tests/ReflectionClass_newInstance_001.phpt25
-rw-r--r--ext/reflection/tests/ReflectionClass_toString_001.phpt21
-rw-r--r--ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt24
-rw-r--r--ext/reflection/tests/ReflectionMethod_invokeArgs_error1.phpt15
-rw-r--r--ext/reflection/tests/ReflectionMethod_invokeArgs_error3.phpt13
-rw-r--r--ext/reflection/tests/ReflectionMethod_invoke_basic.phpt14
-rw-r--r--ext/reflection/tests/ReflectionMethod_invoke_error1.phpt4
-rw-r--r--ext/reflection/tests/ReflectionMethod_invoke_error2.phpt15
-rw-r--r--ext/reflection/tests/ReflectionNamedType.phpt41
-rw-r--r--ext/reflection/tests/ReflectionProperty_getValue_error.phpt15
-rw-r--r--ext/reflection/tests/ReflectionType_001.phpt18
-rw-r--r--ext/reflection/tests/ReflectionType_002.phpt4
-rw-r--r--ext/reflection/tests/ReflectionType_possible_types.phpt31
-rw-r--r--ext/reflection/tests/bug29986.phpt10
-rw-r--r--ext/reflection/tests/bug38217.phpt14
-rw-r--r--ext/reflection/tests/bug45765.phpt2
-rw-r--r--ext/reflection/tests/bug72661.phpt10
-rw-r--r--ext/reflection/tests/bug72846.phpt48
-rw-r--r--ext/reflection/tests/request38992.phpt22
29 files changed, 1012 insertions, 378 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 08acc7e5d2..df15efd077 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -60,10 +60,12 @@ PHPAPI zend_class_entry *reflection_function_ptr;
PHPAPI zend_class_entry *reflection_generator_ptr;
PHPAPI zend_class_entry *reflection_parameter_ptr;
PHPAPI zend_class_entry *reflection_type_ptr;
+PHPAPI zend_class_entry *reflection_named_type_ptr;
PHPAPI zend_class_entry *reflection_class_ptr;
PHPAPI zend_class_entry *reflection_object_ptr;
PHPAPI zend_class_entry *reflection_method_ptr;
PHPAPI zend_class_entry *reflection_property_ptr;
+PHPAPI zend_class_entry *reflection_class_constant_ptr;
PHPAPI zend_class_entry *reflection_extension_ptr;
PHPAPI zend_class_entry *reflection_zend_extension_ptr;
@@ -87,7 +89,7 @@ ZEND_DECLARE_MODULE_GLOBALS(reflection)
/* Method macros */
#define METHOD_NOTSTATIC(ce) \
- if (!Z_OBJ(EX(This)) || !instanceof_function(Z_OBJCE(EX(This)), ce)) { \
+ if ((Z_TYPE(EX(This)) != IS_OBJECT) || !instanceof_function(Z_OBJCE(EX(This)), ce)) { \
php_error_docref(NULL, E_ERROR, "%s() cannot be called statically", get_active_function_name()); \
return; \
} \
@@ -104,9 +106,10 @@ ZEND_DECLARE_MODULE_GLOBALS(reflection)
#define GET_REFLECTION_OBJECT() \
intern = Z_REFLECTION_P(getThis()); \
- if (intern->ptr == NULL) { \
+ if (intern->ptr == NULL) { \
RETURN_ON_EXCEPTION \
- php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the reflection object"); \
+ zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
+ return; \
} \
#define GET_REFLECTION_OBJECT_PTR(target) \
@@ -215,7 +218,8 @@ typedef enum {
REF_TYPE_PARAMETER,
REF_TYPE_TYPE,
REF_TYPE_PROPERTY,
- REF_TYPE_DYNAMIC_PROPERTY
+ REF_TYPE_DYNAMIC_PROPERTY,
+ REF_TYPE_CLASS_CONSTANT
} reflection_type_t;
/* Struct for reflection objects */
@@ -333,7 +337,7 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
efree(intern->ptr);
break;
case REF_TYPE_GENERATOR:
- break;
+ case REF_TYPE_CLASS_CONSTANT:
case REF_TYPE_OTHER:
break;
}
@@ -368,6 +372,7 @@ static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{
static void _const_string(string *str, char *name, zval *value, char *indent);
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent);
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent);
+static void _class_const_string(string *str, char *name, zend_class_constant *c, char* indent);
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent);
static void _extension_string(string *str, zend_module_entry *module, char *indent);
static void _zend_extension_string(string *str, zend_extension *extension, char *indent);
@@ -450,11 +455,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
string_printf(str, "%s - Constants [%d] {\n", indent, count);
if (count > 0) {
zend_string *key;
- zval *value;
+ zend_class_constant *c;
- ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, value) {
- zval_update_constant_ex(value, 1, NULL);
- _const_string(str, ZSTR_VAL(key), value, indent);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ _class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent.buf));
} ZEND_HASH_FOREACH_END();
}
string_printf(str, "%s }\n", indent);
@@ -631,6 +635,29 @@ static void _const_string(string *str, char *name, zval *value, char *indent)
}
/* }}} */
+/* {{{ _class_const_string */
+static void _class_const_string(string *str, char *name, zend_class_constant *c, char *indent)
+{
+ char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
+ char *type;
+
+ zval_update_constant_ex(&c->value, c->ce);
+ type = zend_zval_type_name(&c->value);
+
+ if (Z_TYPE(c->value) == IS_ARRAY) {
+ string_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
+ indent, visibility, type, name);
+ } else {
+ zend_string *value_str = zval_get_string(&c->value);
+
+ string_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
+ indent, visibility, type, name, ZSTR_VAL(value_str));
+
+ zend_string_release(value_str);
+ }
+}
+/* }}} */
+
/* {{{ _get_recv_opcode */
static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
{
@@ -640,7 +667,7 @@ static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
++offset;
while (op < end) {
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
- || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == (zend_long)offset)
+ || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
{
return op;
}
@@ -693,14 +720,10 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
zval zv;
- zend_class_entry *old_scope;
string_write(str, " = ", sizeof(" = ")-1);
ZVAL_DUP(&zv, RT_CONSTANT(&fptr->op_array, precv->op2));
- old_scope = EG(scope);
- EG(scope) = fptr->common.scope;
- zval_update_constant_ex(&zv, 1, NULL);
- EG(scope) = old_scope;
+ zval_update_constant_ex(&zv, fptr->common.scope);
if (Z_TYPE(zv) == IS_TRUE) {
string_write(str, "true", sizeof("true")-1);
} else if (Z_TYPE(zv) == IS_FALSE) {
@@ -1254,7 +1277,7 @@ static void reflection_type_factory(zend_function *fptr, zval *closure_object, s
reflection_object *intern;
type_reference *reference;
- reflection_instantiate(reflection_type_ptr, object);
+ reflection_instantiate(reflection_named_type_ptr, object);
intern = Z_REFLECTION_P(object);
reference = (type_reference*) emalloc(sizeof(type_reference));
reference->arg_info = arg_info;
@@ -1360,11 +1383,31 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
/* }}} */
+/* {{{ reflection_class_constant_factory */
+static void reflection_class_constant_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
+{
+ reflection_object *intern;
+ zval name;
+ zval classname;
+
+ ZVAL_STR_COPY(&name, name_str);
+ ZVAL_STR_COPY(&classname, ce->name);
+
+ reflection_instantiate(reflection_class_constant_ptr, object);
+ intern = Z_REFLECTION_P(object);
+ intern->ptr = constant;
+ intern->ref_type = REF_TYPE_CLASS_CONSTANT;
+ intern->ce = constant->ce;
+ intern->ignore_visibility = 0;
+ reflection_update_property(object, "name", &name);
+ reflection_update_property(object, "class", &classname);
+}
+/* }}} */
+
/* {{{ _reflection_export */
static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
{
zval reflector;
- zval output, *output_ptr = &output;
zval *argument_ptr, *argument2_ptr;
zval retval, params[2];
int result;
@@ -1394,9 +1437,7 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c
/* Call __construct() */
fci.size = sizeof(fci);
- fci.function_table = NULL;
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = Z_OBJ(reflector);
fci.retval = &retval;
fci.param_count = ctor_argc;
@@ -1423,12 +1464,10 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c
}
/* Call static reflection::export */
- ZVAL_BOOL(&output, return_output);
ZVAL_COPY_VALUE(&params[0], &reflector);
- ZVAL_COPY_VALUE(&params[1], output_ptr);
+ ZVAL_BOOL(&params[1], return_output);
ZVAL_STRINGL(&fci.function_name, "reflection::export", sizeof("reflection::export") - 1);
- fci.function_table = &reflection_ptr->function_table;
fci.object = NULL;
fci.retval = &retval;
fci.param_count = 2;
@@ -1467,7 +1506,8 @@ static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTIO
if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {
return NULL;
}
- php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the reflection object");
+ zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object");
+ return NULL;
}
param = intern->ptr;
@@ -1900,7 +1940,7 @@ ZEND_METHOD(reflection_function, getStaticVariables)
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
}
ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) {
- if (UNEXPECTED(zval_update_constant_ex(val, 1, fptr->common.scope) != SUCCESS)) {
+ if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
return;
}
} ZEND_HASH_FOREACH_END();
@@ -1929,9 +1969,7 @@ ZEND_METHOD(reflection_function, invoke)
}
fci.size = sizeof(fci);
- fci.function_table = NULL;
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = NULL;
fci.retval = &retval;
fci.param_count = num_args;
@@ -1940,7 +1978,7 @@ ZEND_METHOD(reflection_function, invoke)
fcc.initialized = 1;
fcc.function_handler = fptr;
- fcc.calling_scope = EG(scope);
+ fcc.calling_scope = zend_get_executed_scope();
fcc.called_scope = NULL;
fcc.object = NULL;
@@ -1989,9 +2027,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
} ZEND_HASH_FOREACH_END();
fci.size = sizeof(fci);
- fci.function_table = NULL;
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = NULL;
fci.retval = &retval;
fci.param_count = argc;
@@ -2000,7 +2036,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
fcc.initialized = 1;
fcc.function_handler = fptr;
- fcc.calling_scope = EG(scope);
+ fcc.calling_scope = zend_get_executed_scope();
fcc.called_scope = NULL;
fcc.object = NULL;
@@ -2285,7 +2321,7 @@ ZEND_METHOD(reflection_generator, getThis)
REFLECTION_CHECK_VALID_GENERATOR(ex)
- if (Z_OBJ(ex->This)) {
+ if (Z_TYPE(ex->This) == IS_OBJECT) {
ZVAL_COPY(return_value, &ex->This);
} else {
ZVAL_NULL(return_value);
@@ -2861,15 +2897,9 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
return;
}
- ZVAL_COPY_VALUE(return_value, RT_CONSTANT(&param->fptr->op_array, precv->op2));
+ ZVAL_DUP(return_value, RT_CONSTANT(&param->fptr->op_array, precv->op2));
if (Z_CONSTANT_P(return_value)) {
- zend_class_entry *old_scope = EG(scope);
-
- EG(scope) = param->fptr->common.scope;
- zval_update_constant_ex(return_value, 0, NULL);
- EG(scope) = old_scope;
- } else {
- zval_copy_ctor(return_value);
+ zval_update_constant_ex(return_value, param->fptr->common.scope);
}
}
/* }}} */
@@ -2970,33 +3000,74 @@ ZEND_METHOD(reflection_type, isBuiltin)
}
/* }}} */
+/* {{{ reflection_type_name */
+static zend_string *reflection_type_name(type_reference *param) {
+ switch (param->arg_info->type_hint) {
+ case IS_ARRAY: return zend_string_init("array", sizeof("array") - 1, 0);
+ case IS_CALLABLE: return zend_string_init("callable", sizeof("callable") - 1, 0);
+ case IS_OBJECT:
+ if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
+ !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
+ return zend_string_init(((zend_internal_arg_info*)param->arg_info)->class_name, strlen(((zend_internal_arg_info*)param->arg_info)->class_name), 0);
+ }
+ return zend_string_copy(param->arg_info->class_name);
+ case IS_STRING: return zend_string_init("string", sizeof("string") - 1, 0);
+ case _IS_BOOL: return zend_string_init("bool", sizeof("bool") - 1, 0);
+ case IS_LONG: return zend_string_init("int", sizeof("int") - 1, 0);
+ case IS_DOUBLE: return zend_string_init("float", sizeof("float") - 1, 0);
+ case IS_VOID: return zend_string_init("void", sizeof("void") - 1, 0);
+ case IS_ITERABLE: return zend_string_init("iterable", sizeof("iterable") - 1, 0);
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
/* {{{ proto public string ReflectionType::__toString()
Return the text of the type hint */
ZEND_METHOD(reflection_type, __toString)
{
reflection_object *intern;
type_reference *param;
+ zend_string *str;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(param);
+
+ str = reflection_type_name(param);
+
+ if (param->arg_info->type_hint == IS_OBJECT
+ && !zend_string_equals_literal_ci(param->arg_info->class_name, "self")
+ && !zend_string_equals_literal_ci(param->arg_info->class_name, "parent")) {
+ str = zend_string_extend(str, ZSTR_LEN(str) + 1, 0);
+ memmove(ZSTR_VAL(str) + 1, ZSTR_VAL(str), ZSTR_LEN(str) + 1);
+ ZSTR_VAL(str)[0] = '\\';
+ }
+
+ if (param->arg_info->allow_null) {
+ str = zend_string_extend(str, ZSTR_LEN(str) + 1, 0);
+ memmove(ZSTR_VAL(str) + 1, ZSTR_VAL(str), ZSTR_LEN(str) + 1);
+ ZSTR_VAL(str)[0] = '?';
+ }
+
+ RETURN_STR(str);
+}
+/* }}} */
- switch (param->arg_info->type_hint) {
- case IS_ARRAY: RETURN_STRINGL("array", sizeof("array") - 1);
- case IS_CALLABLE: RETURN_STRINGL("callable", sizeof("callable") - 1);
- case IS_OBJECT:
- if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
- !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
- RETURN_STRING(((zend_internal_arg_info*)param->arg_info)->class_name);
- }
- RETURN_STR_COPY(param->arg_info->class_name);
- case IS_STRING: RETURN_STRINGL("string", sizeof("string") - 1);
- case _IS_BOOL: RETURN_STRINGL("bool", sizeof("bool") - 1);
- case IS_LONG: RETURN_STRINGL("int", sizeof("int") - 1);
- case IS_DOUBLE: RETURN_STRINGL("float", sizeof("float") - 1);
- EMPTY_SWITCH_DEFAULT_CASE()
+/* {{{ proto public string ReflectionNamedType::getName()
+ Return the text of the type hint */
+ZEND_METHOD(reflection_named_type, getName)
+{
+ reflection_object *intern;
+ type_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
}
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETURN_STR(reflection_type_name(param));
}
/* }}} */
@@ -3154,19 +3225,18 @@ ZEND_METHOD(reflection_method, getClosure)
}
/* }}} */
-/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
- Invokes the method. */
-ZEND_METHOD(reflection_method, invoke)
+/* {{{ reflection_method_invoke */
+static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
{
zval retval;
- zval *params = NULL;
- zend_object *object;
+ zval *params = NULL, *val, *object;
reflection_object *intern;
zend_function *mptr;
- int result, num_args = 0;
+ int i, argc = 0, result;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
+ zval *param_array;
METHOD_NOTSTATIC(reflection_method_ptr);
@@ -3190,115 +3260,25 @@ ZEND_METHOD(reflection_method, invoke)
return;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &params, &num_args) == FAILURE) {
- return;
- }
-
- /* In case this is a static method, we should'nt pass an object_ptr
- * (which is used as calling context aka $this). We can thus ignore the
- * first parameter.
- *
- * Else, we verify that the given object is an instance of the class.
- */
- if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
- object = NULL;
- obj_ce = mptr->common.scope;
- } else {
- if (Z_TYPE(params[0]) != IS_OBJECT) {
- _DO_THROW("Non-object passed to Invoke()");
- /* Returns from this function */
+ if (variadic) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!*", &object, &params, &argc) == FAILURE) {
+ return;
}
-
- obj_ce = Z_OBJCE(params[0]);
-
- if (!instanceof_function(obj_ce, mptr->common.scope)) {
- _DO_THROW("Given object is not an instance of the class this method was declared in");
- /* Returns from this function */
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_array) == FAILURE) {
+ return;
}
- object = Z_OBJ(params[0]);
- }
-
- fci.size = sizeof(fci);
- fci.function_table = NULL;
- ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
- fci.object = object;
- fci.retval = &retval;
- fci.param_count = num_args - 1;
- fci.params = params + 1;
- fci.no_separation = 1;
-
- fcc.initialized = 1;
- fcc.function_handler = mptr;
- fcc.calling_scope = obj_ce;
- fcc.called_scope = intern->ce;
- fcc.object = object;
-
- result = zend_call_function(&fci, &fcc);
-
- if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0,
- "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
- return;
- }
-
- if (Z_TYPE(retval) != IS_UNDEF) {
- ZVAL_COPY_VALUE(return_value, &retval);
- }
-}
-/* }}} */
+ argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-/* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
- Invokes the function and pass its arguments as array. */
-ZEND_METHOD(reflection_method, invokeArgs)
-{
- zval retval;
- zval *params, *val, *object;
- reflection_object *intern;
- zend_function *mptr;
- int i, argc;
- int result;
- zend_fcall_info fci;
- zend_fcall_info_cache fcc;
- zend_class_entry *obj_ce;
- zval *param_array;
-
- METHOD_NOTSTATIC(reflection_method_ptr);
-
- GET_REFLECTION_OBJECT_PTR(mptr);
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_array) == FAILURE) {
- return;
- }
-
- if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
- || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
- && intern->ignore_visibility == 0)
- {
- if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_throw_exception_ex(reflection_exception_ptr, 0,
- "Trying to invoke abstract method %s::%s()",
- ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
- } else {
- zend_throw_exception_ex(reflection_exception_ptr, 0,
- "Trying to invoke %s method %s::%s() from scope %s",
- mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
- ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
- ZSTR_VAL(Z_OBJCE_P(getThis())->name));
- }
- return;
+ params = safe_emalloc(sizeof(zval), argc, 0);
+ argc = 0;
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
+ ZVAL_COPY(&params[argc], val);
+ argc++;
+ } ZEND_HASH_FOREACH_END();
}
- argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-
- params = safe_emalloc(sizeof(zval), argc, 0);
- argc = 0;
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
- ZVAL_COPY(&params[argc], val);
- argc++;
- } ZEND_HASH_FOREACH_END();
-
/* In case this is a static method, we should'nt pass an object_ptr
* (which is used as calling context aka $this). We can thus ignore the
* first parameter.
@@ -3310,7 +3290,6 @@ ZEND_METHOD(reflection_method, invokeArgs)
obj_ce = mptr->common.scope;
} else {
if (!object) {
- efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Trying to invoke non static method %s::%s() without an object",
ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
@@ -3320,16 +3299,16 @@ ZEND_METHOD(reflection_method, invokeArgs)
obj_ce = Z_OBJCE_P(object);
if (!instanceof_function(obj_ce, mptr->common.scope)) {
- efree(params);
+ if (!variadic) {
+ efree(params);
+ }
_DO_THROW("Given object is not an instance of the class this method was declared in");
/* Returns from this function */
}
}
fci.size = sizeof(fci);
- fci.function_table = NULL;
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = object ? Z_OBJ_P(object) : NULL;
fci.retval = &retval;
fci.param_count = argc;
@@ -3340,21 +3319,25 @@ ZEND_METHOD(reflection_method, invokeArgs)
fcc.function_handler = mptr;
fcc.calling_scope = obj_ce;
fcc.called_scope = intern->ce;
- fcc.object = (object) ? Z_OBJ_P(object) : NULL;
+ fcc.object = object ? Z_OBJ_P(object) : NULL;
- /*
- * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
- */
- if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
- fcc.function_handler = _copy_function(mptr);
+ if (!variadic) {
+ /*
+ * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
+ */
+ if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
+ fcc.function_handler = _copy_function(mptr);
+ }
}
result = zend_call_function(&fci, &fcc);
- for (i = 0; i < argc; i++) {
- zval_ptr_dtor(&params[i]);
+ if (!variadic) {
+ for (i = 0; i < argc; i++) {
+ zval_ptr_dtor(&params[i]);
+ }
+ efree(params);
}
- efree(params);
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -3368,6 +3351,22 @@ ZEND_METHOD(reflection_method, invokeArgs)
}
/* }}} */
+/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
+ Invokes the method. */
+ZEND_METHOD(reflection_method, invoke)
+{
+ reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
+ Invokes the function and pass its arguments as array. */
+ZEND_METHOD(reflection_method, invokeArgs)
+{
+ reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionMethod::isFinal()
Returns whether this method is final */
ZEND_METHOD(reflection_method, isFinal)
@@ -3656,6 +3655,197 @@ ZEND_METHOD(reflection_method, setAccessible)
}
/* }}} */
+/* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
+ Constructor. Throws an Exception in case the given class constant does not exist */
+ZEND_METHOD(reflection_class_constant, __construct)
+{
+ zval *classname, *object, name, cname;
+ zend_string *constname;
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_class_constant *constant = NULL;
+
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
+ return;
+ }
+
+ object = getThis();
+ intern = Z_REFLECTION_P(object);
+
+ /* Find the class entry */
+ switch (Z_TYPE_P(classname)) {
+ case IS_STRING:
+ if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0,
+ "Class %s does not exist", Z_STRVAL_P(classname));
+ return;
+ }
+ break;
+
+ case IS_OBJECT:
+ ce = Z_OBJCE_P(classname);
+ break;
+
+ default:
+ _DO_THROW("The parameter class is expected to be either a string or an object");
+ /* returns out of this function */
+ }
+
+ if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
+ return;
+ }
+
+ ZVAL_STR_COPY(&name, constname);
+ ZVAL_STR_COPY(&cname, ce->name);
+
+ intern->ptr = constant;
+ intern->ref_type = REF_TYPE_CLASS_CONSTANT;
+ intern->ce = constant->ce;
+ intern->ignore_visibility = 0;
+ reflection_update_property(object, "name", &name);
+ reflection_update_property(object, "class", &cname);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::__toString()
+ Returns a string representation */
+ZEND_METHOD(reflection_class_constant, __toString)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+ string str;
+ zval name;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ string_init(&str);
+ _default_get_entry(getThis(), "name", sizeof("name")-1, &name);
+ _class_const_string(&str, Z_STRVAL(name), ref, "");
+ zval_ptr_dtor(&name);
+ RETURN_NEW_STR(str.buf);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::getName()
+ Returns the constant' name */
+ZEND_METHOD(reflection_class_constant, getName)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
+}
+/* }}} */
+
+static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isPublic()
+ Returns whether this constant is public */
+ZEND_METHOD(reflection_class_constant, isPublic)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isPrivate()
+ Returns whether this constant is private */
+ZEND_METHOD(reflection_class_constant, isPrivate)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isProtected()
+ Returns whether this constant is protected */
+ZEND_METHOD(reflection_class_constant, isProtected)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
+}
+/* }}} */
+
+/* {{{ proto public int ReflectionClassConstant::getModifiers()
+ Returns a bitfield of the access modifiers for this constant */
+ZEND_METHOD(reflection_class_constant, getModifiers)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionClassConstant::getValue()
+ Returns this constant's value */
+ZEND_METHOD(reflection_class_constant, getValue)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ ZVAL_DUP(return_value, &ref->value);
+ if (Z_CONSTANT_P(return_value)) {
+ zval_update_constant_ex(return_value, ref->ce);
+ }
+}
+/* }}} */
+
+/* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
+ Get the declaring class */
+ZEND_METHOD(reflection_class_constant, getDeclaringClass)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ zend_reflection_class_factory(ref->ce, return_value);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::getDocComment()
+ Returns the doc comment for this constant */
+ZEND_METHOD(reflection_class_constant, getDocComment)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ if (ref->doc_comment) {
+ RETURN_STR_COPY(ref->doc_comment);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
/* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class, export)
@@ -3753,7 +3943,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_CONSTANT(prop_copy)) {
- if (UNEXPECTED(zval_update_constant_ex(&prop_copy, 1, NULL) != SUCCESS)) {
+ if (UNEXPECTED(zval_update_constant_ex(&prop_copy, NULL) != SUCCESS)) {
return;
}
}
@@ -4399,6 +4589,8 @@ ZEND_METHOD(reflection_class, getConstants)
{
reflection_object *intern;
zend_class_entry *ce;
+ zend_string *key;
+ zend_class_constant *c;
zval *val;
if (zend_parse_parameters_none() == FAILURE) {
@@ -4406,13 +4598,36 @@ ZEND_METHOD(reflection_class, getConstants)
}
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
- ZEND_HASH_FOREACH_VAL(&ce->constants_table, val) {
- ZVAL_DEREF(val);
- if (UNEXPECTED(zval_update_constant_ex(val, 1, ce) != SUCCESS)) {
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
+ zend_array_destroy(Z_ARRVAL_P(return_value));
return;
}
+ val = zend_hash_add_new(Z_ARRVAL_P(return_value), key, &c->value);
+ Z_TRY_ADDREF_P(val);
+ } ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
+/* {{{ proto public array ReflectionClass::getReflectionConstants()
+ Returns an associative array containing this class' constants as ReflectionClassConstant objects */
+ZEND_METHOD(reflection_class, getReflectionConstants)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_string *name;
+ zend_class_constant *constant;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+ array_init(return_value);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
+ zval class_const;
+ reflection_class_constant_factory(ce, name, constant, &class_const);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
} ZEND_HASH_FOREACH_END();
- zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref);
}
/* }}} */
@@ -4422,7 +4637,7 @@ ZEND_METHOD(reflection_class, getConstant)
{
reflection_object *intern;
zend_class_entry *ce;
- zval *value;
+ zend_class_constant *c;
zend_string *name;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -4431,16 +4646,36 @@ ZEND_METHOD(reflection_class, getConstant)
}
GET_REFLECTION_OBJECT_PTR(ce);
- ZEND_HASH_FOREACH_VAL(&ce->constants_table, value) {
- ZVAL_DEREF(value);
- if (UNEXPECTED(zval_update_constant_ex(value, 1, ce) != SUCCESS)) {
+ ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
+ if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
return;
}
} ZEND_HASH_FOREACH_END();
- if ((value = zend_hash_find(&ce->constants_table, name)) == NULL) {
+ if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
RETURN_FALSE;
}
- ZVAL_DUP(return_value, value);
+ ZVAL_DUP(return_value, &c->value);
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
+ Returns the class' constant as ReflectionClassConstant objects */
+ZEND_METHOD(reflection_class, getReflectionConstant)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_class_constant *constant;
+ zend_string *name;
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
+ return;
+ }
+
+ if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
+ RETURN_FALSE;
+ }
+ reflection_class_constant_factory(ce, name, constant, return_value);
}
/* }}} */
@@ -4599,10 +4834,10 @@ ZEND_METHOD(reflection_class, newInstance)
return;
}
- old_scope = EG(scope);
- EG(scope) = ce;
+ old_scope = EG(fake_scope);
+ EG(fake_scope) = ce;
constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
/* Run the constructor if there is one */
if (constructor) {
@@ -4627,9 +4862,7 @@ ZEND_METHOD(reflection_class, newInstance)
}
fci.size = sizeof(fci);
- fci.function_table = EG(function_table);
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = Z_OBJ_P(return_value);
fci.retval = &retval;
fci.param_count = num_args;
@@ -4638,7 +4871,7 @@ ZEND_METHOD(reflection_class, newInstance)
fcc.initialized = 1;
fcc.function_handler = constructor;
- fcc.calling_scope = EG(scope);
+ fcc.calling_scope = zend_get_executed_scope();;
fcc.called_scope = Z_OBJCE_P(return_value);
fcc.object = Z_OBJ_P(return_value);
@@ -4704,10 +4937,10 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
return;
}
- old_scope = EG(scope);
- EG(scope) = ce;
+ old_scope = EG(fake_scope);
+ EG(fake_scope) = ce;
constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
- EG(scope) = old_scope;
+ EG(fake_scope) = old_scope;
/* Run the constructor if there is one */
if (constructor) {
@@ -4731,9 +4964,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
}
fci.size = sizeof(fci);
- fci.function_table = EG(function_table);
ZVAL_UNDEF(&fci.function_name);
- fci.symbol_table = NULL;
fci.object = Z_OBJ_P(return_value);
fci.retval = &retval;
fci.param_count = argc;
@@ -4742,7 +4973,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
fcc.initialized = 1;
fcc.function_handler = constructor;
- fcc.calling_scope = EG(scope);
+ fcc.calling_scope = zend_get_executed_scope();
fcc.called_scope = Z_OBJCE_P(return_value);
fcc.object = Z_OBJ_P(return_value);
@@ -4937,9 +5168,9 @@ ZEND_METHOD(reflection_class, isSubclassOf)
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
argument = Z_REFLECTION_P(class_name);
- if (argument == NULL || argument->ptr == NULL) {
- php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
- /* Bails out */
+ if (argument->ptr == NULL) {
+ zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
+ return;
}
class_ce = argument->ptr;
break;
@@ -4981,9 +5212,9 @@ ZEND_METHOD(reflection_class, implementsInterface)
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
argument = Z_REFLECTION_P(interface);
- if (argument == NULL || argument->ptr == NULL) {
- php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
- /* Bails out */
+ if (argument->ptr == NULL) {
+ zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
+ return;
}
interface_ce = argument->ptr;
break;
@@ -5158,6 +5389,14 @@ ZEND_METHOD(reflection_property, export)
}
/* }}} */
+/* {{{ proto public static mixed ReflectionClassConstant::export(mixed class, string name [, bool return]) throws ReflectionException
+ Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
+ZEND_METHOD(reflection_class_constant, export)
+{
+ _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_constant_ptr, 2);
+}
+/* }}} */
+
/* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
Constructor. Throws an Exception in case the given property does not exist */
ZEND_METHOD(reflection_property, __construct)
@@ -5375,10 +5614,12 @@ ZEND_METHOD(reflection_property, getValue)
return;
}
if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
- php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
- /* Bails out */
+ zend_throw_error(NULL, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
+ return;
}
- ZVAL_DUP(return_value, &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]);
+ member_p = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+ ZVAL_DEREF(member_p);
+ ZVAL_COPY(return_value, member_p);
} else {
const char *class_name, *prop_name;
size_t prop_name_len;
@@ -5388,11 +5629,20 @@ ZEND_METHOD(reflection_property, getValue)
return;
}
+ if (!instanceof_function(Z_OBJCE_P(object), ref->ce)) {
+ _DO_THROW("Given object is not an instance of the class this property was declared in");
+ /* Returns from this function */
+ }
+
zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len);
member_p = zend_read_property(ref->ce, object, prop_name, prop_name_len, 0, &rv);
if (member_p != &rv) {
+ ZVAL_DEREF(member_p);
ZVAL_COPY(return_value, member_p);
} else {
+ if (Z_ISREF_P(member_p)) {
+ zend_unwrap_reference(member_p);
+ }
ZVAL_COPY_VALUE(return_value, member_p);
}
}
@@ -5431,8 +5681,8 @@ ZEND_METHOD(reflection_property, setValue)
}
if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
- php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
- /* Bails out */
+ zend_throw_error(NULL, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
+ return;
}
variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
if (variable_ptr != value) {
@@ -5561,7 +5811,6 @@ ZEND_METHOD(reflection_extension, __construct)
object = getThis();
intern = Z_REFLECTION_P(object);
-
lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len);
if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
@@ -6313,7 +6562,9 @@ static const zend_function_entry reflection_class_functions[] = {
ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getReflectionConstants, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
+ ZEND_ME(reflection_class, getReflectionConstant, arginfo_reflection_class_getConstant, 0)
ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
@@ -6405,6 +6656,33 @@ static const zend_function_entry reflection_property_functions[] = {
PHP_FE_END
};
+ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant_export, 0, 0, 2)
+ ZEND_ARG_INFO(0, class)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, return)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant___construct, 0, 0, 2)
+ ZEND_ARG_INFO(0, class)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry reflection_class_constant_functions[] = {
+ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
+ ZEND_ME(reflection_class_constant, export, arginfo_reflection_class_constant_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
+ ZEND_ME(reflection_class_constant, __construct, arginfo_reflection_class_constant___construct, 0)
+ ZEND_ME(reflection_class_constant, __toString, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getName, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getValue, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isPublic, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isPrivate, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isProtected, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
ZEND_ARG_INFO(0, function)
ZEND_ARG_INFO(0, parameter)
@@ -6450,6 +6728,11 @@ static const zend_function_entry reflection_type_functions[] = {
PHP_FE_END
};
+static const zend_function_entry reflection_named_type_functions[] = {
+ ZEND_ME(reflection_named_type, getName, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
ZEND_ARG_INFO(0, name)
ZEND_ARG_INFO(0, return)
@@ -6566,6 +6849,10 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
_reflection_entry.create_object = reflection_objects_new;
reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
+
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
_reflection_entry.create_object = reflection_objects_new;
@@ -6601,6 +6888,13 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
+ zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
+ zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
+ zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
+
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
diff --git a/ext/reflection/php_reflection.h b/ext/reflection/php_reflection.h
index b4f2cd7bc0..e89e13a151 100644
--- a/ext/reflection/php_reflection.h
+++ b/ext/reflection/php_reflection.h
@@ -38,6 +38,7 @@ extern PHPAPI zend_class_entry *reflection_function_abstract_ptr;
extern PHPAPI zend_class_entry *reflection_function_ptr;
extern PHPAPI zend_class_entry *reflection_parameter_ptr;
extern PHPAPI zend_class_entry *reflection_type_ptr;
+extern PHPAPI zend_class_entry *reflection_named_type_ptr;
extern PHPAPI zend_class_entry *reflection_class_ptr;
extern PHPAPI zend_class_entry *reflection_object_ptr;
extern PHPAPI zend_class_entry *reflection_method_ptr;
diff --git a/ext/reflection/tests/004.phpt b/ext/reflection/tests/004.phpt
index 41632aa3ba..36ae406b43 100644
--- a/ext/reflection/tests/004.phpt
+++ b/ext/reflection/tests/004.phpt
@@ -38,6 +38,6 @@ try {
echo "===DONE===\n";?>
--EXPECTF--
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; a has a deprecated constructor in %s on line %d
-Non-object passed to Invoke()
+Trying to invoke non static method a::a() without an object
Given object is not an instance of the class this method was declared in
===DONE===
diff --git a/ext/reflection/tests/007.phpt b/ext/reflection/tests/007.phpt
index 004158ccff..d9204171b5 100644
--- a/ext/reflection/tests/007.phpt
+++ b/ext/reflection/tests/007.phpt
@@ -25,6 +25,10 @@ function test($class)
{
var_dump($e->getMessage());
}
+ catch (Throwable $e)
+ {
+ echo "Exception: " . $e->getMessage() . "\n";
+ }
echo "====>newInstance(25)\n";
try
@@ -129,15 +133,7 @@ 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) {
-}
+Exception: Too few arguments to function WithCtorWithArgs::__construct(), 0 passed and exactly 1 expected
====>newInstance(25)
WithCtorWithArgs::__construct(25)
array(1) {
diff --git a/ext/reflection/tests/017.phpt b/ext/reflection/tests/017.phpt
index d40c4d83f9..1d9275d21b 100644
--- a/ext/reflection/tests/017.phpt
+++ b/ext/reflection/tests/017.phpt
@@ -10,12 +10,12 @@ class Foo {
$class = new ReflectionClass("Foo");
echo $class;
?>
---EXPECTF--
+--EXPECTF--
Class [ <user> class Foo ] {
@@ %s017.php 2-4
- Constants [1] {
- Constant [ string test ] { ok }
+ Constant [ public string test ] { ok }
}
- Static properties [0] {
diff --git a/ext/reflection/tests/ReflectionClassConstant_basic1.phpt b/ext/reflection/tests/ReflectionClassConstant_basic1.phpt
new file mode 100644
index 0000000000..fd8118650f
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClassConstant_basic1.phpt
@@ -0,0 +1,194 @@
+--TEST--
+Test usage of ReflectionClassConstant methods __toString(), export(), getName(), getValue(), isPublic(), isPrivate(), isProtected(), getModifiers(), getDeclaringClass() and getDocComment().
+--FILE--
+<?php
+
+function reflectClassConstant($base, $constant) {
+ $constInfo = new ReflectionClassConstant($base, $constant);
+ echo "**********************************\n";
+ $class = is_object($base) ? get_class($base) : $base;
+ echo "Reflecting on class constant $class::$constant\n\n";
+ echo "__toString():\n";
+ var_dump($constInfo->__toString());
+ echo "export():\n";
+ var_dump(ReflectionClassConstant::export($base, $constant, true));
+ echo "export():\n";
+ var_dump(ReflectionClassConstant::export($base, $constant, false));
+ echo "getName():\n";
+ var_dump($constInfo->getName());
+ echo "getValue():\n";
+ var_dump($constInfo->getValue());
+ echo "isPublic():\n";
+ var_dump($constInfo->isPublic());
+ echo "isPrivate():\n";
+ var_dump($constInfo->isPrivate());
+ echo "isProtected():\n";
+ var_dump($constInfo->isProtected());
+ echo "getModifiers():\n";
+ var_dump($constInfo->getModifiers());
+ echo "getDeclaringClass():\n";
+ var_dump($constInfo->getDeclaringClass());
+ echo "getDocComment():\n";
+ var_dump($constInfo->getDocComment());
+ echo "\n**********************************\n";
+}
+
+class TestClass {
+ public const /** My Doc comment */ PUB = true;
+ /** Another doc comment */
+ protected const PROT = 4;
+ private const PRIV = "keepOut";
+}
+$instance = new TestClass();
+
+reflectClassConstant("TestClass", "PUB");
+reflectClassConstant("TestClass", "PROT");
+reflectClassConstant("TestClass", "PRIV");
+reflectClassConstant($instance, "PRIV");
+reflectClassConstant($instance, "BAD_CONST");
+
+?>
+--EXPECTF--
+**********************************
+Reflecting on class constant TestClass::PUB
+
+__toString():
+string(38) "Constant [ public boolean PUB ] { 1 }
+"
+export():
+string(38) "Constant [ public boolean PUB ] { 1 }
+"
+export():
+Constant [ public boolean PUB ] { 1 }
+
+NULL
+getName():
+string(3) "PUB"
+getValue():
+bool(true)
+isPublic():
+bool(true)
+isPrivate():
+bool(false)
+isProtected():
+bool(false)
+getModifiers():
+int(256)
+getDeclaringClass():
+object(ReflectionClass)#3 (1) {
+ ["name"]=>
+ string(9) "TestClass"
+}
+getDocComment():
+string(21) "/** My Doc comment */"
+
+**********************************
+**********************************
+Reflecting on class constant TestClass::PROT
+
+__toString():
+string(42) "Constant [ protected integer PROT ] { 4 }
+"
+export():
+string(42) "Constant [ protected integer PROT ] { 4 }
+"
+export():
+Constant [ protected integer PROT ] { 4 }
+
+NULL
+getName():
+string(4) "PROT"
+getValue():
+int(4)
+isPublic():
+bool(false)
+isPrivate():
+bool(false)
+isProtected():
+bool(true)
+getModifiers():
+int(512)
+getDeclaringClass():
+object(ReflectionClass)#3 (1) {
+ ["name"]=>
+ string(9) "TestClass"
+}
+getDocComment():
+string(26) "/** Another doc comment */"
+
+**********************************
+**********************************
+Reflecting on class constant TestClass::PRIV
+
+__toString():
+string(45) "Constant [ private string PRIV ] { keepOut }
+"
+export():
+string(45) "Constant [ private string PRIV ] { keepOut }
+"
+export():
+Constant [ private string PRIV ] { keepOut }
+
+NULL
+getName():
+string(4) "PRIV"
+getValue():
+string(7) "keepOut"
+isPublic():
+bool(false)
+isPrivate():
+bool(true)
+isProtected():
+bool(false)
+getModifiers():
+int(1024)
+getDeclaringClass():
+object(ReflectionClass)#3 (1) {
+ ["name"]=>
+ string(9) "TestClass"
+}
+getDocComment():
+bool(false)
+
+**********************************
+**********************************
+Reflecting on class constant TestClass::PRIV
+
+__toString():
+string(45) "Constant [ private string PRIV ] { keepOut }
+"
+export():
+string(45) "Constant [ private string PRIV ] { keepOut }
+"
+export():
+Constant [ private string PRIV ] { keepOut }
+
+NULL
+getName():
+string(4) "PRIV"
+getValue():
+string(7) "keepOut"
+isPublic():
+bool(false)
+isPrivate():
+bool(true)
+isProtected():
+bool(false)
+getModifiers():
+int(1024)
+getDeclaringClass():
+object(ReflectionClass)#3 (1) {
+ ["name"]=>
+ string(9) "TestClass"
+}
+getDocComment():
+bool(false)
+
+**********************************
+
+Fatal error: Uncaught ReflectionException: Class Constant TestClass::BAD_CONST does not exist in %s:%d
+Stack trace:
+#0 %s(%d): ReflectionClassConstant->__construct(Object(TestClass), 'BAD_CONST')
+#1 %s(%d): reflectClassConstant(Object(TestClass), 'BAD_CONST')
+#2 {main}
+ thrown in %s on line %d
diff --git a/ext/reflection/tests/ReflectionClassConstant_getValue.phpt b/ext/reflection/tests/ReflectionClassConstant_getValue.phpt
new file mode 100644
index 0000000000..e447d15357
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClassConstant_getValue.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Test variations of getting constant values
+--FILE--
+<?php
+
+/* Use separate classes to make sure that in-place constant updates don't interfere */
+class A {
+ const X = self::Y * 2;
+ const Y = 1;
+}
+class B {
+ const X = self::Y * 2;
+ const Y = 1;
+}
+class C {
+ const X = self::Y * 2;
+ const Y = 1;
+}
+
+var_dump((new ReflectionClassConstant('A', 'X'))->getValue());
+echo new ReflectionClassConstant('B', 'X');
+echo new ReflectionClass('C');
+
+?>
+--EXPECTF--
+int(2)
+Constant [ public integer X ] { 2 }
+Class [ <user> class C ] {
+ @@ %s 12-15
+
+ - Constants [2] {
+ Constant [ public integer X ] { 2 }
+ Constant [ public integer Y ] { 1 }
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [0] {
+ }
+}
diff --git a/ext/reflection/tests/ReflectionClass_export_array_bug72222.phpt b/ext/reflection/tests/ReflectionClass_export_array_bug72222.phpt
index e64dc97109..9ccc285433 100644
--- a/ext/reflection/tests/ReflectionClass_export_array_bug72222.phpt
+++ b/ext/reflection/tests/ReflectionClass_export_array_bug72222.phpt
@@ -13,8 +13,8 @@ Class [ <user> class A ] {
@@ %s 2-5
- Constants [2] {
- Constant [ integer A ] { 8 }
- Constant [ array B ] { Array }
+ Constant [ public integer A ] { 8 }
+ Constant [ public array B ] { Array }
}
- Static properties [0] {
diff --git a/ext/reflection/tests/ReflectionClass_isArray.phpt b/ext/reflection/tests/ReflectionClass_isArray.phpt
new file mode 100644
index 0000000000..3eec0dac54
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_isArray.phpt
@@ -0,0 +1,24 @@
+--TEST--
+public bool ReflectionParameter::isArray ( void );
+--CREDITS--
+marcosptf - <marcosptf@yahoo.com.br> - @phpsp - sao paulo - br
+--FILE--
+<?php
+function testReflectionIsArray($a = null, $b = 0, array $c, $d=true, array $e, $f=1.5, $g="", array $h, $i="#F989898") {}
+
+$reflection = new ReflectionFunction('testReflectionIsArray');
+
+foreach ($reflection->getParameters() as $parameter) {
+ var_dump($parameter->isArray());
+}
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+bool(false)
diff --git a/ext/reflection/tests/ReflectionClass_newInstanceArgs_001.phpt b/ext/reflection/tests/ReflectionClass_newInstanceArgs_001.phpt
index d3a426de4c..3ad654dd84 100644
--- a/ext/reflection/tests/ReflectionClass_newInstanceArgs_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_newInstanceArgs_001.phpt
@@ -38,13 +38,27 @@ $rcC = new ReflectionClass('C');
$rcD = new ReflectionClass('D');
$rcE = new ReflectionClass('E');
-$a1 = $rcA->newInstanceArgs();
-$a2 = $rcA->newInstanceArgs(array('x'));
-var_dump($a1, $a2);
+try {
+ var_dump($rcA->newInstanceArgs());
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+try {
+ var_dump($rcA->newInstanceArgs(array('x')));
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
-$b1 = $rcB->newInstanceArgs();
-$b2 = $rcB->newInstanceArgs(array('x', 123));
-var_dump($b1, $b2);
+try {
+ var_dump($rcB->newInstanceArgs());
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+try {
+ var_dump($rcB->newInstanceArgs(array('x', 123)));
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
try {
$rcC->newInstanceArgs();
@@ -73,25 +87,15 @@ try {
--EXPECTF--
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in %s on line %d
In constructor of class A
-In constructor of class A
object(A)#%d (0) {
}
+In constructor of class A
object(A)#%d (0) {
}
-
-Warning: Missing argument 1 for B::__construct() in %s on line 9
-
-Warning: Missing argument 2 for B::__construct() in %s on line 9
-
-Notice: Undefined variable: a in %s on line 10
-
-Notice: Undefined variable: b in %s on line 10
-In constructor of class B with args ,
+Exception: Too few arguments to function B::__construct(), 0 passed and exactly 2 expected
In constructor of class B with args x, 123
object(B)#%d (0) {
}
-object(B)#%d (0) {
-}
Access to non-public constructor of class C
Access to non-public constructor of class D
object(E)#%d (0) {
diff --git a/ext/reflection/tests/ReflectionClass_newInstance_001.phpt b/ext/reflection/tests/ReflectionClass_newInstance_001.phpt
index afa278a9a1..e29cc8734f 100644
--- a/ext/reflection/tests/ReflectionClass_newInstance_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_newInstance_001.phpt
@@ -42,9 +42,16 @@ $a1 = $rcA->newInstance();
$a2 = $rcA->newInstance('x');
var_dump($a1, $a2);
-$b1 = $rcB->newInstance();
-$b2 = $rcB->newInstance('x', 123);
-var_dump($b1, $b2);
+try {
+ var_dump($rcB->newInstance());
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+try {
+ var_dump($rcB->newInstance('x', 123));
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
try {
$rcC->newInstance();
@@ -78,20 +85,10 @@ object(A)#%d (0) {
}
object(A)#%d (0) {
}
-
-Warning: Missing argument 1 for B::__construct() in %s on line 9
-
-Warning: Missing argument 2 for B::__construct() in %s on line 9
-
-Notice: Undefined variable: a in %s on line 10
-
-Notice: Undefined variable: b in %s on line 10
-In constructor of class B with args ,
+Exception: Too few arguments to function B::__construct(), 0 passed and exactly 2 expected
In constructor of class B with args x, 123
object(B)#%d (0) {
}
-object(B)#%d (0) {
-}
Access to non-public constructor of class C
Access to non-public constructor of class D
object(E)#%d (0) {
diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt
index b9a9b0d559..29d58420e3 100644
--- a/ext/reflection/tests/ReflectionClass_toString_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt
@@ -12,9 +12,9 @@ echo $rc;
Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
- Constants [3] {
- Constant [ integer IS_IMPLICIT_ABSTRACT ] { 16 }
- Constant [ integer IS_EXPLICIT_ABSTRACT ] { 32 }
- Constant [ integer IS_FINAL ] { 4 }
+ Constant [ public integer IS_IMPLICIT_ABSTRACT ] { 16 }
+ Constant [ public integer IS_EXPLICIT_ABSTRACT ] { 32 }
+ Constant [ public integer IS_FINAL ] { 4 }
}
- Static properties [0] {
@@ -34,7 +34,7 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
Property [ <default> public $name ]
}
- - Methods [50] {
+ - Methods [52] {
Method [ <internal:Reflection> final private method __clone ] {
- Parameters [0] {
@@ -175,6 +175,12 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
}
}
+ Method [ <internal:Reflection> public method getReflectionConstants ] {
+
+ - Parameters [0] {
+ }
+ }
+
Method [ <internal:Reflection> public method getConstant ] {
- Parameters [1] {
@@ -182,6 +188,13 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
}
}
+ Method [ <internal:Reflection> public method getReflectionConstant ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $name ]
+ }
+ }
+
Method [ <internal:Reflection> public method getInterfaces ] {
- Parameters [0] {
diff --git a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
index 4eda22a3f9..9b2122d1b9 100644
--- a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
+++ b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
@@ -9,7 +9,7 @@ var_dump($ext->getClasses());
?>
==DONE==
--EXPECT--
-array(14) {
+array(16) {
["ReflectionException"]=>
object(ReflectionClass)#2 (1) {
["name"]=>
@@ -50,33 +50,43 @@ array(14) {
["name"]=>
string(14) "ReflectionType"
}
- ["ReflectionMethod"]=>
+ ["ReflectionNamedType"]=>
object(ReflectionClass)#10 (1) {
["name"]=>
+ string(19) "ReflectionNamedType"
+ }
+ ["ReflectionMethod"]=>
+ object(ReflectionClass)#11 (1) {
+ ["name"]=>
string(16) "ReflectionMethod"
}
["ReflectionClass"]=>
- object(ReflectionClass)#11 (1) {
+ object(ReflectionClass)#12 (1) {
["name"]=>
string(15) "ReflectionClass"
}
["ReflectionObject"]=>
- object(ReflectionClass)#12 (1) {
+ object(ReflectionClass)#13 (1) {
["name"]=>
string(16) "ReflectionObject"
}
["ReflectionProperty"]=>
- object(ReflectionClass)#13 (1) {
+ object(ReflectionClass)#14 (1) {
["name"]=>
string(18) "ReflectionProperty"
}
+ ["ReflectionClassConstant"]=>
+ object(ReflectionClass)#15 (1) {
+ ["name"]=>
+ string(23) "ReflectionClassConstant"
+ }
["ReflectionExtension"]=>
- object(ReflectionClass)#14 (1) {
+ object(ReflectionClass)#16 (1) {
["name"]=>
string(19) "ReflectionExtension"
}
["ReflectionZendExtension"]=>
- object(ReflectionClass)#15 (1) {
+ object(ReflectionClass)#17 (1) {
["name"]=>
string(23) "ReflectionZendExtension"
}
diff --git a/ext/reflection/tests/ReflectionMethod_invokeArgs_error1.phpt b/ext/reflection/tests/ReflectionMethod_invokeArgs_error1.phpt
index ac97e3ed2a..c9d1e6379a 100644
--- a/ext/reflection/tests/ReflectionMethod_invokeArgs_error1.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invokeArgs_error1.phpt
@@ -25,12 +25,9 @@ var_dump($methodWithArgs->invokeArgs($testClassInstance, array()));
--EXPECTF--
Method with args:
-Warning: Missing argument 1 for TestClass::methodWithArgs() in %s on line %d
-
-Warning: Missing argument 2 for TestClass::methodWithArgs() in %s on line %d
-
-Notice: Undefined variable: a in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
-Called methodWithArgs(, )
-NULL
+Fatal error: Uncaught Error: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invokeArgs_error1.php:5
+Stack trace:
+#0 [internal function]: TestClass->methodWithArgs()
+#1 %sReflectionMethod_invokeArgs_error1.php(19): ReflectionMethod->invokeArgs(Object(TestClass), Array)
+#2 {main}
+ thrown in %sReflectionMethod_invokeArgs_error1.php on line 5
diff --git a/ext/reflection/tests/ReflectionMethod_invokeArgs_error3.phpt b/ext/reflection/tests/ReflectionMethod_invokeArgs_error3.phpt
index 513cc1845f..1222467a6b 100644
--- a/ext/reflection/tests/ReflectionMethod_invokeArgs_error3.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invokeArgs_error3.phpt
@@ -14,7 +14,11 @@ class TestClass {
public static function staticMethod() {
echo "Called staticMethod()\n";
- var_dump($this);
+ try {
+ var_dump($this);
+ } catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+ }
}
private static function privateMethod() {
@@ -103,9 +107,7 @@ NULL
Warning: ReflectionMethod::invokeArgs() expects parameter 1 to be object, boolean given in %s on line %d
NULL
Called staticMethod()
-
-Notice: Undefined variable: this in %s on line %d
-NULL
+Exception: Using $this when not in object context
NULL
Private method:
@@ -113,5 +115,4 @@ string(86) "Trying to invoke private method TestClass::privateMethod() from scop
Abstract method:
string(53) "Trying to invoke abstract method AbstractClass::foo()"
-
-Warning: ReflectionMethod::invokeArgs() expects exactly 2 parameters, 1 given in %s on line %d
+string(53) "Trying to invoke abstract method AbstractClass::foo()"
diff --git a/ext/reflection/tests/ReflectionMethod_invoke_basic.phpt b/ext/reflection/tests/ReflectionMethod_invoke_basic.phpt
index cbf358c062..7bfe245f82 100644
--- a/ext/reflection/tests/ReflectionMethod_invoke_basic.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invoke_basic.phpt
@@ -22,7 +22,11 @@ class TestClass {
public static function staticMethod() {
echo "Called staticMethod()\n";
- var_dump($this);
+ try {
+ var_dump($this);
+ } catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+ }
}
private static function privateMethod() {
@@ -93,15 +97,11 @@ Static method:
Warning: ReflectionMethod::invoke() expects at least 1 parameter, 0 given in %s on line %d
NULL
-Called staticMethod()
-Notice: Undefined variable: this in %s on line %d
-NULL
+Warning: ReflectionMethod::invoke() expects parameter 1 to be object, boolean given in %s on line %d
NULL
Called staticMethod()
-
-Notice: Undefined variable: this in %s on line %d
-NULL
+Exception: Using $this when not in object context
NULL
Method that throws an exception:
diff --git a/ext/reflection/tests/ReflectionMethod_invoke_error1.phpt b/ext/reflection/tests/ReflectionMethod_invoke_error1.phpt
index 758f1acd13..ef5621e7e5 100644
--- a/ext/reflection/tests/ReflectionMethod_invoke_error1.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invoke_error1.phpt
@@ -59,7 +59,9 @@ try {
?>
--EXPECTF--
invoke() on a non-object:
-string(29) "Non-object passed to Invoke()"
+
+Warning: ReflectionMethod::invoke() expects parameter 1 to be object, boolean given in %s%eReflectionMethod_invoke_error1.php on line %d
+NULL
invoke() on a non-instance:
string(72) "Given object is not an instance of the class this method was declared in"
diff --git a/ext/reflection/tests/ReflectionMethod_invoke_error2.phpt b/ext/reflection/tests/ReflectionMethod_invoke_error2.phpt
index a070c8f583..60a9ebae97 100644
--- a/ext/reflection/tests/ReflectionMethod_invoke_error2.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invoke_error2.phpt
@@ -21,12 +21,9 @@ var_dump($methodWithArgs->invoke($testClassInstance));
--EXPECTF--
Method with args:
-Warning: Missing argument 1 for TestClass::methodWithArgs() in %s on line %d
-
-Warning: Missing argument 2 for TestClass::methodWithArgs() in %s on line %d
-
-Notice: Undefined variable: a in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
-Called methodWithArgs(, )
-NULL
+Fatal error: Uncaught Error: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invoke_error2.php:5
+Stack trace:
+#0 [internal function]: TestClass->methodWithArgs()
+#1 %sReflectionMethod_invoke_error2.php(15): ReflectionMethod->invoke(Object(TestClass))
+#2 {main}
+ thrown in %sReflectionMethod_invoke_error2.php on line 5
diff --git a/ext/reflection/tests/ReflectionNamedType.phpt b/ext/reflection/tests/ReflectionNamedType.phpt
new file mode 100644
index 0000000000..1ce1222216
--- /dev/null
+++ b/ext/reflection/tests/ReflectionNamedType.phpt
@@ -0,0 +1,41 @@
+--TEST--
+ReflectionNamedType::getName() and ReflectionNamedType::__toString()
+--FILE--
+<?php
+
+function testInternalTypes(?Traversable $traversable): ?string {
+ return 'test';
+}
+
+function testUserDefinedTypes(?Test $traversable): ?Test {
+ return new Test;
+}
+
+$function = new ReflectionFunction('testInternalTypes');
+$type = $function->getParameters()[0]->getType();
+$return = $function->getReturnType();
+
+var_dump($type->getName());
+var_dump((string) $type);
+var_dump($return->getName());
+var_dump((string) $return);
+
+$function = new ReflectionFunction('testUserDefinedTypes');
+$type = $function->getParameters()[0]->getType();
+$return = $function->getReturnType();
+
+var_dump($type->getName());
+var_dump((string) $type);
+var_dump($return->getName());
+var_dump((string) $return);
+
+?>
+--EXPECTF--
+string(11) "Traversable"
+string(13) "?\Traversable"
+string(6) "string"
+string(7) "?string"
+string(4) "Test"
+string(6) "?\Test"
+string(4) "Test"
+string(6) "?\Test" \ No newline at end of file
diff --git a/ext/reflection/tests/ReflectionProperty_getValue_error.phpt b/ext/reflection/tests/ReflectionProperty_getValue_error.phpt
index 62009d8bb9..c9bf0b0f25 100644
--- a/ext/reflection/tests/ReflectionProperty_getValue_error.phpt
+++ b/ext/reflection/tests/ReflectionProperty_getValue_error.phpt
@@ -15,7 +15,7 @@ class AnotherClass {
}
$instance = new TestClass();
-$instanceWithNoProperties = new AnotherClass();
+$invalidInstance = new AnotherClass();
$propInfo = new ReflectionProperty('TestClass', 'pub2');
echo "Too few args:\n";
@@ -45,9 +45,9 @@ catch(Exception $exc) {
echo $exc->getMessage();
}
-echo "\n\nInstance without property:\n";
+echo "\n\nInvalid instance:\n";
$propInfo = new ReflectionProperty('TestClass', 'pub2');
-var_dump($propInfo->getValue($instanceWithNoProperties));
+var_dump($propInfo->getValue($invalidInstance));
?>
--EXPECTF--
@@ -77,7 +77,10 @@ string(15) "static property"
Protected property:
Cannot access non-public member TestClass::prot
-Instance without property:
+Invalid instance:
-Notice: Undefined property: AnotherClass::$pub2 in %s on line %d
-NULL
+Fatal error: Uncaught ReflectionException: Given object is not an instance of the class this property was declared in in %s:47
+Stack trace:
+#0 %s(47): ReflectionProperty->getValue(Object(AnotherClass))
+#1 {main}
+ thrown in %s on line 47
diff --git a/ext/reflection/tests/ReflectionType_001.phpt b/ext/reflection/tests/ReflectionType_001.phpt
index f764cf1519..c0ae24490c 100644
--- a/ext/reflection/tests/ReflectionType_001.phpt
+++ b/ext/reflection/tests/ReflectionType_001.phpt
@@ -79,7 +79,7 @@ foreach ([
bool(true)
bool(false)
bool(false)
-string(8) "stdClass"
+string(9) "\stdClass"
** Function 0 - Parameter 1
bool(true)
bool(false)
@@ -94,7 +94,7 @@ string(8) "callable"
bool(true)
bool(true)
bool(false)
-string(8) "stdClass"
+string(10) "?\stdClass"
** Function 0 - Parameter 4
bool(false)
** Function 0 - Parameter 5
@@ -121,19 +121,19 @@ string(5) "float"
bool(true)
bool(false)
bool(false)
-string(11) "NotExisting"
+string(12) "\NotExisting"
** Function 1 - Parameter 0
bool(true)
bool(false)
bool(false)
-string(4) "Test"
+string(5) "\Test"
*** methods
** Method 0 - parameter 0
bool(true)
bool(false)
bool(false)
-string(10) "SplSubject"
+string(11) "\SplSubject"
** Method 1 - parameter 0
bool(true)
bool(false)
@@ -148,7 +148,7 @@ string(6) "parent"
bool(true)
bool(false)
bool(false)
-string(4) "Test"
+string(5) "\Test"
*** return types
** Function/method return type 0
@@ -157,7 +157,7 @@ bool(false)
bool(true)
bool(false)
bool(false)
-string(8) "stdClass"
+string(9) "\stdClass"
** Function/method return type 2
bool(true)
bool(false)
@@ -177,9 +177,9 @@ string(6) "parent"
bool(true)
bool(false)
bool(false)
-string(4) "Test"
+string(5) "\Test"
** Function/method return type 6
bool(true)
bool(false)
bool(false)
-string(4) "Test"
+string(5) "\Test"
diff --git a/ext/reflection/tests/ReflectionType_002.phpt b/ext/reflection/tests/ReflectionType_002.phpt
index 8313862ec5..9c9c77b76b 100644
--- a/ext/reflection/tests/ReflectionType_002.phpt
+++ b/ext/reflection/tests/ReflectionType_002.phpt
@@ -12,6 +12,6 @@ unset($rm, $rp);
var_dump((string) $rt, (string) $rrt);
--EXPECT--
-string(4) "Test"
-string(5) "Test2"
+string(5) "\Test"
+string(6) "\Test2"
diff --git a/ext/reflection/tests/ReflectionType_possible_types.phpt b/ext/reflection/tests/ReflectionType_possible_types.phpt
new file mode 100644
index 0000000000..0db5b7c3f0
--- /dev/null
+++ b/ext/reflection/tests/ReflectionType_possible_types.phpt
@@ -0,0 +1,31 @@
+--TEST--
+ReflectionType possible types
+--FILE--
+<?php
+
+$functions = [
+ function(): void {},
+ function(): int {},
+ function(): float {},
+ function(): string {},
+ function(): bool {},
+ function(): array {},
+ function(): callable {},
+ function(): StdClass {}
+];
+
+foreach ($functions as $function) {
+ $reflectionFunc = new ReflectionFunction($function);
+ $returnType = $reflectionFunc->getReturnType();
+ var_dump($returnType->__toString());
+}
+?>
+--EXPECTF--
+string(4) "void"
+string(3) "int"
+string(5) "float"
+string(6) "string"
+string(4) "bool"
+string(5) "array"
+string(8) "callable"
+string(9) "\StdClass"
diff --git a/ext/reflection/tests/bug29986.phpt b/ext/reflection/tests/bug29986.phpt
index 4c4d629f39..f5aa62a00b 100644
--- a/ext/reflection/tests/bug29986.phpt
+++ b/ext/reflection/tests/bug29986.phpt
@@ -20,11 +20,11 @@ Class [ <user> class just_constants ] {
@@ %s %d-%d
- Constants [5] {
- Constant [ boolean BOOLEAN_CONSTANT ] { 1 }
- Constant [ null NULL_CONSTANT ] { }
- Constant [ string STRING_CONSTANT ] { This is a string }
- Constant [ integer INTEGER_CONSTANT ] { 1000 }
- Constant [ float FLOAT_CONSTANT ] { 3.14159265 }
+ Constant [ public boolean BOOLEAN_CONSTANT ] { 1 }
+ Constant [ public null NULL_CONSTANT ] { }
+ Constant [ public string STRING_CONSTANT ] { This is a string }
+ Constant [ public integer INTEGER_CONSTANT ] { 1000 }
+ Constant [ public float FLOAT_CONSTANT ] { 3.14159265 }
}
- Static properties [0] {
diff --git a/ext/reflection/tests/bug38217.phpt b/ext/reflection/tests/bug38217.phpt
index cf007d9547..988f1c8953 100644
--- a/ext/reflection/tests/bug38217.phpt
+++ b/ext/reflection/tests/bug38217.phpt
@@ -18,7 +18,11 @@ class Object1 {
}
$class= new ReflectionClass('Object1');
-var_dump($class->newInstanceArgs());
+try {
+ var_dump($class->newInstanceArgs());
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
var_dump($class->newInstanceArgs(array('test')));
@@ -27,13 +31,7 @@ echo "Done\n";
--EXPECTF--
object(Object)#%d (0) {
}
-
-Warning: Missing argument 1 for Object1::__construct() in %s on line %d
-
-Notice: Undefined variable: var in %s on line %d
-NULL
-object(Object1)#%d (0) {
-}
+Exception: Too few arguments to function Object1::__construct(), 0 passed and exactly 1 expected
string(4) "test"
object(Object1)#%d (0) {
}
diff --git a/ext/reflection/tests/bug45765.phpt b/ext/reflection/tests/bug45765.phpt
index b0c1be2c4c..7963a03eea 100644
--- a/ext/reflection/tests/bug45765.phpt
+++ b/ext/reflection/tests/bug45765.phpt
@@ -31,7 +31,7 @@ Object of class [ <user> class foo extends foo2 ] {
@@ %s 7-21
- Constants [1] {
- Constant [ string BAR ] { foo's bar }
+ Constant [ public string BAR ] { foo's bar }
}
- Static properties [0] {
diff --git a/ext/reflection/tests/bug72661.phpt b/ext/reflection/tests/bug72661.phpt
new file mode 100644
index 0000000000..40d14922b8
--- /dev/null
+++ b/ext/reflection/tests/bug72661.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #72661 (ReflectionType::__toString crashes with iterable)
+--FILE--
+<?php
+function test(iterable $arg) { }
+
+var_dump((string)(new ReflectionParameter("test", 0))->getType());
+?>
+--EXPECT--
+string(8) "iterable"
diff --git a/ext/reflection/tests/bug72846.phpt b/ext/reflection/tests/bug72846.phpt
deleted file mode 100644
index ab8b6cac79..0000000000
--- a/ext/reflection/tests/bug72846.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-Bug #72846 (getConstant for a array constant with constant values returns NULL/NFC/UKNOWN)
---FILE--
-<?php
-
-namespace Some {
-
- abstract class A
- {
- const ONE = '1';
- const TWO = '2';
-
- const CONST_NUMBERS = [
- self::ONE,
- self::TWO,
- ];
-
- const NUMBERS = [
- '1',
- '2',
- ];
- }
-
- class B extends A
- {
- }
-
- $ref = new \ReflectionClass('Some\B');
-
- var_dump($ref->getConstant('ONE'));
- var_dump($ref->getConstant('CONST_NUMBERS'));
- var_dump($ref->getConstant('NUMBERS'));
-}
-?>
---EXPECT--
-string(1) "1"
-array(2) {
- [0]=>
- string(1) "1"
- [1]=>
- string(1) "2"
-}
-array(2) {
- [0]=>
- string(1) "1"
- [1]=>
- string(1) "2"
-}
diff --git a/ext/reflection/tests/request38992.phpt b/ext/reflection/tests/request38992.phpt
new file mode 100644
index 0000000000..8c0052fd85
--- /dev/null
+++ b/ext/reflection/tests/request38992.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Request #38992 (invoke() and invokeArgs() static method calls should match)
+--FILE--
+<?php
+class MyClass
+{
+ public static function doSomething()
+ {
+ echo "Did it!\n";
+ }
+}
+
+$r = new ReflectionMethod('MyClass', 'doSomething');
+$r->invoke('WTF?');
+$r->invokeArgs('WTF?', array());
+?>
+===DONE===
+--EXPECTF--
+Warning: ReflectionMethod::invoke() expects parameter 1 to be object, string given in %s%erequest38992.php on line %d
+
+Warning: ReflectionMethod::invokeArgs() expects parameter 1 to be object, string given in %s%erequest38992.php on line %d
+===DONE===