Skip to content

Embedded documents not updated after changing a remove operation to an update #2767

Open
@jfortunato

Description

@jfortunato

Bug Report

Q A
BC Break yes
Version 2.11.0

Summary

After removing a parent document with embedded documents and then changing this removal to an update in an onFlush listener, the embedded document updates are not applied.

Current behavior

After all operations have completed the embedded documents are not updated in the database, although the parent document is.

How to reproduce

#[ODM\Document]
class TestDocument
{
    #[ODM\Id]
    public ?string $id = null;

    #[ODM\Field(type: 'int')]
    public int $removedCount = 0;

    #[ODM\EmbedMany(targetDocument: TestEmbeddedDocument::class)]
    public $embeddedDocuments;

    public function __construct(array $embeddedDocuments)
    {
        $this->embeddedDocuments = new ArrayCollection($embeddedDocuments);
    }

    public function incrementRemovedCount(): void
    {
        $this->removedCount++;
        foreach ($this->embeddedDocuments as $embeddedDocument) {
            $embeddedDocument->removedCount++;
        }
    }
}

#[ODM\EmbeddedDocument]
class TestEmbeddedDocument
{
    #[ODM\Field(type: 'int')]
    public int $removedCount = 0;
}

Populate and remove the documents

// Save the parent document with 1 embedded document, both initialized
// with a `removedCount` of 0.
$document = new TestDocument([new TestEmbeddedDocument()]);
$dm->persist($document);
$dm->flush();

// Sometime later, not necessarily in the same script that initially saves
// the document, remove the document and trigger the event listener.
$dm->remove($document);
$dm->flush();

The event listener that changes the removal operation to an update operation

class MyEventListener
{
    public function onFlush(OnFlushEventArgs $eventArgs): void
    {
        $dm = $eventArgs->getDocumentManager();
        $uow = $dm->getUnitOfWork();

        foreach ($uow->getScheduledDocumentDeletions() as $document) {
            if ($document instanceof TestDocument) {
                // Increment the `removedCount` on both the parent document and
                // the embedded document
                $document->incrementRemovedCount();
                // Re-persist the same document & recompute changeset to change the operation from a
                // removal to an update.
                $dm->persist($document);
                $uow->recomputeSingleDocumentChangeSet($dm->getClassMetadata(TestDocument::class), $document);
            }
        }
    }
}

Expected behavior

After all operations have completed, both the embedded documents as well as the parent document should be updated in the database to have a removedCount of 1. This was the case before the 2.11.x release. What actually happens is that the parent document will have a removedCount of 1 but the embedded document will have a removedCount of 0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions