add parent recursion support; package.xml
authorMichael Wallner <mike@php.net>
Mon, 4 Feb 2013 11:04:12 +0000 (12:04 +0100)
committerMichael Wallner <mike@php.net>
Mon, 4 Feb 2013 11:04:12 +0000 (12:04 +0100)
config.m4
package.xml [new file with mode: 0644]
php_propro.c

index f419731e7c47ac86d25915313713270c11a22cb7..925eebb605b99bfb332225f128356cb0e317e958 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -2,5 +2,6 @@ PHP_ARG_ENABLE(propro, whether to enable property proxy support,
 [  --enable-propro           Enable property proxy support])
 
 if test "$PHP_PROPRO" != "no"; then
+       PHP_INSTALL_HEADERS(ext/propro, php_propro.h)
        PHP_NEW_EXTENSION(propro, php_propro.c, $ext_shared)
 fi
diff --git a/package.xml b/package.xml
new file mode 100644 (file)
index 0000000..94b7ba2
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package 
+ packagerversion="1.4.11" 
+ version="2.0" 
+ xmlns="http://pear.php.net/dtd/package-2.0" 
+ xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" 
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+ xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>propro</name>
+ <channel>pecl.php.net</channel>
+ <summary>Property proxy</summary>
+ <description>A reusable split-off of pecl_http's property proxy API.</description>
+ <lead>
+  <name>Michael Wallner</name>
+  <user>mike</user>
+  <email>mike@php.net</email>
+  <active>yes</active>
+ </lead>
+ <date>2013-02-03</date>
+ <version>
+  <release>1.0.0</release>
+  <api>1.0.0</api>
+ </version>
+ <stability>
+  <release>stable</release>
+  <api>stable</api>
+ </stability>
+ <license>BSD, revised</license>
+ <notes><![CDATA[
+* Initial split-off release
+]]></notes>
+ <contents>
+  <dir name="/">
+   <file role="doc" name="CREDITS" />
+   <file role="doc" name="LICENSE" />
+   <file role="src" name="config.m4" />
+   <file role="src" name="php_propro.h" />
+   <file role="src" name="php_propro.c" />
+   <dir name="tests">
+    <file role="test" name="001.phpt" />
+   </dir>
+  </dir>
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.4</min>
+   </php>
+   <pearinstaller>
+    <min>1.4.0</min>
+   </pearinstaller>
+  </required>
+ </dependencies>
+ <providesextension>propro</providesextension>
+ <extsrcrelease>
+  <configureoption default="yes" name="enable-propro" prompt="whether to enable property proxy support" />
+ </extsrcrelease>
+</package>
+
index 07272b23fb57bdd1fd18acaef7b57dd163b30301..1b58fc7aee4e4dcc10c777d8c990b3b701db4eae 100644 (file)
@@ -91,18 +91,48 @@ PHP_PROPRO_API zend_object_value php_property_proxy_object_new_ex(zend_class_ent
        return o->zv;
 }
 
+static zval *get_parent_proxied_value(zval *object TSRMLS_DC);
 static zval *get_proxied_value(zval *object TSRMLS_DC);
 static zval *read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
 static STATUS cast_proxied_value(zval *object, zval *return_value, int type TSRMLS_DC);
 static void write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC);
 static void set_proxied_value(zval **object, zval *value TSRMLS_DC);
 
+static zval *get_parent_proxied_value(zval *object TSRMLS_DC)
+{
+       zval *value = NULL;
+       php_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
+
+       if (obj->proxy) {
+               if (obj->parent) {
+                       zval *parent;
+
+                       MAKE_STD_ZVAL(parent);
+                       parent->type = IS_OBJECT;
+                       parent->value.obj = obj->parent->zv;
+                       zend_objects_store_add_ref_by_handle(obj->parent->zv.handle TSRMLS_CC);
+                       value = get_proxied_value(parent TSRMLS_CC);
+                       zval_ptr_dtor(&parent);
+               }
+       }
+
+       return value;
+}
+
 static zval *get_proxied_value(zval *object TSRMLS_DC)
 {
        zval **hash_value, *value = NULL;
        php_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
 
        if (obj->proxy) {
+               if (obj->parent) {
+                       zval *parent_value = get_parent_proxied_value(object TSRMLS_CC);
+
+                       Z_ADDREF_P(parent_value);
+                       zval_ptr_dtor(&obj->proxy->container);
+                       obj->proxy->container = parent_value;
+               }
+
                switch (Z_TYPE_P(obj->proxy->container)) {
                case IS_OBJECT:
                        value = zend_read_property(Z_OBJCE_P(obj->proxy->container), obj->proxy->container, obj->proxy->member_str, obj->proxy->member_len, 0 TSRMLS_CC);
@@ -139,6 +169,14 @@ static void set_proxied_value(zval **object, zval *value TSRMLS_DC)
        php_property_proxy_object_t *obj = zend_object_store_get_object(*object TSRMLS_CC);
 
        if (obj->proxy) {
+               if (obj->parent) {
+                       zval *parent_value = get_parent_proxied_value(*object TSRMLS_CC);
+
+                       Z_ADDREF_P(parent_value);
+                       zval_ptr_dtor(&obj->proxy->container);
+                       obj->proxy->container = parent_value;
+               }
+
                switch (Z_TYPE_P(obj->proxy->container)) {
                case IS_OBJECT:
                        zend_update_property(Z_OBJCE_P(obj->proxy->container), obj->proxy->container, obj->proxy->member_str, obj->proxy->member_len, value TSRMLS_CC);
@@ -155,7 +193,9 @@ static void set_proxied_value(zval **object, zval *value TSRMLS_DC)
                        MAKE_STD_ZVAL(zparent);
                        zparent->type = IS_OBJECT;
                        zparent->value.obj = obj->parent->zv;
+                       zend_objects_store_add_ref_by_handle(obj->parent->zv.handle TSRMLS_CC);
                        set_proxied_value(&zparent, obj->proxy->container TSRMLS_CC);
+                       zval_ptr_dtor(&zparent);
                }
        }
 }
@@ -163,13 +203,12 @@ static void set_proxied_value(zval **object, zval *value TSRMLS_DC)
 static zval *read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
 {
        zval *value = NULL;
-       zval *proxied_value;
+       zval *proxied_value = get_proxied_value(object TSRMLS_CC);
+       zval *o = offset;
 
-       if ((proxied_value = get_proxied_value(object TSRMLS_CC))) {
-               zval *o = offset;
-
-               convert_to_string_ex(&o);
+       convert_to_string_ex(&o);
 
+       if (BP_VAR_R == type && proxied_value) {
                if (Z_TYPE_P(proxied_value) == IS_ARRAY) {
                        zval **hash_value;
                        if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(proxied_value), Z_STRVAL_P(o), Z_STRLEN_P(o), (void *) &hash_value)) {
@@ -177,25 +216,32 @@ static zval *read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
                                value = *hash_value;
                        }
                }
+       } else {
+               php_property_proxy_t *proxy;
+               php_property_proxy_object_t *proxy_obj;
 
-               if (!value) {
-                       zval **hash_value;
-
-                       SEPARATE_ZVAL(&proxied_value);
+               if (proxied_value) {
                        convert_to_array(proxied_value);
-
-                       MAKE_STD_ZVAL(value);
-                       ZVAL_NULL(value);
-                       zend_symtable_update(Z_ARRVAL_P(proxied_value), Z_STRVAL_P(o), Z_STRLEN_P(o) + 1, (void *) &value, sizeof(zval *), (void *) &hash_value);
-                       value = *hash_value;
-                       Z_SET_ISREF_P(value);
-
+                       Z_ADDREF_P(proxied_value);
+               } else {
+                       MAKE_STD_ZVAL(proxied_value);
+                       array_init(proxied_value);
                        set_proxied_value(&object, proxied_value TSRMLS_CC);
                }
 
-               if (o != offset) {
-                       zval_ptr_dtor(&o);
-               }
+               add_assoc_null_ex(proxied_value, Z_STRVAL_P(o), Z_STRLEN_P(o) + 1);
+
+               proxy = php_property_proxy_init(proxied_value, Z_STRVAL_P(o), Z_STRLEN_P(o) TSRMLS_CC);
+               zval_ptr_dtor(&proxied_value);
+               MAKE_STD_ZVAL(value);
+               Z_SET_REFCOUNT_P(value, 0);
+               value->type = IS_OBJECT;
+               value->value.obj = php_property_proxy_object_new_ex(php_property_proxy_get_class_entry(), proxy, &proxy_obj TSRMLS_CC);
+               proxy_obj->parent = zend_object_store_get_object(object TSRMLS_CC);
+               zend_objects_store_add_ref_by_handle(proxy_obj->parent->zv.handle TSRMLS_CC);
+       }
+       if (o && o != offset) {
+               zval_ptr_dtor(&o);
        }
 
        return value;
@@ -203,32 +249,35 @@ static zval *read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
 
 static void write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
 {
-       zval *proxied_value;
+       zval *proxied_value, *o = offset;
+       php_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
 
        if ((proxied_value = get_proxied_value(object TSRMLS_CC))) {
-               zval *o = offset;
-
-               SEPARATE_ZVAL(&proxied_value);
                convert_to_array(proxied_value);
+               Z_ADDREF_P(proxied_value);
+       } else {
+               MAKE_STD_ZVAL(proxied_value);
+               array_init(proxied_value);
+       }
 
-               if (Z_REFCOUNT_P(value) > 1) {
-                       SEPARATE_ZVAL(&value);
-               }
-               Z_ADDREF_P(value);
-
-               if (o) {
-                       convert_to_string_ex(&o);
-                       zend_symtable_update(Z_ARRVAL_P(proxied_value), Z_STRVAL_P(o), Z_STRLEN_P(o) + 1, (void *) &value, sizeof(zval *), NULL);
-               } else {
-                       zend_hash_next_index_insert(Z_ARRVAL_P(proxied_value), (void *) &value, sizeof(zval *), NULL);
-               }
+       if (Z_REFCOUNT_P(value) > 1) {
+               SEPARATE_ZVAL(&value);
+       }
+       Z_ADDREF_P(value);
 
-               if (o != offset) {
-                       zval_ptr_dtor(&o);
-               }
+       if (o) {
+               convert_to_string_ex(&o);
+               zend_symtable_update(Z_ARRVAL_P(proxied_value), Z_STRVAL_P(o), Z_STRLEN_P(o) + 1, (void *) &value, sizeof(zval *), NULL);
+       } else {
+               zend_hash_next_index_insert(Z_ARRVAL_P(proxied_value), (void *) &value, sizeof(zval *), NULL);
+       }
 
-               set_proxied_value(&object, proxied_value TSRMLS_CC);
+       if (o && o != offset) {
+               zval_ptr_dtor(&o);
        }
+
+       set_proxied_value(&object, proxied_value TSRMLS_CC);
+       zval_ptr_dtor(&proxied_value);
 }
 
 ZEND_BEGIN_ARG_INFO_EX(ai_propro_construct, 0, 0, 2)