API Deprecate delete in favour of archive

Remove "delete from live" duplicate action in favour of existing "unpublish" which is more consistent with current terminology
Add pop-up verification to destructive actions
Fix bug preventing side-by-side preview of archived pages
Fix bug in reporting publishing of error pages
Restoring a page without an available parent will restore to root
This commit is contained in:
Damian Mooyman 2015-05-15 11:51:23 +12:00
parent 1f9fc33349
commit b169823a00
15 changed files with 457 additions and 45 deletions

View File

@ -22,21 +22,49 @@ class CMSBatchAction_Publish extends CMSBatchAction {
}
/**
* Un-publish items batch action.
* Unpublish items batch action.
*
* @package cms
* @subpackage batchaction
*/
class CMSBatchAction_Unpublish extends CMSBatchAction {
public function getActionTitle() {
return _t('CMSBatchActions.UNPUBLISH_PAGES', 'Un-publish');
return _t('CMSBatchActions.UNPUBLISH_PAGES', 'Unpublish');
}
public function run(SS_List $pages) {
return $this->batchaction($pages, 'doUnpublish',
_t('CMSBatchActions.UNPUBLISHED_PAGES', 'Un-published %d pages')
_t('CMSBatchActions.UNPUBLISHED_PAGES', 'Unpublished %d pages')
);
}
public function applicablePages($ids) {
return $this->applicablePagesHelper($ids, 'canDeleteFromLive', false, true);
}
}
/**
* Archives a page, removing it from both live and stage
*
* @package cms
* @subpackage batchaction
*/
class CMSBatchAction_Archive extends CMSBatchAction {
public function getActionTitle() {
return _t('CMSBatchActions.ARCHIVE', 'Archive');
}
public function run(SS_List $pages) {
return $this->batchaction($pages, 'doArchive',
_t('CMSBatchActions.ARCHIVED_PAGES', 'Archived %d pages')
);
}
public function applicablePages($ids) {
return $this->applicablePagesHelper($ids, 'canArchive', true, true);
}
}
/**
@ -44,6 +72,7 @@ class CMSBatchAction_Unpublish extends CMSBatchAction {
*
* @package cms
* @subpackage batchaction
* @deprecated since version 4.0
*/
class CMSBatchAction_Delete extends CMSBatchAction {
public function getActionTitle() {
@ -51,6 +80,7 @@ class CMSBatchAction_Delete extends CMSBatchAction {
}
public function run(SS_List $pages) {
Deprecation::notice('4.0', 'Delete is deprecated. Use Archive instead');
$status = array(
'modified'=>array(),
'deleted'=>array(),
@ -93,14 +123,15 @@ class CMSBatchAction_Delete extends CMSBatchAction {
*
* @package cms
* @subpackage batchaction
* @deprecated since version 4.0
*/
class CMSBatchAction_DeleteFromLive extends CMSBatchAction {
public function getActionTitle() {
return _t('CMSBatchActions.DELETE_PAGES', 'Delete from published site');
}
public function run(SS_List $pages) {
Deprecation::notice('4.0', 'Delete From Live is deprecated. Use Unpublish instead');
$status = array(
'modified'=>array(),
'deleted'=>array()

View File

@ -36,6 +36,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
private static $page_length = 15;
private static $allowed_actions = array(
'archive',
'buildbrokenlinks',
'deleteitems',
'DeleteItemsForm',
@ -56,6 +57,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'ListViewForm',
'childfilter',
);
/**
* Enable legacy batch actions.
* @deprecated since version 4.0
* @var array
* @config
*/
private static $enabled_legacy_actions = array();
public function init() {
// set reading lang
@ -88,8 +97,24 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
CMSBatchActionHandler::register('publish', 'CMSBatchAction_Publish');
CMSBatchActionHandler::register('unpublish', 'CMSBatchAction_Unpublish');
CMSBatchActionHandler::register('delete', 'CMSBatchAction_Delete');
CMSBatchActionHandler::register('deletefromlive', 'CMSBatchAction_DeleteFromLive');
// Check legacy actions
$legacy = $this->config()->enabled_legacy_actions;
// Delete from live is unnecessary since we have unpublish which does the same thing
if(in_array('CMSBatchAction_DeleteFromLive', $legacy)) {
Deprecation::notice('4.0', 'Delete From Live is deprecated. Use Un-publish instead');
CMSBatchActionHandler::register('deletefromlive', 'CMSBatchAction_DeleteFromLive');
}
// Delete action
if(in_array('CMSBatchAction_Delete', $legacy)) {
Deprecation::notice('4.0', 'Delete from Stage is deprecated. Use Archive instead.');
CMSBatchActionHandler::register('delete', 'CMSBatchAction_Delete');
} else {
CMSBatchActionHandler::register('archive', 'CMSBatchAction_Archive');
}
}
public function index($request) {
@ -1059,13 +1084,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
* @see deletefromlive()
*/
public function delete($data, $form) {
Deprecation::notice('4.0', 'Delete from stage is deprecated. Use archive instead');
$id = $data['ID'];
$record = DataObject::get_by_id("SiteTree", $id);
if($record && !$record->canDelete()) return Security::permissionFailure();
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
// save ID and delete record
$recordID = $record->ID;
// Delete record
$record->delete();
$this->response->addHeader(
@ -1077,6 +1102,34 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
return $this->getResponseNegotiator()->respond($this->getRequest());
}
/**
* Delete this page from both live and stage
*
* @param type $data
* @param type $form
*/
public function archive($data, $form) {
$id = $data['ID'];
$record = DataObject::get_by_id("SiteTree", $id);
if(!$record || !$record->exists()) {
throw new SS_HTTPResponse_Exception("Bad record ID #$id", 404);
}
if(!$record->canArchive()) {
return Security::permissionFailure();
}
// Archive record
$record->doArchive();
$this->response->addHeader(
'X-Status',
rawurlencode(sprintf(_t('CMSMain.ARCHIVEDPAGE',"Archived page '%s'"), $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());
}
public function publish($data, $form) {
$data['publish'] = '1';

View File

@ -286,7 +286,7 @@ class CMSSiteTreeFilter_DeletedPages extends CMSSiteTreeFilter {
protected $numChildrenMethod = 'numHistoricalChildren';
static public function title() {
return _t('CMSSiteTreeFilter_DeletedPages.Title', "All pages, including deleted");
return _t('CMSSiteTreeFilter_DeletedPages.Title', "All pages, including archived");
}
public function getFilteredPages() {
@ -305,7 +305,7 @@ class CMSSiteTreeFilter_DeletedPages extends CMSSiteTreeFilter {
class CMSSiteTreeFilter_ChangedPages extends CMSSiteTreeFilter {
static public function title() {
return _t('CMSSiteTreeFilter_ChangedPages.Title', "Changed pages");
return _t('CMSSiteTreeFilter_ChangedPages.Title', "Modified pages");
}
public function getFilteredPages() {
@ -354,7 +354,7 @@ class CMSSiteTreeFilter_StatusRemovedFromDraftPages extends CMSSiteTreeFilter {
class CMSSiteTreeFilter_StatusDraftPages extends CMSSiteTreeFilter {
static public function title() {
return _t('CMSSiteTreeFilter_StatusDraftPages.Title', 'Draft unpublished pages');
return _t('CMSSiteTreeFilter_StatusDraftPages.Title', 'Draft pages');
}
/**
@ -393,7 +393,7 @@ class CMSSiteTreeFilter_StatusDeletedPages extends CMSSiteTreeFilter {
protected $numChildrenMethod = 'numHistoricalChildren';
static public function title() {
return _t('CMSSiteTreeFilter_StatusDeletedPages.Title', 'Deleted pages');
return _t('CMSSiteTreeFilter_StatusDeletedPages.Title', 'Archived pages');
}
/**

View File

@ -119,7 +119,7 @@ class ContentController extends Controller {
|| (Versioned::current_stage() && Versioned::current_stage() != 'Live')
)
) {
if(!$this->dataRecord->canViewStage(Versioned::current_archived_date() ? 'Stage' : Versioned::current_stage())) {
if(!$this->dataRecord->canView()) {
Session::clear('currentStage');
Session::clear('archiveDate');

View File

@ -260,6 +260,7 @@ class ErrorPage extends Page {
$this->response->addHeader('X-Status', rawurlencode($fileErrorText));
return $this->httpError(405);
}
return true;
}
/**

View File

@ -509,7 +509,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
*/
public function RelativeLink($action = null) {
if($this->ParentID && self::config()->nested_urls) {
$base = $this->Parent()->RelativeLink($this->URLSegment);
$parent = $this->Parent();
// If page is removed select parent from version history (for archive page view)
if((!$parent || !$parent->exists()) && $this->IsDeletedFromStage) {
$parent = Versioned::get_latest_version('SiteTree', $this->ParentID);
}
$base = $parent->RelativeLink($this->URLSegment);
} elseif(!$action && $this->URLSegment == RootURLController::get_homepage_link()) {
// Unset base for root-level homepages.
// Note: Homepages with action parameters (or $action === true)
@ -2298,20 +2303,50 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if($this->canDelete() && $this->canDeleteFromLive()) {
// "delete from live"
$majorActions->push(
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))->addExtraClass('ss-ui-action-destructive')
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))
->addExtraClass('ss-ui-action-destructive')
);
}
} else {
// Determine if we should force a restore to root (where once it was a subpage)
$restoreToRoot = $this->isParentArchived();
// "restore"
$title = $restoreToRoot
? _t('CMSMain.RESTORE_TO_ROOT','Restore draft at top level')
: _t('CMSMain.RESTORE','Restore draft');
$description = $restoreToRoot
? _t('CMSMain.RESTORE_TO_ROOT_DESC','Restore the archived version to draft as a top level page')
: _t('CMSMain.RESTORE_DESC', 'Restore the archived version to draft');
$majorActions->push(
FormAction::create('restore',_t('CMSMain.RESTORE','Restore'))->setAttribute('data-icon', 'decline')
FormAction::create('restore', $title)
->setDescription($description)
->setAttribute('data-to-root', $restoreToRoot)
->setAttribute('data-icon', 'decline')
);
}
} else {
if($this->canDelete()) {
// "delete"
// Detect use of legacy actions
// {@see CMSMain::enabled_legacy_actions}
$legacy = CMSMain::config()->enabled_legacy_actions;
if(in_array('CMSBatchAction_Delete', $legacy)) {
Deprecation::notice('4.0', 'Delete from Stage is deprecated. Use Archive instead.');
if($this->canDelete()) {
// delete
$moreOptions->push(
FormAction::create('delete',_t('CMSMain.DELETE','Delete draft'))
->addExtraClass('delete ss-ui-action-destructive')
);
}
} elseif($this->canArchive()) {
// "archive"
$moreOptions->push(
FormAction::create('delete',_t('CMSMain.DELETE','Delete draft'))->addExtraClass('delete ss-ui-action-destructive')
FormAction::create('archive',_t('CMSMain.ARCHIVE','Archive'))
->setDescription(_t(
'SiteTree.BUTTONARCHIVEDESC',
'Unpublish and send to archive'
))
->addExtraClass('delete ss-ui-action-destructive')
);
}
@ -2353,6 +2388,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
*
* @uses SiteTreeExtension->onBeforePublish()
* @uses SiteTreeExtension->onAfterPublish()
* @return bool True if published
*/
public function doPublish() {
if (!$this->canPublish()) return false;
@ -2461,6 +2497,22 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
}
$this->invokeWithExtensions('onAfterRevertToLive', $this);
return true;
}
/**
* Determine if this page references a parent which is archived, and not available in stage
*
* @return bool True if there is an archived parent
*/
protected function isParentArchived() {
if($parentID = $this->ParentID) {
$parentPage = Versioned::get_latest_version("SiteTree", $parentID);
if(!$parentPage || $parentPage->IsDeletedFromStage) {
return true;
}
}
return false;
}
/**
@ -2469,6 +2521,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return self
*/
public function doRestoreToStage() {
// Ensure that the parent page is restored, otherwise restore to root
if($this->isParentArchived()) {
$this->ParentID = 0;
}
// if no record can be found on draft stage (meaning it has been "deleted from draft" before),
// create an empty record
if(!DB::prepared_query("SELECT \"ID\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($this->ID))->value()) {
@ -2496,6 +2553,50 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
return $result;
}
/**
* Removes the page from both live and stage
*
* @return bool Success
*/
public function doArchive() {
if($this->doUnpublish()) {
$this->delete();
return true;
}
return false;
}
/**
* Check if the current user is allowed to archive this page.
* If extended, ensure that both canDelete and canDeleteFromLive are extended also
*
* @param Member $member
* @return bool
*/
public function canArchive($member = null) {
if(!$member) {
$member = Member::currentUser();
}
// Standard mechanism for accepting permission changes from extensions
$extended = $this->extendedCan('canArchive', $member);
if($extended !== null) {
return $extended;
}
// Check if this page can be deleted
if(!$this->canDelete($member)) {
return false;
}
// If published, check if we can delete from live
if($this->ExistsOnLive && !$this->canDeleteFromLive($member)) {
return false;
}
return true;
}
/**
* Synonym of {@link doUnpublish}
*/
@ -2689,9 +2790,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
'title' => _t('SiteTree.REMOVEDFROMDRAFTHELP', 'Page is published, but has been deleted from draft'),
);
} else {
$flags['deletedonlive'] = array(
'text' => _t('SiteTree.DELETEDPAGESHORT', 'Deleted'),
'title' => _t('SiteTree.DELETEDPAGEHELP', 'Page is no longer published'),
$flags['archived'] = array(
'text' => _t('SiteTree.ARCHIVEDPAGESHORT', 'Archived'),
'title' => _t('SiteTree.ARCHIVEDPAGEHELP', 'Page is removed from draft and live'),
);
}
} else if($this->IsAddedToStage) {

View File

@ -276,6 +276,116 @@
}
});
/**
* Class: .cms-edit-form .Actions #Form_EditForm_action_archive
*
* Informing the user about the archive action while requiring confirmation
*/
$('.cms-edit-form .Actions #Form_EditForm_action_archive').entwine({
/**
* Function: onclick
*
* Parameters:
* (Event) e
*/
onclick: function(e) {
var form = this.parents('form:first'), version = form.find(':input[name=Version]').val(), message = '';
message = ss.i18n.sprintf(
ss.i18n._t('CMSMain.Archive'),
version
);
if(confirm(message)) {
return this._super(e);
} else {
return false;
}
}
});
/**
* Class: .cms-edit-form .Actions #Form_EditForm_action_restore
*
* Informing the user about the archive action while requiring confirmation
*/
$('.cms-edit-form .Actions #Form_EditForm_action_restore').entwine({
/**
* Function: onclick
*
* Parameters:
* (Event) e
*/
onclick: function(e) {
var form = this.parents('form:first'),
version = form.find(':input[name=Version]').val(),
message = '',
toRoot = this.data('toRoot');
message = ss.i18n.sprintf(
ss.i18n._t(toRoot ? 'CMSMain.RestoreToRoot' : 'CMSMain.Restore'),
version
);
if(confirm(message)) {
return this._super(e);
} else {
return false;
}
}
});
/**
* Class: .cms-edit-form .Actions #Form_EditForm_action_delete
*
* Informing the user about the delete from draft action while requiring confirmation
*/
$('.cms-edit-form .Actions #Form_EditForm_action_delete').entwine({
/**
* Function: onclick
*
* Parameters:
* (Event) e
*/
onclick: function(e) {
var form = this.parents('form:first'), version = form.find(':input[name=Version]').val(), message = '';
message = ss.i18n.sprintf(
ss.i18n._t('CMSMain.DeleteFromDraft'),
version
);
if(confirm(message)) {
return this._super(e);
} else {
return false;
}
}
});
/**
* Class: .cms-edit-form .Actions #Form_EditForm_action_unpublish
* Informing the user about the unpublish action while requiring confirmation
*/
$('.cms-edit-form .Actions #Form_EditForm_action_unpublish').entwine({
/**
* Function: onclick
*
* Parameters:
* (Event) e
*/
onclick: function(e) {
var form = this.parents('form:first'), version = form.find(':input[name=Version]').val(), message = '';
message = ss.i18n.sprintf(
ss.i18n._t('CMSMain.Unpublish'),
version
);
if(confirm(message)) {
return this._super(e);
} else {
return false;
}
}
});
/**
* Enable save buttons upon detecting changes to content.
* "changed" class is added by jQuery.changetracker.

View File

@ -36,8 +36,13 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
"Tree.ThisPageOnly": "This page only",
"Tree.ThisPageAndSubpages": "This page and subpages",
"Tree.ShowAsList": "Show children as list",
"CMSMain.ConfirmRestoreFromLive": "Do you really want to copy the published content to the draft site?",
"CMSMain.ConfirmRestoreFromLive": "Are you sure you want to revert draft to when the page was last published?",
"CMSMain.RollbackToVersion": "Do you really want to roll back to version #%s of this page?",
"CMSMain.Archive": "Are you sure you want to archive this page?\n\nThe page will be unpublished and sent to the archive.",
"CMSMain.Restore": "Are you sure you want to restore this page from archive?",
"CMSMain.RestoreToRoot": "Are you sure you want to restore this page from archive?\n\nBecause the parent page is not available this will be restored to the top level.",
"CMSMain.Unpublish": "Are you sure you want to remove your page from the published site?\n\nThis page will still be available in the sitetree as draft.",
"CMSMain.DeleteFromDraft": "Are you sure you want to remove your page from the draft site?\n\nThis page will remain on the published site.",
"URLSEGMENT.Edit": "Edit",
"URLSEGMENT.OK": "OK",
"URLSEGMENT.Cancel": "Cancel",

View File

@ -31,8 +31,13 @@
"Tree.ThisPageOnly": "This page only",
"Tree.ThisPageAndSubpages": "This page and subpages",
"Tree.ShowAsList": "Show children as list",
"CMSMain.ConfirmRestoreFromLive": "Do you really want to copy the published content to the draft site?",
"CMSMain.ConfirmRestoreFromLive": "Are you sure you want to revert draft to when the page was last published?",
"CMSMain.RollbackToVersion": "Do you really want to roll back to version #%s of this page?",
"CMSMain.Archive": "Are you sure you want to archive this page?\n\nThe page will be unpublished and sent to the archive.",
"CMSMain.Restore": "Are you sure you want to restore this page from archive?",
"CMSMain.RestoreToRoot": "Are you sure you want to restore this page from archive?\n\nBecause the parent page is not available this will be restored to the top level.",
"CMSMain.Unpublish": "Are you sure you want to remove your page from the published site?\n\nThis page will still be available in the sitetree as draft.",
"CMSMain.DeleteFromDraft": "Are you sure you want to remove your page from the draft site?\n\nThis page will remain on the published site.",
"URLSEGMENT.Edit": "Edit",
"URLSEGMENT.OK": "OK",
"URLSEGMENT.Cancel": "Cancel",

View File

@ -67,8 +67,8 @@ en:
DELETE_PAGES: 'Delete from published site'
PUBLISHED_PAGES: 'Published %d pages, %d failures'
PUBLISH_PAGES: Publish
UNPUBLISHED_PAGES: 'Un-published %d pages'
UNPUBLISH_PAGES: Un-publish
UNPUBLISHED_PAGES: 'Unpublished %d pages'
UNPUBLISH_PAGES: Unpublish
CMSMain:
ACCESS: 'Access to ''{title}'' section'
ACCESS_HELP: 'Allow viewing of the section containing page tree and content. View and edit permissions can be handled through page specific dropdowns, as well as the separate "Content permissions".'
@ -100,8 +100,11 @@ en:
REMOVED: 'Deleted ''{title}''{description} from live site'
REMOVEDPAGE: 'Removed ''{title}'' from the published site'
REMOVEDPAGEFROMDRAFT: 'Removed ''%s'' from the draft site'
RESTORE: Restore
RESTORE: 'Restore draft'
RESTORE_TO_ROOT: 'Restore draft at top level'
RESTORE_TO_ROOT_DESC: 'Restore the archived version to draft as a top level page'
RESTORED: 'Restored ''{title}'' successfully'
RESTORE_DESC: 'Restore the archived version to draft'
ROLLBACK: 'Roll back to this version'
ROLLEDBACKPUBv2: 'Rolled back to published version.'
ROLLEDBACKVERSIONv2: 'Rolled back to version #%d.'
@ -152,11 +155,19 @@ en:
FILTERDATETO: To
FILTERLABELTEXT: Content
CMSSiteTreeFilter_ChangedPages:
Title: 'Changed pages'
Title: 'Modified pages'
CMSSiteTreeFilter_DeletedPages:
Title: 'All pages, including deleted'
Title: 'All pages, including archived'
CMSSIteTreeFilter_PublishedPages:
Title: 'Published pages'
CMSSiteTreeFilter_Search:
Title: 'All pages'
CMSSiteTreeFilter_StatusDeletedPages:
Title: 'Archived pages'
CMSSiteTreeFilter_StatusDraftPages:
Title: 'Draft pages'
CMSSiteTreeFilter_StatusRemovedFromDraftPages:
Title: 'Live but removed from draft'
ContentControl:
NOTEWONTBESHOWN: 'Note: this message will not be shown to your visitors'
ContentController:

View File

@ -35,7 +35,7 @@ So that only high quality changes are seen by our visitors
When I click "More options" in the "#ActionMenus" element
Then I should not see "Unpublish" in the "#ActionMenus_MoreOptions" element
And I should see "Not published" in the "#ActionMenus_MoreOptions" element
And I should see "Delete draft" in the "#ActionMenus_MoreOptions" element
And I should see "Archive" in the "#ActionMenus_MoreOptions" element
And I should see a "Save & publish" button
And I should see a "Saved" button
@ -48,7 +48,7 @@ So that only high quality changes are seen by our visitors
When I press the "Publish" button
And I click "More options" in the "#ActionMenus" element
Then I should see "Unpublish" in the "#ActionMenus_MoreOptions" element
And I should see "Delete draft" in the "#ActionMenus_MoreOptions" element
And I should see "Archive" in the "#ActionMenus_MoreOptions" element
And I should see a "Published" button
And I should see a "Saved" button
@ -64,7 +64,7 @@ So that only high quality changes are seen by our visitors
And I click on "Hello" in the tree
When I click "More options" in the "#ActionMenus" element
And I press the "Unpublish" button
And I press the "Unpublish" button, confirming the dialog
Then I press the "Log out" button
And I go to "/hello"
@ -80,16 +80,16 @@ So that only high quality changes are seen by our visitors
And I click "More options" in the "#ActionMenus" element
Then I should see "Unpublish" in the "#ActionMenus_MoreOptions" element
When I press the "Unpublish" button
When I press the "Unpublish" button, confirming the dialog
And I click "More options" in the "#ActionMenus" element
Then I should see "Delete draft" in the "#ActionMenus_MoreOptions" element
Then I should see "Archive" in the "#ActionMenus_MoreOptions" element
When I press the "Delete draft" button
When I press the "Archive" button, confirming the dialog
Then I should see a "Restore" button
And I should not see a "Published" button
And I should not see a "Save & publish" button
And I should not see a "Saved" button
And I should not see a "Save draft" button
When I press the "Restore" button
When I press the "Restore" button, confirming the dialog
Then I should see a "Save & publish" button

View File

@ -46,7 +46,7 @@ Feature: Search for a page
And the "page" "Deleted Page" is deleted
When I press the "Apply Filter" button
Then I should not see "Deleted Page" in the tree
When I select "All pages, including deleted" from "Pages"
When I select "All pages, including archived" from "Pages"
And I press the "Apply Filter" button
Then I should see "Deleted Page" in the tree
@ -56,7 +56,7 @@ Feature: Search for a page
And the "page" "Deleted Page" is deleted
When I press the "Apply Filter" button
Then I should not see "Deleted Page" in the tree
When I select "Deleted pages" from "Pages"
When I select "Archived pages" from "Pages"
And I press the "Apply Filter" button
Then I should see "Deleted Page" in the tree
And I should not see "About Us" in the tree
@ -66,7 +66,7 @@ Feature: Search for a page
And the "page" "Draft Page" is not published
When I press the "Apply Filter" button
Then I should see "Draft Page" in the tree
When I select "Draft unpublished pages" from "Pages"
When I select "Draft pages" from "Pages"
And I press the "Apply Filter" button
Then I should see "Draft Page" in the tree
And I should not see "About Us" in the tree
@ -81,7 +81,7 @@ Feature: Search for a page
When I go to "/admin/pages"
And I expand the "Filter" CMS Panel
When I select "Changed pages" from "Pages"
When I select "Modified pages" from "Pages"
And I press the "Apply Filter" button
Then I should see "About Us" in the tree
And I should not see "Home" in the tree

View File

@ -0,0 +1,86 @@
<?php
/**
* Tests CMS Specific subclasses of {@see CMSBatchAction}
*/
class CMSBatchActionsTest extends SapphireTest {
protected static $fixture_file = 'CMSBatchActionsTest.yml';
public function setUp() {
parent::setUp();
// published page
$published = $this->objFromFixture('Page', 'published');
$published->doPublish();
// Deleted / archived page
$archived = $this->objFromFixture('Page', 'archived');
$archived->doArchive();
// Unpublished
$unpublished = $this->objFromFixture('Page', 'unpublished');
$unpublished->doPublish();
$unpublished->doUnpublish();
// Modified
$modified = $this->objFromFixture('Page', 'modified');
$modified->doPublish();
$modified->Title = 'modified2';
$modified->write();
}
/**
* Test which pages can be published via batch actions
*/
public function testBatchPublish() {
$this->logInWithPermission('ADMIN');
$pages = Versioned::get_including_deleted('Page');
$ids = $pages->column('ID');
$action = new CMSBatchAction_Publish();
// Test applicable pages
$applicable = $action->applicablePages($ids);
$this->assertContains($this->idFromFixture('Page', 'published'), $applicable);
$this->assertNotContains($this->idFromFixture('Page', 'archived'), $applicable);
$this->assertContains($this->idFromFixture('Page', 'unpublished'), $applicable);
$this->assertContains($this->idFromFixture('Page', 'modified'), $applicable);
}
/**
* Test which pages can be unpublished via batch actions
*/
public function testBatchUnpublish() {
$this->logInWithPermission('ADMIN');
$pages = Versioned::get_including_deleted('Page');
$ids = $pages->column('ID');
$action = new CMSBatchAction_Unpublish();
// Test applicable page
$applicable = $action->applicablePages($ids);
$this->assertContains($this->idFromFixture('Page', 'published'), $applicable);
$this->assertNotContains($this->idFromFixture('Page', 'archived'), $applicable);
$this->assertNotContains($this->idFromFixture('Page', 'unpublished'), $applicable);
$this->assertContains($this->idFromFixture('Page', 'modified'), $applicable);
}
/**
* Test which pages can be published via batch actions
*/
public function testBatchArchive() {
$this->logInWithPermission('ADMIN');
$pages = Versioned::get_including_deleted('Page');
$ids = $pages->column('ID');
$action = new CMSBatchAction_Archive();
// Test applicable pages
$applicable = $action->applicablePages($ids);
$this->assertContains($this->idFromFixture('Page', 'published'), $applicable);
$this->assertNotContains($this->idFromFixture('Page', 'archived'), $applicable);
$this->assertContains($this->idFromFixture('Page', 'unpublished'), $applicable);
$this->assertContains($this->idFromFixture('Page', 'modified'), $applicable);
}
}

View File

@ -0,0 +1,9 @@
Page:
published:
Title: Published
archived:
Title: archived
unpublished:
Title: unpublished
modified:
Title: modified1

View File

@ -4,7 +4,7 @@
* - action_save
* - action_publish
* - action_unpublish
* - action_delete
* - action_archive
* - action_deletefromlive
* - action_rollback
* - action_revert
@ -83,7 +83,7 @@ class SiteTreeActionsTest extends FunctionalTest {
$this->assertNotNull($actions->dataFieldByName('action_save'));
$this->assertNotNull($actions->dataFieldByName('action_publish'));
$this->assertNotNull($actions->dataFieldByName('action_unpublish'));
$this->assertNotNull($actions->dataFieldByName('action_delete'));
$this->assertNotNull($actions->dataFieldByName('action_archive'));
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNull($actions->dataFieldByName('action_rollback'));
$this->assertNull($actions->dataFieldByName('action_revert'));
@ -111,7 +111,7 @@ class SiteTreeActionsTest extends FunctionalTest {
$this->assertNull($actions->dataFieldByName('action_save'));
$this->assertNull($actions->dataFieldByName('action_publish'));
$this->assertNull($actions->dataFieldByName('action_unpublish'));
$this->assertNull($actions->dataFieldByName('action_delete'));
$this->assertNull($actions->dataFieldByName('action_archive'));
$this->assertNotNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNull($actions->dataFieldByName('action_rollback'));
$this->assertNotNull($actions->dataFieldByName('action_revert'));
@ -135,7 +135,7 @@ class SiteTreeActionsTest extends FunctionalTest {
$this->assertNotNull($actions->dataFieldByName('action_save'));
$this->assertNotNull($actions->dataFieldByName('action_publish'));
$this->assertNotNull($actions->dataFieldByName('action_unpublish'));
$this->assertNotNull($actions->dataFieldByName('action_delete'));
$this->assertNotNull($actions->dataFieldByName('action_archive'));
$this->assertNull($actions->dataFieldByName('action_deletefromlive'));
$this->assertNotNull($actions->dataFieldByName('action_rollback'));
$this->assertNull($actions->dataFieldByName('action_revert'));
@ -155,7 +155,7 @@ class SiteTreeActionsTest extends FunctionalTest {
$this->assertNull($actions->dataFieldByName('action_save'));
$this->assertNull($actions->dataFieldByName('action_publish'));
$this->assertNull($actions->dataFieldByName('action_unpublish'));
$this->assertNull($actions->dataFieldByName('action_delete'));
$this->assertNull($actions->dataFieldByName('action_archive'));
$this->assertNotNull($actions->dataFieldByName('action_email'));
$this->assertNotNull($actions->dataFieldByName('action_rollback'));
}