diff --git a/Zend/tests/lazy_objects/isLazy.phpt b/Zend/tests/lazy_objects/isLazy.phpt new file mode 100644 index 0000000000000..691b42b708dbc --- /dev/null +++ b/Zend/tests/lazy_objects/isLazy.phpt @@ -0,0 +1,140 @@ +--TEST-- +Lazy Objects: ReflectionProperty::isLazy() +--FILE-- +dynamic = 1; + $pr = new ReflectionProperty($tmp, $name); + } else { + $pr = $reflector->getProperty($name); + } + printf("%s: %d\n", $name, $pr->isLazy($obj)); + } +} + +$reflector = new ReflectionClass(C::class); + +print "# Ghost\n"; + +$obj = $reflector->newLazyGhost(function () { }); + +testProps($reflector, $obj); + +$pr = $reflector->getProperty('typed'); +$pr->skipLazyInitialization($obj); +printf("typed (skipped): %d\n", $pr->isLazy($obj)); + +print "# Initialized Ghost\n"; + +$reflector->initializeLazyObject($obj); + +testProps($reflector, $obj); + +print "# Proxy\n"; + +$obj = $reflector->newLazyProxy(function () { + return new C(); +}); + +testProps($reflector, $obj); + +$pr = $reflector->getProperty('typed'); +$pr->skipLazyInitialization($obj); +printf("typed (skipped prop): %d\n", $pr->isLazy($obj)); + +print "# Initialized Proxy\n"; + +$reflector->initializeLazyObject($obj); + +testProps($reflector, $obj); + +print "# Nested Proxy\n"; + +$nested = new C(); +$obj = $reflector->newLazyProxy(function () use ($nested) { + return $nested; +}); +$reflector->initializeLazyObject($obj); +$reflector->resetAsLazyProxy($nested, function () { + return new C(); +}); + +testProps($reflector, $obj); + +print "# Nested Proxy (nested initialized)\n"; + +$nested = new C(); +$obj = $reflector->newLazyProxy(function () use ($nested) { + return $nested; +}); +$reflector->initializeLazyObject($obj); +$reflector->resetAsLazyProxy($nested, function () { + return new C(); +}); +$reflector->initializeLazyObject($nested); + +testProps($reflector, $obj); + +print "# Internal\n"; + +$obj = (new DateTime())->diff(new DateTime()); +$reflector = new ReflectionClass(DateInterval::class); +$pr = new ReflectionProperty($obj, 'y'); +printf("y: %d\n", $pr->isLazy($obj)); + +?> +--EXPECT-- +# Ghost +staticProp: 0 +typed: 1 +untyped: 1 +virtual: 0 +dynamic: 0 +typed (skipped): 0 +# Initialized Ghost +staticProp: 0 +typed: 0 +untyped: 0 +virtual: 0 +dynamic: 0 +# Proxy +staticProp: 0 +typed: 1 +untyped: 1 +virtual: 0 +dynamic: 0 +typed (skipped prop): 0 +# Initialized Proxy +staticProp: 0 +typed: 0 +untyped: 0 +virtual: 0 +dynamic: 0 +# Nested Proxy +staticProp: 0 +typed: 1 +untyped: 1 +virtual: 0 +dynamic: 0 +# Nested Proxy (nested initialized) +staticProp: 0 +typed: 0 +untyped: 0 +virtual: 0 +dynamic: 0 +# Internal +y: 0 diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 36edb6b527e15..e2a7bda46d304 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6271,6 +6271,30 @@ ZEND_METHOD(ReflectionProperty, skipLazyInitialization) } } +ZEND_METHOD(ReflectionProperty, isLazy) +{ + reflection_object *intern; + property_reference *ref; + zend_object *object; + + GET_REFLECTION_OBJECT_PTR(ref); + + ZEND_PARSE_PARAMETERS_START(1, 1) { + Z_PARAM_OBJ_OF_CLASS(object, intern->ce) + } ZEND_PARSE_PARAMETERS_END(); + + if (!ref->prop || ref->prop->flags & (ZEND_ACC_STATIC | ZEND_ACC_VIRTUAL)) { + RETURN_FALSE; + } + + while (zend_object_is_lazy_proxy(object) + && zend_lazy_object_initialized(object)) { + object = zend_lazy_object_get_instance(object); + } + + RETURN_BOOL(Z_PROP_FLAG_P(OBJ_PROP(object, ref->prop->offset)) & IS_PROP_LAZY); +} + /* {{{ Returns true if property was initialized */ ZEND_METHOD(ReflectionProperty, isInitialized) { diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 2b86559168012..a4671cdf77386 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -502,6 +502,8 @@ public function setRawValueWithoutLazyInitialization(object $object, mixed $valu public function skipLazyInitialization(object $object): void {} + public function isLazy(object $object): bool {} + /** @tentative-return-type */ public function isInitialized(?object $object = null): bool {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index f55e96a7ed7ac..9f44ee949b08a 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: 273777e0bc50a3d5059bb2db7b0a1e293b26e338 */ + * Stub hash: 2620fb2d8fc950283bfc174372c72361b37e9d41 */ 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) @@ -399,6 +399,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_skipLaz ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) ZEND_END_ARG_INFO() +#define arginfo_class_ReflectionProperty_isLazy arginfo_class_ReflectionClass_isUninitializedLazyObject + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_isInitialized, 0, 0, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, object, IS_OBJECT, 1, "null") ZEND_END_ARG_INFO() @@ -843,6 +845,7 @@ ZEND_METHOD(ReflectionProperty, getRawValue); ZEND_METHOD(ReflectionProperty, setRawValue); ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization); ZEND_METHOD(ReflectionProperty, skipLazyInitialization); +ZEND_METHOD(ReflectionProperty, isLazy); ZEND_METHOD(ReflectionProperty, isInitialized); ZEND_METHOD(ReflectionProperty, isPublic); ZEND_METHOD(ReflectionProperty, isPrivate); @@ -1140,6 +1143,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, setRawValue, arginfo_class_ReflectionProperty_setRawValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, setRawValueWithoutLazyInitialization, arginfo_class_ReflectionProperty_setRawValueWithoutLazyInitialization, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, skipLazyInitialization, arginfo_class_ReflectionProperty_skipLazyInitialization, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, isLazy, arginfo_class_ReflectionProperty_isLazy, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isInitialized, arginfo_class_ReflectionProperty_isInitialized, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isPublic, arginfo_class_ReflectionProperty_isPublic, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, isPrivate, arginfo_class_ReflectionProperty_isPrivate, ZEND_ACC_PUBLIC)