From c2d24f9022ba1d21a32e62c06e5993d90d97ea52 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sat, 21 Nov 2009 02:39:12 +0000 Subject: [PATCH] FEATURE Changed CMSMain and LeftAndMain form submissions to return raw HTML instead of using FormResponse logic and evaluated javascript. This allows a more customizeable UI layer that is decoupled from the serverside logic. Any state changes should be propagated through the form itself. ENHANCEMENT Using new 'X-STATUS' HTTP response header for CMS form responses, as it is more robust for submitting variable length strings than the original 'Status' header. The status is evaluated in LeftAndMain.EditForm.js API CHANGE Removed CMSMain->tellBrowserAboutPublicationChange(), LeftAndMain->returnItemToUser(), LeftAndMain->getActionUpdateJS(), LeftAndMain->addTreeNodeJS(), LeftAndMain->deleteTreeNodeJS(). Use javascript to respond to state changes API CHANGE Removed CMSForm and CMSRightForm javascript classes, superseded by LeftAndMain.EditForm.js ENHANCEMENT Removed custom change detection in LeftAndMain->save(), this should be handled by DataObject->write() ENHANCEMENT Removed switch in LeftAndMain->save() which doesnt process saving if the record hasn't been altered, to simplify the saving logic ENHANCEMENT Removed custom add/remove tree node logic in LeftAndMain->save() which was retrieving state from DataObjectLog. This was never actively used, and should be handled by custom clientside logic. git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92674 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- code/AssetAdmin.php | 1 - code/CMSMain.php | 242 ++++++++++++------------ code/LeftAndMain.php | 295 ++++++----------------------- javascript/LeftAndMain_left.js | 38 ++++ javascript/LeftAndMain_right.js | 319 -------------------------------- 5 files changed, 223 insertions(+), 672 deletions(-) diff --git a/code/AssetAdmin.php b/code/AssetAdmin.php index 69fa862f7c..f8b6789d5b 100755 --- a/code/AssetAdmin.php +++ b/code/AssetAdmin.php @@ -578,7 +578,6 @@ public function deletefolder() { if(is_numeric($id)) { $record = DataObject::get_by_id($this->stat('tree_class'), $id); if($record) { - $script .= $this->deleteTreeNodeJS($record); $record->delete(); $record->destroy(); } diff --git a/code/CMSMain.php b/code/CMSMain.php index adf14cd38f..19d4efeed3 100755 --- a/code/CMSMain.php +++ b/code/CMSMain.php @@ -369,6 +369,10 @@ public function getEditForm($id) { } } + $form = new Form($this, "EditForm", $fields, $actions); + $form->loadDataFrom($record); + $form->disableDefaultAction(); + // Add a default or custom validator. // @todo Currently the default Validator.js implementation // adds javascript to the document body, meaning it won't @@ -387,15 +391,6 @@ public function getEditForm($id) { } else { $form->unsetValidator(); } - - // The clientside (mainly LeftAndMain*.js) rely on ajax responses - // which can be evaluated as javascript, hence we need - // to override any global changes to the validation handler. - $validator->setJavascriptValidationHandler('prototype'); - - $form = new Form($this, "EditForm", $fields, $actions, $validator); - $form->loadDataFrom($record); - $form->disableDefaultAction(); if(!$record->canEdit() || $record->IsDeletedFromStage) { $readonlyFields = $form->Fields()->makeReadonly(); @@ -421,27 +416,29 @@ public function getEditForm($id) { // Data saving handlers - public function addpage() { - $className = isset($_REQUEST['PageType']) ? $_REQUEST['PageType'] : "Page"; - $parent = isset($_REQUEST['ParentID']) ? $_REQUEST['ParentID'] : 0; - $suffix = isset($_REQUEST['Suffix']) ? "-" . $_REQUEST['Suffix'] : null; + public function addpage($data, $form) { + $className = isset($data['PageType']) ? $data['PageType'] : "Page"; + $parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0; + $suffix = isset($data['Suffix']) ? "-" . $data['Suffix'] : null; - if(!$parent && isset($_REQUEST['Parent'])) { - $page = SiteTree::get_by_link($_REQUEST['Parent']); - if($page) $parent = $page->ID; + if(!$parentID && isset($data['Parent'])) { + $page = SiteTree:: get_by_link(Convert::raw2sql($data['Parent'])); + if($page) $parentID = $page->ID; } - if(is_numeric($parent)) $parentObj = DataObject::get_by_id("SiteTree", $parent); - if(!$parentObj || !$parentObj->ID) $parent = 0; + if(is_numeric($parentID)) $parentObj = DataObject::get_by_id("SiteTree", $parentID); + if(!$parentObj || !$parentObj->ID) $parentID = 0; if($parentObj && !$parentObj->canAddChildren()) return Security::permissionFailure($this); if(!singleton($className)->canCreate()) return Security::permissionFailure($this); $p = $this->getNewItem("new-$className-$parent".$suffix, false); - $p->Locale = $_REQUEST['Locale']; + $p->Locale = $data['Locale']; $p->write(); - - return $this->returnItemToUser($p); + + $form = $this->getEditForm($p->ID); + + return $form->formHtmlContent(); } /** @@ -491,10 +488,9 @@ public function getNewItem($id, $setID = true) { * * @see delete() */ - public function deletefromlive($urlParams, $form) { - $id = $_REQUEST['ID']; + public function deletefromlive($data, $form) { Versioned::reading_stage('Live'); - $record = DataObject::get_by_id("SiteTree", $id); + $record = DataObject::get_by_id("SiteTree", $data['ID']); if($record && !$record->canDelete()) return Security::permissionFailure($this); $descRemoved = ''; @@ -525,10 +521,17 @@ public function deletefromlive($urlParams, $form) { $descRemoved = ''; } - FormResponse::add($this->deleteTreeNodeJS($record)); - FormResponse::status_message(sprintf(_t('CMSMain.REMOVED', 'Deleted \'%s\'%s from live site'), $record->Title, $descRemoved), 'good'); + $this->response->addHeader( + 'X-Status', + sprintf( + _t('CMSMain.REMOVED', 'Deleted \'%s\'%s from live site'), + $record->Title, + $descRemoved + ) + ); - return FormResponse::respond(); + // nothing to return + return ''; } /** @@ -547,22 +550,37 @@ public function performPublish($record) { * * @uses SiteTree->doRevertToLive() */ - public function revert($urlParams, $form) { - $id = (int)$_REQUEST['ID']; - $record = Versioned::get_one_by_stage('SiteTree', 'Live', "\"SiteTree_Live\".\"ID\" = '{$id}'"); + public function revert($data, $form) { + if(!isset($data['ID'])) return new HTTPResponse("Please pass an ID in the form content", 400); + + $restoredPage = Versioned::get_latest_version("SiteTree", $data['ID']); + if(!$restoredPage) return new HTTPResponse("SiteTree #$id not found", 400); + + $record = Versioned::get_one_by_stage( + 'SiteTree', + 'Live', + sprintf("\"SiteTree_Live\".\"ID\" = '%d'", (int)$data['ID']) + ); // a user can restore a page without publication rights, as it just adds a new draft state // (this action should just be available when page has been "deleted from draft") - if(isset($record) && $record && !$record->canEdit()) return Security::permissionFailure($this); + if(isset($record) && $record && !$record->canEdit()) { + return Security::permissionFailure($this); + } $record->doRevertToLive(); - - $title = Convert::raw2js($record->Title); - FormResponse::get_page($id); - FormResponse::add("$('sitetree').setNodeTitle($id, '$title');"); - FormResponse::status_message(sprintf(_t('CMSMain.RESTORED',"Restored '%s' successfully",PR_MEDIUM,'Param %s is a title'),$title),'good'); - - return FormResponse::respond(); + + $this->response->addHeader( + 'X-Status', + sprintf( + _t('CMSMain.RESTORED',"Restored '%s' successfully",PR_MEDIUM,'Param %s is a title'), + $record->Title + ) + ); + + $form = $this->getEditForm($record->ID); + + return $form->formHtmlContent(); } /** @@ -580,20 +598,23 @@ public function delete($data, $form) { $recordID = $record->ID; $record->delete(); + $this->response->addHeader( + 'X-Status', + sprintf( + _t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"), + $record->Title + ) + ); + if(Director::is_ajax()) { // need a valid ID value even if the record doesn't have one in the database // (its still present in the live tables) - $liveRecord = Versioned::get_one_by_stage('SiteTree', 'Live', "\"SiteTree_Live\".\"ID\" = $recordID"); - // if the page has never been published to live, we need to act the same way as in deletefromlive() - if($liveRecord) { - // the form is readonly now, so we need to refresh the representation - FormResponse::get_page($recordID); - return $this->tellBrowserAboutPublicationChange($liveRecord, sprintf(_t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"),$record->Title)); - } else { - FormResponse::add($this->deleteTreeNodeJS($record)); - FormResponse::status_message(sprintf(_t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"),$record->Title), 'good'); - return FormResponse::respond(); - } + $liveRecord = Versioned::get_one_by_stage( + 'SiteTree', + 'Live', + "\"SiteTree_Live\".\"ID\" = $recordID" + ); + return ($liveRecord) ? $form->formHtmlContent() : ""; } else { Director::redirectBack(); } @@ -674,65 +695,49 @@ function versions() { /** * Roll a page back to a previous version */ - function rollback() { - if(isset($_REQUEST['Version']) && (bool)$_REQUEST['Version']) { - $record = $this->performRollback($_REQUEST['ID'], $_REQUEST['Version']); - echo sprintf(_t('CMSMain.ROLLEDBACKVERSION',"Rolled back to version #%d. New version number is #%d"),$_REQUEST['Version'],$record->Version); + function rollback($data, $form) { + if(isset($data['Version']) && (bool)$data['Version']) { + $record = $this->performRollback($data['ID'], $data['Version']); + $message = sprintf( + _t('CMSMain.ROLLEDBACKVERSION',"Rolled back to version #%d. New version number is #%d"), + $data['Version'], + $record->Version + ); } else { - $record = $this->performRollback($_REQUEST['ID'], "Live"); - echo sprintf(_t('CMSMain.ROLLEDBACKPUB',"Rolled back to published version. New version number is #%d"),$record->Version); + $record = $this->performRollback($data['ID'], "Live"); + $message = sprintf( + _t('CMSMain.ROLLEDBACKPUB',"Rolled back to published version. New version number is #%d"), + $record->Version + ); } + + $this->response->addHeader('X-Status', $message); + + $form = $this->getEditForm($record->ID); + + return $form->formHtmlContent(); } - function publish($urlParams, $form) { - $urlParams['publish'] = '1'; + function publish($data, $form) { + $data['publish'] = '1'; - return $this->save($urlParams, $form); + return $this->save($data, $form); } - function unpublish() { - $SQL_id = Convert::raw2sql($_REQUEST['ID']); - - $page = DataObject::get_by_id("SiteTree", $SQL_id); + function unpublish($data, $form) { + $page = DataObject::get_by_id("SiteTree", $data['ID']); if($page && !$page->canPublish()) return Security::permissionFailure($this); $page->doUnpublish(); - return $this->tellBrowserAboutPublicationChange($page, sprintf(_t('CMSMain.REMOVEDPAGE',"Removed '%s' from the published site"),$page->Title)); - } - - /** - * Return a few pieces of information about a change to a page - * - Send the new status message - * - Update the action buttons - * - Update the treenote - * - Send a status message - */ - function tellBrowserAboutPublicationChange($page, $statusMessage) { - $JS_title = Convert::raw2js($page->TreeTitle()); - - $JS_stageURL = $page->IsDeletedFromStage ? '' : Convert::raw2js($page->AbsoluteLink()); - $liveRecord = Versioned::get_one_by_stage('SiteTree', 'Live', "\"SiteTree\".\"ID\" = $page->ID"); - - $JS_liveURL = $liveRecord ? Convert::raw2js($liveRecord->AbsoluteLink()) : ''; - - FormResponse::add($this->getActionUpdateJS($page)); - FormResponse::update_status($page->Status); + $this->response->addHeader( + 'X-Status', + sprintf(_t('CMSMain.REMOVEDPAGE',"Removed '%s' from the published site"),$page->Title) + ); - if($JS_stageURL || $JS_liveURL) { - FormResponse::add("\$('sitetree').setNodeTitle($page->ID, '$JS_title');"); - } else { - FormResponse::add("var node = $('sitetree').getTreeNodeByIdx('$page->ID');"); - FormResponse::add("if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);"); - FormResponse::add("$('Form_EditForm').reloadIfSetTo($page->ID);"); - } + $form->loadDataFrom($page); - if($statusMessage) FormResponse::status_message($statusMessage, 'good'); - FormResponse::add("$('Form_EditForm').elements.StageURLSegment.value = '$JS_stageURL';"); - FormResponse::add("$('Form_EditForm').elements.LiveURLSegment.value = '$JS_liveURL';"); - FormResponse::add("$('Form_EditForm').notify('PagePublished', $('Form_EditForm').elements.ID.value);"); - - return FormResponse::respond(); + return $form->formHtmlContent(); } function performRollback($id, $version) { @@ -1085,6 +1090,7 @@ function SearchTreeForm() { ) ) ); + $form->unsetValidator(); return $form; } @@ -1167,24 +1173,26 @@ function publishall() { /** * Restore a completely deleted page from the SiteTree_versions table. */ - function restore() { - if(($id = $_REQUEST['ID']) && is_numeric($id)) { - $restoredPage = Versioned::get_latest_version("SiteTree", $id); - if($restoredPage) { - $restoredPage = $restoredPage->doRestoreToStage(); - - FormResponse::get_page($id); - $title = Convert::raw2js($restoredPage->TreeTitle()); - FormResponse::add("$('sitetree').setNodeTitle($id, '$title');"); - FormResponse::status_message(sprintf(_t('CMSMain.RESTORED',"Restored '%s' successfully",PR_MEDIUM,'Param %s is a title'),$title),'good'); - return FormResponse::respond(); - - } else { - return new SS_HTTPResponse("SiteTree #$id not found", 400); - } - } else { - return new SS_HTTPResponse("Please pass an ID in the form content", 400); + function restore($data, $form) { + if(!isset($data['ID']) || !is_numeric($data['ID'])) { + return new HTTPResponse("Please pass an ID in the form content", 400); } + + $restoredPage = Versioned::get_latest_version("SiteTree", $id); + if(!$restoredPage) return new HTTPResponse("SiteTree #$id not found", 400); + + $restoredPage = $restoredPage->doRestoreToStage(); + + $this->response->addHeader( + 'X-Status', + sprintf( + _t('CMSMain.RESTORED',"Restored '%s' successfully",PR_MEDIUM,'Param %s is a title'), + $restoredPage->TreeTitle + ) + ); + + $form = $this->getEditForm($id); + return $form->formHtmlContent(); } function duplicate() { @@ -1201,8 +1209,9 @@ function duplicate() { $newPage->ParentID = $_GET['parentID']; $newPage->write(); } - - return $this->returnItemToUser($newPage); + + $form = $this->getEditForm($newPage->ID); + return $form->formHtmlContent(); } else { user_error("CMSMain::duplicate() Bad ID: '$id'", E_USER_WARNING); } @@ -1217,14 +1226,13 @@ function duplicatewithchildren() { $newPage = $page->duplicateWithChildren(); - return $this->returnItemToUser($newPage); + $form = $this->getEditForm($newPage->ID); + return $form->formHtmlContent(); } else { user_error("CMSMain::duplicate() Bad ID: '$id'", E_USER_WARNING); } } - - /** * Create a new translation from an existing item, switch to this language and reload the tree. */ diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php index a308ee662e..405b91b1bd 100644 --- a/code/LeftAndMain.php +++ b/code/LeftAndMain.php @@ -344,6 +344,7 @@ public function show($request) { SSViewer::setOption('rewriteHashlinks', false); return $this->EditForm()->formHtmlContent(); } else { + // Rendering is handled by template, which will call EditForm() eventually return array(); } } @@ -545,220 +546,92 @@ public function getsubtree($request) { return $tree; } - /** - * Allows you to returns a new data object to the tree (subclass of sitetree) - * and updates the tree via javascript. - */ - public function returnItemToUser($p) { - if(Director::is_ajax()) { - // Prepare the object for insertion. - $parentID = (int) $p->ParentID; - $id = $p->ID ? $p->ID : "new-$p->class-$p->ParentID"; - $treeTitle = Convert::raw2js($p->TreeTitle()); - $hasChildren = (is_numeric($id) && $p->AllChildren() && $p->AllChildren()->Count()) ? ' unexpanded' : ''; - $singleInstanceCSSClass = $p->stat('single_instance_only') ? $p->stat('single_instance_only_css_class') : ""; - - // Ensure there is definitly a node avaliable. if not, append to the home tree. - $response = <<class}{$hasChildren} {$singleInstanceCSSClass}"); - node = tree.getTreeNodeByIdx($parentID); - if(!node) { - node = tree.getTreeNodeByIdx(0); - } - node.open(); - node.appendTreeNode(newNode); - newNode.selectTreeNode(); -JS; - FormResponse::add($response); - FormResponse::add($this->hideSingleInstanceOnlyFromCreateFieldJS($p)); - - return FormResponse::respond(); - } else { - Director::redirect('admin/' . self::$url_segment . '/show/' . $p->ID); - } - } - /** * Save and Publish page handler */ - public function save($urlParams, $form) { + public function save($data, $form) { $className = $this->stat('tree_class'); - $result = ''; - $SQL_id = Convert::raw2sql($_REQUEST['ID']); + // Existing or new record? + $SQL_id = Convert::raw2sql($data['ID']); if(substr($SQL_id,0,3) != 'new') { - $record = DataObject::get_one($className, "\"$className\".\"ID\" = {$SQL_id}"); + $record = DataObject::get_by_id($className, $SQL_id); if($record && !$record->canEdit()) return Security::permissionFailure($this); } else { if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this); $record = $this->getNewItem($SQL_id, false); } - - // We don't want to save a new version if there are no changes - $dataFields_new = $form->Fields()->dataFields(); - $dataFields_old = $record->getAllFields(); - $changed = false; - $hasNonRecordFields = false; - foreach($dataFields_new as $datafield) { - // if the form has fields not belonging to the record - if(!isset($dataFields_old[$datafield->Name()])) { - $hasNonRecordFields = true; - } - // if field-values have changed - if(!isset($dataFields_old[$datafield->Name()]) || $dataFields_old[$datafield->Name()] != $datafield->dataValue()) { - $changed = true; - } - } - - if(!$changed && !$hasNonRecordFields) { - // Tell the user we have saved even though we haven't, as not to confuse them - if(is_a($record, "Page")) { - $record->Status = "Saved (update)"; - } - FormResponse::status_message(_t('LeftAndMain.SAVEDUP',"Saved"), "good"); - FormResponse::update_status($record->Status); - return FormResponse::respond(); - } - - $form->dataFieldByName('ID')->Value = 0; - - if(isset($urlParams['Sort']) && is_numeric($urlParams['Sort'])) { - $record->Sort = $urlParams['Sort']; - } - - // HACK: This should be turned into something more general - $originalClass = $record->ClassName; - $originalStatus = $record->Status; - $originalParentID = $record->ParentID; - + $record->HasBrokenLink = 0; $record->HasBrokenFile = 0; $record->writeWithoutVersion(); - // HACK: This should be turned into something more general - $originalURLSegment = $record->URLSegment; - - $form->saveInto($record, true); - if(is_a($record, "Page")) { $record->Status = ($record->Status == "New page" || $record->Status == "Saved (new)") ? "Saved (new)" : "Saved (update)"; } - if(Director::is_ajax()) { - if($SQL_id != $record->ID) { - FormResponse::add("$('sitetree').setNodeIdx(\"{$SQL_id}\", \"$record->ID\");"); - FormResponse::add("$('Form_EditForm').elements.ID.value = \"$record->ID\";"); - } - - if($added = DataObjectLog::getAdded('SiteTree')) { - foreach($added as $page) { - if($page->ID != $record->ID) $result .= $this->addTreeNodeJS($page); - } - } - if($deleted = DataObjectLog::getDeleted('SiteTree')) { - foreach($deleted as $page) { - if($page->ID != $record->ID) $result .= $this->deleteTreeNodeJS($page); - } - } - if($changed = DataObjectLog::getChanged('SiteTree')) { - foreach($changed as $page) { - if($page->ID != $record->ID) { - $title = Convert::raw2js($page->TreeTitle()); - FormResponse::add("$('sitetree').setNodeTitle($page->ID, \"$title\");"); - } - } - } - - $message = _t('LeftAndMain.SAVEDUP'); - - // Update the class instance if necessary - if($originalClass != $record->ClassName) { - $newClassName = $record->ClassName; - // The records originally saved attribute was overwritten by $form->saveInto($record) before. - // This is necessary for newClassInstance() to work as expected, and trigger change detection - // on the ClassName attribute - $record->setClassName($originalClass); - // Replace $record with a new instance - $record = $record->newClassInstance($newClassName); - - // update the tree icon - FormResponse::add("if(\$('sitetree').setNodeIcon) \$('sitetree').setNodeIcon($record->ID, '$originalClass', '$record->ClassName');"); - } + // Update the class instance if necessary + if($data['ClassName'] != $record->ClassName) { + $newClassName = $record->ClassName; + // The records originally saved attribute was overwritten by $form->saveInto($record) before. + // This is necessary for newClassInstance() to work as expected, and trigger change detection + // on the ClassName attribute + $record->setClassName($data['ClassName']); + // Replace $record with a new instance + $record = $record->newClassInstance($newClassName); + } - // HACK: This should be turned into somethign more general - if( ($record->class == 'VirtualPage' && $originalURLSegment != $record->URLSegment) || - ($originalClass != $record->ClassName) || self::$ForceReload == true) { - FormResponse::add("$('Form_EditForm').getPageFromServer($record->ID);"); - } + // save form data into record + $form->saveInto($record, true); + $record->write(); + + // if changed to a single_instance_only page type + if ($record->stat('single_instance_only')) { + FormResponse::add("jQuery('#sitetree li.{$record->ClassName}').addClass('{$record->stat('single_instance_only_css_class')}');"); + FormResponse::add($this->hideSingleInstanceOnlyFromCreateFieldJS($record)); + } + else { + FormResponse::add("jQuery('#sitetree li.{$record->ClassName}').removeClass('{$record->stat('single_instance_only_css_class')}');"); + } + // if chnaged from a single_instance_only page type + $sampleOriginalClassObject = new $data['ClassName'](); + if($sampleOriginalClassObject->stat('single_instance_only')) { + FormResponse::add($this->showSingleInstanceOnlyInCreateFieldJS($sampleOriginalClassObject)); + } - // After reloading action - if($originalStatus != $record->Status) { - $message .= sprintf(_t('LeftAndMain.STATUSTO'," Status changed to '%s'"),$record->Status); - } + // If the 'Save & Publish' button was clicked, also publish the page + if (isset($data['publish']) && $data['publish'] == 1) { + $record->doPublish(); + $this->extend('onAfterSave', $record); - if($originalParentID != $record->ParentID) { - FormResponse::add("if(\$('sitetree').setNodeParentID) \$('sitetree').setNodeParentID($record->ID, $record->ParentID);"); - } - - $record->write(); + // Update classname with original and get new instance (see above for explanation) + $record->setClassName($data['ClassName']); + $publishedRecord = $record->newClassInstance($record->ClassName); - // if changed to a single_instance_only page type - if ($record->stat('single_instance_only')) { - FormResponse::add("jQuery('#sitetree li.{$record->ClassName}').addClass('{$record->stat('single_instance_only_css_class')}');"); - FormResponse::add($this->hideSingleInstanceOnlyFromCreateFieldJS($record)); - } - else { - FormResponse::add("jQuery('#sitetree li.{$record->ClassName}').removeClass('{$record->stat('single_instance_only_css_class')}');"); - } - // if chnaged from a single_instance_only page type - $sampleOriginalClassObject = new $originalClass(); - if($sampleOriginalClassObject->stat('single_instance_only')) { - FormResponse::add($this->showSingleInstanceOnlyInCreateFieldJS($sampleOriginalClassObject)); - } + $this->response->addHeader( + 'X-Status', + sprintf( + _t( + 'LeftAndMain.STATUSPUBLISHEDSUCCESS', + "Published '%s' successfully", + PR_MEDIUM, + 'Status message after publishing a page, showing the page title' + ), + $publishedRecord->Title + ) + ); - if( ($record->class != 'VirtualPage') && $originalURLSegment != $record->URLSegment) { - $message .= sprintf(_t('LeftAndMain.CHANGEDURL'," Changed URL to '%s'"),$record->URLSegment); - FormResponse::add("\$('Form_EditForm').elements.URLSegment.value = \"$record->URLSegment\";"); - FormResponse::add("\$('Form_EditForm_StageURLSegment').value = \"{$record->URLSegment}\";"); - } - - // If the 'Save & Publish' button was clicked, also publish the page - if (isset($urlParams['publish']) && $urlParams['publish'] == 1) { - $this->extend('onAfterSave', $record); + $form->loadDataFrom($publishedRecord); + } else { + $this->extend('onAfterSave', $record); + $this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP')); - $record->doPublish(); - - // Update classname with original and get new instance (see above for explanation) - $record->setClassName($originalClass); - $publishedRecord = $record->newClassInstance($record->ClassName); - - return $this->tellBrowserAboutPublicationChange( - $publishedRecord, - sprintf( - _t( - 'LeftAndMain.STATUSPUBLISHEDSUCCESS', - "Published '%s' successfully", - PR_MEDIUM, - 'Status message after publishing a page, showing the page title' - ), - $record->Title - ) - ); - } else { - // BUGFIX: Changed icon only shows after Save button is clicked twice http://support.silverstripe.com/gsoc/ticket/76 - $title = Convert::raw2js($record->TreeTitle()); - FormResponse::add("$('sitetree').setNodeTitle(\"$record->ID\", \"$title\");"); - $result .= $this->getActionUpdateJS($record); - FormResponse::status_message($message, "good"); - FormResponse::update_status($record->Status); - - $this->extend('onAfterSave', $record); - - return FormResponse::respond(); - } + // write process might've changed the record, so we reload before returning + $form->loadDataFrom($record); } + + return $form->formHtmlContent(); } /** @@ -809,54 +682,6 @@ protected function showSingleInstanceOnlyInCreateFieldJS($deletedPage) { JS; } - /** - * Return a piece of javascript that will update the actions of the main form - */ - public function getActionUpdateJS($record) { - // Get the new action buttons - - $tempForm = $this->getEditForm($record->ID); - $actionList = ''; - foreach($tempForm->Actions() as $action) { - $actionList .= $action->Field() . ' '; - } - - FormResponse::add("$('Form_EditForm').loadActionsFromString('" . Convert::raw2js($actionList) . "');"); - - return FormResponse::respond(); - } - - /** - * Return JavaScript code to generate a tree node for the given page, if visible - */ - public function addTreeNodeJS($page, $select = false) { - $parentID = (int)$page->ParentID; - $title = Convert::raw2js($page->TreeTitle()); - $response = <<ID, "$title", "$page->class"); -var parentNode = $('sitetree').getTreeNodeByIdx($parentID); -if(parentNode) parentNode.appendTreeNode(newNode); -JS; - $response .= ($select ? "newNode.selectTreeNode();\n" : "") ; - FormResponse::add($response); - return FormResponse::respond(); - } - /** - * Return JavaScript code to remove a tree node for the given page, if it exists. - */ - public function deleteTreeNodeJS($page) { - $id = $page->ID ? $page->ID : $page->OldID; - $response = <<showSingleInstanceOnlyInCreateFieldJS($page)); - return FormResponse::respond(); - } - /** * Sets a static variable on this class which means the panel will be reloaded. */ diff --git a/javascript/LeftAndMain_left.js b/javascript/LeftAndMain_left.js index cebaf55896..be2b23b28a 100755 --- a/javascript/LeftAndMain_left.js +++ b/javascript/LeftAndMain_left.js @@ -329,6 +329,8 @@ SiteTree.prototype = { */ this.observeMethod('SelectionChanged', this.interruptLoading.bind(this) ); + + jQuery('#Form_EditForm').bind('loadnewpage', this.onLoadNewPage.bind(this)); }, destroy: function () { if(this.Tree) this.Tree.destroy(); @@ -344,6 +346,42 @@ SiteTree.prototype = { interruptLoading: function( newLoadingNode ) { if( this.loadingNode ) this.loadingNode.removeNodeClass('loading'); this.loadingNode = newLoadingNode; + }, + + onLoadNewPage: function(e, eventData) { + // finds a certain value in an array generated by jQuery.serializeArray() + var findInSerializedArray = function(arr, name) { + for(var i=0; i"; - } - }, - - /** - * Reload lose the form if the current page is open. - */ - reloadIfSetTo: function(id) { - if(this.elements.ID && this.elements.ID.value == id) { - this.getPageFromServer(id); - } - }, - - close: function() { - this.innerHTML = "

 

"; - var actions; - if(actions = $('form_actions_' + this.formName)) { - actions.parentNode.removeChild(actions); - } - }, - - updateStatus: function( newStatus ) { - - if( $('Form_EditForm_Status') ) - $('Form_EditForm_Status').innerHTML = "STATUS: " + newStatus; - }, - - /** - * Load a new page into the right-hand form. - * - * @param formContent string - * @param response object (optional) - * @param evalResponse boolean (optional) - */ - loadNewPage : function(formContent, response, evalResponse) { - //alert('here: ' + formContent); - var rightHTML = formContent; - - // Rewrite # links - rightHTML = rightHTML.replace(/(]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#'); - - // Rewrite iframe links (for IE) - rightHTML = rightHTML.replace(/(]*src=")([^"]+)("[^>]*>)/g, '$1' + jQuery('base').attr('href') + '$2$3'); - - // Note: TinyMCE coupling - jQuery('#Form_EditForm').concrete('ss').cleanup(); - - // Prepare iframes for removal, otherwise we get loading bugs - var i, allIframes = this.getElementsByTagName('iframe'); - if(allIframes) for(i=0;i