mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUGFIX: Fixed bugs with copying custom fields into Virtual pages, generally made virtual pages more robust and performant.
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@101112 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
48d3f48edb
commit
25836a1bea
@ -46,6 +46,31 @@ class VirtualPage extends Page {
|
|||||||
return $virtualFields;
|
return $virtualFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CopyContentFrom() {
|
||||||
|
if(empty($this->record['CopyContentFromID'])) return new SiteTree();
|
||||||
|
|
||||||
|
if(!isset($this->components['CopyContentFrom'])) {
|
||||||
|
$this->components['CopyContentFrom'] = DataObject::get_by_id("SiteTree",
|
||||||
|
$this->record['CopyContentFromID']);
|
||||||
|
|
||||||
|
// Don't let VirtualPages point to other VirtualPages
|
||||||
|
if($this->components['CopyContentFrom'] instanceof VirtualPage) {
|
||||||
|
$this->components['CopyContentFrom'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// has_one component semantics incidate than an empty object should be returned
|
||||||
|
if(!$this->components['CopyContentFrom']) {
|
||||||
|
$this->components['CopyContentFrom'] = new SiteTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->components['CopyContentFrom'];
|
||||||
|
}
|
||||||
|
function setCopyContentFromID($val) {
|
||||||
|
if(DataObject::get_by_id('SiteTree', $val) instanceof VirtualPage) $val = 0;
|
||||||
|
return $this->setField("CopyContentFromID", $val);
|
||||||
|
}
|
||||||
|
|
||||||
function ContentSource() {
|
function ContentSource() {
|
||||||
return $this->CopyContentFrom();
|
return $this->CopyContentFrom();
|
||||||
}
|
}
|
||||||
@ -59,6 +84,8 @@ class VirtualPage extends Page {
|
|||||||
public function syncLinkTracking() {
|
public function syncLinkTracking() {
|
||||||
if($this->CopyContentFromID) {
|
if($this->CopyContentFromID) {
|
||||||
$this->HasBrokenLink = !(bool) DataObject::get_by_id('SiteTree', $this->CopyContentFromID);
|
$this->HasBrokenLink = !(bool) DataObject::get_by_id('SiteTree', $this->CopyContentFromID);
|
||||||
|
} else {
|
||||||
|
$this->HasBrokenLink = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +137,8 @@ class VirtualPage extends Page {
|
|||||||
_t('VirtualPage.CHOOSE', "Choose a page to link to"),
|
_t('VirtualPage.CHOOSE', "Choose a page to link to"),
|
||||||
"SiteTree"
|
"SiteTree"
|
||||||
);
|
);
|
||||||
$copyContentFromField->setFilterFunction(create_function('$item', 'return $item->ClassName != "VirtualPage";'));
|
// filter doesn't let you select children of virtual pages as as source page
|
||||||
|
//$copyContentFromField->setFilterFunction(create_function('$item', 'return !($item instanceof VirtualPage);'));
|
||||||
|
|
||||||
// Setup virtual fields
|
// Setup virtual fields
|
||||||
if($virtualFields = $this->getVirtualFields()) {
|
if($virtualFields = $this->getVirtualFields()) {
|
||||||
@ -129,7 +157,7 @@ class VirtualPage extends Page {
|
|||||||
$fields->addFieldToTab("Root.Content.Main", $copyContentFromField, "Title");
|
$fields->addFieldToTab("Root.Content.Main", $copyContentFromField, "Title");
|
||||||
|
|
||||||
// Create links back to the original object in the CMS
|
// Create links back to the original object in the CMS
|
||||||
if($this->CopyContentFromID) {
|
if($this->CopyContentFrom()->ID) {
|
||||||
$linkToContent = "<a class=\"cmsEditlink\" href=\"admin/show/$this->CopyContentFromID\">" .
|
$linkToContent = "<a class=\"cmsEditlink\" href=\"admin/show/$this->CopyContentFromID\">" .
|
||||||
_t('VirtualPage.EDITCONTENT', 'click here to edit the content') . "</a>";
|
_t('VirtualPage.EDITCONTENT', 'click here to edit the content') . "</a>";
|
||||||
$fields->addFieldToTab("Root.Content.Main",
|
$fields->addFieldToTab("Root.Content.Main",
|
||||||
@ -149,15 +177,17 @@ class VirtualPage extends Page {
|
|||||||
// On regular write, this will copy from published source. This happens on every publish
|
// On regular write, this will copy from published source. This happens on every publish
|
||||||
if($this->extension_instances['Versioned']->migratingVersion
|
if($this->extension_instances['Versioned']->migratingVersion
|
||||||
&& Versioned::current_stage() == 'Live') {
|
&& Versioned::current_stage() == 'Live') {
|
||||||
$performCopyFrom = true;
|
if($this->CopyContentFromID) {
|
||||||
|
$performCopyFrom = true;
|
||||||
|
|
||||||
$stageSourceVersion = DB::query("SELECT \"Version\" FROM \"SiteTree\" WHERE \"ID\" = $this->CopyContentFromID")->value();
|
$stageSourceVersion = DB::query("SELECT \"Version\" FROM \"SiteTree\" WHERE \"ID\" = $this->CopyContentFromID")->value();
|
||||||
$liveSourceVersion = DB::query("SELECT \"Version\" FROM \"SiteTree_Live\" WHERE \"ID\" = $this->CopyContentFromID")->value();
|
$liveSourceVersion = DB::query("SELECT \"Version\" FROM \"SiteTree_Live\" WHERE \"ID\" = $this->CopyContentFromID")->value();
|
||||||
|
|
||||||
// We're going to create a new VP record in SiteTree_versions because the published
|
// We're going to create a new VP record in SiteTree_versions because the published
|
||||||
// version might not exist, unless we're publishing the latest version
|
// version might not exist, unless we're publishing the latest version
|
||||||
if($stageSourceVersion != $liveSourceVersion) {
|
if($stageSourceVersion != $liveSourceVersion) {
|
||||||
$this->extension_instances['Versioned']->migratingVersion = null;
|
$this->extension_instances['Versioned']->migratingVersion = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On regular write, this will copy from draft source. This is only executed when the source
|
// On regular write, this will copy from draft source. This is only executed when the source
|
||||||
@ -173,7 +203,7 @@ class VirtualPage extends Page {
|
|||||||
$source = DataObject::get_one("SiteTree",sprintf('"SiteTree"."ID" = %d', $this->CopyContentFromID));
|
$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
|
// Leave the updating of image tracking until after write, in case its a new record
|
||||||
$this->copyFrom($source, false);
|
$this->copyFrom($source, false);
|
||||||
$this->URLSegment = $source->URLSegment . '-' . $this->ID;
|
$this->URLSegment = $source->URLSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::onBeforeWrite();
|
parent::onBeforeWrite();
|
||||||
@ -234,18 +264,13 @@ class VirtualPage extends Page {
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
function __get($field) {
|
function __get($field) {
|
||||||
$return = parent::__get($field);
|
if(parent::hasMethod($funcName = "get$field")) {
|
||||||
if ($return === null) {
|
return $this->$funcName();
|
||||||
if($this->copyContentFrom()->hasMethod($funcName = "get$field")) {
|
} else if(parent::hasField($field)) {
|
||||||
$return = $this->copyContentFrom()->$funcName();
|
return $this->getField($field);
|
||||||
} else if($this->copyContentFrom()->hasField($field)) {
|
} else {
|
||||||
$return = $this->copyContentFrom()->getField($field);
|
return $this->copyContentFrom()->$field;
|
||||||
} else if($field == 'Content') {
|
|
||||||
return '<p>' . _t('VirtualPage.NOTFOUND', 'We could not find the content for this virtual page.') . '</p>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,17 +280,22 @@ class VirtualPage extends Page {
|
|||||||
* @param string $args
|
* @param string $args
|
||||||
*/
|
*/
|
||||||
function __call($method, $args) {
|
function __call($method, $args) {
|
||||||
try {
|
if(parent::hasMethod($method)) {
|
||||||
return parent::__call($method, $args);
|
return parent::__call($method, $args);
|
||||||
} catch (Exception $e) {
|
} else {
|
||||||
// Hack... detect exception type. We really should use exception subclasses.
|
return call_user_func_array(array($this->copyContentFrom(), $method), $args);
|
||||||
// if the exception isn't a 'no method' error, rethrow it
|
|
||||||
if ($e->getCode() !== 2175) throw $e;
|
|
||||||
$original = $this->copyContentFrom();
|
|
||||||
return call_user_func_array(array($original, $method), $args);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasField($field) {
|
||||||
|
return (
|
||||||
|
array_key_exists($field, $this->record)
|
||||||
|
|| $this->hasDatabaseField($field)
|
||||||
|
|| array_key_exists($field, $this->db()) // Needed for composite fields
|
||||||
|
|| parent::hasMethod("get{$field}")
|
||||||
|
|| $this->CopyContentFrom()->hasField($field)
|
||||||
|
);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Overwrite to also check for method on the original data object
|
* Overwrite to also check for method on the original data object
|
||||||
*
|
*
|
||||||
@ -273,9 +303,8 @@ class VirtualPage extends Page {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function hasMethod($method) {
|
function hasMethod($method) {
|
||||||
$haveIt = parent::hasMethod($method);
|
if(parent::hasMethod($method)) return true;
|
||||||
if (!$haveIt) $haveIt = $this->copyContentFrom()->hasMethod($method);
|
return $this->copyContentFrom()->hasMethod($method);
|
||||||
return $haveIt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user