Permalink
Browse files

Support for __get, __set and __call in classes.

This should work as follows: if class hasn't member with given name,
__get/__set is called. If class has no method with given name, __call is called.
__get/__set are not recursive, __call can be.
  • Loading branch information...
1 parent 1f49fb1 commit d8651c82cdd2ab28e21d9c7c9fe0742d107fd6e4 @smalyshev smalyshev committed Sep 4, 2002
Showing with 335 additions and 43 deletions.
  1. +7 −0 Zend/zend.h
  2. +12 −4 Zend/zend_compile.c
  3. +7 −0 Zend/zend_compile.h
  4. +38 −17 Zend/zend_execute.c
  5. +1 −1 Zend/zend_extensions.h
  6. +268 −21 Zend/zend_object_handlers.c
  7. +2 −0 Zend/zend_objects.c
View
@@ -226,6 +226,8 @@ typedef struct _zend_class_entry zend_class_entry;
typedef struct _zend_object {
zend_class_entry *ce;
HashTable *properties;
+ int in_get:1;
+ int in_set:1;
} zend_object;
typedef unsigned int zend_object_handle;
@@ -311,9 +313,14 @@ struct _zend_class_entry {
union _zend_function *constructor;
union _zend_function *destructor;
union _zend_function *clone;
+ union _zend_function *__get;
+ union _zend_function *__set;
+ union _zend_function *__call;
/* handlers */
zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);
+
+ /* old handlers */
void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
zval (*handle_property_get)(zend_property_reference *property_reference);
int (*handle_property_set)(zend_property_reference *property_reference, zval *value);
View
@@ -895,10 +895,6 @@ void zend_do_free(znode *op1 TSRMLS_DC)
}
}
-#define ZEND_CLONE_FUNC_NAME "__clone"
-#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct"
-#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct"
-
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference TSRMLS_DC)
{
zend_op_array op_array;
@@ -938,6 +934,12 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
} else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
+ CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
+ CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
+ } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
+ CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
}
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -1551,6 +1553,9 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
new_class_entry->constructor = NULL;
new_class_entry->destructor = NULL;
new_class_entry->clone = NULL;
+ new_class_entry->__get = NULL;
+ new_class_entry->__set = NULL;
+ new_class_entry->__call = NULL;
new_class_entry->create_object = NULL;
new_class_entry->handle_function_call = NULL;
@@ -2050,6 +2055,9 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
new_class_entry->constructor = NULL;
new_class_entry->destructor = NULL;
new_class_entry->clone = NULL;
+ new_class_entry->__get = NULL;
+ new_class_entry->__set = NULL;
+ new_class_entry->__call = NULL;
new_class_entry->create_object = NULL;
new_class_entry->handle_function_call = NULL;
View
@@ -710,4 +710,11 @@ int zendlex(znode *zendlval TSRMLS_DC);
END_EXTERN_C()
+#define ZEND_CLONE_FUNC_NAME "__clone"
+#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct"
+#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct"
+#define ZEND_GET_FUNC_NAME "__get"
+#define ZEND_SET_FUNC_NAME "__set"
+#define ZEND_CALL_FUNC_NAME "__call"
+
#endif /* ZEND_COMPILE_H */
View
@@ -140,7 +140,7 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC)
static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2, temp_variable *Ts, int type TSRMLS_DC)
{
zval *prop_ptr = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
- zval **retval;
+ zval **retval = NULL;
zval tmp;
@@ -161,7 +161,9 @@ static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2,
if(Z_OBJ_HT_P(object)->get_property_ptr != NULL) {
retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC);
- } else {
+ }
+
+ if(retval == NULL) {
zend_error(E_WARNING, "This object doesn't support property references");
retval = &EG(error_zval_ptr);
}
@@ -321,6 +323,7 @@ static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval tmp;
zval **retval = &Ts[result->u.var].var.ptr;
+ int have_get_ptr = 0;
Ts[result->u.var].var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
@@ -356,12 +359,17 @@ static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
- binary_op(*zptr, *zptr, value TSRMLS_CC);
- *retval = *zptr;
- SELECTIVE_PZVAL_LOCK(*retval, result);
- } else {
+ have_get_ptr = 1;
+ binary_op(*zptr, *zptr, value TSRMLS_CC);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ }
+ }
+
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
@@ -989,6 +997,7 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval **retval = &Ts[result->u.var].var.ptr;
+ int have_get_ptr = 0;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
@@ -1006,12 +1015,17 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
- incdec_op(*zptr);
- *retval = *zptr;
- SELECTIVE_PZVAL_LOCK(*retval, result);
- } else {
+ have_get_ptr = 1;
+ incdec_op(*zptr);
+ *retval = *zptr;
+ SELECTIVE_PZVAL_LOCK(*retval, result);
+ }
+ }
+
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
@@ -1030,6 +1044,7 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem
zval *object;
zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
zval *retval = &Ts[result->u.var].tmp_var;
+ int have_get_ptr = 0;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
@@ -1045,13 +1060,19 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, tem
if(Z_OBJ_HT_P(object)->get_property_zval_ptr) {
zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC);
- SEPARATE_ZVAL_IF_NOT_REF(zptr);
+ if(zptr != NULL) { /* NULL means no success in getting PTR */
+ have_get_ptr = 1;
+ SEPARATE_ZVAL_IF_NOT_REF(zptr);
+
+ *retval = **zptr;
+ zendi_zval_copy_ctor(*retval);
+
+ incdec_op(*zptr);
- *retval = **zptr;
- zendi_zval_copy_ctor(*retval);
+ }
+ }
- incdec_op(*zptr);
- } else {
+ if(!have_get_ptr) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC);
SEPARATE_ZVAL_IF_NOT_REF(&z);
*retval = *z;
View
@@ -23,7 +23,7 @@
#include "zend_compile.h"
-#define ZEND_EXTENSION_API_NO 20010710
+#define ZEND_EXTENSION_API_NO 220020901
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
Oops, something went wrong.

0 comments on commit d8651c8

Please sign in to comment.