Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use Doctrine metadata even when persist is disabled #841

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/Persistence/PersistentObjectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,15 @@ protected function normalizeParameter(string $field, mixed $value): mixed
if ($inversedRelationshipMetadata && !$inversedRelationshipMetadata->isCollection) {
$inverseField = $inversedRelationshipMetadata->inverseField;

// we need to handle the circular dependency involved by inversed one-to-one relationship:
// a placeholder object is used, which will be replaced by the real object, after its instantiation
$inversedObject = $value->withPersistMode(PersistMode::NO_PERSIST_BUT_SCHEDULE_FOR_INSERT)
->create([$inverseField => $placeholder = (new \ReflectionClass(static::class()))->newInstanceWithoutConstructor()]);
$inversedObject = $value->withPersistMode(
$this->isPersisting() ? PersistMode::NO_PERSIST_BUT_SCHEDULE_FOR_INSERT : PersistMode::WITHOUT_PERSISTING
)

// we need to handle the circular dependency involved by inversed one-to-one relationship:
// a placeholder object is used, which will be replaced by the real object, after its instantiation
->create([
$inverseField => $placeholder = (new \ReflectionClass(static::class()))->newInstanceWithoutConstructor(),
]);

$inversedObject = unproxy($inversedObject, withAutoRefresh: false);

Expand All @@ -312,7 +317,7 @@ protected function normalizeParameter(string $field, mixed $value): mixed

protected function normalizeCollection(string $field, FactoryCollection $collection): array
{
if (!$this->isPersisting() || !$collection->factory instanceof self) {
if (!Configuration::instance()->isPersistenceAvailable() || !$collection->factory instanceof self) {
return parent::normalizeCollection($field, $collection);
}

Expand All @@ -321,10 +326,13 @@ protected function normalizeCollection(string $field, FactoryCollection $collect
$inverseRelationshipMetadata = $pm->inverseRelationshipMetadata(static::class(), $collection->factory::class(), $field);

if ($inverseRelationshipMetadata && $inverseRelationshipMetadata->isCollection) {
$this->tempAfterInstantiate[] = static function(object $object) use ($collection, $inverseRelationshipMetadata, $field) {
$this->tempAfterInstantiate[] = function(object $object) use ($collection, $inverseRelationshipMetadata, $field) {
$inverseField = $inverseRelationshipMetadata->inverseField;

$inverseObjects = $collection->withPersistMode(PersistMode::NO_PERSIST_BUT_SCHEDULE_FOR_INSERT)->create([$inverseField => $object]);
$inverseObjects = $collection->withPersistMode(
$this->isPersisting() ? PersistMode::NO_PERSIST_BUT_SCHEDULE_FOR_INSERT : PersistMode::WITHOUT_PERSISTING
)
->create([$inverseField => $object]);

$inverseObjects = unproxy($inverseObjects, withAutoRefresh: false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,21 @@ public function disabling_persistence_cascades_to_children(): void
foreach ($contact->getTags() as $tag) {
$this->assertNull($tag->id);
}
}

/** @test */
#[Test]
#[DataProvider('provideCascadeRelationshipsCombinations')]
#[UsingRelationships(Contact::class, ['category'])]
public function disabling_persistence_cascades_to_children_one_to_many(): void
{
$category = static::categoryFactory()->withoutPersisting()->create([
'contacts' => static::contactFactory()->many(3),
]);

// ensure nothing was persisted in Doctrine by flushing
self::getContainer()->get(EntityManagerInterface::class)->flush(); // @phpstan-ignore method.notFound

static::contactFactory()::assert()->empty();
static::categoryFactory()::assert()->empty();

Expand All @@ -340,6 +350,27 @@ public function disabling_persistence_cascades_to_children(): void
}
}

/** @test */
#[Test]
#[DataProvider('provideCascadeRelationshipsCombinations')]
#[UsingRelationships(Contact::class, ['address'])]
public function disabling_persistence_cascades_to_children_inversed_one_to_one(): void
{
$address = static::addressFactory()->withoutPersisting()->create([
'contact' => static::contactFactory(),
]);

// ensure nothing was persisted in Doctrine by flushing
self::getContainer()->get(EntityManagerInterface::class)->flush(); // @phpstan-ignore method.notFound

static::contactFactory()::assert()->empty();
static::addressFactory()::assert()->empty();

$this->assertNull($address->id);
$this->assertInstanceOf(Contact::class, $address->getContact());
$this->assertNull($address->getContact()->id);
}

/** @test */
#[Test]
#[DataProvider('provideCascadeRelationshipsCombinations')]
Expand Down