The patch below adds the ReflectionMethod::setAccessible() method and
 adds support for the ignore_visibility flag that is controlled by this
 method to ReflectionMethod::invoke() and ReflectionMethod::invokeArgs().

 The patch complements ReflectionProperty::setAccessible() that was added
 in PHP 5.3.0. It has been developed for PHP_5_3 and I am proposing it
 for PHP 5.3.1 (it's a new feature, but a minor one).

 If accepted, I will provide a patch against trunk as well as tests
 and documentation.

 Cheers!
Sebastian

Index: ext/reflection/php_reflection.c
===================================================================
--- ext/reflection/php_reflection.c     (revision 287971)
+++ ext/reflection/php_reflection.c     (working copy)
@@ -176,7 +176,6 @@
 typedef struct _property_reference {
        zend_class_entry *ce;
        zend_property_info prop;
-       unsigned int ignore_visibility:1;
 } property_reference;

 /* Struct for parameters */
@@ -201,6 +200,7 @@
        reflection_type_t ref_type;
        zval *obj;
        zend_class_entry *ce;
+       unsigned int ignore_visibility:1;
 } reflection_object;

 static zend_object_handlers reflection_object_handlers;
@@ -1290,10 +1290,10 @@
        reference = (property_reference*) emalloc(sizeof(property_reference));
        reference->ce = ce;
        reference->prop = *prop;
-       reference->ignore_visibility = 0;
        intern->ptr = reference;
        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);
 }
@@ -2561,8 +2561,9 @@

        GET_REFLECTION_OBJECT_PTR(mptr);

-       if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
-               || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
+       if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
+                || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
+                && intern->ignore_visibility == 0)
        {
                if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
                        zend_throw_exception_ex(reflection_exception_ptr, 0 
TSRMLS_CC,
@@ -2669,8 +2670,9 @@
                return;
        }

-       if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
-               || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
+       if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
+                || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
+                && intern->ignore_visibility == 0)
        {
                if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
                        zend_throw_exception_ex(reflection_exception_ptr, 0 
TSRMLS_CC,
@@ -2959,6 +2961,28 @@
 }
 /* }}} */

+/* {{{ proto public void ReflectionMethod::setAccessible()
+   Sets whether non-public methods can be invoked */
+ZEND_METHOD(reflection_method, setAccessible)
+{
+       reflection_object *intern;
+       zend_bool visible;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == 
FAILURE) {
+               return;
+       }
+
+       intern = getThis();
+       intern = (reflection_object *) zend_object_store_get_object(intern 
TSRMLS_CC);
+
+       if (intern == NULL) {
+               return;
+       }
+
+       intern->ignore_visibility = visible;
+}
+/* }}} */
+
 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, 
bool return]) throws ReflectionException
    Exports a reflection object. Returns the output if TRUE is specified for 
return, printing it otherwise. */
 ZEND_METHOD(reflection_class, export)
@@ -4375,10 +4399,10 @@
                reference->prop = *property_info;
        }
        reference->ce = ce;
-       reference->ignore_visibility = 0;
        intern->ptr = reference;
        intern->ref_type = REF_TYPE_PROPERTY;
        intern->ce = ce;
+       intern->ignore_visibility = 0;
 }
 /* }}} */

@@ -4491,7 +4515,7 @@
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);

-       if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) 
&& ref->ignore_visibility == 0) {
+       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,
                        "Cannot access non-public member %s::%s", 
intern->ce->name, Z_STRVAL(name));
@@ -4543,7 +4567,7 @@
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);

-       if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && ref->ignore_visibility == 
0) {
+       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,
                        "Cannot access non-public member %s::%s", 
intern->ce->name, Z_STRVAL(name));
@@ -4660,14 +4684,20 @@
 ZEND_METHOD(reflection_property, setAccessible)
 {
        reflection_object *intern;
-       property_reference *ref;
        zend_bool visible;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == 
FAILURE) {
                return;
        }
-       GET_REFLECTION_OBJECT_PTR(ref);
-       ref->ignore_visibility = visible;
+
+       intern = getThis();
+       intern = (reflection_object *) zend_object_store_get_object(intern 
TSRMLS_CC);
+
+       if (intern == NULL) {
+               return;
+       }
+
+       intern->ignore_visibility = visible;
 }
 /* }}} */

@@ -5095,6 +5125,10 @@
        ZEND_ARG_ARRAY_INFO(0, args, 0)
 ZEND_END_ARG_INFO()

+ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
+       ZEND_ARG_INFO(0, value)
+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)
@@ -5112,6 +5146,7 @@
        ZEND_ME(reflection_method, invokeArgs, 
arginfo_reflection_method_invokeArgs, 0)
        ZEND_ME(reflection_method, getDeclaringClass, NULL, 0)
        ZEND_ME(reflection_method, getPrototype, NULL, 0)
+       ZEND_ME(reflection_property, setAccessible, 
arginfo_reflection_method_setAccessible, 0)
        {NULL, NULL, NULL}
 };


-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to