? .DS_Store ? menu_item_grouping_00.patch ? menu_item_grouping_01.patch ? modules/.DS_Store ? sites/default/.DS_Store ? sites/default/settings.php Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.856 diff -u -p -r1.856 common.inc --- includes/common.inc 23 Jan 2009 14:23:27 -0000 1.856 +++ includes/common.inc 25 Jan 2009 13:39:59 -0000 @@ -3476,6 +3476,9 @@ function drupal_common_theme() { 'arguments' => array('form' => NULL), ), // from menu.inc + 'menu_item_grouping' => array( + 'arguments' => array('items' => NULL), + ), 'menu_item_link' => array( 'arguments' => array('item' => NULL), ), Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.310 diff -u -p -r1.310 menu.inc --- includes/menu.inc 4 Jan 2009 20:04:32 -0000 1.310 +++ includes/menu.inc 25 Jan 2009 13:40:01 -0000 @@ -141,7 +141,16 @@ define('MENU_NORMAL_ITEM', MENU_VISIBLE_ define('MENU_CALLBACK', MENU_VISIBLE_IN_BREADCRUMB); /** - * Menu type -- A normal menu item, hidden until enabled by an administrator. + * Menu type -- A menu item that lists all its children. + * + * If a menu item's sole purpose is to serve as a "container" for other menu + * items, it's callback is an item grouping. They act as normal items, the + * difference is that page and access callbacks are applied automatically. + */ +define('MENU_ITEM_GROUPING', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB | 0x0010); + +/** + * Menu type -- A "normal" menu item, hidden until enabled by an administrator. * * Modules may "suggest" menu items that the administrator may enable. They act * just as callbacks do until enabled, at which time they act like normal items. @@ -1222,6 +1231,82 @@ function _menu_tree_data($result, $paren } /** + * List a menu item's children. + * + * @return string + */ +function menu_item_grouping() { + $item = menu_get_item(); + $items = system_admin_menu_block($item); + // Bypass the listing if only one child is available. + if (count($items) == 1) { + $item = array_shift($items); + drupal_goto($item['href']); + } + return theme('menu_item_grouping', $items); +} + +/** + * Determine if a user should have access to a menu item. + * + * Users should only have access if all of the following cases are true: + * - The user has access to at least one of this item's children. + * - The custom access callback (if any) returns TRUE. + * + * @param $path string + * The path of the menu item to check access to. + * @param $callback string + * A custom access callback to check as well. + * @param $arguments array + * Arguments to pass on to the access callback. + * + * @return boolean + */ +function menu_item_grouping_access($path, $callback, $arguments) { + if (is_string($callback)) { + $custom_access = call_user_func_array($callback, $arguments); + } + + $item = array('path' => $path); + $items = system_admin_menu_block($item); + foreach ($items as $child) { + _menu_check_access($child, array()); + if ($child['access']) { + if ($custom_access) { + return TRUE; + } + else { + return FALSE; + } + } + } + + return FALSE; +} + +/** + * Theme a list of menu items. + * + * @param $items + * The items as returned from system_admin_menu_block(). + * + * @return string + */ +function theme_menu_item_grouping($items) { + $output = ''; + + if ($items) { + $output = ''; + } + return $output; +} + +/** * Generate the HTML output for a single menu link. * * @ingroup themeable @@ -2569,6 +2654,14 @@ function _menu_router_build($callbacks) $item['access callback'] = intval($item['access callback']); } + if ($item['type'] == MENU_ITEM_GROUPING) { + $item['page callback'] = 'menu_item_grouping'; + // MENU_ITEM_GROUPING items may have two access callbacks. + $access_arguments = isset($item['access arguments']) ? $item['access arguments'] : array(); + $item['access arguments'] = array($path, $item['access callback'], $access_arguments); + $item['access callback'] = 'menu_item_grouping_access'; + } + $item += array( 'access arguments' => array(), 'access callback' => '', Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1018 diff -u -p -r1.1018 node.module --- modules/node/node.module 22 Jan 2009 12:46:06 -0000 1.1018 +++ modules/node/node.module 25 Jan 2009 13:40:02 -0000 @@ -1656,7 +1656,7 @@ function node_menu() { ); $items['node/add'] = array( 'title' => 'Create content', - 'page callback' => 'node_add_page', + 'type' => MENU_ITEM_GROUPING, 'access callback' => '_node_add_access', 'weight' => 1, );