[Validator] try to call __get method if property is uninitialized

This commit is contained in:
Alessandro Chitolina 2020-01-31 18:44:35 +01:00
parent b2339b5e32
commit 427bc3aa18
No known key found for this signature in database
GPG Key ID: 245FF08D9662DB42
3 changed files with 48 additions and 2 deletions

View File

@ -50,8 +50,21 @@ class PropertyMetadata extends MemberMetadata
{
$reflProperty = $this->getReflectionMember($object);
if (\PHP_VERSION_ID >= 70400 && !$reflProperty->isInitialized($object)) {
return null;
if (\PHP_VERSION_ID >= 70400 && $reflProperty->hasType() && !$reflProperty->isInitialized($object)) {
// There is no way to check if a property has been unset or if it is uninitialized.
// When trying to access an uninitialized property, __get method is triggered.
// If __get method is not present, no fallback is possible
// Otherwise we need to catch an Error in case we are trying to access an uninitialized but set property.
if (!method_exists($object, '__get')) {
return null;
}
try {
return $reflProperty->getValue($object);
} catch (\Error $e) {
return null;
}
}
return $reflProperty->getValue($object);

View File

@ -0,0 +1,18 @@
<?php
namespace Symfony\Component\Validator\Tests\Fixtures;
class Entity_74_Proxy extends Entity_74
{
public string $notUnset;
public function __construct()
{
unset($this->uninitialized);
}
public function __get($name)
{
return 42;
}
}

View File

@ -15,11 +15,13 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Mapping\PropertyMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\Entity_74;
use Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy;
class PropertyMetadataTest extends TestCase
{
const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74';
const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy';
const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
public function testInvalidPropertyName()
@ -66,4 +68,17 @@ class PropertyMetadataTest extends TestCase
$this->assertNull($metadata->getPropertyValue($entity));
}
/**
* @requires PHP 7.4
*/
public function testGetPropertyValueFromUninitializedPropertyShouldNotReturnNullIfMagicGetIsPresent()
{
$entity = new Entity_74_Proxy();
$metadata = new PropertyMetadata(self::CLASSNAME_74_PROXY, 'uninitialized');
$notUnsetMetadata = new PropertyMetadata(self::CLASSNAME_74_PROXY, 'notUnset');
$this->assertNull($notUnsetMetadata->getPropertyValue($entity));
$this->assertEquals(42, $metadata->getPropertyValue($entity));
}
}