Skip to content

Commit

Permalink
Merge pull request #5302 from open-sausages/pulls/4.0/changesets-impr…
Browse files Browse the repository at this point in the history
…ove-api

Improve changset api & resiliency
  • Loading branch information
Damian Mooyman committed Apr 15, 2016
2 parents 38025f5 + 9a5db5f commit 2e259d1
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
8 changes: 4 additions & 4 deletions model/versioning/ChangeSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public function addObject(DataObject $object) {

$references = [
'ObjectID' => $object->ID,
'ObjectClass' => $object->ClassName
'ObjectClass' => ClassInfo::baseDataClass($object)
];

// Get existing item in case already added
Expand Down Expand Up @@ -146,7 +146,7 @@ public function addObject(DataObject $object) {
public function removeObject(DataObject $object) {
$item = ChangeSetItem::get()->filter([
'ObjectID' => $object->ID,
'ObjectClass' => $object->ClassName,
'ObjectClass' => ClassInfo::baseDataClass($object),
'ChangeSetID' => $this->ID
])->first();

Expand All @@ -161,7 +161,7 @@ public function removeObject(DataObject $object) {

protected function implicitKey($item) {
if ($item instanceof ChangeSetItem) return $item->ObjectClass.'.'.$item->ObjectID;
return $item->ClassName.'.'.$item->ID;
return ClassInfo::baseDataClass($item).'.'.$item->ID;
}

protected function calculateImplicit() {
Expand All @@ -183,7 +183,7 @@ protected function calculateImplicit() {

$referenced[$key] = [
'ObjectID' => $referee->ID,
'ObjectClass' => $referee->ClassName
'ObjectClass' => ClassInfo::baseDataClass($referee)
];

$references[$key][] = $item->ID;
Expand Down
40 changes: 35 additions & 5 deletions model/versioning/ChangeSetItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
* A single line in a changeset
*
* @property string $Added
* @property string $ObjectClass
* @property int $ObjectID
* @property string $ObjectClass The _base_ data class for the referenced DataObject
* @property int $ObjectID The numeric ID for the referenced object
* @method ManyManyList ReferencedBy() List of explicit items that require this change
* @method ManyManyList References() List of implicit items required by this change
* @method ChangeSet ChangeSet()
Expand Down Expand Up @@ -65,6 +65,12 @@ class ChangeSetItem extends DataObject implements Thumbnail {
)
);

public function onBeforeWrite() {
// Make sure ObjectClass refers to the base data class in the case of old or wrong code
$this->ObjectClass = ClassInfo::baseDataClass($this->ObjectClass);
parent::onBeforeWrite();
}

public function getTitle() {
// Get title of modified object
$object = $this->getObjectLatestVersion();
Expand All @@ -74,8 +80,6 @@ public function getTitle() {
return $this->i18n_singular_name() . ' #' . $this->ID;
}



/**
* Get a thumbnail for this object
*
Expand All @@ -91,7 +95,6 @@ public function ThumbnailURL($width, $height) {
return null;
}


/**
* Get the type of change: none, created, deleted, modified, manymany
*
Expand Down Expand Up @@ -315,4 +318,31 @@ public function can($perm, $member = null, $context = array()) {
// Default permissions
return (bool)Permission::checkMember($member, ChangeSet::config()->required_permission);
}

/**
* Get the ChangeSetItems that reference a passed DataObject
*
* @param DataObject $object
* @return DataList
*/
public static function get_for_object($object) {
return ChangeSetItem::get()->filter([
'ObjectID' => $object->ID,
'ObjectClass' => ClassInfo::baseDataClass($object)
]);
}

/**
* Get the ChangeSetItems that reference a passed DataObject
*
* @param int $objectID The ID of the object
* @param string $objectClass The class of the object (or any parent class)
* @return DataList
*/
public static function get_for_object_by_id($objectID, $objectClass) {
return ChangeSetItem::get()->filter([
'ObjectID' => $objectID,
'ObjectClass' => ClassInfo::baseDataClass($objectClass)
]);
}
}
23 changes: 22 additions & 1 deletion tests/model/ChangeSetItemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function testChangeType() {

$item = new ChangeSetItem([
'ObjectID' => $object->ID,
'ObjectClass' => $object->ClassName
'ObjectClass' => ClassInfo::baseDataClass($object->ClassName)
]);

$this->assertEquals(
Expand Down Expand Up @@ -73,4 +73,25 @@ function testChangeType() {
'Objects that have been deleted and then unpublished should return no change'
);
}

function testGetForObject() {
$object = new ChangeSetItemTest_Versioned(['Foo' => 1]);
$object->write();

$item = new ChangeSetItem([
'ObjectID' => $object->ID,
'ObjectClass' => ClassInfo::baseDataClass($object)
]);
$item->write();

$this->assertEquals(
ChangeSetItemTest_Versioned::get()->byID($object->ID)->toMap(),
ChangeSetItem::get_for_object($object)->first()->Object()->toMap()
);

$this->assertEquals(
ChangeSetItemTest_Versioned::get()->byID($object->ID)->toMap(),
ChangeSetItem::get_for_object_by_id($object->ID, $object->ClassName)->first()->Object()->toMap()
);
}
}
32 changes: 28 additions & 4 deletions tests/model/ChangeSetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ class ChangeSetTest_End extends DataObject implements TestOnly {
];
}

/**
* @mixin Versioned
*/
class ChangeSetTest_EndChild extends ChangeSetTest_End implements TestOnly {

private static $db = [
'Qux' => 'Int',
];
}

/**
* Test {@see ChangeSet} and {@see ChangeSetItem} models
*/
Expand All @@ -109,6 +119,7 @@ class ChangeSetTest extends SapphireTest {
'ChangeSetTest_Base',
'ChangeSetTest_Mid',
'ChangeSetTest_End',
'ChangeSetTest_EndChild',
];

/**
Expand Down Expand Up @@ -139,7 +150,7 @@ protected function assertChangeSetLooksLike($cs, $match) {
$object = $this->objFromFixture($class, $identifier);

foreach($items as $i => $item) {
if ($item->ObjectClass == $object->ClassName && $item->ObjectID == $object->ID && $item->Added == $mode) {
if ($item->ObjectClass == ClassInfo::baseDataClass($object) && $item->ObjectID == $object->ID && $item->Added == $mode) {
unset($items[$i]);
continue 2;
}
Expand All @@ -160,6 +171,19 @@ protected function assertChangeSetLooksLike($cs, $match) {
);
}
}

public function testAddObject() {
$cs = new ChangeSet();
$cs->write();

$cs->addObject($this->objFromFixture('ChangeSetTest_End', 'end1'));
$cs->addObject($this->objFromFixture('ChangeSetTest_EndChild', 'endchild1'));

$this->assertChangeSetLooksLike($cs, [
'ChangeSetTest_End.end1' => ChangeSetItem::EXPLICITLY,
'ChangeSetTest_EndChild.endchild1' => ChangeSetItem::EXPLICITLY
]);
}

public function testRepeatedSyncIsNOP() {
$this->publishAllFixtures();
Expand Down Expand Up @@ -207,10 +231,11 @@ public function testSync() {
'ChangeSetTest_End.end1' => ChangeSetItem::IMPLICITLY
]);

$endItem = $cs->Changes()->filter('ObjectClass', 'ChangeSetTest_End')->first();
$baseItem = ChangeSetItem::get_for_object($base)->first();
$endItem = ChangeSetItem::get_for_object($end)->first();

$this->assertEquals(
[$base->ID],
[$baseItem->ID],
$endItem->ReferencedBy()->column("ID")
);

Expand Down Expand Up @@ -256,7 +281,6 @@ public function testIsSynced() {
$this->assertTrue($cs->isSynced());
}


public function testCanPublish() {
// Create changeset containing all items (unpublished)
$this->logInWithPermission('ADMIN');
Expand Down
4 changes: 4 additions & 0 deletions tests/model/ChangeSetTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ ChangeSetTest_End:
Baz: 1
end2:
Baz: 2
ChangeSetTest_EndChild:
endchild1:
Baz: 3
Qux: 3
ChangeSetTest_Mid:
mid1:
Bar: 1
Expand Down

0 comments on commit 2e259d1

Please sign in to comment.