/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: |
- +----------------------------------------------------------------------+
+ +--------------------------------------------------------------------+
+ | PECL :: propro |
+ +--------------------------------------------------------------------+
+ | Redistribution and use in source and binary forms, with or without |
+ | modification, are permitted provided that the conditions mentioned |
+ | in the accompanying LICENSE file are met. |
+ +--------------------------------------------------------------------+
+ | Copyright (c) 2013 Michael Wallner <mike@php.net> |
+ +--------------------------------------------------------------------+
*/
-/* $Id$ */
#ifdef HAVE_CONFIG_H
# include "config.h"
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);
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);
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);
}
}
}
static zval *read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
{
zval *value = NULL;
- zval *proxied_value;
-
- if ((proxied_value = get_proxied_value(object TSRMLS_CC))) {
- zval *o = offset;
+ zval *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)) {
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;
static void write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
{
- zval *proxied_value;
+ zval *proxied_value, *o = offset;
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)