Skip to content

Commit 1dccda1

Browse files
authored
[bug] fix/improve embeddable support (#193)
- fix regression in #181 (closes #192) - remove requirement to call `->withoutPersisting()` for embeddables
1 parent 5f39d8a commit 1dccda1

File tree

9 files changed

+114
-9
lines changed

9 files changed

+114
-9
lines changed

src/Factory.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,21 @@ private function relationshipField(self $factory): ?string
355355

356356
// Check inversedBy side ($this is the owner of the relation)
357357
$factoryClassMetadata = self::configuration()->objectManagerFor($factoryClass)->getMetadataFactory()->getMetadataFor($factoryClass);
358+
358359
foreach ($factoryClassMetadata->getAssociationNames() as $field) {
359360
if (!$factoryClassMetadata->isAssociationInverseSide($field) && $factoryClassMetadata->getAssociationTargetClass($field) === $relationClass) {
360361
return $field;
361362
}
362363
}
363364

364-
// Check mappedBy side ($factory is the owner of the relation)
365-
$relationClassMetadata = self::configuration()->objectManagerFor($relationClass)->getClassMetadata($relationClass);
365+
try {
366+
// Check mappedBy side ($factory is the owner of the relation)
367+
$relationClassMetadata = self::configuration()->objectManagerFor($relationClass)->getClassMetadata($relationClass);
368+
} catch (\RuntimeException $e) {
369+
// relation not managed - could be embeddable
370+
return null;
371+
}
372+
366373
foreach ($relationClassMetadata->getAssociationNames() as $field) {
367374
if (($relationClassMetadata->isSingleValuedAssociation($field) || $relationClassMetadata->isCollectionValuedAssociation($field)) && $relationClassMetadata->getAssociationTargetClass($field) === $factoryClass) {
368375
return $field;
@@ -418,6 +425,17 @@ private function hasCascadePersist(self $factory, ?string $field): bool
418425

419426
private function isPersisting(): bool
420427
{
421-
return self::configuration()->hasManagerRegistry() ? $this->persist : false;
428+
if (!$this->persist || !self::configuration()->hasManagerRegistry()) {
429+
return false;
430+
}
431+
432+
try {
433+
self::configuration()->objectManagerFor($this->class);
434+
435+
return true;
436+
} catch (\RuntimeException $e) {
437+
// entity not managed (perhaps Embeddable)
438+
return false;
439+
}
422440
}
423441
}

tests/Fixtures/Entity/Contact.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ public function getAddress(): Address
4242
{
4343
return $this->address;
4444
}
45+
46+
public function setAddress(Address $address): void
47+
{
48+
$this->address = $address;
49+
}
4550
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Zenstruck\Foundry\Tests\Fixtures\Factories;
4+
5+
use Zenstruck\Foundry\ModelFactory;
6+
use Zenstruck\Foundry\Tests\Fixtures\Entity\Address;
7+
8+
/**
9+
* @author Kevin Bond <kevinbond@gmail.com>
10+
*/
11+
final class AddressFactory extends ModelFactory
12+
{
13+
protected static function getClass(): string
14+
{
15+
return Address::class;
16+
}
17+
18+
protected function getDefaults(): array
19+
{
20+
return ['value' => 'Some address'];
21+
}
22+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Zenstruck\Foundry\Tests\Fixtures\Factories;
4+
5+
use Zenstruck\Foundry\ModelFactory;
6+
use Zenstruck\Foundry\Tests\Fixtures\Entity\Contact;
7+
8+
/**
9+
* @author Kevin Bond <kevinbond@gmail.com>
10+
*/
11+
final class ContactFactory extends ModelFactory
12+
{
13+
protected static function getClass(): string
14+
{
15+
return Contact::class;
16+
}
17+
18+
protected function getDefaults(): array
19+
{
20+
return [
21+
'name' => 'Sally',
22+
'address' => AddressFactory::new(),
23+
];
24+
}
25+
}

tests/Functional/FactoryTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Zenstruck\Foundry\AnonymousFactory;
77
use Zenstruck\Foundry\Test\Factories;
88
use Zenstruck\Foundry\Test\ResetDatabase;
9+
use Zenstruck\Foundry\Tests\Fixtures\Entity\Address;
910
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
1011
use Zenstruck\Foundry\Tests\Fixtures\Entity\Post;
1112
use Zenstruck\Foundry\Tests\Fixtures\Entity\Tag;
@@ -122,4 +123,16 @@ public function creating_with_factory_attribute_persists_the_factory(): void
122123

123124
$this->assertNotNull($object->getCategory()->getId());
124125
}
126+
127+
/**
128+
* @test
129+
*/
130+
public function can_create_embeddable(): void
131+
{
132+
$object1 = (new AnonymousFactory(Address::class))->create();
133+
$object2 = (new AnonymousFactory(Address::class))->create(['value' => 'an address']);
134+
135+
$this->assertNull($object1->getValue());
136+
$this->assertSame('an address', $object2->getValue());
137+
}
125138
}

tests/Functional/ModelFactoryTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
use Zenstruck\Foundry\Test\Factories;
88
use Zenstruck\Foundry\Test\ResetDatabase;
99
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
10+
use Zenstruck\Foundry\Tests\Fixtures\Factories\AddressFactory;
1011
use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryFactory;
1112
use Zenstruck\Foundry\Tests\Fixtures\Factories\CommentFactory;
13+
use Zenstruck\Foundry\Tests\Fixtures\Factories\ContactFactory;
1214
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactory;
1315
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactoryWithInvalidInitialize;
1416
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactoryWithNullInitialize;
@@ -440,4 +442,30 @@ public function can_find_by(): void
440442
$this->assertSame('name2', $categories[0]->getName());
441443
$this->assertSame('name2', $categories[1]->getName());
442444
}
445+
446+
/**
447+
* @test
448+
*/
449+
public function embeddables_are_never_persisted(): void
450+
{
451+
$object1 = AddressFactory::createOne();
452+
$object2 = AddressFactory::createOne(['value' => 'another address']);
453+
454+
$this->assertSame('Some address', $object1->getValue());
455+
$this->assertSame('another address', $object2->getValue());
456+
}
457+
458+
/**
459+
* @test
460+
*/
461+
public function factory_with_embeddable(): void
462+
{
463+
ContactFactory::repository()->assert()->empty();
464+
465+
$object = ContactFactory::createOne();
466+
467+
ContactFactory::repository()->assert()->count(1);
468+
$this->assertSame('Sally', $object->getName());
469+
$this->assertSame('Some address', $object->getAddress()->getValue());
470+
}
443471
}

tests/Unit/FactoryTest.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ public function can_create_object(): void
254254
{
255255
$registry = $this->createMock(ManagerRegistry::class);
256256
$registry
257-
->expects($this->exactly(2))
258257
->method('getManagerForClass')
259258
->with(Post::class)
260259
->willReturn($this->createMock(ObjectManager::class))
@@ -278,7 +277,6 @@ public function can_create_many_objects_legacy(): void
278277

279278
$registry = $this->createMock(ManagerRegistry::class);
280279
$registry
281-
->expects($this->exactly(6))
282280
->method('getManagerForClass')
283281
->with(Post::class)
284282
->willReturn($this->createMock(ObjectManager::class))
@@ -304,7 +302,6 @@ public function can_add_after_persist_events(): void
304302
{
305303
$registry = $this->createMock(ManagerRegistry::class);
306304
$registry
307-
->expects($this->exactly(2)) // once for persisting, once for each afterPersist event
308305
->method('getManagerForClass')
309306
->with(Post::class)
310307
->willReturn($this->createMock(ObjectManager::class))

tests/Unit/FunctionsTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ public function create(): void
6565
{
6666
$registry = $this->createMock(ManagerRegistry::class);
6767
$registry
68-
->expects($this->exactly(2))
6968
->method('getManagerForClass')
7069
->with(Category::class)
7170
->willReturn($this->createMock(ObjectManager::class))
@@ -85,7 +84,6 @@ public function create_many(): void
8584
{
8685
$registry = $this->createMock(ManagerRegistry::class);
8786
$registry
88-
->expects($this->exactly(6))
8987
->method('getManagerForClass')
9088
->with(Category::class)
9189
->willReturn($this->createMock(ObjectManager::class))

tests/Unit/ProxyTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ public function saving_unpersisted_proxy_changes_it_to_a_persisted_proxy(): void
7171
{
7272
$registry = $this->createMock(ManagerRegistry::class);
7373
$registry
74-
->expects($this->exactly(2))
7574
->method('getManagerForClass')
7675
->with(Category::class)
7776
->willReturn($this->createMock(ObjectManager::class))

0 commit comments

Comments
 (0)