From a764d75d087d48e1405f2a72c727f9b2e438bdd8 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 15 Feb 2008 12:38:53 +0000 Subject: [PATCH] - Add the ReflectionProperty::setAccesible() method that allows non-public property's values to be read through ::getValue(). #- [DOC] --- NEWS | 2 + ext/reflection/php_reflection.c | 34 +++++++++++++- .../reflectionProperty_setAccesible.phpt | 46 +++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 ext/reflection/tests/reflectionProperty_setAccesible.phpt diff --git a/NEWS b/NEWS index 1f63ddaa57..b959327552 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,8 @@ PHP NEWS . Added SplDoublyLinkedList, SplStack, SplQueue classes. (Etienne) . Added FilesystemIterator. (Marcus) . Added GlobIterator. (Marcus) +- Add the ReflectionProperty::setAccesible() method that allows non-public + property's values to be read through ::getValue(). - Added ability to use Traversable objects instead of plain arrays in ext/soap. (Joshua Reese, Dmitry) - Added stream_supports_lock() function. (Benjamin Schulz) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 1b23b253b4..e3a0f1e3dc 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -180,6 +180,7 @@ static void string_free(string *str) typedef struct _property_reference { zend_class_entry *ce; zend_property_info prop; + unsigned int ignore_visibility:1; } property_reference; /* Struct for parameters */ @@ -1176,6 +1177,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info reference = (property_reference*) emalloc(sizeof(property_reference)); reference->ce = ce; reference->prop = *prop; + reference->ignore_visibility = 0; intern->ptr = reference; intern->free_ptr = 1; intern->ce = ce; @@ -3856,6 +3858,7 @@ ZEND_METHOD(reflection_property, __construct) reference = (property_reference*) emalloc(sizeof(property_reference)); reference->ce = ce; reference->prop = *property_info; + reference->ignore_visibility = 0; intern->ptr = reference; intern->free_ptr = 1; intern->ce = ce; @@ -3963,7 +3966,7 @@ ZEND_METHOD(reflection_property, getValue) METHOD_NOTSTATIC(reflection_property_ptr); GET_REFLECTION_OBJECT_PTR(ref); - if (!(ref->prop.flags & ZEND_ACC_PUBLIC)) { + if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && ref->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)); @@ -3981,10 +3984,13 @@ ZEND_METHOD(reflection_property, getValue) zval_copy_ctor(return_value); INIT_PZVAL(return_value); } else { + char *class_name, *prop_name; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) { return; } - member_p = zend_read_property(Z_OBJCE_P(object), object, ref->prop.name, ref->prop.name_length, 1 TSRMLS_CC); + zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name); + member_p = zend_read_property(Z_OBJCE_P(object), object, prop_name, strlen(prop_name), 1 TSRMLS_CC); *return_value= *member_p; zval_copy_ctor(return_value); INIT_PZVAL(return_value); @@ -4113,6 +4119,24 @@ ZEND_METHOD(reflection_property, getDocComment) } /* }}} */ +/* {{{ proto public int ReflectionProperty::setAccesible() + Sets whether non-public properties can be requested */ +ZEND_METHOD(reflection_property, setAccesible) +{ + reflection_object *intern; + property_reference *ref; + zend_bool visible; + + METHOD_NOTSTATIC_NUMPARAMS(reflection_property_ptr, 1); + GET_REFLECTION_OBJECT_PTR(ref); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == FAILURE) { + return; + } + ref->ignore_visibility = visible; +} +/* }}} */ + /* {{{ proto public static mixed ReflectionExtension::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_extension, export) @@ -4719,6 +4743,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setValue, 0) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() +static +ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccesible, 0) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + static const zend_function_entry reflection_property_functions[] = { ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) ZEND_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC) @@ -4735,6 +4764,7 @@ static const zend_function_entry reflection_property_functions[] = { ZEND_ME(reflection_property, getModifiers, NULL, 0) ZEND_ME(reflection_property, getDeclaringClass, NULL, 0) ZEND_ME(reflection_property, getDocComment, NULL, 0) + ZEND_ME(reflection_property, setAccesible, arginfo_reflection_property_setAccesible, 0) {NULL, NULL, NULL} }; diff --git a/ext/reflection/tests/reflectionProperty_setAccesible.phpt b/ext/reflection/tests/reflectionProperty_setAccesible.phpt new file mode 100644 index 0000000000..f96dac77f5 --- /dev/null +++ b/ext/reflection/tests/reflectionProperty_setAccesible.phpt @@ -0,0 +1,46 @@ +--TEST-- +Test ReflectionProperty::setAccesible(). +--SKIPIF-- + +--FILE-- +getValue($instance)); +} +catch(Exception $exc) { + echo $exc->getMessage(), "\n"; +} + +$propInfo->setAccesible(true); +var_dump($propInfo->getValue($instance)); + +$propInfo->setAccesible(false); +try { + var_dump($propInfo->getValue($instance)); +} +catch(Exception $exc) { + echo $exc->getMessage(), "\n"; +} +?> +--EXPECTF-- + +Protected property: +Cannot access non-public member TestClass::prot +int(4) +Cannot access non-public member TestClass::prot -- 2.50.1