Skip to content

Commit ce7b4f7

Browse files
committed
feature: allow to create objects in dataProvider thanks to lazy proxy
1 parent 105c4ce commit ce7b4f7

12 files changed

+246
-144
lines changed

src/Persistence/IsProxy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ public function _repository(): ProxyRepositoryDecorator
112112
return new ProxyRepositoryDecorator(parent::class);
113113
}
114114

115+
public function _initializeLazyObject(): void
116+
{
117+
$this->initializeLazyObject();
118+
}
119+
115120
private function _autoRefresh(): void
116121
{
117122
if (!$this->_getAutoRefresh()) {

src/Persistence/PersistentObjectFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ final public static function truncate(): void
204204
static::repository()->truncate();
205205
}
206206

207-
final public function create(callable|array $attributes = []): object
207+
public function create(callable|array $attributes = []): object
208208
{
209209
$object = parent::create($attributes);
210210

src/Persistence/PersistentProxyObjectFactory.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Doctrine\Persistence\ObjectRepository;
1515
use Zenstruck\Foundry\Configuration;
16+
use Zenstruck\Foundry\Exception\FoundryNotBooted;
1617
use Zenstruck\Foundry\Factory;
1718
use Zenstruck\Foundry\Object\Instantiator;
1819
use Zenstruck\Foundry\FactoryCollection; // keep me!
@@ -36,6 +37,15 @@
3637
*/
3738
abstract class PersistentProxyObjectFactory extends PersistentObjectFactory
3839
{
40+
public function create(callable|array $attributes = []): object
41+
{
42+
try {
43+
return parent::create($attributes);
44+
} catch (FoundryNotBooted) {
45+
return ProxyGenerator::wrapFactory($this, $attributes);
46+
}
47+
}
48+
3949
/**
4050
* @return class-string<T>
4151
*/

src/Persistence/Proxy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ public function _real(): object;
4949
* @return ProxyRepositoryDecorator<T,ObjectRepository<T>>
5050
*/
5151
public function _repository(): ProxyRepositoryDecorator;
52+
53+
/**
54+
* @internal
55+
*/
56+
public function _initializeLazyObject(): void;
5257
}

src/Persistence/ProxyGenerator.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public static function wrap(object $object): Proxy
4343
return self::generateClassFor($object)::createLazyProxy(static fn() => $object); // @phpstan-ignore-line
4444
}
4545

46+
public static function wrapFactory(PersistentProxyObjectFactory $factory, callable|array $attributes): Proxy
47+
{
48+
return self::generateClassFor($factory)::createLazyProxy(static fn() => $factory->create($attributes)); // @phpstan-ignore-line
49+
}
50+
4651
/**
4752
* @template T
4853
*
@@ -76,8 +81,8 @@ public static function unwrap(mixed $what): mixed
7681
*/
7782
private static function generateClassFor(object $object): string
7883
{
79-
/** @var class-string $class */
80-
$class = $object instanceof DoctrineProxy ? \get_parent_class($object) : $object::class;
84+
$class = self::extractClassName($object);
85+
8186
$proxyClass = \str_replace('\\', '', $class).'Proxy';
8287

8388
/** @var class-string<LazyObjectInterface&Proxy<T>&T> $proxyClass */
@@ -143,4 +148,16 @@ public function __unserialize(\$data): void
143148

144149
return $proxyCode;
145150
}
151+
152+
/**
153+
* @return class-string
154+
*/
155+
private static function extractClassName(object $object): string
156+
{
157+
if ($object instanceof PersistentProxyObjectFactory) {
158+
return $object::class();
159+
}
160+
161+
return $object instanceof DoctrineProxy ? \get_parent_class($object) : $object::class;
162+
}
146163
}

src/Test/Factories.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
use PHPUnit\Framework\Attributes\After;
1515
use PHPUnit\Framework\Attributes\Before;
1616
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
17+
use Symfony\Component\VarExporter\LazyObjectInterface;
18+
use Webmozart\Assert\Assert;
1719
use Zenstruck\Foundry\Configuration;
20+
use Zenstruck\Foundry\Persistence\Proxy;
1821

1922
/**
2023
* @author Kevin Bond <[email protected]>
@@ -26,7 +29,7 @@ trait Factories
2629
* @before
2730
*/
2831
#[Before]
29-
public static function _bootFoundry(): void
32+
public function _bootFoundry(): void
3033
{
3134
if (!\is_subclass_of(static::class, KernelTestCase::class)) { // @phpstan-ignore-line
3235
// unit test
@@ -46,6 +49,34 @@ public static function _bootFoundry(): void
4649
});
4750
}
4851

52+
/**
53+
* @internal
54+
* @before
55+
*/
56+
#[Before]
57+
public function _loadDataProvidedProxies(): void
58+
{
59+
if (!\is_subclass_of(static::class, KernelTestCase::class)) { // @phpstan-ignore-line
60+
return;
61+
}
62+
63+
$providedData = method_exists($this, 'getProvidedData') ? $this->getProvidedData() : $this->providedData(); // @phpstan-ignore method.notFound
64+
65+
foreach ($providedData as $providedDatum) {
66+
if ($providedDatum instanceof Proxy) {
67+
$providedDatum->_initializeLazyObject();
68+
}
69+
70+
if (is_array($providedDatum) && count($providedDatum)) {
71+
foreach ($providedDatum as $itemFromCollection) {
72+
if ($itemFromCollection instanceof Proxy) {
73+
$itemFromCollection->_initializeLazyObject();
74+
}
75+
}
76+
}
77+
}
78+
}
79+
4980
/**
5081
* @internal
5182
* @after

tests/Integration/Mongo/GenericDocumentFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class GenericDocumentFactoryTest extends GenericFactoryTestCase
2323
{
2424
use RequiresMongo;
2525

26-
protected function factory(): GenericModelFactory
26+
protected static function factory(): GenericDocumentFactory
2727
{
2828
return GenericDocumentFactory::new();
2929
}

tests/Integration/Mongo/GenericDocumentProxyFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ final class GenericDocumentProxyFactoryTest extends GenericProxyFactoryTestCase
2626
{
2727
use RequiresMongo;
2828

29-
protected function factory(): PersistentProxyObjectFactory
29+
protected static function factory(): GenericProxyDocumentFactory
3030
{
3131
return GenericProxyDocumentFactory::new();
3232
}

tests/Integration/ORM/GenericEntityFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class GenericEntityFactoryTest extends GenericFactoryTestCase
2323
{
2424
use RequiresORM;
2525

26-
protected function factory(): GenericModelFactory
26+
protected static function factory(): GenericEntityFactory
2727
{
2828
return GenericEntityFactory::new();
2929
}

tests/Integration/ORM/GenericEntityProxyFactoryTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;
1515
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\EntityWithReadonly\EntityWithReadonly;
16+
use Zenstruck\Foundry\Tests\Fixture\Entity\GenericEntity;
17+
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\GenericEntityFactory;
1618
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\GenericProxyEntityFactory;
1719
use Zenstruck\Foundry\Tests\Integration\Persistence\GenericProxyFactoryTestCase;
1820
use Zenstruck\Foundry\Tests\Integration\RequiresORM;
@@ -26,7 +28,7 @@ final class GenericEntityProxyFactoryTest extends GenericProxyFactoryTestCase
2628
{
2729
use RequiresORM;
2830

29-
protected function factory(): PersistentProxyObjectFactory
31+
protected static function factory(): GenericProxyEntityFactory
3032
{
3133
return GenericProxyEntityFactory::new();
3234
}

0 commit comments

Comments
 (0)