mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
ext/zend_test: Test zend_call_method_if_exists()
This commit is contained in:
parent
a9f3e3c44e
commit
fc6c49cbf4
17 changed files with 391 additions and 1 deletions
|
@ -514,6 +514,28 @@ static ZEND_FUNCTION(zend_object_init_with_constructor)
|
||||||
ZVAL_COPY_VALUE(return_value, &obj);
|
ZVAL_COPY_VALUE(return_value, &obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ZEND_FUNCTION(zend_call_method_if_exists)
|
||||||
|
{
|
||||||
|
zend_object *obj = NULL;
|
||||||
|
zend_string *method_name;
|
||||||
|
uint32_t num_args = 0;
|
||||||
|
zval *args = NULL;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(2, -1)
|
||||||
|
Z_PARAM_OBJ(obj)
|
||||||
|
Z_PARAM_STR(method_name)
|
||||||
|
Z_PARAM_VARIADIC('*', args, num_args)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
zend_result status = zend_call_method_if_exists(obj, method_name, return_value, num_args, args);
|
||||||
|
if (status == FAILURE) {
|
||||||
|
ZEND_ASSERT(Z_ISUNDEF_P(return_value));
|
||||||
|
if (EG(exception)) {
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
RETURN_NULL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ZEND_FUNCTION(zend_get_unit_enum)
|
static ZEND_FUNCTION(zend_get_unit_enum)
|
||||||
{
|
{
|
||||||
ZEND_PARSE_PARAMETERS_NONE();
|
ZEND_PARSE_PARAMETERS_NONE();
|
||||||
|
|
|
@ -293,6 +293,8 @@ namespace {
|
||||||
|
|
||||||
function zend_object_init_with_constructor(string $class, mixed ...$args): mixed {}
|
function zend_object_init_with_constructor(string $class, mixed ...$args): mixed {}
|
||||||
|
|
||||||
|
function zend_call_method_if_exists(object $obj, string $method, mixed ...$args): mixed {}
|
||||||
|
|
||||||
function zend_test_zend_ini_parse_quantity(string $str): int {}
|
function zend_test_zend_ini_parse_quantity(string $str): int {}
|
||||||
function zend_test_zend_ini_parse_uquantity(string $str): int {}
|
function zend_test_zend_ini_parse_uquantity(string $str): int {}
|
||||||
|
|
||||||
|
|
10
ext/zend_test/test_arginfo.h
generated
10
ext/zend_test/test_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 13a5559e87cb073c921006bb3be5354b90247306 */
|
* Stub hash: 073039fa0d9c41eb842f6944eb4acfc9217103cf */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
@ -113,6 +113,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_object_init_with_constructo
|
||||||
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
|
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_call_method_if_exists, 0, 2, IS_MIXED, 0)
|
||||||
|
ZEND_ARG_TYPE_INFO(0, obj, IS_OBJECT, 0)
|
||||||
|
ZEND_ARG_TYPE_INFO(0, method, IS_STRING, 0)
|
||||||
|
ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_ini_parse_quantity, 0, 1, IS_LONG, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_ini_parse_quantity, 0, 1, IS_LONG, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
@ -293,6 +299,7 @@ static ZEND_FUNCTION(zend_test_attribute_with_named_argument);
|
||||||
static ZEND_FUNCTION(zend_get_current_func_name);
|
static ZEND_FUNCTION(zend_get_current_func_name);
|
||||||
static ZEND_FUNCTION(zend_call_method);
|
static ZEND_FUNCTION(zend_call_method);
|
||||||
static ZEND_FUNCTION(zend_object_init_with_constructor);
|
static ZEND_FUNCTION(zend_object_init_with_constructor);
|
||||||
|
static ZEND_FUNCTION(zend_call_method_if_exists);
|
||||||
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity);
|
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity);
|
||||||
static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity);
|
static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity);
|
||||||
static ZEND_FUNCTION(zend_test_zend_ini_str);
|
static ZEND_FUNCTION(zend_test_zend_ini_str);
|
||||||
|
@ -419,6 +426,7 @@ static const zend_function_entry ext_functions[] = {
|
||||||
ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name)
|
ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name)
|
||||||
ZEND_FE(zend_call_method, arginfo_zend_call_method)
|
ZEND_FE(zend_call_method, arginfo_zend_call_method)
|
||||||
ZEND_FE(zend_object_init_with_constructor, arginfo_zend_object_init_with_constructor)
|
ZEND_FE(zend_object_init_with_constructor, arginfo_zend_object_init_with_constructor)
|
||||||
|
ZEND_FE(zend_call_method_if_exists, arginfo_zend_call_method_if_exists)
|
||||||
ZEND_FE(zend_test_zend_ini_parse_quantity, arginfo_zend_test_zend_ini_parse_quantity)
|
ZEND_FE(zend_test_zend_ini_parse_quantity, arginfo_zend_test_zend_ini_parse_quantity)
|
||||||
ZEND_FE(zend_test_zend_ini_parse_uquantity, arginfo_zend_test_zend_ini_parse_uquantity)
|
ZEND_FE(zend_test_zend_ini_parse_uquantity, arginfo_zend_test_zend_ini_parse_uquantity)
|
||||||
ZEND_FE(zend_test_zend_ini_str, arginfo_zend_test_zend_ini_str)
|
ZEND_FE(zend_test_zend_ini_str, arginfo_zend_test_zend_ini_str)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with existing non public methods
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
protected function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
private function bar() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
||||||
|
NULL
|
|
@ -0,0 +1,23 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with existing public method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class C {
|
||||||
|
private function priv() {
|
||||||
|
var_dump(__METHOD__);
|
||||||
|
}
|
||||||
|
public function test() {
|
||||||
|
// this should call $c->priv()
|
||||||
|
zend_call_method_if_exists($this, 'priv');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = new C();
|
||||||
|
$c->test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(7) "C::priv"
|
|
@ -0,0 +1,21 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with existing public method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "A::foo"
|
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with existing non public static methods
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
protected static function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
private static function bar() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
||||||
|
NULL
|
|
@ -0,0 +1,21 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with existing static public method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public static function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "A::foo"
|
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method on extended class with a trampoline
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In A trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In B trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($b, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(24) "In B trampoline for bar!"
|
|
@ -0,0 +1,23 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method on extended class with a trampoline
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In A trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {}
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($b, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(24) "In A trampoline for bar!"
|
|
@ -0,0 +1,25 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with throwing method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
throw new Exception("Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Exception: Error
|
|
@ -0,0 +1,44 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method on class with a trampoline and static trampoline
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In A trampoline for $name!";
|
||||||
|
}
|
||||||
|
public static function __callStatic(string $name, array $arguments): string {
|
||||||
|
return "In A static trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
public static function __callStatic(string $name, array $arguments): string {
|
||||||
|
return "In B static trampoline for $name!";
|
||||||
|
}
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In B trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
$r = zend_call_method_if_exists($b, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(24) "In A trampoline for bar!"
|
||||||
|
string(24) "In B trampoline for bar!"
|
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method on class with a static trampoline
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
public static function __callStatic(string $name, array $arguments): string {
|
||||||
|
return "In static trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method on class with a trampoline
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(22) "In trampoline for bar!"
|
|
@ -0,0 +1,21 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() with non existing method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'bar');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() shadowing a private method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private function foo() {
|
||||||
|
return 'Not available';
|
||||||
|
}
|
||||||
|
public function __call(string $name, array $arguments): string {
|
||||||
|
return "In trampoline for $name!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = new A();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($a, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(22) "In trampoline for foo!"
|
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
zend_call_method_if_exists() shadowing a private method
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private function foo() {
|
||||||
|
return 'Not available';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
public function foo() {
|
||||||
|
return __METHOD__;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$b = new B();
|
||||||
|
|
||||||
|
$r = zend_call_method_if_exists($b, 'foo');
|
||||||
|
var_dump($r);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(6) "B::foo"
|
Loading…
Add table
Add a link
Reference in a new issue