API CHANGE: Added VirtualPage::$non_virtual_fields and VirtualPage::$initially_copied_fields for configuring the behaviour of virtual pages. (merged from r100463)

This commit is contained in:
Sam Minnee 2011-10-07 10:05:18 +02:00 committed by Ingo Schommer
parent 987eedf9ba
commit 6fc01394a6
2 changed files with 107 additions and 22 deletions

View File

@ -13,19 +13,11 @@ class VirtualPage extends Page {
public static $virtualFields;
static $has_one = array(
"CopyContentFrom" => "SiteTree",
);
static $db = array(
"VersionID" => "Int",
);
/**
* Generates the array of fields required for the page type.
* @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.
*/
function getVirtualFields() {
$nonVirtualFields = array(
public static $non_virtual_fields = array(
"SecurityTypeID",
"OwnerID",
"URLSegment",
@ -39,8 +31,33 @@ class VirtualPage extends Page {
"Expiry",
);
$allFields = $this->db();
if($hasOne = $this->has_one()) foreach($hasOne as $link) $allFields[$link . 'ID'] = "Int";
/**
* @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",
);
static $db = array(
"VersionID" => "Int",
);
/**
* Generates the array of fields required for the page type.
*/
function getVirtualFields() {
$nonVirtualFields = array_merge(self::$non_virtual_fields, self::$initially_copied_fields);
$record = $this->CopyContentFrom();
$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;
}
@ -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();

View File

@ -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 {