From 3538fc5f15a75eaf69ba0f93e5fb43763a40b311 Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Fri, 24 Nov 2017 12:53:35 +1300 Subject: [PATCH 1/9] Upgrading for ss4 --- README.md | 142 ++--- _config/config.yml | 4 +- code/SinglePageAdmin.php | 463 -------------- composer.json | 9 +- images/singlepageadmin.png | Bin 1252 -> 0 bytes src/SinglePageAdmin.php | 567 ++++++++++++++++++ {code => src}/SinglePageCMSForm.php | 22 +- templates/SinglePageAdmin_Content.ss | 46 +- templates/SinglePageAdmin_EditForm.ss | 65 +- .../SinglePageAdmin_SilverStripeNavigator.ss | 10 +- 10 files changed, 722 insertions(+), 606 deletions(-) delete mode 100644 code/SinglePageAdmin.php delete mode 100755 images/singlepageadmin.png create mode 100644 src/SinglePageAdmin.php rename {code => src}/SinglePageCMSForm.php (56%) diff --git a/README.md b/README.md index 3314826..78f6290 100755 --- a/README.md +++ b/README.md @@ -1,71 +1,71 @@ -# SilverStripe Single Page Administration - -Single page administration via a LeftAndMain like interface. Let your clients edit pages without seeing the site tree. - -## Features - - * Single page administration - * Only allows publish functionality for the page - * You can hide the site tree from everybody (when used in conjunction with silverstripe-catalogmanager) - -## Installation - -Installation via composer - -```bash -$ composer require littlegiant/silverstripe-singlepageadmin -``` - -## How to use - -Simply extend the SinglePageAdmin class instead of ModelAdmin and include the class via the `tree_class` static. - -```php - -class HomePageAdmin extends SinglePageAdmin -{ - private static $menu_title = "Home Page"; - private static $tree_class = 'HomePage'; - private static $url_segment = "home-page"; - -} -``` - -The single page admin assumes you have one and only have one item of the class which you are trying to administrate and -makes no attempt to try and check if this is the case, naively getting the first object which matches. It is up to you -to ensure that the class has one and only one instance created, usually via canCreate() functionality. - -## License - -The MIT License (MIT) - -Copyright (c) 2015 Little Giant Design Ltd - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -## Contributing - - -### Code guidelines - -This project follows the standards defined in: - -* [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) -* [PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) -* [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) +# SilverStripe Single Page Administration + +Single page administration via a LeftAndMain like interface. Let your clients edit pages without seeing the site tree. + +## Features + + * Single page administration + * Only allows publish functionality for the page + * You can hide the site tree from everybody (when used in conjunction with silverstripe-catalogmanager) + +## Installation + +Installation via composer + +```bash +$ composer require littlegiant/silverstripe-singlepageadmin +``` + +## How to use + +Simply extend the SinglePageAdmin class instead of ModelAdmin and include the class via the `tree_class` static. + +```php +use LittleGiant\SilverStripe\SinglePageAdmin\SinglePageAdmin; + +class HomePageAdmin extends SinglePageAdmin +{ + private static $menu_title = "Home Page"; + private static $tree_class = 'HomePage'; + private static $url_segment = "home-page"; +} +``` + +The single page admin assumes you have one and only have one item of the class which you are trying to administrate and +makes no attempt to try and check if this is the case, naively getting the first object which matches. It is up to you +to ensure that the class has one and only one instance created, usually via canCreate() functionality. + +## License + +The MIT License (MIT) + +Copyright (c) 2015 Little Giant Design Ltd + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +## Contributing + + +### Code guidelines + +This project follows the standards defined in: + +* [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) +* [PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) +* [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) diff --git a/_config/config.yml b/_config/config.yml index 8d4c315..40f013a 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -1,9 +1,7 @@ --- Name: catalog-manager -After: 'framework/*','cms/*' --- - -SiteConfig: +SilverStripe\SiteConfig\SiteConfig: required_permission: - SITETREE_VIEW_ALL - SITETREE_EDIT_ALL diff --git a/code/SinglePageAdmin.php b/code/SinglePageAdmin.php deleted file mode 100644 index 64c016c..0000000 --- a/code/SinglePageAdmin.php +++ /dev/null @@ -1,463 +0,0 @@ -" if no permissions are defined here. - * See {@link canView()} for more details on permission checks. - * - * @config - * @var Array Codes which are required from the current user to view this controller. - */ - private static $required_permission_codes; - - /** - * A cached reference to the page record - * @var SiteTree - */ - protected $page; - - - /** - * Initialize requirements for this view - */ - public function init() - { - parent::init(); - Requirements::javascript(CMS_DIR . '/javascript/CMSMain.EditForm.js'); - } - - /** - * Helper function for getting the single page instance, existing or created - * @return SiteTree - */ - protected function findOrMakePage() - { - if ($this->page) { - return $this->page; - } - - $currentStage = Versioned::current_stage(); - Versioned::reading_stage('Stage'); - - $treeClass = $this->config()->get('tree_class'); - $page = $treeClass::get()->first(); - - if (!$page || !$page->exists()) { - $page = $treeClass::create(); - $page->Title = $treeClass; - $page->write(); - $page->doPublish(); - } - - Versioned::reading_stage($currentStage); - - return $this->page = $page; - } - - /** - * @param null $member - * @return bool|int - */ - public function canView($member = null) - { - if(!$member && $member !== false){ - $member = Member::currentUser(); - } - - $codes = array(); - $extraCodes = $this->stat('required_permission_codes'); - - if ($extraCodes !== false) { // allow explicit FALSE to disable subclass check - if ($extraCodes) { - $codes = array_merge($codes, (array)$extraCodes); - } else { - $codes[] = "CMS_ACCESS_$this->class"; - } - } - - - foreach ($codes as $code) { - if (!Permission::checkMember($member, $code)) { - return false; - } - } - - return parent::canView($member); - } - - /** - * @return array - */ - public function providePermissions() - { - $perms = array(); - - // Add any custom SinglePageAdmin subclasses. - foreach (ClassInfo::subclassesFor('SinglePageAdmin') as $i => $class) { - - if ($class == 'SinglePageAdmin') { - continue; - } - - if (ClassInfo::classImplements($class, 'TestOnly')) { - continue; - } - - $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title_for_class($class)); - $perms["CMS_ACCESS_" . $class] = array( - 'name' => _t( - 'CMSMain.ACCESS', - "Access to '{title}' section", - "Item in permission selection identifying the admin section. Example: Access to 'Files & Images'", - array('title' => $title) - ), - 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access') - ); - } - - return $perms; - } - - /** - * @param null $id Not used. - * @param null $fields Not used. - * @return Form - */ - public function getEditForm($id = null, $fields = null) - { - $page = $this->findOrMakePage(); - $fields = $page->getCMSFields(); - - $fields->push(new HiddenField('PreviewURL', 'Preview URL', RootURLController::get_homepage_link())); - $fields->push($navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator())); - $navField->setAllowHTML(true); - - $currentStage = Versioned::current_stage(); - Versioned::reading_stage('Stage'); - - $form = SinglePageCMSForm::create( - $this, - 'EditForm', - $fields, - $this->getCMSActions() - )->setHTMLID('Form_EditForm'); - - if ($page->hasMethod('getCMSValidator')) { - $form->setValidator($page->getCMSValidator()); - } - - if ($form->Fields()->hasTabset()) { - $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); - } - $form - ->setResponseNegotiator($this->getResponseNegotiator()) - ->addExtraClass('cms-content center cms-edit-form') - ->setHTMLID('Form_EditForm') - ->loadDataFrom($page) - ->setTemplate($this->getTemplatesWithSuffix('_EditForm')); - - $this->extend('updateEditForm', $form); - - Versioned::reading_stage($currentStage); - - return $form; - - } - - /** - * Return the edit form - * - * @param null $request - * @return Form - */ - public function EditForm($request = null) - { - return $this->getEditForm(); - } - - /** - * This function is necessary for for some module functionality that relies on the controller having the current - * page ID implemented - * - * @return mixed - */ - public function currentPageID() - { - return $this->findOrMakePage()->ID; - } - - /** - * Used for preview controls, mainly links which switch between different states of the page. - * - * @return ArrayData - */ - public function getSilverStripeNavigator() - { - return $this->renderWith('SinglePageAdmin_SilverStripeNavigator'); - } - - /** - * @return mixed - */ - public function getResponseNegotiator() - { - $neg = parent::getResponseNegotiator(); - $controller = $this; - $neg->setCallback('CurrentForm', function () use (&$controller) { - return $controller->renderWith($controller->getTemplatesWithSuffix('_Content')); - }); - return $neg; - } - - /** - * @return mixed - */ - public function LinkPreview() - { - $page = $this->findOrMakePage(); - $baseLink = ($page && $page instanceof SiteTree) ? $page->Link('?stage=Stage') : Director::absoluteBaseURL(); - return $baseLink; - } - - /** - * @return FieldList - */ - protected function getCMSActions() - { - $page = $this->findOrMakePage(); - $published = $page->isPublished(); - - $actions = FieldList::create(); - $actions->push( - FormAction::create('save', _t('SiteTree.BUTTONSAVED', 'Saved')) - ->setAttribute('data-icon', 'accept') - ->setAttribute('data-icon-alternate', 'addpage') - ->setAttribute('data-text-alternate', _t('CMSMain.SAVEDRAFT', 'Save draft')) - ->setUseButtonTag(true) - ); - - $publish = FormAction::create( - 'publish', - $published ? - _t('SiteTree.BUTTONPUBLISHED', 'Published') : - _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish') - ) - ->setAttribute('data-icon', 'accept') - ->setAttribute('data-icon-alternate', 'disk') - ->setAttribute('data-text-alternate', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish')) - ->setUseButtonTag(true); - - if ($page->stagesDiffer('Stage', 'Live') && $published) { - $publish->addExtraClass('ss-ui-alternate'); - $actions->push( - FormAction::create( - 'rollback', - _t( - 'SiteTree.BUTTONCANCELDRAFT', - 'Cancel draft changes' - ) - ) - ->setDescription( - _t( - 'SiteTree.BUTTONCANCELDRAFTDESC', - 'Delete your draft and revert to the currently published page' - ) - ) - ->setUseButtonTag(true) - ); - } - $actions->push($publish); - - if ($published) { - $actions->push( - FormAction::create( - 'unpublish', - _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish') - ) - ->addExtraClass('ss-ui-action-destructive') - ->setUseButtonTag(true) - ); - } - - $this->extend('updateCMSActions', $actions); - - return $actions; - } - - /** - * @param $data - * @param $form - * @return HTMLText|SS_HTTPResponse|ViewableData_Customised - */ - public function save($data, $form) - { - $currentStage = Versioned::current_stage(); - Versioned::reading_stage('Stage'); - $value = $this->doSave($data, $form); - Versioned::reading_stage($currentStage); - - return $value; - } - - /** - * @param $data - * @param $form - * @return HTMLText|SS_HTTPResponse|ViewableData_Customised - */ - public function publish($data, $form) - { - $data['__publish__'] = true; - - return $this->doSave($data, $form); - } - - /** - * @param $data - * @param $form - * @return mixed - */ - public function doSave($data, $form) - { - $page = $this->findOrMakePage(); - $controller = Controller::curr(); - $publish = isset($data['__publish__']); - - if (!$page->canEdit()) { - return $controller->httpError(403); - } - - try { - $form->saveInto($page); - $page->write(); - if ($publish) { - $page->doPublish(); - } - } catch (ValidationException $e) { - $form->sessionMessage($e->getResult()->message(), 'bad'); - $responseNegotiator = new PjaxResponseNegotiator(array( - 'CurrentForm' => function () use (&$form) { - return $form->forTemplate(); - }, - 'default' => function () use (&$controller) { - return $controller->redirectBack(); - } - )); - if ($controller->getRequest()->isAjax()) { - $controller->getRequest()->addHeader('X-Pjax', 'CurrentForm'); - } - return $responseNegotiator->respond($controller->getRequest()); - } - - $link = '"' . $page->Title . '"'; - $message = _t( - $publish ? 'SinglePageAdmin.Published' : 'GridFieldDetailForm.Saved', - ($publish ? 'Published' : 'Saved') . ' {name} {link}', - array( - 'name' => $page->i18n_singular_name(), - 'link' => $link - ) - ); - - $form->sessionMessage($message, 'good'); - $action = $this->edit(Controller::curr()->getRequest()); - - return $action; - } - - /** - * @return HTMLText|ViewableData_Customised - */ - public function unPublish() - { - $currentStage = Versioned::current_stage(); - Versioned::reading_stage('Live'); - - $page = $this->findOrMakePage(); - - // This way our ID won't be unset - $clone = clone $page; - $clone->delete(); - - Versioned::reading_stage($currentStage); - - return $this->edit(Controller::curr()->getRequest()); - } - - /** - * @param $data - * @param $form - * @return HTMLText|ViewableData_Customised - */ - public function rollback($data, $form) - { - $page = $this->findOrMakePage(); - - if (!$page->canEdit()) { - return Controller::curr()->httpError(403); - } - - $page->doRollbackTo('Live'); - - $this->page = DataList::create($page->class)->byID($page->ID); - - $message = _t( - 'CMSMain.ROLLEDBACKPUBv2', - "Rolled back to published version." - ); - - $form->sessionMessage($message, 'good'); - - return $this->owner->edit(Controller::curr()->getRequest()); - } - - - /** - * @param $request - * @return mixed - */ - public function edit($request) - { - $controller = Controller::curr(); - $form = $this->EditForm($request); - - $return = $this->customise(array( - 'Backlink' => $controller->hasMethod('Backlink') ? $controller->Backlink() : $controller->Link(), - 'EditForm' => $form, - ))->renderWith('SinglePageAdmin_Content'); - - if ($request->isAjax()) { - return $return; - } else { - return $controller->customise(array( - 'Content' => $return, - )); - } - } - -} diff --git a/composer.json b/composer.json index a9a210d..3376a0c 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "littlegiant/silverstripe-singlepageadmin", - "type": "silverstripe-module", + "type": "silverstripe-vendormodule", "description": "Single page administration via a LeftAndMain like interface", "license": "MIT", "authors": [ @@ -8,7 +8,12 @@ "name": "Stevie Mayhew", "email": "stevie@stevie.co.nz", "role": "Developer" + }, + { + "name": "Ryan Potter", + "email": "ryan.potter@littlegiant.co.nz", + "role": "Developer" } ], "minimum-stability": "dev" -} \ No newline at end of file +} diff --git a/images/singlepageadmin.png b/images/singlepageadmin.png deleted file mode 100755 index 8d200aaa35a8958e890eb422f44f3b46fc00cddc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1252 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m=!ZaB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxR5#hc&_u!9QqR!T z(8R(}N5ROz&{*HVSl`fC*U-qyz|zXlQ~?TIxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7KMf<|~|UP^v> zu_jo#udkJ7UU5lcUUI6Zi>(sS0KLr26f0v_150x^CleO~7iU95S7S#<6GIC}V`p;{ z10z=hH%pjam;B_?+|;}hnBEkGUQ?WUK`9}(0BEyIYEfocYKmJ?ey#%8$5xrR-C~5( zJgD9j+-@<(saGH97=2K@BE>UI2$*<4On9mVa^UGcH4m8Bi-4*6yvUm`3=E8so-U3d z6}NgWpVf9r6gmDe{g`Z!kCK?0YHG5xm&Vy+r?~z%d%V%fS)fN=-INI`;ij^{c8~E*i|9fmZusdn~x&NKPa}pJvJmjgGxScgl^!S9sw%aZUefq#!^^A0y_D}#Q;r`IlaE=#a3Jh~{!kN*ejW{Hd6)g{7j zUp>gQt=a0R>J{acidz+Xlb^1>(|Ciayh~f+id$cn^JJ@Yo9fnfZD88=sd3kb>pPCc zi(GjW_|qkXeQMY5#yR%w+Ry)OTEUdbt1G&3BCAb?{-%1P|39pEn>AN|&^^E)&>xeo Tea)^JRPK1X`njxgN@xNA5%9rU diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php new file mode 100644 index 0000000..e59475a --- /dev/null +++ b/src/SinglePageAdmin.php @@ -0,0 +1,567 @@ +" if no permissions are defined here. + * See {@link canView()} for more details on permission checks. + * + * @config + * @var array + */ + private static $required_permission_codes; + + /** + * A cached reference to the page record + * @var SiteTree + */ + protected $page; + + + /** + * Initialize requirements for this view + */ + public function init() + { + parent::init(); + + Requirements::javascript('silverstripe/cms: client/dist/js/bundle.js'); + Requirements::javascript('silverstripe/cms: client/dist/js/SilverStripeNavigator.js'); + Requirements::css('silverstripe/cms: client/dist/styles/bundle.css'); + Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false, true); + + /** + * As of 4.0 all subclasses of LeftAndMain have to have a + * $url_segment as a result of this, we need to hide the + * item from the cms menu. + * + * @TODO: Check if there's a better way of getting around adding a $url_segment - Ryan Potter 24/11/17 + */ + CMSMenu::remove_menu_item('LittleGiant-SilverStripe-SinglePageAdmin-SinglePageAdmin'); + } + + /** + * Helper function for getting the single page instance, existing or created + * @return SiteTree + */ + protected function findOrMakePage() + { + if ($this->page) { + return $this->page; + } + + $currentStage = Versioned::get_stage(); + Versioned::set_stage('Stage'); + + $treeClass = $this->config()->get('tree_class'); + $page = $treeClass::get()->first(); + + if (!$page || !$page->exists()) { + $page = $treeClass::create(); + $page->Title = $treeClass; + $page->write(); + $page->doPublish(); + } + + Versioned::set_stage($currentStage); + + return $this->page = $page; + } + + /** + * @param null $member + * @return bool|int + */ + public function canView($member = null) + { + if (!$member && $member !== false) { + $member = Member::currentUser(); + } + + $codes = []; + $extraCodes = $this->stat('required_permission_codes'); + + if ($extraCodes !== false) { // allow explicit FALSE to disable subclass check + if ($extraCodes) { + $codes = array_merge($codes, (array)$extraCodes); + } else { + $codes[] = "CMS_ACCESS_$this->class"; + } + } + + + foreach ($codes as $code) { + if (!Permission::checkMember($member, $code)) { + return false; + } + } + + return parent::canView($member); + } + + /** + * @return array + */ + public function providePermissions() + { + $perms = []; + + // Add any custom SinglePageAdmin subclasses. + foreach (ClassInfo::subclassesFor('SinglePageAdmin') as $i => $class) { + + if ($class == 'SinglePageAdmin') { + continue; + } + + if (ClassInfo::classImplements($class, 'TestOnly')) { + continue; + } + + $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title_for_class($class)); + $perms["CMS_ACCESS_" . $class] = [ + 'name' => _t( + 'CMSMain.ACCESS', + "Access to '{title}' section", + "Item in permission selection identifying the admin section. Example: Access to 'Files & Images'", + ['title' => $title] + ), + 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'), + ]; + } + + return $perms; + } + + /** + * @param null $id + * @param null $fields + * @return $this|null|\SilverStripe\Forms\Form + */ + public function getEditForm($id = null, $fields = null) + { + $page = $this->findOrMakePage(); + $fields = $page->getCMSFields(); + + $fields->push(new HiddenField('PreviewURL', 'Preview URL', RootURLController::get_homepage_link())); + $fields->push($navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator())); + $navField->setAllowHTML(true); + + $currentStage = Versioned::get_stage(); + Versioned::set_stage('Stage'); + + // Check record exists + if (!$page) { + return $this->EmptyForm(); + } + + // Check if this record is viewable + if ($page && !$page->canView()) { + $response = Security::permissionFailure($this); + $this->setResponse($response); + + return null; + } + + $negotiator = $this->getResponseNegotiator(); + $form = SinglePageCMSForm::create( + $this, + "EditForm", + $fields, + $this->getCMSActions() + )->setHTMLID('Form_EditForm'); + $form->addExtraClass('cms-edit-form'); + $form->loadDataFrom($page); + $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); + $form->setAttribute('data-pjax-fragment', 'CurrentForm'); + $form->setValidationResponseCallback(function (ValidationResult $errors) use ($negotiator, $form) { + $request = $this->getRequest(); + if ($request->isAjax() && $negotiator) { + $result = $form->forTemplate(); + + return $negotiator->respond($request, [ + 'CurrentForm' => function () use ($result) { + return $result; + }, + ]); + } + + return null; + }); + + $this->extend('updateEditForm', $form); + + Versioned::set_stage($currentStage); + + return $form; + + } + + /** + * @param null $request + * @return null|\SilverStripe\Forms\Form|SinglePageAdmin + */ + public function EditForm($request = null) + { + return $this->getEditForm(); + } + + /** + * @desc This function is necessary for for some module functionality that relies on the controller having the current page ID implemented + * @return mixed + */ + public function currentPageID() + { + return $this->findOrMakePage()->ID; + } + + /** + * @desc Used for preview controls, mainly links which switch between different states of the page. + * @return \SilverStripe\ORM\FieldType\DBHTMLText + */ + public function getSilverStripeNavigator() + { + return $this->renderWith('SinglePageAdmin_SilverStripeNavigator'); + } + + /** + * @return mixed + */ + public function getResponseNegotiator() + { + $neg = parent::getResponseNegotiator(); + $controller = $this; + $neg->setCallback('CurrentForm', function () use (&$controller) { + return $controller->renderWith('LittleGiant\SilverStripeSinglePageAdmin\SinglePageAdmin_Content'); + }); + + return $neg; + } + + /** + * @return mixed + */ + public function LinkPreview() + { + $page = $this->findOrMakePage(); + $baseLink = ($page && $page instanceof SiteTree) ? $page->Link('?stage=Stage') : Director::absoluteBaseURL(); + + return $baseLink; + } + + /** + * @return FieldList + * @TODO: classes + */ + protected function getCMSActions() + { + $page = $this->findOrMakePage(); + + // Get status of page + $isPublished = $page->isPublished(); + $isOnDraft = $page->isOnDraft(); + $stagesDiffer = $page->stagesDiffer('Stage', 'Live'); + + // Check permissions + $canPublish = $page->canPublish(); + $canUnpublish = $page->canUnpublish(); + $canEdit = $page->canEdit(); + + // Major actions appear as buttons immediately visible as page actions. + $majorActions = CompositeField::create()->setName('MajorActions'); + $majorActions->setFieldHolderTemplate(get_class($majorActions) . '_holder_buttongroup'); + + // "save", supports an alternate state that is still clickable, but notifies the user that the action is not needed. + $noChangesClasses = 'btn-outline-primary font-icon-tick'; + if ($canEdit && $isOnDraft) { + $majorActions->push( + FormAction::create('save', _t(__CLASS__ . '.BUTTONSAVED', 'Saved')) + ->addExtraClass($noChangesClasses) + ->setAttribute('data-btn-alternate-add', 'btn-primary font-icon-save') + ->setAttribute('data-btn-alternate-remove', $noChangesClasses) + ->setUseButtonTag(true) + ->setAttribute('data-text-alternate', _t('SilverStripe\\CMS\\Controllers\\CMSMain.SAVEDRAFT', 'Save draft')) + ); + } + + // "publish", as with "save", it supports an alternate state to show when action is needed. + if ($canPublish && $isOnDraft) { + $majorActions->push( + $publish = FormAction::create('publish', _t(__CLASS__ . '.BUTTONPUBLISHED', 'Published')) + ->addExtraClass($noChangesClasses) + ->setAttribute('data-btn-alternate-add', 'btn-primary font-icon-rocket') + ->setAttribute('data-btn-alternate-remove', $noChangesClasses) + ->setUseButtonTag(true) + ->setAttribute('data-text-alternate', _t(__CLASS__ . '.BUTTONSAVEPUBLISH', 'Save & publish')) + ); + + // Set up the initial state of the button to reflect the state of the underlying SiteTree object. + if ($stagesDiffer) { + $publish->addExtraClass('btn-primary font-icon-rocket'); + $publish->setTitle(_t(__CLASS__ . '.BUTTONSAVEPUBLISH', 'Save & publish')); + $publish->removeExtraClass($noChangesClasses); + } + } + + // Minor options are hidden behind a drop-up and appear as links (although they are still FormActions). + $rootTabSet = new TabSet('ActionMenus'); + $moreOptions = new Tab( + 'MoreOptions', + _t(__CLASS__ . '.MoreOptions', 'More options', 'Expands a view for more buttons') + ); + $moreOptions->addExtraClass('popover-actions-simulate'); + $rootTabSet->push($moreOptions); + $rootTabSet->addExtraClass('ss-ui-action-tabset action-menus noborder'); + + // Add to campaign option if not-archived and has publish permission + if (($isPublished || $isOnDraft) && $canPublish) { + $moreOptions->push( + AddToCampaignHandler_FormAction::create() + ->removeExtraClass('btn-primary') + ->addExtraClass('btn-secondary') + ); + } + + // Rollback + if ($isOnDraft && $isPublished && $canEdit && $stagesDiffer) { + $moreOptions->push( + FormAction::create('rollback', _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 + if ($isPublished && $canPublish && $isOnDraft && $canUnpublish) { + $moreOptions->push( + FormAction::create('unpublish', _t(__CLASS__ . '.BUTTONUNPUBLISH', 'Unpublish'), 'delete') + ->setDescription(_t(__CLASS__ . '.BUTTONUNPUBLISHDESC', 'Remove this page from the published site')) + ->addExtraClass('btn-secondary') + ); + } + + $actions = new FieldList([$majorActions, $rootTabSet]); + $this->extend('updateCMSActions', $actions); + + return $actions; + } + + /** + * @param array $data + * @param \SilverStripe\Forms\Form $form + * @return mixed + */ + public function save($data, $form) + { + $currentStage = Versioned::get_stage(); + Versioned::set_stage('Stage'); + $value = $this->doSave($data, $form); + Versioned::set_stage($currentStage); + + return $value; + } + + /** + * @param $data + * @param $form + * @return mixed + */ + public function publish($data, $form) + { + $data['__publish__'] = true; + + return $this->doSave($data, $form); + } + + /** + * @param $data + * @param $form + * @return mixed + */ + public function doSave($data, $form) + { + $page = $this->findOrMakePage(); + $controller = Controller::curr(); + $publish = isset($data['__publish__']); + + if (!$page->canEdit()) { + return new HTTPResponse(403); + } + + try { + $form->saveInto($page); + $page->write(); + if ($publish) { + $page->doPublish(); + } + } catch (ValidationException $e) { + $form->sessionMessage($e->getResult()->message(), 'bad'); + $responseNegotiator = new PjaxResponseNegotiator([ + 'CurrentForm' => function () use (&$form) { + return $form->forTemplate(); + }, + 'default' => function () use (&$controller) { + return $controller->redirectBack(); + }, + ]); + if ($controller->getRequest()->isAjax()) { + $controller->getRequest()->addHeader('X-Pjax', 'CurrentForm'); + } + + return $responseNegotiator->respond($controller->getRequest()); + } + + $link = '"' . $page->Title . '"'; + $message = _t( + $publish ? 'SinglePageAdmin.Published' : 'GridFieldDetailForm.Saved', + ($publish ? 'Published' : 'Saved') . ' {name} {link}', + [ + 'name' => $page->i18n_singular_name(), + 'link' => $link, + ] + ); + + $form->sessionMessage($message, 'good'); + $action = $this->edit(Controller::curr()->getRequest()); + + return $action; + } + + /** + * @return mixed + */ + public function unPublish() + { + $currentStage = Versioned::get_stage(); + Versioned::set_stage('Live'); + + $page = $this->findOrMakePage(); + + // This way our ID won't be unset + $clone = clone $page; + $clone->delete(); + + Versioned::set_stage($currentStage); + + return $this->edit(Controller::curr()->getRequest()); + } + + /** + * @param $data + * @param $form + * @return HTTPResponse + */ + public function rollback($data, $form) + { + $page = $this->findOrMakePage(); + + if (!$page->canEdit()) { + return new HTTPResponse(403); + } + + $page->doRollbackTo('Live'); + + $this->page = DataList::create($page->class)->byID($page->ID); + + $message = _t( + 'CMSMain.ROLLEDBACKPUBv2', + "Rolled back to published version." + ); + + $form->sessionMessage($message, 'good'); + + return $this->owner->edit(Controller::curr()->getRequest()); + } + + + /** + * @param $request + * @return mixed + */ + public function edit($request) + { + $controller = Controller::curr(); + $form = $this->EditForm($request); + + $return = $this->customise([ + 'Backlink' => $controller->hasMethod('Backlink') ? $controller->Backlink() : $controller->Link(), + 'EditForm' => $form, + ])->renderWith('SinglePageAdmin_Content'); + + if ($request->isAjax()) { + return $return; + } else { + return $controller->customise([ + 'Content' => $return, + ]); + } + } + +} diff --git a/code/SinglePageCMSForm.php b/src/SinglePageCMSForm.php similarity index 56% rename from code/SinglePageCMSForm.php rename to src/SinglePageCMSForm.php index 6824440..fb6ca51 100644 --- a/code/SinglePageCMSForm.php +++ b/src/SinglePageCMSForm.php @@ -1,29 +1,35 @@ getRequest(); $negotiator = $this->getResponseNegotiator(); - if($request->isAjax() && $negotiator) { + if ($request->isAjax() && $negotiator) { $this->setupFormErrors(); $result = $this->customise( - array('EditForm' => $this) + ['EditForm' => $this] )->renderWith(Controller::curr()->getTemplatesWithSuffix('_Content')); - return $negotiator->respond($request, array( - 'CurrentForm' => function() use($result) { + return $negotiator->respond($request, [ + 'CurrentForm' => function () use ($result) { return $result; - } - )); + }, + ]); } else { return parent::getValidationErrorResponse(); } diff --git a/templates/SinglePageAdmin_Content.ss b/templates/SinglePageAdmin_Content.ss index 5304978..61a3130 100755 --- a/templates/SinglePageAdmin_Content.ss +++ b/templates/SinglePageAdmin_Content.ss @@ -1,23 +1,23 @@ -
-
- <% with $EditForm %> -
- <% with $Controller %> - <% include CMSBreadcrumbs %> - <% end_with %> -
- <% if $Fields.hasTabset %> - <% with $Fields.fieldByName('Root') %> -
-
    - <% loop $Tabs %> - class="$extraClass"<% end_if %>>$Title - <% end_loop %> -
-
- <% end_with %> - <% end_if %> - <% end_with %> -
- $EditForm -
\ No newline at end of file +
+
+ <% with $EditForm %> +
+ <% with $Controller %> + <% include SilverStripe\\Admin\\CMSBreadcrumbs %> + <% end_with %> +
+ <%--<% if $Fields.hasTabset %>--%> + <%--<% with $Fields.fieldByName('Root') %>--%> + <%--
--%> + <%--
    --%> + <%--<% loop $Tabs %>--%> + <%-- class="$extraClass"<% end_if %>>$Title--%> + <%--<% end_loop %>--%> + <%--
--%> + <%--
--%> + <%--<% end_with %>--%> + <%--<% end_if %>--%> + <% end_with %> +
+ {$EditForm} +
diff --git a/templates/SinglePageAdmin_EditForm.ss b/templates/SinglePageAdmin_EditForm.ss index cb2311c..7c20f36 100755 --- a/templates/SinglePageAdmin_EditForm.ss +++ b/templates/SinglePageAdmin_EditForm.ss @@ -1,31 +1,34 @@ -
-
- <% if $Message %> -

$Message

- <% else %> - - <% end_if %> - -
- <% if $Legend %>$Legend<% end_if %> - <% loop $Fields %> - $FieldHolder - <% end_loop %> -
-
-
-
- <% if $Actions %> -
- <% loop $Actions %> - $Field - <% end_loop %> - <% if $Controller.LinkPreview %> - - <% _t('LeftAndMain.PreviewButton', 'Preview') %> » - - <% end_if %> -
- <% end_if %> -
-
\ No newline at end of file +<% if $IncludeFormTag %> +
+<% end_if %> +<% with $Controller %> + $EditFormTools +<% end_with %> +
+ <% if $Message %> +

$Message

+ <% else %> + + <% end_if %> +
+ <% if $Legend %> + $Legend<% end_if %> + <% loop $Fields %> + $FieldHolder + <% end_loop %> +
+
+
+
+ Foo Bar + <% if $Actions %> +
+ <% loop $Actions %> + $FieldHolder + <% end_loop %> +
+ <% end_if %> +
+<% if $IncludeFormTag %> +
+<% end_if %> diff --git a/templates/SinglePageAdmin_SilverStripeNavigator.ss b/templates/SinglePageAdmin_SilverStripeNavigator.ss index e12372c..1df0318 100755 --- a/templates/SinglePageAdmin_SilverStripeNavigator.ss +++ b/templates/SinglePageAdmin_SilverStripeNavigator.ss @@ -1,5 +1,5 @@ - \ No newline at end of file +<%----%> From c07913a280a78b2f41d4f127cbbe0bc3404d6e96 Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Fri, 24 Nov 2017 14:41:53 +1300 Subject: [PATCH 2/9] Moved templates into their correct places --- src/SinglePageAdmin.php | 18 ++++++++---------- .../Includes}/SinglePageAdmin_Content.ss | 0 .../Includes}/SinglePageAdmin_EditForm.ss | 1 - 3 files changed, 8 insertions(+), 11 deletions(-) rename templates/{ => LittleGiant/SilverStripe/SinglePageAdmin/Includes}/SinglePageAdmin_Content.ss (100%) rename templates/{ => LittleGiant/SilverStripe/SinglePageAdmin/Includes}/SinglePageAdmin_EditForm.ss (98%) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index e59475a..c325405 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -38,7 +38,11 @@ class SinglePageAdmin extends LeftAndMain implements PermissionProvider { /** - * @var string + * As of 4.0 all subclasses of LeftAndMain have to have a + * $url_segment as a result of this, we need to hide the + * item from the cms menu. + * + * @TODO: Figure out a way to hide the menu item - Ryan Potter 24/11/17 */ private static $url_segment = 'little-giant/single-page-admin'; @@ -94,15 +98,6 @@ public function init() Requirements::javascript('silverstripe/cms: client/dist/js/SilverStripeNavigator.js'); Requirements::css('silverstripe/cms: client/dist/styles/bundle.css'); Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false, true); - - /** - * As of 4.0 all subclasses of LeftAndMain have to have a - * $url_segment as a result of this, we need to hide the - * item from the cms menu. - * - * @TODO: Check if there's a better way of getting around adding a $url_segment - Ryan Potter 24/11/17 - */ - CMSMenu::remove_menu_item('LittleGiant-SilverStripe-SinglePageAdmin-SinglePageAdmin'); } /** @@ -236,6 +231,9 @@ public function getEditForm($id = null, $fields = null) )->setHTMLID('Form_EditForm'); $form->addExtraClass('cms-edit-form'); $form->loadDataFrom($page); + /** + * + */ $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); $form->setAttribute('data-pjax-fragment', 'CurrentForm'); $form->setValidationResponseCallback(function (ValidationResult $errors) use ($negotiator, $form) { diff --git a/templates/SinglePageAdmin_Content.ss b/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss similarity index 100% rename from templates/SinglePageAdmin_Content.ss rename to templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss diff --git a/templates/SinglePageAdmin_EditForm.ss b/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss similarity index 98% rename from templates/SinglePageAdmin_EditForm.ss rename to templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss index 7c20f36..a63046a 100755 --- a/templates/SinglePageAdmin_EditForm.ss +++ b/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss @@ -20,7 +20,6 @@
- Foo Bar <% if $Actions %>
<% loop $Actions %> From f01c8847b8d48c51e799005c968205eb5cc2df2d Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Fri, 24 Nov 2017 16:25:56 +1300 Subject: [PATCH 3/9] Began changing the rollback methods for the single page admin --- src/SinglePageAdmin.php | 114 +++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index c325405..d78f2a4 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -5,6 +5,7 @@ use SilverStripe\Admin\CMSMenu; use SilverStripe\Admin\LeftAndMain; use SilverStripe\CampaignAdmin\AddToCampaignHandler_FormAction; +use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\CMS\Controllers\RootURLController; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Control\Controller; @@ -229,11 +230,8 @@ public function getEditForm($id = null, $fields = null) $fields, $this->getCMSActions() )->setHTMLID('Form_EditForm'); - $form->addExtraClass('cms-edit-form'); + $form->addExtraClass('cms-edit-form fill-height flexbox-area-grow'); $form->loadDataFrom($page); - /** - * - */ $form->setTemplate($this->getTemplatesWithSuffix('_EditForm')); $form->setAttribute('data-pjax-fragment', 'CurrentForm'); $form->setValidationResponseCallback(function (ValidationResult $errors) use ($negotiator, $form) { @@ -294,7 +292,7 @@ public function getResponseNegotiator() $neg = parent::getResponseNegotiator(); $controller = $this; $neg->setCallback('CurrentForm', function () use (&$controller) { - return $controller->renderWith('LittleGiant\SilverStripeSinglePageAdmin\SinglePageAdmin_Content'); + return $controller->renderWith($this->getTemplatesWithSuffix('_EditForm')); }); return $neg; @@ -439,60 +437,46 @@ public function publish($data, $form) } /** + * @desc Save the page * @param $data * @param $form - * @return mixed + * @return mixed|HTTPResponse */ public function doSave($data, $form) { + $request = $this->getRequest(); $page = $this->findOrMakePage(); $controller = Controller::curr(); $publish = isset($data['__publish__']); + // If the user doesn't have permission to save then throw an error. if (!$page->canEdit()) { - return new HTTPResponse(403); + return new HTTPResponse('Permission Error', 403); } - try { - $form->saveInto($page); - $page->write(); - if ($publish) { - $page->doPublish(); - } - } catch (ValidationException $e) { - $form->sessionMessage($e->getResult()->message(), 'bad'); - $responseNegotiator = new PjaxResponseNegotiator([ - 'CurrentForm' => function () use (&$form) { - return $form->forTemplate(); - }, - 'default' => function () use (&$controller) { - return $controller->redirectBack(); - }, - ]); - if ($controller->getRequest()->isAjax()) { - $controller->getRequest()->addHeader('X-Pjax', 'CurrentForm'); - } - - return $responseNegotiator->respond($controller->getRequest()); + // save form data into record + $form->saveInto($page, true); + $page->write(); + $this->extend('onAfterSave', $page); + + // Set the response message + $message = _t(__CLASS__ . '.SAVEDUP', 'Saved.'); + if ($this->getSchemaRequested()) { + $schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $id); + // Ensure that newly created records have all their data loaded back into the form. + $form->loadDataFrom($page); + $form->setMessage($message, 'good'); + $response = $this->getSchemaResponse($schemaId, $form); + } else { + $response = $this->getResponseNegotiator()->respond($request); } + $response->addHeader('X-Status', rawurlencode($message)); - $link = '"' . $page->Title . '"'; - $message = _t( - $publish ? 'SinglePageAdmin.Published' : 'GridFieldDetailForm.Saved', - ($publish ? 'Published' : 'Saved') . ' {name} {link}', - [ - 'name' => $page->i18n_singular_name(), - 'link' => $link, - ] - ); - - $form->sessionMessage($message, 'good'); - $action = $this->edit(Controller::curr()->getRequest()); - - return $action; + return $this->edit(Controller::curr()->getRequest());; } /** + * @desc Unpublish the page * @return mixed */ public function unPublish() @@ -520,22 +504,46 @@ public function rollback($data, $form) { $page = $this->findOrMakePage(); - if (!$page->canEdit()) { - return new HTTPResponse(403); - } + $page->extend('onBeforeRollback', $page->ID, $page->Version); - $page->doRollbackTo('Live'); + $id = (isset($page->ID)) ? (int)$page->ID : null; + $version = (isset($page->Version)) ? (int)$page->Version : null; - $this->page = DataList::create($page->class)->byID($page->ID); + /** @var DataObject|Versioned $record */ + $record = Versioned::get_latest_version($this->config()->get('tree_class'), $id); + if ($record && !$record->canEdit()) { + return Security::permissionFailure($this); + } - $message = _t( - 'CMSMain.ROLLEDBACKPUBv2', - "Rolled back to published version." - ); + if ($version) { + $record->doRollbackTo($version); + $message = _t( + __CLASS__ . '.ROLLEDBACKVERSIONv2', + "Rolled back to version #{version}.", + ['version' => $page->Version] + ); + } else { + $record->doRevertToLive(); + $message = _t( + __CLASS__ . '.ROLLEDBACKPUBv2', + "Rolled back to published version." + ); + } + + $this->getResponse()->addHeader('X-Status', rawurlencode($message)); - $form->sessionMessage($message, 'good'); + // 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. + $url = Controller::join_links(CMSPageEditController::singleton()->Link('show'), $record->ID); + $this->getResponse()->addHeader('X-ControllerURL', $url); + $this->getRequest()->addHeader('X-Pjax', 'Content'); + $this->getResponse()->addHeader('X-Pjax', 'Content'); - return $this->owner->edit(Controller::curr()->getRequest()); + /** + * @TODO: Redirect the user back to the single page admin page. - Ryan Potter 24/11/17 + */ + return $this->getResponseNegotiator()->respond($this->getRequest()); } From 6bc09c153f57d7e8e24eee8b0e8faa1f680c57dd Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Fri, 24 Nov 2017 17:05:54 +1300 Subject: [PATCH 4/9] Updated save method --- src/SinglePageAdmin.php | 48 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index d78f2a4..caf9cd8 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -5,6 +5,7 @@ use SilverStripe\Admin\CMSMenu; use SilverStripe\Admin\LeftAndMain; use SilverStripe\CampaignAdmin\AddToCampaignHandler_FormAction; +use SilverStripe\CMS\Controllers\CMSMain; use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\CMS\Controllers\RootURLController; use SilverStripe\CMS\Model\SiteTree; @@ -431,7 +432,7 @@ public function save($data, $form) */ public function publish($data, $form) { - $data['__publish__'] = true; + $data['__publish__'] = '1'; return $this->doSave($data, $form); } @@ -445,13 +446,15 @@ public function publish($data, $form) public function doSave($data, $form) { $request = $this->getRequest(); + $page = $this->findOrMakePage(); $controller = Controller::curr(); $publish = isset($data['__publish__']); - // If the user doesn't have permission to save then throw an error. - if (!$page->canEdit()) { - return new HTTPResponse('Permission Error', 403); + // Check publishing permissions + $doPublish = !empty($publish); + if ($page && $doPublish && !$page->canPublish()) { + return Security::permissionFailure($this); } // save form data into record @@ -460,19 +463,25 @@ public function doSave($data, $form) $this->extend('onAfterSave', $page); // Set the response message - $message = _t(__CLASS__ . '.SAVEDUP', 'Saved.'); - if ($this->getSchemaRequested()) { - $schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $id); - // Ensure that newly created records have all their data loaded back into the form. - $form->loadDataFrom($page); - $form->setMessage($message, 'good'); - $response = $this->getSchemaResponse($schemaId, $form); + // If the 'Save & Publish' button was clicked, also publish the page + if ($doPublish) { + $page->publishRecursive(); + $message = _t( + 'SilverStripe\\CMS\\Controllers\\CMSMain.PUBLISHED', + "Published '{title}' successfully.", + ['title' => $page->Title] + ); } else { - $response = $this->getResponseNegotiator()->respond($request); + $message = _t( + 'SilverStripe\\CMS\\Controllers\\CMSMain.SAVED', + "Saved '{title}' successfully.", + ['title' => $page->Title] + ); } - $response->addHeader('X-Status', rawurlencode($message)); - return $this->edit(Controller::curr()->getRequest());; + $this->getResponse()->addHeader('X-Status', rawurlencode($message)); + + return $this->edit($controller->getRequest()); } /** @@ -504,7 +513,7 @@ public function rollback($data, $form) { $page = $this->findOrMakePage(); - $page->extend('onBeforeRollback', $page->ID, $page->Version); +// $page->extend('onBeforeRollback', $page->ID, $page->Version); $id = (isset($page->ID)) ? (int)$page->ID : null; $version = (isset($page->Version)) ? (int)$page->Version : null; @@ -535,14 +544,11 @@ public function rollback($data, $form) // 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. - $url = Controller::join_links(CMSPageEditController::singleton()->Link('show'), $record->ID); - $this->getResponse()->addHeader('X-ControllerURL', $url); + $url = Controller::curr()->getRequest(); + $this->getResponse()->addHeader('X-ControllerURL', $url->getURL()); // @TODO: Redirect to the base url of the form - 24/11/17 Ryan Potter $this->getRequest()->addHeader('X-Pjax', 'Content'); $this->getResponse()->addHeader('X-Pjax', 'Content'); - /** - * @TODO: Redirect the user back to the single page admin page. - Ryan Potter 24/11/17 - */ return $this->getResponseNegotiator()->respond($this->getRequest()); } @@ -559,7 +565,7 @@ public function edit($request) $return = $this->customise([ 'Backlink' => $controller->hasMethod('Backlink') ? $controller->Backlink() : $controller->Link(), 'EditForm' => $form, - ])->renderWith('SinglePageAdmin_Content'); + ])->renderWith($this->getTemplatesWithSuffix('_Content')); if ($request->isAjax()) { return $return; From 2738945be3f199cef6676281f6706c3ccc7796bf Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Mon, 27 Nov 2017 09:40:13 +1300 Subject: [PATCH 5/9] Made the singlepageadmin class abstract --- src/SinglePageAdmin.php | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index caf9cd8..e2ec15a 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -2,16 +2,12 @@ namespace LittleGiant\SilverStripe\SinglePageAdmin; -use SilverStripe\Admin\CMSMenu; use SilverStripe\Admin\LeftAndMain; use SilverStripe\CampaignAdmin\AddToCampaignHandler_FormAction; -use SilverStripe\CMS\Controllers\CMSMain; -use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\CMS\Controllers\RootURLController; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; -use SilverStripe\Control\PjaxResponseNegotiator; use SilverStripe\Core\ClassInfo; use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\FieldList; @@ -20,8 +16,6 @@ use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\Tab; use SilverStripe\Forms\TabSet; -use SilverStripe\ORM\DataList; -use SilverStripe\ORM\ValidationException; use SilverStripe\ORM\ValidationResult; use SilverStripe\Security\Member; use SilverStripe\Security\Permission; @@ -37,17 +31,8 @@ * @package SinglePageAdmin * @author Stevie Mayhew */ -class SinglePageAdmin extends LeftAndMain implements PermissionProvider +abstract class SinglePageAdmin extends LeftAndMain implements PermissionProvider { - /** - * As of 4.0 all subclasses of LeftAndMain have to have a - * $url_segment as a result of this, we need to hide the - * item from the cms menu. - * - * @TODO: Figure out a way to hide the menu item - Ryan Potter 24/11/17 - */ - private static $url_segment = 'little-giant/single-page-admin'; - /** * @var string */ From 583ab4999da2a8a6bb6426d71119383077a0dcf7 Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Mon, 27 Nov 2017 10:37:31 +1300 Subject: [PATCH 6/9] Remove abstract class --- src/SinglePageAdmin.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index e2ec15a..37e8885 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -31,8 +31,17 @@ * @package SinglePageAdmin * @author Stevie Mayhew */ -abstract class SinglePageAdmin extends LeftAndMain implements PermissionProvider +class SinglePageAdmin extends LeftAndMain implements PermissionProvider { + /** + * As of 4.0 all subclasses of LeftAndMain have to have a + * $url_segment as a result of this, we need to hide the + * item from the cms menu. + * + * @TODO: Figure out a way to hide the menu item - Ryan Potter 24/11/17 + */ + private static $url_segment = 'little-giant/single-page-admin'; + /** * @var string */ From 96eda2cbdd13a6dc57063179f5efe2fdfb31c723 Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Mon, 27 Nov 2017 10:46:31 +1300 Subject: [PATCH 7/9] Updated permissions --- src/SinglePageAdmin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index 37e8885..b28f5f3 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -163,9 +163,9 @@ public function providePermissions() $perms = []; // Add any custom SinglePageAdmin subclasses. - foreach (ClassInfo::subclassesFor('SinglePageAdmin') as $i => $class) { + foreach (ClassInfo::subclassesFor(SinglePageAdmin::class) as $i => $class) { - if ($class == 'SinglePageAdmin') { + if ($class == SinglePageAdmin::class) { continue; } @@ -173,7 +173,7 @@ public function providePermissions() continue; } - $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title_for_class($class)); + $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title($class)); $perms["CMS_ACCESS_" . $class] = [ 'name' => _t( 'CMSMain.ACCESS', From c43b966dbeb9486c6b9a5ea40dd54c071415b852 Mon Sep 17 00:00:00 2001 From: Ryan Potter Date: Mon, 27 Nov 2017 10:57:43 +1300 Subject: [PATCH 8/9] Fixed permission error --- src/SinglePageAdmin.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SinglePageAdmin.php b/src/SinglePageAdmin.php index b28f5f3..3b3d461 100644 --- a/src/SinglePageAdmin.php +++ b/src/SinglePageAdmin.php @@ -17,7 +17,6 @@ use SilverStripe\Forms\Tab; use SilverStripe\Forms\TabSet; use SilverStripe\ORM\ValidationResult; -use SilverStripe\Security\Member; use SilverStripe\Security\Permission; use SilverStripe\Security\PermissionProvider; use SilverStripe\Security\Security; @@ -131,17 +130,18 @@ protected function findOrMakePage() public function canView($member = null) { if (!$member && $member !== false) { - $member = Member::currentUser(); + $member = Security::getCurrentUser(); } $codes = []; - $extraCodes = $this->stat('required_permission_codes'); + $extraCodes = $this->config()->get('required_permission_codes'); if ($extraCodes !== false) { // allow explicit FALSE to disable subclass check if ($extraCodes) { $codes = array_merge($codes, (array)$extraCodes); } else { - $codes[] = "CMS_ACCESS_$this->class"; + $class = static::class; + $codes[] = "CMS_ACCESS_$class"; } } From 38c22c5f2d25a0bbe39500d213051470e03a618b Mon Sep 17 00:00:00 2001 From: Stevie Mayhew Date: Fri, 9 Feb 2018 15:04:16 +1300 Subject: [PATCH 9/9] Update namespaces Update form templates Update tab systems --- _config/config.yml | 2 +- .../SinglePageAdmin}/SinglePageAdmin.php | 18 +++---- .../SinglePageAdmin}/SinglePageCMSForm.php | 2 +- .../Includes/SinglePageAdmin_Content.ss | 23 --------- .../Includes/SinglePageAdmin_EditForm.ss | 33 ------------- .../Includes/SinglePageAdmin_Content.ss | 28 +++++++++++ .../Includes/SinglePageAdmin_EditForm.ss | 47 +++++++++++++++++++ .../SinglePageAdmin_SilverStripeNavigator.ss | 5 -- 8 files changed, 84 insertions(+), 74 deletions(-) rename src/{ => LittleGiant/SinglePageAdmin}/SinglePageAdmin.php (97%) rename src/{ => LittleGiant/SinglePageAdmin}/SinglePageCMSForm.php (95%) delete mode 100755 templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss delete mode 100755 templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss create mode 100644 templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss create mode 100644 templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss delete mode 100755 templates/SinglePageAdmin_SilverStripeNavigator.ss diff --git a/_config/config.yml b/_config/config.yml index 40f013a..9af9504 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -1,5 +1,5 @@ --- -Name: catalog-manager +Name: singlepageadmin --- SilverStripe\SiteConfig\SiteConfig: required_permission: diff --git a/src/SinglePageAdmin.php b/src/LittleGiant/SinglePageAdmin/SinglePageAdmin.php similarity index 97% rename from src/SinglePageAdmin.php rename to src/LittleGiant/SinglePageAdmin/SinglePageAdmin.php index 3b3d461..8ad77ad 100644 --- a/src/SinglePageAdmin.php +++ b/src/LittleGiant/SinglePageAdmin/SinglePageAdmin.php @@ -1,6 +1,6 @@ renderWith('SinglePageAdmin_SilverStripeNavigator'); + return false; } /** @@ -287,6 +285,7 @@ public function getResponseNegotiator() $neg = parent::getResponseNegotiator(); $controller = $this; $neg->setCallback('CurrentForm', function () use (&$controller) { + error_log($controller->renderWith($this->getTemplatesWithSuffix('_EditForm'))); return $controller->renderWith($this->getTemplatesWithSuffix('_EditForm')); }); @@ -306,7 +305,6 @@ public function LinkPreview() /** * @return FieldList - * @TODO: classes */ protected function getCMSActions() { @@ -439,8 +437,6 @@ public function publish($data, $form) */ public function doSave($data, $form) { - $request = $this->getRequest(); - $page = $this->findOrMakePage(); $controller = Controller::curr(); $publish = isset($data['__publish__']); @@ -507,7 +503,7 @@ public function rollback($data, $form) { $page = $this->findOrMakePage(); -// $page->extend('onBeforeRollback', $page->ID, $page->Version); + $page->extend('onBeforeRollback', $page->ID, $page->Version); $id = (isset($page->ID)) ? (int)$page->ID : null; $version = (isset($page->Version)) ? (int)$page->Version : null; diff --git a/src/SinglePageCMSForm.php b/src/LittleGiant/SinglePageAdmin/SinglePageCMSForm.php similarity index 95% rename from src/SinglePageCMSForm.php rename to src/LittleGiant/SinglePageAdmin/SinglePageCMSForm.php index fb6ca51..39a5826 100644 --- a/src/SinglePageCMSForm.php +++ b/src/LittleGiant/SinglePageAdmin/SinglePageCMSForm.php @@ -1,6 +1,6 @@ -
- <% with $EditForm %> -
- <% with $Controller %> - <% include SilverStripe\\Admin\\CMSBreadcrumbs %> - <% end_with %> -
- <%--<% if $Fields.hasTabset %>--%> - <%--<% with $Fields.fieldByName('Root') %>--%> - <%--
--%> - <%--
    --%> - <%--<% loop $Tabs %>--%> - <%-- class="$extraClass"<% end_if %>>$Title--%> - <%--<% end_loop %>--%> - <%--
--%> - <%--
--%> - <%--<% end_with %>--%> - <%--<% end_if %>--%> - <% end_with %> -
- {$EditForm} -
diff --git a/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss b/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss deleted file mode 100755 index a63046a..0000000 --- a/templates/LittleGiant/SilverStripe/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss +++ /dev/null @@ -1,33 +0,0 @@ -<% if $IncludeFormTag %> -
-<% end_if %> -<% with $Controller %> - $EditFormTools -<% end_with %> -
- <% if $Message %> -

$Message

- <% else %> - - <% end_if %> -
- <% if $Legend %> - $Legend<% end_if %> - <% loop $Fields %> - $FieldHolder - <% end_loop %> -
-
-
-
- <% if $Actions %> -
- <% loop $Actions %> - $FieldHolder - <% end_loop %> -
- <% end_if %> -
-<% if $IncludeFormTag %> -
-<% end_if %> diff --git a/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss b/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss new file mode 100644 index 0000000..a595c16 --- /dev/null +++ b/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_Content.ss @@ -0,0 +1,28 @@ +
+ $Tools + +
+
+
+ <% if $BreadcrumbsBackLink %><% end_if %> + <% include SilverStripe\\Admin\\CMSBreadcrumbs %> +
+ + <% if $EditForm.Fields.hasTabset %> + <% with $EditForm.Fields.fieldByName('Root') %> +
+ +
+ <% end_with %> + <% end_if %> +
+ +
+ $EditForm +
+
+
diff --git a/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss b/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss new file mode 100644 index 0000000..ef3db8d --- /dev/null +++ b/templates/LittleGiant/SinglePageAdmin/Includes/SinglePageAdmin_EditForm.ss @@ -0,0 +1,47 @@ +
+ +
+ <% if $Message %> +

$Message

+ <% else %> + + <% end_if %> + +
+ <% if $Legend %>$Legend<% end_if %> + <% loop $Fields %> + <% if $Tabs %> + <% loop $Tabs %> + <% if $Tabs %> + $FieldHolder + <% else %> +
+ <% loop $Fields %> + $FieldHolder + <% end_loop %> +
+ <% end_if %> + <% end_loop %> + <% else %> + $FieldHolder + <% end_if %> + <% end_loop %> +
+
+
+ +
+ <% if $Actions %> +
+ <% loop $Actions %> + $Field + <% end_loop %> + <% if $Controller.LinkPreview %> + + <%t SilverStripe\\Admin\\LeftAndMain.PreviewButton 'Preview' %> » + + <% end_if %> +
+ <% end_if %> +
+
diff --git a/templates/SinglePageAdmin_SilverStripeNavigator.ss b/templates/SinglePageAdmin_SilverStripeNavigator.ss deleted file mode 100755 index 1df0318..0000000 --- a/templates/SinglePageAdmin_SilverStripeNavigator.ss +++ /dev/null @@ -1,5 +0,0 @@ -<%----%>