From 47bd0180d17cbaa3409de909020901820d89b047 Mon Sep 17 00:00:00 2001 From: Andrii Serdiuk Date: Tue, 21 Jul 2020 01:36:57 +0300 Subject: [PATCH] [PropertyAccess] Fix accessing dynamic properties --- .../PropertyAccess/PropertyAccessor.php | 14 +++++++---- .../Fixtures/TestClassDynamicProperty.php | 11 +++++++++ .../Tests/PropertyAccessorTest.php | 24 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassDynamicProperty.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index af7331d52b..52894afaa1 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -435,10 +435,16 @@ class PropertyAccessor implements PropertyAccessorInterface throw $e; } - } elseif ($object instanceof \stdClass && property_exists($object, $property)) { - $result[self::VALUE] = $object->$property; - if (isset($zval[self::REF])) { - $result[self::REF] = &$object->$property; + } elseif (property_exists($object, $property)) { + try { + $result[self::VALUE] = $object->$property; + if (isset($zval[self::REF])) { + $result[self::REF] = &$object->$property; + } + } catch (\Error $e) { + if (!$ignoreInvalidProperty) { + throw new NoSuchPropertyException(sprintf('Can\'t read protected or private property "%s" in class "%s".', $property, $class), 0, $e); + } } } elseif (!$ignoreInvalidProperty) { throw new NoSuchPropertyException(sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class)); diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassDynamicProperty.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassDynamicProperty.php new file mode 100644 index 0000000000..93caeb6db2 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassDynamicProperty.php @@ -0,0 +1,11 @@ +dynamicProperty = $dynamicProperty; + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 89e02f334d..790deb5e69 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -21,6 +21,7 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestAdderRemoverInvalidArgumentLength; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestAdderRemoverInvalidMethods; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; +use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassDynamicProperty; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassIsWritable; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet; @@ -97,6 +98,29 @@ class PropertyAccessorTest extends TestCase $this->assertSame($value, $this->propertyAccessor->getValue($objectOrArray, $path)); } + /** + * Test get dynamic value from object is other than \stdClass instance. + */ + public function testGetDynamicValue() + { + $value = 'dynamicPropertyValue'; + $path = 'dynamicProperty'; + $object = new TestClassDynamicProperty($value); + + $this->assertSame($value, $this->propertyAccessor->getValue($object, $path)); + } + + /** + * Ensure exact exception with message was thrown on access to non-public property. + */ + public function testGetInaccessibleProperty() + { + $this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException'); + $this->expectExceptionMessage(sprintf('Can\'t read protected or private property "%s" in class "%s".', 'protectedProperty', TestClass::class)); + + $this->propertyAccessor->getValue(new TestClass('Bernhard'), 'protectedProperty'); + } + /** * @dataProvider getPathsWithMissingProperty */