Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

A new constant RUNKIT_OVERRIDE_OBJECTS was introduced. Use it by bitw…

…ise adding to the flags parameter of functions runkit_default_property_add and runkit_import to add (and remove) properties of existing objects. This feature works in PHP 5.x and above and it is switched off by default.

New (the third one) parameter remove_from_objects of boolean type was introduced in runkit_default_property_remove function. Pass the TRUE value to remove property from existing objects. This feature works in PHP 5.x and above. The default value for this parameter is FALSE.
  • Loading branch information...
commit 07179d72a2165a8bee60ddab5f0b79d96b39a387 1 parent d069e23
@zenovich authored
Showing with 1,597 additions and 206 deletions.
  1. +25 −2 package.xml
  2. +15 −10 php_runkit.h
  3. +1 −0  runkit.c
  4. +30 −51 runkit_import.c
  5. +423 −119 runkit_props.c
  6. +1 −1  tests/runkit_default_property_add.phpt
  7. +14 −4 tests/runkit_default_property_add_and_remove_for_class_with_dynamic_properties.phpt
  8. +72 −0 tests/runkit_default_property_add_and_remove_for_class_with_dynamic_properties_overriding_in_objects.phpt
  9. +49 −0 tests/runkit_default_property_add_overriding_objects.phpt
  10. +27 −0 tests/runkit_default_property_add_overriding_objects4.phpt
  11. +0 −4 tests/runkit_default_property_add_to_subclasses.phpt
  12. +85 −0 tests/runkit_default_property_add_to_subclasses_overriding_objects.phpt
  13. +4 −2 tests/runkit_default_property_remove.phpt
  14. +11 −8 tests/runkit_default_property_remove_and_add_for_class_with_dynamic_properties.phpt
  15. +81 −0 tests/runkit_default_property_remove_and_add_for_class_with_dynamic_properties_overriding_objects.phpt
  16. +1 −1  tests/runkit_default_property_remove_and_reflection.phpt
  17. +5 −1 tests/runkit_default_property_remove_from_subclasses.phpt
  18. +52 −0 tests/runkit_default_property_remove_from_subclasses_overriding_objects.phpt
  19. +15 −2 tests/runkit_default_property_remove_inheritance.phpt
  20. +61 −0 tests/runkit_default_property_remove_inheritance_overriding_objects.phpt
  21. +46 −0 tests/runkit_default_property_remove_overriding_objects.phpt
  22. +30 −0 tests/runkit_default_property_remove_overriding_objects4.phpt
  23. +94 −0 tests/runkit_default_property_remove_private_and_inheritance.phpt
  24. +69 −0 tests/runkit_default_property_remove_private_and_inheritance_overriding_objects.phpt
  25. +92 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance.phpt
  26. +95 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance54.phpt
  27. +90 −0 tests/runkit_default_property_remove_private_shadow_and_inheritance_overriding_objects.phpt
  28. +8 −0 tests/runkit_import_class_property.phpt
  29. +6 −1 tests/runkit_import_class_property_and_inheritance.phpt
  30. +59 −0 tests/runkit_import_class_property_and_inheritance_overriding_objects.phpt
  31. +8 −0 tests/runkit_import_class_property_not_overriding_subclasses.phpt
  32. +7 −0 tests/runkit_import_function_overriding_objects4.inc
  33. +19 −0 tests/runkit_import_function_overriding_objects4.phpt
  34. +2 −0  tests/runkit_import_static_properties_override.phpt
View
27 package.xml
@@ -17,7 +17,7 @@ Execute code in restricted environment (sandboxing).
<active>yes</active>
</lead>
- <date>2012-01-02</date>
+ <date>2013-05-12</date>
<version>
<release>1.0.4</release>
<api>1.0.4</api>
@@ -38,7 +38,13 @@ Execute code in restricted environment (sandboxing).
New optional argument 'return_ref' of functions runkit_function_add and runkit_function_redefine was introduced
New constant RUNKIT_ACC_RETURN_REFERENCE was introduced for use with functions runkit_method_add and runkit_method_redefine
+ Properties adding, removing, and importing were reworked for proper inheritance (including objects in PHP5+)
- + Namespaces are fully supported by constants manipulation functions (Thanks to Anthony Dovgal)
+ + A new constant RUNKIT_OVERRIDE_OBJECTS was introduced. Use it by bitwise adding to the flags parameter
+ of functions runkit_default_property_add and runkit_import to add (and remove) properties of existing objects.
+ This feature works in PHP 5.x and above and it is switched off by default.
+ + New (the third one) parameter remove_from_objects of boolean type was introduced
+ in runkit_default_property_remove function. Pass the TRUE value to remove property from existing objects.
+ This feature works in PHP 5.x and above. The default value for this parameter is FALSE.
+ + Namespaces are fully supported by constants manipulation functions (Thanks to Antony Dovgal)
Critical fixes:
* Highly probable crashes on using Reflection objects after modifying removing or renaming of functions, methods, and properties,
@@ -223,6 +229,23 @@ Execute code in restricted environment (sandboxing).
<file name="runkit_static_property_add_existing.phpt" role="test" />
<file name="runkit_static_property_add_to_subclasses.phpt" role="test" />
<file name="runkit_superglobals.phpt" role="test" />
+ <file name="runkit_default_property_add_and_remove_for_class_with_dynamic_properties_overriding_in_objects.phpt" role="test" />
+ <file name="runkit_default_property_add_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_add_overriding_objects4.phpt" role="test" />
+ <file name="runkit_default_property_add_to_subclasses_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_and_add_for_class_with_dynamic_properties_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_from_subclasses_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_overriding_objects4.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_and_inheritance.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance54.phpt" role="test" />
+ <file name="runkit_default_property_remove_private_shadow_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_import_class_property_and_inheritance_overriding_objects.phpt" role="test" />
+ <file name="runkit_import_function_overriding_objects4.inc" role="test" />
+ <file name="runkit_import_function_overriding_objects4.phpt" role="test" />
</dir> <!-- //tests -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
View
25 php_runkit.h
@@ -39,13 +39,15 @@
#define PHP_RUNKIT_SANDBOX_CLASSNAME "Runkit_Sandbox"
#define PHP_RUNKIT_SANDBOX_PARENT_CLASSNAME "Runkit_Sandbox_Parent"
-#define PHP_RUNKIT_IMPORT_FUNCTIONS 0x0001
-#define PHP_RUNKIT_IMPORT_CLASS_METHODS 0x0002
-#define PHP_RUNKIT_IMPORT_CLASS_CONSTS 0x0004
-#define PHP_RUNKIT_IMPORT_CLASS_PROPS 0x0008
-#define PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS 0x0010
-#define PHP_RUNKIT_IMPORT_CLASSES (PHP_RUNKIT_IMPORT_CLASS_METHODS|PHP_RUNKIT_IMPORT_CLASS_CONSTS|PHP_RUNKIT_IMPORT_CLASS_PROPS|PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS)
-#define PHP_RUNKIT_IMPORT_OVERRIDE 0x0020
+#define PHP_RUNKIT_IMPORT_FUNCTIONS 0x0001
+#define PHP_RUNKIT_IMPORT_CLASS_METHODS 0x0002
+#define PHP_RUNKIT_IMPORT_CLASS_CONSTS 0x0004
+#define PHP_RUNKIT_IMPORT_CLASS_PROPS 0x0008
+#define PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS 0x0010
+#define PHP_RUNKIT_IMPORT_CLASSES (PHP_RUNKIT_IMPORT_CLASS_METHODS|PHP_RUNKIT_IMPORT_CLASS_CONSTS|\
+ PHP_RUNKIT_IMPORT_CLASS_PROPS|PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS)
+#define PHP_RUNKIT_IMPORT_OVERRIDE 0x0020
+#define PHP_RUNKIT_OVERRIDE_OBJECTS 0x8000
#if ZEND_MODULE_API_NO > 20050922
#define ZEND_ENGINE_2_2
@@ -270,11 +272,14 @@ int php_runkit_update_children_consts(RUNKIT_53_TSRMLS_ARG(void *pDest), int num
/* runkit_props.c */
int php_runkit_update_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce), int num_args, va_list args, zend_hash_key *hash_key);
-int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int propname_len, zval *copyval, long visibility, const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override TSRMLS_DC);
-int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
- int parent_offset, zend_bool was_static TSRMLS_DC);
+int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int propname_len, zval *copyval, long visibility, const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override, int override_in_objects TSRMLS_DC);
#ifdef ZEND_ENGINE_2
+int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
+ zend_bool was_static, zend_bool remove_from_objects, zend_property_info *parent_property TSRMLS_DC);
void php_runkit_remove_property_from_reflection_objects(zend_class_entry *ce, const char *prop_name, int prop_name_len TSRMLS_DC);
+#else
+int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
+ zend_bool was_static, zend_bool remove_from_objects, void *parent_property TSRMLS_DC);
#endif
#ifdef ZEND_ENGINE_2
View
1  runkit.c
@@ -271,6 +271,7 @@ PHP_MINIT_FUNCTION(runkit)
REGISTER_LONG_CONSTANT("RUNKIT_ACC_PRIVATE", 0x400, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RUNKIT_ACC_STATIC", 0x001, CONST_CS | CONST_PERSISTENT);
#endif
+ REGISTER_LONG_CONSTANT("RUNKIT_OVERRIDE_OBJECTS", PHP_RUNKIT_OVERRIDE_OBJECTS, CONST_CS | CONST_PERSISTENT);
#ifdef PHP_RUNKIT_CLASSKIT_COMPAT
#ifdef ZEND_ENGINE_2
View
81 runkit_import.c
@@ -259,7 +259,7 @@ static int php_runkit_import_class_consts(zend_class_entry *dce, zend_class_entr
#ifdef ZEND_ENGINE_2
/* {{{ php_runkit_import_class_static_props
*/
-static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_class_entry *ce, int override TSRMLS_DC)
+static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_class_entry *ce, int override, int remove_from_objects TSRMLS_DC)
{
HashPosition pos;
char *key;
@@ -290,43 +290,19 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
#endif // (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
if (zend_hash_find(&dce->properties_info, key, key_len, (void*) &ex_property_info_ptr) == SUCCESS && ex_property_info_ptr) {
if (override) {
- if (!(ex_property_info_ptr->flags & ZEND_ACC_STATIC)) {
- if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, -1, 0 TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot remove old member)", dce->name, key);
- goto import_st_prop_skip;
- }
- if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
- property_info_ptr->doc_comment,
- property_info_ptr->doc_comment_len, dce,
- override TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
- goto import_st_prop_skip;
- }
+ if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, 0, 0, NULL TSRMLS_CC) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot remove old member)", dce->name, key);
goto import_st_prop_skip;
- } else {
- zval *pcopy;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- zval_ptr_dtor(&dce->default_static_members_table[ex_property_info_ptr->offset]);
- dce->default_static_members_table[ex_property_info_ptr->offset] = ce->default_static_members_table[property_info_ptr->offset];
- ce->default_static_members_table[property_info_ptr->offset] = NULL;
- zval_update_constant(&dce->default_static_members_table[ex_property_info_ptr->offset], dce TSRMLS_CC);
- pcopy = dce->default_static_members_table[ex_property_info_ptr->offset];
-#else
- pcopy = *pp;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 2)
- SEPARATE_ARG_IF_REF(pcopy);
-#else
- Z_ADDREF_P(pcopy);
-#endif
- if (zend_hash_update(CE_STATIC_MEMBERS(dce), ex_property_info_ptr->name, ex_property_info_ptr->name_length + 1, (void*)pp, sizeof(zval*), NULL) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s", dce->name, key);
- }
-#endif
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
- (apply_func_args_t)php_runkit_update_children_def_props,
- 7, dce, pcopy, key, key_len - 1,
- property_info_ptr->flags, dce, override);
}
+ zval_update_constant(pp, dce TSRMLS_CC);
+ if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
+ property_info_ptr->doc_comment,
+ property_info_ptr->doc_comment_len, dce,
+ override, remove_from_objects TSRMLS_CC) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
+ goto import_st_prop_skip;
+ }
+ goto import_st_prop_skip;
} else {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s::$%s already exists, not importing", dce->name, key);
goto import_st_prop_skip;
@@ -335,7 +311,7 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
if (php_runkit_def_prop_add_int(dce, key, key_len - 1, *pp, property_info_ptr->flags,
property_info_ptr->doc_comment,
property_info_ptr->doc_comment_len, dce,
- override TSRMLS_CC) != SUCCESS) {
+ override, remove_from_objects TSRMLS_CC) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to import %s::$%s (cannot add new member)", dce->name, key);
goto import_st_prop_skip;
}
@@ -353,7 +329,7 @@ static int php_runkit_import_class_static_props(zend_class_entry *dce, zend_clas
/* {{{ php_runkit_import_class_props
*/
-static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry *ce, int override TSRMLS_DC)
+static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry *ce, int override, int remove_from_objects TSRMLS_DC)
{
HashPosition pos;
char *key;
@@ -372,15 +348,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
goto import_st54_prop_skip;
}
if (zend_hash_exists(&dce->properties_info, key, key_len)) {
- if (override) {
- if (php_runkit_def_prop_remove_int(dce, key, key_len - 1, NULL, -1, 0 TSRMLS_CC) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Unable to remove old property %s%s%s, not importing",
- dce->name, (property_info_ptr->flags & ZEND_ACC_STATIC) ? "::$" : "->",
- property_info_ptr->name);
- goto import_st54_prop_skip;
- }
- } else {
+ if (!override) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s%s already exists, not importing",
dce->name, (property_info_ptr->flags & ZEND_ACC_STATIC) ? "::$" : "->", key);
goto import_st54_prop_skip;
@@ -406,7 +374,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
php_runkit_def_prop_add_int(dce, key, key_len - 1, *p,
property_info_ptr->flags, property_info_ptr->doc_comment,
- property_info_ptr->doc_comment_len, dce, override TSRMLS_CC);
+ property_info_ptr->doc_comment_len, dce, override, remove_from_objects TSRMLS_CC);
}
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
else {
@@ -427,7 +395,7 @@ static int php_runkit_import_class_props(zend_class_entry *dce, zend_class_entry
}
}
- php_runkit_def_prop_add_int(dce, key, key_len - 1, *p, 0, NULL, 0, dce, override TSRMLS_CC);
+ php_runkit_def_prop_add_int(dce, key, key_len - 1, *p, 0, NULL, 0, dce, override, remove_from_objects TSRMLS_CC);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Property has invalid key name");
}
@@ -487,12 +455,16 @@ static int php_runkit_import_classes(HashTable *class_table, long flags
php_runkit_import_class_consts(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
}
if (flags & PHP_RUNKIT_IMPORT_CLASS_STATIC_PROPS) {
- php_runkit_import_class_static_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
+ php_runkit_import_class_static_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) != 0,
+ (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
+ TSRMLS_CC);
}
#endif
if (flags & PHP_RUNKIT_IMPORT_CLASS_PROPS) {
- php_runkit_import_class_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) TSRMLS_CC);
+ php_runkit_import_class_props(dce, ce, (flags & PHP_RUNKIT_IMPORT_OVERRIDE) != 0,
+ (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0
+ TSRMLS_CC);
}
if (flags & PHP_RUNKIT_IMPORT_CLASS_METHODS) {
@@ -618,6 +590,13 @@ PHP_FUNCTION(runkit_import)
}
convert_to_string(filename);
+#ifndef ZEND_ENGINE_2
+ if (flags & PHP_RUNKIT_OVERRIDE_OBJECTS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Overriding in objects is not supported for PHP versions below 5.0");
+ flags &= ~PHP_RUNKIT_OVERRIDE_OBJECTS;
+ }
+#endif
+
if (compile_file != zend_compile_file) {
/* An accellerator or other dark force is at work
* Use the wrapper method to force the builtin compiler
View
542 runkit_props.c
@@ -27,13 +27,14 @@
Scan the class_table for children of the class just updated */
int php_runkit_update_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce), int num_args, va_list args, zend_hash_key *hash_key)
{
- zend_class_entry *parent_class = va_arg(args, zend_class_entry*);
+ zend_class_entry *parent_class = va_arg(args, zend_class_entry*);
zval *p = va_arg(args, zval*);
char *pname = va_arg(args, char*);
int pname_len = va_arg(args, int);
int access_type = va_arg(args, int);
zend_class_entry *definer_class = va_arg(args, zend_class_entry*);
int override = va_arg(args, int);
+ int override_in_objects = va_arg(args, int);
RUNKIT_UNDER53_TSRMLS_FETCH();
@@ -46,7 +47,7 @@ int php_runkit_update_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *
return ZEND_HASH_APPLY_KEEP;
}
- php_runkit_def_prop_add_int(ce, pname, pname_len, p, access_type, NULL, 0, definer_class, override TSRMLS_CC);
+ php_runkit_def_prop_add_int(ce, pname, pname_len, p, access_type, NULL, 0, definer_class, override, override_in_objects TSRMLS_CC);
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
@@ -58,9 +59,12 @@ int php_runkit_remove_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *
zend_class_entry *parent_class = va_arg(args, zend_class_entry*);
char *pname = va_arg(args, char*);
int pname_len = va_arg(args, int);
- zend_class_entry *definer_class = va_arg(args, zend_class_entry*);
- int parent_offset = va_arg(args, int);
+ zend_class_entry *class_we_originally_removing_from = va_arg(args, zend_class_entry*);
zend_bool was_static = va_arg(args, int);
+ zend_bool remove_from_objects = va_arg(args, int);
+#ifdef ZEND_ENGINE_2
+ zend_property_info *parent_property = va_arg(args, zend_property_info *);
+#endif
RUNKIT_UNDER53_TSRMLS_FETCH();
@@ -73,23 +77,47 @@ int php_runkit_remove_children_def_props(RUNKIT_53_TSRMLS_ARG(zend_class_entry *
return ZEND_HASH_APPLY_KEEP;
}
- php_runkit_def_prop_remove_int(ce, pname, pname_len, definer_class, parent_offset, was_static TSRMLS_CC);
+ php_runkit_def_prop_remove_int(ce, pname, pname_len, class_we_originally_removing_from, was_static, remove_from_objects,
+#ifdef ZEND_ENGINE_2
+ parent_property
+#else
+ NULL
+#endif
+ TSRMLS_CC);
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
-/* {{{ php_runkit_remove_shadowed_property_from_childs
- Clean private properties by offset */
-int php_runkit_remove_shadowed_property_from_childs(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce), int num_args, va_list args, zend_hash_key *hash_key)
+#if PHP_MAJOR_VERSION >= 5
+/* {{{ php_runkit_remove_property_by_full_name */
+static int php_runkit_remove_property_by_full_name(zend_property_info *prop, zend_property_info *comp_prop, zend_hash_key *key) {
+ if (prop->h == comp_prop->h && prop->name_length == comp_prop->name_length &&
+ memcmp(prop->name, comp_prop->name, prop->name_length) == 0) {
+ return ZEND_HASH_APPLY_REMOVE;
+ }
+
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* {{{ php_runkit_remove_overlapped_property_from_childs
+ Clean private properties by offset */
+int php_runkit_remove_overlapped_property_from_childs(RUNKIT_53_TSRMLS_ARG(zend_class_entry *ce), int num_args, va_list args, zend_hash_key *hash_key)
{
zend_class_entry *parent_class = va_arg(args, zend_class_entry*);
- char *pname = va_arg(args, char*);
- int pname_len = va_arg(args, int);
+ char *propname = va_arg(args, char*);
+ int propname_len = va_arg(args, int);
int offset = va_arg(args, int);
zend_bool is_static = va_arg(args, int);
+ zend_bool remove_from_objects = va_arg(args, int);
+ zend_property_info *property_info_ptr = va_arg(args, zend_property_info *);
int i;
+ long h;
+ zend_property_info *p;
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4 || PHP_MAJOR_VERSION > 5
zval **table;
+#endif
+ RUNKIT_UNDER53_TSRMLS_FETCH();
ce = *((zend_class_entry**)ce);
@@ -98,37 +126,110 @@ int php_runkit_remove_shadowed_property_from_childs(RUNKIT_53_TSRMLS_ARG(zend_cl
return ZEND_HASH_APPLY_KEEP;
}
- table = is_static ? ce->default_static_members_table : ce->default_properties_table;
- if (table[offset]) {
- zval_ptr_dtor(&table[offset]);
- table[offset] = NULL;
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+ if (!remove_from_objects && (property_info_ptr->flags & ZEND_ACC_SHADOW)) {
+ return ZEND_HASH_APPLY_KEEP;
}
+#endif
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_remove_shadowed_property_from_childs,
- 5, ce, pname, pname_len, offset, is_static);
- php_runkit_remove_property_from_reflection_objects(ce, pname, pname_len TSRMLS_CC);
+ zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
+ (apply_func_args_t) php_runkit_remove_overlapped_property_from_childs,
+ 8, ce, propname, propname_len, offset, is_static, remove_from_objects, property_info_ptr);
+ php_runkit_remove_property_from_reflection_objects(ce, propname, propname_len TSRMLS_CC);
if (is_static || !EG(objects_store).object_buckets) {
- return ZEND_HASH_APPLY_KEEP;
+ goto st_success;
}
+
for (i = 1; i < EG(objects_store).top ; i++) {
if (EG(objects_store).object_buckets[i].valid && (!EG(objects_store).object_buckets[i].destructor_called) &&
- EG(objects_store).object_buckets[i].bucket.obj.object) {
+ EG(objects_store).object_buckets[i].bucket.obj.object) {
zend_object *object;
object = (zend_object *) EG(objects_store).object_buckets[i].bucket.obj.object;
if (object->ce == ce) {
- if (object->properties_table[offset]) {
+ if (!remove_from_objects) {
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+ zval **prop_val;
+ h = zend_get_hash_value((char *) propname, propname_len + 1);
+ if (zend_hash_quick_find(object->properties, (char *) property_info_ptr->name,
+ property_info_ptr->name_length + 1,
+ property_info_ptr->h, (void *) &prop_val) == SUCCESS) {
+ zval **foo;
+ if ((property_info_ptr->flags & (ZEND_ACC_PRIVATE | ZEND_ACC_PROTECTED | ZEND_ACC_SHADOW)) && prop_val) {
+ Z_ADDREF_P(*prop_val);
+ if (PZVAL_IS_REF(*prop_val)) {
+ SEPARATE_ZVAL(prop_val);
+ }
+ zend_hash_quick_update(object->properties, (char *) propname,
+ propname_len + 1, h, prop_val,
+ sizeof(zval *), (void *) &foo);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE,
+ "Making %s::%s public to remove it "
+ "from class without objects overriding",
+ ce->name, propname);
+ zend_hash_quick_del(object->properties,
+ property_info_ptr->name,
+ property_info_ptr->name_length+1,
+ property_info_ptr->h);
+ }
+ }
+#endif
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4 || PHP_MAJOR_VERSION > 5
+ zval *prop_val = NULL;
+ h = zend_get_hash_value((char *) propname, propname_len + 1);
if (!object->properties) {
- zval_ptr_dtor(&object->properties_table[offset]);
- } else {
- zend_hash_del(object->properties, pname, pname_len+1);
+ prop_val = object->properties_table[offset];
+ rebuild_object_properties(object);
+ } else if (object->properties_table[offset]) {
+ prop_val = *(zval **) object->properties_table[offset];
+ }
+ if ((property_info_ptr->flags & (ZEND_ACC_PRIVATE | ZEND_ACC_PROTECTED | ZEND_ACC_SHADOW)) && prop_val) {
+ Z_ADDREF_P(prop_val);
+ if (h != property_info_ptr->h) {
+ zend_hash_quick_del(object->properties, property_info_ptr->name, property_info_ptr->name_length+1, property_info_ptr->h);
+ }
+ zend_hash_quick_update(object->properties, propname, propname_len+1, h,
+ &prop_val, sizeof(zval *), (void *) &object->properties_table[offset]);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Making %s::%s public to remove it "
+ "from class without objects overriding", ce->name, propname);
+ }
+#endif
+ } else {
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+ zend_hash_quick_del(object->properties, property_info_ptr->name, property_info_ptr->name_length+1,
+ property_info_ptr->h);
+#else
+ if (object->properties_table[offset]) {
+ if (!object->properties) {
+ zval_ptr_dtor(&object->properties_table[offset]);
+ object->properties_table[offset] = NULL;
+ } else {
+ zend_hash_del(object->properties, propname, propname_len+1);
+ }
}
- object->properties_table[offset] = NULL;
+#endif
}
}
}
}
-
+st_success:
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4 || PHP_MAJOR_VERSION > 5
+ table = is_static ? ce->default_static_members_table : ce->default_properties_table;
+ if (table[offset]) {
+ zval_ptr_dtor(&table[offset]);
+ table[offset] = NULL;
+ }
+#elif PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+ zend_hash_quick_del(&ce->default_properties, property_info_ptr->name, property_info_ptr->name_length+1,
+ property_info_ptr->h);
+#endif
+ h = zend_get_hash_value((char *) propname, propname_len + 1);
+ zend_hash_apply_with_argument(&ce->properties_info, (apply_func_arg_t) php_runkit_remove_property_by_full_name,
+ property_info_ptr TSRMLS_CC);
+ if (zend_hash_quick_find(&ce->properties_info, propname, propname_len + 1, h, (void *) &p) == SUCCESS &&
+ p->h == property_info_ptr->h) {
+ zend_hash_quick_del(&ce->properties_info, propname, propname_len + 1, h);
+ }
return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
@@ -136,7 +237,8 @@ int php_runkit_remove_shadowed_property_from_childs(RUNKIT_53_TSRMLS_ARG(zend_cl
/* {{{ php_runkit_def_prop_add_int */
int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int propname_len, zval *copyval, long visibility,
- const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override TSRMLS_DC)
+ const char *doc_comment, int doc_comment_len, zend_class_entry *definer_class, int override,
+ int override_in_objects TSRMLS_DC)
{
#if PHP_MAJOR_VERSION >= 5
int i;
@@ -182,7 +284,7 @@ int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int
ce->name, (prop_info_ptr->flags & ZEND_ACC_STATIC) ? "::$" : "->", propname);
return FAILURE;
} else {
- php_runkit_def_prop_remove_int(ce, propname, propname_len, NULL, -1, 0 TSRMLS_CC);
+ php_runkit_def_prop_remove_int(ce, propname, propname_len, NULL, 0, override_in_objects, NULL TSRMLS_CC);
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
#endif
@@ -227,14 +329,18 @@ int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int
if (visibility & ZEND_ACC_PRIVATE) {
char *newkey;
int newkey_len;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 3) || (PHP_MAJOR_VERSION < 5)
char *oldkey;
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ const char *interned_name;
+#endif
int oldkey_len;
+ zend_property_info new_prop_info;
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 3) || (PHP_MAJOR_VERSION < 5)
zval **prop;
#endif
zend_mangle_property_name(&newkey, &newkey_len, definer_class->name, definer_class->name_length, (char *) propname, propname_len, ce->type & ZEND_INTERNAL_CLASS);
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 3) || (PHP_MAJOR_VERSION < 5)
zend_mangle_property_name(&oldkey, &oldkey_len, ce->name, ce->name_length, (char *) propname, propname_len, ce->type & ZEND_INTERNAL_CLASS);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 3)
symt = (visibility & ZEND_ACC_STATIC) ? &ce->default_static_members : &ce->default_properties;
if (zend_hash_find(symt, oldkey, oldkey_len + 1, (void*) &prop) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find just added property");
@@ -243,24 +349,35 @@ int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int
Z_ADDREF_P(*prop);
zend_hash_update(symt, newkey, newkey_len + 1, prop, sizeof(zval *), NULL);
zend_hash_del(symt, oldkey, oldkey_len + 1);
- pefree((void*)oldkey, ce->type & ZEND_INTERNAL_CLASS);
#endif
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 3
- pefree((void*)prop_info_ptr->name, ce->type & ZEND_INTERNAL_CLASS);
#endif
+ memcpy(&new_prop_info, prop_info_ptr, sizeof(zend_property_info));
+ new_prop_info.name = newkey;
+ new_prop_info.name_length = newkey_len;
+ new_prop_info.ce = definer_class;
+
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- str_efree(prop_info_ptr->name);
+ interned_name = zend_new_interned_string(new_prop_info.name, new_prop_info.name_length+1, 0 TSRMLS_CC);
+ if (interned_name != new_prop_info.name) {
+ efree((char*)new_prop_info.name);
+ new_prop_info.name = interned_name;
+ }
#endif
- prop_info_ptr->name = newkey;
- prop_info_ptr->name_length = newkey_len;
- prop_info_ptr->h = zend_get_hash_value(prop_info_ptr->name, prop_info_ptr->name_length + 1);
+
+ new_prop_info.h = zend_get_hash_value(new_prop_info.name, new_prop_info.name_length + 1);
+ new_prop_info.doc_comment = new_prop_info.doc_comment ? estrndup(new_prop_info.doc_comment, new_prop_info.doc_comment_len) : NULL;
+ zend_hash_quick_del(&ce->properties_info, (char *) propname, propname_len + 1, h);
+ zend_hash_quick_update(&ce->properties_info, (char *) propname, propname_len + 1, h, &new_prop_info, sizeof(zend_property_info), NULL);
+ pefree((void*)oldkey, ce->type & ZEND_INTERNAL_CLASS);
+ zend_hash_quick_find(&ce->properties_info, (char *) propname, propname_len + 1, h, (void*) &prop_info_ptr);
}
prop_info_ptr->ce = definer_class;
}
#endif // PHP_MAJOR_VERSION >= 5
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
- (apply_func_args_t)php_runkit_update_children_def_props, 7, ce, copyval,
- propname, propname_len, visibility, definer_class, override);
+ (apply_func_args_t)php_runkit_update_children_def_props, 8, ce, copyval,
+ propname, propname_len, visibility, definer_class, override, override_in_objects);
#if PHP_MAJOR_VERSION >= 5
if (!prop_info_ptr && zend_hash_quick_find(&ce->properties_info, (char *) propname, propname_len + 1, h, (void*) &prop_info_ptr) != SUCCESS) {
@@ -282,28 +399,108 @@ int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int
object = (zend_object *) EG(objects_store).object_buckets[i].bucket.obj.object;
if (object->ce == ce) {
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ int new_size = offset + 1;
if (!object->properties_table) {
- object->properties_table = pemalloc(sizeof(void*) * (offset + 1), 0);
+ object->properties_table = pemalloc(sizeof(void*) * (new_size), 0);
+ memset(object->properties_table, 0, new_size * sizeof(void *));
} else {
- object->properties_table = perealloc(object->properties_table, sizeof(void*) * (offset + 1), 0);
+ object->properties_table = perealloc(object->properties_table, sizeof(void*) * (new_size), 0);
+ object->properties_table[new_size - 1] = NULL;
}
-
if (ce->default_properties_table[offset]) {
if (!object->properties) {
- object->properties_table[offset] = ce->default_properties_table[offset];
+ if (override_in_objects) {
+ Z_ADDREF_P(ce->default_properties_table[offset]);
+ object->properties_table[offset] = ce->default_properties_table[offset];
+ } else {
+ if (object->properties_table[offset]) {
+ zval_ptr_dtor(&object->properties_table[offset]);
+ object->properties_table[offset] = NULL;
+ }
+ }
} else {
- zend_hash_quick_update(object->properties, propname, propname_len+1, h, &ce->default_properties_table[offset], sizeof(zval *), (void**)&object->properties_table[offset]);
+ zval **prop_val;
+ if (zend_hash_quick_find(object->properties, prop_info_ptr->name,
+ prop_info_ptr->name_length+1,
+ prop_info_ptr->h, (void *) &prop_val) != SUCCESS &&
+ (prop_info_ptr->h == h || zend_hash_quick_find(object->properties, propname,
+ propname_len+1,
+ h, (void *) &prop_val) != SUCCESS)) {
+ if (override_in_objects) {
+ if (object->properties_table[offset]) {
+ zval_ptr_dtor((zval **) object->properties_table[offset]);
+ object->properties_table[offset] = NULL;
+ }
+ object->properties_table[offset] = ce->default_properties_table[offset];
+#if ZTS
+ ALLOC_ZVAL(object->properties_table[offset]);
+ MAKE_COPY_ZVAL(&ce->default_properties_table[offset], object->properties_table[offset]);
+#else
+ Z_ADDREF_P(ce->default_properties_table[offset]);
+#endif
+ zend_hash_quick_update(object->properties, prop_info_ptr->name, prop_info_ptr->name_length+1,
+ prop_info_ptr->h, &object->properties_table[offset], sizeof(zval *),
+ (void*)&object->properties_table[offset]);
+ if (prop_info_ptr->h != h) {
+ zend_hash_quick_del(object->properties, propname, propname_len+1, h);
+ }
+ }
+ } else {
+ if (!override_in_objects) {
+ object->properties_table[offset] = (zval *) *prop_val;
+ Z_ADDREF_P(object->properties_table[offset]);
+ zend_hash_quick_update(object->properties, prop_info_ptr->name,
+ prop_info_ptr->name_length+1, prop_info_ptr->h,
+ &object->properties_table[offset],
+ sizeof(zval *),
+ (void*)&object->properties_table[offset]);
+ if (prop_info_ptr->h != h) {
+ zend_hash_quick_del(object->properties, propname, propname_len+1, h);
+ }
+ } else {
+ object->properties_table[offset] = ce->default_properties_table[offset];
+ Z_ADDREF_P(object->properties_table[offset]);
+ zend_hash_quick_update(object->properties, prop_info_ptr->name,
+ prop_info_ptr->name_length+1, prop_info_ptr->h,
+ &object->properties_table[offset],
+ sizeof(zval *),
+ (void*)&object->properties_table[offset]);
+ }
+ }
}
- Z_ADDREF_P(ce->default_properties_table[offset]);
}
#else
if (!object->properties) {
ALLOC_HASHTABLE(object->properties);
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
}
- Z_ADDREF_P(pcopyval);
- zend_hash_quick_del(object->properties, (char *) prop_info_ptr->name, prop_info_ptr->name_length + 1, prop_info_ptr->h);
- zend_hash_quick_add(object->properties, (char *) prop_info_ptr->name, prop_info_ptr->name_length + 1, prop_info_ptr->h, &pcopyval, sizeof(zval *), NULL);
+ if (override_in_objects) {
+ Z_ADDREF_P(pcopyval);
+ zend_hash_quick_del(object->properties, (char *) prop_info_ptr->name,
+ prop_info_ptr->name_length + 1, prop_info_ptr->h);
+ zend_hash_quick_add(object->properties, (char *) prop_info_ptr->name,
+ prop_info_ptr->name_length + 1, prop_info_ptr->h, &pcopyval,
+ sizeof(zval *), NULL);
+ } else {
+ zval **prop_val = NULL;
+ if (zend_hash_quick_find(object->properties, prop_info_ptr->name,
+ prop_info_ptr->name_length+1,
+ prop_info_ptr->h, (void *) &prop_val) != SUCCESS &&
+ (prop_info_ptr->h == h ||
+ zend_hash_quick_find(object->properties, (char *) propname, propname_len+1,
+ h, (void *) &prop_val) != SUCCESS)) {
+ } else if (prop_info_ptr->h != h && prop_val) {
+ zval **foo;
+ Z_ADDREF_P(*prop_val);
+ if (PZVAL_IS_REF(*prop_val)) {
+ SEPARATE_ZVAL(prop_val);
+ }
+ zend_hash_quick_update(object->properties, prop_info_ptr->name,
+ prop_info_ptr->name_length+1,
+ prop_info_ptr->h, prop_val, sizeof(zval *), (void *) &foo);
+ zend_hash_quick_del(object->properties, (char *) propname, propname_len+1, h);
+ }
+ }
#endif // (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
}
}
@@ -316,7 +513,8 @@ int php_runkit_def_prop_add_int(zend_class_entry *ce, const char *propname, int
/* {{{ php_runkit_def_prop_add
*/
-static int php_runkit_def_prop_add(char *classname, int classname_len, char *propname, int propname_len, zval *value, long visibility TSRMLS_DC)
+static int php_runkit_def_prop_add(char *classname, int classname_len, char *propname, int propname_len, zval *value,
+ long visibility, int override_in_objects TSRMLS_DC)
{
zend_class_entry *ce;
zval *copyval;
@@ -361,7 +559,8 @@ static int php_runkit_def_prop_add(char *classname, int classname_len, char *pro
#endif // PHP_MAJOR_VERSION >= 5
- if (php_runkit_def_prop_add_int(ce, propname, propname_len, copyval, visibility, NULL, 0, ce, 0 TSRMLS_CC) != SUCCESS) {
+ if (php_runkit_def_prop_add_int(ce, propname, propname_len, copyval, visibility, NULL, 0, ce, 0,
+ override_in_objects TSRMLS_CC) != SUCCESS) {
return FAILURE;
}
@@ -369,9 +568,37 @@ static int php_runkit_def_prop_add(char *classname, int classname_len, char *pro
}
/* }}} */
-/* {{{ php_runkit_def_prop_remove */
-int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *definer_class,
- int parent_offset, zend_bool was_static TSRMLS_DC)
+/* {{{ php_runkit_dump_string */
+static inline void php_runkit_dump_string(const char *str, int len) {
+ int j;
+ for (j=0; j<len; j++) {
+ printf("%c", str[j]);
+ }
+}
+/* }}} */
+
+/* {{{ php_runkit_dump_hashtable_keys */
+static inline void php_runkit_dump_hashtable_keys(HashTable* ht) {
+ HashPosition pos;
+ void *ptr;
+ for(zend_hash_internal_pointer_end_ex(ht, &pos);
+ zend_hash_get_current_data_ex(ht, (void*)&ptr, &pos) == SUCCESS;
+ zend_hash_move_backwards_ex(ht, &pos)) {
+ printf("key = ");
+ php_runkit_dump_string(pos->arKey, pos->nKeyLength);
+ }
+}
+/* }}} */
+
+/* {{{ php_runkit_def_prop_remove_int */
+int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, int propname_len, zend_class_entry *class_we_originally_removing_from,
+ zend_bool was_static, zend_bool remove_from_objects,
+#ifdef ZEND_ENGINE_2
+ zend_property_info *parent_property
+#else
+ void *parent_property
+#endif
+ TSRMLS_DC)
{
#if PHP_MAJOR_VERSION == 4
/* Resolve the property's name */
@@ -383,7 +610,8 @@ int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, i
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to remove the property from class: %s::%s", ce->name, propname);
return FAILURE;
}
- zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t)php_runkit_remove_children_def_props, 6, ce, propname, propname_len, -1, 0, NULL);
+ zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t)php_runkit_remove_children_def_props, 8, ce, propname, propname_len, NULL, 0, 0, NULL, -1);
+ return SUCCESS;
#else
int i;
long h;
@@ -395,32 +623,23 @@ int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, i
h = zend_get_hash_value((char *) propname, propname_len + 1);
if (zend_hash_quick_find(&ce->properties_info, (char *) propname, propname_len + 1, h, (void*)&property_info_ptr) == SUCCESS) {
- if (definer_class && property_info_ptr->ce != definer_class) {
-#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
- char *private;
- int private_len;
- zend_mangle_property_name(&private, &private_len, definer_class->name, definer_class->name_length, (char *) propname, propname_len, 0);
- php_runkit_remove_property_from_reflection_objects(ce, private, private_len TSRMLS_CC);
- if (zend_hash_exists(&ce->default_properties, private, private_len + 1)) {
- zend_hash_del(&ce->default_properties, private, private_len + 1);
- }
- if (zend_hash_exists(&ce->default_static_members, private, private_len + 1)) {
- zend_hash_del(&ce->default_static_members, private, private_len + 1);
- }
- efree(private);
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_remove_children_def_props,
- 6, ce, propname, propname_len, definer_class, -1, 0);
-#elif (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- if (parent_offset >= 0 && parent_offset != property_info_ptr->offset) {
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
- (apply_func_args_t)php_runkit_remove_shadowed_property_from_childs,
- 5, ce, propname, propname_len, parent_offset, was_static);
- }
+ if (class_we_originally_removing_from == NULL) {
+ class_we_originally_removing_from = property_info_ptr->ce;
+ }
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ if (parent_property &&
+ ((parent_property->offset >= 0 && parent_property->offset != property_info_ptr->offset) ||
+ parent_property->ce != property_info_ptr->ce ||
+ ((parent_property->flags & ZEND_ACC_STATIC) != (property_info_ptr->flags & ZEND_ACC_STATIC))
+ )) {
+ return SUCCESS;
+ }
#endif // PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+
+ if (class_we_originally_removing_from != property_info_ptr->ce) {
return SUCCESS;
- } else if (!definer_class) {
- definer_class = property_info_ptr->ce;
}
+
if (property_info_ptr->flags & ZEND_ACC_STATIC) {
was_static = 1;
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
@@ -437,56 +656,57 @@ int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, i
#endif // (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
} else {
was_static = 0;
-#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- if (ce->default_properties_table[property_info_ptr->offset]) {
- zval_ptr_dtor(&ce->default_properties_table[property_info_ptr->offset]);
- ce->default_properties_table[property_info_ptr->offset] = NULL;
- }
-#else
+#if !(PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) && (PHP_MAJOR_VERSION <= 5)
php_runkit_remove_property_from_reflection_objects(ce, property_info_ptr->name, property_info_ptr->name_length TSRMLS_CC);
- if (zend_hash_quick_del(&ce->default_properties, property_info_ptr->name, property_info_ptr->name_length + 1, property_info_ptr->h) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to remove the property %s->%s", ce->name, propname);
- return FAILURE;
- }
-#endif // (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+#endif // !(PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) && (PHP_MAJOR_VERSION <= 5)
}
flags = property_info_ptr->flags;
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
offset = property_info_ptr->offset;
- if (property_info_ptr->flags & ZEND_ACC_PRIVATE) {
+ if (property_info_ptr->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
if (offset >= 0) {
zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
- (apply_func_args_t)php_runkit_remove_shadowed_property_from_childs,
- 5, ce, propname, propname_len, offset, property_info_ptr->flags & ZEND_ACC_STATIC);
+ (apply_func_args_t)php_runkit_remove_overlapped_property_from_childs,
+ 8, ce, propname, propname_len, offset,
+ property_info_ptr->flags & ZEND_ACC_STATIC, remove_from_objects, property_info_ptr);
}
}
+#elif PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4
+ if (property_info_ptr->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
+ zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
+ (apply_func_args_t)php_runkit_remove_overlapped_property_from_childs,
+ 8, ce, propname, propname_len, 0,
+ property_info_ptr->flags & ZEND_ACC_STATIC, remove_from_objects, property_info_ptr);
+ }
#endif
- zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)), (apply_func_args_t)php_runkit_remove_children_def_props,
- 6, ce, propname, propname_len, definer_class,
+ zend_hash_apply_with_arguments(RUNKIT_53_TSRMLS_PARAM(EG(class_table)),
+ (apply_func_args_t)php_runkit_remove_children_def_props,
+ 8, ce, propname, propname_len, class_we_originally_removing_from,
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- offset, was_static
+ was_static
#else
- -1, 0
+ 0
#endif
+ , remove_from_objects, property_info_ptr
);
php_runkit_remove_property_from_reflection_objects(ce, propname, propname_len TSRMLS_CC);
- if (zend_hash_quick_del(&ce->properties_info, (char *) propname, propname_len + 1, h) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to remove the property %s::%s", ce->name, propname);
- return FAILURE;
- }
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
#endif
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::%s does not exist", ce->name, propname);
- return FAILURE;
+ if (parent_property) {
+ return SUCCESS;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::%s does not exist", ce->name, propname);
+ return FAILURE;
+ }
}
if ((flags & ZEND_ACC_STATIC) || !EG(objects_store).object_buckets) {
- return SUCCESS;
+ goto st_success;
}
for (i = 1; i < EG(objects_store).top ; i++) {
if (EG(objects_store).object_buckets[i].valid && (!EG(objects_store).object_buckets[i].destructor_called) &&
@@ -495,30 +715,91 @@ int php_runkit_def_prop_remove_int(zend_class_entry *ce, const char *propname, i
object = (zend_object *) EG(objects_store).object_buckets[i].bucket.obj.object;
if (object->ce == ce) {
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
- if (object->properties_table[offset]) {
+ if (!remove_from_objects) {
+ zval *prop_val = NULL;
if (!object->properties) {
- zval_ptr_dtor(&object->properties_table[offset]);
- } else {
- zend_hash_quick_del(object->properties, propname, propname_len+1, h);
+ prop_val = object->properties_table[offset];
+ rebuild_object_properties(object);
+ } else if (object->properties_table[offset]) {
+ prop_val = *(zval **) object->properties_table[offset];
+ }
+ if ((property_info_ptr->flags & (ZEND_ACC_PRIVATE | ZEND_ACC_PROTECTED | ZEND_ACC_SHADOW)) && prop_val) {
+ Z_ADDREF_P(prop_val);
+ if (h != property_info_ptr->h) {
+ zend_hash_quick_del(object->properties, property_info_ptr->name, property_info_ptr->name_length+1, property_info_ptr->h);
+ }
+ zend_hash_quick_update(object->properties, propname, propname_len+1, h,
+ &prop_val, sizeof(zval *), (void *) &object->properties_table[offset]);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Making %s::%s public to remove it from class without objects overriding", ce->name, propname);
+ }
+ } else {
+ if (object->properties_table[offset]) {
+ if (!object->properties) {
+ zval_ptr_dtor(&object->properties_table[offset]);
+ object->properties_table[offset] = NULL;
+ } else {
+ zend_hash_quick_del(object->properties, property_info_ptr->name, property_info_ptr->name_length+1,
+ property_info_ptr->h);
+ }
}
- object->properties_table[offset] = NULL;
}
#else
if (object->properties) {
- zend_hash_del(object->properties, (char *) propname, propname_len + 1);
+ if (remove_from_objects) {
+ zend_hash_quick_del(object->properties, (char *) property_info_ptr->name, property_info_ptr->name_length + 1,
+ property_info_ptr->h);
+ } else {
+ if (property_info_ptr->flags & (ZEND_ACC_PRIVATE | ZEND_ACC_PROTECTED)) {
+ zval **prop_val;
+ if (zend_hash_quick_find(object->properties, (char *) property_info_ptr->name,
+ property_info_ptr->name_length + 1,
+ property_info_ptr->h, (void *) &prop_val) == SUCCESS) {
+ if (h != property_info_ptr->h) {
+ Z_ADDREF_P(*prop_val);
+ if (PZVAL_IS_REF(*prop_val)) {
+ SEPARATE_ZVAL(prop_val);
+ }
+ zend_hash_quick_update(object->properties, (char *) propname,
+ propname_len+1, h, prop_val,
+ sizeof(zval *), (void *) NULL);
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE,
+ "Making %s::%s public to remove it from class without objects overriding",
+ ce->name, propname);
+ zend_hash_quick_del(object->properties,
+ property_info_ptr->name,
+ property_info_ptr->name_length+1,
+ property_info_ptr->h);
+ }
+ }
+ }
+ }
}
#endif
}
}
}
-#endif // PHP_MAJOR_VERSION == 4
+st_success:
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
+ if (was_static == 0 && ce->default_properties_table[property_info_ptr->offset]) {
+ zval_ptr_dtor(&ce->default_properties_table[property_info_ptr->offset]);
+ ce->default_properties_table[property_info_ptr->offset] = NULL;
+ }
+#else
+ if (was_static == 0) {
+ zend_hash_quick_del(&ce->default_properties, property_info_ptr->name, property_info_ptr->name_length + 1,
+ property_info_ptr->h);
+ }
+#endif
+ zend_hash_quick_del(&ce->properties_info, (char *) propname, propname_len + 1, h);
return SUCCESS;
+#endif // PHP_MAJOR_VERSION == 4
}
/* }}} */
/* {{{ php_runkit_def_prop_remove */
-static int php_runkit_def_prop_remove(char *classname, int classname_len, char *propname, int propname_len TSRMLS_DC)
+static int php_runkit_def_prop_remove(char *classname, int classname_len, char *propname, int propname_len,
+ zend_bool remove_from_objects TSRMLS_DC)
{
zend_class_entry *ce;
@@ -534,7 +815,7 @@ static int php_runkit_def_prop_remove(char *classname, int classname_len, char *
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
php_runkit_clear_all_functions_runtime_cache(TSRMLS_C);
#endif
- return php_runkit_def_prop_remove_int(ce, propname, propname_len, NULL, -1, 0 TSRMLS_CC);
+ return php_runkit_def_prop_remove_int(ce, propname, propname_len, NULL, 0, remove_from_objects, NULL TSRMLS_CC);
}
/* }}} */
@@ -592,17 +873,30 @@ PHP_FUNCTION(runkit_default_property_add)
char *classname, *propname;
int classname_len, propname_len;
zval *value;
- long visibility;
+ long visibility = 0;
+ int override_in_objects = 0;
#ifdef ZEND_ENGINE_2
visibility = ZEND_ACC_PUBLIC;
#endif
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/s/z|l", &classname, &classname_len, &propname, &propname_len, &value, &visibility) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/s/z|l/", &classname, &classname_len, &propname, &propname_len,
+ &value, &visibility) == FAILURE) {
RETURN_FALSE;
}
- RETURN_BOOL(php_runkit_def_prop_add(classname, classname_len, propname, propname_len, value, visibility TSRMLS_CC) == SUCCESS);
+ override_in_objects = (visibility & PHP_RUNKIT_OVERRIDE_OBJECTS) != 0;
+
+#ifndef ZEND_ENGINE_2
+ if (override_in_objects) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Overriding in objects is not supported for PHP versions below 5.0");
+ override_in_objects = 0;
+ }
+#endif
+
+ visibility &= ~PHP_RUNKIT_OVERRIDE_OBJECTS;
+
+ RETURN_BOOL(php_runkit_def_prop_add(classname, classname_len, propname, propname_len, value, visibility, override_in_objects TSRMLS_CC) == SUCCESS);
}
/* }}} */
@@ -611,14 +905,24 @@ Remove a property from a class
*/
PHP_FUNCTION(runkit_default_property_remove)
{
- char *classname, *propname;
- int classname_len, propname_len;
+ char *classname, *propname;
+ int classname_len, propname_len;
+ zend_bool remove_from_objects = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/s/|b", &classname, &classname_len, &propname, &propname_len,
+ &remove_from_objects) == FAILURE) {
+ RETURN_FALSE;
+ }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/s/", &classname, &classname_len, &propname, &propname_len) == FAILURE) {
- RETURN_FALSE;
- }
+#ifndef ZEND_ENGINE_2
+ if (remove_from_objects) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Removing from objects is not supported for PHP versions below 5.0");
+ remove_from_objects = 0;
+ }
+#endif
- RETURN_BOOL(php_runkit_def_prop_remove(classname, classname_len, propname, propname_len TSRMLS_CC) == SUCCESS);
+ RETURN_BOOL(php_runkit_def_prop_remove(classname, classname_len, propname, propname_len,
+ remove_from_objects TSRMLS_CC) == SUCCESS);
}
/* }}} */
#endif /* PHP_RUNKIT_MANIPULATION */
View
2  tests/runkit_default_property_add.phpt
@@ -20,7 +20,7 @@ runkit_default_property_add($className, $propName, $value, RUNKIT_ACC_PUBLIC);
runkit_default_property_add($className, 'privateProperty', "a", RUNKIT_ACC_PRIVATE);
runkit_default_property_add($className, 'protectedProperty', NULL, RUNKIT_ACC_PROTECTED);
$obj = new $className();
-runkit_default_property_add($className, 'dynamic', $obj);
+runkit_default_property_add($className, 'dynamic', $obj, RUNKIT_OVERRIDE_OBJECTS);
$value = 10;
print_r(new $className());
View
18 tests/runkit_default_property_add_and_remove_for_class_with_dynamic_properties.phpt
@@ -21,8 +21,11 @@ runkit_default_property_add('A', 'b', 2);
echo 'b=', $o->b, "\n";
echo 'd=', $o->d, "\n";
runkit_default_property_remove('A', 'b');
-echo 'b=', @$o->b, "\n";
+$o1 = new A;
+echo 'b=', $o->b, "\n";
+echo 'b=', @$o1->b, "\n";
echo 'd=', $o->d, "\n";
+echo 'd=', $o1->d, "\n";
echo "\n";
@@ -36,21 +39,28 @@ runkit_default_property_add('A', 'b', 2);
echo 'b=', $o->b, "\n";
echo 'd=', $o->d, "\n";
runkit_default_property_remove('A', 'b');
-echo 'b=', @$o->b, "\n";
+$o1 = new B;
+echo 'b=', $o->b, "\n";
+echo 'b=', @$o1->b, "\n";
echo 'd=', $o->d, "\n";
+echo 'd=', $o1->d, "\n";
--EXPECT--
b=1
d=3
-b=2
+b=1
d=3
+b=1
b=
d=3
+d=3
b=
d=3
b=1
d=3
-b=2
+b=1
d=3
+b=1
b=
d=3
+d=3
View
72 tests/runkit_default_property_add_and_remove_for_class_with_dynamic_properties_overriding_in_objects.phpt
@@ -0,0 +1,72 @@
+--TEST--
+runkit_default_property_add() and runkit_default_property_remove() functions on classes having dynamic properties overriding in objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode('.', PHP_VERSION)) < 5) print "skip";
+?>
+--FILE--
+<?php
+class A {
+ var $d=3;
+}
+
+class B extends A {
+}
+
+$o = new A;
+$o->b = 1;
+echo 'b=', $o->b, "\n";
+echo 'd=', $o->d, "\n";
+runkit_default_property_add('A', 'b', 2, RUNKIT_OVERRIDE_OBJECTS);
+echo 'b=', $o->b, "\n";
+echo 'd=', $o->d, "\n";
+runkit_default_property_remove('A', 'b');
+$o1 = new A;
+echo 'b=', $o->b, "\n";
+echo 'b=', @$o1->b, "\n";
+echo 'd=', $o->d, "\n";
+echo 'd=', $o1->d, "\n";
+
+echo "\n";
+
+$o = new B;
+echo 'b=', @$o->b, "\n";
+echo 'd=', $o->d, "\n";
+$o->b = 1;
+echo 'b=', $o->b, "\n";
+echo 'd=', $o->d, "\n";
+runkit_default_property_add('A', 'b', 2, RUNKIT_OVERRIDE_OBJECTS);
+echo 'b=', $o->b, "\n";
+echo 'd=', $o->d, "\n";
+runkit_default_property_remove('A', 'b');
+$o1 = new B;
+echo 'b=', $o->b, "\n";
+echo 'b=', @$o1->b, "\n";
+echo 'd=', $o->d, "\n";
+echo 'd=', $o1->d, "\n";
+runkit_default_property_remove('A', 'd', 1);
+$o1 = new B;
+echo 'd=', @$o->d, "\n";
+echo 'd=', @$o1->d, "\n";
+--EXPECT--
+b=1
+d=3
+b=2
+d=3
+b=2
+b=
+d=3
+d=3
+
+b=
+d=3
+b=1
+d=3
+b=2
+d=3
+b=2
+b=
+d=3
+d=3
+d=
+d=
View
49 tests/runkit_default_property_add_overriding_objects.phpt
@@ -0,0 +1,49 @@
+--TEST--
+runkit_default_property_add() function with overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode('.', PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=on
+--FILE--
+<?php
+class RunkitClass {
+}
+
+$className = 'RunkitClass';
+$propName = 'publicProperty';
+$value = 1;
+$obj = new $className();
+runkit_default_property_add($className, 'constArray', array('a'=>1), RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, $propName, $value, RUNKIT_ACC_PUBLIC | RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, 'privateProperty', "a", RUNKIT_ACC_PRIVATE | RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, 'protectedProperty', NULL, RUNKIT_ACC_PROTECTED | RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, 'dynamic', $obj, RUNKIT_OVERRIDE_OBJECTS);
+$value = 10;
+print_r($obj);
+
+$obj = new stdClass();
+runkit_default_property_add('stdClass', 'str', 'test', RUNKIT_OVERRIDE_OBJECTS);
+print_r($obj);
+?>
+--EXPECTF--
+RunkitClass Object
+(
+ [constArray] => Array
+ (
+ [a] => 1
+ )
+
+ [publicProperty] => 1
+ [privateProperty%sprivate] => a
+ [protectedProperty:protected] =>%w
+%w[dynamic] => RunkitClass Object
+%w*RECURSION*%w
+)
+
+Warning: runkit_default_property_add(): Adding properties to internal classes is not allowed in %s on line %d
+stdClass Object
+(
+)
View
27 tests/runkit_default_property_add_overriding_objects4.phpt
@@ -0,0 +1,27 @@
+--TEST--
+runkit_default_property_add() function with objects overriding (PHP4)
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) != 4) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$className = 'RunkitClass';
+$obj = new $className();
+runkit_default_property_add($className, 'publicProperty', 1, RUNKIT_OVERRIDE_OBJECTS);
+print_r($obj);
+?>
+--EXPECTF--
+Warning: runkit_default_property_add(): Overriding in objects is not supported for PHP versions below 5.0 in %s on line %d
+runkitclass Object
+(
+)
View
4 tests/runkit_default_property_add_to_subclasses.phpt
@@ -52,8 +52,6 @@ RunkitSubClass Object
[publicProperty] => 1
[privateProperty%sprivate] => a
[protectedProperty:protected] =>%w
-%w[dynamic] => RunkitSubClass Object
-%w*RECURSION*%w
)
RunkitSubClass Object
(
@@ -75,8 +73,6 @@ RunkitSubClass Object
[publicProperty] => 1
[privateProperty%sprivate] => a
[protectedProperty:protected] =>%w
-%w[dynamic] => RunkitSubClass Object
-%w*RECURSION*%w
)
)
View
85 tests/runkit_default_property_add_to_subclasses_overriding_objects.phpt
@@ -0,0 +1,85 @@
+--TEST--
+runkit_default_property_add() add properties to subclasses overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode('.', PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=on
+--FILE--
+<?php
+class RunkitClass {
+ public function setPrivate() {$this->privateProperty = "b";}
+ public function setProtected() {$this->protectedProperty = 1;}
+}
+
+class RunkitSubClass extends RunkitClass {}
+class StdSubClass extends stdClass {}
+
+$className = 'RunkitClass';
+$propName = 'publicProperty';
+$parentObj = new $className;
+runkit_default_property_add($className, 'constArray', array('a'=>1), RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, $propName, 1, RUNKIT_ACC_PUBLIC | RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, 'privateProperty', "a", RUNKIT_ACC_PRIVATE | RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_add($className, 'protectedProperty', NULL, RUNKIT_ACC_PROTECTED | RUNKIT_OVERRIDE_OBJECTS);
+$obj = new RunkitSubClass;
+runkit_default_property_add($className, 'dynamic', $obj, RUNKIT_OVERRIDE_OBJECTS);
+
+$parentObj->constArray = array('b'=>2);
+$parentObj->publicProperty = 2;
+$parentObj->setPrivate();
+$parentObj->setProtected();
+$parentObj->dynamic = $parentObj;
+
+print_r($obj);
+print_r(new RunkitSubClass);
+
+$obj = new StdSubClass();
+runkit_default_property_add('StdSubClass', 'str', 'test', RUNKIT_OVERRIDE_OBJECTS);
+print_r($obj);
+?>
+--EXPECTF--
+RunkitSubClass Object
+(
+ [constArray] => Array
+ (
+ [a] => 1
+ )
+
+ [publicProperty] => 1
+ [privateProperty%sprivate] => a
+ [protectedProperty:protected] =>%w
+%w[dynamic] => RunkitSubClass Object
+%w*RECURSION*%w
+)
+RunkitSubClass Object
+(
+ [constArray] => Array
+ (
+ [a] => 1
+ )
+
+ [publicProperty] => 1
+ [privateProperty%sprivate] => a
+ [protectedProperty:protected] =>%w
+ [dynamic] => RunkitSubClass Object
+ (
+ [constArray] => Array
+ (
+ [a] => 1
+ )
+
+ [publicProperty] => 1
+ [privateProperty%sprivate] => a
+ [protectedProperty:protected] =>%w
+%w[dynamic] => RunkitSubClass Object
+%w*RECURSION*%w
+ )
+
+)
+StdSubClass Object
+(
+ [str] => test
+)
View
6 tests/runkit_default_property_remove.phpt
@@ -27,9 +27,11 @@ runkit_default_property_add($className, 'dynamic', $obj);
runkit_default_property_remove($className, 'dynamic');
runkit_default_property_remove($className, 'publicproperty');
runkit_default_property_remove($className, 'publicproperty');
-runkit_default_property_remove($className, 'privateProperty');
-runkit_default_property_remove($className, 'protectedProperty');
+@runkit_default_property_remove($className, 'privateProperty');
+@runkit_default_property_remove($className, 'protectedProperty');
runkit_default_property_remove($className, 'constArray');
+
+
print_r(new $className());
$obj = new stdClass();
View
19 tests/runkit_default_property_remove_and_add_for_class_with_dynamic_properties.phpt
@@ -1,5 +1,5 @@
--TEST--
-runkit_default_property_remove() and runkit_default_property_add() functions on classes having dynamic properties
+runkit_default_property_remove() and runkit_default_property_add() functions on classes having dynamic properties (without overriding objects)
--SKIPIF--
<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
if(array_shift(explode('.', PHP_VERSION)) < 5) print "skip";
@@ -29,6 +29,8 @@ echo $o->getC(), "\n";
echo $o->b, $o->d, "\n";
echo "remove\n";
runkit_default_property_remove('A', 'c');
+$o1 = new B;
+echo $o1->getC(), "\n";
echo $o->getC(), "\n";
echo $o->b, $o->d, "\n";
echo "add private\n";
@@ -52,25 +54,26 @@ d
bd
remove
-Notice: Undefined property: B::$c in %s on line %d
-
+Notice: runkit_default_property_remove(): Making B::c public to remove it from class without objects overriding in %s on line %d
+1
bd
add public
-2
+1
bd
remove
Notice: Undefined property: B::$c in %s on line %d
+1
bd
add private
-3
+1
bd
remove
-Notice: Undefined property: B::$c in %s on line %d
-
+Notice: runkit_default_property_remove(): Making B::c public to remove it from class without objects overriding in %s on line %d
+1
bd
add public to B
-2
+1
bd
View
81 tests/runkit_default_property_remove_and_add_for_class_with_dynamic_properties_overriding_objects.phpt
@@ -0,0 +1,81 @@
+--TEST--
+runkit_default_property_remove() and runkit_default_property_add() functions on classes having dynamic properties (overriding objects)
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode('.', PHP_VERSION)) < 5) print "skip";
+?>
+--FILE--
+<?php
+class A {
+ private $c = 1;
+ public $d = 'd';
+ public function getC() {return $this->c;}
+}
+class B extends A {}
+
+$o = new B;
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+$o->b = 'b';
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "remove\n";
+runkit_default_property_remove('A', 'c', TRUE);
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "add public\n";
+runkit_default_property_add('A', 'c', 2, RUNKIT_OVERRIDE_OBJECTS);
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "remove\n";
+runkit_default_property_remove('A', 'c', TRUE);
+$o1 = new B;
+echo $o1->getC(), "\n";
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "add private\n";
+runkit_default_property_add('A', 'c', 3, RUNKIT_ACC_PRIVATE | RUNKIT_OVERRIDE_OBJECTS);
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "remove\n";
+runkit_default_property_remove('A', 'c', TRUE);
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+echo "add public to B\n";
+runkit_default_property_add('B', 'c', 2, RUNKIT_OVERRIDE_OBJECTS);
+echo $o->getC(), "\n";
+echo $o->b, $o->d, "\n";
+--EXPECTF--
+1
+
+Notice: Undefined property: B::$b in %s on line %d
+d
+1
+bd
+remove
+
+Notice: Undefined property: B::$c in %s on line %d
+
+bd
+add public
+2
+bd
+remove
+
+Notice: Undefined property: B::$c in %s on line %d
+
+
+Notice: Undefined property: B::$c in %s on line %d
+
+bd
+add private
+3
+bd
+remove
+
+Notice: Undefined property: B::$c in %s on line %d
+
+bd
+add public to B
+2
+bd
View
2  tests/runkit_default_property_remove_and_reflection.phpt
@@ -16,7 +16,7 @@ $reflClass = new ReflectionClass('RunkitClass');
$reflObject = new ReflectionObject($obj);
$reflProp = new ReflectionProperty('RunkitClass', 'publicProperty');
-runkit_default_property_remove('RunkitClass','publicProperty');
+runkit_default_property_remove('RunkitClass','publicProperty', TRUE);
try {
var_dump($reflClass->getProperty('publicProperty'));
View
6 tests/runkit_default_property_remove_from_subclasses.phpt
@@ -37,12 +37,16 @@ print_r(new RunkitSubClass());
$obj = new StdSubClass();
runkit_default_property_add('StdSubClass', 'str', "test");
-runkit_default_property_remove('StdSubClass', 'str');
+runkit_default_property_remove('StdSubClass', 'str', TRUE);
print_r($obj);
$obj = NULL;
?>
--EXPECTF--
Warning: runkit_default_property_remove(): RunkitClass::publicproperty does not exist in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubClass::protectedProperty public to remove it from class without objects overriding in %s on line %d
RunkitSubClass Object
(
[publicProperty] => 1
View
52 tests/runkit_default_property_remove_from_subclasses_overriding_objects.phpt
@@ -0,0 +1,52 @@
+--TEST--
+runkit_default_property_remove() remove properties from subclasses overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ public $constArray = array();
+ public $publicProperty = 1;
+ public $publicproperty = 2;
+ private $privateProperty = "a";
+ protected $protectedProperty = "b";
+}
+
+class RunkitSubClass extends RunkitClass {}
+class StdSubClass extends stdClass {}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$className = 'RunkitClass';
+$obj = new RunkitSubClass();
+runkit_default_property_add($className, 'dynamic', $obj, RUNKIT_OVERRIDE_OBJECTS);
+
+runkit_default_property_remove($className, 'dynamic', TRUE);
+runkit_default_property_remove($className, 'publicproperty', TRUE);
+runkit_default_property_remove($className, 'publicproperty', TRUE);
+runkit_default_property_remove($className, 'privateProperty', TRUE);
+runkit_default_property_remove($className, 'protectedProperty', TRUE);
+runkit_default_property_remove($className, 'constArray', TRUE);
+print_r($obj);
+
+$obj = new StdSubClass();
+runkit_default_property_add('StdSubClass', 'str', "test", RUNKIT_OVERRIDE_OBJECTS);
+runkit_default_property_remove('StdSubClass', 'str', TRUE);
+print_r($obj);
+$obj = NULL;
+?>
+--EXPECTF--
+Warning: runkit_default_property_remove(): RunkitClass::publicproperty does not exist in %s on line %d
+RunkitSubClass Object
+(
+ [publicProperty] => 1
+)
+StdSubClass Object
+(
+)
View
17 tests/runkit_default_property_remove_inheritance.phpt
@@ -22,6 +22,7 @@ class RunkitSubClass extends RunkitClass {
private $privateProperty = "aa";
protected $protectedProperty = "bb";
protected $staticProperty = "ss";
+ function getPrivate() {return $this->privateProperty;}
}
class RunkitSubSubClass extends RunkitSubClass {
protected $protectedProperty = "cc";
@@ -40,10 +41,19 @@ runkit_default_property_remove('RunkitSubClass', 'removedProperty');
runkit_default_property_remove($className, 'removedProperty');
print_r(new RunkitClass());
print_r(new RunkitSubClass());
-print_r(new $obj);
+$out = print_r($obj, true);
+$version = explode(".", PHP_VERSION);
+if ((int) $version[0] == 5 && (int) $version[1] < 4) {
+ $out = preg_replace("/\n\s+\[privateProperty:RunkitClass:private\] => a$/m", "", $out);
+}
+if ((int) $version[0] == 5 && (int) $version[1] < 3) {
+ $out = preg_replace("/\n\s+\[privateProperty:private\] => a$/m", "", $out);
+}
+print $out;
+print_r($obj->getPrivate());
?>
--EXPECTF--
-Warning: runkit_default_property_remove(): RunkitSubClass::removedProperty does not exist in %s on line %d
+Notice: runkit_default_property_remove(): Making RunkitSubSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
RunkitClass Object
(
)
@@ -60,4 +70,7 @@ RunkitSubSubClass Object
[publicProperty] => 2
[privateProperty%sprivate] => aa
[staticProperty:protected] => ss
+ [removedProperty] => r
+ [privateProperty] => a
)
+aa
View
61 tests/runkit_default_property_remove_inheritance_overriding_objects.phpt
@@ -0,0 +1,61 @@
+--TEST--
+runkit_default_property_remove() remove properties with inheritance overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ public $publicProperty = 1;
+ private $privateProperty = "a";
+ protected $protectedProperty = "b";
+ private static $staticProperty = "s";
+ public $removedProperty = "r";
+}
+
+class RunkitSubClass extends RunkitClass {
+ public $publicProperty = 2;
+ private $privateProperty = "aa";
+ protected $protectedProperty = "bb";
+ protected $staticProperty = "ss";
+ function getPrivate() {return $this->privateProperty;}
+}
+class RunkitSubSubClass extends RunkitSubClass {
+ protected $protectedProperty = "cc";
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$className = 'RunkitClass';
+$obj = new RunkitSubSubClass();
+
+runkit_default_property_remove($className, 'publicProperty', TRUE);
+runkit_default_property_remove($className, 'privateProperty', TRUE);
+runkit_default_property_remove($className, 'protectedProperty', TRUE);
+runkit_default_property_remove('RunkitSubClass', 'removedProperty', TRUE);
+runkit_default_property_remove($className, 'removedProperty', TRUE);
+$out = print_r($obj, true);
+/*$version = explode(".", PHP_VERSION);
+if ((int) $version[0] == 5 && (int) $version[1] < 4) {
+ $out = preg_replace("/\n\s+\[privateProperty:RunkitClass:private\] => a$/m", "", $out);
+}
+if ((int) $version[0] == 5 && (int) $version[1] < 3) {
+ $out = preg_replace("/\n\s+\[privateProperty:private\] => a$/m", "", $out);
+}*/
+print $out;
+print_r($obj->getPrivate());
+?>
+--EXPECTF--
+RunkitSubSubClass Object
+(
+ [protectedProperty:protected] => cc
+ [publicProperty] => 2
+ [privateProperty%sprivate] => aa
+ [staticProperty:protected] => ss
+)
+aa
View
46 tests/runkit_default_property_remove_overriding_objects.phpt
@@ -0,0 +1,46 @@
+--TEST--
+runkit_default_property_remove() function overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ public $constArray = array();
+ public $publicProperty = 1;
+ public $publicproperty = 2;
+ private $privateProperty = "a";
+ protected $protectedProperty = "b";
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$className = 'RunkitClass';
+$obj = new $className();
+runkit_default_property_add($className, 'dynamic', $obj, RUNKIT_OVERRIDE_OBJECTS);
+
+runkit_default_property_remove($className, 'dynamic', TRUE);
+runkit_default_property_remove($className, 'publicproperty', TRUE);
+runkit_default_property_remove($className, 'publicproperty', TRUE);
+runkit_default_property_remove($className, 'privateProperty', TRUE);
+runkit_default_property_remove($className, 'protectedProperty', TRUE);
+runkit_default_property_remove($className, 'constArray', TRUE);
+print_r($obj);
+
+$obj = new stdClass();
+runkit_default_property_remove('stdClass', 'str');
+$obj = NULL;
+?>
+--EXPECTF--
+Warning: runkit_default_property_remove(): RunkitClass::publicproperty does not exist in %s on line %d
+RunkitClass Object
+(
+ [publicProperty] => 1
+)
+
+Warning: runkit_default_property_remove(): Removing properties from internal classes is not allowed in %s on line %d
View
30 tests/runkit_default_property_remove_overriding_objects4.phpt
@@ -0,0 +1,30 @@
+--TEST--
+runkit_default_property_remove() function with overriding objects (PHP4)
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) != 4) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ var $publicProperty = 1;
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$className = 'RunkitClass';
+$obj = new $className();
+runkit_default_property_remove($className, 'publicProperty', TRUE);
+print_r($obj);
+
+?>
+--EXPECTF--
+Warning: runkit_default_property_remove(): Removing from objects is not supported for PHP versions below 5.0 in %s on line %d
+runkitclass Object
+(
+ [publicProperty] => 1
+)
View
94 tests/runkit_default_property_remove_private_and_inheritance.phpt
@@ -0,0 +1,94 @@
+--TEST--
+runkit_default_property_remove() remove private properties with inheritance
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ private $privateProperty = "original";
+ function getPrivate() {return $this->privateProperty;}
+}
+
+class RunkitSubClass extends RunkitClass {
+}
+
+class RunkitSubSubClass extends RunkitSubClass {
+ private $privateProperty = "overriden";
+ function getPrivate1() {return $this->privateProperty;}
+}
+
+class RunkitSubSubSubClass extends RunkitSubSubClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$obj = new RunkitClass();
+$objs = new RunkitSubClass();
+$objss = new RunkitSubSubClass();
+$objsss = new RunkitSubSubSubClass();
+
+runkit_default_property_remove('RunkitClass', 'privateProperty');
+print_r(new RunkitClass());
+print_r(new RunkitSubClass());
+print_r(new RunkitSubSubClass());
+print_r(new RunkitSubSubSubClass());
+print_r($obj);
+print_r($objs);
+print_r($objss);
+print_r($objsss);
+echo $obj->getPrivate(), "\n";
+echo $objs->getPrivate(), "\n";
+echo $objss->getPrivate1(), "\n";
+echo $objsss->getPrivate1(), "\n";
+?>
+--EXPECTF--
+Notice: runkit_default_property_remove(): Making RunkitSubSubSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+RunkitClass Object
+(
+)
+RunkitSubClass Object
+(
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+RunkitClass Object
+(
+ [privateProperty] => original
+)
+RunkitSubClass Object
+(
+ [privateProperty] => original
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty] => original
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty] => original
+)
+original
+original
+overriden
+overriden
+
View
69 tests/runkit_default_property_remove_private_and_inheritance_overriding_objects.phpt
@@ -0,0 +1,69 @@
+--TEST--
+runkit_default_property_remove() remove private properties with inheritance overriding objects
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ if(array_shift(explode(".", PHP_VERSION)) < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ private $privateProperty = "original";
+ function getPrivate() {return $this->privateProperty;}
+}
+
+class RunkitSubClass extends RunkitClass {
+}
+
+class RunkitSubSubClass extends RunkitSubClass {
+ private $privateProperty = "overriden";
+ function getPrivate1() {return $this->privateProperty;}
+}
+
+class RunkitSubSubSubClass extends RunkitSubSubClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$obj = new RunkitClass();
+$objs = new RunkitSubClass();
+$objss = new RunkitSubSubClass();
+$objsss = new RunkitSubSubSubClass();
+
+runkit_default_property_remove('RunkitClass', 'privateProperty', TRUE);
+print_r($obj);
+print_r($objs);
+print_r($objss);
+print_r($objsss);
+echo $obj->getPrivate(), "\n";
+echo $objs->getPrivate(), "\n";
+echo $objss->getPrivate1(), "\n";
+echo $objsss->getPrivate1(), "\n";
+?>
+--EXPECTF--
+RunkitClass Object
+(
+)
+RunkitSubClass Object
+(
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+
+Notice: Undefined property: RunkitClass::$privateProperty in %s on line %d
+
+
+Notice: Undefined property: RunkitSubClass::$privateProperty in %s on line %d
+
+overriden
+overriden
+
View
92 tests/runkit_default_property_remove_private_shadow_and_inheritance.phpt
@@ -0,0 +1,92 @@
+--TEST--
+runkit_default_property_remove() remove private properties with inheritance
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ $version = explode(".", PHP_VERSION);
+ if($version[0] < 5) print "skip";
+ if($version[0] == 5 && $version[1] >= 4) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ private $privateProperty = "original";
+ function getPrivate() {return $this->privateProperty;}
+}
+
+class RunkitSubClass extends RunkitClass {
+}
+
+class RunkitSubSubClass extends RunkitSubClass {
+ private $privateProperty = "overriden";
+ function getPrivate1() {return $this->privateProperty;}
+}
+
+class RunkitSubSubSubClass extends RunkitSubSubClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$obj = new RunkitClass();
+$objs = new RunkitSubClass();
+$objss = new RunkitSubSubClass();
+$objsss = new RunkitSubSubSubClass();
+
+runkit_default_property_remove('RunkitSubClass', 'privateProperty');
+print_r(new RunkitClass());
+print_r(new RunkitSubClass());
+print_r(new RunkitSubSubClass());
+print_r(new RunkitSubSubSubClass());
+print_r($obj);
+print_r($objs);
+print_r($objss);
+print_r($objsss);
+echo $obj->getPrivate(), "\n";
+echo $objs->getPrivate(), "\n";
+echo $objss->getPrivate(), "\n";
+echo $objsss->getPrivate(), "\n";
+?>
+--EXPECTF--
+RunkitClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubClass Object
+(
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty%sprivate] => original
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty%sprivate] => original
+)
+RunkitClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty%sprivate] => original
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty%sprivate] => original
+)
+original
+original
+original
+original
+
View
95 tests/runkit_default_property_remove_private_shadow_and_inheritance54.phpt
@@ -0,0 +1,95 @@
+--TEST--
+runkit_default_property_remove() remove private properties with inheritance
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ $version = explode(".", PHP_VERSION);
+ if($version[0] < 5) print "skip";
+ if($version[0] == 5 && $version[1] < 4) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ private $privateProperty = "original";
+ function getPrivate() {return $this->privateProperty;}
+}
+
+class RunkitSubClass extends RunkitClass {
+}
+
+class RunkitSubSubClass extends RunkitSubClass {
+ private $privateProperty = "overriden";
+ function getPrivate1() {return $this->privateProperty;}
+}
+
+class RunkitSubSubSubClass extends RunkitSubSubClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$obj = new RunkitClass();
+$objs = new RunkitSubClass();
+$objss = new RunkitSubSubClass();
+$objsss = new RunkitSubSubSubClass();
+
+runkit_default_property_remove('RunkitSubClass', 'privateProperty');
+print_r(new RunkitClass());
+print_r(new RunkitSubClass());
+print_r(new RunkitSubSubClass());
+print_r(new RunkitSubSubSubClass());
+print_r($obj);
+print_r($objs);
+print_r($objss);
+print_r($objsss);
+echo $obj->getPrivate(), "\n";
+echo $objs->getPrivate(), "\n";
+echo $objss->getPrivate(), "\n";
+echo $objsss->getPrivate(), "\n";
+?>
+--EXPECTF--
+Notice: runkit_default_property_remove(): Making RunkitSubSubSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+
+Notice: runkit_default_property_remove(): Making RunkitSubClass::privateProperty public to remove it from class without objects overriding in %s on line %d
+RunkitClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubClass Object
+(
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+RunkitClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubClass Object
+(
+ [privateProperty] => original
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty] => original
+)
+RunkitSubSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+ [privateProperty] => original
+)
+original
+original
+original
+original
+
View
90 tests/runkit_default_property_remove_private_shadow_and_inheritance_overriding_objects.phpt
@@ -0,0 +1,90 @@
+--TEST--
+runkit_default_property_remove() remove private properties with inheritance with objects overriding
+--SKIPIF--
+<?php if(!extension_loaded("runkit") || !RUNKIT_FEATURE_MANIPULATION) print "skip";
+ $version = explode(".", PHP_VERSION);
+ if($version[0] < 5) print "skip";
+?>
+--INI--
+error_reporting=E_ALL
+display_errors=On
+--FILE--
+<?php
+class RunkitClass {
+ private $privateProperty = "original";
+ function getPrivate() {return $this->privateProperty;}
+}
+
+class RunkitSubClass extends RunkitClass {
+}
+
+class RunkitSubSubClass extends RunkitSubClass {
+ private $privateProperty = "overriden";
+ function getPrivate1() {return $this->privateProperty;}
+}
+
+class RunkitSubSubSubClass extends RunkitSubSubClass {
+}
+
+ini_set('display_errors', 1);
+ini_set('error_reporting', E_ALL);
+
+$obj = new RunkitClass();
+$objs = new RunkitSubClass();
+$objss = new RunkitSubSubClass();
+$objsss = new RunkitSubSubSubClass();
+
+runkit_default_property_remove('RunkitSubClass', 'privateProperty', TRUE);
+print_r(new RunkitClass());
+print_r(new RunkitSubClass());
+print_r(new RunkitSubSubClass());
+print_r(new RunkitSubSubSubClass());
+print_r($obj);
+print_r($objs);
+print_r($objss);
+print_r($objsss);
+echo $obj->getPrivate(), "\n";
+echo $objs->getPrivate(), "\n";
+echo $objss->getPrivate(), "\n";
+echo $objsss->getPrivate(), "\n";
+?>
+--EXPECTF--
+RunkitClass Object
+(
+ [privateProperty%sprivate] => original
+)
+RunkitSubClass Object
+(
+)
+RunkitSubSubClass Object
+(
+ [privateProperty%sprivate] => overriden
+)
+R