Skip to content

Commit b475c47

Browse files
committed
[VarExporter] generate __doUnserialize() method in ProxyHelper::generateLazyProxy()
1 parent 10514a6 commit b475c47

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/Symfony/Component/VarExporter/ProxyHelper.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,35 @@ public static function generateLazyProxy(?\ReflectionClass $class, array $interf
197197
$body = $methods ? "\n".implode("\n\n", $methods)."\n" : '';
198198
$propertyScopes = $class ? self::exportPropertyScopes($class->name) : '[]';
199199

200+
if (
201+
$class?->hasMethod('__unserialize')
202+
&& $class->getMethod('__unserialize')->getParameters()[0]->getType()
203+
) {
204+
// fix contravariance type problem when $class declares a `__unserialize()` method without typehint.
205+
$lazyProxyTraitStatement = <<<EOPHP
206+
use \Symfony\Component\VarExporter\LazyProxyTrait {
207+
__unserialize as private __doUnserialize;
208+
}
209+
EOPHP;
210+
211+
$body .= <<<EOPHP
212+
213+
public function __unserialize(\$data): void
214+
{
215+
\$this->__doUnserialize(\$data);
216+
}
217+
218+
EOPHP;
219+
} else {
220+
$lazyProxyTraitStatement = <<<EOPHP
221+
use \Symfony\Component\VarExporter\LazyProxyTrait;
222+
EOPHP;
223+
}
224+
200225
return <<<EOPHP
201226
{$parent} implements \\{$interfaces}
202227
{
203-
use \Symfony\Component\VarExporter\LazyProxyTrait;
228+
{$lazyProxyTraitStatement}
204229
205230
private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes};
206231
{$body}}

src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php

+45
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,50 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
160160
$this->assertSame($expected, ProxyHelper::generateLazyProxy(null, [new \ReflectionClass(TestForProxyHelperInterface1::class), new \ReflectionClass(TestForProxyHelperInterface2::class)]));
161161
}
162162

163+
/**
164+
* @dataProvider classWithUnserializeMagicMethodProvider
165+
*/
166+
public function testGenerateLazyProxyForClassWithUnserializeMagicMethod(object $obj, string $expected)
167+
{
168+
$this->assertStringContainsString($expected, ProxyHelper::generateLazyProxy(new \ReflectionClass($obj::class)));
169+
}
170+
171+
public static function classWithUnserializeMagicMethodProvider(): iterable
172+
{
173+
yield 'not type hinted __unserialize method' => [new class() {
174+
public function __unserialize($array)
175+
{
176+
}
177+
}, <<<'EOPHP'
178+
implements \Symfony\Component\VarExporter\LazyObjectInterface
179+
{
180+
use \Symfony\Component\VarExporter\LazyProxyTrait {
181+
__unserialize as private __doUnserialize;
182+
}
183+
184+
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
185+
186+
public function __unserialize($data): void
187+
{
188+
$this->__doUnserialize($data);
189+
}
190+
}
191+
EOPHP];
192+
193+
yield 'type hinted __unserialize method' => [new class() {
194+
public function __unserialize(array $array)
195+
{
196+
}
197+
}, <<<'EOPHP'
198+
implements \Symfony\Component\VarExporter\LazyObjectInterface
199+
{
200+
use \Symfony\Component\VarExporter\LazyProxyTrait;
201+
202+
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
203+
}
204+
EOPHP];
205+
}
206+
163207
public function testAttributes()
164208
{
165209
$expected = <<<'EOPHP'
@@ -182,6 +226,7 @@ public function foo(#[\SensitiveParameter, AnotherAttribute] $a): int
182226
{
183227
}
184228
});
229+
185230
$this->assertStringContainsString($expected, ProxyHelper::generateLazyProxy($class));
186231
}
187232

0 commit comments

Comments
 (0)