mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
API CHANGE: Refactor CMSMenu internals to not generate the menu item list until its actually needed, rather than from a CMSMenu::populate_menu() call in cms/_config.php. This lets an app/_config.php file actually manipulate the menu.
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@84523 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
9fbce63fa9
commit
a16ae60d59
@ -15,7 +15,7 @@ Director::addRules(50, array(
|
|||||||
'dev/buildcache/$Action' => 'RebuildStaticCacheTask',
|
'dev/buildcache/$Action' => 'RebuildStaticCacheTask',
|
||||||
));
|
));
|
||||||
|
|
||||||
CMSMenu::populate_menu();
|
CMSMenu::add_director_rules();
|
||||||
|
|
||||||
// Default CMS HTMLEditorConfig
|
// Default CMS HTMLEditorConfig
|
||||||
HtmlEditorConfig::get('cms')->setOptions(array(
|
HtmlEditorConfig::get('cms')->setOptions(array(
|
||||||
|
173
code/CMSMenu.php
173
code/CMSMenu.php
@ -6,21 +6,36 @@
|
|||||||
* @package cms
|
* @package cms
|
||||||
* @subpackage content
|
* @subpackage content
|
||||||
*/
|
*/
|
||||||
class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $menu_items = array();
|
/**
|
||||||
|
* An array of changes to be made to the menu items, in the order that the changes should be
|
||||||
|
* applied. Each item is a map in one of the two forms:
|
||||||
|
* - array('type' => 'add', 'item' => new CMSMenuItem(...) )
|
||||||
|
* - array('type' => 'remove', 'code' => 'codename' )
|
||||||
|
*/
|
||||||
|
protected static $menu_item_changes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true if clear_menu() is called, to indicate that the default menu shouldn't be
|
||||||
|
* included
|
||||||
|
*/
|
||||||
|
protected static $menu_is_cleared = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate CMS main menu items by collecting valid
|
* Generate CMS main menu items by collecting valid
|
||||||
* subclasses of {@link LeftAndMain}
|
* subclasses of {@link LeftAndMain}
|
||||||
*/
|
*/
|
||||||
public static function populate_menu() {
|
public static function populate_menu() {
|
||||||
$cmsClasses = self::get_cms_classes();
|
self::$menu_is_cleared = false;
|
||||||
foreach($cmsClasses as $cmsClass) {
|
|
||||||
self::add_controller($cmsClass);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
/**
|
||||||
|
* Add Director rules for all of the CMS controllers.
|
||||||
|
*/
|
||||||
|
public static function add_director_rules() {
|
||||||
|
array_map(array('self','add_director_rule_for_controller'), self::get_cms_classes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,10 +47,15 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
* when the item is removed. Functionality needed in {@link Director}.
|
* when the item is removed. Functionality needed in {@link Director}.
|
||||||
*/
|
*/
|
||||||
public static function add_controller($controllerClass) {
|
public static function add_controller($controllerClass) {
|
||||||
|
self::add_menu_item_obj($controllerClass, self::menuitem_for_controller($controllerClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a CMSMenuItem to add the given controller to the CMSMenu
|
||||||
|
*/
|
||||||
|
protected static function menuitem_for_controller($controllerClass) {
|
||||||
$urlBase = Object::get_static($controllerClass, 'url_base');
|
$urlBase = Object::get_static($controllerClass, 'url_base');
|
||||||
$urlSegment = Object::get_static($controllerClass, 'url_segment');
|
$urlSegment = Object::get_static($controllerClass, 'url_segment');
|
||||||
$urlRule = Object::get_static($controllerClass, 'url_rule');
|
|
||||||
$urlPriority = Object::get_static($controllerClass, 'url_priority');
|
|
||||||
$menuPriority = Object::get_static($controllerClass, 'menu_priority');
|
$menuPriority = Object::get_static($controllerClass, 'menu_priority');
|
||||||
|
|
||||||
// Don't add menu items defined the old way
|
// Don't add menu items defined the old way
|
||||||
@ -43,27 +63,32 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
|
|
||||||
$link = Controller::join_links($urlBase, $urlSegment) . '/';
|
$link = Controller::join_links($urlBase, $urlSegment) . '/';
|
||||||
|
|
||||||
|
// doesn't work if called outside of a controller context (e.g. in _config.php)
|
||||||
|
// as the locale won't be detected properly. Use {@link LeftAndMain->MainMenu()} to update
|
||||||
|
// titles for existing menu entries
|
||||||
|
$defaultTitle = LeftAndMain::menu_title_for_class($controllerClass);
|
||||||
|
$menuTitle = _t("{$controllerClass}.MENUTITLE", $defaultTitle);
|
||||||
|
|
||||||
|
return new CMSMenuItem($menuTitle, $link, $controllerClass, $menuPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the appropriate Director rules for the given controller.
|
||||||
|
*/
|
||||||
|
protected static function add_director_rule_for_controller($controllerClass) {
|
||||||
|
$urlBase = Object::get_static($controllerClass, 'url_base');
|
||||||
|
$urlSegment = Object::get_static($controllerClass, 'url_segment');
|
||||||
|
$urlRule = Object::get_static($controllerClass, 'url_rule');
|
||||||
|
$urlPriority = Object::get_static($controllerClass, 'url_priority');
|
||||||
|
|
||||||
|
$link = Controller::join_links($urlBase, $urlSegment) . '/';
|
||||||
|
|
||||||
// Make director rule
|
// Make director rule
|
||||||
if($urlRule[0] == '/') $urlRule = substr($urlRule,1);
|
if($urlRule[0] == '/') $urlRule = substr($urlRule,1);
|
||||||
$rule = $link . '/' . $urlRule; // the / will combine with the / on the end of $link to make a //
|
$rule = $link . '/' . $urlRule; // the / will combine with the / on the end of $link to make a //
|
||||||
Director::addRules($urlPriority, array(
|
Director::addRules($urlPriority, array(
|
||||||
$rule => $controllerClass
|
$rule => $controllerClass
|
||||||
));
|
));
|
||||||
|
|
||||||
// doesn't work if called outside of a controller context (e.g. in _config.php)
|
|
||||||
// as the locale won't be detected properly. Use {@link LeftAndMain->MainMenu()} to update
|
|
||||||
// titles for existing menu entries
|
|
||||||
$defaultTitle = LeftAndMain::menu_title_for_class($controllerClass);
|
|
||||||
$menuTitle = _t("{$controllerClass}.MENUTITLE", $defaultTitle);
|
|
||||||
|
|
||||||
// Add menu item
|
|
||||||
return self::add_menu_item(
|
|
||||||
$controllerClass,
|
|
||||||
$menuTitle,
|
|
||||||
$link,
|
|
||||||
$controllerClass,
|
|
||||||
$menuPriority
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,9 +122,6 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
// 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;
|
||||||
|
|
||||||
$menuItems = self::$menu_items;
|
|
||||||
if(isset($menuItems[$code])) return false;
|
|
||||||
|
|
||||||
return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority);
|
return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +132,7 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function get_menu_item($code) {
|
public static function get_menu_item($code) {
|
||||||
$menuItems = self::$menu_items;
|
$menuItems = self::get_menu_items();
|
||||||
return (isset($menuItems[$code])) ? $menuItems[$code] : false;
|
return (isset($menuItems[$code])) ? $menuItems[$code] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +142,43 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function get_menu_items() {
|
public static function get_menu_items() {
|
||||||
return self::$menu_items;
|
$menuItems = array();
|
||||||
|
|
||||||
|
// Set up default menu items
|
||||||
|
if(!self::$menu_is_cleared) {
|
||||||
|
$cmsClasses = self::get_cms_classes();
|
||||||
|
foreach($cmsClasses as $cmsClass) {
|
||||||
|
$menuItems[$cmsClass] = self::menuitem_for_controller($cmsClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply changes
|
||||||
|
foreach(self::$menu_item_changes as $change) {
|
||||||
|
switch($change['type']) {
|
||||||
|
case 'add':
|
||||||
|
$menuItems[$change['code']] = $change['item'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'remove':
|
||||||
|
unset($menuItems[$change['code']]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
user_error("Bad menu item change type {$change[type]}", E_USER_WARNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort menu items according to priority
|
||||||
|
$menuPriority = array();
|
||||||
|
$i = 0;
|
||||||
|
foreach($menuItems as $key => $menuItem) {
|
||||||
|
$i++;
|
||||||
|
// This funny litle formula ensures that the first item added with the same priority will be left-most.
|
||||||
|
$menuPriority[$key] = $menuItem->priority*100 - $i;
|
||||||
|
}
|
||||||
|
array_multisort($menuPriority, SORT_DESC, $menuItems);
|
||||||
|
|
||||||
|
return $menuItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,18 +212,15 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
* @param string $code Unique identifier for this menu item
|
* @param string $code Unique identifier for this menu item
|
||||||
*/
|
*/
|
||||||
public static function remove_menu_item($code) {
|
public static function remove_menu_item($code) {
|
||||||
$menuItems = self::$menu_items;
|
self::$menu_item_changes[] = array('type' => 'remove', 'code' => $code);
|
||||||
if(isset($menuItems[$code])) unset($menuItems[$code]);
|
|
||||||
// replace the whole array
|
|
||||||
self::$menu_items = $menuItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the entire menu
|
* Clears the entire menu
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static function clear_menu() {
|
public static function clear_menu() {
|
||||||
self::$menu_items = array();
|
self::$menu_item_changes = array();
|
||||||
|
self::$menu_is_cleared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,20 +237,22 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
* @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) {
|
||||||
$menuItems = self::$menu_items;
|
self::$menu_item_changes[] = array(
|
||||||
$menuItems[$code] = new CMSMenuItem($menuTitle, $url, $controllerClass, $priority);
|
'type' => 'add',
|
||||||
|
'code' => $code,
|
||||||
$menuPriority = array();
|
'item' => new CMSMenuItem($menuTitle, $url, $controllerClass, $priority),
|
||||||
$i = 0;
|
);
|
||||||
foreach($menuItems as $key => $menuItem) {
|
|
||||||
$i++;
|
|
||||||
// This funny litle formula ensures that the first item added with the same priority will be left-most.
|
|
||||||
$menuPriority[$key] = $menuItem->priority*100 - $i;
|
|
||||||
}
|
}
|
||||||
array_multisort($menuPriority, SORT_DESC, $menuItems);
|
|
||||||
|
|
||||||
self::$menu_items = $menuItems;
|
/**
|
||||||
return true;
|
* Add a previously built menuitem object to the menu
|
||||||
|
*/
|
||||||
|
protected static function add_menu_item_obj($code, $cmsMenuItem) {
|
||||||
|
self::$menu_item_changes[] = array(
|
||||||
|
'type' => 'add',
|
||||||
|
'code' => $code,
|
||||||
|
'item' => $cmsMenuItem,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,25 +282,11 @@ class CMSMenu extends Object implements Iterator, i18nEntityProvider
|
|||||||
return $subClasses;
|
return $subClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterator Interface Methods
|
/**
|
||||||
public function key() {
|
* IteratorAggregate Interface Method. Iterates over the menu items.
|
||||||
return key(self::$menu_items);
|
*/
|
||||||
}
|
function getIterator() {
|
||||||
|
return new ArrayIterator(self::get_menu_items());
|
||||||
public function current() {
|
|
||||||
return current(self::$menu_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function next() {
|
|
||||||
return next(self::$menu_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rewind() {
|
|
||||||
return reset(self::$menu_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function valid() {
|
|
||||||
return (bool)self::current();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user