Skip to content

Commit 211b6fe

Browse files
authored
Resolved a bug where a soft-deleted object isn't remove from the ObjectManager
1 parent 08207de commit 211b6fe

File tree

5 files changed

+75
-3
lines changed

5 files changed

+75
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ a release.
1818
---
1919

2020
## [Unreleased]
21+
### Fixed
22+
- SoftDeleteable: Resolved a bug where a soft-deleted object isn't remove from the ObjectManager (#2930)
23+
2124
### Added
2225
- IP address provider for use with extensions with IP address references (#2928)
2326

@@ -105,7 +108,7 @@ a release.
105108
- Dropped support for doctrine/dbal < 3.2
106109

107110
### Deprecated
108-
- Calling `Gedmo\Mapping\Event\Adapter\ORM::getObjectManager()` and `getObject()` on EventArgs that do not implement `getObjectManager()` and `getObject()` (such as old EventArgs implementing `getEntityManager()` and `getEntity()`)
111+
- Calling `Gedmo\Mapping\Event\Adapter\ORM::getObjectManager()` and `getObject()` on EventArgs that do not implement `getObjectManager()` and `getObject()` (such as old EventArgs implementing `getEntityManager()` and `getEntity()`)
109112
- Calling `Gedmo\Uploadable\Event\UploadableBaseEventArgs::getEntityManager()` and `getEntity()`. Call `getObjectManager()` and `getObject()` instead.
110113

111114
## [3.13.0] - 2023-09-06

src/SoftDeleteable/SoftDeleteableListener.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class SoftDeleteableListener extends MappedEventSubscriber
5151
*/
5252
public const POST_SOFT_DELETE = 'postSoftDelete';
5353

54+
/**
55+
* Objects soft-deleted on flush.
56+
*
57+
* @var array<object>
58+
*/
59+
private array $softDeletedObjects = [];
60+
5461
/**
5562
* @return string[]
5663
*/
@@ -59,6 +66,7 @@ public function getSubscribedEvents()
5966
return [
6067
'loadClassMetadata',
6168
'onFlush',
69+
'postFlush',
6270
];
6371
}
6472

@@ -102,7 +110,7 @@ public function onFlush(EventArgs $args)
102110

103111
$evm->dispatchEvent(
104112
self::PRE_SOFT_DELETE,
105-
$preSoftDeleteEventArgs
113+
$preSoftDeleteEventArgs,
106114
);
107115
}
108116

@@ -129,10 +137,27 @@ public function onFlush(EventArgs $args)
129137
$postSoftDeleteEventArgs
130138
);
131139
}
140+
141+
$this->softDeletedObjects[] = $object;
132142
}
133143
}
134144
}
135145

146+
/**
147+
* Detach soft-deleted objects from object manager.
148+
*
149+
* @return void
150+
*/
151+
public function postFlush(EventArgs $args)
152+
{
153+
$ea = $this->getEventAdapter($args);
154+
$om = $ea->getObjectManager();
155+
foreach ($this->softDeletedObjects as $index => $object) {
156+
$om->detach($object);
157+
unset($this->softDeletedObjects[$index]);
158+
}
159+
}
160+
136161
/**
137162
* Maps additional metadata
138163
*

tests/Gedmo/Blameable/Fixture/Entity/Article.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Article implements Blameable
4848
* @ORM\OneToMany(targetEntity="Gedmo\Tests\Blameable\Fixture\Entity\Comment", mappedBy="article")
4949
*/
5050
#[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'article')]
51-
private $comments;
51+
private Collection $comments;
5252

5353
/**
5454
* @Gedmo\Blameable(on="create")

tests/Gedmo/SoftDeleteable/Fixture/Entity/Article.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,12 @@ public function addComment(Comment $comment): void
9292
{
9393
$this->comments[] = $comment;
9494
}
95+
96+
/**
97+
* @return Collection<int, Comment>
98+
*/
99+
public function getComments(): Collection
100+
{
101+
return $this->comments;
102+
}
95103
}

tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,42 @@ public function testShouldFilterBeQueryCachedCorrectlyWhenToggledForEntity(): vo
522522
static::assertCount(0, $data);
523523
}
524524

525+
public function testSoftDeletedObjectIsRemovedPostFlush(): void
526+
{
527+
$repo = $this->em->getRepository(Article::class);
528+
$commentRepo = $this->em->getRepository(Comment::class);
529+
530+
$comment = new Comment();
531+
$commentValue = 'Comment 1';
532+
$comment->setComment($commentValue);
533+
534+
$art0 = new Article();
535+
$field = 'title';
536+
$value = 'Title 1';
537+
$art0->setTitle($value);
538+
$art0->addComment($comment);
539+
540+
$this->em->persist($art0);
541+
$this->em->flush();
542+
543+
$art = $repo->findOneBy([$field => $value]);
544+
545+
static::assertNull($art->getDeletedAt());
546+
static::assertNull($comment->getDeletedAt());
547+
static::assertCount(1, $art->getComments());
548+
549+
$this->em->remove($comment);
550+
551+
// The Comment has been marked for removal, but not yet flushed. This means the
552+
// Comment should still be available.
553+
static::assertInstanceOf(Comment::class, $commentRepo->find($comment->getId()));
554+
555+
$this->em->flush();
556+
557+
// Now that we've flushed, the Comment should no longer be available and should return null.
558+
static::assertNull($commentRepo->find($comment->getId()));
559+
}
560+
525561
public function testPostSoftDeleteEventIsDispatched(): void
526562
{
527563
$this->em->getEventManager()->addEventSubscriber(new WithPreAndPostSoftDeleteEventArgsTypeListener());

0 commit comments

Comments
 (0)