[PropertyAccess] Fix handling of uninitialized property of anonymous class

This commit is contained in:
“Filip 2022-01-11 13:16:26 +01:00 committed by Nicolas Grekas
parent 4d04a2dd57
commit 27d5edf3d2
2 changed files with 38 additions and 3 deletions

View File

@ -436,11 +436,11 @@ class PropertyAccessor implements PropertyAccessorInterface
}
} catch (\Error $e) {
// handle uninitialized properties in PHP >= 7.4
if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) {
$r = new \ReflectionProperty($matches[1], $matches[2]);
if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ('.preg_quote(get_debug_type($object), '/').')::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) {
$r = new \ReflectionProperty($class, $matches[2]);
$type = ($type = $r->getType()) instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getName(), $type), 0, $e);
throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $matches[1], $r->getName(), $type), 0, $e);
}
throw $e;

View File

@ -176,6 +176,41 @@ class PropertyAccessorTest extends TestCase
$this->propertyAccessor->getValue($object, 'uninitialized');
}
/**
* @requires PHP 7.4
*/
public function testGetValueThrowsExceptionIfUninitializedNotNullablePropertyWithGetterOfAnonymousClass()
{
$this->expectException(AccessException::class);
$this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.');
$object = eval('return new class() {
private string $uninitialized;
public function getUninitialized(): string
{
return $this->uninitialized;
}
};');
$this->propertyAccessor->getValue($object, 'uninitialized');
}
/**
* @requires PHP 7.4
*/
public function testGetValueThrowsExceptionIfUninitializedPropertyOfAnonymousClass()
{
$this->expectException(AccessException::class);
$this->expectExceptionMessage('The property "class@anonymous::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.');
$object = eval('return new class() {
public string $uninitialized;
};');
$this->propertyAccessor->getValue($object, 'uninitialized');
}
public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousStdClass()
{
$this->expectException(AccessException::class);