From 28466f1248cdaa357c73cc835cda701bee258a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CFilip?= Date: Tue, 11 Jan 2022 13:16:26 +0100 Subject: [PATCH] [PropertyAccess] Fix handling of uninitialized property of anonymous class --- PropertyAccessor.php | 6 +++--- Tests/PropertyAccessorTest.php | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/PropertyAccessor.php b/PropertyAccessor.php index fccc09b..d389992 100644 --- a/PropertyAccessor.php +++ b/PropertyAccessor.php @@ -436,11 +436,11 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid } } 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; diff --git a/Tests/PropertyAccessorTest.php b/Tests/PropertyAccessorTest.php index 95c37b4..bcecf16 100644 --- a/Tests/PropertyAccessorTest.php +++ b/Tests/PropertyAccessorTest.php @@ -176,6 +176,41 @@ public function getUninitialized(): array $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);