From 2d751866b976a02e22743359733edc55cd20e9fd Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 28 Aug 2024 10:37:07 +0200 Subject: [PATCH 1/2] [PropertyAccess] Fix handling property names with a `.` --- PropertyAccessor.php | 20 +++++++++++++++++--- Tests/PropertyAccessorTest.php | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/PropertyAccessor.php b/PropertyAccessor.php index 359aaa7..992e260 100644 --- a/PropertyAccessor.php +++ b/PropertyAccessor.php @@ -150,7 +150,7 @@ public function getValue($objectOrArray, $propertyPath) self::VALUE => $objectOrArray, ]; - if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) { + if (\is_object($objectOrArray) && (false === strpbrk((string) $propertyPath, '.[') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) { return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE]; } @@ -166,7 +166,7 @@ public function getValue($objectOrArray, $propertyPath) */ public function setValue(&$objectOrArray, $propertyPath, $value) { - if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) { + if (\is_object($objectOrArray) && (false === strpbrk((string) $propertyPath, '.[') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) { $zval = [ self::VALUE => $objectOrArray, ]; @@ -293,7 +293,13 @@ public function isReadable($objectOrArray, $propertyPath) $zval = [ self::VALUE => $objectOrArray, ]; - $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices); + + // handle stdClass with properties with a dot in the name + if ($objectOrArray instanceof \stdClass && str_contains($propertyPath, '.') && property_exists($objectOrArray, $propertyPath)) { + $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty); + } else { + $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength(), $this->ignoreInvalidIndices); + } return true; } catch (AccessException $e) { @@ -314,6 +320,14 @@ public function isWritable($objectOrArray, $propertyPath) $zval = [ self::VALUE => $objectOrArray, ]; + + // handle stdClass with properties with a dot in the name + if ($objectOrArray instanceof \stdClass && str_contains($propertyPath, '.') && property_exists($objectOrArray, $propertyPath)) { + $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty); + + return true; + } + $propertyValues = $this->readPropertiesUntil($zval, $propertyPath, $propertyPath->getLength() - 1); for ($i = \count($propertyValues) - 1; 0 <= $i; --$i) { diff --git a/Tests/PropertyAccessorTest.php b/Tests/PropertyAccessorTest.php index 5f1b51e..f6d5a4b 100644 --- a/Tests/PropertyAccessorTest.php +++ b/Tests/PropertyAccessorTest.php @@ -674,6 +674,7 @@ public static function getValidPropertyPaths() [['firstName' => 'Bernhard'], '[firstName]', 'Bernhard'], [['index' => ['firstName' => 'Bernhard']], '[index][firstName]', 'Bernhard'], [(object) ['firstName' => 'Bernhard'], 'firstName', 'Bernhard'], + [(object) ['first.Name' => 'Bernhard'], 'first.Name', 'Bernhard'], [(object) ['property' => ['firstName' => 'Bernhard']], 'property[firstName]', 'Bernhard'], [['index' => (object) ['firstName' => 'Bernhard']], '[index].firstName', 'Bernhard'], [(object) ['property' => (object) ['firstName' => 'Bernhard']], 'property.firstName', 'Bernhard'], From 866f6cd84f2094cbc6f66ce9752faf749916e2a9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 30 Aug 2024 18:06:13 +0200 Subject: [PATCH 2/2] Fix expected missing return types --- PropertyAccessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PropertyAccessor.php b/PropertyAccessor.php index 2a1ed4b..6d1ebaf 100644 --- a/PropertyAccessor.php +++ b/PropertyAccessor.php @@ -95,7 +95,7 @@ public function getValue(object|array $objectOrArray, string|PropertyPathInterfa self::VALUE => $objectOrArray, ]; - if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[?') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) { + if (\is_object($objectOrArray) && (false === strpbrk((string) $propertyPath, '.[?') || $objectOrArray instanceof \stdClass && property_exists($objectOrArray, $propertyPath))) { return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE]; }