From b868893a5491f6d0efe8c27f301dc629fe7e8c49 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 12 Jan 2010 23:30:50 +0000 Subject: [PATCH] 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) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@96748 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- core/model/VirtualPage.php | 50 +++++++++++++++++++++++--------- tests/model/VirtualPageTest.php | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/core/model/VirtualPage.php b/core/model/VirtualPage.php index 2ba154f26..a2bfa5854 100755 --- a/core/model/VirtualPage.php +++ b/core/model/VirtualPage.php @@ -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(); diff --git a/tests/model/VirtualPageTest.php b/tests/model/VirtualPageTest.php index 38fcd4dc8..aac6ea565 100644 --- a/tests/model/VirtualPageTest.php +++ b/tests/model/VirtualPageTest.php @@ -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()); + } + } \ No newline at end of file