mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
0848aca462
API Implemented recursive versioned actions (publish, etc) API Un-deprecate delete batch action API Changed Versioned getters and setters for stages BUG Inject query parameters during DataObject construction to prevent incorrect lazy loading
625 lines
19 KiB
PHP
625 lines
19 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Tests ownership API of versioned DataObjects
|
|
*/
|
|
class VersionedOwnershipTest extends SapphireTest {
|
|
|
|
protected $extraDataObjects = array(
|
|
'VersionedOwnershipTest_Object',
|
|
'VersionedOwnershipTest_Subclass',
|
|
'VersionedOwnershipTest_Related',
|
|
'VersionedOwnershipTest_Attachment',
|
|
'VersionedOwnershipTest_RelatedMany',
|
|
);
|
|
|
|
protected static $fixture_file = 'VersionedOwnershipTest.yml';
|
|
|
|
public function setUp()
|
|
{
|
|
parent::setUp();
|
|
|
|
Versioned::set_stage(Versioned::DRAFT);
|
|
|
|
// Automatically publish any object named *_published
|
|
foreach($this->getFixtureFactory()->getFixtures() as $class => $fixtures) {
|
|
foreach($fixtures as $name => $id) {
|
|
if(stripos($name, '_published') !== false) {
|
|
/** @var Versioned|DataObject $object */
|
|
$object = DataObject::get($class)->byID($id);
|
|
$object->publish('Stage', 'Live');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Virtual "sleep" that doesn't actually slow execution, only advances SS_DateTime::now()
|
|
*
|
|
* @param int $minutes
|
|
*/
|
|
protected function sleep($minutes) {
|
|
$now = SS_Datetime::now();
|
|
$date = DateTime::createFromFormat('Y-m-d H:i:s', $now->getValue());
|
|
$date->modify("+{$minutes} minutes");
|
|
SS_Datetime::set_mock_now($date->format('Y-m-d H:i:s'));
|
|
}
|
|
|
|
/**
|
|
* Test basic findOwned() in stage mode
|
|
*/
|
|
public function testFindOwned() {
|
|
/** @var VersionedOwnershipTest_Subclass $subclass1 */
|
|
$subclass1 = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass1_published');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
['Title' => 'Attachment 1'],
|
|
['Title' => 'Attachment 2'],
|
|
['Title' => 'Attachment 5'],
|
|
['Title' => 'Related Many 1'],
|
|
['Title' => 'Related Many 2'],
|
|
['Title' => 'Related Many 3'],
|
|
],
|
|
$subclass1->findOwned()
|
|
);
|
|
|
|
// Non-recursive search
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
['Title' => 'Related Many 1'],
|
|
['Title' => 'Related Many 2'],
|
|
['Title' => 'Related Many 3'],
|
|
],
|
|
$subclass1->findOwned(false)
|
|
);
|
|
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2 */
|
|
$subclass2 = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass2_published');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2'],
|
|
['Title' => 'Attachment 3'],
|
|
['Title' => 'Attachment 4'],
|
|
['Title' => 'Attachment 5'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2->findOwned()
|
|
);
|
|
|
|
// Non-recursive search
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2->findOwned(false)
|
|
);
|
|
|
|
/** @var VersionedOwnershipTest_Related $related1 */
|
|
$related1 = $this->objFromFixture('VersionedOwnershipTest_Related', 'related1');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Attachment 1'],
|
|
['Title' => 'Attachment 2'],
|
|
['Title' => 'Attachment 5'],
|
|
],
|
|
$related1->findOwned()
|
|
);
|
|
|
|
/** @var VersionedOwnershipTest_Related $related2 */
|
|
$related2 = $this->objFromFixture('VersionedOwnershipTest_Related', 'related2_published');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Attachment 3'],
|
|
['Title' => 'Attachment 4'],
|
|
['Title' => 'Attachment 5'],
|
|
],
|
|
$related2->findOwned()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test findOwners
|
|
*/
|
|
public function testFindOwners() {
|
|
/** @var VersionedOwnershipTest_Attachment $attachment1 */
|
|
$attachment1 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment1');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
['Title' => 'Subclass 1'],
|
|
],
|
|
$attachment1->findOwners()
|
|
);
|
|
|
|
// Non-recursive search
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
],
|
|
$attachment1->findOwners(false)
|
|
);
|
|
|
|
/** @var VersionedOwnershipTest_Attachment $attachment5 */
|
|
$attachment5 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment5_published');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
['Title' => 'Related 2'],
|
|
['Title' => 'Subclass 1'],
|
|
['Title' => 'Subclass 2'],
|
|
],
|
|
$attachment5->findOwners()
|
|
);
|
|
|
|
// Non-recursive
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 1'],
|
|
['Title' => 'Related 2'],
|
|
],
|
|
$attachment5->findOwners(false)
|
|
);
|
|
|
|
/** @var VersionedOwnershipTest_Related $related1 */
|
|
$related1 = $this->objFromFixture('VersionedOwnershipTest_Related', 'related1');
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Subclass 1'],
|
|
],
|
|
$related1->findOwners()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test findOwners on Live stage
|
|
*/
|
|
public function testFindOwnersLive() {
|
|
// Modify a few records on stage
|
|
$related2 = $this->objFromFixture('VersionedOwnershipTest_Related', 'related2_published');
|
|
$related2->Title .= ' Modified';
|
|
$related2->write();
|
|
$attachment3 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment3_published');
|
|
$attachment3->Title .= ' Modified';
|
|
$attachment3->write();
|
|
$attachment4 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment4_published');
|
|
$attachment4->delete();
|
|
$subclass2ID = $this->idFromFixture('VersionedOwnershipTest_Subclass', 'subclass2_published');
|
|
|
|
// Check that stage record is ok
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2Stage */
|
|
$subclass2Stage = \Versioned::get_by_stage('VersionedOwnershipTest_Subclass', 'Stage')->byID($subclass2ID);
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2 Modified'],
|
|
['Title' => 'Attachment 3 Modified'],
|
|
['Title' => 'Attachment 5'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2Stage->findOwned()
|
|
);
|
|
|
|
// Non-recursive
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2 Modified'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2Stage->findOwned(false)
|
|
);
|
|
|
|
// Live records are unchanged
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2Live */
|
|
$subclass2Live = \Versioned::get_by_stage('VersionedOwnershipTest_Subclass', 'Live')->byID($subclass2ID);
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2'],
|
|
['Title' => 'Attachment 3'],
|
|
['Title' => 'Attachment 4'],
|
|
['Title' => 'Attachment 5'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2Live->findOwned()
|
|
);
|
|
|
|
// Test non-recursive
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2'],
|
|
['Title' => 'Related Many 4'],
|
|
],
|
|
$subclass2Live->findOwned(false)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test that objects are correctly published recursively
|
|
*/
|
|
public function testRecursivePublish() {
|
|
/** @var VersionedOwnershipTest_Subclass $parent */
|
|
$parent = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass1_published');
|
|
$parentID = $parent->ID;
|
|
$banner1 = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany1_published');
|
|
$banner2 = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany2_published');
|
|
$banner2ID = $banner2->ID;
|
|
|
|
// Modify, Add, and Delete banners on stage
|
|
$banner1->Title = 'Renamed Banner 1';
|
|
$banner1->write();
|
|
|
|
$banner2->delete();
|
|
|
|
$banner4 = new VersionedOwnershipTest_RelatedMany();
|
|
$banner4->Title = 'New Banner';
|
|
$parent->Banners()->add($banner4);
|
|
|
|
// Check state of objects before publish
|
|
$oldLiveBanners = [
|
|
['Title' => 'Related Many 1'],
|
|
['Title' => 'Related Many 2'], // Will be deleted
|
|
// `Related Many 3` isn't published
|
|
];
|
|
$newBanners = [
|
|
['Title' => 'Renamed Banner 1'], // Renamed
|
|
['Title' => 'Related Many 3'], // Published without changes
|
|
['Title' => 'New Banner'], // Created
|
|
];
|
|
$parentDraft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($newBanners, $parentDraft->Banners());
|
|
$parentLive = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::LIVE)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($oldLiveBanners, $parentLive->Banners());
|
|
|
|
// On publishing of owner, all children should now be updated
|
|
$parent->doPublish();
|
|
|
|
// Now check each object has the correct state
|
|
$parentDraft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($newBanners, $parentDraft->Banners());
|
|
$parentLive = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::LIVE)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($newBanners, $parentLive->Banners());
|
|
|
|
// Check that the deleted banner hasn't actually been deleted from the live stage,
|
|
// but in fact has been unlinked.
|
|
$banner2Live = Versioned::get_by_stage('VersionedOwnershipTest_RelatedMany', Versioned::LIVE)
|
|
->byID($banner2ID);
|
|
$this->assertEmpty($banner2Live->PageID);
|
|
}
|
|
|
|
/**
|
|
* Test that owning objects get unpublished as needed
|
|
*/
|
|
public function testRecursiveUnpublish() {
|
|
// Unsaved objects can't be unpublished
|
|
$unsaved = new VersionedOwnershipTest_Subclass();
|
|
$this->assertFalse($unsaved->doUnpublish());
|
|
|
|
// Draft-only objects can't be unpublished
|
|
/** @var VersionedOwnershipTest_RelatedMany $banner3Unpublished */
|
|
$banner3Unpublished = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany3');
|
|
$this->assertFalse($banner3Unpublished->doUnpublish());
|
|
|
|
// First test: mid-level unpublish; We expect that owners should be unpublished, but not
|
|
// owned objects, nor other siblings shared by the same owner.
|
|
$related2 = $this->objFromFixture('VersionedOwnershipTest_Related', 'related2_published');
|
|
/** @var VersionedOwnershipTest_Attachment $attachment3 */
|
|
$attachment3 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment3_published');
|
|
/** @var VersionedOwnershipTest_RelatedMany $relatedMany4 */
|
|
$relatedMany4 = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany4_published');
|
|
/** @var VersionedOwnershipTest_Related $related2 */
|
|
$this->assertTrue($related2->doUnpublish());
|
|
$subclass2 = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass2_published');
|
|
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2 */
|
|
$this->assertFalse($subclass2->isPublished()); // Owner IS unpublished
|
|
$this->assertTrue($attachment3->isPublished()); // Owned object is NOT unpublished
|
|
$this->assertTrue($relatedMany4->isPublished()); // Owned object by owner is NOT unpublished
|
|
|
|
// Second test: multi-level unpublish should recursively cascade down all owning objects
|
|
// Publish related2 again
|
|
$subclass2->doPublish();
|
|
$this->assertTrue($subclass2->isPublished());
|
|
$this->assertTrue($related2->isPublished());
|
|
$this->assertTrue($attachment3->isPublished());
|
|
|
|
// Unpublish leaf node
|
|
$this->assertTrue($attachment3->doUnpublish());
|
|
|
|
// Now all owning objects (only) are unpublished
|
|
$this->assertFalse($attachment3->isPublished()); // Unpublished because we just unpublished it
|
|
$this->assertFalse($related2->isPublished()); // Unpublished because it owns attachment3
|
|
$this->assertFalse($subclass2->isPublished()); // Unpublished ecause it owns related2
|
|
$this->assertTrue($relatedMany4->isPublished()); // Stays live because recursion only affects owners not owned.
|
|
}
|
|
|
|
public function testRecursiveArchive() {
|
|
// When archiving an object, any published owners should be unpublished at the same time
|
|
// but NOT achived
|
|
|
|
/** @var VersionedOwnershipTest_Attachment $attachment3 */
|
|
$attachment3 = $this->objFromFixture('VersionedOwnershipTest_Attachment', 'attachment3_published');
|
|
$attachment3ID = $attachment3->ID;
|
|
$this->assertTrue($attachment3->doArchive());
|
|
|
|
// This object is on neither stage nor live
|
|
$stageAttachment = Versioned::get_by_stage('VersionedOwnershipTest_Attachment', Versioned::DRAFT)
|
|
->byID($attachment3ID);
|
|
$liveAttachment = Versioned::get_by_stage('VersionedOwnershipTest_Attachment', Versioned::LIVE)
|
|
->byID($attachment3ID);
|
|
$this->assertEmpty($stageAttachment);
|
|
$this->assertEmpty($liveAttachment);
|
|
|
|
// Owning object is unpublished only
|
|
/** @var VersionedOwnershipTest_Related $stageOwner */
|
|
$stageOwner = $this->objFromFixture('VersionedOwnershipTest_Related', 'related2_published');
|
|
$this->assertTrue($stageOwner->isOnDraft());
|
|
$this->assertFalse($stageOwner->isPublished());
|
|
|
|
// Bottom level owning object is also unpublished
|
|
/** @var VersionedOwnershipTest_Subclass $stageTopOwner */
|
|
$stageTopOwner = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass2_published');
|
|
$this->assertTrue($stageTopOwner->isOnDraft());
|
|
$this->assertFalse($stageTopOwner->isPublished());
|
|
}
|
|
|
|
public function testRecursiveRevertToLive() {
|
|
/** @var VersionedOwnershipTest_Subclass $parent */
|
|
$parent = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass1_published');
|
|
$parentID = $parent->ID;
|
|
$banner1 = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany1_published');
|
|
$banner2 = $this->objFromFixture('VersionedOwnershipTest_RelatedMany', 'relatedmany2_published');
|
|
$banner2ID = $banner2->ID;
|
|
|
|
// Modify, Add, and Delete banners on stage
|
|
$banner1->Title = 'Renamed Banner 1';
|
|
$banner1->write();
|
|
|
|
$banner2->delete();
|
|
|
|
$banner4 = new VersionedOwnershipTest_RelatedMany();
|
|
$banner4->Title = 'New Banner';
|
|
$banner4->write();
|
|
$parent->Banners()->add($banner4);
|
|
|
|
// Check state of objects before publish
|
|
$liveBanners = [
|
|
['Title' => 'Related Many 1'],
|
|
['Title' => 'Related Many 2'],
|
|
];
|
|
$modifiedBanners = [
|
|
['Title' => 'Renamed Banner 1'], // Renamed
|
|
['Title' => 'Related Many 3'], // Published without changes
|
|
['Title' => 'New Banner'], // Created
|
|
];
|
|
$parentDraft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($modifiedBanners, $parentDraft->Banners());
|
|
$parentLive = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::LIVE)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($liveBanners, $parentLive->Banners());
|
|
|
|
// When reverting parent, all records should be put back on stage
|
|
$this->assertTrue($parent->doRevertToLive());
|
|
|
|
// Now check each object has the correct state
|
|
$parentDraft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($liveBanners, $parentDraft->Banners());
|
|
$parentLive = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::LIVE)
|
|
->byID($parentID);
|
|
$this->assertDOSEquals($liveBanners, $parentLive->Banners());
|
|
|
|
// Check that the newly created banner, even though it still exist, has been
|
|
// unlinked from the reverted draft record
|
|
/** @var VersionedOwnershipTest_RelatedMany $banner4Draft */
|
|
$banner4Draft = Versioned::get_by_stage('VersionedOwnershipTest_RelatedMany', Versioned::DRAFT)
|
|
->byID($banner4->ID);
|
|
$this->assertTrue($banner4Draft->isOnDraft());
|
|
$this->assertFalse($banner4Draft->isPublished());
|
|
$this->assertEmpty($banner4Draft->PageID);
|
|
}
|
|
|
|
/**
|
|
* Test that rolling back to a single version works recursively
|
|
*/
|
|
public function testRecursiveRollback() {
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2 */
|
|
$this->sleep(1);
|
|
$subclass2 = $this->objFromFixture('VersionedOwnershipTest_Subclass', 'subclass2_published');
|
|
|
|
// Create a few new versions
|
|
$versions = [];
|
|
for($version = 1; $version <= 3; $version++) {
|
|
// Write owned objects
|
|
$this->sleep(1);
|
|
foreach($subclass2->findOwned(true) as $obj) {
|
|
$obj->Title .= " - v{$version}";
|
|
$obj->write();
|
|
}
|
|
// Write parent
|
|
$this->sleep(1);
|
|
$subclass2->Title .= " - v{$version}";
|
|
$subclass2->write();
|
|
$versions[$version] = $subclass2->Version;
|
|
}
|
|
|
|
|
|
// Check reverting to first version
|
|
$this->sleep(1);
|
|
$subclass2->doRollbackTo($versions[1]);
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2Draft */
|
|
$subclass2Draft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($subclass2->ID);
|
|
$this->assertEquals('Subclass 2 - v1', $subclass2Draft->Title);
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2 - v1'],
|
|
['Title' => 'Attachment 3 - v1'],
|
|
['Title' => 'Attachment 4 - v1'],
|
|
['Title' => 'Attachment 5 - v1'],
|
|
['Title' => 'Related Many 4 - v1'],
|
|
],
|
|
$subclass2Draft->findOwned(true)
|
|
);
|
|
|
|
// Check rolling forward to a later version
|
|
$this->sleep(1);
|
|
$subclass2->doRollbackTo($versions[3]);
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2Draft */
|
|
$subclass2Draft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($subclass2->ID);
|
|
$this->assertEquals('Subclass 2 - v1 - v2 - v3', $subclass2Draft->Title);
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2 - v1 - v2 - v3'],
|
|
['Title' => 'Attachment 3 - v1 - v2 - v3'],
|
|
['Title' => 'Attachment 4 - v1 - v2 - v3'],
|
|
['Title' => 'Attachment 5 - v1 - v2 - v3'],
|
|
['Title' => 'Related Many 4 - v1 - v2 - v3'],
|
|
],
|
|
$subclass2Draft->findOwned(true)
|
|
);
|
|
|
|
// And rolling back one version
|
|
$this->sleep(1);
|
|
$subclass2->doRollbackTo($versions[2]);
|
|
/** @var VersionedOwnershipTest_Subclass $subclass2Draft */
|
|
$subclass2Draft = Versioned::get_by_stage('VersionedOwnershipTest_Subclass', Versioned::DRAFT)
|
|
->byID($subclass2->ID);
|
|
$this->assertEquals('Subclass 2 - v1 - v2', $subclass2Draft->Title);
|
|
$this->assertDOSEquals(
|
|
[
|
|
['Title' => 'Related 2 - v1 - v2'],
|
|
['Title' => 'Attachment 3 - v1 - v2'],
|
|
['Title' => 'Attachment 4 - v1 - v2'],
|
|
['Title' => 'Attachment 5 - v1 - v2'],
|
|
['Title' => 'Related Many 4 - v1 - v2'],
|
|
],
|
|
$subclass2Draft->findOwned(true)
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @mixin Versioned
|
|
*/
|
|
class VersionedOwnershipTest_Object extends DataObject implements TestOnly {
|
|
private static $extensions = array(
|
|
'Versioned',
|
|
);
|
|
|
|
private static $db = array(
|
|
'Title' => 'Varchar(255)',
|
|
'Content' => 'Text',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Object which:
|
|
* - owns a has_one object
|
|
* - owns has_many objects
|
|
*/
|
|
class VersionedOwnershipTest_Subclass extends VersionedOwnershipTest_Object implements TestOnly {
|
|
private static $db = array(
|
|
'Description' => 'Text',
|
|
);
|
|
|
|
private static $has_one = array(
|
|
'Related' => 'VersionedOwnershipTest_Related',
|
|
);
|
|
|
|
private static $has_many = array(
|
|
'Banners' => 'VersionedOwnershipTest_RelatedMany'
|
|
);
|
|
|
|
private static $owns = array(
|
|
'Related',
|
|
'Banners',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Object which:
|
|
* - owned by has_many objects
|
|
* - owns many_many Objects
|
|
*
|
|
* @mixin Versioned
|
|
*/
|
|
class VersionedOwnershipTest_Related extends DataObject implements TestOnly {
|
|
private static $extensions = array(
|
|
'Versioned',
|
|
);
|
|
|
|
private static $db = array(
|
|
'Title' => 'Varchar(255)',
|
|
);
|
|
|
|
private static $has_many = array(
|
|
'Parents' => 'VersionedOwnershipTest_Subclass.Related',
|
|
);
|
|
|
|
private static $owned_by = array(
|
|
'Parents',
|
|
);
|
|
|
|
private static $many_many = array(
|
|
// Note : Currently unversioned, take care
|
|
'Attachments' => 'VersionedOwnershipTest_Attachment',
|
|
);
|
|
|
|
private static $owns = array(
|
|
'Attachments',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Object which is owned by a has_one object
|
|
*
|
|
* @mixin Versioned
|
|
*/
|
|
class VersionedOwnershipTest_RelatedMany extends DataObject implements TestOnly {
|
|
private static $extensions = array(
|
|
'Versioned',
|
|
);
|
|
|
|
private static $db = array(
|
|
'Title' => 'Varchar(255)',
|
|
);
|
|
|
|
private static $has_one = array(
|
|
'Page' => 'VersionedOwnershipTest_Subclass'
|
|
);
|
|
|
|
private static $owned_by = array(
|
|
'Page'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @mixin Versioned
|
|
*/
|
|
class VersionedOwnershipTest_Attachment extends DataObject implements TestOnly {
|
|
|
|
private static $extensions = array(
|
|
'Versioned',
|
|
);
|
|
|
|
private static $db = array(
|
|
'Title' => 'Varchar(255)',
|
|
);
|
|
|
|
private static $belongs_many_many = array(
|
|
'AttachedTo' => 'VersionedOwnershipTest_Related.Attachments'
|
|
);
|
|
|
|
private static $owned_by = array(
|
|
'AttachedTo'
|
|
);
|
|
}
|