diff --git a/src/ChangeSet.php b/src/ChangeSet.php index feeaef67..53801b68 100644 --- a/src/ChangeSet.php +++ b/src/ChangeSet.php @@ -216,6 +216,22 @@ public function removeObject(DataObject $object) // TODO: Handle case of implicit added item being removed. $item->delete(); + + // Get the implicitly included items for this ChangeSet + $implicit = $this->calculateImplicit(); + + foreach ($this->Changes()->filter(['Added' => ChangeSetItem::IMPLICITLY]) as $changeSetItem) { + $objectKey = $this->implicitKey($changeSetItem); + + // If a ChangeSetItem exists, but isn't in $implicit, it's no longer required, so delete it + if (!array_key_exists($objectKey, $implicit ?? [])) { + $changeSetItem->delete(); + } else { + // Otherwise it is required, so update ReferencedBy and remove from $implicit + $changeSetItem->ReferencedBy()->setByIDList($implicit[$objectKey]['ReferencedBy']); + unset($implicit[$objectKey]); + } + } } $this->sync(); diff --git a/tests/php/ChangeSetTest.php b/tests/php/ChangeSetTest.php index 768e70b9..5ed3b1b5 100644 --- a/tests/php/ChangeSetTest.php +++ b/tests/php/ChangeSetTest.php @@ -735,4 +735,32 @@ public function testIsSyncedCanBeSkipped() $this->assertFalse($changeset->isSyncCalled, 'isSynced is skipped when providing truthy argument to publish'); } + + public function testRemoveObject() + { + $this->publishAllFixtures(); + + $mid1 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid1'); + $mid2 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid2'); + + $changeset = new ChangeSet(); + $changeset->write(); + $changeset->addObject($mid1); + $changeset->addObject($mid2); + $changeset->publish(); + + $changeset->removeObject($mid1); + + $this->assertChangeSetLooksLike( + $changeset, + [ + ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::EXPLICITLY, + ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY, + ] + ); + + $changeset->removeObject($mid2); + + $this->assertChangeSetLooksLike($changeset, []); + } }