Skip to content

Commit 1c82070

Browse files
committed
[ObjectMapper] initialize lazy objects
1 parent deac4c6 commit 1c82070

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

src/Symfony/Component/ObjectMapper/ObjectMapper.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\ObjectMapper\Metadata\ReflectionObjectMapperMetadataFactory;
2121
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException as PropertyAccessorNoSuchPropertyException;
2222
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
23+
use Symfony\Component\VarExporter\LazyObjectInterface;
2324

2425
/**
2526
* Object to object mapper.
@@ -300,6 +301,12 @@ private function getCallable(string|callable $fn, ?ContainerInterface $locator =
300301
*/
301302
private function getSourceReflectionClass(object $source, \ReflectionClass $targetRefl): \ReflectionClass
302303
{
304+
if ($source instanceof LazyObjectInterface) {
305+
$source->initializeLazyObject();
306+
} elseif (\PHP_VERSION_ID >= 80400) {
307+
(new \ReflectionClass($source))->initializeLazyObject($source);
308+
}
309+
303310
$metadata = $this->metadataFactory->create($source);
304311
try {
305312
$refl = new \ReflectionClass($source);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures;
13+
14+
use Symfony\Component\VarExporter\Internal\LazyDecoratorTrait;
15+
use Symfony\Component\VarExporter\LazyObjectInterface;
16+
17+
class LazyFoo extends \stdClass implements LazyObjectInterface
18+
{
19+
use LazyDecoratorTrait;
20+
21+
public string $name = 'foo';
22+
private ?bool $initialized;
23+
24+
public function initializeLazyObject(): static
25+
{
26+
$this->initialized = true;
27+
28+
return $this;
29+
}
30+
31+
public function getInitialized(): ?bool
32+
{
33+
return $this->initialized;
34+
}
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures;
13+
14+
class MyProxy
15+
{
16+
public string $name;
17+
}

src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallback\B as InstanceCallbackB;
4141
use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\A as InstanceCallbackWithArgumentsA;
4242
use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\B as InstanceCallbackWithArgumentsB;
43+
use Symfony\Component\ObjectMapper\Tests\Fixtures\LazyFoo;
4344
use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\AToBMapper;
4445
use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\MapStructMapperMetadataFactory;
4546
use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\Source;
@@ -51,6 +52,7 @@
5152
use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargetProperty\C as MultipleTargetPropertyC;
5253
use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargets\A as MultipleTargetsA;
5354
use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargets\C as MultipleTargetsC;
55+
use Symfony\Component\ObjectMapper\Tests\Fixtures\MyProxy;
5456
use Symfony\Component\ObjectMapper\Tests\Fixtures\Recursion\AB;
5557
use Symfony\Component\ObjectMapper\Tests\Fixtures\Recursion\Dto;
5658
use Symfony\Component\ObjectMapper\Tests\Fixtures\ServiceLocator\A as ServiceLocatorA;
@@ -345,4 +347,37 @@ public function testDefaultValueStdClassWithPropertyInfo()
345347
$this->assertSame('abc', $b->id);
346348
$this->assertNull($b->optional);
347349
}
350+
351+
public function testMapInitializesLazyObject()
352+
{
353+
$lazy = new LazyFoo();
354+
$mapper = new ObjectMapper();
355+
$mapper->map($lazy, \stdClass::class);
356+
$this->assertTrue($lazy->getInitialized());
357+
}
358+
359+
public function testMapInitializesNativePhp84LazyObject()
360+
{
361+
if (\PHP_VERSION_ID < 80400) {
362+
$this->markTestSkipped('Native lazy objects require PHP 8.4 or higher.');
363+
}
364+
365+
$initialized = false;
366+
$initializer = function () use (&$initialized) {
367+
$initialized = true;
368+
369+
$p = new MyProxy();
370+
$p->name = 'test';
371+
372+
return $p;
373+
};
374+
375+
$r = new \ReflectionClass(MyProxy::class);
376+
$lazyObj = $r->newLazyProxy($initializer);
377+
$this->assertFalse($initialized);
378+
$mapper = new ObjectMapper();
379+
$d = $mapper->map($lazyObj, MyProxy::class);
380+
$this->assertSame('test', $d->name);
381+
$this->assertTrue($initialized);
382+
}
348383
}

src/Symfony/Component/ObjectMapper/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"psr/container": "^2.0"
2121
},
2222
"require-dev": {
23-
"symfony/property-access": "^7.2"
23+
"symfony/property-access": "^7.2",
24+
"symfony/var-exporter": "^7.2"
2425
},
2526
"autoload": {
2627
"psr-4": {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy