Permalink
Browse files

API: Add attributes argument for CMSMenuItem.

Currently help menu item is the only external link in the CMS and the ability for it to work is hardcoded in the template. This request makes the target attribute definable by CMSMenu::add_link().

Adds documentation for how to add a basic external link to the CMS.
  • Loading branch information...
1 parent e4ff3b8 commit 2d0a3544055dfa8f2b7147c09197478c5ade95f7 @wilr wilr committed Oct 2, 2013
View
@@ -1,16 +1,21 @@
<?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}.
- * That is, for each class in the CMS that creates an administration panel, a CMS menu item will be created.
- * The default configuration will also include a 'help' link to the SilverStripe user documentation.
+ * The menu will be automatically populated with menu items for subclasses of
+ * {@link LeftAndMain}. That is, for each class in the CMS that creates an
+ * 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
- * @subpackage content
+ * @package framework
+ * @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
@@ -79,10 +84,12 @@ protected static function menuitem_for_controller($controllerClass) {
* @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
* left.
+ * @param array $attributes an array of attributes to include on the link.
+ *
* @return boolean The result of the operation.
*/
- public static function add_link($code, $menuTitle, $url, $priority = -1) {
- return self::add_menu_item($code, $menuTitle, $url, null, $priority);
+ public static function add_link($code, $menuTitle, $url, $priority = -1, $attributes = null) {
+ return self::add_menu_item($code, $menuTitle, $url, null, $priority, $attributes);
}
/**
@@ -97,13 +104,17 @@ public static function add_link($code, $menuTitle, $url, $priority = -1) {
* @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
* 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
*/
- 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($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 @@ public static function clear_menu() {
* @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
* 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
*/
- 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(
'type' => 'add',
'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) {
self::$menu_item_changes[] = array(
View
@@ -1,12 +1,18 @@
<?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
- * @subpackage content
+ * @see CMSMenu
+ *
+ * @package framework
+ * @subpackage admin
*/
-class CMSMenuItem extends Object
-{
+class CMSMenuItem extends Object {
+
/**
* The (translated) menu title
* @var string $title
@@ -32,7 +38,16 @@ class CMSMenuItem extends Object
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
+ *
* @param string $title
* @param string $url
* @param string $controller Controller class name
@@ -43,7 +58,41 @@ public function __construct($title, $url, $controller = null, $priority = -1) {
$this->url = $url;
$this->controller = $controller;
$this->priority = $priority;
+
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 @@ public function init() {
'Help',
_t('LeftAndMain.HELP', 'Help', 'Menu title'),
$this->config()->help_link,
- -2
+ -2,
+ array(
+ 'target' => '_blank'
+ )
);
// Allow customisation of the access check by a extension
@@ -616,6 +619,7 @@ public function MainMenu($cached = true) {
if($menuItems) {
foreach($menuItems as $code => $menuItem) {
// alternate permission checks (in addition to LeftAndMain->canView())
+
if(
isset($menuItem->controller)
&& $this->hasMethod('alternateMenuDisplayCheck')
@@ -661,9 +665,10 @@ public function MainMenu($cached = true) {
$menuIcon = LeftAndMain::menu_icon_for_class($menuItem->controller);
if (!empty($menuIcon)) $menuIconStyling .= $menuIcon;
}
-
+
$menu->push(new ArrayData(array(
"MenuItem" => $menuItem,
+ "AttributesHTML" => $menuItem->getAttributesHTML(),
"Title" => Convert::raw2xml($title),
"Code" => DBField::create_field('Text', $code),
"Link" => $menuItem->url,
@@ -230,6 +230,13 @@
// Ignore external links, fallback to standard link behaviour
var isExternal = $.path.isExternal(this.attr('href'));
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();
var item = this.getMenuItem();
@@ -24,7 +24,7 @@
<ul class="cms-menu-list">
<% loop $MainMenu %>
<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}">&nbsp;</span>
<span class="text">$Title</span>
</a>
@@ -1,6 +1,6 @@
<?php
/**
- * @package cms
+ * @package framework
* @subpackage tests
*/
class CMSMenuTest extends SapphireTest implements TestOnly {
@@ -35,7 +35,21 @@ public function testBasicMenuHandling() {
$this->assertNull($menuItem->controller, 'Link menu item has no controller class');
$this->assertEquals($menuItem->priority, -1, 'Link menu item has the correct priority');
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() {
@@ -81,8 +95,15 @@ public function testAdvancedMenuHandling() {
}
+/**
+ * @package framework
+ * @subpackage tests
+ */
class CMSMenuTest_LeftAndMainController extends LeftAndMain implements TestOnly {
+
private static $url_segment = 'CMSMenuTest_LeftAndMainController';
+
private static $menu_title = 'CMSMenuTest_LeftAndMainController';
+
private static $menu_priority = 50;
}
@@ -1,38 +1,95 @@
-# 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.
-We can easily change that behaviour by using the static `$menu_title` and `$menu_icon` statics to
+Every time you add a new extension of the `[api:LeftAndMain]` class to the CMS,
+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.
-The most popular extension of LeftAndMain is the `api:ModelAdmin` class, so we'll use that for an example.
-We'll take the `ProductAdmin` class used in the [ModelAdmin reference](../reference/modeladmin#setup).
+### Defining a Custom Icon
-First we'll need a custom icon. For this purpose SilverStripe uses 16x16 black-and-transparent PNG graphics.
-In this case we'll place the icon in `mysite/images`, but you are free to use any location.
+First we'll need a custom icon. For this purpose SilverStripe uses 16x16
+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
class ProductAdmin extends ModelAdmin {
// ...
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.
-If its not defined, the CMS falls back to using the class name of the controller,
-removing the "Admin" bit at the end.
+If its not defined, the CMS falls back to using the class name of the
+controller, removing the "Admin" bit at the end.
:::php
class ProductAdmin extends ModelAdmin {
// ...
private static $menu_title = 'My Custom Admin';
}
-In order to localize the menu title in different languages, use the `<classname>.MENUTITLE`
-entity name, which is automatically created when running the i18n text collection.
-For more information on language and translations, please refer to the [i18n](../reference/ii8n) docs.
+In order to localize the menu title in different languages, use the
+`<classname>.MENUTITLE` entity name, which is automatically created when running
+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

0 comments on commit 2d0a354

Please sign in to comment.