2007-08-15 08:38:41 +02:00
|
|
|
<?php
|
2008-02-25 03:10:37 +01:00
|
|
|
/**
|
2008-06-15 15:33:53 +02:00
|
|
|
* @package sapphire
|
|
|
|
* @subpackage tests
|
2008-02-25 03:10:37 +01:00
|
|
|
*/
|
2007-08-15 08:38:41 +02:00
|
|
|
class SiteTreeTest extends SapphireTest {
|
|
|
|
static $fixture_file = 'sapphire/tests/SiteTreeTest.yml';
|
2009-05-25 08:59:21 +02:00
|
|
|
|
2007-08-15 08:38:41 +02:00
|
|
|
/**
|
|
|
|
* Test generation of the URLSegment values.
|
|
|
|
* - Turns things into lowercase-hyphen-format
|
|
|
|
* - Generates from Title by default, unless URLSegment is explicitly set
|
|
|
|
* - Resolves duplicates by appending a number
|
2008-10-30 22:51:59 +01:00
|
|
|
* - renames classes with a class name conflict
|
2007-08-15 08:38:41 +02:00
|
|
|
*/
|
|
|
|
function testURLGeneration() {
|
|
|
|
$expectedURLs = array(
|
|
|
|
'home' => 'home',
|
|
|
|
'staff' => 'my-staff',
|
|
|
|
'about' => 'about-us',
|
|
|
|
'staffduplicate' => 'my-staff-2',
|
|
|
|
'product1' => '1-1-test-product',
|
|
|
|
'product2' => 'another-product',
|
|
|
|
'product3' => 'another-product-2',
|
|
|
|
'product4' => 'another-product-3',
|
2008-10-30 22:51:59 +01:00
|
|
|
'object' => 'object',
|
2009-05-14 08:58:23 +02:00
|
|
|
'controller' => 'controller-2',
|
|
|
|
'numericonly' => '1930',
|
2007-08-15 08:38:41 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
foreach($expectedURLs as $fixture => $urlSegment) {
|
2009-07-08 02:06:16 +02:00
|
|
|
$obj = $this->objFromFixture('Page', $fixture);
|
2007-08-15 08:38:41 +02:00
|
|
|
$this->assertEquals($urlSegment, $obj->URLSegment);
|
|
|
|
}
|
|
|
|
}
|
2007-08-16 08:36:39 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that publication copies data to SiteTree_Live
|
|
|
|
*/
|
|
|
|
function testPublishCopiesToLiveTable() {
|
2009-07-08 02:06:16 +02:00
|
|
|
$obj = $this->objFromFixture('Page','about');
|
2007-08-16 08:36:39 +02:00
|
|
|
$obj->publish('Stage', 'Live');
|
|
|
|
|
2008-11-24 10:31:14 +01:00
|
|
|
$createdID = DB::query("SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"URLSegment\" = '$obj->URLSegment'")->value();
|
2007-08-16 08:36:39 +02:00
|
|
|
$this->assertEquals($obj->ID, $createdID);
|
|
|
|
}
|
|
|
|
|
2009-07-03 03:21:48 +02:00
|
|
|
/**
|
|
|
|
* Test that field which are set and then cleared are also transferred to the published site.
|
|
|
|
*/
|
|
|
|
function testPublishDeletedFields() {
|
2009-07-08 02:06:16 +02:00
|
|
|
$obj = $this->objFromFixture('Page', 'about');
|
2009-07-03 03:21:48 +02:00
|
|
|
$obj->MetaTitle = "asdfasdf";
|
|
|
|
$obj->write();
|
|
|
|
$obj->doPublish();
|
|
|
|
|
|
|
|
$this->assertEquals('asdfasdf', DB::query("SELECT \"MetaTitle\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value());
|
|
|
|
|
|
|
|
$obj->MetaTitle = null;
|
|
|
|
$obj->write();
|
|
|
|
$obj->doPublish();
|
|
|
|
|
|
|
|
$this->assertNull(DB::query("SELECT \"MetaTitle\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-07-14 13:09:44 +02:00
|
|
|
function testParentNodeCachedInMemory() {
|
|
|
|
$parent = new SiteTree();
|
|
|
|
$parent->Title = 'Section Title';
|
|
|
|
$child = new SiteTree();
|
|
|
|
$child->Title = 'Page Title';
|
|
|
|
$child->setParent($parent);
|
|
|
|
|
|
|
|
$this->assertType("SiteTree", $child->Parent);
|
|
|
|
$this->assertEquals("Section Title", $child->Parent->Title);
|
|
|
|
}
|
2007-08-16 08:36:39 +02:00
|
|
|
|
2008-07-14 13:09:44 +02:00
|
|
|
function testParentModelReturnType() {
|
2008-07-16 05:30:29 +02:00
|
|
|
$parent = new SiteTreeTest_PageNode();
|
|
|
|
$child = new SiteTreeTest_PageNode();
|
2008-07-14 13:09:44 +02:00
|
|
|
|
|
|
|
$child->setParent($parent);
|
2008-07-16 05:30:29 +02:00
|
|
|
$this->assertType('SiteTreeTest_PageNode', $child->Parent);
|
2008-07-14 13:09:44 +02:00
|
|
|
}
|
2007-08-16 08:36:39 +02:00
|
|
|
|
2008-08-11 05:42:59 +02:00
|
|
|
/**
|
|
|
|
* Confirm that DataObject::get_one() gets records from SiteTree_Live
|
|
|
|
*/
|
|
|
|
function testGetOneFromLive() {
|
|
|
|
$s = new SiteTree();
|
|
|
|
$s->Title = "V1";
|
|
|
|
$s->URLSegment = "get-one-test-page";
|
|
|
|
$s->write();
|
|
|
|
$s->publish("Stage", "Live");
|
|
|
|
$s->Title = "V2";
|
|
|
|
$s->write();
|
|
|
|
|
|
|
|
$oldStage = Versioned::current_stage();
|
|
|
|
Versioned::reading_stage('Live');
|
|
|
|
|
2008-11-24 10:31:14 +01:00
|
|
|
$checkSiteTree = DataObject::get_one("SiteTree", "\"URLSegment\" = 'get-one-test-page'");
|
2008-08-11 05:42:59 +02:00
|
|
|
$this->assertEquals("V1", $checkSiteTree->Title);
|
2009-05-25 08:59:21 +02:00
|
|
|
|
|
|
|
Versioned::reading_stage($oldStage);
|
2008-08-11 05:42:59 +02:00
|
|
|
}
|
|
|
|
|
2008-08-12 01:51:45 +02:00
|
|
|
function testChidrenOfRootAreTopLevelPages() {
|
|
|
|
$pages = DataObject::get("SiteTree");
|
|
|
|
foreach($pages as $page) $page->publish('Stage', 'Live');
|
|
|
|
unset($pages);
|
|
|
|
|
|
|
|
/* If we create a new SiteTree object with ID = 0 */
|
|
|
|
$obj = new SiteTree();
|
|
|
|
/* Then its children should be the top-level pages */
|
|
|
|
$stageChildren = $obj->stageChildren()->toDropDownMap('ID','Title');
|
|
|
|
$liveChildren = $obj->liveChildren()->toDropDownMap('ID','Title');
|
|
|
|
$allChildren = $obj->AllChildrenIncludingDeleted()->toDropDownMap('ID','Title');
|
|
|
|
|
|
|
|
$this->assertContains('Home', $stageChildren);
|
|
|
|
$this->assertContains('Products', $stageChildren);
|
|
|
|
$this->assertNotContains('Staff', $stageChildren);
|
|
|
|
|
|
|
|
$this->assertContains('Home', $liveChildren);
|
|
|
|
$this->assertContains('Products', $liveChildren);
|
|
|
|
$this->assertNotContains('Staff', $liveChildren);
|
|
|
|
|
|
|
|
$this->assertContains('Home', $allChildren);
|
|
|
|
$this->assertContains('Products', $allChildren);
|
|
|
|
$this->assertNotContains('Staff', $allChildren);
|
|
|
|
}
|
2008-08-15 05:08:03 +02:00
|
|
|
|
|
|
|
function testCanSaveBlankToHasOneRelations() {
|
|
|
|
/* DataObject::write() should save to a has_one relationship if you set a field called (relname)ID */
|
|
|
|
$page = new SiteTree();
|
|
|
|
$parentID = $this->idFromFixture('Page', 'home');
|
|
|
|
$page->ParentID = $parentID;
|
|
|
|
$page->write();
|
2008-11-24 10:31:14 +01:00
|
|
|
$this->assertEquals($parentID, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value());
|
2008-08-15 05:08:03 +02:00
|
|
|
|
|
|
|
/* You should then be able to save a null/0/'' value to the relation */
|
|
|
|
$page->ParentID = null;
|
|
|
|
$page->write();
|
2008-11-24 10:31:14 +01:00
|
|
|
$this->assertEquals(0, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value());
|
2008-08-15 05:08:03 +02:00
|
|
|
}
|
2008-08-11 05:42:59 +02:00
|
|
|
|
2008-12-17 23:41:07 +01:00
|
|
|
function testStageStates() {
|
|
|
|
// newly created page
|
|
|
|
$createdPage = new SiteTree();
|
|
|
|
$createdPage->write();
|
|
|
|
$this->assertFalse($createdPage->IsDeletedFromStage);
|
|
|
|
$this->assertTrue($createdPage->IsAddedToStage);
|
|
|
|
$this->assertTrue($createdPage->IsModifiedOnStage);
|
|
|
|
|
|
|
|
// published page
|
|
|
|
$publishedPage = new SiteTree();
|
|
|
|
$publishedPage->write();
|
|
|
|
$publishedPage->publish('Stage','Live');
|
|
|
|
$this->assertFalse($publishedPage->IsDeletedFromStage);
|
|
|
|
$this->assertFalse($publishedPage->IsAddedToStage);
|
|
|
|
$this->assertFalse($publishedPage->IsModifiedOnStage);
|
|
|
|
|
|
|
|
// published page, deleted from stage
|
|
|
|
$deletedFromDraftPage = new SiteTree();
|
|
|
|
$deletedFromDraftPage->write();
|
|
|
|
$deletedFromDraftPageID = $deletedFromDraftPage->ID;
|
|
|
|
$deletedFromDraftPage->publish('Stage','Live');
|
|
|
|
$deletedFromDraftPage->deleteFromStage('Stage');
|
|
|
|
$this->assertTrue($deletedFromDraftPage->IsDeletedFromStage);
|
|
|
|
$this->assertFalse($deletedFromDraftPage->IsAddedToStage);
|
|
|
|
$this->assertFalse($deletedFromDraftPage->IsModifiedOnStage);
|
|
|
|
|
|
|
|
// published page, deleted from live
|
|
|
|
$deletedFromLivePage = new SiteTree();
|
|
|
|
$deletedFromLivePage->write();
|
|
|
|
$deletedFromLivePage->publish('Stage','Live');
|
|
|
|
$deletedFromLivePage->deleteFromStage('Stage');
|
|
|
|
$deletedFromLivePage->deleteFromStage('Live');
|
|
|
|
$this->assertTrue($deletedFromLivePage->IsDeletedFromStage);
|
|
|
|
$this->assertFalse($deletedFromLivePage->IsAddedToStage);
|
|
|
|
$this->assertFalse($deletedFromLivePage->IsModifiedOnStage);
|
|
|
|
|
|
|
|
// published page, modified
|
|
|
|
$modifiedOnDraftPage = new SiteTree();
|
|
|
|
$modifiedOnDraftPage->write();
|
|
|
|
$modifiedOnDraftPage->publish('Stage','Live');
|
|
|
|
$modifiedOnDraftPage->Content = 'modified';
|
|
|
|
$modifiedOnDraftPage->write();
|
|
|
|
$this->assertFalse($modifiedOnDraftPage->IsDeletedFromStage);
|
|
|
|
$this->assertFalse($modifiedOnDraftPage->IsAddedToStage);
|
|
|
|
$this->assertTrue($modifiedOnDraftPage->IsModifiedOnStage);
|
|
|
|
}
|
2009-05-01 05:49:34 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that a page can be completely deleted and restored to the stage site
|
|
|
|
*/
|
|
|
|
function testRestoreToStage() {
|
|
|
|
$page = $this->objFromFixture('Page', 'about');
|
|
|
|
$pageID = $page->ID;
|
|
|
|
$page->delete();
|
|
|
|
$this->assertTrue(!DataObject::get_by_id("Page", $pageID));
|
|
|
|
|
|
|
|
$deletedPage = Versioned::get_latest_version('SiteTree', $pageID);
|
|
|
|
$resultPage = $deletedPage->doRestoreToStage();
|
|
|
|
|
|
|
|
$requeriedPage = DataObject::get_by_id("Page", $pageID);
|
|
|
|
|
|
|
|
$this->assertEquals($pageID, $resultPage->ID);
|
|
|
|
$this->assertEquals($pageID, $requeriedPage->ID);
|
|
|
|
$this->assertEquals('About Us', $requeriedPage->Title);
|
|
|
|
$this->assertEquals('Page', $requeriedPage->class);
|
|
|
|
|
|
|
|
|
2009-05-25 08:59:21 +02:00
|
|
|
$page2 = $this->objFromFixture('Page', 'products');
|
2009-05-01 05:49:34 +02:00
|
|
|
$page2ID = $page2->ID;
|
|
|
|
$page2->doUnpublish();
|
|
|
|
$page2->delete();
|
|
|
|
|
|
|
|
// Check that if we restore while on the live site that the content still gets pushed to
|
|
|
|
// stage
|
|
|
|
Versioned::reading_stage('Live');
|
|
|
|
$deletedPage = Versioned::get_latest_version('SiteTree', $page2ID);
|
|
|
|
$deletedPage->doRestoreToStage();
|
2009-05-07 08:00:50 +02:00
|
|
|
$this->assertTrue(!Versioned::get_one_by_stage("Page", "Live", "\"SiteTree\".ID = " . $page2ID));
|
2009-05-01 05:49:34 +02:00
|
|
|
|
|
|
|
Versioned::reading_stage('Stage');
|
|
|
|
$requeriedPage = DataObject::get_by_id("Page", $page2ID);
|
2009-05-25 08:59:21 +02:00
|
|
|
$this->assertEquals('Products', $requeriedPage->Title);
|
2009-05-01 05:49:34 +02:00
|
|
|
$this->assertEquals('Page', $requeriedPage->class);
|
|
|
|
|
|
|
|
}
|
2009-05-06 08:36:16 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test SiteTree::get_by_url()
|
|
|
|
*/
|
|
|
|
function testGetByURL() {
|
|
|
|
// Test basic get by url
|
|
|
|
$this->assertEquals($this->idFromFixture('Page', 'home'), SiteTree::get_by_url("home")->ID);
|
|
|
|
|
|
|
|
// Test the extraFilter argument
|
|
|
|
// Note: One day, it would be more appropriate to return null instead of false for queries such as these
|
|
|
|
$this->assertFalse(SiteTree::get_by_url("home", "1 = 2"));
|
|
|
|
}
|
2009-05-25 08:59:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
function testDeleteFromStageOperatesRecursively() {
|
2009-07-08 06:06:23 +02:00
|
|
|
$pageAbout = $this->objFromFixture('Page', 'about');
|
|
|
|
$pageStaff = $this->objFromFixture('Page', 'staff');
|
|
|
|
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
|
|
|
|
|
|
|
$pageAbout->delete();
|
2009-05-25 08:59:21 +02:00
|
|
|
|
2009-07-08 06:06:23 +02:00
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageAbout->ID));
|
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageStaff->ID));
|
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageStaffDuplicate->ID));
|
2009-05-25 08:59:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function testDeleteFromLiveOperatesRecursively() {
|
2009-07-08 06:06:23 +02:00
|
|
|
$pageAbout = $this->objFromFixture('Page', 'about');
|
|
|
|
$pageAbout->doPublish();
|
|
|
|
$pageStaff = $this->objFromFixture('Page', 'staff');
|
|
|
|
$pageStaff->doPublish();
|
|
|
|
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
|
|
|
$pageStaffDuplicate->doPublish();
|
2009-05-25 08:59:21 +02:00
|
|
|
|
|
|
|
$parentPage = $this->objFromFixture('Page', 'about');
|
|
|
|
$parentPage->doDeleteFromLive();
|
|
|
|
|
|
|
|
Versioned::reading_stage('Live');
|
2009-07-08 06:06:23 +02:00
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageAbout->ID));
|
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageStaff->ID));
|
|
|
|
$this->assertFalse(DataObject::get_by_id('Page', $pageStaffDuplicate->ID));
|
2009-05-25 08:59:21 +02:00
|
|
|
Versioned::reading_stage('Stage');
|
|
|
|
}
|
2009-07-31 07:43:41 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Simple test to confirm that querying from a particular archive date doesn't throw
|
|
|
|
* an error
|
|
|
|
*/
|
|
|
|
function testReadArchiveDate() {
|
2009-08-10 06:35:50 +02:00
|
|
|
Versioned::reading_archived_date('2009-07-02 14:05:07');
|
2009-07-31 07:43:41 +02:00
|
|
|
|
|
|
|
DataObject::get('SiteTree', 'ParentID = 0');
|
|
|
|
|
|
|
|
Versioned::reading_archived_date(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testEditPermissions() {
|
|
|
|
$editor = $this->objFromFixture("Member", "editor");
|
|
|
|
|
|
|
|
$home = $this->objFromFixture("Page", "home");
|
|
|
|
$products = $this->objFromFixture("Page", "products");
|
|
|
|
$product1 = $this->objFromFixture("Page", "product1");
|
|
|
|
$product4 = $this->objFromFixture("Page", "product4");
|
|
|
|
|
|
|
|
// Can't edit a page that is locked to admins
|
|
|
|
$this->assertFalse($home->canEdit($editor));
|
|
|
|
|
|
|
|
// Can edit a page that is locked to editors
|
|
|
|
$this->assertTrue($products->canEdit($editor));
|
|
|
|
|
|
|
|
// Can edit a child of that page that inherits
|
|
|
|
$this->assertTrue($product1->canEdit($editor));
|
|
|
|
|
|
|
|
// Can't edit a child of that page that has its permissions overridden
|
|
|
|
$this->assertFalse($product4->canEdit($editor));
|
|
|
|
}
|
2009-05-06 08:36:16 +02:00
|
|
|
|
2008-07-14 13:09:44 +02:00
|
|
|
}
|
|
|
|
|
2008-10-08 05:36:12 +02:00
|
|
|
// We make these extend page since that's what all page types are expected to do
|
|
|
|
class SiteTreeTest_PageNode extends Page implements TestOnly { }
|
|
|
|
class SiteTreeTest_PageNode_Controller extends Page_Controller implements TestOnly {
|
|
|
|
}
|
2008-07-14 13:09:44 +02:00
|
|
|
|
|
|
|
?>
|