From 0815f8d558b3e8def255a1b8103e08ffd5eb51f9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 11 Sep 2024 23:31:00 +0200 Subject: [PATCH] Implement ReflectionProperty::hasHook[s] --- ext/reflection/php_reflection.c | 35 +++++++++++++++++++ ext/reflection/php_reflection.stub.php | 4 +++ ext/reflection/php_reflection_arginfo.h | 12 ++++++- ...eflectionProperty_getHook_inheritance.phpt | 2 +- .../ReflectionProperty_getHooks.phpt | 5 +++ .../tests/property_hooks/basics.phpt | 31 ++++++++++++++++ 6 files changed, 87 insertions(+), 2 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index b8fe4180ccf27..14cde89f21cac 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6509,6 +6509,18 @@ ZEND_METHOD(ReflectionProperty, getDefaultValue) } /* }}} */ +ZEND_METHOD(ReflectionProperty, hasHooks) +{ + reflection_object *intern; + property_reference *ref; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(ref); + + RETURN_BOOL(ref->prop && ref->prop->hooks); +} + ZEND_METHOD(ReflectionProperty, getHooks) { reflection_object *intern; @@ -6538,6 +6550,29 @@ ZEND_METHOD(ReflectionProperty, getHooks) } } +ZEND_METHOD(ReflectionProperty, hasHook) +{ + + reflection_object *intern; + property_reference *ref; + zend_object *type; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OF_CLASS(type, reflection_property_hook_type_ptr) + ZEND_PARSE_PARAMETERS_END(); + + GET_REFLECTION_OBJECT_PTR(ref); + + zend_property_hook_kind kind; + if (zend_string_equals_literal(Z_STR_P(zend_enum_fetch_case_name(type)), "Get")) { + kind = ZEND_PROPERTY_HOOK_GET; + } else { + kind = ZEND_PROPERTY_HOOK_SET; + } + + RETURN_BOOL(ref->prop && ref->prop->hooks && ref->prop->hooks[kind]); +} + ZEND_METHOD(ReflectionProperty, getHook) { reflection_object *intern; diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 5db496db1f447..eb5ae7169119d 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -557,9 +557,13 @@ public function getDefaultValue(): mixed {} public function getAttributes(?string $name = null, int $flags = 0): array {} + public function hasHooks(): bool {} + /** @return array */ public function getHooks(): array {} + public function hasHook(PropertyHookType $type): bool {} + public function getHook(PropertyHookType $type): ?ReflectionMethod {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index b7913404b043e..e96a5442c4e7c 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8faf835d31acf3ae3e12a0dfca56f0744b95831b */ + * Stub hash: 83e9d4a4b2f49739af3e7faa3037df13e779bb8b */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -448,8 +448,14 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionProperty_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes +#define arginfo_class_ReflectionProperty_hasHooks arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + #define arginfo_class_ReflectionProperty_getHooks arginfo_class_ReflectionFunctionAbstract_getClosureUsedVariables +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_hasHook, 0, 1, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, type, PropertyHookType, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionProperty_getHook, 0, 1, ReflectionMethod, 1) ZEND_ARG_OBJ_INFO(0, type, PropertyHookType, 0) ZEND_END_ARG_INFO() @@ -858,7 +864,9 @@ ZEND_METHOD(ReflectionProperty, hasType); ZEND_METHOD(ReflectionProperty, hasDefaultValue); ZEND_METHOD(ReflectionProperty, getDefaultValue); ZEND_METHOD(ReflectionProperty, getAttributes); +ZEND_METHOD(ReflectionProperty, hasHooks); ZEND_METHOD(ReflectionProperty, getHooks); +ZEND_METHOD(ReflectionProperty, hasHook); ZEND_METHOD(ReflectionProperty, getHook); ZEND_METHOD(ReflectionClassConstant, __construct); ZEND_METHOD(ReflectionClassConstant, __toString); @@ -1152,7 +1160,9 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, hasDefaultValue, arginfo_class_ReflectionProperty_hasDefaultValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getDefaultValue, arginfo_class_ReflectionProperty_getDefaultValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getAttributes, arginfo_class_ReflectionProperty_getAttributes, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, hasHooks, arginfo_class_ReflectionProperty_hasHooks, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getHooks, arginfo_class_ReflectionProperty_getHooks, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, hasHook, arginfo_class_ReflectionProperty_hasHook, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getHook, arginfo_class_ReflectionProperty_getHook, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/reflection/tests/property_hooks/ReflectionProperty_getHook_inheritance.phpt b/ext/reflection/tests/property_hooks/ReflectionProperty_getHook_inheritance.phpt index 820f83f025dc1..3283e8e37a1ce 100644 --- a/ext/reflection/tests/property_hooks/ReflectionProperty_getHook_inheritance.phpt +++ b/ext/reflection/tests/property_hooks/ReflectionProperty_getHook_inheritance.phpt @@ -1,5 +1,5 @@ --TEST-- -ReflectionClass::get{Get,Set}() inheritance +ReflectionClass::getHook() inheritance --FILE-- hasHooks()); var_dump($rp->getHooks()); } ?> --EXPECT-- +bool(false) array(0) { } +bool(true) array(2) { ["get"]=> object(ReflectionMethod)#1 (2) { @@ -35,6 +38,7 @@ array(2) { string(4) "Test" } } +bool(true) array(1) { ["get"]=> object(ReflectionMethod)#2 (2) { @@ -44,6 +48,7 @@ array(1) { string(4) "Test" } } +bool(true) array(1) { ["set"]=> object(ReflectionMethod)#3 (2) { diff --git a/ext/reflection/tests/property_hooks/basics.phpt b/ext/reflection/tests/property_hooks/basics.phpt index 92a613bcb8042..8c363dcc4bfb0 100644 --- a/ext/reflection/tests/property_hooks/basics.phpt +++ b/ext/reflection/tests/property_hooks/basics.phpt @@ -10,6 +10,8 @@ class Test { get { echo "get\n"; } set { echo "set($value)\n"; } } + public $prop5 { get { echo "get\n"; } } + public $prop6 { set { echo "set($value)\n"; } } } abstract class Test2 { abstract public $prop4 { get; set; } @@ -27,13 +29,17 @@ function dumpFlags(ReflectionProperty $rp) { $test = new Test; $rp1 = new ReflectionProperty(Test::class, 'prop1'); +var_dump($rp1->hasHook(PropertyHookType::Get)); var_dump($rp1->getHook(PropertyHookType::Get)); +var_dump($rp1->hasHook(PropertyHookType::Set)); var_dump($rp1->getHook(PropertyHookType::Set)); dumpFlags($rp1); echo "\n"; $rp2 = new ReflectionProperty(Test::class, 'prop2'); +var_dump($rp2->hasHook(PropertyHookType::Get)); var_dump($g = $rp2->getHook(PropertyHookType::Get)); +var_dump($rp2->hasHook(PropertyHookType::Set)); var_dump($s = $rp2->getHook(PropertyHookType::Set)); var_dump($g->invoke($test)); try { @@ -48,7 +54,9 @@ dumpFlags($rp2); echo "\n"; $rp3 = new ReflectionProperty(Test::class, 'prop3'); +var_dump($rp3->hasHook(PropertyHookType::Get)); var_dump($g = $rp3->getHook(PropertyHookType::Get)); +var_dump($rp3->hasHook(PropertyHookType::Set)); var_dump($s = $rp3->getHook(PropertyHookType::Set)); $g->invoke($test); $s->invoke($test, 42); @@ -57,19 +65,34 @@ echo "\n"; $rp4 = new ReflectionProperty(Test2::class, 'prop4'); dumpFlags($rp4); +echo "\n"; + +$rp5 = new ReflectionProperty(Test::class, 'prop5'); +var_dump($rp5->hasHook(PropertyHookType::Get)); +var_dump($rp5->hasHook(PropertyHookType::Set)); +echo "\n"; + +$rp6 = new ReflectionProperty(Test::class, 'prop6'); +var_dump($rp6->hasHook(PropertyHookType::Get)); +var_dump($rp6->hasHook(PropertyHookType::Set)); +echo "\n"; ?> --EXPECT-- +bool(false) NULL +bool(false) NULL Abstract: false false +bool(true) object(ReflectionMethod)#6 (2) { ["name"]=> string(11) "$prop2::get" ["class"]=> string(4) "Test" } +bool(true) object(ReflectionMethod)#7 (2) { ["name"]=> string(11) "$prop2::set" @@ -80,12 +103,14 @@ NULL NULL Abstract: false false +bool(true) object(ReflectionMethod)#9 (2) { ["name"]=> string(11) "$prop3::get" ["class"]=> string(4) "Test" } +bool(true) object(ReflectionMethod)#6 (2) { ["name"]=> string(11) "$prop3::set" @@ -97,3 +122,9 @@ set(42) Abstract: false false Abstract: true true + +bool(true) +bool(false) + +bool(false) +bool(true)