ENHANCEMENT Removed object state setting in CMSMain/SiteTree publication process: DeletedFromStage, CheckedPublicationDifferences, IsAddedToStage and added getters for them. Improves testability as we don't have to rely on random methods like MenuTitle() being called to set object state.

ENHANCEMENT Flushing cache in SiteTree->onAfterWrite() and SiteTree->onAfterDelete() to ensure the publication state is up to date


git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@69410 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-12-17 22:41:07 +00:00
parent bc430a96df
commit 40215a9937
3 changed files with 115 additions and 44 deletions

View File

@ -435,16 +435,6 @@ class Hierarchy extends DataObjectDecorator {
// First, go through the stage children. They will all be listed but may be different colours // First, go through the stage children. They will all be listed but may be different colours
if($stageChildren) { if($stageChildren) {
foreach($stageChildren as $child) { foreach($stageChildren as $child) {
// Not found on live = new page
if(!isset($idxFoundInLive[$child->ID])) {
$child->AddedToStage = true;
// Version different on live = edited page
} else if($idxFoundInLive[$child->ID]->Version != $child->Version) {
$child->ModifiedOnStage = true;
}
$child->CheckedPublicationDifferences = true;
$this->allChildrenIncludingDeleted->push($child); $this->allChildrenIncludingDeleted->push($child);
} }
} }
@ -454,8 +444,6 @@ class Hierarchy extends DataObjectDecorator {
foreach($liveChildren as $child) { foreach($liveChildren as $child) {
// Not found on stage = deleted page. Anything else is ignored // Not found on stage = deleted page. Anything else is ignored
if(!isset($idxFoundInStage[$child->ID])) { if(!isset($idxFoundInStage[$child->ID])) {
$child->DeletedFromStage = true;
$child->CheckedPublicationDifferences = true;
$this->allChildrenIncludingDeleted->push($child); $this->allChildrenIncludingDeleted->push($child);
} }
} }

View File

@ -305,7 +305,6 @@ class SiteTree extends DataObject implements PermissionProvider {
*/ */
public function duplicate($doWrite = true) { public function duplicate($doWrite = true) {
$page = parent::duplicate($doWrite); $page = parent::duplicate($doWrite);
$page->CheckedPublicationDifferences = $page->AddedToStage = true;
return $page; return $page;
} }
@ -989,7 +988,19 @@ class SiteTree extends DataObject implements PermissionProvider {
parent::onBeforeWrite(); parent::onBeforeWrite();
} }
function onAfterWrite() {
// Need to flush cache to avoid outdated versionnumber references
$this->flushCache();
parent::onAfterWrite();
}
function onAfterDelete() {
// Need to flush cache to avoid outdated versionnumber references
$this->flushCache();
parent::onAfterDelete();
}
/** /**
@ -1278,7 +1289,7 @@ class SiteTree extends DataObject implements PermissionProvider {
function getCMSActions() { function getCMSActions() {
$actions = new FieldSet(); $actions = new FieldSet();
if($this->isPublished() && $this->canPublish()) { if($this->isPublished() && $this->canPublish() && !$this->IsDeletedFromStage) {
// "unpublish" // "unpublish"
$unpublish = FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete'); $unpublish = FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete');
$unpublish->describe(_t('SiteTree.BUTTONUNPUBLISHDESC', "Remove this page from the published site")); $unpublish->describe(_t('SiteTree.BUTTONUNPUBLISHDESC', "Remove this page from the published site"));
@ -1286,7 +1297,7 @@ class SiteTree extends DataObject implements PermissionProvider {
$actions->push($unpublish); $actions->push($unpublish);
} }
if($this->stagesDiffer('Stage', 'Live')) { if($this->stagesDiffer('Stage', 'Live') && !$this->IsDeletedFromStage) {
if($this->isPublished() && $this->canEdit()) { if($this->isPublished() && $this->canEdit()) {
// "rollback" // "rollback"
$rollback = FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete'); $rollback = FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'), 'delete');
@ -1296,7 +1307,7 @@ class SiteTree extends DataObject implements PermissionProvider {
} }
} }
if($this->DeletedFromStage) { if($this->IsDeletedFromStage) {
if($this->can('CMSEdit')) { if($this->can('CMSEdit')) {
// "restore" // "restore"
$actions->push(new FormAction('revert',_t('CMSMain.RESTORE','Restore'))); $actions->push(new FormAction('revert',_t('CMSMain.RESTORE','Restore')));
@ -1315,7 +1326,7 @@ class SiteTree extends DataObject implements PermissionProvider {
} }
} }
if($this->canPublish()) { if($this->canPublish() && !$this->IsDeletedFromStage) {
// "publish" // "publish"
$actions->push(new FormAction('publish', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save and Publish'))); $actions->push(new FormAction('publish', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save and Publish')));
} }
@ -1599,34 +1610,17 @@ class SiteTree extends DataObject implements PermissionProvider {
* @return string * @return string
*/ */
function TreeTitle() { function TreeTitle() {
// If somthing if($this->IsDeletedFromStage) {
if(!$this->CheckedPublicationDifferences && $this->ID) { $tag ="del title=\"" . _t('SiteTree.REMOVEDFROMDRAFT', 'Removed from draft site') . "\"";
$stageVersion = } elseif($this->IsAddedToStage) {
DB::query("SELECT \"Version\" FROM \"SiteTree\" WHERE \"ID\" = $this->ID")->value(); $tag = "ins title=\"" . _t('SiteTree.ADDEDTODRAFT', 'Added to draft site') . "\"";
$liveVersion = } elseif($this->IsModifiedOnStage) {
DB::query("SELECT \"Version\" FROM \"SiteTree_Live\" WHERE \"ID\" = $this->ID")->value(); $tag = "span title=\"" . _t('SiteTree.MODIFIEDONDRAFT', 'Modified on draft site') . "\" class=\"modified\"";
if($stageVersion && !$liveVersion)
$this->AddedToStage = true;
else if(!$stageVersion && $liveVersion)
$this->DeletedFromStage = true;
else if($stageVersion != $liveVersion)
$this->ModifiedOnStage = true;
}
$tag =
($this->DeletedFromStage ?
"del title=\"" . _t('SiteTree.REMOVEDFROMDRAFT', 'Removed from draft site') . "\"" :
($this->AddedToStage ?
"ins title=\"" . _t('SiteTree.ADDEDTODRAFT', 'Added to draft site') . "\"" :
($this->ModifiedOnStage ?
"span title=\"" . _t('SiteTree.MODIFIEDONDRAFT', 'Modified on draft site') . "\" class=\"modified\"" : "")));
if($tag) {
return "<$tag>" . $this->MenuTitle . "</" . strtok($tag,' ') . ">";
} else { } else {
return $this->MenuTitle; $tag = '';
} }
return ($tag) ? "<$tag>" . $this->MenuTitle . "</" . strtok($tag,' ') . ">" : $this->MenuTitle;
} }
/** /**
@ -1675,6 +1669,50 @@ class SiteTree extends DataObject implements PermissionProvider {
return $classes; return $classes;
} }
/**
* Compares current draft with live version,
* and returns TRUE if no draft version of this page exists,
* but the page is still published (after triggering "Delete from draft site" in the CMS).
*
* @return boolean
*/
function getIsDeletedFromStage() {
if(!$this->ID) return true;
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->ID);
return (!$stageVersion && $liveVersion);
}
/**
* Compares current draft with live version,
* and returns TRUE if these versions differ,
* meaning there have been unpublished changes to the draft site.
*
* @return boolean
*/
public function getIsModifiedOnStage() {
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->ID);
return ($stageVersion != $liveVersion);
}
/**
* Compares current draft with live version,
* and returns true if no live version exists,
* meaning the page was never published.
*
* @return boolean
*/
public function getIsAddedToStage() {
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->ID);
return ($stageVersion && !$liveVersion);
}
/** /**
* Stops extendCMSFields() being called on getCMSFields(). * Stops extendCMSFields() being called on getCMSFields().
* This is useful when you need access to fields added by subclasses * This is useful when you need access to fields added by subclasses

View File

@ -6,7 +6,6 @@
class SiteTreeTest extends SapphireTest { class SiteTreeTest extends SapphireTest {
static $fixture_file = 'sapphire/tests/SiteTreeTest.yml'; static $fixture_file = 'sapphire/tests/SiteTreeTest.yml';
/** /**
* Test generation of the URLSegment values. * Test generation of the URLSegment values.
* - Turns things into lowercase-hyphen-format * - Turns things into lowercase-hyphen-format
@ -122,6 +121,52 @@ class SiteTreeTest extends SapphireTest {
$this->assertEquals(0, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value()); $this->assertEquals(0, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value());
} }
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);
}
} }
// We make these extend page since that's what all page types are expected to do // We make these extend page since that's what all page types are expected to do