summaryrefslogtreecommitdiff
path: root/ext/reflection/php_reflection.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/reflection/php_reflection.c')
-rw-r--r--ext/reflection/php_reflection.c1160
1 files changed, 840 insertions, 320 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index a73b67026..b96e86a44 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -39,11 +39,16 @@
#include "zend_ini.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
+#include "zend_extensions.h"
-/* Undefine "getParameters" macro defined in "main/php3_compat.h" */
-#ifdef getParameters
-# undef getParameters
-#endif
+#define reflection_update_property(object, name, value) do { \
+ zval *member; \
+ MAKE_STD_ZVAL(member); \
+ ZVAL_STRINGL(member, name, sizeof(name)-1, 1); \
+ zend_std_write_property(object, member, value, NULL TSRMLS_CC); \
+ Z_DELREF_P(value); \
+ zval_ptr_dtor(&member); \
+ } while (0)
/* Class entry pointers */
PHPAPI zend_class_entry *reflector_ptr;
@@ -57,6 +62,7 @@ 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_extension_ptr;
+PHPAPI zend_class_entry *reflection_zend_extension_ptr;
#if MBO_0
ZEND_BEGIN_MODULE_GLOBALS(reflection)
@@ -119,7 +125,7 @@ static void string_init(string *str)
str->alloced = 1024;
*str->string = '\0';
}
-
+
static string *string_printf(string *str, const char *format, ...)
{
int len;
@@ -172,6 +178,8 @@ static void string_free(string *str)
}
/* }}} */
+/* {{{ Object structure */
+
/* Struct for properties */
typedef struct _property_reference {
zend_class_entry *ce;
@@ -204,9 +212,11 @@ typedef struct {
unsigned int ignore_visibility:1;
} reflection_object;
+/* }}} */
+
static zend_object_handlers reflection_object_handlers;
-static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC)
+static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */
{
zval **value;
@@ -216,6 +226,7 @@ static void _default_get_entry(zval *object, char *name, int name_len, zval *ret
MAKE_COPY_ZVAL(value, return_value);
}
+/* }}} */
#ifdef ilia_0
static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value TSRMLS_DC) /* {{{ */
@@ -231,13 +242,14 @@ static void _default_lookup_entry(zval *object, char *name, int name_len, zval *
/* }}} */
#endif
-static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC)
+static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC) /* {{{ */
{
zend_uint num_interfaces = ++class_entry->num_interfaces;
class_entry->interfaces = (zend_class_entry **) realloc(class_entry->interfaces, sizeof(zend_class_entry *) * num_interfaces);
class_entry->interfaces[num_interfaces - 1] = interface_entry;
}
+/* }}} */
static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
{
@@ -263,13 +275,13 @@ static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
&& fptr->type == ZEND_INTERNAL_FUNCTION
&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
{
- efree(fptr->internal_function.function_name);
+ efree((char*)fptr->internal_function.function_name);
efree(fptr);
}
}
/* }}} */
-static void reflection_free_objects_storage(void *object TSRMLS_DC)
+static void reflection_free_objects_storage(void *object TSRMLS_DC) /* {{{ */
{
reflection_object *intern = (reflection_object *) object;
parameter_reference *reference;
@@ -290,7 +302,7 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
break;
case REF_TYPE_DYNAMIC_PROPERTY:
prop_reference = (property_reference*)intern->ptr;
- efree(prop_reference->prop.name);
+ efree((char*)prop_reference->prop.name);
efree(intern->ptr);
break;
case REF_TYPE_OTHER:
@@ -303,10 +315,10 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
}
zend_objects_free_object_storage(object TSRMLS_CC);
}
+/* }}} */
-static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
+static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- zval tmp;
zend_object_value retval;
reflection_object *intern;
@@ -314,13 +326,14 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->zo.ce = class_type;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
return retval;
}
+/* }}} */
-static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
+static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) /* {{{ */
{
if (!object) {
ALLOC_ZVAL(object);
@@ -331,36 +344,44 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_
Z_SET_ISREF_P(object);
return object;
}
+/* }}} */
static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
-static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char *indent TSRMLS_DC);
+static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC);
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
+static void _zend_extension_string(string *str, zend_extension *extension, char *indent TSRMLS_DC);
/* {{{ _class_string */
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
{
int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
string sub_indent;
-
+
string_init(&sub_indent);
string_printf(&sub_indent, "%s ", indent);
/* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
- if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
- string_printf(str, "%s%s", indent, ce->doc_comment);
+ if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+ string_printf(str, "%s%s", indent, ce->info.user.doc_comment);
string_write(str, "\n", 1);
}
if (obj) {
string_printf(str, "%sObject of class [ ", indent);
} else {
- string_printf(str, "%s%s [ ", indent, (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : "Class");
+ char *kind = "Class";
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ kind = "Interface";
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ kind = "Trait";
+ }
+ string_printf(str, "%s%s [ ", indent, kind);
}
string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
- if (ce->module) {
- string_printf(str, ":%s", ce->module->name);
+ if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
+ string_printf(str, ":%s", ce->info.internal.module->name);
}
string_printf(str, "> ");
if (ce->get_iterator != NULL) {
@@ -368,13 +389,15 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
string_printf(str, "interface ");
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ string_printf(str, "trait ");
} else {
if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
string_printf(str, "abstract ");
}
if (ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
string_printf(str, "final ");
- }
+ }
string_printf(str, "class ");
}
string_printf(str, "%s", ce->name);
@@ -398,8 +421,8 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
/* The information where a class is declared is only available for user classes */
if (ce->type == ZEND_USER_CLASS) {
- string_printf(str, "%s @@ %s %d-%d\n", indent, ce->filename,
- ce->line_start, ce->line_end);
+ string_printf(str, "%s @@ %s %d-%d\n", indent, ce->info.user.filename,
+ ce->info.user.line_start, ce->info.user.line_end);
}
/* Constants */
@@ -429,7 +452,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
/* Static properties */
if (&ce->properties_info) {
- /* counting static properties */
+ /* counting static properties */
count = zend_hash_num_elements(&ce->properties_info);
if (count > 0) {
HashPosition pos;
@@ -447,7 +470,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
}
- /* static properties */
+ /* static properties */
string_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
if (count_static_props > 0) {
HashPosition pos;
@@ -465,10 +488,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "%s }\n", indent);
}
-
+
/* Static methods */
if (&ce->function_table) {
- /* counting static methods */
+ /* counting static methods */
count = zend_hash_num_elements(&ce->function_table);
if (count > 0) {
HashPosition pos;
@@ -486,7 +509,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
}
- /* static methods */
+ /* static methods */
string_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
if (count_static_funcs > 0) {
HashPosition pos;
@@ -550,7 +573,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
if (prop_name_size && prop_name[0]) { /* skip all private and protected properties */
if (!zend_hash_quick_exists(&ce->properties_info, prop_name, prop_name_size, zend_get_hash_value(prop_name, prop_name_size))) {
count++;
- _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);
+ _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);
}
}
efree(prop_name);
@@ -621,7 +644,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "%s }\n", indent);
}
-
+
string_printf(str, "%s}\n", indent);
string_free(&sub_indent);
}
@@ -659,7 +682,7 @@ static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
++offset;
while (op < end) {
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
- && op->op1.u.constant.value.lval == (long)offset)
+ && op->op1.num == (long)offset)
{
return op;
}
@@ -683,8 +706,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
- } else if (arg_info->array_type_hint) {
- string_printf(str, "array ");
+ } else if (arg_info->type_hint) {
+ string_printf(str, "%s ", zend_get_type_by_const(arg_info->type_hint));
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@@ -699,12 +722,12 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
}
if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
- if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+ if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
zval *zv, zv_copy;
int use_copy;
string_write(str, " = ", sizeof(" = ")-1);
ALLOC_ZVAL(zv);
- *zv = precv->op2.u.constant;
+ *zv = *precv->op2.zv;
zval_copy_ctor(zv);
INIT_PZVAL(zv);
zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
@@ -723,6 +746,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "...", sizeof("...")-1);
}
string_write(str, "'", sizeof("'")-1);
+ } else if (Z_TYPE_P(zv) == IS_ARRAY) {
+ string_write(str, "Array", sizeof("Array")-1);
} else {
zend_make_printable_zval(zv, &zv_copy, &use_copy);
string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
@@ -802,7 +827,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
unsigned int lc_name_len;
/* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
- * What's "wrong" is that any whitespace before the doc comment start is
+ * What's "wrong" is that any whitespace before the doc comment start is
* swallowed, leading to an unaligned comment.
*/
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
@@ -875,13 +900,13 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
string_printf(str, "function ");
}
- if (fptr->op_array.return_reference) {
+ if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
string_printf(str, "&");
}
string_printf(str, "%s ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
- string_printf(str, "%s @@ %s %d - %d\n", indent,
+ string_printf(str, "%s @@ %s %d - %d\n", indent,
fptr->op_array.filename,
fptr->op_array.line_start,
fptr->op_array.line_end);
@@ -900,7 +925,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
/* {{{ _property_string */
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC)
{
- char *class_name;
+ const char *class_name;
string_printf(str, "%sProperty [ ", indent);
if (!prop) {
@@ -913,7 +938,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_write(str, "<default> ", sizeof("<default> ") - 1);
}
}
-
+
/* These are mutually exclusive */
switch (prop->flags & ZEND_ACC_PPP_MASK) {
case ZEND_ACC_PUBLIC:
@@ -930,7 +955,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
- zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
+ zend_unmangle_property_name(prop->name, prop->name_length, &class_name, (const char**)&prop_name);
string_printf(str, "$%s", prop_name);
}
@@ -938,7 +963,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
}
/* }}} */
-static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
@@ -972,23 +997,25 @@ static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_ar
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
-static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
int *num_classes = va_arg(args, int*);
- if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+ if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
string_printf(str, "\n");
_class_string(str, *pce, NULL, indent TSRMLS_CC);
(*num_classes)++;
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
-static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
@@ -1001,6 +1028,7 @@ static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_ar
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
/* {{{ _extension_string */
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC)
@@ -1023,7 +1051,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
while(dep->name) {
string_printf(str, "%s Dependency [ %s (", indent, dep->name);
-
+
switch(dep->type) {
case MODULE_DEP_REQUIRED:
string_write(str, "Required", sizeof("Required") - 1);
@@ -1039,10 +1067,10 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
break;
}
- if (dep->rel) {
+ if (dep->rel) {
string_printf(str, " %s", dep->rel);
}
- if (dep->version) {
+ if (dep->version) {
string_printf(str, " %s", dep->version);
}
string_write(str, ") ]\n", sizeof(") ]\n") - 1);
@@ -1066,7 +1094,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
{
string str_constants;
int num_constants = 0;
-
+
string_init(&str_constants);
zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
if (num_constants) {
@@ -1087,26 +1115,26 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
while (func->fname) {
int fname_len = strlen(func->fname);
char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
-
- if (zend_hash_find(EG(function_table), lc_name, fname_len+1, (void**) &fptr) == FAILURE) {
+
+ if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
func++;
efree(lc_name);
continue;
}
-
+
_function_string(str, fptr, NULL, " " TSRMLS_CC);
efree(lc_name);
func++;
}
string_printf(str, "%s }\n", indent);
}
-
+
{
string str_classes;
string sub_indent;
int num_classes = 0;
-
+
string_init(&sub_indent);
string_printf(&sub_indent, "%s ", indent);
string_init(&str_classes);
@@ -1124,6 +1152,27 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
}
/* }}} */
+static void _zend_extension_string(string *str, zend_extension *extension, char *indent TSRMLS_DC) /* {{{ */
+{
+ string_printf(str, "%sZend Extension [ %s ", indent, extension->name);
+
+ if (extension->version) {
+ string_printf(str, "%s ", extension->version);
+ }
+ if (extension->copyright) {
+ string_printf(str, "%s ", extension->copyright);
+ }
+ if (extension->author) {
+ string_printf(str, "by %s ", extension->author);
+ }
+ if (extension->URL) {
+ string_printf(str, "<%s> ", extension->URL);
+ }
+
+ string_printf(str, "]\n");
+}
+/* }}} */
+
/* {{{ _function_check_flag */
static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
{
@@ -1151,7 +1200,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR
intern->ptr = ce;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = ce;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1180,7 +1229,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1211,7 +1260,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
intern->ref_type = REF_TYPE_PARAMETER;
intern->ce = fptr->common.scope;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1233,7 +1282,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = NULL;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1257,8 +1306,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
+ reflection_update_property(object, "class", classname);
}
/* }}} */
@@ -1269,7 +1318,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
zval *name;
zval *classname;
property_reference *reference;
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
@@ -1304,8 +1353,8 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
intern->ref_type = REF_TYPE_PROPERTY;
intern->ce = ce;
intern->ignore_visibility = 0;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
+ reflection_update_property(object, "class", classname);
}
/* }}} */
@@ -1361,7 +1410,7 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c
fcc.object_ptr = reflector_ptr;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
@@ -1536,10 +1585,10 @@ ZEND_METHOD(reflection_function, __construct)
nsname = &lcname[1];
name_len--;
}
-
+
if (zend_hash_find(EG(function_table), nsname, name_len + 1, (void **)&fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", name_str);
return;
}
@@ -1550,7 +1599,7 @@ ZEND_METHOD(reflection_function, __construct)
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, fptr->common.function_name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
intern->ptr = fptr;
intern->ref_type = REF_TYPE_FUNCTION;
intern->obj = closure;
@@ -1602,6 +1651,65 @@ ZEND_METHOD(reflection_function, isClosure)
}
/* }}} */
+/* {{{ proto public bool ReflectionFunction::getClosureThis()
+ Returns this pointer bound to closure */
+ZEND_METHOD(reflection_function, getClosureThis)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+ zval* closure_this;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+ if (intern->obj) {
+ closure_this = zend_get_closure_this_ptr(intern->obj TSRMLS_CC);
+ if (closure_this) {
+ RETURN_ZVAL(closure_this, 1, 0);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
+ Returns the scope associated to the closure */
+ZEND_METHOD(reflection_function, getClosureScopeClass)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+ const zend_function *closure_func;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+ if (intern->obj) {
+ closure_func = zend_get_closure_method_def(intern->obj TSRMLS_CC);
+ if (closure_func && closure_func->common.scope) {
+ zend_reflection_class_factory(closure_func->common.scope, return_value TSRMLS_CC);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionFunction::getClosure()
+ Returns a dynamically created closure for the function */
+ZEND_METHOD(reflection_function, getClosure)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+
+ zend_create_closure(return_value, fptr, NULL, NULL TSRMLS_CC);
+}
+/* }}} */
+
+
/* {{{ proto public bool ReflectionFunction::isInternal()
Returns whether this is an internal function */
ZEND_METHOD(reflection_function, isInternal)
@@ -1724,7 +1832,7 @@ ZEND_METHOD(reflection_function, getStaticVariables)
zval *tmp_copy;
reflection_object *intern;
zend_function *fptr;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -1750,7 +1858,7 @@ ZEND_METHOD(reflection_function, invoke)
zend_fcall_info_cache fcc;
reflection_object *intern;
zend_function *fptr;
-
+
METHOD_NOTSTATIC(reflection_function_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
@@ -1781,7 +1889,7 @@ ZEND_METHOD(reflection_function, invoke)
}
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
return;
}
@@ -1811,7 +1919,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
reflection_object *intern;
zend_function *fptr;
zval *param_array;
-
+
METHOD_NOTSTATIC(reflection_function_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
@@ -1820,9 +1928,9 @@ ZEND_METHOD(reflection_function, invokeArgs)
}
argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-
+
params = safe_emalloc(sizeof(zval **), argc, 0);
- zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
fci.size = sizeof(fci);
@@ -1846,7 +1954,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
efree(params);
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
return;
}
@@ -1867,7 +1975,7 @@ ZEND_METHOD(reflection_function, returnsReference)
METHOD_NOTSTATIC(reflection_function_abstract_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
- RETURN_BOOL(fptr->op_array.return_reference);
+ RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
}
/* }}} */
@@ -1915,7 +2023,7 @@ ZEND_METHOD(reflection_function, getParameters)
array_init(return_value);
for (i = 0; i < fptr->common.num_args; i++) {
- zval *parameter;
+ zval *parameter;
ALLOC_ZVAL(parameter);
reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), intern->obj, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
@@ -2006,7 +2114,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (intern == NULL) {
return;
}
-
+
/* First, find the function */
switch (Z_TYPE_P(reference)) {
case IS_STRING: {
@@ -2017,7 +2125,7 @@ ZEND_METHOD(reflection_parameter, __construct)
lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
if (zend_hash_find(EG(function_table), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", Z_STRVAL_P(reference));
return;
}
@@ -2032,7 +2140,7 @@ ZEND_METHOD(reflection_parameter, __construct)
zend_class_entry **pce;
unsigned int lcname_len;
char *lcname;
-
+
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE))
{
@@ -2051,7 +2159,7 @@ ZEND_METHOD(reflection_parameter, __construct)
}
ce = *pce;
}
-
+
convert_to_string_ex(method);
lcname_len = Z_STRLEN_PP(method);
lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), lcname_len);
@@ -2060,21 +2168,21 @@ ZEND_METHOD(reflection_parameter, __construct)
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
&& (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
{
- /* nothign to do. don't set is_closure since is the invoke handler,
- not the closure itself */
+ /* nothing to do. don't set is_closure since is the invoke handler,
+- not the closure itself */
} else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, Z_STRVAL_PP(method));
return;
}
efree(lcname);
}
break;
-
+
case IS_OBJECT: {
ce = Z_OBJCE_P(reference);
-
+
if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
fptr = (zend_function *)zend_get_closure_method_def(reference TSRMLS_CC);
Z_ADDREF_P(reference);
@@ -2086,12 +2194,12 @@ ZEND_METHOD(reflection_parameter, __construct)
}
}
break;
-
+
default:
_DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
/* returns out of this function */
}
-
+
/* Now, search for the parameter */
arg_info = fptr->common.arg_info;
if (Z_TYPE_PP(parameter) == IS_LONG) {
@@ -2099,7 +2207,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fptr->common.function_name);
+ efree((char*)fptr->common.function_name);
}
efree(fptr);
}
@@ -2123,7 +2231,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (position == -1) {
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fptr->common.function_name);
+ efree((char*)fptr->common.function_name);
}
efree(fptr);
}
@@ -2134,14 +2242,14 @@ ZEND_METHOD(reflection_parameter, __construct)
/* returns out of this function */
}
}
-
+
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
} else {
ZVAL_NULL(name);
}
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
ref->arg_info = &arg_info[position];
@@ -2221,7 +2329,7 @@ ZEND_METHOD(reflection_parameter, getDeclaringClass)
if (param->fptr->common.scope) {
zend_reflection_class_factory(param->fptr->common.scope, return_value TSRMLS_CC);
- }
+ }
}
/* }}} */
@@ -2251,29 +2359,29 @@ ZEND_METHOD(reflection_parameter, getClass)
* TODO: Think about moving these checks to the compiler or some sort of
* lint-mode.
*/
- if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) {
+ if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "self", sizeof("self")- 1)) {
ce = param->fptr->common.scope;
if (!ce) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'self' as type hint but function is not a class member!");
return;
}
pce= &ce;
- } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) {
+ } else if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "parent", sizeof("parent")- 1)) {
ce = param->fptr->common.scope;
if (!ce) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'parent' as type hint but function is not a class member!");
return;
}
if (!ce->parent) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'parent' as type hint although class does not have a parent!");
return;
}
pce= &ce->parent;
} else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", param->arg_info->class_name);
return;
}
@@ -2294,7 +2402,23 @@ ZEND_METHOD(reflection_parameter, isArray)
}
GET_REFLECTION_OBJECT_PTR(param);
- RETVAL_BOOL(param->arg_info->array_type_hint);
+ RETVAL_BOOL(param->arg_info->type_hint == IS_ARRAY);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::isCallable()
+ Returns whether parameter MUST be callable */
+ZEND_METHOD(reflection_parameter, isCallable)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(param->arg_info->type_hint == IS_CALLABLE);
}
/* }}} */
@@ -2330,6 +2454,23 @@ ZEND_METHOD(reflection_parameter, isPassedByReference)
}
/* }}} */
+/* {{{ proto public bool ReflectionParameter::canBePassedByValue()
+ Returns whether this parameter can be passed by value */
+ZEND_METHOD(reflection_parameter, canBePassedByValue)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
+ RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionParameter::getPosition()
Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter, getPosition)
@@ -2383,7 +2524,7 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
RETURN_FALSE;
}
precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
- if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+ if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
RETURN_FALSE;
}
RETURN_TRUE;
@@ -2409,16 +2550,16 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
return;
}
if (param->offset < param->required) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional");
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional");
return;
}
precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
- if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error");
+ if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error");
return;
}
- *return_value = precv->op2.u.constant;
+ *return_value = *precv->op2.zv;
INIT_PZVAL(return_value);
if (Z_TYPE_P(return_value) != IS_CONSTANT && Z_TYPE_P(return_value) != IS_CONSTANT_ARRAY) {
zval_copy_ctor(return_value);
@@ -2455,7 +2596,7 @@ ZEND_METHOD(reflection_method, __construct)
return;
}
if ((tmp = strstr(name_str, "::")) == NULL) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str);
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str);
return;
}
classname = &ztmp;
@@ -2475,13 +2616,13 @@ ZEND_METHOD(reflection_method, __construct)
if (intern == NULL) {
return;
}
-
+
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %s does not exist", Z_STRVAL_P(classname));
if (classname == &ztmp) {
zval_dtor(&ztmp);
}
@@ -2515,7 +2656,7 @@ ZEND_METHOD(reflection_method, __construct)
/* do nothing, mptr already set */
} else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, name_str);
return;
}
@@ -2524,11 +2665,11 @@ ZEND_METHOD(reflection_method, __construct)
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
-
+ reflection_update_property(object, "class", classname);
+
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, mptr->common.function_name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
intern->ptr = mptr;
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce;
@@ -2553,6 +2694,41 @@ ZEND_METHOD(reflection_method, __toString)
}
/* }}} */
+/* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
+ Invokes the function */
+ZEND_METHOD(reflection_method, getClosure)
+{
+ reflection_object *intern;
+ zval *obj;
+ zend_function *mptr;
+
+ METHOD_NOTSTATIC(reflection_method_ptr);
+ GET_REFLECTION_OBJECT_PTR(mptr);
+
+ if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_create_closure(return_value, mptr, mptr->common.scope, NULL TSRMLS_CC);
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+ return;
+ }
+
+ if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope TSRMLS_CC)) {
+ _DO_THROW("Given object is not an instance of the class this method was declared in");
+ /* Returns from this function */
+ }
+
+ /* This is an original closure object and __invoke is to be called. */
+ if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
+ (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+ {
+ RETURN_ZVAL(obj, 1, 0);
+ } else {
+ zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
Invokes the method. */
ZEND_METHOD(reflection_method, invoke)
@@ -2566,7 +2742,7 @@ ZEND_METHOD(reflection_method, invoke)
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
-
+
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
@@ -2576,12 +2752,12 @@ ZEND_METHOD(reflection_method, invoke)
&& intern->ignore_visibility == 0)
{
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Trying to invoke abstract method %s::%s()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %s::%s() from scope %s",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2592,7 +2768,7 @@ ZEND_METHOD(reflection_method, invoke)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &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.
@@ -2618,10 +2794,10 @@ ZEND_METHOD(reflection_method, invoke)
_DO_THROW("Given object is not an instance of the class this method was declared in");
/* Returns from this function */
}
-
+
object_ptr = *params[0];
}
-
+
fci.size = sizeof(fci);
fci.function_table = NULL;
fci.function_name = NULL;
@@ -2639,13 +2815,13 @@ ZEND_METHOD(reflection_method, invoke)
fcc.object_ptr = object_ptr;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
if (params) {
efree(params);
}
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2671,7 +2847,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
zval *param_array;
-
+
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
@@ -2685,12 +2861,12 @@ ZEND_METHOD(reflection_method, invokeArgs)
&& intern->ignore_visibility == 0)
{
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Trying to invoke abstract method %s::%s()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %s::%s() from scope %s",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2699,11 +2875,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
}
argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-
+
params = safe_emalloc(sizeof(zval **), argc, 0);
- zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
-
+
/* 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.
@@ -2717,11 +2893,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke non static method %s::%s() without an object",
+ "Trying to invoke non static method %s::%s() without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
-
+
obj_ce = Z_OBJCE_P(object);
if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
@@ -2730,7 +2906,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
/* Returns from this function */
}
}
-
+
fci.size = sizeof(fci);
fci.function_table = NULL;
fci.function_name = NULL;
@@ -2748,11 +2924,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
fcc.object_ptr = object;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
efree(params);
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2824,7 +3000,7 @@ ZEND_METHOD(reflection_function, isDeprecated)
ZEND_METHOD(reflection_function, inNamespace)
{
zval **name;
- char *colon;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2833,8 +3009,8 @@ ZEND_METHOD(reflection_function, inNamespace)
RETURN_FALSE;
}
if (Z_TYPE_PP(name) == IS_STRING
- && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
- && colon > Z_STRVAL_PP(name))
+ && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
+ && backslash > Z_STRVAL_PP(name))
{
RETURN_TRUE;
}
@@ -2847,7 +3023,7 @@ ZEND_METHOD(reflection_function, inNamespace)
ZEND_METHOD(reflection_function, getNamespaceName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2870,7 +3046,7 @@ ZEND_METHOD(reflection_function, getNamespaceName)
ZEND_METHOD(reflection_function, getShortName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2899,7 +3075,7 @@ ZEND_METHOD(reflection_method, isConstructor)
return;
}
GET_REFLECTION_OBJECT_PTR(mptr);
- /* we need to check if the ctor is the ctor of the class level we we
+ /* we need to check if the ctor is the ctor of the class level we we
* looking at since we might be looking at an inherited old style ctor
* defined in base class. */
RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
@@ -2946,7 +3122,7 @@ ZEND_METHOD(reflection_method, getDeclaringClass)
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -2964,13 +3140,13 @@ ZEND_METHOD(reflection_method, getPrototype)
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
if (!mptr->common.prototype) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s does not have a prototype", intern->ce->name, mptr->common.function_name);
return;
}
@@ -3032,17 +3208,17 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (intern == NULL) {
return;
}
-
+
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", classname);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
intern->obj = argument;
zval_add_ref(&argument);
}
- } else {
+ } else {
convert_to_string_ex(&argument);
if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
@@ -3053,7 +3229,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", classname);
intern->ptr = *ce;
}
@@ -3069,49 +3245,74 @@ ZEND_METHOD(reflection_class, __construct)
}
/* }}} */
+/* {{{ add_class_vars */
+static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
+{
+ HashPosition pos;
+ zend_property_info *prop_info;
+ zval *prop, *prop_copy;
+ char *key;
+ uint key_len;
+ ulong num_index;
+
+ zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
+ zend_hash_move_forward_ex(&ce->properties_info, &pos);
+ if (((prop_info->flags & ZEND_ACC_SHADOW) &&
+ prop_info->ce != ce) ||
+ ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ !zend_check_protected(prop_info->ce, ce)) ||
+ ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+ prop_info->ce != ce)) {
+ continue;
+ }
+ prop = NULL;
+ if (prop_info->offset >= 0) {
+ if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
+ prop = ce->default_static_members_table[prop_info->offset];
+ } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
+ prop = ce->default_properties_table[prop_info->offset];
+ }
+ }
+ if (!prop) {
+ continue;
+ }
+
+ /* copy: enforce read only access */
+ ALLOC_ZVAL(prop_copy);
+ *prop_copy = *prop;
+ zval_copy_ctor(prop_copy);
+ INIT_PZVAL(prop_copy);
+
+ /* this is necessary to make it able to work with default array
+ * properties, returned to user */
+ if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
+ }
+
+ add_assoc_zval(return_value, key, prop_copy);
+ }
+}
+/* }}} */
+
/* {{{ proto public array ReflectionClass::getStaticProperties()
Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class, getStaticProperties)
{
reflection_object *intern;
zend_class_entry *ce;
- HashPosition pos;
- zval **value;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
array_init(return_value);
-
- zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
-
- while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
- uint key_len;
- char *key;
- ulong num_index;
-
- if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
- char *prop_name, *class_name;
- zval *prop_copy;
-
- zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
-
- /* filter privates from base classes */
- if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
- /* copy: enforce read only access */
- ALLOC_ZVAL(prop_copy);
- MAKE_COPY_ZVAL(value, prop_copy);
-
- add_assoc_zval(return_value, prop_name, prop_copy);
- }
- }
- zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
- }
+ add_class_vars(ce, 1, return_value TSRMLS_CC);
}
/* }}} */
@@ -3124,7 +3325,7 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
char *name;
int name_len;
zval **prop, *def_value = NULL;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &name, &name_len, &def_value) == FAILURE) {
return;
}
@@ -3132,12 +3333,12 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
- prop = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
+ prop = zend_std_get_static_property(ce, name, name_len, 1, NULL TSRMLS_CC);
if (!prop) {
if (def_value) {
RETURN_ZVAL(def_value, 1, 0);
} else {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not have a property named %s", ce->name, name);
}
return;
@@ -3158,7 +3359,7 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
zval **variable_ptr, *value;
int refcount;
zend_uchar is_ref;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value) == FAILURE) {
return;
}
@@ -3166,12 +3367,12 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
- variable_ptr = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
+ variable_ptr = zend_std_get_static_property(ce, name, name_len, 1, NULL TSRMLS_CC);
if (!variable_ptr) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not have a property named %s", ce->name, name);
return;
- }
+ }
refcount = Z_REFCOUNT_PP(variable_ptr);
is_ref = Z_ISREF_PP(variable_ptr);
zval_dtor(*variable_ptr);
@@ -3189,51 +3390,15 @@ ZEND_METHOD(reflection_class, getDefaultProperties)
{
reflection_object *intern;
zend_class_entry *ce;
- int count, i;
- HashTable *ht_list[3];
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
-
zend_update_class_constants(ce TSRMLS_CC);
-
- ht_list[0] = CE_STATIC_MEMBERS(ce);
- ht_list[1] = &ce->default_properties;
- ht_list[2] = NULL;
-
- for (i = 0; ht_list[i] != NULL; i++) {
-
- count = zend_hash_num_elements(ht_list[i]);
- if (count > 0) {
- HashPosition pos;
- zval **prop;
-
- zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
- while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
- char *key, *class_name, *prop_name;
- uint key_len;
- ulong num_index;
- zval *prop_copy;
-
- zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
- zend_hash_move_forward_ex(ht_list[i], &pos);
- zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
- if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
- /* filter privates from base classes */
- continue;
- }
-
- /* copy: enforce read only access */
- ALLOC_ZVAL(prop_copy);
- MAKE_COPY_ZVAL(prop, prop_copy);
-
- add_assoc_zval(return_value, prop_name, prop_copy);
- }
- }
- }
+ add_class_vars(ce, 1, return_value TSRMLS_CC);
+ add_class_vars(ce, 0, return_value TSRMLS_CC);
}
/* }}} */
@@ -3308,7 +3473,7 @@ ZEND_METHOD(reflection_class, getFileName)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_CLASS) {
- RETURN_STRING(ce->filename, 1);
+ RETURN_STRING(ce->info.user.filename, 1);
}
RETURN_FALSE;
}
@@ -3326,7 +3491,7 @@ ZEND_METHOD(reflection_class, getStartLine)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_FUNCTION) {
- RETURN_LONG(ce->line_start);
+ RETURN_LONG(ce->info.user.line_start);
}
RETURN_FALSE;
}
@@ -3344,7 +3509,7 @@ ZEND_METHOD(reflection_class, getEndLine)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_CLASS) {
- RETURN_LONG(ce->line_end);
+ RETURN_LONG(ce->info.user.line_end);
}
RETURN_FALSE;
}
@@ -3361,8 +3526,8 @@ ZEND_METHOD(reflection_class, getDocComment)
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
- RETURN_STRINGL(ce->doc_comment, ce->doc_comment_len, 1);
+ if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+ RETURN_STRINGL(ce->info.user.doc_comment, ce->info.user.doc_comment_len, 1);
}
RETURN_FALSE;
}
@@ -3394,7 +3559,7 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
- char *name, *lc_name;
+ char *name, *lc_name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3424,7 +3589,7 @@ ZEND_METHOD(reflection_class, getMethod)
zend_class_entry *ce;
zend_function *mptr;
zval obj_tmp;
- char *name, *lc_name;
+ char *name, *lc_name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3455,7 +3620,7 @@ ZEND_METHOD(reflection_class, getMethod)
efree(lc_name);
} else {
efree(lc_name);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s does not exist", name);
return;
}
@@ -3493,7 +3658,7 @@ static int _addmethod_va(zend_function *mptr TSRMLS_DC, int num_args, va_list ar
zval *retval = va_arg(args, zval*);
long filter = va_arg(args, long);
zval *obj = va_arg(args, zval *);
-
+
_addmethod(mptr, ce, retval, filter, obj TSRMLS_CC);
return ZEND_HASH_APPLY_KEEP;
}
@@ -3539,7 +3704,7 @@ ZEND_METHOD(reflection_class, hasProperty)
reflection_object *intern;
zend_property_info *property_info;
zend_class_entry *ce;
- char *name;
+ char *name;
int name_len;
zval *property;
@@ -3558,7 +3723,7 @@ ZEND_METHOD(reflection_class, hasProperty)
if (intern->obj && Z_OBJ_HANDLER_P(intern->obj, has_property)) {
MAKE_STD_ZVAL(property);
ZVAL_STRINGL(property, name, name_len, 1);
- if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2 TSRMLS_CC)) {
+ if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2, 0 TSRMLS_CC)) {
zval_ptr_dtor(&property);
RETURN_TRUE;
}
@@ -3576,7 +3741,7 @@ ZEND_METHOD(reflection_class, getProperty)
reflection_object *intern;
zend_class_entry *ce, **pce;
zend_property_info *property_info;
- char *name, *tmp, *classname;
+ char *name, *tmp, *classname;
int name_len, classname_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3632,9 +3797,9 @@ ZEND_METHOD(reflection_class, getProperty)
if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
return;
- }
+ }
}
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Property %s does not exist", name);
}
/* }}} */
@@ -3650,7 +3815,7 @@ static int _addproperty(zend_property_info *pptr TSRMLS_DC, int num_args, va_lis
if (pptr->flags & ZEND_ACC_SHADOW) {
return 0;
}
-
+
if (pptr->flags & filter) {
ALLOC_ZVAL(property);
reflection_property_factory(ce, pptr, property TSRMLS_CC);
@@ -3761,7 +3926,7 @@ ZEND_METHOD(reflection_class, getConstant)
reflection_object *intern;
zend_class_entry *ce;
zval **value;
- char *name;
+ char *name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3817,6 +3982,39 @@ ZEND_METHOD(reflection_class, isInstantiable)
}
/* }}} */
+/* {{{ proto public bool ReflectionClass::isCloneable()
+ Returns whether this class is cloneable */
+ZEND_METHOD(reflection_class, isCloneable)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zval obj;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+ if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
+ RETURN_FALSE;
+ }
+ if (intern->obj) {
+ if (ce->clone) {
+ RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
+ } else {
+ RETURN_BOOL(Z_OBJ_HANDLER_P(intern->obj, clone_obj) != NULL);
+ }
+ } else {
+ if (ce->clone) {
+ RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
+ } else {
+ object_init_ex(&obj, ce);
+ RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
+ zval_dtor(&obj);
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionClass::isInterface()
Returns whether this is an interface or a class */
ZEND_METHOD(reflection_class, isInterface)
@@ -3825,6 +4023,14 @@ ZEND_METHOD(reflection_class, isInterface)
}
/* }}} */
+/* {{{ proto public bool ReflectionClass::isTrait()
+ Returns whether this is a trait */
+ZEND_METHOD(reflection_class, isTrait)
+{
+ _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionClass::isFinal()
Returns whether this class is final */
ZEND_METHOD(reflection_class, isFinal)
@@ -3869,7 +4075,7 @@ ZEND_METHOD(reflection_class, isInstance)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
- GET_REFLECTION_OBJECT_PTR(ce);
+ GET_REFLECTION_OBJECT_PTR(ce);
RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC));
}
/* }}} */
@@ -3881,7 +4087,7 @@ ZEND_METHOD(reflection_class, newInstance)
zval *retval_ptr = NULL;
reflection_object *intern;
zend_class_entry *ce;
-
+
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
@@ -3946,6 +4152,24 @@ ZEND_METHOD(reflection_class, newInstance)
}
/* }}} */
+/* {{{ proto public stdclass ReflectionClass::newInstanceWithoutConstructor()
+ Returns an instance of this class without invoking its constructor */
+ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ METHOD_NOTSTATIC(reflection_class_ptr);
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ if (ce->create_object != NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class that cannot be instantiated without invoking its constructor", ce->name);
+ }
+
+ object_init_ex(return_value, ce);
+}
+/* }}} */
+
/* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
Returns an instance of this class */
ZEND_METHOD(reflection_class, newInstanceArgs)
@@ -3955,8 +4179,8 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
zend_class_entry *ce;
int argc = 0;
HashTable *args;
-
-
+
+
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
@@ -3966,7 +4190,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
if (ZEND_NUM_ARGS() > 0) {
argc = args->nNumOfElements;
}
-
+
/* Run the constructor if there is one */
if (ce->constructor) {
zval ***params = NULL;
@@ -3977,10 +4201,10 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
return;
}
-
+
if (argc) {
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);
+ zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
}
@@ -4076,6 +4300,80 @@ ZEND_METHOD(reflection_class, getInterfaceNames)
}
/* }}} */
+/* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
+ Returns an array of traits used by this class */
+ZEND_METHOD(reflection_class, getTraits)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_uint i;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ for (i=0; i < ce->num_traits; i++) {
+ zval *trait;
+ ALLOC_ZVAL(trait);
+ zend_reflection_class_factory(ce->traits[i], trait TSRMLS_CC);
+ add_assoc_zval_ex(return_value, ce->traits[i]->name, ce->traits[i]->name_length + 1, trait);
+ }
+}
+/* }}} */
+
+/* {{{ proto public String[] ReflectionClass::getTraitNames()
+ Returns an array of names of traits used by this class */
+ZEND_METHOD(reflection_class, getTraitNames)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_uint i;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ for (i=0; i < ce->num_traits; i++) {
+ add_next_index_stringl(return_value, ce->traits[i]->name, ce->traits[i]->name_length, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto public arra ReflectionClass::getTraitaliases()
+ Returns an array of trait aliases */
+ZEND_METHOD(reflection_class, getTraitAliases)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ if (ce->trait_aliases) {
+ zend_uint i = 0;
+ while (ce->trait_aliases[i]) {
+ char *method_name;
+ int method_name_len;
+ zend_trait_method_reference *cur_ref = ce->trait_aliases[i]->trait_method;
+
+ method_name_len = spprintf(&method_name, 0, "%s::%s", cur_ref->class_name, cur_ref->method_name);
+ add_assoc_stringl_ex(return_value, ce->trait_aliases[i]->alias, ce->trait_aliases[i]->alias_len + 1, method_name, method_name_len, 0);
+ i++;
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
Returns the class' parent class, or, if none exists, FALSE */
ZEND_METHOD(reflection_class, getParentClass)
@@ -4087,7 +4385,7 @@ ZEND_METHOD(reflection_class, getParentClass)
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
-
+
if (ce->parent) {
zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC);
} else {
@@ -4110,16 +4408,16 @@ ZEND_METHOD(reflection_class, isSubclassOf)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE) {
return;
}
-
+
switch(class_name->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(class_name));
return;
}
class_ce = *pce;
- break;
+ break;
case IS_OBJECT:
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);
@@ -4132,7 +4430,7 @@ ZEND_METHOD(reflection_class, isSubclassOf)
}
/* no break */
default:
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter one must either be a string or a ReflectionClass object");
return;
}
@@ -4155,16 +4453,16 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &interface) == FAILURE) {
return;
}
-
+
switch(interface->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
}
interface_ce = *pce;
- break;
+ break;
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) {
argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC);
@@ -4177,13 +4475,13 @@ ZEND_METHOD(reflection_class, implementsInterface)
}
/* no break */
default:
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter one must either be a string or a ReflectionClass object");
return;
}
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s is a Class", interface_ce->name);
return;
}
@@ -4197,7 +4495,7 @@ ZEND_METHOD(reflection_class, isIterateable)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4215,7 +4513,7 @@ ZEND_METHOD(reflection_class, getExtension)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4223,8 +4521,8 @@ ZEND_METHOD(reflection_class, getExtension)
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->module) {
- reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
+ if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+ reflection_extension_factory(return_value, ce->info.internal.module->name TSRMLS_CC);
}
}
/* }}} */
@@ -4235,7 +4533,7 @@ ZEND_METHOD(reflection_class, getExtensionName)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4243,8 +4541,8 @@ ZEND_METHOD(reflection_class, getExtensionName)
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->module) {
- RETURN_STRING(ce->module->name, 1);
+ if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+ RETURN_STRING(ce->info.internal.module->name, 1);
} else {
RETURN_FALSE;
}
@@ -4256,7 +4554,7 @@ ZEND_METHOD(reflection_class, getExtensionName)
ZEND_METHOD(reflection_class, inNamespace)
{
zval **name;
- char *colon;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4265,8 +4563,8 @@ ZEND_METHOD(reflection_class, inNamespace)
RETURN_FALSE;
}
if (Z_TYPE_PP(name) == IS_STRING
- && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
- && colon > Z_STRVAL_PP(name))
+ && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
+ && backslash > Z_STRVAL_PP(name))
{
RETURN_TRUE;
}
@@ -4279,7 +4577,7 @@ ZEND_METHOD(reflection_class, inNamespace)
ZEND_METHOD(reflection_class, getNamespaceName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4302,7 +4600,7 @@ ZEND_METHOD(reflection_class, getNamespaceName)
ZEND_METHOD(reflection_class, getShortName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4349,7 +4647,8 @@ ZEND_METHOD(reflection_property, export)
ZEND_METHOD(reflection_property, __construct)
{
zval *propname, *classname;
- char *name_str, *class_name, *prop_name;
+ char *name_str;
+ const char *class_name, *prop_name;
int name_len, dynam_prop = 0;
zval *object;
reflection_object *intern;
@@ -4367,13 +4666,13 @@ ZEND_METHOD(reflection_property, __construct)
if (intern == NULL) {
return;
}
-
+
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %s does not exist", Z_STRVAL_P(classname));
return;
}
ce = *pce;
@@ -4382,7 +4681,7 @@ ZEND_METHOD(reflection_property, __construct)
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 */
@@ -4400,12 +4699,12 @@ ZEND_METHOD(reflection_property, __construct)
return;
}
}
-
+
if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
/* we have to search the class hierarchy for this (implicit) public or protected property */
zend_class_entry *tmp_ce = ce;
zend_property_info *tmp_info;
-
+
while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, name_str, name_len + 1, (void **) &tmp_info) != SUCCESS) {
ce = tmp_ce;
property_info = tmp_info;
@@ -4413,19 +4712,19 @@ ZEND_METHOD(reflection_property, __construct)
}
}
- MAKE_STD_ZVAL(classname);
+ MAKE_STD_ZVAL(classname);
MAKE_STD_ZVAL(propname);
-
+
if (dynam_prop == 0) {
zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
ZVAL_STRINGL(classname, property_info->ce->name, property_info->ce->name_length, 1);
ZVAL_STRING(propname, prop_name, 1);
} else {
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
ZVAL_STRINGL(propname, name_str, name_len, 1);
}
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
+ reflection_update_property(object, "class", classname);
+ reflection_update_property(object, "name", propname);
reference = (property_reference*) emalloc(sizeof(property_reference));
if (dynam_prop) {
@@ -4475,7 +4774,7 @@ ZEND_METHOD(reflection_property, getName)
}
/* }}} */
-static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
+static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
{
reflection_object *intern;
property_reference *ref;
@@ -4486,6 +4785,7 @@ static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
GET_REFLECTION_OBJECT_PTR(ref);
RETURN_BOOL(ref->prop.flags & mask);
}
+/* }}} */
/* {{{ proto public bool ReflectionProperty::isPublic()
Returns whether this property is public */
@@ -4550,14 +4850,14 @@ ZEND_METHOD(reflection_property, getValue)
reflection_object *intern;
property_reference *ref;
zval *object, name;
- zval **member = NULL, *member_p = NULL;
+ zval *member_p = NULL;
METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref);
if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
_default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
zval_dtor(&name);
return;
@@ -4565,14 +4865,16 @@ 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) {
+ if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
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);
+ *return_value= *CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+ zval_copy_ctor(return_value);
+ INIT_PZVAL(return_value);
} else {
- char *class_name, *prop_name;
-
+ const char *class_name, *prop_name;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
@@ -4596,16 +4898,14 @@ ZEND_METHOD(reflection_property, setValue)
zval **variable_ptr;
zval *object, name;
zval *value;
- int setter_done = 0;
zval *tmp;
- HashTable *prop_table;
METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref);
if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
_default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
zval_dtor(&name);
return;
@@ -4618,36 +4918,37 @@ ZEND_METHOD(reflection_property, setValue)
}
}
zend_update_class_constants(intern->ce TSRMLS_CC);
- prop_table = CE_STATIC_MEMBERS(intern->ce);
- if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) {
+ if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
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) {
- setter_done = 1;
- } else {
+ variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+ if (*variable_ptr != value) {
if (PZVAL_IS_REF(*variable_ptr)) {
- zval_dtor(*variable_ptr);
- (*variable_ptr)->type = value->type;
+ zval garbage = **variable_ptr; /* old value should be destroyed */
+
+ /* To check: can't *variable_ptr be some system variable like error_zval here? */
+ Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);
(*variable_ptr)->value = value->value;
if (Z_REFCOUNT_P(value) > 0) {
zval_copy_ctor(*variable_ptr);
}
- setter_done = 1;
- }
- }
- if (!setter_done) {
- zval **foo;
+ zval_dtor(&garbage);
+ } else {
+ zval *garbage = *variable_ptr;
- Z_ADDREF_P(value);
- if (PZVAL_IS_REF(value)) {
- SEPARATE_ZVAL(&value);
+ /* if we assign referenced variable, we should separate it */
+ Z_ADDREF_P(value);
+ if (PZVAL_IS_REF(value)) {
+ SEPARATE_ZVAL(&value);
+ }
+ *variable_ptr = value;
+ zval_ptr_dtor(&garbage);
}
- zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
}
} else {
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
return;
@@ -4666,7 +4967,7 @@ ZEND_METHOD(reflection_property, getDeclaringClass)
property_reference *ref;
zend_class_entry *tmp_ce, *ce;
zend_property_info *tmp_info;
- char *prop_name, *class_name;
+ const char *prop_name, *class_name;
int prop_name_len;
if (zend_parse_parameters_none() == FAILURE) {
@@ -4770,14 +5071,14 @@ ZEND_METHOD(reflection_extension, __construct)
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
free_alloca(lcname, use_heap);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Extension %s does not exist", name_str);
return;
}
free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, module->name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property( object, "name", name);
intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL;
@@ -4863,7 +5164,7 @@ ZEND_METHOD(reflection_extension, getFunctions)
efree(lc_name);
continue;
}
-
+
ALLOC_ZVAL(function);
reflection_function_factory(fptr, NULL, function TSRMLS_CC);
add_assoc_zval_ex(return_value, func->fname, fname_len+1, function);
@@ -4874,7 +5175,7 @@ ZEND_METHOD(reflection_extension, getFunctions)
}
/* }}} */
-static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
zval *const_val;
zval *retval = va_arg(args, zval*);
@@ -4889,6 +5190,7 @@ static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list
}
return 0;
}
+/* }}} */
/* {{{ proto public array ReflectionExtension::getConstants()
Returns an associative array containing this extension's constants and their values */
@@ -4948,7 +5250,7 @@ static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, v
struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
int add_reflection_class = va_arg(args, int);
- if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+ if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
if (add_reflection_class) {
ALLOC_ZVAL(zclass);
zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
@@ -5007,11 +5309,11 @@ ZEND_METHOD(reflection_extension, getDependencies)
return;
}
GET_REFLECTION_OBJECT_PTR(module);
-
+
array_init(return_value);
dep = module->deps;
-
+
if (!dep)
{
return;
@@ -5021,7 +5323,7 @@ ZEND_METHOD(reflection_extension, getDependencies)
char *relation;
char *rel_type;
int len;
-
+
switch(dep->type) {
case MODULE_DEP_REQUIRED:
rel_type = "Required";
@@ -5037,10 +5339,10 @@ ZEND_METHOD(reflection_extension, getDependencies)
break;
}
- len = spprintf(&relation, 0, "%s%s%s%s%s",
+ len = spprintf(&relation, 0, "%s%s%s%s%s",
rel_type,
dep->rel ? " " : "",
- dep->rel ? dep->rel : "",
+ dep->rel ? dep->rel : "",
dep->version ? " " : "",
dep->version ? dep->version : "");
add_assoc_stringl(return_value, dep->name, relation, len, 0);
@@ -5049,7 +5351,7 @@ ZEND_METHOD(reflection_extension, getDependencies)
}
/* }}} */
-/* {{{ proto public void ReflectionExtension::info() U
+/* {{{ proto public void ReflectionExtension::info()
Prints phpinfo block for the extension */
ZEND_METHOD(reflection_extension, info)
{
@@ -5065,6 +5367,180 @@ ZEND_METHOD(reflection_extension, info)
}
/* }}} */
+/* {{{ proto public bool ReflectionExtension::isPersistent()
+ Returns whether this extension is persistent */
+ZEND_METHOD(reflection_extension, isPersistent)
+{
+ reflection_object *intern;
+ zend_module_entry *module;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(module);
+
+ RETURN_BOOL(module->type == MODULE_PERSISTENT);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionExtension::isTemporary()
+ Returns whether this extension is temporary */
+ZEND_METHOD(reflection_extension, isTemporary)
+{
+ reflection_object *intern;
+ zend_module_entry *module;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(module);
+
+ RETURN_BOOL(module->type == MODULE_TEMPORARY);
+}
+/* }}} */
+
+/* {{{ proto public static mixed ReflectionZendExtension::export(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_zend_extension, export)
+{
+ _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::__construct(string name)
+ Constructor. Throws an Exception in case the given Zend extension does not exist */
+ZEND_METHOD(reflection_zend_extension, __construct)
+{
+ zval *name;
+ zval *object;
+ reflection_object *intern;
+ zend_extension *extension;
+ char *name_str;
+ int name_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
+ return;
+ }
+
+ object = getThis();
+ intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
+ if (intern == NULL) {
+ return;
+ }
+
+ extension = zend_get_extension(name_str);
+ if (!extension) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Zend Extension %s does not exist", name_str);
+ return;
+ }
+ MAKE_STD_ZVAL(name);
+ ZVAL_STRING(name, extension->name, 1);
+ reflection_update_property(object, "name", name);
+ intern->ptr = extension;
+ intern->ref_type = REF_TYPE_OTHER;
+ intern->ce = NULL;
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::__toString()
+ Returns a string representation */
+ZEND_METHOD(reflection_zend_extension, __toString)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+ string str;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+ string_init(&str);
+ _zend_extension_string(&str, extension, "" TSRMLS_CC);
+ RETURN_STRINGL(str.string, str.len - 1, 0);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::getName()
+ Returns the name of this Zend extension */
+ZEND_METHOD(reflection_zend_extension, getName)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->name, 1);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::getVersion()
+ Returns the version information of this Zend extension */
+ZEND_METHOD(reflection_zend_extension, getVersion)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->version ? extension->version : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getAuthor()
+ * Returns the name of this Zend extension's author */
+ZEND_METHOD(reflection_zend_extension, getAuthor)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->author ? extension->author : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getURL()
+ Returns this Zend extension's URL*/
+ZEND_METHOD(reflection_zend_extension, getURL)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->URL ? extension->URL : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getCopyright()
+ Returns this Zend extension's copyright information */
+ZEND_METHOD(reflection_zend_extension, getCopyright)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->copyright ? extension->copyright : "", 1);
+}
+/* }}} */
+
/* {{{ method tables */
static const zend_function_entry reflection_exception_functions[] = {
PHP_FE_END
@@ -5120,6 +5596,8 @@ static const zend_function_entry reflection_function_abstract_functions[] = {
ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
@@ -5144,6 +5622,7 @@ static const zend_function_entry reflection_function_functions[] = {
ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
+ ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
PHP_FE_END
};
@@ -5172,6 +5651,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0)
+ ZEND_ARG_INFO(0, object)
+ZEND_END_ARG_INFO()
+
static const zend_function_entry reflection_method_functions[] = {
ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
@@ -5184,6 +5667,7 @@ static const zend_function_entry reflection_method_functions[] = {
ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
@@ -5253,6 +5737,9 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
ZEND_ARG_INFO(0, args)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
ZEND_ARG_ARRAY_INFO(0, args, 0)
ZEND_END_ARG_INFO()
@@ -5274,6 +5761,7 @@ static const zend_function_entry reflection_class_functions[] = {
ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
@@ -5291,11 +5779,16 @@ static const zend_function_entry reflection_class_functions[] = {
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)
+ ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
+ ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
@@ -5392,10 +5885,12 @@ static const zend_function_entry reflection_parameter_functions[] = {
ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
@@ -5427,6 +5922,25 @@ static const zend_function_entry reflection_extension_functions[] = {
ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry reflection_zend_extension_functions[] = {
+ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
+ ZEND_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
+ ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_extension___construct, 0)
+ ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
PHP_FE_END
};
/* }}} */
@@ -5438,19 +5952,19 @@ const zend_function_entry reflection_ext_functions[] = { /* {{{ */
static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
-static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
if ((Z_TYPE_P(member) == IS_STRING)
- && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
+ && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
{
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
}
else
{
- zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC);
+ zend_std_obj_handlers->write_property(object, member, value, key TSRMLS_CC);
}
}
/* }}} */
@@ -5537,6 +6051,12 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC);
zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
+ reflection_register_implement(reflection_zend_extension_ptr, reflector_ptr TSRMLS_CC);
+ zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
+
return SUCCESS;
} /* }}} */