mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #2474 from wilr/externalcmslink
API: Add attributes argument for CMSMenuItem for external links
This commit is contained in:
commit
e7953f3b41
@ -1,16 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* The object manages the main CMS menu. See {@link LeftAndMain::init()} for example usage.
|
* The object manages the main CMS menu. See {@link LeftAndMain::init()} for
|
||||||
|
* example usage.
|
||||||
*
|
*
|
||||||
* The menu will be automatically populated with menu items for subclasses of {@link LeftAndMain}.
|
* The menu will be automatically populated with menu items for subclasses of
|
||||||
* That is, for each class in the CMS that creates an administration panel, a CMS menu item will be created.
|
* {@link LeftAndMain}. That is, for each class in the CMS that creates an
|
||||||
* The default configuration will also include a 'help' link to the SilverStripe user documentation.
|
* administration panel, a CMS menu item will be created. The default
|
||||||
|
* configuration will also include a 'help' link to the SilverStripe user
|
||||||
|
* documentation.
|
||||||
|
*
|
||||||
|
* Additional CMSMenu items can be added through {@link LeftAndMainExtension::init()}
|
||||||
|
* extensions added to {@link LeftAndMain}.
|
||||||
*
|
*
|
||||||
* @package cms
|
* @package framework
|
||||||
* @subpackage content
|
* @subpackage admin
|
||||||
*/
|
*/
|
||||||
class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider
|
class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of changes to be made to the menu items, in the order that the changes should be
|
* An array of changes to be made to the menu items, in the order that the changes should be
|
||||||
@ -79,10 +84,12 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider
|
|||||||
* @param string $url The url of the link
|
* @param string $url The url of the link
|
||||||
* @param integer $priority The menu priority (sorting order) of the menu item. Higher priorities will be further
|
* @param integer $priority The menu priority (sorting order) of the menu item. Higher priorities will be further
|
||||||
* left.
|
* left.
|
||||||
|
* @param array $attributes an array of attributes to include on the link.
|
||||||
|
*
|
||||||
* @return boolean The result of the operation.
|
* @return boolean The result of the operation.
|
||||||
*/
|
*/
|
||||||
public static function add_link($code, $menuTitle, $url, $priority = -1) {
|
public static function add_link($code, $menuTitle, $url, $priority = -1, $attributes = null) {
|
||||||
return self::add_menu_item($code, $menuTitle, $url, null, $priority);
|
return self::add_menu_item($code, $menuTitle, $url, null, $priority, $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,13 +104,17 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider
|
|||||||
* @param string $controllerClass The controller class for this menu, used to check permisssions.
|
* @param string $controllerClass The controller class for this menu, used to check permisssions.
|
||||||
* If blank, it's assumed that this is public, and always shown to users who
|
* If blank, it's assumed that this is public, and always shown to users who
|
||||||
* have the rights to access some other part of the admin area.
|
* have the rights to access some other part of the admin area.
|
||||||
|
* @param array $attributes an array of attributes to include on the link.
|
||||||
|
*
|
||||||
* @return boolean Success
|
* @return boolean Success
|
||||||
*/
|
*/
|
||||||
public static function add_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1) {
|
public static function add_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1, $attributes = null) {
|
||||||
// If a class is defined, then force the use of that as a code. This helps prevent menu item duplication
|
// If a class is defined, then force the use of that as a code. This helps prevent menu item duplication
|
||||||
if($controllerClass) $code = $controllerClass;
|
if($controllerClass) {
|
||||||
|
$code = $controllerClass;
|
||||||
|
}
|
||||||
|
|
||||||
return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority);
|
return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority, $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,18 +234,26 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider
|
|||||||
* @param string $controllerClass The controller class for this menu, used to check permisssions.
|
* @param string $controllerClass The controller class for this menu, used to check permisssions.
|
||||||
* If blank, it's assumed that this is public, and always shown to users who
|
* If blank, it's assumed that this is public, and always shown to users who
|
||||||
* have the rights to access some other part of the admin area.
|
* have the rights to access some other part of the admin area.
|
||||||
|
* @param array $attributes an array of attributes to include on the link.
|
||||||
|
*
|
||||||
* @return boolean Success
|
* @return boolean Success
|
||||||
*/
|
*/
|
||||||
public static function replace_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1) {
|
public static function replace_menu_item($code, $menuTitle, $url, $controllerClass = null, $priority = -1, $attributes = null) {
|
||||||
|
$item = new CMSMenuItem($menuTitle, $url, $controllerClass, $priority);
|
||||||
|
|
||||||
|
if($attributes) {
|
||||||
|
$item->setAttributes($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
self::$menu_item_changes[] = array(
|
self::$menu_item_changes[] = array(
|
||||||
'type' => 'add',
|
'type' => 'add',
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
'item' => new CMSMenuItem($menuTitle, $url, $controllerClass, $priority),
|
'item' => $item,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a previously built menuitem object to the menu
|
* Add a previously built menu item object to the menu
|
||||||
*/
|
*/
|
||||||
protected static function add_menu_item_obj($code, $cmsMenuItem) {
|
protected static function add_menu_item_obj($code, $cmsMenuItem) {
|
||||||
self::$menu_item_changes[] = array(
|
self::$menu_item_changes[] = array(
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple CMS menu item
|
* A simple CMS menu item.
|
||||||
|
*
|
||||||
|
* Items can be added to the menu through custom {@link LeftAndMainExtension}
|
||||||
|
* classes and {@link CMSMenu}.
|
||||||
*
|
*
|
||||||
* @package cms
|
* @see CMSMenu
|
||||||
* @subpackage content
|
*
|
||||||
|
* @package framework
|
||||||
|
* @subpackage admin
|
||||||
*/
|
*/
|
||||||
class CMSMenuItem extends Object
|
class CMSMenuItem extends Object {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* The (translated) menu title
|
* The (translated) menu title
|
||||||
* @var string $title
|
* @var string $title
|
||||||
@ -31,8 +37,17 @@ class CMSMenuItem extends Object
|
|||||||
*/
|
*/
|
||||||
public $priority;
|
public $priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes for the link. For instance, custom data attributes or standard
|
||||||
|
* HTML anchor properties.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $attributes = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new CMS Menu Item
|
* Create a new CMS Menu Item
|
||||||
|
*
|
||||||
* @param string $title
|
* @param string $title
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param string $controller Controller class name
|
* @param string $controller Controller class name
|
||||||
@ -43,7 +58,41 @@ class CMSMenuItem extends Object
|
|||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->controller = $controller;
|
$this->controller = $controller;
|
||||||
$this->priority = $priority;
|
$this->priority = $priority;
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attributes
|
||||||
|
*/
|
||||||
|
public function setAttributes($attributes) {
|
||||||
|
$this->attributes = $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array
|
||||||
|
*
|
||||||
|
* @return HTML
|
||||||
|
*/
|
||||||
|
public function getAttributesHTML($attrs = null) {
|
||||||
|
$exclude = (is_string($attrs)) ? func_get_args() : null;
|
||||||
|
|
||||||
|
if(!$attrs || is_string($attrs)) {
|
||||||
|
$attrs = $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove empty
|
||||||
|
$attrs = array_filter((array)$attrs, function($v) {
|
||||||
|
return ($v || $v === 0 || $v === '0');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create markkup
|
||||||
|
$parts = array();
|
||||||
|
|
||||||
|
foreach($attrs as $name => $value) {
|
||||||
|
$parts[] = ($value === true) ? "{$name}=\"{$name}\"" : "{$name}=\"" . Convert::raw2att($value) . "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' ', $parts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,10 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
'Help',
|
'Help',
|
||||||
_t('LeftAndMain.HELP', 'Help', 'Menu title'),
|
_t('LeftAndMain.HELP', 'Help', 'Menu title'),
|
||||||
$this->config()->help_link,
|
$this->config()->help_link,
|
||||||
-2
|
-2,
|
||||||
|
array(
|
||||||
|
'target' => '_blank'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Allow customisation of the access check by a extension
|
// Allow customisation of the access check by a extension
|
||||||
@ -616,6 +619,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
if($menuItems) {
|
if($menuItems) {
|
||||||
foreach($menuItems as $code => $menuItem) {
|
foreach($menuItems as $code => $menuItem) {
|
||||||
// alternate permission checks (in addition to LeftAndMain->canView())
|
// alternate permission checks (in addition to LeftAndMain->canView())
|
||||||
|
|
||||||
if(
|
if(
|
||||||
isset($menuItem->controller)
|
isset($menuItem->controller)
|
||||||
&& $this->hasMethod('alternateMenuDisplayCheck')
|
&& $this->hasMethod('alternateMenuDisplayCheck')
|
||||||
@ -661,9 +665,10 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
$menuIcon = LeftAndMain::menu_icon_for_class($menuItem->controller);
|
$menuIcon = LeftAndMain::menu_icon_for_class($menuItem->controller);
|
||||||
if (!empty($menuIcon)) $menuIconStyling .= $menuIcon;
|
if (!empty($menuIcon)) $menuIconStyling .= $menuIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
$menu->push(new ArrayData(array(
|
$menu->push(new ArrayData(array(
|
||||||
"MenuItem" => $menuItem,
|
"MenuItem" => $menuItem,
|
||||||
|
"AttributesHTML" => $menuItem->getAttributesHTML(),
|
||||||
"Title" => Convert::raw2xml($title),
|
"Title" => Convert::raw2xml($title),
|
||||||
"Code" => DBField::create_field('Text', $code),
|
"Code" => DBField::create_field('Text', $code),
|
||||||
"Link" => $menuItem->url,
|
"Link" => $menuItem->url,
|
||||||
|
@ -230,6 +230,13 @@
|
|||||||
// Ignore external links, fallback to standard link behaviour
|
// Ignore external links, fallback to standard link behaviour
|
||||||
var isExternal = $.path.isExternal(this.attr('href'));
|
var isExternal = $.path.isExternal(this.attr('href'));
|
||||||
if(e.which > 1 || isExternal) return;
|
if(e.which > 1 || isExternal) return;
|
||||||
|
|
||||||
|
// if the developer has this to open in a new window, handle
|
||||||
|
// that
|
||||||
|
if(this.attr('target') == "_blank") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var item = this.getMenuItem();
|
var item = this.getMenuItem();
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<ul class="cms-menu-list">
|
<ul class="cms-menu-list">
|
||||||
<% loop $MainMenu %>
|
<% loop $MainMenu %>
|
||||||
<li class="$LinkingMode $FirstLast <% if $LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
|
<li class="$LinkingMode $FirstLast <% if $LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
|
||||||
<a href="$Link" <% if $Code == 'Help' %>target="_blank"<% end_if%>>
|
<a href="$Link" $AttributesHTML>
|
||||||
<span class="icon icon-16 icon-{$Code.LowerCase}"> </span>
|
<span class="icon icon-16 icon-{$Code.LowerCase}"> </span>
|
||||||
<span class="text">$Title</span>
|
<span class="text">$Title</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* @package cms
|
* @package framework
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class CMSMenuTest extends SapphireTest implements TestOnly {
|
class CMSMenuTest extends SapphireTest implements TestOnly {
|
||||||
@ -35,7 +35,21 @@ class CMSMenuTest extends SapphireTest implements TestOnly {
|
|||||||
$this->assertNull($menuItem->controller, 'Link menu item has no controller class');
|
$this->assertNull($menuItem->controller, 'Link menu item has no controller class');
|
||||||
$this->assertEquals($menuItem->priority, -1, 'Link menu item has the correct priority');
|
$this->assertEquals($menuItem->priority, -1, 'Link menu item has the correct priority');
|
||||||
CMSMenu::clear_menu();
|
CMSMenu::clear_menu();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLinkWithExternalAttributes() {
|
||||||
|
CMSMenu::clear_menu();
|
||||||
|
|
||||||
|
CMSMenu::add_link('LinkCode', 'link title', 'http://www.example.com', -2, array(
|
||||||
|
'target' => '_blank'
|
||||||
|
));
|
||||||
|
|
||||||
|
$menuItems = CMSMenu::get_menu_items();
|
||||||
|
$menuItem = $menuItems['LinkCode'];
|
||||||
|
|
||||||
|
$this->assertEquals('target="_blank"', $menuItem->getAttributesHTML());
|
||||||
|
|
||||||
|
CMSMenu::clear_menu();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCmsClassDetection() {
|
public function testCmsClassDetection() {
|
||||||
@ -81,8 +95,15 @@ class CMSMenuTest extends SapphireTest implements TestOnly {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package framework
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
class CMSMenuTest_LeftAndMainController extends LeftAndMain implements TestOnly {
|
class CMSMenuTest_LeftAndMainController extends LeftAndMain implements TestOnly {
|
||||||
|
|
||||||
private static $url_segment = 'CMSMenuTest_LeftAndMainController';
|
private static $url_segment = 'CMSMenuTest_LeftAndMainController';
|
||||||
|
|
||||||
private static $menu_title = 'CMSMenuTest_LeftAndMainController';
|
private static $menu_title = 'CMSMenuTest_LeftAndMainController';
|
||||||
|
|
||||||
private static $menu_priority = 50;
|
private static $menu_priority = 50;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
# How to customize the CMS Menu #
|
# How to customize the CMS Menu
|
||||||
|
|
||||||
## Defining a Custom Icon ##
|
## Adding a administration panel
|
||||||
|
|
||||||
Every time you add a new extension of the `api:LeftAndMain` class to the CMS, SilverStripe will automatically create a new menu-item for it, with a default title and icon.
|
Every time you add a new extension of the `[api:LeftAndMain]` class to the CMS,
|
||||||
We can easily change that behaviour by using the static `$menu_title` and `$menu_icon` statics to
|
SilverStripe will automatically create a new `[api:CMSMenuItem]` for it
|
||||||
|
|
||||||
|
The most popular extension of LeftAndMain is a `[api:ModelAdmin]` class, so
|
||||||
|
for a more detailed introduction to creating new `ModelAdmin` interfaces, read
|
||||||
|
the [ModelAdmin referencee](../reference/modeladmin).
|
||||||
|
|
||||||
|
In this document we'll take the `ProductAdmin` class used in the
|
||||||
|
[ModelAdmin referencee](../reference/modeladmin#setup) and so how we can change
|
||||||
|
the menu behaviour by using the static `$menu_title` and `$menu_icon` statics to
|
||||||
provide a custom title and icon.
|
provide a custom title and icon.
|
||||||
|
|
||||||
The most popular extension of LeftAndMain is the `api:ModelAdmin` class, so we'll use that for an example.
|
### Defining a Custom Icon
|
||||||
We'll take the `ProductAdmin` class used in the [ModelAdmin reference](../reference/modeladmin#setup).
|
|
||||||
|
|
||||||
First we'll need a custom icon. For this purpose SilverStripe uses 16x16 black-and-transparent PNG graphics.
|
First we'll need a custom icon. For this purpose SilverStripe uses 16x16
|
||||||
In this case we'll place the icon in `mysite/images`, but you are free to use any location.
|
black-and-transparent PNG graphics. In this case we'll place the icon in
|
||||||
|
`mysite/images`, but you are free to use any location.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class ProductAdmin extends ModelAdmin {
|
class ProductAdmin extends ModelAdmin {
|
||||||
@ -18,11 +26,11 @@ In this case we'll place the icon in `mysite/images`, but you are free to use an
|
|||||||
private static $menu_icon = 'mysite/images/product-icon.png';
|
private static $menu_icon = 'mysite/images/product-icon.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
## Defining a Custom Title ##
|
### Defining a Custom Title
|
||||||
|
|
||||||
The title of menu entries is configured through the `$menu_title` static.
|
The title of menu entries is configured through the `$menu_title` static.
|
||||||
If its not defined, the CMS falls back to using the class name of the controller,
|
If its not defined, the CMS falls back to using the class name of the
|
||||||
removing the "Admin" bit at the end.
|
controller, removing the "Admin" bit at the end.
|
||||||
|
|
||||||
:::php
|
:::php
|
||||||
class ProductAdmin extends ModelAdmin {
|
class ProductAdmin extends ModelAdmin {
|
||||||
@ -30,9 +38,58 @@ removing the "Admin" bit at the end.
|
|||||||
private static $menu_title = 'My Custom Admin';
|
private static $menu_title = 'My Custom Admin';
|
||||||
}
|
}
|
||||||
|
|
||||||
In order to localize the menu title in different languages, use the `<classname>.MENUTITLE`
|
In order to localize the menu title in different languages, use the
|
||||||
entity name, which is automatically created when running the i18n text collection.
|
`<classname>.MENUTITLE` entity name, which is automatically created when running
|
||||||
For more information on language and translations, please refer to the [i18n](../reference/ii8n) docs.
|
the i18n text collection.
|
||||||
|
|
||||||
|
For more information on language and translations, please refer to the
|
||||||
|
[i18n](../reference/ii8n) docs.
|
||||||
|
|
||||||
|
## Adding an external link to the menu
|
||||||
|
|
||||||
|
On top of your administration windows, the menu can also have external links
|
||||||
|
(e.g to external reference). In this example, we're going to add a link to
|
||||||
|
Google to the menu.
|
||||||
|
|
||||||
|
First, we need to define a `[api:LeftAndMainExtension]` which will contain our
|
||||||
|
button configuration.
|
||||||
|
|
||||||
|
:::php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class CustomLeftAndMain extends LeftAndMainExtension {
|
||||||
|
|
||||||
|
public function init() {
|
||||||
|
// unique identifier for this item. Will have an ID of Menu-$ID
|
||||||
|
$id = 'LinkToGoogle';
|
||||||
|
|
||||||
|
// your 'nice' title
|
||||||
|
$title = 'Google';
|
||||||
|
|
||||||
|
// the link you want to item to go to
|
||||||
|
$link = 'http://google.com';
|
||||||
|
|
||||||
|
// priority controls the ordering of the link in the stack. The
|
||||||
|
// lower the number, the lower in the list
|
||||||
|
$priority = -2;
|
||||||
|
|
||||||
|
// Add your own attributes onto the link. In our case, we want to
|
||||||
|
// open the link in a new window (not the original)
|
||||||
|
$attributes = array(
|
||||||
|
'target' => '_blank'
|
||||||
|
);
|
||||||
|
|
||||||
|
CMSMenu::add_link($id, $title, $link, $priority, $attributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
To have the link appear, make sure you add the extension to the `LeftAndMain`
|
||||||
|
class. For more information about configuring extensions see the
|
||||||
|
[DataExtension referencee](../reference/dataextension).
|
||||||
|
|
||||||
|
:::php
|
||||||
|
LeftAndMain::add_extension('CustomLeftAndMain')
|
||||||
|
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user