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 Remove implicitly added item #423

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
16 changes: 16 additions & 0 deletions src/ChangeSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
118 changes: 113 additions & 5 deletions tests/php/ChangeSetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ public function testRepeatedSyncIsNOP()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand All @@ -172,6 +173,7 @@ public function testRepeatedSyncIsNOP()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand All @@ -196,6 +198,7 @@ public function testSync()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand All @@ -214,6 +217,7 @@ public function testSync()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand Down Expand Up @@ -255,6 +259,7 @@ public function testSync()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand Down Expand Up @@ -301,6 +306,7 @@ public function testIsSynced()
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
Expand All @@ -319,6 +325,7 @@ public function testIsSynced()
[
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
);
Expand All @@ -334,7 +341,7 @@ public function testCanPublish()
$base = $this->objFromFixture(ChangeSetTest\BaseObject::class, 'base');
$changeSet->addObject($base);
$changeSet->sync();
$this->assertEquals(5, $changeSet->Changes()->count());
$this->assertEquals(6, $changeSet->Changes()->count());

// Test un-authenticated user cannot publish
$this->logOut();
Expand Down Expand Up @@ -378,7 +385,7 @@ public function testCanPublishNested()
$changeSet->addObject($base);
$changeSet->addObject($mid1);
$changeSet->sync();
$this->assertEquals(5, $changeSet->Changes()->count());
$this->assertEquals(6, $changeSet->Changes()->count());

// With model publish permissions only publish is allowed
$this->assertTrue($changeSet->canPublish());
Expand Down Expand Up @@ -434,7 +441,7 @@ public function testCanEdit()
$base = $this->objFromFixture(ChangeSetTest\BaseObject::class, 'base');
$changeSet->addObject($base);
$changeSet->sync();
$this->assertEquals(5, $changeSet->Changes()->count());
$this->assertEquals(6, $changeSet->Changes()->count());

// Check canEdit
$this->logOut();
Expand Down Expand Up @@ -465,7 +472,7 @@ public function testCanDelete()
$base = $this->objFromFixture(ChangeSetTest\BaseObject::class, 'base');
$changeSet->addObject($base);
$changeSet->sync();
$this->assertEquals(5, $changeSet->Changes()->count());
$this->assertEquals(6, $changeSet->Changes()->count());

// Check canDelete
$this->logOut();
Expand All @@ -485,7 +492,7 @@ public function testCanView()
$base = $this->objFromFixture(ChangeSetTest\BaseObject::class, 'base');
$changeSet->addObject($base);
$changeSet->sync();
$this->assertEquals(5, $changeSet->Changes()->count());
$this->assertEquals(6, $changeSet->Changes()->count());

// Check canView
$this->logOut();
Expand Down Expand Up @@ -617,6 +624,7 @@ public function testUnlinkDisassociated()
[
ChangeSetTest\BaseObject::class . '.base' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
);
Expand Down Expand Up @@ -735,4 +743,104 @@ public function testIsSyncedCanBeSkipped()

$this->assertFalse($changeset->isSyncCalled, 'isSynced is skipped when providing truthy argument to publish');
}

public function testRemoveObject()
maxime-rainville marked this conversation as resolved.
Show resolved Hide resolved
{
$this->publishAllFixtures();

$mid1 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid1'); // Item mid2 reference Item end2

$changeset = new ChangeSet();
$changeset->write();
$changeset->addObject($mid1);
$changeset->publish();

maxime-rainville marked this conversation as resolved.
Show resolved Hide resolved
$this->assertChangeSetLooksLike(
$changeset,
[
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
]
);

$changeset->removeObject($mid1); // Remove mid1

$this->assertChangeSetLooksLike(
$changeset,
[]
);
}

public function testRemoveObjectsWithReferencesToOneItem()
{
$this->publishAllFixtures();

$mid2 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid2'); // Item mid2 reference Item end2
$mid3 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid4'); // Item mid4 reference Item end2

$changeset = new ChangeSet();
$changeset->write();
$changeset->addObject($mid2);
$changeset->addObject($mid3);
$changeset->publish();

$this->assertChangeSetLooksLike(
$changeset,
[
ChangeSetTest\MidObject::class . '.mid2' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY,
]
);

$changeset->removeObject($mid2); // Remove mid2

$this->assertChangeSetLooksLike(
$changeset,
[
ChangeSetTest\MidObject::class . '.mid4' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\EndObject::class . '.end2' => ChangeSetItem::IMPLICITLY, // Item end2 is still in ChangeSet
]
);

$changeset->removeObject($mid3); // Remove mid3

$this->assertChangeSetLooksLike(
$changeset,
[]
);
}

public function testRemoveObjectWithImplicitlyAddedItemOnly()
{
$this->publishAllFixtures();

$mid1 = $this->objFromFixture(ChangeSetTest\MidObject::class, 'mid1'); // Item mid1 reference Item end1
$end1 = $this->objFromFixture(ChangeSetTest\EndObject::class, 'end1'); // Item end1

$changeset = new ChangeSet();
$changeset->write();
$changeset->addObject($mid1);
$changeset->addObject($end1); // Item end1 explicitly added to ChangeSet
$changeset->publish();

$this->assertChangeSetLooksLike(
$changeset,
[
ChangeSetTest\MidObject::class . '.mid1' => ChangeSetItem::EXPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::IMPLICITLY,
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::EXPLICITLY
]
);

$changeset->removeObject($mid1); // Remove mid1

$this->assertChangeSetLooksLike(
$changeset,
[
ChangeSetTest\EndObject::class . '.end1' => ChangeSetItem::EXPLICITLY // Item end1 is still in ChangeSet
]
);
}
maxime-rainville marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 4 additions & 0 deletions tests/php/ChangeSetTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ SilverStripe\Versioned\Tests\ChangeSetTest\MidObject:
End: =>SilverStripe\Versioned\Tests\ChangeSetTest\EndObject.end2
mid3:
Base: =>SilverStripe\Versioned\Tests\ChangeSetTest\BaseObject.base2
mid4:
Bar: 3
Base: =>SilverStripe\Versioned\Tests\ChangeSetTest\BaseObject.base
End: =>SilverStripe\Versioned\Tests\ChangeSetTest\EndObject.end2
SilverStripe\Versioned\Tests\ChangeSetTest\UnversionedObject:
unversioned1:
Title: 'object'
Expand Down