? admin_menu_d6_0.patch ? total-d6-menu-132524-65.patch ? total-d6-menu-132524-66.patch ? tests/admin_menu.test Index: CHANGELOG.txt =================================================================== RCS file: /cvs/drupal/contributions/modules/admin_menu/CHANGELOG.txt,v retrieving revision 1.33 diff -u -p -r1.33 CHANGELOG.txt --- CHANGELOG.txt 26 Apr 2008 16:20:19 -0000 1.33 +++ CHANGELOG.txt 6 Jun 2008 20:02:38 -0000 @@ -8,6 +8,7 @@ Admin Menu 6.x-x.x, xxxx-xx-xx ------------------------------ #132524 by sun: Moved gettext translation files into translations. #132524 by sun: Committing pre-alpha code for D6 due to public demand. +#132524 by pwolanin: Major rewrite to better use Drupal 6 menu system. Admin Menu 5.x-2.x, xxxx-xx-xx Index: README.txt =================================================================== RCS file: /cvs/drupal/contributions/modules/admin_menu/README.txt,v retrieving revision 1.20 diff -u -p -r1.20 README.txt --- README.txt 6 Apr 2008 15:29:02 -0000 1.20 +++ README.txt 6 Jun 2008 20:02:38 -0000 @@ -3,11 +3,11 @@ -- SUMMARY -- Drupal Administration Menu displays the whole menu tree below /admin including -all invisible local tasks in a drop-down menu. So administrators need less time +most local tasks in a drop-down menu. So administrators need less time to access pages which are only visible after one or two clicks normally. -Admin menu also provides hook_admin_menu() that allows other modules to add or -alter menu items. +Admin menu also provides hook_admin_menu() that allows other modules to add +menu links. For a full description visit the project page: http://drupal.org/project/admin_menu @@ -39,10 +39,10 @@ None. - display drupal links: Displays additional links to Drupal.org and issue queues of all enabled contrib modules in the Drupal Administration Menu icon. - Please bear in mind that the displayed menu items in Drupal Administration Menu - depend on the actual permissions of a user. For example, if a user does not - have the permission 'administer access control' and 'administer users', the - whole 'User management' menu item will not be displayed. +Please bear in mind that the displayed menu items in Drupal Administration Menu +depend on the actual permissions of a user. For example, if a user does not +have the permission 'administer access control' and 'administer users', the +whole 'User management' menu item will not be displayed. -- CUSTOMIZATION -- @@ -89,34 +89,11 @@ body #admin-menu { font-size: 10px; } -- FAQ -- -Q: After upgrading to 5.x-2.x, admin_menu disappeared. Why? +Q: After upgrading to 6.x-1.x, admin_menu disappeared. Why? A: This should not happen. If it did, visit - http:///admin/build/menu to re-generate your menu cache. - -Q: After upgrading, admin_menu disappeared. Why? - -A: Prior to release 5.x-1.2, Drupal Administration Menu was output in a block. - Since 5.x-1.2, it is output via hook_footer(). Some custom themes may not - (yet) output $closure, so admin_menu could no longer be displayed. If you - decided to move the 'administer' tree into a new menu and disabled that menu - block, a site could become (temporarily) unmaintainable. Either way, you - should fix your theme by adding the following code in front of the closing - HTML () tag: - - - - -Q: After upgrading, the menu item 'administer' is no longer removed. Why? - -A: Prior to release 5.x-1.2, Drupal Administration Menu was output via - hook_block(), which allowed to alter the global menu array. Since 5.x-1.2, it - is output via hook_footer() and thus no longer able to alter the menu. As - long as there will be no built-in solution in an upcoming release, you may - perform the following steps as a workaround: - - Create a new menu. - - Edit the menu item 'administer' and select the new menu as parent. - + http:///admin/build/modules to re-generate your menu. + Q: I enabled "Aggregate and compress CSS files", but I found admin_menu.css is still there, is it normal? @@ -131,6 +108,8 @@ Current maintainers: * Daniel F. Kudwien (sun) - dev@unleashedmind.com * Stefan M. Kudwien (smk-ka) - dev@unleashedmind.com +Drupal 6 upgrade with help from Peter Wolanin (pwolanin) + This project has been sponsored by: * UNLEASHED MIND Specialized in consulting and planning of Drupal powered sites, UNLEASHED Index: admin_menu.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/admin_menu/admin_menu.inc,v retrieving revision 1.11 diff -u -p -r1.11 admin_menu.inc --- admin_menu.inc 26 Apr 2008 16:10:09 -0000 1.11 +++ admin_menu.inc 6 Jun 2008 20:02:39 -0000 @@ -2,367 +2,248 @@ // $Id: admin_menu.inc,v 1.11 2008/04/26 16:10:09 sun Exp $ /** - * @file - * Cached builder functions for Drupal Administration Menu. - */ - -/** - * Build the administration menu tree. + * The key function that builds the menu links whenever there is a menu rebuild. * - * This is only called if the menu has been modified, i.e. the menu cache has - * been cleared. - * - * @param int $mid_admin - * The menu item id to use for the administration menu. */ -function admin_menu_build($mid_admin) { - global $_menu; - $_admin_menu = array(); - - // Retrieve the full menu structure. - $_admin_menu = admin_menu_tree_all_data(); - - // Adjust some menu items for better user experience. - #admin_menu_adjust_items($_admin_menu); - - // Allow other modules to integrate with admin_menu. - foreach (module_implements('admin_menu') as $module) { - $function = $module .'_admin_menu'; - #$function($_admin_menu, TRUE); +function _admin_menu_rebuild_links() { + // Get the newly rebuilt menu + $menu = menu_router_build(); + // Add normal and suggested items as links. + $menu_links = array(); + foreach ($menu as $path => $item) { + + if (($item['type'] != MENU_CALLBACK) && ($item['_parts'][0] == 'admin') && (count($item['_parts']) > 1)) { + // TODO: handle local tasks with wildcards + if (!strpos($path, '%')) { + $item = admin_menu_link_build($item); + $menu_links[$path] = $item; + $sort[$path] = $item['_number_parts']; + } + } + } + admin_menu_adjust_items($menu_links, $sort); + if ($menu_links) { + // Make sure no child comes before its parent. + array_multisort($sort, SORT_NUMERIC, $menu_links); + + // KISS for now - completely rebuild each time. + db_query("DELETE FROM {menu_links} WHERE module = '%s'", 'admin_menu'); + foreach ($menu_links as $item) { + menu_link_save($item); + } + } + // Allow modules to add more links. If you want to alter links saved by + // admin_menu, use hook_menu_link_alter() and look for + // $item['module'] == 'admin_menu' + $links = module_invoke_all('admin_menu'); + foreach ($links as $item) { + admin_menu_link_save($item); } - - return $_admin_menu; } /** - * Get the data structure representing the administrative menu tree. - * - * @see menu_tree_all_data() + * Prepare a menu link from basic information formatted for a router item. */ -function admin_menu_tree_all_data() { - // chx way. 13/03/2008 sun - // $item_admin = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE link_path = 'admin' AND menu_name = 'navigation'")); - $item_admin = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE router_path = 'admin'")); - $item_admin = array_merge_recursive($item_admin, menu_get_item('admin')); - - // chx way. 13/03/2008 sun - // $data['tree'] = menu_tree_all_data('navigation', $item_admin); - // return $data['tree']; - - $args = $parents = array($item_admin['mlid']); - $placeholders = implode(', ', array_fill(0, count($args), '%d')); - - // Collect all links as well as all of their children. - do { - $result = db_query("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND has_children = 1 AND plid IN (". $placeholders .') AND mlid NOT IN ('. $placeholders .')', array_merge(array($item_admin['menu_name']), $args, $args)); - $num_rows = FALSE; - while ($item = db_fetch_array($result)) { - $args[] = $item['mlid']; - $num_rows = TRUE; - } - $placeholders = implode(', ', array_fill(0, count($args), '%d')); - } while ($num_rows); - - // Build db_query arguments array. - array_unshift($args, $item_admin['menu_name']); - - // Until now, everything seems to be a wanted behaviour of the new menu system - // in Drupal 6. However, {menu_links} does not contain any local tasks, and - // because of that, it's getting crude now. - - // Select the links from the table, and recursively build the tree. We - // LEFT JOIN since there is no match in {menu_router} for an external - // link. - // Union select all local tasks from {menu_router} - // - that start with 'admin/', - // - using the mlid of the corresponding tab_parent path in {menu_links} as plid, - // - using the depth of the tab_parent path in {menu_links} + 1 as depth. - $types = array(MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK); - $args = array_merge($args, $types); - $data['tree'] = menu_tree_data(db_query("( - SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, ml.* - FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path - WHERE ml.menu_name = '%s' AND ml.plid IN (". $placeholders .") - ) UNION ( - SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, - ml.menu_name, ml.mlid + 100000 as mlid, ml.plid, ml.link_path, ml.router_path, m.title as link_title, ml.options, ml.module, ml.hidden, ml.external, ml.has_children, ml.expanded, ml.weight, ml.depth + 1 as depth, ml.customized, ml.p1, ml.p2, ml.p3, ml.p4, ml.p5, ml.p6, ml.p7, ml.p8, ml.p9, ml.updated - FROM {menu_router} m LEFT JOIN {menu_links} ml ON ml.router_path = m.tab_parent - WHERE ml.router_path REGEXP '[^%%]*' AND m.path LIKE 'admin/%%' AND m.type IN (". db_placeholders($types) .") - ) - ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents); - - $data['node_links'] = array(); - menu_tree_collect_node_links($data['tree'], $data['node_links']); - - // Check access for the current user to each item in the tree. - menu_tree_check_access($data['tree'], $data['node_links']); - - return $data['tree']; +function admin_menu_link_build($item) { + $item['module'] = 'admin_menu'; + $item['menu_name'] = 'admin_menu'; + $item += array( + 'link_title' => $item['title'], + 'link_path' => $item['path'], + 'hidden' => 0, + 'options' => array(), + ); + $item['options']['alter'] = TRUE; + if (!empty($item['description'])) { + $item['options']['attributes']['title'] = $item['description']; + } + if (!empty($item['query'])) { + $item['options']['query'] = $item['query']; + } + return $item; } /** - * Recursively adds items to the administration menu. - * - * Any accessible menu items are added, including local tasks. - * - * @param array $_admin_menu - * An array containing the complete administration menu structure, passed by - * reference. - * @param array $item - * The (starting) menu item to use for the administration menu. + * Convenience function that looks up the plid if $item['parent_path'] is set. */ -function _admin_menu_get_children(&$_admin_menu, &$item) { - global $_menu; - - if (isset($item['children'])) { - foreach ($item['children'] as $child) { - // Check access permissions. - if (!variable_get('admin_menu_show_all', 0)) { - $item_is_accessible = !isset($_menu['items'][$child]['access']) || (isset($_menu['items'][$child]['access']) && $_menu['items'][$child]['access']); - } - else { - $item_is_accessible = TRUE; - } - // Check menu item type. - $item_is_visible = $_menu['items'][$child]['type'] & (MENU_VISIBLE_IN_TREE | MENU_IS_LOCAL_TASK); - - // Create the child item if it is accessible and visible. - // Additional condition to hide items linking to parent: - // && !($_menu['items'][$child]['type'] & MENU_LINKS_TO_PARENT) - if ($item_is_accessible && $item_is_visible) { - $_admin_menu[$child] = $_menu['items'][$child]; - admin_menu_item_url($_admin_menu, $child); - - // Recurse to child menu items. - if (isset($_menu['items'][$child]['children'])) { - _admin_menu_get_children($_admin_menu, $_admin_menu[$child]); - } - - // Remove this child item if it is visible in the navigation. - unset($_menu['visible'][$child]); - } - else { - // Remove child menu item from parent's children list. - $parent_id = $_menu['items'][$child]['pid']; - if (isset($_menu['items'][$parent_id]['children']) && is_array($_menu['items'][$parent_id]['children'])) { - $child_key = array_search($child, $_menu['items'][$parent_id]['children']); - if ($child_key !== FALSE) { - unset($_admin_menu[$parent_id]['children'][$child_key]); - } - } - } +function admin_menu_link_save($item) { + if (isset($item['parent_path'])) { + $plid = db_result(db_query("SELECT mlid from {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", 'admin_menu', $item['parent_path'])); + if ($plid) { + $item['plid'] = $plid; } } + $item = admin_menu_link_build($item); + menu_link_save($item); } /** - * Add some hard-coded features for better user experience. - * - * @param array $_admin_menu - * An array containing the complete administration menu structure, passed by - * reference. + * Implementation of hook_admin_menu(). */ -function admin_menu_adjust_items(&$_admin_menu) { - global $_menu, $user, $base_url; - - // Add the icon containing special links. - $mid_admin = $_admin_menu['index']['admin']; - $mid_icon = admin_menu_add_item($_admin_menu, $mid_admin, array( - 'title' => theme('admin_menu_icon'), - 'path' => drupal_get_normal_path(variable_get('site_frontpage', 'node')), - 'weight' => -100, - 'class' => 'admin-menu-icon', - )); - $_admin_menu['index']['admin_menu_icon'] = $mid_icon; - +function admin_menu_admin_menu() { + global $base_url; + + $icon_path = drupal_get_normal_path(variable_get('site_frontpage', 'node')); + + $links[] = array( + 'title' => 'Drupal.org', + 'path' => 'http://drupal.org', + 'weight' => 100, + 'parent_path' => $icon_path, + ); // Add 'administer' item to the icon menu. - $mid_icon_admin = admin_menu_add_item($_admin_menu, $mid_icon, array('title' => 'Administer', 'path' => 'admin', 'weight' => 10)); - // ...and reset 'administer' menu item id in path index. - $_admin_menu['index']['admin'] = $mid_admin; - - // Move 'By module' item if accessible, or remove it. - $mid_bymodule = $_admin_menu['index']['admin/by-module']; - if (user_access('administer site configuration')) { - admin_menu_move_item($_admin_menu, $mid_bymodule, $mid_icon_admin); - } - else { - admin_menu_remove_item($_admin_menu, 'admin/by-module'); - } - - // Remove 'By task' menu item. - admin_menu_remove_item($_admin_menu, 'admin/by-task'); - + $links[] = array( + 'title' => 'Administer', + 'path' => 'admin', + 'weight' => 10, + 'parent_path' => $icon_path, + ); + // Add system update links. - admin_menu_add_item($_admin_menu, $mid_icon, array('title' => 'Run cron', 'path' => 'admin/reports/status/run-cron', 'weight' => 50, 'query' => drupal_get_destination())); - if ($user->uid == 1) { - admin_menu_add_item($_admin_menu, $mid_icon, array('title' => 'Run updates', 'path' => $base_url .'/update.php', 'weight' => 50)); - } - - // Add links to drupal.org. - if (user_access('display drupal links')) { - $mid_drupal = admin_menu_add_item($_admin_menu, $mid_icon, array('title' => 'Drupal.org', 'path' => 'http://drupal.org', 'weight' => 100)); - admin_menu_add_item($_admin_menu, $mid_drupal, array('title' => 'Drupal issue queue', 'path' => 'http://drupal.org/project/issues/drupal')); - - // Add links to project issue queues. - foreach (module_list(FALSE, FALSE, TRUE) as $module) { - $info = drupal_parse_info_file(drupal_get_path('module', $module) .'/'. $module .'.info'); - if (isset($info['project']) && $info['project'] == 'drupal') { - continue; - } - $url = 'http://drupal.org/project/issues/'. $module; - // Filter project versions via query string not yet supported. - // @see http://drupal.org/node/97569 - // $url .= !empty($info['version']) ? '/'. $info['version'] : ''; - admin_menu_add_item($_admin_menu, $mid_drupal, array('title' => '@title issue queue', 'title arguments' => array('@title' => $info['name']), 'path' => $url)); - } - } - - // Add logout item. - if ($user->uid > 0) { - $mid_logout = $_menu['path index']['logout']; - admin_menu_add_item($_admin_menu, $mid_admin, array( - 'title' => 'Logout @name', - 'title arguments' => array('@name' => $user->name), - 'path' => $_menu['items'][$mid_logout]['path'], + $links[] = array( + 'title' => 'Run cron', + 'path' => 'admin/reports/status/run-cron', + 'weight' => 50, + 'parent_path' => $icon_path, + ); + $links[] = array( + 'title' => 'Run updates', + 'path' => $base_url .'/update.php', + 'weight' => 50, + 'parent_path' => $icon_path, + ); + + // Add links to project issue queues. + $links[] = array( + 'title' => 'Drupal issue queue', + 'path' => 'http://drupal.org/project/issues/drupal', + 'weight' => -10, + 'parent_path' => 'http://drupal.org', + ); + + foreach (module_list(FALSE, FALSE, TRUE) as $module) { + $info = drupal_parse_info_file(drupal_get_path('module', $module) .'/'. $module .'.info'); + + if (!isset($info['project']) || $info['project'] == 'drupal') { + continue; + } + $url = 'http://drupal.org/project/issues/'. $info['project']; + $links[] = array( + 'title' => check_plain($info['name']) . 'issue queue', + 'path' => $url, + 'parent_path' => 'http://drupal.org', + ); + } + $links[] = array( + 'title' => 'Create content', + 'path' => 'node/add', + 'weight' => -100, + 'parent_path' => 'admin/content', + ); + foreach (node_get_types('types', NULL, TRUE) as $type) { + $type_url_str = str_replace('_', '-', $type->type); + $path = 'node/add/'. $type_url_str; + $links[] = array( + 'title' => $type->name, + 'path' => $path, 'weight' => -100, - 'class' => 'admin-menu-action admin-menu-logout', - )); - } - - // Add 'Create ' menu items to Content management > Content. - // If an user does not have 'administer nodes' permission, we need to copy - // the 'Create content' item from the Navigation menu into 'Content - // management' and append node/add/* items there instead. - if (!user_access('administer nodes')) { - $mid_content_management = $_admin_menu['index']['admin/content']; - $mid_node_add = $_menu['path index']['node/add']; - $create_content = $_menu['items'][$mid_node_add]; - $create_content['weight'] = 0; - $mid_content = admin_menu_add_item($_admin_menu, $mid_content_management, $create_content); + 'parent_path' => 'node/add', + ); } - else { - $mid_content = $_admin_menu['index']['admin/content/node']; - } - $mid_node_add = $_menu['path index']['node/add']; - admin_menu_copy_items($_admin_menu, $mid_node_add, $mid_content, 'Add @title'); -} -/** - * Recursively copy menu items from a source parent menu item to a target item. - * - * @param array $_admin_menu - * An array containing the complete administration menu structure, passed by - * reference. - * @param int $source_pid - * A source parent menu item id from which children shall be copied. - * @param int $target_pid - * A target parent menu item id. - * @param string $title - * An optional string containing the token !title, that has already been - * passed through t(), which will be used to dynamically replace previous - * menu item titles. - * @param bool $tree - * Whether to rebuild the complete hierarchy from the source parent menu item - * or copy menu items flattened. Defaults to TRUE. - */ -function admin_menu_copy_items(&$_admin_menu, $source_pid, $target_pid, $title = NULL, $tree = TRUE) { - global $_menu; - - if (isset($_menu['items'][$source_pid]['children']) && isset($_admin_menu[$target_pid])) { - foreach ($_menu['items'][$source_pid]['children'] as $mid) { - $item = $_menu['items'][$mid]; - if (!$item['access']) { - continue; - } - if (isset($title)) { - $item['title'] = $title; - $item['title arguments'] = array('@title' => $_menu['items'][$mid]['title']); - } - // Only add child to target if it does not already exist. - if (!in_array($mid, $_admin_menu[$target_pid]['children'])) { - admin_menu_add_item($_admin_menu, $target_pid, $item); - } - - // Recurse into children. - if (isset($_menu['items'][$mid]['children']) && count($_menu['items'][$mid]['children'])) { - if ($tree) { - admin_menu_copy_items($_admin_menu, $mid, $mid, $title); - } - else { - admin_menu_copy_items($_admin_menu, $mid, $target_pid, $title, FALSE); - unset($_admin_menu[$mid]['children']); - // Note: Uncomment following lines to remove unnecessary parent items. - // unset($_admin_menu[$target_pid]['children'][array_search($mid, $_admin_menu[$target_pid]['children'])]); - // unset($_admin_menu[$mid]); + // Add devel module links + if (module_exists('devel')) { + // Add variable editor. + $links[] = array( + 'title' => 'Variable editor', + 'path' => 'devel/variable', + 'weight' => 20, + 'parent_path' => $icon_path, + ); + // Add clear-cache. + $links[] = array( + 'title' => 'Empty cache', + 'path' => 'devel/cache/clear', + 'weight' => 20, + 'parent_path' => $icon_path, + ); + + // Add switch_user items. + if ($devel_user_links = module_invoke('devel', 'switch_user_list')) { + foreach ($devel_user_links as $link) { + if (preg_match('!href="'. base_path() .'([^\?]+)\?([^"]+)" title="([^"]+)">(()?[^<]+()?)!', $link, $match)) { + $links[] = array( + 'title' => $match[4], + 'description' => $match[3], + 'path' => $match[1], + 'weight' => 20, + 'query' => 'destination', + 'parent_path' => 'logout', + ); } } } + } + + return $links; } /** - * Moves the child pointer of a menu item to a new parent. + * Add some hard-coded features for better user experience. * - * @param array $_admin_menu + * @param array $menu_links * An array containing the complete administration menu structure, passed by * reference. - * @param int $mid - * The menu item id of the item to move. - * @param int $pid - * The menu item id of the new parent. - */ -function admin_menu_move_item(&$_admin_menu, $mid, $pid) { - global $_menu; - - if (isset($_admin_menu[$mid]) && isset($_admin_menu[$pid])) { - // Remove current child pointer. Determine the path from the index - // because it contains the unprocessed urls. - $index = array_flip($_admin_menu['index']); - admin_menu_remove_item($_admin_menu, $index[$mid]); - - // Insert new child pointer. - $_admin_menu[$mid]['pid'] = $pid; - $_admin_menu[$pid]['children'][] = $mid; - return TRUE; - } - else { - return FALSE; + * @param array $sort + * An array containing the # parts of each link - must be updated if a link + * is added. + */ +function admin_menu_adjust_items(&$menu_links, &$sort) { + global $user, $base_url; + $links = array(); + + // Change or remove items, or add new top-level items + $add_links['admin/by-module'] = $menu_links['admin/by-module']; + unset($menu_links['admin/by-module'], $sort['admin/by-module']); + unset($menu_links['admin/by-task'], $sort['admin/by-task']); + + // Remove "edit" links + foreach (node_get_types('types', NULL, TRUE) as $type) { + $type_url_str = str_replace('_', '-', $type->type); + $path = 'admin/content/node-type/'. $type_url_str .'/edit'; + unset($menu_links[$path], $sort[$path]); } -} -/** - * Removes the child pointer for a menu item. - * - * @param array $_admin_menu - * An array containing the complete administration menu structure, passed by - * reference. - * @param string $path - * The menu path to remove, e.g. 'foo/bar'. - */ -function admin_menu_remove_item(&$_admin_menu, $path) { - global $_menu; - - $mid = $_admin_menu['index'][$path]; - if (isset($_admin_menu[$mid])) { - $pid = $_admin_menu[$mid]['pid']; - $child_key = array_search($mid, $_admin_menu[$pid]['children']); - if ($child_key !== FALSE) { - unset($_admin_menu[$pid]['children'][$child_key]); - return TRUE; - } - else { - return FALSE; - } + // Add the icon containing special links. + $links[] = array( + 'title' => theme('admin_menu_icon'), + 'path' => drupal_get_normal_path(variable_get('site_frontpage', 'node')), + 'weight' => -100, + 'options' => array('extra class' => 'admin-menu-icon', 'html' => TRUE), + ); + // Add llink to show current authenticated/anonymous users - we will add the + // data dynamically in the _alter hook. + $links[] = array( + 'title' => 'icon_users', + 'path' => 'user', + 'weight' => -90, + 'parent_path' => 'admin', + 'options' => array('extra class' => 'admin-menu-action admin-menu-icon admin-menu-users', 'html' => TRUE), + ); + $links[] = array( + 'title' => 'Log out', + 'path' => 'logout', + 'weight' => -100, + 'options' => array('extra class' => 'admin-menu-action admin-menu-logout'), + ); + foreach ($links as $item) { + $path = $item['path']; + $item = admin_menu_link_build($item); + $menu_links[$path] = $item; + $sort[$path] = 1; } - return FALSE; -} -/** - * Render an icon to display in the Administration Menu. - * - * @ingroup themeable - */ -function theme_admin_menu_icon() { - return ''; + return; } Index: admin_menu.install =================================================================== RCS file: /cvs/drupal/contributions/modules/admin_menu/admin_menu.install,v retrieving revision 1.4 diff -u -p -r1.4 admin_menu.install --- admin_menu.install 24 Feb 2008 17:32:47 -0000 1.4 +++ admin_menu.install 6 Jun 2008 20:02:39 -0000 @@ -2,17 +2,18 @@ // $Id: admin_menu.install,v 1.4 2008/02/24 17:32:47 sun Exp $ /** - * #224605: Rebuild cached menu for users. + * Implementation of hook_install(). */ -function admin_menu_update_5202() { - $ret = array(); +function admin_menu_install() { - // Clear CSS preprocessor cache. - drupal_clear_css_cache(); - - // Clear cache_menu. - cache_clear_all(NULL, 'cache_menu'); +} - return $ret; +/** + * Implementation of hook_uninstall(). + */ +function admin_menu_uninstall() { + // Delete menu links. + db_query("DELETE FROM {menu_links} WHERE module = 'admin_menu'"); + menu_cache_clear_all(); } Index: admin_menu.module =================================================================== RCS file: /cvs/drupal/contributions/modules/admin_menu/admin_menu.module,v retrieving revision 1.43 diff -u -p -r1.43 admin_menu.module --- admin_menu.module 26 Apr 2008 16:10:09 -0000 1.43 +++ admin_menu.module 6 Jun 2008 20:02:39 -0000 @@ -111,61 +111,25 @@ function admin_menu_theme_settings() { * output Admin menu in the footer to circumvent this. */ function admin_menu_footer($main = 0) { + + // Check for the flag indicating that we need to rebuild. + if (variable_get('admin_menu_rebuild_links', FALSE)) { + include_once(drupal_get_path('module', 'admin_menu') . '/' . 'admin_menu.inc'); + _admin_menu_rebuild_links(); + variable_del('admin_menu_rebuild_links'); + } + if (!user_access('access administration menu')) { return; } - global $_menu; - - // Get the menu item of /q=admin, which is the root for admin menu. - // $mid_admin = $_menu['path index']['admin']; - $_admin_menu =& admin_menu_get_menu(); - - // Allow other modules to integrate with admin_menu (uncached). - foreach (module_implements('admin_menu') as $module) { - $function = $module .'_admin_menu'; - // $function($_admin_menu, FALSE); - } - + $content = '
'; - $content .= admin_menu_tree_output($_admin_menu); - // $content .= menu_tree_output($_admin_menu); + $content .= admin_menu_tree_output(menu_tree_all_data('admin_menu')); $content .= '
'; return $content; } /** - * Return Administration Menu from cache or rebuild it. - * - * @param int $mid_admin - * The menu item id to use for the administration menu. - * - * @return array - * An array containing a complete menu structure of all cached administration - * menu items. - */ -function &admin_menu_get_menu($mid_admin = 2) { - static $_admin_menu; - - if (isset($_admin_menu)) { - return $_admin_menu; - } - global $user, $language; - - $cid = 'links:admin_menu:all:admin:'. $user->uid .':'. $language->language; - $cache = 0; // cache_get($cid, 'cache_menu'); - if ($cache && isset($cache->data)) { - $_admin_menu = $cache->data; - } - else { - require_once drupal_get_path('module', 'admin_menu') .'/admin_menu.inc'; - $_admin_menu = admin_menu_build($mid_admin); - // cache_set($cid, $_admin_menu, 'cache_menu', 0); - } - - return $_admin_menu; -} - -/** * Returns a rendered menu tree. * * @param $tree @@ -176,25 +140,11 @@ function &admin_menu_get_menu($mid_admin */ function admin_menu_tree_output($tree) { $output = ''; - $items = array(); - // Pull out just the menu items we are going to render so that we - // get an accurate count for the first/last classes. foreach ($tree as $data) { - if (!$data['link']['hidden']) { - $items[] = $data; - } - } - - // Since we allow other modules to add items to admin menu, we need to sort - // all items (again). - #usort($_admin_menu[$pid]['children'], '_admin_menu_sort'); - - foreach ($items as $i => $data) { - $extra_class = NULL; - // Allow HTML and omit alias lookups. - $data['link']['options']['html'] = TRUE; - $data['link']['options']['alias'] = TRUE; + $extra_class = isset($data['link']['localized_options']['extra class']) ? $data['link']['localized_options']['extra class'] : NULL; + // Omit alias lookups. + $data['link']['localized_options']['alias'] = TRUE; $link = theme('menu_item_link', $data['link']); if ($data['below']) { @@ -235,189 +185,112 @@ function theme_admin_menu_item($link, $h return ''. $link . $menu .''; } -/** - * Comparator routine for use in sorting menu items. - */ -function _admin_menu_sort($a, $b) { - $_admin_menu = admin_menu_get_menu(); - - $a = $_admin_menu[$a]; - $b = $_admin_menu[$b]; - - if ($a['weight'] < $b['weight']) { - return -1; - } - elseif ($a['weight'] > $b['weight']) { - return 1; - } - elseif (isset($a['title']) && isset($b['title'])) { - return strnatcasecmp($a['title'], $b['title']); - } - else { - return 1; - } -} /** - * Adjust the menu item path. - * - * Adjust the path of local tasks and let them point to their parent item. - * Finally build the url. These functions have been moved here to be able - * to cache the final results. + * Implementation of hook_form_[form_id]_alter(). * - * @param &$item - * An admin menu item. + * Extends Devel module with Administration Menu developer settings. */ -function admin_menu_item_url(&$_admin_menu, $mid) { - $link_item = $mid; - while ($_admin_menu[$link_item]['type'] & MENU_LINKS_TO_PARENT) { - $link_item = $_admin_menu[$link_item]['pid']; - } - - if (!isset($_admin_menu[$link_item]['processed'])) { - $_admin_menu[$mid]['path'] = url($_admin_menu[$link_item]['path'], isset($_admin_menu[$mid]['query']) ? $_admin_menu[$mid]['query'] : NULL); - $_admin_menu[$link_item]['processed'] = TRUE; - } - else { - // Copy the already processed path of the parent item to the - // default local task. - $_admin_menu[$mid]['path'] = $_admin_menu[$link_item]['path']; - } +function admin_menu_form_devel_admin_settings_alter(&$form, $form_state) { + // Shift system_settings_form buttons. + $weight = isset($form['buttons']['#weight']) ? $form['buttons']['#weight'] : 0; + $form['buttons']['#weight'] = $weight + 1; + + $form['admin_menu'] = array( + '#type' => 'fieldset', + '#title' => t('Administration Menu settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $display_options = array('mid', 'weight', 'pid'); + $display_options = array(0 => t('None'), 'mlid' => t('Menu link id'), 'weight' => t('Weight'), 'plid' => t('Parent link id')); + $form['admin_menu']['admin_menu_display'] = array( + '#type' => 'radios', + '#title' => t('Display extra information for menu items in Drupal Administration Menu'), + '#default_value' => variable_get('admin_menu_display', 0), + '#options' => $display_options, + '#description' => t('If enabled, the chosen information will appear next to each menu item link.'), + ); + $form['admin_menu']['admin_menu_show_all'] = array( + '#type' => 'checkbox', + '#title' => t('Display all menu items'), + '#default_value' => variable_get('admin_menu_show_all', 0), + '#description' => t('Enable this option to disable user access checks for menu items, i.e. every menu item in the visible menu tree will be displayed to every user regardless of access permissions.'), + ); + // Rebuild the admin menu + $form['#submit'][] = 'admin_menu_menu_alter'; } + /** - * Add a custom menu item. - * - * @param array $_admin_menu - * An array containing the complete administration menu structure, passed by - * reference. - * @param int $pid - * The parent menu item id. - * @param array $item - * An menu item array for the menu system. May contain the key 'weight' to - * adjust the item's weight. You can use Devel module to display additional - * information about menu items. - * - * @return int - * The id of the new menu item. + * Implementation of hook_enable(). */ -function admin_menu_add_item(&$_admin_menu, $pid, $item) { - if (empty($item['path'])) { - return FALSE; - } - $item['pid'] = $pid; - $item['children'] = array(); - $id = max(array_keys($_admin_menu)) + 1; - $_admin_menu[$id] = $item; - $_admin_menu[$pid]['children'][] = $id; - $_admin_menu['index'][$item['path']] = $id; - admin_menu_item_url($_admin_menu, $id); - - return $id; +function admin_menu_enable() { + variable_set('admin_menu_rebuild_links', TRUE); } + /** - * Implementation of hook_admin_menu(). - * - * @param array $admin_menu - * An array containing the complete administration menu structure, passed by - * reference. - * @param bool $may_cache - * Whether changes will be cached. If new menu items contain dynamic - * information, such as query strings or user-related data, these should be - * added on each page request ($may_cache = FALSE). + * Implementation of hook_menu_alter(). */ -function admin_menu_admin_menu(&$admin_menu, $may_cache) { - if (!$may_cache) { - // Add count of active anonymous/authenticated users. - // @see user_block(), user.module - $interval = time() - variable_get('user_block_seconds_online', 900); - $count_anon = sess_count($interval); - $count_auth = db_result(db_query("SELECT COUNT(DISTINCT uid) FROM {sessions} WHERE uid > 0 AND timestamp >= %d", $interval)); - - $mid_admin = $admin_menu['index']['admin']; - $title = t('Current anonymous / authenticated users'); - $icon_users = '@title'; - admin_menu_add_item($admin_menu, $mid_admin, array( - 'title' => $count_anon .' / '. $count_auth .' '. $icon_users, - 'title arguments' => array('@title' => 'Current anonymous / authenticated users'), - 'path' => user_access('administer users') ? 'admin/user/user' : drupal_get_normal_path(variable_get('site_frontpage', 'node')), - 'weight' => -90, - 'class' => 'admin-menu-action admin-menu-icon admin-menu-users', - )); - } +function admin_menu_menu_alter() { + variable_set('admin_menu_rebuild_links', TRUE); } /** - * Implementation of hook_form_alter(). + * Render an icon to display in the Administration Menu. * - * Extends Devel module with Administration Menu developer settings. + * @ingroup themeable */ -function admin_menu_form_alter(&$form, $form_state, $form_id) { - if ($form_id == 'devel_admin_settings') { - // Shift system_settings_form buttons. - $weight = $form['buttons']['#weight']; - $form['buttons']['#weight'] = $weight + 1; - - $form['admin_menu'] = array( - '#type' => 'fieldset', - '#title' => t('Administration Menu settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - $display_options = array('mid', 'weight', 'pid'); - $display_options = array(0 => t('None'), 'mid' => t('Id'), 'weight' => t('Weight'), 'pid' => t('Parent id')); - $form['admin_menu']['admin_menu_display'] = array( - '#type' => 'radios', - '#title' => t('Display extra information for menu items in Drupal Administration Menu'), - '#default_value' => variable_get('admin_menu_display', 0), - '#options' => $display_options, - '#description' => t('If enabled, the chosen information will appear next to each menu item link.'), - ); - $form['admin_menu']['admin_menu_show_all'] = array( - '#type' => 'checkbox', - '#title' => t('Display all menu items'), - '#default_value' => variable_get('admin_menu_show_all', 0), - '#description' => t('Enable this option to disable user access checks for menu items, i.e. every menu item in the visible menu tree will be displayed to every user regardless of access permissions.'), - ); - } +function theme_admin_menu_icon() { + return ''; } /** - * Implementation of hook_admin_menu() for Devel module (temporary). + * Implementation of hook_translated_menu_link_alter(). * - * - Adds most used functions 'empty cache' and 'variable editor' to the menu in - * Administration Menu's icon. - * - Adds links to switch to a different user to the logout button. + * Here is where we make changes to links that need dynamic information such + * as the current page path or the number of users. */ -if (module_exists('devel') && !function_exists('devel_admin_menu')) { - function devel_admin_menu(&$admin_menu, $may_cache) { - $access_devel = user_access('access devel information'); - $access_switch = user_access('switch users'); - if (!$access_devel && !$access_switch) { - return; - } - - $mid_icon = $admin_menu['index']['admin_menu_icon']; - if ($may_cache) { - // Add variable editor. - if ($access_devel) { - admin_menu_add_item($admin_menu, $mid_icon, array('title' => 'Variable editor', 'path' => 'devel/variable', 'weight' => 20)); +function admin_menu_translated_menu_link_alter(&$item, $map) { + static $acccess_all; + + if (!isset($acccess_all)) { + // We only ever do this for development + $acccess_all = variable_get('admin_menu_show_all', 0) && module_exists('devel'); + } + if ($item['menu_name'] == 'admin_menu') { + if ($acccess_all && !$item['access']) { + $item['access'] = TRUE; + // Prepare for http://drupal.org/node/266596 + if (!isset($item['localized_options'])) { + _menu_item_localize($item, $map, TRUE); } } - else { - // Add clear-cache. - if ($access_devel) { - admin_menu_add_item($admin_menu, $mid_icon, array('title' => 'Empty cache', 'path' => 'devel/cache/clear', 'weight' => 20, 'query' => drupal_get_destination())); + // Fix destination query strings + if (isset($item['localized_options']['query'])) { + if ($item['localized_options']['query'] == 'destination') { + $item['localized_options']['query'] = drupal_get_destination(); } - // Add switch_user items. - if ($access_switch && $devel_user_links = module_invoke('devel', 'switch_user_list')) { - $mid_logout = $admin_menu['index']['logout']; - foreach ($devel_user_links as $link) { - if (preg_match('!href="'. base_path() .'([^\?]+)\?([^"]+)" title="([^"]+)">(()?[^<]+()?)!', $link, $match)) { - admin_menu_add_item($admin_menu, $mid_logout, array('title' => $match[4], 'description' => $match[3], 'path' => $match[1], 'query' => $match[2])); - } - } + } + if (($item['link_path'] == 'http://drupal.org') && !user_access('display drupal links')) { + $item['access'] = FALSE; + } + if ($extra = variable_get('admin_menu_display', 0)) { + $item['title'] .= ' '. $extra[0] .': '. $item[$extra]; + } + if ($item['title'] == 'icon_users') { + // Add count of active anonymous/authenticated users. + // @see user_block(), user.module + $interval = time() - variable_get('user_block_seconds_online', 900); + $count_anon = sess_count($interval); + $count_auth = db_result(db_query("SELECT COUNT(DISTINCT uid) FROM {sessions} WHERE uid > 0 AND timestamp >= %d", $interval)); + $icon_users = '@title'; + + $dyn = $count_anon .' / '. $count_auth .' '. $icon_users; + $item['title'] = t('!dyn anonymous / authenticated users', array('!dyn' => $dyn)); + if (user_access('administer users')) { + $item['href'] = 'admin/user/user'; } } }