sebastian Thu, 10 Sep 2009 05:04:53 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=288218
Log:
Add ReflectionMethod::setAccessible() for invoking non-public methods through
the Reflection API.
Changed paths:
U php/php-src/trunk/NEWS
U php/php-src/trunk/ext/reflection/php_reflection.c
A
php/php-src/trunk/ext/reflection/tests/ReflectionMethod_setAccessible.phpt
Modified: php/php-src/trunk/NEWS
===================================================================
--- php/php-src/trunk/NEWS 2009-09-10 05:02:52 UTC (rev 288217)
+++ php/php-src/trunk/NEWS 2009-09-10 05:04:53 UTC (rev 288218)
@@ -45,6 +45,8 @@
(Sara)
- Added stream_resolve_include_path() function which checks which file fopen()
with a relative path will open. (Sara)
+- Added ReflectionMethod::setAccessible() for invoking non-public methods
+ through the Reflection API. (Sebastian)
- Fixed bug #46647 (SplFileObject::fgetcsv segfaults). (Etienne)
- Fixed bug #40325 (Vary: header missing in gzip output handlers). (Mike)
Modified: php/php-src/trunk/ext/reflection/php_reflection.c
===================================================================
--- php/php-src/trunk/ext/reflection/php_reflection.c 2009-09-10 05:02:52 UTC (rev 288217)
+++ php/php-src/trunk/ext/reflection/php_reflection.c 2009-09-10 05:04:53 UTC (rev 288218)
@@ -171,7 +171,6 @@
typedef struct _property_reference {
zend_class_entry *ce;
zend_property_info prop;
- unsigned int ignore_visibility:1;
} property_reference;
/* Struct for parameters */
@@ -196,6 +195,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;
@@ -1293,10 +1293,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_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
zend_ascii_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
}
@@ -2701,8 +2701,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,
@@ -2804,8 +2805,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,
@@ -3109,6 +3111,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 U
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class, export)
@@ -4580,10 +4604,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;
}
/* }}} */
@@ -4730,7 +4754,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 %v::%v", intern->ce->name, Z_UNIVAL(name));
@@ -4785,7 +4809,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 %v::%v", intern->ce->name, Z_UNIVAL(name));
@@ -4904,14 +4928,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;
}
/* }}} */
@@ -5342,6 +5372,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)
@@ -5360,6 +5394,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}
};
Added: php/php-src/trunk/ext/reflection/tests/ReflectionMethod_setAccessible.phpt
===================================================================
--- php/php-src/trunk/ext/reflection/tests/ReflectionMethod_setAccessible.phpt (rev 0)
+++ php/php-src/trunk/ext/reflection/tests/ReflectionMethod_setAccessible.phpt 2009-09-10 05:04:53 UTC (rev 288218)
@@ -0,0 +1,111 @@
+--TEST--
+Test ReflectionMethod::setAccessible().
+--FILE--
+<?php
+class A {
+ private function aPrivate($a) { print __METHOD__ . "\n"; }
+ private static function aPrivateStatic($a) { print __METHOD__ . "\n"; }
+ protected function aProtected($a) { print __METHOD__ . "\n"; }
+ protected static function aProtectedStatic($a) { print __METHOD__ . "\n"; }
+}
+
+$private = new ReflectionMethod('A', 'aPrivate');
+$privateStatic = new ReflectionMethod('A', 'aPrivateStatic');
+$protected = new ReflectionMethod('A', 'aProtected');
+$protectedStatic = new ReflectionMethod('A', 'aProtectedStatic');
+
+try {
+ $private->invoke(new A, NULL);
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $private->invokeArgs(new A, array(NULL));
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $privateStatic->invoke(NULL, NULL);
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $privateStatic->invokeArgs(NULL, array(NULL));
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $protected->invoke(new A, NULL);
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $protected->invokeArgs(new A, array(NULL));
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $protectedStatic->invoke(NULL, NULL);
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ $protectedStatic->invokeArgs(NULL, array(NULL));
+}
+
+catch (ReflectionException $e) {
+ var_dump($e->getMessage());
+}
+
+$private->setAccessible(TRUE);
+$privateStatic->setAccessible(TRUE);
+$protected->setAccessible(TRUE);
+$protectedStatic->setAccessible(TRUE);
+
+$private->invoke(new A, NULL);
+$private->invokeArgs(new A, array(NULL));
+$privateStatic->invoke(NULL, NULL);
+$privateStatic->invokeArgs(NULL, array(NULL));
+$protected->invoke(new A, NULL);
+$protected->invokeArgs(new A, array(NULL));
+$protectedStatic->invoke(NULL, NULL);
+$protectedStatic->invokeArgs(NULL, array(NULL));
+?>
+--EXPECT--
+unicode(73) "Trying to invoke private method A::aPrivate() from scope ReflectionMethod"
+unicode(73) "Trying to invoke private method A::aPrivate() from scope ReflectionMethod"
+unicode(79) "Trying to invoke private method A::aPrivateStatic() from scope ReflectionMethod"
+unicode(79) "Trying to invoke private method A::aPrivateStatic() from scope ReflectionMethod"
+unicode(77) "Trying to invoke protected method A::aProtected() from scope ReflectionMethod"
+unicode(77) "Trying to invoke protected method A::aProtected() from scope ReflectionMethod"
+unicode(83) "Trying to invoke protected method A::aProtectedStatic() from scope ReflectionMethod"
+unicode(83) "Trying to invoke protected method A::aProtectedStatic() from scope ReflectionMethod"
+A::aPrivate
+A::aPrivate
+A::aPrivateStatic
+A::aPrivateStatic
+A::aProtected
+A::aProtected
+A::aProtectedStatic
+A::aProtectedStatic
Property changes on: php/php-src/trunk/ext/reflection/tests/ReflectionMethod_setAccessible.phpt
___________________________________________________________________
Added: svn:keywords
+ Id Rev Revision
Added: svn:eol-style
+ native
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php