Merge pull request #1522 from micmania1/fix-sitetree-rading-stage

This commit is contained in:
micmania1 2016-06-09 15:13:09 +12:00 committed by Daniel Hensby
parent c8976a9d64
commit 5f2d8cae0d
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E

View File

@ -4,29 +4,29 @@
*
* This class creates a 2-frame layout - left-tree and right-form - to sit beneath the main
* admin menu.
*
*
* @package cms
* @subpackage controller
* @todo Create some base classes to contain the generic functionality that will be replicated.
*/
class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionProvider {
private static $url_segment = 'pages';
private static $url_rule = '/$Action/$ID/$OtherID';
// Maintain a lower priority than other administration sections
// so that Director does not think they are actions of CMSMain
private static $url_priority = 39;
private static $menu_title = 'Edit Page';
private static $menu_priority = 10;
private static $tree_class = "SiteTree";
private static $subitem_class = "Member";
/**
* Amount of results showing on a single page.
*
@ -34,7 +34,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* @var int
*/
private static $page_length = 15;
private static $allowed_actions = array(
'archive',
'buildbrokenlinks',
@ -71,14 +71,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) {
Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages('SiteTree')));
}
parent::init();
Versioned::reading_stage("Stage");
Requirements::css(CMS_DIR . '/css/screen.css');
Requirements::customCSS($this->generatePageIconsCss());
Requirements::combine_files(
'cmsmain.js',
array_merge(
@ -144,7 +144,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function ShowSwitchView() {
return true;
}
/**
* Overloads the LeftAndMain::ShowView. Allows to pass a page as a parameter, so we are able
* to switch view also for archived versions.
@ -153,7 +153,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$page) {
$page = $this->currentPage();
}
if($page) {
$nav = SilverStripeNavigator::get_for_record($page);
return $nav['items'];
@ -305,10 +305,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$this->extend('updateExtraTreeTools', $html);
return $html;
}
/**
* Returns a Form for page searching for use in templates.
*
*
* Can be modified from a decorator by a 'updateSearchForm' method
*
* @return Form
@ -318,7 +318,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$content = new TextField('q[Term]', _t('CMSSearch.FILTERLABELTEXT', 'Content'));
$dateHeader = new HeaderField('q[Date]', _t('CMSSearch.FILTERDATEHEADING', 'Date'), 4);
$dateFrom = new DateField(
'q[LastEditedFrom]',
'q[LastEditedFrom]',
_t('CMSSearch.FILTERDATEFROM', 'From')
);
$dateFrom->setConfig('showcalendar', true);
@ -328,17 +328,17 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
);
$dateTo->setConfig('showcalendar', true);
$pageFilter = new DropdownField(
'q[FilterClass]',
_t('CMSMain.PAGES', 'Pages'),
'q[FilterClass]',
_t('CMSMain.PAGES', 'Pages'),
CMSSiteTreeFilter::get_all_filters()
);
$pageClasses = new DropdownField(
'q[ClassName]',
_t('CMSMain.PAGETYPEOPT', 'Page Type', 'Dropdown for limiting search to a page type'),
'q[ClassName]',
_t('CMSMain.PAGETYPEOPT', 'Page Type', 'Dropdown for limiting search to a page type'),
$this->getPageTypes()
);
$pageClasses->setEmptyString(_t('CMSMain.PAGETYPEANYOPT','Any'));
// Group the Datefields
$dateGroup = new FieldGroup(
$dateHeader,
@ -346,7 +346,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$dateTo
);
$dateGroup->setFieldHolderTemplate('FieldGroup_DefaultFieldHolder')->addExtraClass('stacked');
// Create the Field list
$fields = new FieldList(
$content,
@ -354,7 +354,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$pageFilter,
$pageClasses
);
// Create the Search and Reset action
$actions = new FieldList(
FormAction::create('doSearch', _t('CMSMain_left_ss.APPLY_FILTER', 'Apply Filter'))
@ -366,7 +366,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
foreach($actions->dataFields() as $action) {
$action->setUseButtonTag(true);
}
// Create the form
$form = Form::create($this, 'SearchForm', $fields, $actions)
->addExtraClass('cms-search-form')
@ -374,19 +374,19 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
->setFormAction($this->Link())
->disableSecurityToken()
->unsetValidator();
// Load the form with previously sent search data
$form->loadDataFrom($this->getRequest()->getVars());
// Allow decorators to modify the form
$this->extend('updateSearchForm', $form);
return $form;
}
/**
* Returns a sorted array suitable for a dropdown with pagetypes and their translated name
*
*
* @return array
*/
protected function getPageTypes() {
@ -397,7 +397,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
asort($pageTypes);
return $pageTypes;
}
public function doSearch($data, $form) {
return $this->getsubtree($this->getRequest());
}
@ -506,18 +506,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) continue;
$addAction = $instance->i18n_singular_name();
// Get description (convert 'Page' to 'SiteTree' for correct localization lookups)
$description = _t((($class == 'Page') ? 'SiteTree' : $class) . '.DESCRIPTION');
if(!$description) {
$description = $instance->uninherited('description');
}
if($class == 'Page' && !$description) {
$description = singleton('SiteTree')->uninherited('description');
}
$result->push(new ArrayData(array(
'ClassName' => $class,
'AddAction' => $addAction,
@ -527,9 +527,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'Title' => singleton($class)->i18n_singular_name(),
)));
}
$result = $result->sort('AddAction');
return $result;
}
@ -545,12 +545,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($id instanceof $treeClass) {
return $id;
}
}
else if($id && is_numeric($id)) {
$currentStage = Versioned::get_reading_mode();
if($this->getRequest()->getVar('Version')) {
$versionID = (int) $this->getRequest()->getVar('Version');
}
if($versionID) {
$record = Versioned::get_version($treeClass, $id, $versionID);
} else {
@ -564,9 +566,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
singleton($treeClass)->flushCache();
$record = DataObject::get_by_id($treeClass, $id);
if($record) Versioned::set_reading_mode('');
}
// Then, try getting a deleted record
if(!$record) {
$record = Versioned::get_latest_version($treeClass, $id);
@ -577,19 +578,22 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* we should not check their locale matches the Translatable::get_current_locale,
* here as long as we all the HTTPRequest is init with right locale.
* This bit breaks the all FileIFrameField functions if the field is used in CMS
* and its relevent ajax calles, like loading the tree dropdown for TreeSelectorField.
* and its relevent ajax calles, like loading the tree dropdown for TreeSelectorField.
*/
/* if($record && SiteTree::has_extension('Translatable') && $record->Locale && $record->Locale != Translatable::get_current_locale()) {
$record = null;
}*/
// Set the reading mode back to what it was.
Versioned::set_reading_mode($currentStage);
return $record;
} else if(substr($id,0,3) == 'new') {
return $this->getNewItem($id);
}
}
/**
* @param int $id
* @param FieldList $fields
@ -599,7 +603,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$id) $id = $this->currentPageID();
$form = parent::getEditForm($id);
// TODO Duplicate record fetching (see parent implementation)
$record = $this->getRecord($id);
if($record && !$record->canView()) return Security::permissionFailure($this);
@ -626,14 +630,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if($stageLink) $stageLinkField->setValue($stageLink);
}
}
// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
if(in_array('CMSPreviewable', class_implements($record)) && !$fields->fieldByName('SilverStripeNavigator')) {
$navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator());
$navField->setAllowHTML(true);
$fields->push($navField);
}
// getAllCMSActions can be used to completely redefine the action list
if($record->hasMethod('getAllCMSActions')) {
$actions = $record->getAllCMSActions();
@ -656,14 +660,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// Use <button> to allow full jQuery UI styling
$actionsFlattened = $actions->dataFields();
if($actionsFlattened) foreach($actionsFlattened as $action) $action->setUseButtonTag(true);
if($record->hasMethod('getCMSValidator')) {
$validator = $record->getCMSValidator();
} else {
$validator = new RequiredFields();
}
$form = CMSForm::create(
$form = CMSForm::create(
$this, "EditForm", $fields, $actions, $validator
)->setHTMLID('Form_EditForm');
$form->setResponseNegotiator($this->getResponseNegotiator());
@ -747,7 +751,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
->addHeader('Content-Type', 'application/json; charset=utf-8')
->setBody(Convert::raw2json($disallowedChildren));
}
/**
* Safely reconstruct a selected filter from a given set of query parameters
*
@ -768,7 +772,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* Returns the pages meet a certain criteria as {@see CMSSiteTreeFilter} or the subpages of a parent page
* defaulting to no filter and show all pages in first level.
* Doubles as search results, if any search parameters are set through {@link SearchForm()}.
*
*
* @param array $params Search filter criteria
* @param int $parentID Optional parent node to filter on (can't be combined with other search criteria)
* @return SS_List
@ -783,7 +787,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $list->filter("ParentID", $parentID);
}
}
public function ListViewForm() {
$params = $this->getRequest()->requestVar('q');
$list = $this->getList($params, $parentID = $this->getRequest()->requestVar('ParentID'));
@ -830,7 +834,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return sprintf(
'<a class="cms-panel-link list-children-link" data-pjax-target="ListViewForm,Breadcrumbs" href="%s">%s</a>',
Controller::join_links(
$controller->Link(),
$controller->Link(),
sprintf("?ParentID=%d&view=list", (int)$item->ID)
),
$num
@ -848,8 +852,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
);
}
));
$listview = CMSForm::create(
$listview = CMSForm::create(
$this,
'ListViewForm',
new FieldList($gridField),
@ -859,14 +863,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$listview->setResponseNegotiator($this->getResponseNegotiator());
$this->extend('updateListView', $listview);
$listview->disableSecurityToken();
return $listview;
}
public function currentPageID() {
$id = parent::currentPageID();
$this->extend('updateCurrentPageID', $id);
// Fall back to homepage record
@ -877,10 +881,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
));
if($homepageRecord) $id = $homepageRecord->ID;
}
return $id;
}
//------------------------------------------------------------------------------------------//
// Data saving handlers
@ -900,7 +904,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!singleton($this->stat('tree_class'))->canCreate()) return Security::permissionFailure($this);
$record = $this->getNewItem($id, false);
}
// TODO Coupling to SiteTree
$record->HasBrokenLink = 0;
$record->HasBrokenFile = 0;
@ -921,11 +925,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
// save form data into record
$form->saveInto($record);
$record->write();
// If the 'Save & Publish' button was clicked, also publish the page
if (isset($data['publish']) && $data['publish'] == 1) {
$record->doPublish();
}
}
return $this->getResponseNegotiator()->respond($this->getRequest());
}
@ -944,7 +948,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
}
throw new SS_HTTPResponse_Exception($response);
}
$newItem = new $className();
if( !$suffix ) {
@ -977,25 +981,25 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
# Some modules like subsites add extra fields that need to be set when the new item is created
$this->extend('augmentNewSiteTreeItem', $newItem);
return $newItem;
}
/**
* Delete the page from live. This means a page in draft mode might still exist.
*
*
* @see delete()
*/
public function deletefromlive($data, $form) {
Versioned::reading_stage('Live');
$record = DataObject::get_by_id("SiteTree", $data['ID']);
if($record && !($record->canDelete() && $record->canDeleteFromLive())) return Security::permissionFailure($this);
$descRemoved = '';
$descendantsRemoved = 0;
$recordTitle = $record->Title;
$recordID = $record->ID;
// before deleting the records, get the descendants of this tree
if($record) {
$descendantIDs = $record->getDescendantIDList();
@ -1016,8 +1020,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(isset($descendantsRemoved)) {
$descRemoved = ' ' . _t(
'CMSMain.DESCREMOVED',
'and {count} descendants',
'CMSMain.DESCREMOVED',
'and {count} descendants',
array('count' => $descendantsRemoved)
);
} else {
@ -1028,13 +1032,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'X-Status',
rawurlencode(
_t(
'CMSMain.REMOVED',
'CMSMain.REMOVED',
'Deleted \'{title}\'{description} from live site',
array('title' => $recordTitle, 'description' => $descRemoved)
)
)
);
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
return $this->getResponseNegotiator()->respond($this->getRequest());
}
@ -1044,7 +1048,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*/
public function performPublish($record) {
if($record && !$record->canPublish()) return Security::permissionFailure($this);
$record->doPublish();
}
@ -1052,12 +1056,12 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* Reverts a page by publishing it to live.
* Use {@link restorepage()} if you want to restore a page
* which was deleted from draft without publishing.
*
*
* @uses SiteTree->doRevertToLive()
*/
public function revert($data, $form) {
if(!isset($data['ID'])) return new SS_HTTPResponse("Please pass an ID in the form content", 400);
$id = (int) $data['ID'];
$restoredPage = Versioned::get_latest_version("SiteTree", $id);
if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400);
@ -1072,7 +1076,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
$record->doRevertToLive();
$this->response->addHeader(
'X-Status',
rawurlencode(_t(
@ -1085,7 +1089,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $this->getResponseNegotiator()->respond($this->getRequest());
}
/**
* Delete the current page from draft stage.
* @see deletefromlive()
@ -1104,7 +1108,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'X-Status',
rawurlencode(sprintf(_t('CMSMain.REMOVEDPAGEFROMDRAFT',"Removed '%s' from the draft site"), $record->Title))
);
// Even if the record has been deleted from stage and live, it can be viewed in "archive mode"
return $this->getResponseNegotiator()->respond($this->getRequest());
}
@ -1139,19 +1143,19 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function publish($data, $form) {
$data['publish'] = '1';
return $this->save($data, $form);
}
public function unpublish($data, $form) {
$className = $this->stat('tree_class');
$record = DataObject::get_by_id($className, $data['ID']);
if($record && !$record->canDeleteFromLive()) return Security::permissionFailure($this);
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404);
$record->doUnpublish();
$this->response->addHeader(
'X-Status',
rawurlencode(_t('CMSMain.REMOVEDPAGE',"Removed '{title}' from the published site", array('title' => $record->Title)))
@ -1180,13 +1184,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
*/
public function doRollback($data, $form) {
$this->extend('onBeforeRollback', $data['ID']);
$id = (isset($data['ID'])) ? (int) $data['ID'] : null;
$version = (isset($data['Version'])) ? (int) $data['Version'] : null;
$record = DataObject::get_by_id($this->stat('tree_class'), $id);
if($record && !$record->canEdit()) return Security::permissionFailure($this);
if($version) {
$record->doRollbackTo($version);
$message = _t(
@ -1202,7 +1206,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
}
$this->response->addHeader('X-Status', rawurlencode($message));
// Can be used in different contexts: In normal page edit view, in which case the redirect won't have any effect.
// Or in history view, in which case a revert causes the CMS to re-load the edit view.
// The X-Pjax header forces a "full" content refresh on redirect.
@ -1220,7 +1224,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function batchactions() {
return new CMSBatchActionHandler($this, 'batchactions');
}
public function BatchActionParameters() {
$batchActions = CMSBatchActionHandler::config()->batch_actions;
@ -1238,7 +1242,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$pageHtml = '';
foreach($forms as $urlSegment => $html) {
$pageHtml .= "<div class=\"params\" id=\"BatchActionParameters_$urlSegment\">$html</div>\n\n";
}
}
return new LiteralField("BatchActionParameters", '<div id="BatchActionParameters" style="display:none">'.$pageHtml.'</div>');
}
/**
@ -1247,14 +1251,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function BatchActionList() {
return $this->batchactions()->batchActionList();
}
public function buildbrokenlinks($request) {
// Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
increase_time_limit_to();
increase_memory_limit_to();
if($this->urlParams['ID']) {
$newPageSet[] = DataObject::get_by_id("Page", $this->urlParams['ID']);
} else {
@ -1289,20 +1293,20 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
increase_time_limit_to();
increase_memory_limit_to();
$response = "";
if(isset($this->requestParams['confirm'])) {
// Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
$start = 0;
$pages = DataObject::get("SiteTree", "", "", "", "$start,30");
$count = 0;
while($pages) {
foreach($pages as $page) {
if($page && !$page->canPublish()) return Security::permissionFailure($this);
$page->doPublish();
$page->destroy();
unset($page);
@ -1334,10 +1338,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
. $tokenHtml .
'</form>';
}
return $response;
}
/**
* Restore a completely deleted page from the SiteTree_versions table.
*/
@ -1345,18 +1349,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!isset($data['ID']) || !is_numeric($data['ID'])) {
return new SS_HTTPResponse("Please pass an ID in the form content", 400);
}
$id = (int)$data['ID'];
$restoredPage = Versioned::get_latest_version("SiteTree", $id);
if(!$restoredPage) return new SS_HTTPResponse("SiteTree #$id not found", 400);
$restoredPage = $restoredPage->doRestoreToStage();
$this->response->addHeader(
'X-Status',
rawurlencode(_t(
'CMSMain.RESTORED',
"Restored '{title}' successfully",
"Restored '{title}' successfully",
array('title' => $restoredPage->Title)
))
);
@ -1367,7 +1371,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
public function duplicate($request) {
// Protect against CSRF on destructive action
if(!SecurityToken::inst()->checkRequest($request)) return $this->httpError(400);
if(($id = $this->urlParams['ID']) && is_numeric($id)) {
$page = DataObject::get_by_id("SiteTree", $id);
if($page && (!$page->canEdit() || !$page->canCreate(null, array('Parent' => $page->Parent())))) {
@ -1376,18 +1380,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
if(!$page || !$page->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
$newPage = $page->duplicate();
// ParentID can be hard-set in the URL. This is useful for pages with multiple parents
if(isset($_GET['parentID']) && is_numeric($_GET['parentID'])) {
$newPage->ParentID = $_GET['parentID'];
$newPage->write();
}
$this->response->addHeader(
'X-Status',
rawurlencode(_t(
'CMSMain.DUPLICATED',
"Duplicated '{title}' successfully",
"Duplicated '{title}' successfully",
array('title' => $newPage->Title)
))
);
@ -1419,7 +1423,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'X-Status',
rawurlencode(_t(
'CMSMain.DUPLICATEDWITHCHILDREN',
"Duplicated '{title}' and children successfully",
"Duplicated '{title}' and children successfully",
array('title' => $newPage->Title)
))
);
@ -1433,7 +1437,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return new SS_HTTPResponse("CMSMain::duplicatewithchildren() Bad ID: '$id'", 400);
}
}
public function providePermissions() {
$title = _t("CMSPagesController.MENUTITLE", LeftAndMain::menu_title_for_class('CMSPagesController'));
return array(