]> granicus.if.org Git - php/commitdiff
MFH (discussed with Andi)
authorMarcus Boerger <helly@php.net>
Mon, 27 Sep 2004 19:01:50 +0000 (19:01 +0000)
committerMarcus Boerger <helly@php.net>
Mon, 27 Sep 2004 19:01:50 +0000 (19:01 +0000)
Zend/zend_reflection_api.c
ext/reflection/php_reflection.c

index eb8bf648bea04dc82e72137bdc7e020669708efa..0e72bac6faf0b35c44f84496fc80237ec6c8289f 100644 (file)
@@ -145,8 +145,10 @@ typedef struct _property_reference {
 
 /* Struct for parameters */
 typedef struct _parameter_reference {
-       int offset;
+       zend_uint offset;
+       zend_uint required;
        struct _zend_arg_info *arg_info;
+       zend_function *fptr;
 } parameter_reference;
 
 /* Struct for reflection objects */
@@ -155,6 +157,7 @@ typedef struct {
        void *ptr;
        unsigned int free_ptr:1;
        zval *obj;
+       zend_class_entry *ce;
 } reflection_object;
 
 static zend_object_handlers reflection_object_handlers;
@@ -501,9 +504,14 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR
 /* }}} */
 
 /* {{{ _parameter_string */
-static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int offset, char* indent TSRMLS_DC)
+static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
 {
        string_printf(str, "Parameter #%d [ ", offset);
+       if (offset >= required) {
+               string_printf(str, "<optional> ");
+       } else {
+               string_printf(str, "<required> ");
+       }
        if (arg_info->class_name) {
                string_printf(str, "%s ", arg_info->class_name);
                if (arg_info->allow_null) {
@@ -518,6 +526,32 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int
        } else {
                string_printf(str, "$param%d", offset);
        }
+       if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
+               zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1];
+               if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+                       zval *zv, zv_copy;
+                       int use_copy;
+                       string_write(str, " = ", sizeof(" = ")-1);
+                       zv_copy = precv->op2.u.constant;
+                       zv = &zv_copy;
+                       zval_update_constant(&zv, (void*)1 TSRMLS_CC);
+                       if (Z_TYPE_P(zv) == IS_NULL) {
+                               string_write(str, "NULL", sizeof("NULL")-1);
+                       } else if (Z_TYPE_P(zv) == IS_STRING) {
+                               string_write(str, "'", sizeof("'")-1);
+                               string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
+                               if (Z_STRLEN_P(zv) > 15) {
+                                       string_write(str, "...", sizeof("...")-1);
+                               }
+                               string_write(str, "'", sizeof("'")-1);
+                       } else {
+                               zend_make_printable_zval(zv, &zv_copy, &use_copy);
+                               string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
+                               zval_dtor(&zv_copy);
+                       }
+                       zval_ptr_dtor(&zv);
+               }
+       }
        string_write(str, " ]", sizeof(" ]")-1);
 }
 /* }}} */
@@ -525,8 +559,8 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int
 /* {{{ _function_parameter_string */
 static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
 {
-       zend_uint i;
        struct _zend_arg_info *arg_info = fptr->common.arg_info;
+       zend_uint i, required = fptr->common.required_num_args;
 
        if (!arg_info) {
                return;
@@ -536,7 +570,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
        string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
        for (i = 0; i < fptr->common.num_args; i++) {
                string_printf(str, "%s  ", indent);
-               _parameter_string(str, arg_info, i, indent TSRMLS_CC);
+               _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
                string_write(str, "\n", sizeof("\n")-1);
                arg_info++;
        }
@@ -586,6 +620,9 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
                case ZEND_ACC_PROTECTED:
                        string_printf(str, "protected ");
                        break;
+               default:
+                   string_printf(str, "<visibilty error> ");
+                   break;
        }
 
        string_printf(str, fptr->common.scope ? "method " : "function ");
@@ -791,6 +828,7 @@ static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_D
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = ce;
        intern->free_ptr = 0;
+       intern->ce = ce;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -818,12 +856,13 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC)
        ZVAL_STRINGL(name, module->name, name_len, 1);
        intern->ptr = module;
        intern->free_ptr = 0;
+       intern->ce = NULL;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
 
 /* {{{ reflection_parameter_factory */
-static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int offset, zval *object TSRMLS_DC)
+static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
 {
        reflection_object *intern;
        parameter_reference *reference;
@@ -840,8 +879,11 @@ static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int of
        reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
        reference->arg_info = arg_info;
        reference->offset = offset;
+       reference->required = required;
+       reference->fptr = fptr;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = fptr->common.scope;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -859,6 +901,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = function;
        intern->free_ptr = 0;
+       intern->ce = NULL;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -878,6 +921,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = method;
        intern->free_ptr = 0;
+       intern->ce = ce;
        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);
 }
@@ -923,6 +967,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
        reference->prop = prop;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = ce;
        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);
 }
@@ -1152,6 +1197,7 @@ ZEND_METHOD(reflection_function, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = fptr;
        intern->free_ptr = 0;
+       intern->ce = NULL;
 }
 /* }}} */
 
@@ -1356,13 +1402,41 @@ ZEND_METHOD(reflection_function, returnsReference)
 }
 /* }}} */
 
-/* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
+/* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
+   Gets the number of required parameters */
+ZEND_METHOD(reflection_function, getNumberOfParameters)
+{
+       reflection_object *intern;
+       zend_function *fptr;
+
+       METHOD_NOTSTATIC;
+       GET_REFLECTION_OBJECT_PTR(fptr);
+
+       RETURN_LONG(fptr->common.num_args);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
+   Gets the number of required parameters */
+ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
+{
+       reflection_object *intern;
+       zend_function *fptr;
+
+       METHOD_NOTSTATIC;
+       GET_REFLECTION_OBJECT_PTR(fptr);
+
+       RETURN_LONG(fptr->common.required_num_args);
+}
+/* }}} */
+
+/* {{{ proto public ReflectionParameter[] Reflection_Function::getParameters()
    Returns an array of parameter objects for this function */
 ZEND_METHOD(reflection_function, getParameters)
 {
        reflection_object *intern;
        zend_function *fptr;
-       int i;
+       zend_uint i;
        struct _zend_arg_info *arg_info;
 
        METHOD_NOTSTATIC;
@@ -1375,7 +1449,7 @@ ZEND_METHOD(reflection_function, getParameters)
                 zval *parameter;   
 
                 ALLOC_ZVAL(parameter);
-                reflection_parameter_factory(arg_info, i, parameter TSRMLS_CC);
+                reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
                 add_next_index_zval(return_value, parameter);
                 
                 arg_info++;
@@ -1403,6 +1477,7 @@ ZEND_METHOD(reflection_parameter, __construct)
        zend_function *fptr;
        struct _zend_arg_info *arg_info;
        int position;
+       zend_class_entry *ce = NULL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &reference, &parameter) == FAILURE) {
                return;
@@ -1435,7 +1510,6 @@ ZEND_METHOD(reflection_parameter, __construct)
                case IS_ARRAY: {
                                zval **classref;
                                zval **method;
-                               zend_class_entry *ce;
                                zend_class_entry **pce;
                                char *lcname;
                                
@@ -1479,12 +1553,12 @@ ZEND_METHOD(reflection_parameter, __construct)
        arg_info = fptr->common.arg_info;
        if (Z_TYPE_P(parameter) == IS_LONG) {
                position= Z_LVAL_P(parameter);
-               if (position < 0 || position >= fptr->common.num_args) {
+               if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
                        _DO_THROW("The parameter specified by its offset could not be found");
                        /* returns out of this function */
                }
        } else {
-               int i;
+               zend_uint i;
 
                position= -1;
                convert_to_string_ex(&parameter);
@@ -1510,9 +1584,12 @@ ZEND_METHOD(reflection_parameter, __construct)
 
        ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
        ref->arg_info = &arg_info[position];
-       ref->offset = position;
+       ref->offset = (zend_uint)position;
+       ref->required = fptr->common.required_num_args;
+       ref->fptr = fptr;
        intern->ptr = ref;
        intern->free_ptr = 1;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -1527,7 +1604,7 @@ ZEND_METHOD(reflection_parameter, __toString)
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(param);
        string_init(&str);
-       _parameter_string(&str, param->arg_info, param->offset, "" TSRMLS_CC);
+       _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
        RETURN_STRINGL(str.string, str.len - 1, 0);
 }
 /* }}} */
@@ -1597,6 +1674,80 @@ ZEND_METHOD(reflection_parameter, isPassedByReference)
 }
 /* }}} */
 
+/* {{{ proto public bool ReflectionParameter::isOptional()
+   Returns whether this parameter is an optional parameter */
+ZEND_METHOD(reflection_parameter, isOptional)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       RETVAL_BOOL(param->offset >= param->required);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
+   Returns whether the default value of this parameter is available */
+ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+       zend_op *precv;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       if (param->fptr->type != ZEND_USER_FUNCTION)
+       {
+               RETURN_FALSE;
+       }
+       if (param->offset < param->required) {
+               RETURN_FALSE;
+       }
+       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
+       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::getDefaultValue()
+   Returns the default value of this parameter or throws an exception */
+ZEND_METHOD(reflection_parameter, getDefaultValue)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+       zend_op *precv;
+       zval *zv, zv_copy;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       if (param->fptr->type != ZEND_USER_FUNCTION)
+       {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
+               return;
+       }
+       if (param->offset < param->required) {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
+               return;
+       }
+       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
+       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
+               return;
+       }
+
+       zv_copy = precv->op2.u.constant;
+       zv = &zv_copy;
+       zval_update_constant(&zv, (void*)1 TSRMLS_CC);
+       RETURN_ZVAL(zv, 1, 1);
+}
+/* }}} */
+
 /* {{{ proto public static mixed ReflectionMethod::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_method, export)
@@ -1669,6 +1820,7 @@ ZEND_METHOD(reflection_method, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = mptr;
        intern->free_ptr = 0;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -1848,7 +2000,10 @@ ZEND_METHOD(reflection_method, isConstructor)
 
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(mptr);
-       RETURN_BOOL(mptr->common.scope->constructor == mptr);
+       /* 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);
 }
 /* }}} */
 
@@ -1861,7 +2016,7 @@ ZEND_METHOD(reflection_method, isDestructor)
 
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(mptr);
-       RETURN_BOOL(mptr->common.scope->destructor == mptr);
+       RETURN_BOOL(mptr->common.fn_flags && ZEND_ACC_DTOR);
 }
 /* }}} */
 
@@ -2530,7 +2685,7 @@ ZEND_METHOD(reflection_class, getParentClass)
 }
 /* }}} */
 
-/* {{{ proto public bool ReflectionClass::isSubclassOf(string|reflection_class class)
+/* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
    Returns whether this class is a subclass of another class */
 ZEND_METHOD(reflection_class, isSubclassOf)
 {
@@ -2576,7 +2731,7 @@ ZEND_METHOD(reflection_class, isSubclassOf)
 }
 /* }}} */
 
-/* {{{ proto public bool ReflectionClass::implementsInterface(string|reflection_class interface_name)
+/* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
    Returns whether this class is a subclass of another class */
 ZEND_METHOD(reflection_class, implementsInterface)
 {
@@ -2777,6 +2932,7 @@ ZEND_METHOD(reflection_property, __construct)
        reference->prop = property_info;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -2869,7 +3025,7 @@ ZEND_METHOD(reflection_property, getModifiers)
 }
 /* }}} */
 
-/* {{{ proto public mixed ReflectionProperty::getValue(stdclass object)
+/* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
    Returns this property's value */
 ZEND_METHOD(reflection_property, getValue)
 {
@@ -2886,16 +3042,15 @@ ZEND_METHOD(reflection_property, getValue)
                /* Returns from this function */
        }
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
-               return;
-       }
-
        if ((ref->prop->flags & ZEND_ACC_STATIC)) {
-               if (zend_hash_quick_find(Z_OBJCE_P(object)->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+               if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
                        zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                        /* Bails out */
                }
        } else {
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
+                       return;
+               }
                if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
                        zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                        /* Bails out */
@@ -2907,7 +3062,7 @@ ZEND_METHOD(reflection_property, getValue)
 }
 /* }}} */
 
-/* {{{ proto public void ReflectionProperty::setValue(stdclass object, mixed value)
+/* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
    Sets this property's value */
 ZEND_METHOD(reflection_property, setValue)
 {
@@ -2917,38 +3072,48 @@ ZEND_METHOD(reflection_property, setValue)
        zval *object;
        zval *value;
        int setter_done = 0;
+       zval *tmp;
+       HashTable *prop_table;
 
        METHOD_NOTSTATIC;
        GET_REFLECTION_OBJECT_PTR(ref);
 
-       if (ref->prop->flags & ~ZEND_ACC_PUBLIC) {
+       if (ref->prop->flags & ~(ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)) {
                _DO_THROW("Cannot access non-public member");
                /* Returns from this function */
        }
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
-               return;
-       }
-
-       if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == SUCCESS) {
-               if (*variable_ptr == value) {
-                       setter_done = 1;
-               } else {
-                       if (PZVAL_IS_REF(*variable_ptr)) {
-                               zval_dtor(*variable_ptr);
-                               (*variable_ptr)->type = value->type;
-                               (*variable_ptr)->value = value->value;
-                               if (value->refcount > 0) {
-                                       zval_copy_ctor(*variable_ptr);
-                               }
-                               setter_done = 1;
+       if ((ref->prop->flags & ZEND_ACC_STATIC)) {
+               if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
+                       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) {
+                               return;
                        }
                }
+               prop_table = intern->ce->static_members;
        } else {
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
+                       return;
+               }
+               prop_table = Z_OBJPROP_P(object);
+       }
+
+       if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
                zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                /* Bails out */
        }
-
+       if (*variable_ptr == value) {
+               setter_done = 1;
+       } else {
+               if (PZVAL_IS_REF(*variable_ptr)) {
+                       zval_dtor(*variable_ptr);
+                       (*variable_ptr)->type = value->type;
+                       (*variable_ptr)->value = value->value;
+                       if (value->refcount > 0) {
+                               zval_copy_ctor(*variable_ptr);
+                       }
+                       setter_done = 1;
+               }
+       }
        if (!setter_done) {
                zval **foo;
 
@@ -2956,7 +3121,7 @@ ZEND_METHOD(reflection_property, setValue)
                if (PZVAL_IS_REF(value)) {
                        SEPARATE_ZVAL(&value);
                }
-               zend_hash_quick_update(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
+               zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
        }
 }
 /* }}} */
@@ -3017,6 +3182,7 @@ ZEND_METHOD(reflection_extension, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = module;
        intern->free_ptr = 0;
+       intern->ce = NULL;
 }
 /* }}} */
 
@@ -3243,6 +3409,8 @@ static zend_function_entry reflection_function_functions[] = {
        ZEND_ME(reflection_function, invoke, NULL, 0)
        ZEND_ME(reflection_function, returnsReference, NULL, 0)
        ZEND_ME(reflection_function, getParameters, NULL, 0)
+       ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0)
+       ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0)
        {NULL, NULL, NULL}
 };
 
@@ -3335,6 +3503,9 @@ static zend_function_entry reflection_parameter_functions[] = {
        ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0)
        ZEND_ME(reflection_parameter, getClass, NULL, 0)
        ZEND_ME(reflection_parameter, allowsNull, NULL, 0)
+       ZEND_ME(reflection_parameter, isOptional, NULL, 0)
+       ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0)
+       ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0)
        {NULL, NULL, NULL}
 };
 
index eb8bf648bea04dc82e72137bdc7e020669708efa..0e72bac6faf0b35c44f84496fc80237ec6c8289f 100644 (file)
@@ -145,8 +145,10 @@ typedef struct _property_reference {
 
 /* Struct for parameters */
 typedef struct _parameter_reference {
-       int offset;
+       zend_uint offset;
+       zend_uint required;
        struct _zend_arg_info *arg_info;
+       zend_function *fptr;
 } parameter_reference;
 
 /* Struct for reflection objects */
@@ -155,6 +157,7 @@ typedef struct {
        void *ptr;
        unsigned int free_ptr:1;
        zval *obj;
+       zend_class_entry *ce;
 } reflection_object;
 
 static zend_object_handlers reflection_object_handlers;
@@ -501,9 +504,14 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR
 /* }}} */
 
 /* {{{ _parameter_string */
-static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int offset, char* indent TSRMLS_DC)
+static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
 {
        string_printf(str, "Parameter #%d [ ", offset);
+       if (offset >= required) {
+               string_printf(str, "<optional> ");
+       } else {
+               string_printf(str, "<required> ");
+       }
        if (arg_info->class_name) {
                string_printf(str, "%s ", arg_info->class_name);
                if (arg_info->allow_null) {
@@ -518,6 +526,32 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int
        } else {
                string_printf(str, "$param%d", offset);
        }
+       if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
+               zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1];
+               if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+                       zval *zv, zv_copy;
+                       int use_copy;
+                       string_write(str, " = ", sizeof(" = ")-1);
+                       zv_copy = precv->op2.u.constant;
+                       zv = &zv_copy;
+                       zval_update_constant(&zv, (void*)1 TSRMLS_CC);
+                       if (Z_TYPE_P(zv) == IS_NULL) {
+                               string_write(str, "NULL", sizeof("NULL")-1);
+                       } else if (Z_TYPE_P(zv) == IS_STRING) {
+                               string_write(str, "'", sizeof("'")-1);
+                               string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
+                               if (Z_STRLEN_P(zv) > 15) {
+                                       string_write(str, "...", sizeof("...")-1);
+                               }
+                               string_write(str, "'", sizeof("'")-1);
+                       } else {
+                               zend_make_printable_zval(zv, &zv_copy, &use_copy);
+                               string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
+                               zval_dtor(&zv_copy);
+                       }
+                       zval_ptr_dtor(&zv);
+               }
+       }
        string_write(str, " ]", sizeof(" ]")-1);
 }
 /* }}} */
@@ -525,8 +559,8 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int
 /* {{{ _function_parameter_string */
 static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
 {
-       zend_uint i;
        struct _zend_arg_info *arg_info = fptr->common.arg_info;
+       zend_uint i, required = fptr->common.required_num_args;
 
        if (!arg_info) {
                return;
@@ -536,7 +570,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
        string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
        for (i = 0; i < fptr->common.num_args; i++) {
                string_printf(str, "%s  ", indent);
-               _parameter_string(str, arg_info, i, indent TSRMLS_CC);
+               _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
                string_write(str, "\n", sizeof("\n")-1);
                arg_info++;
        }
@@ -586,6 +620,9 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
                case ZEND_ACC_PROTECTED:
                        string_printf(str, "protected ");
                        break;
+               default:
+                   string_printf(str, "<visibilty error> ");
+                   break;
        }
 
        string_printf(str, fptr->common.scope ? "method " : "function ");
@@ -791,6 +828,7 @@ static void reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_D
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = ce;
        intern->free_ptr = 0;
+       intern->ce = ce;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -818,12 +856,13 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC)
        ZVAL_STRINGL(name, module->name, name_len, 1);
        intern->ptr = module;
        intern->free_ptr = 0;
+       intern->ce = NULL;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
 
 /* {{{ reflection_parameter_factory */
-static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int offset, zval *object TSRMLS_DC)
+static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
 {
        reflection_object *intern;
        parameter_reference *reference;
@@ -840,8 +879,11 @@ static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int of
        reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
        reference->arg_info = arg_info;
        reference->offset = offset;
+       reference->required = required;
+       reference->fptr = fptr;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = fptr->common.scope;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -859,6 +901,7 @@ static void reflection_function_factory(zend_function *function, zval *object TS
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = function;
        intern->free_ptr = 0;
+       intern->ce = NULL;
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
 }
 /* }}} */
@@ -878,6 +921,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
        intern->ptr = method;
        intern->free_ptr = 0;
+       intern->ce = ce;
        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);
 }
@@ -923,6 +967,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
        reference->prop = prop;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = ce;
        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);
 }
@@ -1152,6 +1197,7 @@ ZEND_METHOD(reflection_function, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = fptr;
        intern->free_ptr = 0;
+       intern->ce = NULL;
 }
 /* }}} */
 
@@ -1356,13 +1402,41 @@ ZEND_METHOD(reflection_function, returnsReference)
 }
 /* }}} */
 
-/* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
+/* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
+   Gets the number of required parameters */
+ZEND_METHOD(reflection_function, getNumberOfParameters)
+{
+       reflection_object *intern;
+       zend_function *fptr;
+
+       METHOD_NOTSTATIC;
+       GET_REFLECTION_OBJECT_PTR(fptr);
+
+       RETURN_LONG(fptr->common.num_args);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
+   Gets the number of required parameters */
+ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
+{
+       reflection_object *intern;
+       zend_function *fptr;
+
+       METHOD_NOTSTATIC;
+       GET_REFLECTION_OBJECT_PTR(fptr);
+
+       RETURN_LONG(fptr->common.required_num_args);
+}
+/* }}} */
+
+/* {{{ proto public ReflectionParameter[] Reflection_Function::getParameters()
    Returns an array of parameter objects for this function */
 ZEND_METHOD(reflection_function, getParameters)
 {
        reflection_object *intern;
        zend_function *fptr;
-       int i;
+       zend_uint i;
        struct _zend_arg_info *arg_info;
 
        METHOD_NOTSTATIC;
@@ -1375,7 +1449,7 @@ ZEND_METHOD(reflection_function, getParameters)
                 zval *parameter;   
 
                 ALLOC_ZVAL(parameter);
-                reflection_parameter_factory(arg_info, i, parameter TSRMLS_CC);
+                reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
                 add_next_index_zval(return_value, parameter);
                 
                 arg_info++;
@@ -1403,6 +1477,7 @@ ZEND_METHOD(reflection_parameter, __construct)
        zend_function *fptr;
        struct _zend_arg_info *arg_info;
        int position;
+       zend_class_entry *ce = NULL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &reference, &parameter) == FAILURE) {
                return;
@@ -1435,7 +1510,6 @@ ZEND_METHOD(reflection_parameter, __construct)
                case IS_ARRAY: {
                                zval **classref;
                                zval **method;
-                               zend_class_entry *ce;
                                zend_class_entry **pce;
                                char *lcname;
                                
@@ -1479,12 +1553,12 @@ ZEND_METHOD(reflection_parameter, __construct)
        arg_info = fptr->common.arg_info;
        if (Z_TYPE_P(parameter) == IS_LONG) {
                position= Z_LVAL_P(parameter);
-               if (position < 0 || position >= fptr->common.num_args) {
+               if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
                        _DO_THROW("The parameter specified by its offset could not be found");
                        /* returns out of this function */
                }
        } else {
-               int i;
+               zend_uint i;
 
                position= -1;
                convert_to_string_ex(&parameter);
@@ -1510,9 +1584,12 @@ ZEND_METHOD(reflection_parameter, __construct)
 
        ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
        ref->arg_info = &arg_info[position];
-       ref->offset = position;
+       ref->offset = (zend_uint)position;
+       ref->required = fptr->common.required_num_args;
+       ref->fptr = fptr;
        intern->ptr = ref;
        intern->free_ptr = 1;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -1527,7 +1604,7 @@ ZEND_METHOD(reflection_parameter, __toString)
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(param);
        string_init(&str);
-       _parameter_string(&str, param->arg_info, param->offset, "" TSRMLS_CC);
+       _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
        RETURN_STRINGL(str.string, str.len - 1, 0);
 }
 /* }}} */
@@ -1597,6 +1674,80 @@ ZEND_METHOD(reflection_parameter, isPassedByReference)
 }
 /* }}} */
 
+/* {{{ proto public bool ReflectionParameter::isOptional()
+   Returns whether this parameter is an optional parameter */
+ZEND_METHOD(reflection_parameter, isOptional)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       RETVAL_BOOL(param->offset >= param->required);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
+   Returns whether the default value of this parameter is available */
+ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+       zend_op *precv;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       if (param->fptr->type != ZEND_USER_FUNCTION)
+       {
+               RETURN_FALSE;
+       }
+       if (param->offset < param->required) {
+               RETURN_FALSE;
+       }
+       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
+       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+               RETURN_FALSE;
+       }
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::getDefaultValue()
+   Returns the default value of this parameter or throws an exception */
+ZEND_METHOD(reflection_parameter, getDefaultValue)
+{
+       reflection_object *intern;
+       parameter_reference *param;
+       zend_op *precv;
+       zval *zv, zv_copy;
+
+       METHOD_NOTSTATIC_NUMPARAMS(0);
+       GET_REFLECTION_OBJECT_PTR(param);
+
+       if (param->fptr->type != ZEND_USER_FUNCTION)
+       {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
+               return;
+       }
+       if (param->offset < param->required) {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
+               return;
+       }
+       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
+       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
+               return;
+       }
+
+       zv_copy = precv->op2.u.constant;
+       zv = &zv_copy;
+       zval_update_constant(&zv, (void*)1 TSRMLS_CC);
+       RETURN_ZVAL(zv, 1, 1);
+}
+/* }}} */
+
 /* {{{ proto public static mixed ReflectionMethod::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_method, export)
@@ -1669,6 +1820,7 @@ ZEND_METHOD(reflection_method, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = mptr;
        intern->free_ptr = 0;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -1848,7 +2000,10 @@ ZEND_METHOD(reflection_method, isConstructor)
 
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(mptr);
-       RETURN_BOOL(mptr->common.scope->constructor == mptr);
+       /* 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);
 }
 /* }}} */
 
@@ -1861,7 +2016,7 @@ ZEND_METHOD(reflection_method, isDestructor)
 
        METHOD_NOTSTATIC_NUMPARAMS(0);
        GET_REFLECTION_OBJECT_PTR(mptr);
-       RETURN_BOOL(mptr->common.scope->destructor == mptr);
+       RETURN_BOOL(mptr->common.fn_flags && ZEND_ACC_DTOR);
 }
 /* }}} */
 
@@ -2530,7 +2685,7 @@ ZEND_METHOD(reflection_class, getParentClass)
 }
 /* }}} */
 
-/* {{{ proto public bool ReflectionClass::isSubclassOf(string|reflection_class class)
+/* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
    Returns whether this class is a subclass of another class */
 ZEND_METHOD(reflection_class, isSubclassOf)
 {
@@ -2576,7 +2731,7 @@ ZEND_METHOD(reflection_class, isSubclassOf)
 }
 /* }}} */
 
-/* {{{ proto public bool ReflectionClass::implementsInterface(string|reflection_class interface_name)
+/* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
    Returns whether this class is a subclass of another class */
 ZEND_METHOD(reflection_class, implementsInterface)
 {
@@ -2777,6 +2932,7 @@ ZEND_METHOD(reflection_property, __construct)
        reference->prop = property_info;
        intern->ptr = reference;
        intern->free_ptr = 1;
+       intern->ce = ce;
 }
 /* }}} */
 
@@ -2869,7 +3025,7 @@ ZEND_METHOD(reflection_property, getModifiers)
 }
 /* }}} */
 
-/* {{{ proto public mixed ReflectionProperty::getValue(stdclass object)
+/* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
    Returns this property's value */
 ZEND_METHOD(reflection_property, getValue)
 {
@@ -2886,16 +3042,15 @@ ZEND_METHOD(reflection_property, getValue)
                /* Returns from this function */
        }
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
-               return;
-       }
-
        if ((ref->prop->flags & ZEND_ACC_STATIC)) {
-               if (zend_hash_quick_find(Z_OBJCE_P(object)->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+               if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
                        zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                        /* Bails out */
                }
        } else {
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
+                       return;
+               }
                if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
                        zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                        /* Bails out */
@@ -2907,7 +3062,7 @@ ZEND_METHOD(reflection_property, getValue)
 }
 /* }}} */
 
-/* {{{ proto public void ReflectionProperty::setValue(stdclass object, mixed value)
+/* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
    Sets this property's value */
 ZEND_METHOD(reflection_property, setValue)
 {
@@ -2917,38 +3072,48 @@ ZEND_METHOD(reflection_property, setValue)
        zval *object;
        zval *value;
        int setter_done = 0;
+       zval *tmp;
+       HashTable *prop_table;
 
        METHOD_NOTSTATIC;
        GET_REFLECTION_OBJECT_PTR(ref);
 
-       if (ref->prop->flags & ~ZEND_ACC_PUBLIC) {
+       if (ref->prop->flags & ~(ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)) {
                _DO_THROW("Cannot access non-public member");
                /* Returns from this function */
        }
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
-               return;
-       }
-
-       if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == SUCCESS) {
-               if (*variable_ptr == value) {
-                       setter_done = 1;
-               } else {
-                       if (PZVAL_IS_REF(*variable_ptr)) {
-                               zval_dtor(*variable_ptr);
-                               (*variable_ptr)->type = value->type;
-                               (*variable_ptr)->value = value->value;
-                               if (value->refcount > 0) {
-                                       zval_copy_ctor(*variable_ptr);
-                               }
-                               setter_done = 1;
+       if ((ref->prop->flags & ZEND_ACC_STATIC)) {
+               if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
+                       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) {
+                               return;
                        }
                }
+               prop_table = intern->ce->static_members;
        } else {
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
+                       return;
+               }
+               prop_table = Z_OBJPROP_P(object);
+       }
+
+       if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
                zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
                /* Bails out */
        }
-
+       if (*variable_ptr == value) {
+               setter_done = 1;
+       } else {
+               if (PZVAL_IS_REF(*variable_ptr)) {
+                       zval_dtor(*variable_ptr);
+                       (*variable_ptr)->type = value->type;
+                       (*variable_ptr)->value = value->value;
+                       if (value->refcount > 0) {
+                               zval_copy_ctor(*variable_ptr);
+                       }
+                       setter_done = 1;
+               }
+       }
        if (!setter_done) {
                zval **foo;
 
@@ -2956,7 +3121,7 @@ ZEND_METHOD(reflection_property, setValue)
                if (PZVAL_IS_REF(value)) {
                        SEPARATE_ZVAL(&value);
                }
-               zend_hash_quick_update(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
+               zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
        }
 }
 /* }}} */
@@ -3017,6 +3182,7 @@ ZEND_METHOD(reflection_extension, __construct)
        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
        intern->ptr = module;
        intern->free_ptr = 0;
+       intern->ce = NULL;
 }
 /* }}} */
 
@@ -3243,6 +3409,8 @@ static zend_function_entry reflection_function_functions[] = {
        ZEND_ME(reflection_function, invoke, NULL, 0)
        ZEND_ME(reflection_function, returnsReference, NULL, 0)
        ZEND_ME(reflection_function, getParameters, NULL, 0)
+       ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0)
+       ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0)
        {NULL, NULL, NULL}
 };
 
@@ -3335,6 +3503,9 @@ static zend_function_entry reflection_parameter_functions[] = {
        ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0)
        ZEND_ME(reflection_parameter, getClass, NULL, 0)
        ZEND_ME(reflection_parameter, allowsNull, NULL, 0)
+       ZEND_ME(reflection_parameter, isOptional, NULL, 0)
+       ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0)
+       ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0)
        {NULL, NULL, NULL}
 };