Skip to content

Commit

Permalink
[PropertyAccess] Fix checking for missing properties
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Mar 7, 2024
1 parent 97d1624 commit 8a8bfd3
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
14 changes: 12 additions & 2 deletions src/Symfony/Component/PropertyAccess/PropertyAccessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,18 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
throw $e;
}
} elseif (PropertyReadInfo::TYPE_PROPERTY === $type) {
if ($access->canBeReference() && !isset($object->$name) && !\array_key_exists($name, (array) $object) && !(new \ReflectionProperty($class, $name))->hasType()) {
throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $class, $name));
if (!isset($object->$name) && !\array_key_exists($name, (array) $object)) {
try {
$r = new \ReflectionProperty($class, $name);

if ($r->isPublic() && !$r->hasType()) {
throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $class, $name));
}
} catch (\ReflectionException $e) {
if (!$ignoreInvalidProperty) {
throw new NoSuchPropertyException(sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class));
}
}
}

$result[self::VALUE] = $object->$name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ public function __get(string $property)
return 'constant value';
}
}

public function __isset(string $property)
{
return \in_array($property, ['magicProperty', 'constantMagicProperty'], true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -990,12 +990,19 @@ public function testGetValuePropertyThrowsExceptionIfUninitializedWithLazyGhost(

public function testGetValueGetterThrowsExceptionIfUninitializedWithLazyGhost()
{
$lazyGhost = $this->createUninitializedObjectPropertyGhost();

$this->expectException(UninitializedPropertyException::class);
$this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedObjectProperty::$privateUninitialized" is not readable because it is typed "DateTimeInterface". You should initialize it or declare a default value instead.');

$this->propertyAccessor->getValue($lazyGhost, 'privateUninitialized');
}

public function testIsReadableWithMissingPropertyAndLazyGhost()
{
$lazyGhost = $this->createUninitializedObjectPropertyGhost();

$this->propertyAccessor->getValue($lazyGhost, 'privateUninitialized');
$this->assertFalse($this->propertyAccessor->isReadable($lazyGhost, 'dummy'));
}

private function createUninitializedObjectPropertyGhost(): UninitializedObjectProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,12 @@ public function getReadInfo(string $class, string $property, array $context = []
return new PropertyReadInfo(PropertyReadInfo::TYPE_METHOD, $getsetter, $this->getReadVisiblityForMethod($method), $method->isStatic(), false);
}

if ($allowMagicGet && $reflClass->hasMethod('__get') && ($reflClass->getMethod('__get')->getModifiers() & $this->methodReflectionFlags)) {
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, false, false);
if ($allowMagicGet && $reflClass->hasMethod('__get') && (($r = $reflClass->getMethod('__get'))->getModifiers() & $this->methodReflectionFlags)) {
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, false, $r->returnsReference());
}

if ($hasProperty && ($reflClass->getProperty($property)->getModifiers() & $this->propertyReflectionFlags)) {
$reflProperty = $reflClass->getProperty($property);

return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisiblityForProperty($reflProperty), $reflProperty->isStatic(), true);
if ($hasProperty && (($r = $reflClass->getProperty($property))->getModifiers() & $this->propertyReflectionFlags)) {
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisiblityForProperty($r), $r->isStatic(), true);
}

if ($allowMagicCall && $reflClass->hasMethod('__call') && ($reflClass->getMethod('__call')->getModifiers() & $this->methodReflectionFlags)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,11 @@ public function __get($name)
return $this->foo = 123;
}
}

public function __isset($name)
{
return 'foo' === $name;
}
}

class DummyWithConstructorObject
Expand Down

0 comments on commit 8a8bfd3

Please sign in to comment.