public function testVersionedSiteTreeDeleteWithImageTracking() {
		// Assume that file tracking works. (If it does not, other
		// tests will fail as well.)
		$file = new File();
		$file->Filename = 'test-file.pdf';
		$file->write();
		$fileID = $file->ID;
		
		$page = new Page();
		$page->Title = 'Page';
		$page->Content = '<a href="assets/test-file.pdf">File</a>';
		$page->write();
		$page->doPublish();
		$pageID = $page->ID;
		
		$page->deleteFromStage('Live');
		$page = DataObject::get_by_id('Page', $pageID);
		$page->delete();
		
		$this->assertFalse((bool)DB::query("SELECT \"ID\" FROM \"SiteTree_ImageTracking\" WHERE \"SiteTreeID\" = {$pageID}")->value(),
			"many_many table SiteTree_ImageTracking not cleaned properly");
	}
 function testCmsActionsLimited()
 {
     // For 2.3 and 2.4 compatibility
     $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`";
     $custompublisherspage = $this->objFromFixture('SiteTree', 'custompublisherpage');
     $custompublishersgroup = $this->objFromFixture('Group', 'custompublishergroup');
     $custompublisher = $this->objFromFixture('Member', 'custompublisher');
     $workflowadmin = $this->objFromFixture('Member', 'workflowadmin');
     $custompublisher->Groups()->add($custompublishersgroup);
     $customauthorsgroup = $this->objFromFixture('Group', 'customauthorsgroup');
     $customauthor = $this->objFromFixture('Member', 'customauthor');
     $customauthor->Groups()->add($customauthorsgroup);
     $unpublishedRecord = new Page();
     $unpublishedRecord->CanEditType = 'LoggedInUsers';
     $unpublishedRecord->write();
     $unpublishedRecord->PublisherGroups()->add($custompublishersgroup);
     $custompublisher->logIn();
     $publishedRecord = new Page();
     $publishedRecord->CanEditType = 'LoggedInUsers';
     $publishedRecord->write();
     $publishedRecord->doPublish();
     $publishedRecord->PublisherGroups()->add($custompublishersgroup);
     $deletedFromLiveRecord = new Page();
     $deletedFromLiveRecord->CanEditType = 'LoggedInUsers';
     $deletedFromLiveRecord->write();
     $deletedFromLiveRecord->doPublish();
     $deletedFromLiveRecord->deleteFromStage('Live');
     $deletedFromLiveRecord->PublisherGroups()->add($custompublishersgroup);
     $deletedFromStageRecord = new Page();
     $deletedFromStageRecord->CanEditType = 'LoggedInUsers';
     $deletedFromStageRecord->write();
     $deletedFromStageRecord->PublisherGroups()->add($custompublishersgroup);
     $deletedFromStageRecord->doPublish();
     $deletedFromStageRecordID = $deletedFromStageRecord->ID;
     $deletedFromStageRecord->deleteFromStage('Stage');
     $deletedFromStageRecord = Versioned::get_one_by_stage("SiteTree", "Live", "{$bt}SiteTree{$bt}.{$bt}ID{$bt} = {$deletedFromStageRecordID}");
     $changedOnStageRecord = new Page();
     $changedOnStageRecord->CanEditType = 'LoggedInUsers';
     $changedOnStageRecord->write();
     $changedOnStageRecord->publish('Stage', 'Live');
     $changedOnStageRecord->Content = 'Changed on Stage';
     $changedOnStageRecord->write();
     $changedOnStageRecord->PublisherGroups()->add($custompublishersgroup);
     // test "publish" action for author
     $this->session()->inst_set('loggedInAs', $customauthor->ID);
     $this->assertNotContains('action_publish', $unpublishedRecord->getCMSActions()->column('Name'), 'Author cant trigger publish button');
     $this->assertNotContains('action_publish', $publishedRecord->getCMSActions()->column('Name'), 'Author cant trigger publish button');
     $this->assertNotContains('action_publish', $deletedFromLiveRecord->getCMSActions()->column('Name'), 'Author cant trigger publish button');
     $this->assertNotContains('action_publish', $changedOnStageRecord->getCMSActions()->column('Name'), 'Author cant trigger publish button');
     // test "publish" action for publisher
     $this->session()->inst_set('loggedInAs', $custompublisher->ID);
     WorkflowRequest::set_force_publishers_to_use_workflow(false);
     $this->assertContains('action_publish', $unpublishedRecord->getCMSActions()->column('Name'), 'Publisher cant trigger publish button');
     $this->assertContains('action_publish', $publishedRecord->getCMSActions()->column('Name'), 'Publisher cant trigger publish button');
     $this->assertContains('action_publish', $changedOnStageRecord->getCMSActions()->column('Name'), 'Publisher cant trigger publish button');
     WorkflowRequest::set_force_publishers_to_use_workflow(true);
     $this->assertFalse(in_array('action_publish', $unpublishedRecord->getCMSActions()->column('Name')), 'Publisher can trigger publish button even when forced to use workflow');
     $this->assertFalse(in_array('action_publish', $publishedRecord->getCMSActions()->column('Name')), 'Publisher can trigger publish button even when forced to use workflow');
     $this->assertFalse(in_array('action_publish', $changedOnStageRecord->getCMSActions()->column('Name')), 'Publisher can trigger publish button even when forced to use workflow');
     // test "request publication" action for author
     $this->session()->inst_set('loggedInAs', $customauthor->ID);
     $this->assertContains('action_cms_requestpublication', $unpublishedRecord->getCMSActions()->column('Name'), 'Author can trigger request publication button if page is not published');
     $this->assertNotContains('action_cms_requestpublication', $publishedRecord->getCMSActions()->column('Name'), 'Author cant trigger request publication button if page has been published but not altered on stage');
     $this->assertContains('action_cms_requestpublication', $changedOnStageRecord->getCMSActions()->column('Name'), 'Author can trigger request publication button if page has been changed on stage');
     // test "request removal" action for author
     $this->session()->inst_set('loggedInAs', $customauthor->ID);
     $this->assertNotContains('action_cms_requestdeletefromlive', $unpublishedRecord->getCMSActions()->column('Name'), 'Author cant trigger request removal button if page hasnt been altered');
     $this->assertNotContains('action_cms_requestdeletefromlive', $publishedRecord->getCMSActions()->column('Name'), 'Author cant trigger request removal button if page has been published but not altered on stage');
     $this->assertNotContains('action_cms_requestdeletefromlive', $changedOnStageRecord->getCMSActions()->column('Name'), 'Author cant trigger request removal button if page has been changed on stage but not deleted from stage');
     // test "request removal" action for publisher
     $this->session()->inst_set('loggedInAs', $custompublisher->ID);
     // reset login
     $this->session()->inst_set('loggedInAs', null);
 }
	function testActionsDeletedFromStageRecord() {
		if(class_exists('SiteTreeCMSWorkflow')) return true;

		$author = $this->objFromFixture('Member', 'cmseditor');
		$this->session()->inst_set('loggedInAs', $author->ID);
		
		$page = new Page();
		$page->CanEditType = 'LoggedInUsers';
		$page->write();
		$pageID = $page->ID;
		$page->doPublish();
		$page->deleteFromStage('Stage');
		
		// Get the live version of the page
		$page = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $pageID");
		$this->assertType('SiteTree', $page);
		
		$actions = $page->getCMSActions();
		
		$this->assertNull($actions->dataFieldByName('action_save'));
		$this->assertNull($actions->dataFieldByName('action_publish'));
		$this->assertNull($actions->dataFieldByName('action_unpublish'));
		$this->assertNull($actions->dataFieldByName('action_delete'));
		$this->assertNotNull($actions->dataFieldByName('action_deletefromlive'));
		$this->assertNull($actions->dataFieldByName('action_rollback'));
		$this->assertNotNull($actions->dataFieldByName('action_revert'));
	}
	public function testWithOrphanedManyManyRelations() {
		DataObjectOnDeleteDecorator::set_disabled(true);
		//JanitorDebug::set_verbose(true);
		
		$page1 = new Page();
		$page1->write();
		$page1->doPublish();
		$page1ID = $page1->ID;
		
		$page2 = new Page();
		$page2->Content .= "<p><a href=\"[sitetree_link id={$page1->ID}]\">page1 link</a></p>";
		$page2->write();
		$page2->doPublish();
		$page2ID = $page2->ID;
		
		$query = "SELECT \"ID\" FROM \"SiteTree_LinkTracking\" WHERE \"SiteTreeID\" = $page2ID AND \"ChildID\" = $page1ID";
		
		$page2->deleteFromStage('Live');
		$page2 = DataObject::get_by_id('Page', $page2ID);
		$page2->delete();
		
		$this->assertTrue((bool)DB::query($query)->value(),
			"many_many table SiteTree_LinkTracking cleaned prematurely (possibly due to SilverStripe core changes)");
		
		DataObjectOnDeleteDecorator::set_disabled(false);
		$task = new DataObjectRetroactiveCleanerTask();
		$task->run(null);
		$task->deleteBackup();
		
		$this->assertFalse((bool)DB::query($query)->value(),
			"many_many table SiteTree_LinkTracking not cleaned properly (retroactively)");
		JanitorDebug::set_verbose(false);
	}