From 6fc01394a6fd9aaaeeb11743df491c0595f758fd Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Fri, 7 Oct 2011 10:05:18 +0200 Subject: [PATCH] API CHANGE: Added VirtualPage::$non_virtual_fields and VirtualPage::$initially_copied_fields for configuring the behaviour of virtual pages. (merged from r100463) --- code/model/VirtualPage.php | 62 +++++++++++++++++++----------- tests/model/VirtualPageTest.php | 67 +++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/code/model/VirtualPage.php b/code/model/VirtualPage.php index 4a6f7178..fd9fa292 100644 --- a/code/model/VirtualPage.php +++ b/code/model/VirtualPage.php @@ -13,6 +13,33 @@ class VirtualPage extends Page { public static $virtualFields; + /** + * @var Array Define fields that are not virtual - the virtual page must define these fields themselves. + * Note that anything in {@link self::$initially_copied_fields} is implicitly included in this list. + */ + public static $non_virtual_fields = array( + "SecurityTypeID", + "OwnerID", + "URLSegment", + "Sort", + "Status", + 'ShowInMenus', + // 'Locale' + 'ShowInSearch', + 'Version', + "Embargo", + "Expiry", + ); + + /** + * @var Array Define fields that are initially copied to virtual pages but left modifiable after that. + */ + public static $initially_copied_fields = array( + 'ShowInMenus', + 'ShowInSearch', + 'URLSegment', + ); + static $has_one = array( "CopyContentFrom" => "SiteTree", ); @@ -25,26 +52,16 @@ class VirtualPage extends Page { * Generates the array of fields required for the page type. */ function getVirtualFields() { - $nonVirtualFields = array( - "SecurityTypeID", - "OwnerID", - "URLSegment", - "Sort", - "Status", - 'ShowInMenus', - // 'Locale' - 'ShowInSearch', - 'Version', - "Embargo", - "Expiry", - ); + $nonVirtualFields = array_merge(self::$non_virtual_fields, self::$initially_copied_fields); + $record = $this->CopyContentFrom(); - $allFields = $this->db(); - if($hasOne = $this->has_one()) foreach($hasOne as $link) $allFields[$link . 'ID'] = "Int"; + $allFields = $record->db(); + if($hasOne = $record->has_one()) foreach($hasOne as $link) $allFields[$link . 'ID'] = "Int"; + $virtualFields = array(); foreach($allFields as $field => $type) { if(!in_array($field, $nonVirtualFields)) $virtualFields[] = $field; } - + return $virtualFields; } @@ -195,7 +212,7 @@ class VirtualPage extends Page { // 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; + $performCopyFrom = $this->isChanged('CopyContentFromID', 2) && $this->CopyContentFromID != 0; } // On publish, this will copy from published source @@ -205,7 +222,6 @@ class VirtualPage extends Page { $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; } parent::onBeforeWrite(); @@ -235,10 +251,12 @@ class VirtualPage extends Page { $this->$virtualField = $source->$virtualField; } - // We also want to copy ShowInMenus, but only if we're copying the - // source page for the first time. - if($this->isChanged('CopyContentFromID')) { - $this->ShowInMenus = $source->ShowInMenus; + // We also want to copy certain, but only if we're copying the source page for the first + // time. After this point, the user is free to customise these for the virtual page themselves. + if($this->isChanged('CopyContentFromID', 2) && $this->CopyContentFromID != 0) { + foreach(self::$initially_copied_fields as $fieldName) { + $this->$fieldName = $source->$fieldName; + } } if($updateImageTracking) $this->updateImageTracking(); diff --git a/tests/model/VirtualPageTest.php b/tests/model/VirtualPageTest.php index 8a77d2dc..12573d9a 100644 --- a/tests/model/VirtualPageTest.php +++ b/tests/model/VirtualPageTest.php @@ -352,6 +352,73 @@ class VirtualPageTest extends SapphireTest { $valid = $classCVirtual->validate(); $this->assertFalse($valid->valid(), "Doesn't allow child linked to virtual page type disallowed by parent"); } + + function testGetVirtualFields() { + $origInitiallyCopiedFields = VirtualPage::$initially_copied_fields; + VirtualPage::$initially_copied_fields[] = 'MyInitiallyCopiedField'; + $origNonVirtualField = VirtualPage::$non_virtual_fields; + VirtualPage::$non_virtual_fields[] = 'MyNonVirtualField'; + + // Needs association with an original, otherwise will just return the "base" virtual fields + $page = new VirtualPageTest_ClassA(); + $page->write(); + $virtual = new VirtualPage(); + $virtual->CopyContentFromID = $page->ID; + $virtual->write(); + + $this->assertContains('MyVirtualField', $virtual->getVirtualFields()); + $this->assertNotContains('MyNonVirtualField', $virtual->getVirtualFields()); + $this->assertNotContains('MyInitiallyCopiedField', $virtual->getVirtualFields()); + + VirtualPage::$initially_copied_fields = $origInitiallyCopiedFields; + VirtualPage::$non_virtual_fields = $origNonVirtualField; + } + + function testCopyFrom() { + $origInitiallyCopiedFields = VirtualPage::$initially_copied_fields; + VirtualPage::$initially_copied_fields[] = 'MyInitiallyCopiedField'; + $origNonVirtualField = VirtualPage::$non_virtual_fields; + VirtualPage::$non_virtual_fields[] = 'MyNonVirtualField'; + + $original = new VirtualPageTest_ClassA(); + $original->MyInitiallyCopiedField = 'original'; + $original->MyVirtualField = 'original'; + $original->MyNonVirtualField = 'original'; + $original->write(); + + $virtual = new VirtualPage(); + $virtual->CopyContentFromID = $original->ID; + $virtual->write(); + + $virtual->copyFrom($original); + // Using getField() to avoid side effects from an overloaded __get() + $this->assertEquals( + 'original', + $virtual->getField('MyInitiallyCopiedField'), + 'Fields listed in $initially_copied_fields are copied on first copyFrom() invocation' + ); + $this->assertEquals( + 'original', + $virtual->getField('MyVirtualField'), + 'Fields not listed in $initially_copied_fields are copied in copyFrom()' + ); + $this->assertNull( + $virtual->getField('MyNonVirtualField'), + 'Fields listed in $non_virtual_fields are not copied in copyFrom()' + ); + + $original->MyInitiallyCopiedField = 'changed'; + $original->write(); + $virtual->copyFrom($original); + $this->assertEquals( + 'original', + $virtual->MyInitiallyCopiedField, + 'Fields listed in $initially_copied_fields are not copied on subsequent copyFrom() invocations' + ); + + VirtualPage::$initially_copied_fields = $origInitiallyCopiedFields; + VirtualPage::$non_virtual_fields = $origNonVirtualField; + } } class VirtualPageTest_ClassA extends Page implements TestOnly {