BUGFIX: Update virtual pages semantics to grab content from the published version of the source page when you publish the virtual page, and to not allow publication before their source page is published. (from r92209) (from r96748)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@102377 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2010-04-12 02:40:09 +00:00
parent 7c14bd233a
commit b8246bb433
2 changed files with 88 additions and 13 deletions

View File

@ -58,6 +58,24 @@ class VirtualPage extends Page {
}
}
/**
* We can only publish the page if there is a published source page
*/
public function canPublish($member = null) {
// No source
if(!$this->CopyContentFrom()) {
return false;
}
// Unpublished source
if(!Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->CopyContentFromID)) {
return false;
}
// Default behaviour
return parent::canPublish($member);
}
/**
* Generate the CMS fields from the fields from the original page.
*/
@ -106,19 +124,25 @@ class VirtualPage extends Page {
* We have to change it to copy all the content from the original page first.
*/
function onBeforeWrite() {
// Don't do this stuff when we're publishing
if(!$this->extension_instances['Versioned']->migratingVersion) {
if(
$this->isChanged('CopyContentFromID')
&& $this->CopyContentFromID != 0
&& $this instanceof VirtualPage
) {
$source = DataObject::get_one("SiteTree",sprintf('"SiteTree"."ID" = %d', $this->CopyContentFromID));
if($source) {
$this->copyFrom($source, false);
$this->URLSegment = $source->URLSegment . '-' . $this->ID;
}
}
// On regular write, this will copy from published source. This happens on every publish
if($this->extension_instances['Versioned']->migratingVersion
&& Versioned::current_stage() == 'Live') {
$performCopyFrom = true;
// On regular write, this will copy from draft source. This is only executed when the source
// page changeds
} else {
$performCopyFrom = $this->isChanged('CopyContentFromID') && $this->CopyContentFromID != 0;
}
// On publish, this will copy from published source
if($performCopyFrom && $this instanceof VirtualPage) {
// This flush is needed because the get_one cache doesn't respect site version :-(
singleton('SiteTree')->flushCache();
$source = DataObject::get_one("SiteTree",sprintf('"SiteTree"."ID" = %d', $this->CopyContentFromID));
// Leave the updating of image tracking until after write, in case its a new record
$this->copyFrom($source, false);
$this->URLSegment = $source->URLSegment . '-' . $this->ID;
}
parent::onBeforeWrite();

View File

@ -75,4 +75,55 @@ class VirtualPageTest extends SapphireTest {
$this->assertEquals("My Other Page Nav", $vp->MenuTitle);
}
/**
* Virtual pages are always supposed to chose the same content as the published source page.
* This means that when you publish them, they should show the published content of the source
* page, not the draft content at the time when you clicked 'publish' in the CMS.
*/
function testPublishingAVirtualPageCopiedPublishedContentNotDraftContent() {
$p = new Page();
$p->Content = "published content";
$p->write();
$p->doPublish();
// Don't publish this change - published page will still say 'published content'
$p->Content = "draft content";
$p->write();
$vp = new VirtualPage();
$vp->CopyContentFromID = $p->ID;
$vp->write();
$vp->doPublish();
// The draft content of the virtual page should say 'draft content'
$this->assertEquals('draft content',
DB::query('SELECT "Content" from "SiteTree" WHERE ID = ' . $vp->ID)->value());
// The published content of the virtual page should say 'published content'
$this->assertEquals('published content',
DB::query('SELECT "Content" from "SiteTree_Live" WHERE ID = ' . $vp->ID)->value());
}
function testCantPublishVirtualPagesBeforeTheirSource() {
// An unpublished source page
$p = new Page();
$p->Content = "test content";
$p->write();
// With no source page, we can't publish
$vp = new VirtualPage();
$vp->write();
$this->assertFalse($vp->canPublish());
// When the source page isn't published, we can't publish
$vp->CopyContentFromID = $p->ID;
$vp->write();
$this->assertFalse($vp->canPublish());
// Once the source page gets published, then we can publish
$p->doPublish();
$this->assertTrue($vp->canPublish());
}
}