Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions Zend/tests/lazy_objects/getRawValueWithoutLazyInitialization.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
--TEST--
Lazy objects: getRawValueWithoutLazyInitialization() fetches raw value without triggering initialization
--FILE--
<?php

class C {
public int $a;
public $b = 2;
}

$reflector = new ReflectionClass(C::class);
$propA = $reflector->getProperty('a');
$propB = $reflector->getProperty('b');

$obj = $reflector->newLazyGhost(function () {
throw new \Exception('initializer');
});

print "# Ghost: Lazy properties\n";

$isLazy = null;
var_dump($propA->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$isLazy = null;
var_dump($propB->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

print "# Ghost: Initialized properties\n";

$propA->setRawValueWithoutLazyInitialization($obj, 1);

$isLazy = null;
var_dump($propA->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$propB->skipLazyInitialization($obj);

$isLazy = null;
var_dump($propB->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$obj = $reflector->newLazyProxy(function () {
throw new \Exception('initializer');
});

print "# Proxy: Lazy properties\n";

$isLazy = null;
var_dump($propA->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$isLazy = null;
var_dump($propB->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

print "# Proxy: Initialized properties\n";

$propA->setRawValueWithoutLazyInitialization($obj, 1);

$isLazy = null;
var_dump($propA->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$propB->skipLazyInitialization($obj);

$isLazy = null;
var_dump($propB->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

$obj = $reflector->newLazyProxy(function () {
return new C();
});
$reflector->initializeLazyObject($obj);

print "# Initialized Proxy\n";

try {
$propA->getRawValueWithoutLazyInitialization($obj, $isLazy);
} catch (Error $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

$isLazy = null;
var_dump($propB->getRawValueWithoutLazyInitialization($obj, $isLazy));
var_dump($isLazy);

?>
--EXPECT--
# Ghost: Lazy properties
NULL
bool(true)
NULL
bool(true)
# Ghost: Initialized properties
int(1)
bool(false)
int(2)
bool(false)
# Proxy: Lazy properties
NULL
bool(true)
NULL
bool(true)
# Proxy: Initialized properties
int(1)
bool(false)
int(2)
bool(false)
# Initialized Proxy
Error: Typed property C::$a must not be accessed before initialization
int(2)
bool(false)
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
--TEST--
Lazy objects: getRawValueWithoutLazyInitialization() behaves like getRawValue() on non-lazy objects
--FILE--
<?php

#[AllowDynamicProperties]
class C {
public static $static = 'static';

public int $a;
public $b;
public $c {
get { return 'c'; }
}
public $d {
get { return $this->d; }
set($value) { $this->d = $value; }
}
}

class D extends C {
public function __get($name) {
return ord($name);
}
}

$reflector = new ReflectionClass(C::class);
$propA = $reflector->getProperty('a');
$propB = $reflector->getProperty('b');
$propC = $reflector->getProperty('c');
$propD = $reflector->getProperty('d');
$propStatic = $reflector->getProperty('static');

$obj = new C();
$obj->dynamic = 1;
$propDynamic = new ReflectionProperty($obj, 'dynamic');

$obj = new C();

print "# Non initialized properties\n";

try {
$propA->getRawValueWithoutLazyInitialization($obj);
} catch (Error $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

var_dump($propB->getRawValueWithoutLazyInitialization($obj));

try {
var_dump($propC->getRawValueWithoutLazyInitialization($obj));
} catch (Error $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

var_dump($propD->getRawValueWithoutLazyInitialization($obj));

print "# Initialized properties\n";

$obj->a = 1;
$obj->b = new stdClass;
$obj->d = 4;

var_dump($propA->getRawValueWithoutLazyInitialization($obj));

var_dump($propB->getRawValueWithoutLazyInitialization($obj));

try {
var_dump($propC->getRawValueWithoutLazyInitialization($obj));
} catch (Error $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

var_dump($propD->getRawValueWithoutLazyInitialization($obj));

try {
$propStatic->getRawValueWithoutLazyInitialization($obj);
} catch (ReflectionException $e) {
printf("%s: %s\n", $e::class, $e->getMessage());
}

var_dump($propDynamic->getRawValueWithoutLazyInitialization($obj));

print "# Unset properties and __get()\n";

$obj = new D();
unset($obj->a);
unset($obj->b);

var_dump($propA->getRawValueWithoutLazyInitialization($obj));

var_dump($propB->getRawValueWithoutLazyInitialization($obj));

print "# References\n";

$obj = new C();
$obj->b = &$obj;

var_dump($propB->getRawValueWithoutLazyInitialization($obj));

print "# Internal class\n";

$reflector = new ReflectionClass(Exception::class);
$propMessage = $reflector->getProperty('message');

$obj = new Exception('hello');

var_dump($propMessage->getRawValueWithoutLazyInitialization($obj));

?>
--EXPECTF--
# Non initialized properties
Error: Typed property C::$a must not be accessed before initialization
NULL
Error: Must not read from virtual property C::$c
NULL
# Initialized properties
int(1)
object(stdClass)#%d (0) {
}
Error: Must not read from virtual property C::$c
int(4)
ReflectionException: May not use getRawValueWithoutLazyInitialization on static properties

Warning: Undefined property: C::$dynamic in %s on line %d
NULL
# Unset properties and __get()
int(97)
int(98)
# References
object(C)#%d (2) {
["a"]=>
uninitialized(int)
["b"]=>
*RECURSION*
["d"]=>
NULL
}
# Internal class
string(5) "hello"
101 changes: 101 additions & 0 deletions Zend/tests/lazy_objects/isLazy.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
--TEST--
Lazy Objects: ReflectionProperty::isLazy()
--FILE--
<?php

#[AllowDynamicProperties]
class C {
public static $staticProp;
public int $typed;
public $untyped;
public $virtual {
get {}
}
}

function testProps(ReflectionClass $reflector, object $obj) {
foreach (['staticProp', 'typed', 'untyped', 'virtual', 'dynamic'] as $name) {
if ('dynamic' === $name) {
$tmp = new C();
$tmp->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 "# 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
# Internal
y: 0
Loading
Loading