API CHANGE Moved CMSMain/AssetAdmin/SecurityAdmin implementations for getEditForm() and save() to a common parent: LeftAndMain

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92834 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-11-21 03:20:26 +00:00
parent 9d0954e129
commit 45f87288fc
3 changed files with 174 additions and 184 deletions

View File

@ -261,61 +261,11 @@ HTML;
public function currentPage() {
$id = $this->currentPageID();
if($id && is_numeric($id)) {
return DataObject::get_by_id($this->stat('tree_class'), $id);
return DataObject::get_by_id('File', $id);
} else if($id == 'root') {
return singleton($this->stat('tree_class'));
return singleton('File');
}
}
/**
* @return Form
*/
function EditForm($request = null) {
return $this->getEditForm();
}
/**
* Return the form that displays the details of a folder, including a file list and fields for editing the folder name.
*/
function getEditForm($id = null) {
if(!$id) $id = $this->currentPageID();
$record = ($id && $id != "root") ? DataObject::get_by_id("File", $id) : null;
if($record && !$record->canView()) return Security::permissionFailure($this);
if($record) {
$fields = $record->getCMSFields();
// Required for file tree setup
if(!$fields->dataFieldByName('ParentID')) $fields->push(new HiddenField('ParentID'));
$actions = new FieldSet();
// Only show save button if not 'assets' folder
if($record->canEdit() && $id != 'root') {
$actions = new FieldSet(
new FormAction('save',_t('AssetAdmin.SAVEFOLDERNAME','Save folder name'))
);
}
$form = new Form($this, "EditForm", $fields, $actions);
if($record->ID) {
$form->loadDataFrom($record);
} else {
$form->loadDataFrom(array(
"ID" => "root",
"URL" => Director::absoluteBaseURL() . 'assets/',
));
}
if(!$record->canEdit()) {
$form->makeReadonly();
}
} else {
$form = $this->EmptyForm();
}
return $form;
}
/**
* Return the entire site tree as a nested UL.
@ -377,7 +327,7 @@ HTML;
* @return Form
*/
function AddForm() {
$typeMap = array('Folder' => singleton('Folder')->i18n_singular_name());
$typeMap = array('Folder' => singleton($this->stat('tree_class'))->i18n_singular_name());
$typeField = new DropdownField('Type', false, $typeMap, 'Folder');
$form = new Form(
$this,
@ -451,19 +401,7 @@ HTML;
return $form;
}
public function save($urlParams, $form) {
// Don't save the root folder - there's no database record
if($_REQUEST['ID'] == 'root') {
FormResponse::status_message('Saved', 'good');
return FormResponse::respond();
}
$form->dataFieldByName('Title')->value = $form->dataFieldByName('Name')->value;
return parent::save($urlParams, $form);
}
/**
* #################################
* Garbage collection.

View File

@ -309,13 +309,6 @@ JS;
}
}
/**
* @return Form
*/
function EditForm($request = null) {
return $this->getEditForm();
}
/**
* Calls {@link SiteTree->getCMSFields()}
*/
@ -323,16 +316,16 @@ JS;
// Include JavaScript to ensure HtmlEditorField works.
HtmlEditorField::include_js();
if(!$id) $id = $this->currentPageID();
$record = ($id) ? $this->getRecord($id) : null;
if($record && !$record->canView()) return Security::permissionFailure($this);
$form = parent::getEditForm($id);
// TODO Duplicate record fetching (see parent implementation)
if(!$id) $id = $this->currentPageID();
$record = ($id && $id != "root") ? DataObject::get_by_id($this->stat('tree_class'), $id) : null;
$fields = $form->Fields();
$actions = $form->Actions();
if($record) {
$fields = $record->getCMSFields($this);
if ($fields == null) {
user_error("getCMSFields returned null on a '".get_class($record)."' object - it should return a FieldSet object. Perhaps you forgot to put a return statement at the end of your method?", E_USER_ERROR);
}
$fields->push($idField = new HiddenField("ID", false, $id));
$fields->push($liveURLField = new HiddenField("LiveURLSegment"));
$fields->push($stageURLField = new HiddenField("StageURLSegment"));
@ -349,47 +342,15 @@ JS;
$stageURLField->setValue($record->AbsoluteLink());
}
// getAllCMSActions can be used to completely redefine the action list
if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions();
} else {
$actions = $record->getCMSActions();
// add default actions if none are defined
if(!$actions || !$actions->Count()) {
if($record->canEdit()) {
$actions->push(new FormAction('save',_t('CMSMain.SAVE','Save')));
$actions->push($deleteAction = new FormAction('delete',_t('CMSMain.DELETE','Delete from the draft site')));
$deleteAction->addExtraClass('delete');
}
}
}
$deleteAction = new FormAction(
'delete',
_t('CMSMain.DELETE','Delete from the draft site')
);
$deleteAction->addExtraClass('delete');
$actions->insertBefore($deleteAction, 'action_save');
$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
// be included properly if the associated fields are loaded
// through ajax. This means only serverside validation
// will kick in for pages+validation loaded through ajax.
// This will be solved by using less obtrusive javascript validation
// in the future, see http://open.silverstripe.com/ticket/2915 and http://open.silverstripe.com/ticket/3386
if($record->hasMethod('getCMSValidator')) {
$validator = $record->getCMSValidator();
// 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->setValidator($validator);
} else {
$form->unsetValidator();
}
if(!$record->canEdit() || $record->IsDeletedFromStage) {
$readonlyFields = $form->Fields()->makeReadonly();
$form->setFields($readonlyFields);
if($record->IsDeletedFromStage) {
$form->makeReadonly();
}
} elseif ($id == 0) {
$siteConfig = SiteConfig::current_site_config();
@ -406,6 +367,89 @@ JS;
//------------------------------------------------------------------------------------------//
// Data saving handlers
/**
* Save and Publish page handler
*/
public function save($data, $form) {
$className = $this->stat('tree_class');
// Existing or new record?
$SQL_id = Convert::raw2sql($data['ID']);
if(substr($SQL_id,0,3) != 'new') {
$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);
}
// TODO Coupling to SiteTree
$record->HasBrokenLink = 0;
$record->HasBrokenFile = 0;
$record->writeWithoutVersion();
// 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);
}
// 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));
}
// If the 'Save & Publish' button was clicked, also publish the page
if (isset($data['publish']) && $data['publish'] == 1) {
$record->doPublish();
// Update classname with original and get new instance (see above for explanation)
$record->setClassName($data['ClassName']);
$publishedRecord = $record->newClassInstance($record->ClassName);
$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
)
);
$form->loadDataFrom($publishedRecord);
} else {
$this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP'));
// write process might've changed the record, so we reload before returning
$form->loadDataFrom($record);
}
return $form->formHtmlContent();
}
public function doAdd($data, $form) {
$className = isset($data['PageType']) ? $data['PageType'] : "Page";

View File

@ -534,7 +534,7 @@ class LeftAndMain extends Controller {
}
/**
* Save and Publish page handler
* Save handler
*/
public function save($data, $form) {
$className = $this->stat('tree_class');
@ -549,71 +549,15 @@ class LeftAndMain extends Controller {
$record = $this->getNewItem($SQL_id, false);
}
// TODO Coupling to SiteTree
$record->HasBrokenLink = 0;
$record->HasBrokenFile = 0;
$record->writeWithoutVersion();
// 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);
}
// 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));
}
$this->extend('onAfterSave', $record);
// If the 'Save & Publish' button was clicked, also publish the page
if (isset($data['publish']) && $data['publish'] == 1) {
$record->doPublish();
$this->extend('onAfterSave', $record);
// Update classname with original and get new instance (see above for explanation)
$record->setClassName($data['ClassName']);
$publishedRecord = $record->newClassInstance($record->ClassName);
$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
)
);
$form->loadDataFrom($publishedRecord);
} else {
$this->extend('onAfterSave', $record);
$this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP'));
// write process might've changed the record, so we reload before returning
$form->loadDataFrom($record);
}
$this->response->addHeader('X-Status', _t('LeftAndMain.SAVEDUP'));
// write process might've changed the record, so we reload before returning
$form->loadDataFrom($record);
return $form->formHtmlContent();
}
@ -790,10 +734,74 @@ JS;
* Form might be readonly if the current user doesn't have the permission to edit
* the record.
*/
/**
* @return Form
*/
function EditForm($request = null) {
return $this->EmptyForm();
return $this->getEditForm();
}
public function getEditForm($id = null) {
if(!$id) $id = $this->currentPageID();
$record = ($id && $id != "root") ? DataObject::get_by_id($this->stat('tree_class'), $id) : null;
if($record && !$record->canView()) return Security::permissionFailure($this);
if($record) {
$fields = $record->getCMSFields();
if ($fields == null) {
user_error(
"getCMSFields() returned null - it should return a FieldSet object.
Perhaps you forgot to put a return statement at the end of your method?",
E_USER_ERROR
);
}
if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions();
} else {
$actions = $record->getCMSActions();
// add default actions if none are defined
if(!$actions || !$actions->Count()) {
if($record->canEdit()) {
$actions->push(new FormAction('save',_t('CMSMain.SAVE','Save')));
}
}
}
$form = new Form($this, "EditForm", $fields, $actions);
$form->loadDataFrom($record);
// Add a default or custom validator.
// @todo Currently the default Validator.js implementation
// adds javascript to the document body, meaning it won't
// be included properly if the associated fields are loaded
// through ajax. This means only serverside validation
// will kick in for pages+validation loaded through ajax.
// This will be solved by using less obtrusive javascript validation
// in the future, see http://open.silverstripe.com/ticket/2915 and
// http://open.silverstripe.com/ticket/3386
if($record->hasMethod('getCMSValidator')) {
$validator = $record->getCMSValidator();
// 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->setValidator($validator);
} else {
$form->unsetValidator();
}
if(!$record->canEdit()) {
$readonlyFields = $form->Fields()->makeReadonly();
$form->setFields($readonlyFields);
}
} else {
$form = $this->EmptyForm();
}
return $form;
}
/**
* Returns a placeholder form, used by {@link getEditForm()} if no record is selected.
* Our javascript logic always requires a form to be present in the CMS interface.