diff --git a/UPGRADING b/UPGRADING index a3e0084f7ecc8..bb602e5050978 100644 --- a/UPGRADING +++ b/UPGRADING @@ -431,6 +431,7 @@ PHP 8.4 UPGRADE NOTES - ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE - ReflectionClass::SKIP_DESTRUCTOR RFC: https://wiki.php.net/rfc/lazy-objects + . ReflectionProperty::isDynamic() was introduced. - SOAP: . Added support for clark notation for namespaces in class map. diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 289c9392124e9..b8fe4180ccf27 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -5921,8 +5921,7 @@ ZEND_METHOD(ReflectionProperty, isVirtual) _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VIRTUAL); } -/* {{{ Returns whether this property is default (declared at compilation time). */ -ZEND_METHOD(ReflectionProperty, isDefault) +static void _property_check_dynamic(INTERNAL_FUNCTION_PARAMETERS, bool dynamic_true) { reflection_object *intern; property_reference *ref; @@ -5931,7 +5930,21 @@ ZEND_METHOD(ReflectionProperty, isDefault) RETURN_THROWS(); } GET_REFLECTION_OBJECT_PTR(ref); - RETURN_BOOL(ref->prop != NULL); + bool is_dynamic = ref->prop == NULL; + RETURN_BOOL(dynamic_true ? is_dynamic : !is_dynamic); +} + +/* {{{ Returns whether this property is default (declared at compilation time). */ +ZEND_METHOD(ReflectionProperty, isDefault) +{ + _property_check_dynamic(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} +/* }}} */ + +/* {{{ Returns whether this property is dynamic (not declared at compilation time). */ +ZEND_METHOD(ReflectionProperty, isDynamic) +{ + _property_check_dynamic(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } /* }}} */ diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 366c13f3a1a1d..5db496db1f447 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -522,6 +522,8 @@ public function isReadOnly(): bool {} /** @tentative-return-type */ public function isDefault(): bool {} + public function isDynamic(): bool {} + public function isAbstract(): bool {} public function isVirtual(): bool {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 68c0229d03c01..a397e9cc273d7 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: 09e21577c53d8b53e30aa30e3208d3807ecd8852 */ + * Stub hash: 8faf835d31acf3ae3e12a0dfca56f0744b95831b */ 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) @@ -419,6 +419,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionProperty_isDefault arginfo_class_ReflectionFunctionAbstract_inNamespace +#define arginfo_class_ReflectionProperty_isDynamic arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + #define arginfo_class_ReflectionProperty_isAbstract arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType #define arginfo_class_ReflectionProperty_isVirtual arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType @@ -842,6 +844,7 @@ ZEND_METHOD(ReflectionProperty, isProtectedSet); ZEND_METHOD(ReflectionProperty, isStatic); ZEND_METHOD(ReflectionProperty, isReadOnly); ZEND_METHOD(ReflectionProperty, isDefault); +ZEND_METHOD(ReflectionProperty, isDynamic); ZEND_METHOD(ReflectionProperty, isAbstract); ZEND_METHOD(ReflectionProperty, isVirtual); ZEND_METHOD(ReflectionProperty, isPromoted); @@ -1135,6 +1138,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, isStatic, arginfo_class_ReflectionProperty_isStatic, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isReadOnly, arginfo_class_ReflectionProperty_isReadOnly, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isDefault, arginfo_class_ReflectionProperty_isDefault, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, isDynamic, arginfo_class_ReflectionProperty_isDynamic, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isAbstract, arginfo_class_ReflectionProperty_isAbstract, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isVirtual, arginfo_class_ReflectionProperty_isVirtual, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isPromoted, arginfo_class_ReflectionProperty_isPromoted, ZEND_ACC_PUBLIC) diff --git a/ext/reflection/tests/ReflectionProperty_basic2.phpt b/ext/reflection/tests/ReflectionProperty_basic2.phpt index 09495f744bf28..1c1361dd72509 100644 --- a/ext/reflection/tests/ReflectionProperty_basic2.phpt +++ b/ext/reflection/tests/ReflectionProperty_basic2.phpt @@ -1,16 +1,19 @@ --TEST-- -Test usage of ReflectionProperty methods isDefault(), getModifiers(), getDeclaringClass() and getDocComment(). +Test usage of ReflectionProperty methods isDefault(), isDynamic(), getModifiers(), getDeclaringClass() and getDocComment(). --INI-- opcache.save_comments=1 --FILE-- isDefault()); + echo "isDynamic():\n"; + var_dump($propInfo->isDynamic()); echo "getModifiers():\n"; var_dump($propInfo->getModifiers()); echo "getDeclaringClass():\n"; @@ -20,6 +23,7 @@ function reflectProperty($class, $property) { echo "\n**********************************\n"; } +#[AllowDynamicProperties] class TestClass { public $pub; static public $stat = "static property"; @@ -35,6 +39,10 @@ reflectProperty("TestClass", "stat"); reflectProperty("TestClass", "prot"); reflectProperty("TestClass", "priv"); +$obj = new TestClass(); +$obj->dyn = 'dynamic'; +reflectProperty($obj, "dyn", "TestClass"); + ?> --EXPECTF-- ********************************** @@ -42,6 +50,8 @@ Reflecting on property TestClass::pub isDefault(): bool(true) +isDynamic(): +bool(false) getModifiers(): int(1) getDeclaringClass(): @@ -58,6 +68,8 @@ Reflecting on property TestClass::stat isDefault(): bool(true) +isDynamic(): +bool(false) getModifiers(): int(17) getDeclaringClass(): @@ -74,6 +86,8 @@ Reflecting on property TestClass::prot isDefault(): bool(true) +isDynamic(): +bool(false) getModifiers(): int(2) getDeclaringClass(): @@ -92,6 +106,8 @@ Reflecting on property TestClass::priv isDefault(): bool(true) +isDynamic(): +bool(false) getModifiers(): int(4) getDeclaringClass(): @@ -103,3 +119,21 @@ getDocComment(): bool(false) ********************************** +********************************** +Reflecting on property TestClass::dyn + +isDefault(): +bool(false) +isDynamic(): +bool(true) +getModifiers(): +int(1) +getDeclaringClass(): +object(ReflectionClass)#%d (1) { + ["name"]=> + string(9) "TestClass" +} +getDocComment(): +bool(false) + +********************************** diff --git a/ext/reflection/tests/ReflectionProperty_isDynamic_basic.phpt b/ext/reflection/tests/ReflectionProperty_isDynamic_basic.phpt new file mode 100644 index 0000000000000..401cf8b80322e --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_isDynamic_basic.phpt @@ -0,0 +1,69 @@ +--TEST-- +Test ReflectionProperty::isDynamic() usage. +--FILE-- +isDynamic()); + echo "\n**********************************\n"; +} + +#[AllowDynamicProperties] +class TestClass { + public $pub; + static public $stat = "static property"; + protected $prot = 4; + private $priv = "keepOut"; +} + +reflectProperty("TestClass", "pub"); +reflectProperty("TestClass", "stat"); +reflectProperty("TestClass", "prot"); +reflectProperty("TestClass", "priv"); + +$obj = new TestClass(); +$obj->dyn = 'dynamic'; +reflectProperty($obj, "dyn", "TestClass"); + +?> +--EXPECT-- +********************************** +Reflecting on property TestClass::pub + +isDynamic(): +bool(false) + +********************************** +********************************** +Reflecting on property TestClass::stat + +isDynamic(): +bool(false) + +********************************** +********************************** +Reflecting on property TestClass::prot + +isDynamic(): +bool(false) + +********************************** +********************************** +Reflecting on property TestClass::priv + +isDynamic(): +bool(false) + +********************************** +********************************** +Reflecting on property TestClass::dyn + +isDynamic(): +bool(true) + +**********************************