Skip to content

Commit

Permalink
API: Subsite support for menu of cms (hide admins that don't declare …
Browse files Browse the repository at this point in the history
…support) (fixes silverstripe#101 and silverstripe#89 )

* Hide admins without subsite support from subsites menu
* Add subsite support to default site areas
* Enable reloading of subsites switcher dropdown when navigating the
site, and when editing subsite areas

API Fix parallel pjax menu fetching for subsites.
- thanks Mateusz!

Delint LeftAndMain_Subsites.js
  • Loading branch information
Naomi Guyer committed Aug 22, 2013
1 parent 2d41dc6 commit 9f90b66
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 82 deletions.
9 changes: 9 additions & 0 deletions _config.php
Expand Up @@ -17,3 +17,12 @@
SiteConfig::add_extension('SiteConfigSubsites');

SS_Report::add_excluded_reports('SubsiteReportWrapper');

//Display in cms menu
AssetAdmin::add_extension('SubsiteMenuExtension');
SecurityAdmin::add_extension('SubsiteMenuExtension');
CMSMain::add_extension('SubsiteMenuExtension');
CMSPagesController::add_extension('SubsiteMenuExtension');
SubsiteAdmin::add_extension('SubsiteMenuExtension');
CMSSettingsController::add_extension('SubsiteMenuExtension');

14 changes: 14 additions & 0 deletions code/SubsiteAdmin.php
Expand Up @@ -29,4 +29,18 @@ public function getEditForm($id = null, $fields = null) {

return $form;
}

public function getResponseNegotiator() {
$negotiator = parent::getResponseNegotiator();
$self = $this;
// Register a new callback
$negotiator->setCallback('SubsiteList', function() use(&$self) {
return $self->SubsiteList();
});
return $negotiator;
}

public function SubsiteList() {
return $this->renderWith('SubsiteList');
}
}
12 changes: 11 additions & 1 deletion code/extensions/FileSubsites.php
Expand Up @@ -35,7 +35,17 @@ function updateCMSFields(FieldList $fields) {
$values[$site->ID] = $site->Title;
}
ksort($values);
if($sites)$fields->push(new DropdownField('SubsiteID', 'Subsite', $values));
if($sites){
//Dropdown needed to move folders between subsites
$fields->push($dropdown = new DropdownField('SubsiteID', 'Subsite', $values));
$fields->push(new LiteralField(
'Message',
'<p class="message notice">'.
_t('ASSETADMIN.SUBSITENOTICE', 'Folders and files created in the main site are accessible by all subsites.')
.'</p>'
));
$dropdown->addExtraClass('subsites-move-dropdown');
}
}
}

Expand Down
125 changes: 65 additions & 60 deletions code/extensions/LeftAndMainSubsites.php
Expand Up @@ -51,6 +51,9 @@ function updatePageOptions(&$fields) {
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
}

/*
* Returns a list of the subsites accessible to the current user
*/
public function Subsites() {
// figure out what permission the controller needs
// Subsite::accessible_sites() expects something, so if there's no permission
Expand All @@ -64,76 +67,78 @@ public function Subsites() {
}
}

switch($this->owner->class) {
case "AssetAdmin":
$subsites = Subsite::accessible_sites($permission, true, "Shared files & images");
break;

case "SecurityAdmin":
$subsites = Subsite::accessible_sites($permission, true, "Groups accessing all sites");
if($subsites->find('ID',0)) {
$subsites->push(new ArrayData(array('Title' => 'All groups', 'ID' => -1)));
}
break;

case "CMSMain":
case "CMSPagesController":
// If there's a default site then main site has no meaning
$showMainSite = !DataObject::get_one('Subsite',"\"DefaultSite\"=1");
$subsites = Subsite::accessible_sites($permission, $showMainSite);
break;

case "SubsiteAdmin":
$subsites = Subsite::accessible_sites('ADMIN', true);
break;
return Subsite::accessible_sites($permission);
}

default:
$subsites = Subsite::accessible_sites($permission);
break;
}
/*
* Generates a list of subsites with the data needed to
* produce a dropdown site switcher
* @return ArrayList
*/

return $subsites;
}

public function SubsiteList() {
public function CreateSubsiteList(){
$list = $this->Subsites();
$currentSubsiteID = Subsite::currentSubsiteID();

if($list->Count() > 1) {
$output = '<div class="field dropdown">';
$output .= '<select id="SubsitesSelect">';

foreach($list as $subsite) {
$selected = $subsite->ID == $currentSubsiteID ? ' selected="selected"' : '';

$output .= "\n<option value=\"{$subsite->ID}\"$selected>". Convert::raw2xml($subsite->Title) . "</option>";
}

$output .= '</select></div>';

Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
return $output;
} elseif($list->Count() == 1) {
if($list->First()->DefaultSite==false) {
$output = '<div class="field dropdown">';
$output .= '<select id="SubsitesSelect">';
$output .= "\n<option value=\"0\">". _t('LeftAndMainSubsites.DEFAULT_SITE', 'Default site') . "</option>";
foreach($list as $subsite) {
$selected = $subsite->ID == $currentSubsiteID ? ' selected="selected"' : '';

$output .= "\n<option value=\"{$subsite->ID}\"$selected>". Convert::raw2xml($subsite->Title) . "</option>";
}
if($list == null || $list->Count() == 1 && $list->First()->DefaultSite == true){
return false;
}

Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');

$output = new ArrayList();

if($list->Count() == 1) {
$output->push(new ArrayData(array(
'CurrentState' => 'selected',
'ID' => 0,
'Title' => _t('LeftAndMainSubsites.DEFAULT_SITE', 'Default site')
)));
}

foreach($list as $subsite) {
$CurrentState = $subsite->ID == $currentSubsiteID ? 'selected' : '';

$output->push(new ArrayData(array(
'CurrentState' => $CurrentState,
'ID' => $subsite->ID,
'Title' => Convert::raw2xml($subsite->Title)
)));
}

$output .= '</select></div>';
return $output;
}

Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
return $output;
} else {
return '<span>'.$list->First()->Title.'</span>';
/*
* Returns a subset of the main menu, filtered by admins that have
* a subsiteMenu method returning true
*
* @return ArrayList
*/
public function SubsiteMainMenu(){
if(Subsite::currentSubsiteID() == 0){
return $this->owner->MainMenu();
}
// loop main menu items, add all items that have subsite support
$mainMenu = $this->owner->MainMenu();
$subsitesMenu = new ArrayList();
foreach($mainMenu as $menuItem){
$item = $menuItem->MenuItem;
$controllerName = $item->controller;
if(class_exists($controllerName)){
$controller = singleton($controllerName);
if($controller->hasMethod('subsiteMenu')
&& $controller->subsiteMenu()){
$subsitesMenu->push($menuItem);
}
}
if($menuItem->Code == 'Help'){
$subsitesMenu->push($menuItem);
}
}
return $subsitesMenu;
}

public function CanAddSubsites() {
return Permission::check("ADMIN", "any", null, "all");
}
Expand Down
19 changes: 19 additions & 0 deletions code/extensions/SubsiteMenuExtension.php
@@ -0,0 +1,19 @@
<?php

/*
* Simple extension to show admins in the menu of subsites.
* If an admin area should be available to a subsite, you can attach
* this class to your admin in config. eg:
*
* MyAdmin::add_extension('SubsiteMenuExtension');
*
* Or you can include the subsiteMenu function in your class and have it return true
*/

class SubsiteMenuExtension extends Extension{

public function subsiteMenu(){
return true;
}

}
4 changes: 3 additions & 1 deletion code/model/Subsite.php
Expand Up @@ -219,7 +219,7 @@ function getCMSFields() {
asort($pageTypeMap);

$fields = new FieldList(
new TabSet('Root',
$subsiteTabs = new TabSet('Root',
new Tab('Configuration',
new HeaderField($this->getClassName() . ' configuration', 2),
new TextField('Title', 'Name of subsite:', $this->Title),
Expand Down Expand Up @@ -252,6 +252,8 @@ function getCMSFields() {
new HiddenField('IsSubsite', '', 1)
);

$subsiteTabs->addExtraClass('subsite-model');

$this->extend('updateCMSFields', $fields);
return $fields;
}
Expand Down
8 changes: 8 additions & 0 deletions css/LeftAndMain_Subsites.css
Expand Up @@ -81,3 +81,11 @@ body.SubsiteAdmin .right form #URL .fieldgroup * {
.cms-add-form #PageType li .class-SubsitesVirtualPage, .class-SubsitesVirtualPage a .jstree-pageicon {
background-position: 0 -32px !important;
}

.subsites-move-dropdown{
display:none;
}

#Root_DetailsView .subsites-move-dropdown{
display:block;
}
96 changes: 88 additions & 8 deletions javascript/LeftAndMain_Subsites.js
@@ -1,7 +1,89 @@
/*jslint browser: true, nomen: true*/
/*global $, window, jQuery*/

(function($) {
'use strict';
$.entwine('ss', function($) {
$('#SubsitesSelect').live('change', function() {
window.location.search=$.query.set('SubsiteID', $(this).val());

$('#SubsitesSelect').entwine({
onadd:function(){
this.on('change', function(){
window.location.search=$.query.set('SubsiteID', $(this).val());
});
}
});

$('.cms-container').entwine({

SubsiteCurrentXHR: null,

/**
* LeftAndMain does not give us possibility to parallel-fetch a PJAX fragment.
* We provide our own fetcher that bypasses the history - that's because we
* don't want to load a panel, but rather just a subsite dropdown.
*/
subsiteFetchPjaxFragment: function(url, pjaxFragment) {

// Make sure only one subsite XHR request is ongoing.
if(this.getSubsiteCurrentXHR()){
this.getSubsiteCurrentXHR().abort();
}

var self = this,
xhr,
headers = {},
baseUrl = $('base').attr('href');

url = $.path.isAbsoluteUrl(url) ? url : $.path.makeUrlAbsolute(url, baseUrl);
headers['X-Pjax'] = pjaxFragment;

xhr = $.ajax({
headers: headers,
url: url,
complete: function() {
self.setSubsiteCurrentXHR(null);
},
success: function(data, status, xhr) {
self.handleAjaxResponse(data, status, xhr, null);
}
});

this.setSubsiteCurrentXHR(xhr);
}

});

/*
* Reload subsites dropdown when links are processed
*/
$('.cms-container .cms-menu-list li a').entwine({
onclick: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});

/*
* Reload subsites dropdown when the admin area reloads (for deleting sites)
*/
$('.cms-container .SubsiteAdmin .cms-edit-form fieldset.ss-gridfield').entwine({
onreload: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});




/*
* Reload subsites dropdown when subsites are added or names are modified
*/
$('.cms-container .cms-content-fields .subsite-model').entwine({
onadd: function(e) {
$('.cms-container').subsiteFetchPjaxFragment('admin/subsites/', 'SubsiteList');
this._super(e);
}
});

// Subsite tab of Group editor
Expand Down Expand Up @@ -72,7 +154,9 @@
onafterIframeAdjustedForPreview: function(event, doc) {
var subsiteId = $(doc).find('meta[name=x-subsite-id]').attr('content');

if (!subsiteId) return;
if (!subsiteId) {
return;
}

// Inject the SubsiteID into internal links.
$(doc).find('a').each(function() {
Expand All @@ -95,11 +179,7 @@
}

});

}

});

});

})(jQuery);
}(jQuery));
9 changes: 9 additions & 0 deletions templates/Includes/SubsiteList.ss
@@ -0,0 +1,9 @@
<div class="cms-subsites" data-pjax-fragment="SubsiteList">
<div class="field dropdown">
<select id="SubsitesSelect">
<% loop $CreateSubsiteList %>
<option value="$ID" $CurrentState>$Title</option>
<% end_loop %>
</select>
</div>
</div>

0 comments on commit 9f90b66

Please sign in to comment.