8000 [Validator] try to call __get method if property is uninitialized · symfony/symfony@164ab11 · GitHub
[go: up one dir, main page]

Skip to content

Commit 164ab11

Browse files
committed
[Validator] try to call __get method if property is uninitialized
1 parent b2339b5 commit 164ab11

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

src/Symfony/Component/Validator/Mapping/PropertyMetadata.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,21 @@ public function getPropertyValue($object)
5050
{
5151
$reflProperty = $this->getReflectionMember($object);
5252

53-
if (\PHP_VERSION_ID >= 70400 && !$reflProperty->isInitialized($object)) {
54-
return null;
53+
if (\PHP_VERSION_ID >= 70400 && $reflProperty->hasType() && !$reflProperty->isInitialized($object)) {
54+
// There is no way to check if a property has been unset or it is uninitialized.
55+
// When trying to access an uninitialized property, __get method is triggered in PHP 7.4.0, but not in 7.4.1+.
56+
57+
// If __get method is not present, no fallback is possible
58+
// Otherwise we need to catch a TypeError in case we are trying to access an uninitialized but set property.
59+
if (!\method_exists($object, '__get')) {
60+
return null;
61+
}
62+
63+
try {
64+
return $reflProperty->getValue($object);
65+
} catch (\TypeError $e) {
66+
return null;
67+
}
5568
}
5669

5770
return $reflProperty->getValue($object);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Symfony\Component\Validator\Tests\Fixtures;
4+
5+
class Entity_74_Proxy extends Entity_74
6+
{
7+
public function __construct()
8+
{
9+
unset($this->uninitialized);
10+
}
11+
12+
public function __get($name)
13+
{
14+
return 42;
15+
}
16+
}

src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
use Symfony\Component\Validator\Mapping\PropertyMetadata;
1616
use Symfony\Component\Validator\Tests\Fixtures\Entity;
1717
use Symfony\Component\Validator\Tests\Fixtures\Entity_74;
18+
use Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy;
19+
use Symfony\Component\Validator\Tests\Fixtures\Entity_74_WithMagicGet;
1820

1921
class PropertyMetadataTest extends TestCase
2022
{
2123
const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
2224
const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74';
25+
const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy';
2326
const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
2427

2528
public function testInvalidPropertyName()
@@ -66,4 +69,15 @@ public function testGetPropertyValueFromUninitializedProperty()
6669

6770
$this->assertNull($metadata->getPropertyValue($entity));
6871
}
72+
73+
/**
74+
* @requires PHP 7.4
75+
*/
76+
public function testGetPropertyValueFromUninitializedPropertyShouldNotReturnNullIfMagicGetIsPresent()
77+
{
78+
$entity = new Entity_74_Proxy();
79+
$metadata = new PropertyMetadata(self::CLASSNAME_74_PROXY, 'uninitialized');
80+
81+
$this->assertEquals(42, $metadata->getPropertyValue($entity));
82+
}
6983
}

0 commit comments

Comments
 (0)
0