8000 bug #35546 [Validator] check for __get method existence if property i… · symfony/symfony@ef4dcdb · GitHub
[go: up one dir, main page]

Skip to content

Commit ef4dcdb

Browse files
committed
bug #35546 [Validator] check for __get method existence if property is uninitialized (alekitto)
This PR was merged into the 3.4 branch. Discussion ---------- [Validator] check for __get method existence if property is uninitialized | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #35544 | License | MIT Resolve bug #35544. On PHP 7.4, check if object implements `__get` magic method if property is reported as uninitialized before returning null. Commits ------- 427bc3a [Validator] try to call __get method if property is uninitialized
2 parents af46fd6 + 427bc3a commit ef4dcdb

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-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 if it is uninitialized.
55+
// When trying to access an uninitialized property, __get method is triggered.
56+
57+
// If __get method is not present, no fallback is possible
58+
// Otherwise we need to catch an Error 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 (\Error $e) {
66+
return null;
67+
}
5568
}
5669

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

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
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;
1819

1920
class PropertyMetadataTest extends TestCase
2021
{
2122
const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
2223
const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74';
24+
const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy';
2325
const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
2426

2527
public function testInvalidPropertyName()
@@ -66,4 +68,17 @@ public function testGetPropertyValueFromUninitializedProperty()
6668

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

0 commit comments

Comments
 (0)
0