Skip to content

Commit

Permalink
[Validator] try to call __get method if property is uninitialized
Browse files Browse the repository at this point in the history
  • Loading branch information
alekitto committed Feb 1, 2020
1 parent b2339b5 commit 560e2c8
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/Symfony/Component/Validator/Mapping/PropertyMetadata.php
Expand Up @@ -50,8 +50,21 @@ public function getPropertyValue($object)
{
$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 it is uninitialized.
// When trying to access an uninitialized property, __get method is triggered in PHP 7.4.0, but not in 7.4.1+.

// If __get method is not present, no fallback is possible
// Otherwise we need to catch a TypeError 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 (\TypeError $e) {
return null;
}
}

return $reflProperty->getValue($object);
Expand Down
16 changes: 16 additions & 0 deletions src/Symfony/Component/Validator/Tests/Fixtures/Entity_74_Proxy.php
@@ -0,0 +1,16 @@
<?php

namespace Symfony\Component\Validator\Tests\Fixtures;

class Entity_74_Proxy extends Entity_74
{
public function __construct()
{
unset($this->uninitialized);
}

public function __get($name)
{
return 42;
}
}
Expand Up @@ -15,11 +15,13 @@
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()
Expand Down Expand Up @@ -66,4 +68,15 @@ public function testGetPropertyValueFromUninitializedProperty()

$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');

$this->assertEquals(42, $metadata->getPropertyValue($entity));
}
}

0 comments on commit 560e2c8

Please sign in to comment.