From 34b3fbf04d4370120e21e70a69512e22c97c2a3a Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Tue, 30 Jan 2018 16:21:45 +1300 Subject: [PATCH] FIX Subsites VirtualPage link to edit main page and TreeDropdownField API implementations --- javascript/SubsitesTreeDropdownField.js | 27 +++++++++-------- src/Extensions/LeftAndMainSubsites.php | 32 +++++++++++++++----- src/Extensions/SiteTreeSubsites.php | 8 +++-- src/Forms/SubsitesTreeDropdownField.php | 40 ++++++++++++++++++++----- src/Pages/SubsitesVirtualPage.php | 25 +++++++++++----- 5 files changed, 95 insertions(+), 37 deletions(-) diff --git a/javascript/SubsitesTreeDropdownField.js b/javascript/SubsitesTreeDropdownField.js index 3b24c34b..3964aff2 100644 --- a/javascript/SubsitesTreeDropdownField.js +++ b/javascript/SubsitesTreeDropdownField.js @@ -4,14 +4,14 @@ * Choose a subsite from which to select pages. * Needs to clear tree dropdowns in case selection is changed. */ - $('.subsitestreedropdownfield-chooser').entwine({ + $('select.subsitestreedropdownfield-chooser').entwine({ onchange: function() { // TODO Data binding between two fields - // TODO create resetField method on API instead - var fields = $('.SubsitesTreeDropdownField'); - fields.setValue(null); - fields.setTitle(null); - fields.find('.tree-holder').empty(); + const name = this.attr('name').replace('_SubsiteID', ''); + let field = $('#Form_EditForm_' + name).first(); + field.setValue(0); + field.refresh(); + field.trigger('change'); } }); @@ -20,12 +20,15 @@ * before asking for the tree. */ $('.TreeDropdownField.SubsitesTreeDropdownField').entwine({ - getRequestParams: function() { - var name = this.find(':input[type=hidden]:first').attr('name') + '_SubsiteID', - source = $('[name=' + name + ']'), params = {}; - params[name] = source.length ? source.val() : null; - return params; - } + getAttributes() { + const fieldName = this.attr('id').replace('Form_EditForm_', ''); + const subsiteID = $('#Form_EditForm_' + fieldName + '_SubsiteID option:selected').val(); + + let attributes = this._super(); + attributes.data.urlTree += "?" + fieldName + "_SubsiteID=" + subsiteID; + attributes.data.cacheKey = attributes.data.cacheKey.substring(0, 19) + "_" + subsiteID; + return attributes; + } }); }); })(jQuery); diff --git a/src/Extensions/LeftAndMainSubsites.php b/src/Extensions/LeftAndMainSubsites.php index 6b52b585..87d02a74 100644 --- a/src/Extensions/LeftAndMainSubsites.php +++ b/src/Extensions/LeftAndMainSubsites.php @@ -5,6 +5,7 @@ use SilverStripe\Admin\AdminRootController; use SilverStripe\Admin\CMSMenu; use SilverStripe\Admin\LeftAndMainExtension; +use SilverStripe\CMS\Controllers\CMSPagesController; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\Control\Controller; @@ -270,13 +271,31 @@ public function onBeforeInit() $session->clear($sessionNamespace . '.currentPage'); } - // Subsite ID has already been set to the state via InitStateMiddleware. If the user cannot view - // the current page, or we're in the context of editing a specific page, redirect to the admin landing - // section to prevent a loop of re-loading the original subsite for the current page. - if (!$this->owner->canView() || Controller::curr() instanceof CMSPageEditController) { + // Context: Subsite ID has already been set to the state via InitStateMiddleware + + // If the user cannot view the current page, redirect to the admin landing section + if (!$this->owner->canView()) { return $this->owner->redirect(AdminRootController::config()->get('url_base') . '/'); } + $currentController = Controller::curr(); + if ($currentController instanceof CMSPageEditController) { + /** @var SiteTree $page */ + $page = $currentController->currentPage(); + + // If the page exists but doesn't belong to the requested subsite, redirect to admin/pages which + // will show a list of the requested subsite's pages + $currentSubsiteId = $request->getVar('SubsiteID'); + if ($page && (int) $page->SubsiteID !== (int) $currentSubsiteId) { + return $this->owner->redirect(CMSPagesController::singleton()->Link()); + } + + // Page does belong to the current subsite, so remove the query string parameter and refresh the page + // Remove the subsiteID parameter and redirect back to the current URL again + $request->offsetSet('SubsiteID', null); + return $this->owner->redirect($request->getURL(true)); + } + // Redirect to clear the current page, retaining the current URL parameters return $this->owner->redirect( Controller::join_links($this->owner->Link(), ...array_values($this->owner->getURLParams())) @@ -299,10 +318,7 @@ public function onBeforeInit() $canViewElsewhere = SubsiteState::singleton()->withState(function ($newState) use ($record) { $newState->setSubsiteId($record->SubsiteID); - if ($this->owner->canView(Security::getCurrentUser())) { - return true; - } - return false; + return (bool) $this->owner->canView(Security::getCurrentUser()); }); if ($canViewElsewhere) { diff --git a/src/Extensions/SiteTreeSubsites.php b/src/Extensions/SiteTreeSubsites.php index e12c01e1..5ac586aa 100644 --- a/src/Extensions/SiteTreeSubsites.php +++ b/src/Extensions/SiteTreeSubsites.php @@ -118,15 +118,15 @@ public function updateCMSFields(FieldList $fields) 'SubsiteOperations', _t(__CLASS__ . '.SubsiteOperations', 'Subsite Operations'), [ - new DropdownField('CopyToSubsiteID', _t( + DropdownField::create('CopyToSubsiteID', _t( __CLASS__ . '.CopyToSubsite', 'Copy page to subsite' ), $subsitesMap), - new CheckboxField( + CheckboxField::create( 'CopyToSubsiteWithChildren', _t(__CLASS__ . '.CopyToSubsiteWithChildren', 'Include children pages?') ), - $copyAction = new FormAction( + $copyAction = FormAction::create( 'copytosubsite', _t(__CLASS__ . '.CopyAction', 'Copy') ) @@ -134,6 +134,8 @@ public function updateCMSFields(FieldList $fields) )->setHeadingLevel(4) ); + $copyAction->addExtraClass('btn btn-primary font-icon-save ml-3'); + // @todo check if this needs re-implementation // $copyAction->includeDefaultJS(false); } diff --git a/src/Forms/SubsitesTreeDropdownField.php b/src/Forms/SubsitesTreeDropdownField.php index f92cfbe1..4294306d 100644 --- a/src/Forms/SubsitesTreeDropdownField.php +++ b/src/Forms/SubsitesTreeDropdownField.php @@ -5,6 +5,7 @@ use SilverStripe\Control\Controller; use SilverStripe\Control\HTTPRequest; use SilverStripe\Forms\TreeDropdownField; +use SilverStripe\Subsites\Model\Subsite; use SilverStripe\View\Requirements; use SilverStripe\Subsites\State\SubsiteState; @@ -20,7 +21,10 @@ class SubsitesTreeDropdownField extends TreeDropdownField 'tree' ]; - protected $subsiteID = 0; + /** + * @var int + */ + protected $subsiteId = 0; /** * Extra HTML classes @@ -39,20 +43,42 @@ public function Field($properties = []) return $html; } - public function setSubsiteID($id) + /** + * Sets the subsite ID to use when generating the tree + * + * @param int $id + * @return $this + */ + public function setSubsiteId($id) { - $this->subsiteID = $id; + $this->subsiteId = $id; + return $this; } - public function getSubsiteID() + /** + * Get the subsite ID to use when generating the tree + * + * @return int + */ + public function getSubsiteId() { - return $this->subsiteID; + return $this->subsiteId; } + /** + * Get the CMS tree with the provided subsite ID applied to the state + * + * {@inheritDoc} + */ public function tree(HTTPRequest $request) { - $results = SubsiteState::singleton()->withState(function () use ($request) { - SubsiteState::singleton()->setSubsiteId($this->subsiteID); + // Detect subsite ID from the request + if ($request->getVar($this->getName() . '_SubsiteID')) { + $this->setSubsiteId($request->getVar($this->getName() . '_SubsiteID')); + } + + $results = SubsiteState::singleton()->withState(function (SubsiteState $newState) use ($request) { + $newState->setSubsiteId($this->getSubsiteId()); return parent::tree($request); }); diff --git a/src/Pages/SubsitesVirtualPage.php b/src/Pages/SubsitesVirtualPage.php index 013083a1..ea2a882f 100644 --- a/src/Pages/SubsitesVirtualPage.php +++ b/src/Pages/SubsitesVirtualPage.php @@ -2,14 +2,17 @@ namespace SilverStripe\Subsites\Pages; +use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Model\VirtualPage; use SilverStripe\Control\Controller; use SilverStripe\Core\Config\Config; use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\LabelField; +use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\TextareaField; use SilverStripe\Forms\TextField; +use SilverStripe\Forms\TreeDropdownField; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; use SilverStripe\Subsites\Forms\SubsitesTreeDropdownField; @@ -59,23 +62,32 @@ public function getCMSFields() ); // Setup the linking to the original page. - $pageSelectionField = new SubsitesTreeDropdownField( + $pageSelectionField = SubsitesTreeDropdownField::create( 'CopyContentFromID', - _t('SilverStripe\\CMS\\Model\\VirtualPage.CHOOSE', 'Choose a page to link to'), - "SilverStripe\\CMS\\Model\\SiteTree", + _t('SilverStripe\\CMS\\Model\\VirtualPage.CHOOSE', 'Linked Page'), + SiteTree::class, 'ID', 'MenuTitle' ); + $fields->addFieldToTab( + 'Root.Main', + TreeDropdownField::create('CopyContentFromID', 'Linked Page', SiteTree::class) + ); + if (Controller::has_curr() && Controller::curr()->getRequest()) { - $subsiteID = Controller::curr()->getRequest()->requestVar('CopyContentFromID_SubsiteID'); + $subsiteID = (int) Controller::curr()->getRequest()->requestVar('CopyContentFromID_SubsiteID'); $pageSelectionField->setSubsiteID($subsiteID); } $fields->replaceField('CopyContentFromID', $pageSelectionField); // Create links back to the original object in the CMS if ($this->CopyContentFromID) { - $editLink = "admin/pages/edit/show/$this->CopyContentFromID/?SubsiteID=" . $this->CopyContentFrom()->SubsiteID; + $editLink = Controller::join_links( + CMSPageEditController::singleton()->Link('show'), + $this->CopyContentFromID + ); + $linkToContent = " " . _t('SilverStripe\\CMS\\Model\\VirtualPage.EDITCONTENT', 'Click here to edit the content') . @@ -83,10 +95,9 @@ public function getCMSFields() $fields->removeByName('VirtualPageContentLinkLabel'); $fields->addFieldToTab( 'Root.Main', - $linkToContentLabelField = new LabelField('VirtualPageContentLinkLabel', $linkToContent), + $linkToContentLabelField = LiteralField::create('VirtualPageContentLinkLabel', $linkToContent), 'Title' ); - $linkToContentLabelField->setAllowHTML(true); }