Browse Source

MFH: Implement forward_static_call(_array) to complete LSB. Patch by Mike Lively

PECL
Etienne Kneuss 18 years ago
parent
commit
a1e0945143
  1. 1
      NEWS
  2. 76
      ext/standard/basic_functions.c
  3. 2
      ext/standard/basic_functions.h
  4. 83
      ext/standard/tests/class_object/forward_static_call_001.phpt
  5. 21
      ext/standard/tests/class_object/forward_static_call_002.phpt
  6. 51
      ext/standard/tests/class_object/forward_static_call_003.phpt

1
NEWS

@ -86,6 +86,7 @@ PHP NEWS
- Added PREG_BAD_UTF8_OFFSET_ERROR constant. (Nuno)
- Added request_order INI variable to control specifically $_REQUEST
behavior. (Stas)
- Added forward_static_call(_array) to complete LSB. (Mike Lively)
- Improved PHP runtime speed and memory usage:
. Replaced flex based scanner with re2c based scanner. (Marcus, Nuno, Scott)

76
ext/standard/basic_functions.c

@ -810,6 +810,19 @@ ZEND_BEGIN_ARG_INFO(arginfo_call_user_method_array, 0)
ZEND_ARG_INFO(0, params) /* ARRAY_INFO(0, params, 1) */
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_forward_static_call, 0, 0, 1)
ZEND_ARG_INFO(0, function_name)
ZEND_ARG_INFO(0, parameter)
ZEND_ARG_INFO(0, ...)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_forward_static_call_array, 0, 0, 2)
ZEND_ARG_INFO(0, function_name)
ZEND_ARG_INFO(0, parameters) /* ARRAY_INFO(0, parameters, 1) */
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO(arginfo_register_shutdown_function, 0)
ZEND_ARG_INFO(0, function_name)
@ -3364,6 +3377,8 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(call_user_func_array, arginfo_call_user_func_array)
PHP_DEP_FE(call_user_method, arginfo_call_user_method)
PHP_DEP_FE(call_user_method_array, arginfo_call_user_method_array)
PHP_FE(forward_static_call, arginfo_forward_static_call)
PHP_FE(forward_static_call_array, arginfo_forward_static_call_array)
PHP_FE(serialize, arginfo_serialize)
PHP_FE(unserialize, arginfo_unserialize)
@ -5228,6 +5243,67 @@ PHP_FUNCTION(call_user_method_array)
}
/* }}} */
/* {{{ proto mixed forward_static_call(mixed function_name [, mixed parmeter] [, mixed ...]) U
Call a user function which is the first parameter */
PHP_FUNCTION(forward_static_call)
{
zval *retval_ptr = NULL;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", &fci, &fci_cache, &fci.params, &fci.param_count) == FAILURE) {
return;
}
if (!EG(active_op_array)->scope) {
zend_error(E_ERROR, "Cannot call forward_static_call() when no class scope is active");
}
fci.retval_ptr_ptr = &retval_ptr;
if (EG(called_scope) &&
instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) {
fci_cache.calling_scope = EG(called_scope);
}
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) {
COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr);
}
if (fci.params) {
efree(fci.params);
}
}
/* }}} */
/* {{{ proto mixed call_user_func_array(string function_name, array parameters) U
Call a user function which is the first parameter with the arguments contained in array */
PHP_FUNCTION(forward_static_call_array)
{
zval *params, *retval_ptr = NULL;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "fa/", &fci, &fci_cache, &params) == FAILURE) {
return;
}
zend_fcall_info_args(&fci, params TSRMLS_CC);
fci.retval_ptr_ptr = &retval_ptr;
if (EG(called_scope) &&
instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) {
fci_cache.calling_scope = EG(called_scope);
}
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) {
COPY_PZVAL_TO_ZVAL(*return_value, *fci.retval_ptr_ptr);
}
zend_fcall_info_args_clear(&fci, 1);
}
/* }}} */
void user_shutdown_function_dtor(php_shutdown_function_entry *shutdown_function_entry) /* {{{ */
{
int i;

2
ext/standard/basic_functions.h

@ -84,6 +84,8 @@ PHP_FUNCTION(call_user_func);
PHP_FUNCTION(call_user_func_array);
PHP_FUNCTION(call_user_method);
PHP_FUNCTION(call_user_method_array);
PHP_FUNCTION(forward_static_call);
PHP_FUNCTION(forward_static_call_array);
PHP_FUNCTION(register_shutdown_function);
PHP_FUNCTION(highlight_file);

83
ext/standard/tests/class_object/forward_static_call_001.phpt

@ -0,0 +1,83 @@
--TEST--
forward_static_call() called from outside of a method.
--FILE--
<?php
class A
{
const NAME = 'A';
public static function test() {
echo static::NAME, "\n";
}
}
class B extends A
{
const NAME = 'B';
public static function test() {
echo self::NAME, "\n";
forward_static_call(array('parent', 'test'));
}
public static function test2() {
echo self::NAME, "\n";
forward_static_call(array('self', 'test'));
}
public static function test3() {
echo self::NAME, "\n";
forward_static_call(array('A', 'test'));
}
}
class C extends B
{
const NAME = 'C';
public static function test()
{
echo self::NAME, "\n";
forward_static_call(array('A', 'test'));
}
}
A::test();
echo "-\n";
B::test();
echo "-\n";
B::test2();
echo "-\n";
B::test3();
echo "-\n";
C::test();
echo "-\n";
C::test2();
echo "-\n";
C::test3();
?>
===DONE===
--EXPECTF--
A
-
B
B
-
B
B
B
-
B
B
-
C
C
-
B
B
C
-
B
C
===DONE===

21
ext/standard/tests/class_object/forward_static_call_002.phpt

@ -0,0 +1,21 @@
--TEST--
forward_static_call() from outside of a class method.
--FILE--
<?php
class A
{
public static function test() {
echo "A\n";
}
}
function test() {
forward_static_call(array('A', 'test'));
}
test();
?>
--EXPECTF--
Fatal error: Cannot call forward_static_call() when no class scope is active in %s on line %d

51
ext/standard/tests/class_object/forward_static_call_003.phpt

@ -0,0 +1,51 @@
--TEST--
forward_static_call() calling outside of the inheritance chain.
--FILE--
<?php
class A
{
const NAME = 'A';
public static function test() {
echo static::NAME, "\n";
}
}
class B extends A
{
const NAME = 'B';
public static function test() {
echo self::NAME, "\n";
forward_static_call(array('parent', 'test'));
}
}
class C
{
const NAME = 'C';
public static function test() {
echo self::NAME, "\n";
forward_static_call(array('B', 'test'));
}
}
A::test();
echo "-\n";
B::test();
echo "-\n";
C::test();
?>
===DONE===
--EXPECTF--
A
-
B
B
-
C
B
B
===DONE===
Loading…
Cancel
Save