mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW Admin url can now be customized
The default 'admin/' base URL can now be changed with Director rules
This commit is contained in:
parent
392536cb17
commit
533d5dbd4b
@ -31,4 +31,4 @@ After:
|
||||
---
|
||||
Director:
|
||||
rules:
|
||||
'admin': 'AdminRootController'
|
||||
'admin': 'AdminRootController'
|
@ -4,15 +4,47 @@
|
||||
* @package framework
|
||||
* @subpackage admin
|
||||
*/
|
||||
class AdminRootController extends Controller {
|
||||
class AdminRootController extends Controller implements TemplateGlobalProvider {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @config
|
||||
* The url base that all LeftAndMain derived panels will live under
|
||||
* Won't automatically update the base route if you change this - that has to be done seperately
|
||||
* Convenience function to return the admin route config.
|
||||
* Looks for the {@link Director::$rules} for the current admin Controller.
|
||||
*/
|
||||
private static $url_base = 'admin';
|
||||
public static function get_admin_route() {
|
||||
if (Controller::has_curr()) {
|
||||
$routeParams = Controller::curr()->getRequest()->routeParams();
|
||||
$adminControllerClass = isset($routeParams['Controller']) ? $routeParams['Controller'] : get_called_class();
|
||||
}
|
||||
else {
|
||||
$adminControllerClass = get_called_class();
|
||||
}
|
||||
|
||||
$rules = Config::inst()->get('Director', 'rules');
|
||||
$adminRoute = array_search($adminControllerClass, $rules);
|
||||
return $adminRoute ? $adminRoute : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root admin URL for the site with trailing slash
|
||||
*
|
||||
* @return string
|
||||
* @uses get_admin_route()
|
||||
*/
|
||||
public static function admin_url() {
|
||||
return self::get_admin_route() . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the adminURL JavaScript config in the ss namespace
|
||||
*/
|
||||
public static function include_js() {
|
||||
$js = "(function(root) {
|
||||
root.ss = root.ss || {};
|
||||
root.ss.config = root.ss.config || {};
|
||||
root.ss.config.adminURL = '".self::admin_url()."'
|
||||
}(window));";
|
||||
Requirements::customScript($js, 'adminURLConfig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -74,11 +106,10 @@ class AdminRootController extends Controller {
|
||||
public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
|
||||
// If this is the final portion of the request (i.e. the URL is just /admin), direct to the default panel
|
||||
if ($request->allParsed()) {
|
||||
$base = $this->config()->url_base;
|
||||
$segment = Config::inst()->get($this->config()->default_panel, 'url_segment');
|
||||
|
||||
$this->response = new SS_HTTPResponse();
|
||||
$this->redirect(Controller::join_links($base, $segment));
|
||||
$this->redirect(Controller::join_links(self::admin_url(), $segment));
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
@ -97,4 +128,14 @@ class AdminRootController extends Controller {
|
||||
|
||||
return $this->httpError(404, 'Not found');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array Returns an array of strings of the method names of methods on the call that should be exposed
|
||||
* as global variables in the templates.
|
||||
*/
|
||||
public static function get_template_global_variables() {
|
||||
return array(
|
||||
'adminURL' => 'admin_url'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
|
||||
* Return a CMSMenuItem to add the given controller to the CMSMenu
|
||||
*/
|
||||
protected static function menuitem_for_controller($controllerClass) {
|
||||
$urlBase = Config::inst()->get($controllerClass, 'url_base', Config::FIRST_SET);
|
||||
$urlSegment = Config::inst()->get($controllerClass, 'url_segment', Config::FIRST_SET);
|
||||
$urlBase = AdminRootController::admin_url();
|
||||
$urlSegment = Config::inst()->get($controllerClass, 'url_segment', Config::FIRST_SET);
|
||||
$menuPriority = Config::inst()->get($controllerClass, 'menu_priority', Config::FIRST_SET);
|
||||
|
||||
// Don't add menu items defined the old way
|
||||
|
@ -11,16 +11,6 @@
|
||||
*/
|
||||
class LeftAndMain extends Controller implements PermissionProvider {
|
||||
|
||||
/**
|
||||
* The 'base' url for CMS administration areas.
|
||||
* Note that if this is changed, many javascript
|
||||
* behaviours need to be updated with the correct url
|
||||
*
|
||||
* @config
|
||||
* @var string $url_base
|
||||
*/
|
||||
private static $url_base = "admin";
|
||||
|
||||
/**
|
||||
* The current url segment attached to the LeftAndMain instance
|
||||
*
|
||||
@ -340,6 +330,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
if (Director::isDev()) Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/javascript/leaktools.js');
|
||||
|
||||
HTMLEditorField::include_js();
|
||||
AdminRootController::include_js();
|
||||
|
||||
$leftAndMainIncludes = array_unique(array_merge(
|
||||
array(
|
||||
@ -527,7 +518,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
};
|
||||
|
||||
$link = Controller::join_links(
|
||||
$this->stat('url_base', true),
|
||||
AdminRootController::admin_url(),
|
||||
$segment,
|
||||
'/', // trailing slash needed if $action is null!
|
||||
"$action"
|
||||
@ -642,7 +633,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
|
||||
// default menu is the one with a blank {@link url_segment}
|
||||
} else if(singleton($menuItem->controller)->stat('url_segment') == '') {
|
||||
if($this->Link() == $this->stat('url_base').'/') {
|
||||
if($this->Link() == AdminRootController::admin_url()) {
|
||||
$linkingmode = "current";
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@
|
||||
/**
|
||||
* Publish selected pages action
|
||||
*/
|
||||
$('#Form_BatchActionsForm').register('admin/batchactions/publish', function(ids) {
|
||||
$('#Form_BatchActionsForm').register(ss.config.adminURL+'batchactions/publish', function(ids) {
|
||||
var confirmed = confirm(
|
||||
"You have " + ids.length + " pages selected.\n\n"
|
||||
+ "Do your really want to publish?"
|
||||
@ -344,7 +344,7 @@
|
||||
/**
|
||||
* Unpublish selected pages action
|
||||
*/
|
||||
$('#Form_BatchActionsForm').register('admin/batchactions/unpublish', function(ids) {
|
||||
$('#Form_BatchActionsForm').register(ss.config.adminURL+'batchactions/unpublish', function(ids) {
|
||||
var confirmed = confirm(
|
||||
"You have " + ids.length + " pages selected.\n\n"
|
||||
+ "Do your really want to unpublish?"
|
||||
@ -355,7 +355,7 @@
|
||||
/**
|
||||
* Delete selected pages action
|
||||
*/
|
||||
$('#Form_BatchActionsForm').register('admin/batchactions/delete', function(ids) {
|
||||
$('#Form_BatchActionsForm').register(ss.config.adminURL+'batchactions/delete', function(ids) {
|
||||
var confirmed = confirm(
|
||||
"You have " + ids.length + " pages selected.\n\n"
|
||||
+ "Do your really want to delete?"
|
||||
@ -366,7 +366,7 @@
|
||||
/**
|
||||
* Delete selected pages from live action
|
||||
*/
|
||||
$('#Form_BatchActionsForm').register('admin/batchactions/deletefromlive', function(ids) {
|
||||
$('#Form_BatchActionsForm').register(ss.config.adminURL+'batchactions/deletefromlive', function(ids) {
|
||||
var confirmed = confirm(
|
||||
"You have " + ids.length + " pages selected.\n\n"
|
||||
+ "Do your really want to delete these pages from live?"
|
||||
|
@ -12,7 +12,7 @@
|
||||
<% with $CurrentMember %>
|
||||
<span>
|
||||
<% _t('LeftAndMain_Menu_ss.Hello','Hi') %>
|
||||
<a href="{$AbsoluteBaseURL}admin/myprofile" class="profile-link">
|
||||
<a href="{$AbsoluteBaseURL}{$AdminURL}myprofile" class="profile-link">
|
||||
<% if $FirstName && $Surname %>$FirstName $Surname<% else_if $FirstName %>$FirstName<% else %>$Email<% end_if %>
|
||||
</a>
|
||||
</span>
|
||||
|
@ -351,12 +351,14 @@ class Director implements TemplateGlobalProvider {
|
||||
if(isset($_REQUEST['debug'])) Debug::show($rules);
|
||||
|
||||
foreach($rules as $pattern => $controllerOptions) {
|
||||
if(is_string($controllerOptions)) {
|
||||
if(is_string($controllerOptions) && $controllerOptions) {
|
||||
if(substr($controllerOptions,0,2) == '->') {
|
||||
$controllerOptions = array('Redirect' => substr($controllerOptions,2));
|
||||
} else {
|
||||
$controllerOptions = array('Controller' => $controllerOptions);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(($arguments = $request->match($pattern, true)) !== false) {
|
||||
|
@ -135,7 +135,6 @@ if(Director::isLive()) {
|
||||
*/
|
||||
Debug::loadErrorHandlers();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
|
@ -15,6 +15,42 @@ with some special conventions.
|
||||
For a more practical-oriented approach to CMS customizations, refer to the
|
||||
[Howto: Extend the CMS Interface](../how_tos/extend_cms_interface) which builds
|
||||
|
||||
## The Admin URL
|
||||
|
||||
The CMS interface can be accessed by default through the `admin/` URL. You can change this by setting your own [Director routing rule](director#routing-rules) to the `[api:AdminRootController]` and clear the old rule like in the example below.
|
||||
|
||||
:::yml
|
||||
---
|
||||
Name: myadmin
|
||||
After:
|
||||
- '#adminroutes'
|
||||
---
|
||||
Director:
|
||||
rule:
|
||||
'admin': ''
|
||||
'newAdmin': 'AdminRootController'
|
||||
---
|
||||
|
||||
When extending the CMS or creating modules, you can take advantage of various functions that will return the configured admin URL (by default 'admin/' is returned):
|
||||
|
||||
In PHP you should use:
|
||||
|
||||
:::php
|
||||
AdminRootController::admin_url()
|
||||
|
||||
When writing templates use:
|
||||
|
||||
:::ss
|
||||
$AdminURL
|
||||
|
||||
And in JavaScript, this is avaible through the `ss` namespace
|
||||
|
||||
:::js
|
||||
ss.config.adminURL
|
||||
|
||||
### Multiple Admin URL and overrides
|
||||
|
||||
You can also create your own classes that extend the `[api:AdminRootController]` to create multiple or custom admin areas, with a `Director.rules` for each one.
|
||||
|
||||
## Markup and Style Conventions
|
||||
|
||||
@ -257,7 +293,7 @@ in a single Ajax request.
|
||||
<% include CMSBreadcrumbs %>
|
||||
<div>Static content (not affected by update)</div>
|
||||
<% include MyRecordInfo %>
|
||||
<a href="admin/myadmin" class="cms-panel-link" data-pjax-target="MyRecordInfo,Breadcrumbs">
|
||||
<a href="{$AdminURL}myadmin" class="cms-panel-link" data-pjax-target="MyRecordInfo,Breadcrumbs">
|
||||
Update record info
|
||||
</a>
|
||||
|
||||
@ -285,7 +321,7 @@ On the client, you can set your preference through the `data-pjax-target` attrib
|
||||
on links or through the `X-Pjax` header. For firing off an Ajax request that is
|
||||
tracked in the browser history, use the `pjax` attribute on the state data.
|
||||
|
||||
$('.cms-container').loadPanel('admin/pages', null, {pjax: 'Content'});
|
||||
$('.cms-container').loadPanel(ss.config.adminURL+'pages', null, {pjax: 'Content'});
|
||||
|
||||
## Loading lightweight PJAX fragments
|
||||
|
||||
@ -301,16 +337,16 @@ unrelated to the main flow.
|
||||
In this case you can use the `loadFragment` call supplied by `LeftAndMain.js`. You can trigger as many of these in
|
||||
parallel as you want. This will not disturb the main navigation.
|
||||
|
||||
$('.cms-container').loadFragment('admin/foobar/', 'Fragment1');
|
||||
$('.cms-container').loadFragment('admin/foobar/', 'Fragment2');
|
||||
$('.cms-container').loadFragment('admin/foobar/', 'Fragment3');
|
||||
$('.cms-container').loadFragment(ss.config.adminURL+'foobar/', 'Fragment1');
|
||||
$('.cms-container').loadFragment(ss.config.adminURL+'foobar/', 'Fragment2');
|
||||
$('.cms-container').loadFragment(ss.config.adminURL+'foobar/', 'Fragment3');
|
||||
|
||||
The ongoing requests are tracked by the PJAX fragment name (Fragment1, 2, and 3 above) - resubmission will
|
||||
result in the prior request for this fragment to be aborted. Other parallel requests will continue undisturbed.
|
||||
|
||||
You can also load multiple fragments in one request, as long as they are to the same controller (i.e. URL):
|
||||
|
||||
$('.cms-container').loadFragment('admin/foobar/', 'Fragment2,Fragment3');
|
||||
$('.cms-container').loadFragment(ss.config.adminURL+'foobar/', 'Fragment2,Fragment3');
|
||||
|
||||
This counts as a separate request type from the perspective of the request tracking, so will not abort the singular
|
||||
`Fragment2` nor `Fragment3`.
|
||||
@ -331,7 +367,7 @@ You can hook up a response handler that obtains all the details of the XHR reque
|
||||
Alternatively you can use the jQuery deferred API:
|
||||
|
||||
$('.cms-container')
|
||||
.loadFragment('admin/foobar/', 'Fragment1')
|
||||
.loadFragment(ss.config.adminURL+'foobar/', 'Fragment1')
|
||||
.success(function(data, status, xhr) {
|
||||
// Say 'success'!
|
||||
alert(status);
|
||||
@ -519,19 +555,19 @@ and load the HTML content into the main view. Example:
|
||||
<div id="my-tab-id" class="cms-tabset" data-ignore-tab-state="true">
|
||||
<ul>
|
||||
<li class="<% if MyActiveCondition %> ui-tabs-active<% end_if %>">
|
||||
<a href="admin/mytabs/tab1" class="cms-panel-link">
|
||||
<a href="{$AdminURL}mytabs/tab1" class="cms-panel-link">
|
||||
Tab1
|
||||
</a>
|
||||
</li>
|
||||
<li class="<% if MyActiveCondition %> ui-tabs-active<% end_if %>">
|
||||
<a href="admin/mytabs/tab2" class="cms-panel-link">
|
||||
<a href="{$AdminURL}mytabs/tab2" class="cms-panel-link">
|
||||
Tab2
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
The URL endpoints `admin/mytabs/tab1` and `admin/mytabs/tab2`
|
||||
The URL endpoints `{$AdminURL}mytabs/tab1` and `{$AdminURL}mytabs/tab2`
|
||||
should return HTML fragments suitable for inserting into the content area,
|
||||
through the `PjaxResponseNegotiator` class (see above).
|
||||
|
||||
|
@ -26,7 +26,7 @@ code like this:
|
||||
...
|
||||
<li id="record-15" class="class-Page closed jstree-leaf jstree-unchecked" data-id="15">
|
||||
<ins class="jstree-icon"> </ins>
|
||||
<a class="" title="Page type: Page" href="admin/page/edit/show/15">
|
||||
<a class="" title="Page type: Page" href="{$AdminURL}page/edit/show/15">
|
||||
<ins class="jstree-checkbox"> </ins>
|
||||
<ins class="jstree-icon"> </ins>
|
||||
<span class="text">
|
||||
|
@ -33,10 +33,10 @@ the CMS logic. Add a new section into the `<ul class="cms-menu-list">`
|
||||
<ul class="cms-menu-list">
|
||||
<!-- ... -->
|
||||
<li class="bookmarked-link first">
|
||||
<a href="admin/pages/edit/show/1">Edit "My popular page"</a>
|
||||
<a href="{$AdminURL}pages/edit/show/1">Edit "My popular page"</a>
|
||||
</li>
|
||||
<li class="bookmarked-link last">
|
||||
<a href="admin/pages/edit/show/99">Edit "My other page"</a>
|
||||
<a href="{$AdminURL}pages/edit/show/99">Edit "My other page"</a>
|
||||
</li>
|
||||
</ul>
|
||||
...
|
||||
@ -130,7 +130,7 @@ and replace it with the following:
|
||||
<!-- ... -->
|
||||
<% loop $BookmarkedPages %>
|
||||
<li class="bookmarked-link $FirstLast">
|
||||
<li><a href="admin/pages/edit/show/$ID">Edit "$Title"</a></li>
|
||||
<li><a href="{$AdminURL}pages/edit/show/$ID">Edit "$Title"</a></li>
|
||||
</li>
|
||||
<% end_loop %>
|
||||
</ul>
|
||||
|
@ -17,6 +17,7 @@
|
||||
* `Mailer` no longer calls `xml2raw` on all email subject line, and now must be passed in via plain text.
|
||||
* `ErrorControlChain` now supports reload on exceptions
|
||||
* `FormField::validate` now requires an instance of `Validator`
|
||||
* Admin URL can now be configured via custom Director routing rule
|
||||
|
||||
#### Deprecated classes/methods removed
|
||||
|
||||
@ -124,6 +125,14 @@ languages like JavaScript won't be able to read them.
|
||||
To set it back to be non-HTTP only, you need to set the `$httpOnly` argument to false when calling
|
||||
`Cookie::set()`.
|
||||
|
||||
### Admin URL can now be configured via custom Director routing rule
|
||||
|
||||
The default `admin/` URL to access the CMS interface can now be changed
|
||||
via a custom Director routing rule for `AdminRootController`. If your website or module
|
||||
has hard coded `admin` URLs in PHP, templates or JavaScript, make sure to update those
|
||||
with the appropriate function or config call.
|
||||
See [CMS architecture](/developer_guides/customising_the_admin_interface/cms-architecture#the-admin-url) for language specific functions.
|
||||
|
||||
### Bugfixes
|
||||
* Migration of code to use new parameterised framework
|
||||
|
||||
|
@ -748,7 +748,7 @@ class File extends DataObject {
|
||||
* @todo Coupling with cms module, remove this method.
|
||||
*/
|
||||
public function DeleteLink() {
|
||||
return Director::absoluteBaseURL()."admin/assets/removefile/".$this->ID;
|
||||
return Director::absoluteBaseURL().AdminRootController::admin_url()."assets/removefile/".$this->ID;
|
||||
}
|
||||
|
||||
public function getFilename() {
|
||||
|
Loading…
Reference in New Issue
Block a user