cvs: ZendEngine2(PHP_5_3) / zend_object_handlers.c php-src NEWS

[email protected] ("Andrei Zmievski") Wed, 07 Jan 2009 22:12:39 -0000
Newsgroups php.zend-engine.cvs
Message-ID <cvsandrei1231366359@cvsserver>
andrei		Wed Jan  7 22:12:39 2009 UTC

  Modified files:              (Branch: PHP_5_3)
    /php-src	NEWS 
    /ZendEngine2	zend_object_handlers.c 
  Log:
  Changed __call() to be invoked on private/protected method access,
  similar to properties and __get().
  
  
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.437&r2=1.2027.2.547.2.965.2.438&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.437 php-src/NEWS:1.2027.2.547.2.965.2.438
--- php-src/NEWS:1.2027.2.547.2.965.2.437	Wed Jan  7 16:32:07 2009
+++ php-src/NEWS	Wed Jan  7 22:12:39 2009
@@ -1,6 +1,8 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2009, PHP 5.3.0 Alpha 4
+- Changed __call() to be invoked on private/protected method access, similar to
+  properties and __get(). (Andrei)
 - Upgraded bundled sqlite to version 3.6.7. (Scott)
 
 - Deprecated session_register(), session_unregister() and
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_object_handlers.c?r1=1.135.2.6.2.22.2.24&r2=1.135.2.6.2.22.2.25&diff_format=u
Index: ZendEngine2/zend_object_handlers.c
diff -u ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.24 ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.25
--- ZendEngine2/zend_object_handlers.c:1.135.2.6.2.22.2.24	Sat Jan  3 17:48:39 2009
+++ ZendEngine2/zend_object_handlers.c	Wed Jan  7 22:12:39 2009
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_object_handlers.c,v 1.135.2.6.2.22.2.24 2009/01/03 17:48:39 helly Exp $ */
+/* $Id: zend_object_handlers.c,v 1.135.2.6.2.22.2.25 2009/01/07 22:12:39 andrei Exp $ */
 
 #include "zend.h"
 #include "zend_globals.h"
@@ -781,6 +781,24 @@
 }
 /* }}} */
 
+static inline union _zend_function *zend_get_user_call_function(zend_object *zobj, char *method_name, int method_len) /* {{{ */
+{
+	zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
+	call_user_call->type = ZEND_INTERNAL_FUNCTION;
+	call_user_call->module = zobj->ce->module;
+	call_user_call->handler = zend_std_call_user_call;
+	call_user_call->arg_info = NULL;
+	call_user_call->num_args = 0;
+	call_user_call->scope = zobj->ce;
+	call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
+	call_user_call->function_name = estrndup(method_name, method_len);
+	call_user_call->pass_rest_by_reference = 0;
+	call_user_call->return_reference = ZEND_RETURN_VALUE;
+
+	return (union _zend_function *)call_user_call;
+}
+/* }}} */
+
 static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
 {
 	zend_object *zobj;
@@ -797,19 +815,7 @@
 	if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
 		free_alloca(lc_method_name, use_heap);
 		if (zobj->ce->__call) {
-			zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
-			call_user_call->type = ZEND_INTERNAL_FUNCTION;
-			call_user_call->module = zobj->ce->module;
-			call_user_call->handler = zend_std_call_user_call;
-			call_user_call->arg_info = NULL;
-			call_user_call->num_args = 0;
-			call_user_call->scope = zobj->ce;
-			call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
-			call_user_call->function_name = estrndup(method_name, method_len);
-			call_user_call->pass_rest_by_reference = 0;
-			call_user_call->return_reference = ZEND_RETURN_VALUE;
-
-			return (union _zend_function *)call_user_call;
+			return zend_get_user_call_function(zobj, method_name, method_len);
 		} else {
 			return NULL;
 		}
@@ -820,12 +826,18 @@
 		zend_function *updated_fbc;
 
 		/* Ensure that if we're calling a private function, we're allowed to do so.
+		 * If we're not and __call() handler exists, invoke it, otherwise error out.
 		 */
 		updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
-		if (!updated_fbc) {
-			zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+		if (updated_fbc) {
+			fbc = updated_fbc;
+		} else {
+			if (zobj->ce->__call) {
+				fbc = zend_get_user_call_function(zobj, method_name, method_len);
+			} else {
+				zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+			}
 		}
-		fbc = updated_fbc;
 	} else {
 		/* Ensure that we haven't overridden a private function and end up calling
 		 * the overriding public function...
@@ -843,9 +855,14 @@
 		}
 		if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
 			/* Ensure that if we're calling a protected function, we're allowed to do so.
+			 * If we're not and __call() handler exists, invoke it, otherwise error out.
 			 */
 			if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
-				zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+				if (zobj->ce->__call) {
+					fbc = zend_get_user_call_function(zobj, method_name, method_len);
+				} else {
+					zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+				}
 			}
 		}
 	}