diff --git a/lang/en.yml b/lang/en.yml index 79944a45..49f7b77d 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -80,6 +80,9 @@ en: Published: 'Published {name} {link}' Unpublished: 'Unpublished {name} "{title}"' PUBLISHEDTOASTMESSAGE: 'Published {type} "{title}"' + ROLLEDBACKPERMISSION: 'You do not have permission to roll back this record.' + ROLLEDBACKPUB: 'Rolled back to published version.' + ROLLEDBACKVERSION: 'Rolled back to version #{version}.' SilverStripe\Versioned\VersionedGridFieldState\VersionedGridFieldState: ADDEDTODRAFTHELP: 'Item has not been published yet' ADDEDTODRAFTSHORT: Draft diff --git a/src/VersionedGridFieldItemRequest.php b/src/VersionedGridFieldItemRequest.php index 1b11a56b..324071d0 100644 --- a/src/VersionedGridFieldItemRequest.php +++ b/src/VersionedGridFieldItemRequest.php @@ -4,6 +4,7 @@ use SilverStripe\CMS\Controllers\CMSMain; use SilverStripe\Control\HTTPResponse; +use SilverStripe\Control\PjaxResponseNegotiator; use SilverStripe\Core\Convert; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; @@ -15,6 +16,7 @@ use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\FieldType\DBField; +use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\ORM\ValidationResult; use SilverStripe\View\ArrayData; use SilverStripe\View\SSViewer; @@ -234,6 +236,51 @@ public function doUnpublish($data, $form) return $this->redirectAfterSave(false); } + public function doRollback($data, $form): HTTPResponse|DBHTMLText + { + $version = $this->getRequest()->param('VersionID'); + $this->extend('onBeforeRollback', $data['Version']); + + /** @var Versioned|RecursivePublishable|DataObject $record */ + $record = $this->getRecord(); + + // Check permission + if (!$record->canEdit()) { + return $this->httpError( + 403, + _t( + __CLASS__ . '.ROLLEDBACKPERMISSION', + "You do not have permission to roll back this record." + ) + ); + } + + if ($version) { + $record->rollbackRecursive($version); + $message = _t( + __CLASS__ . '.ROLLEDBACKVERSION', + "Rolled back to version #{version}.", + ['version' => $version] + ); + } else { + $record->doRevertToLive(); + $record->publishRecursive(); + $message = _t( + __CLASS__ . '.ROLLEDBACKPUB', + "Rolled back to published version." + ); + } + + $this->setFormMessage($form, $message); + + $controller = $this->getToplevelController(); + $controller->getResponse()->addHeader('X-ControllerURL', $this->Link('edit')); + $controller->getResponse()->addHeader('X-Pjax', 'Content'); + $controller->getResponse()->addHeader('X-Status', $message); + + return $this->redirectAfterSave(false); + } + /** * @param Form $form * @param string $message @@ -292,7 +339,7 @@ protected function addVersionedButtons(DataObject $record, FieldList $actions) // Get status of the object $isOnDraft = $record->isOnDraft(); $isPublished = $record->isPublished(); - $stagesDiffer = $record->stagesDiffer(); + $stagesDiffer = $record->stagesDiffer || $record->stagesDifferRecursive(); // Check permissions $canPublish = $record->canPublish(); @@ -362,6 +409,18 @@ protected function addVersionedButtons(DataObject $record, FieldList $actions) } } + // "rollback" + if ($isOnDraft && $isPublished && $canEdit && $stagesDiffer) { + $moreOptions->push( + FormAction::create('doRollback', _t(__CLASS__.'.BUTTONCANCELDRAFT', 'Cancel draft changes')) + ->setDescription(_t( + 'SilverStripe\\CMS\\Model\\SiteTree.BUTTONCANCELDRAFTDESC', + 'Delete your draft and revert to the currently published page' + )) + ->addExtraClass('btn-secondary') + ); + } + // "unpublish" action if ($isPublished && $isOnDraft && $canUnpublish) { $actionUnpublish = FormAction::create( diff --git a/src/VersionedGridFieldState/VersionedGridFieldState.php b/src/VersionedGridFieldState/VersionedGridFieldState.php index 65b5dda6..29f5cd1d 100644 --- a/src/VersionedGridFieldState/VersionedGridFieldState.php +++ b/src/VersionedGridFieldState/VersionedGridFieldState.php @@ -225,7 +225,7 @@ protected function getStatusFlags($record) ]; } - if ($record->isModifiedOnDraft()) { + if ($record->isModifiedOnDraft() || $record->stagesDifferRecursive()) { return [ 'modified' => [ 'text' => _t(__CLASS__ . '.MODIFIEDONDRAFTSHORT', 'Modified'),