Here's a quick walkthrough of how the WordPress admin menu is built - I'm not talking the add_menu_page
API, I mean the actual default WordPress menu.
Calling the Menu File
The menu is, obviously, loaded by wp-admin/admin.php
. But it's not loaded through the standard API we're used to using based on the WordPress documentation. Rather, the entire menu (all possible options, submenus, etc) are loaded via a simple array that's defined in wp-admin/menu.php
.
So to load the menu system, admin.php
just require
s menu.php
... around line 99 in WordPress 3.0.
Loading the Menu
The menu itself is stored in the global array $menu
. According to the in-line documentation, the menu array has these elements:
The elements in the array are:
* 0: Menu item name
* 1: Minimum level or capability required.
* 2: The URL of the item's file
* 3: Class
* 4: ID
* 5: Icon for top level menu
The dashboard, for example, is:
$menu[2] = array( __('Dashboard'), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'div' );
The file goes through and loads each menu item into the array and loads all of their sub-menu items into an array called $submenu
that indexes based on the parent menu's url. So the Dashboard's submenu item called "Dashboard" is:
$submenu[ 'index.php' ][0] = array( __('Dashboard'), 'read', 'index.php' );
After the system is done loading all the menus (there aren't that many, but the system steps through the index at time by 5 or 10 ... notice that the Dashboard, even though it's the first menu item, is still indexed as item "2" (PHP arrays start at index 0 ... so this gives you some maneuvering room).
At this point, the system calls wp-admin/includes/menu.php
.
Stepping through the Menu
This third file walks through each menu item and, based on the privileges assigned to the current user, either uses the menu or removes it. First it loops through all the sub-menus and removes pages the user can't access. Then it loops through parent pages and does the same thing. Then it removes any duplicate separators that remain from having eliminated menus.
Finally, it sorts the menus based on their assigned menu order.
Ordering custom menus
The hook admin_menu
is called after menus are set up but before anything is ordered. So it's possible to order the entire WordPress menu system without "hacking" the API.
After the action admin_menu
is fired, your custom pages are loaded into the system. The next thing that happens, is WordPress checks a filter called custom_menu_order
... this filter is always returned false
and tells WordPress whether or not you want to use a custom order.
Add the following to your theme to set the flag to true
instead and define your explicit menu order:
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array('index.php', 'edit.php', 'edit-comments.php');
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
Specify the order you want for all of the menus (I supplied references to the menu-loading file so you can get a list of filenames) and this should take care of it.
EDIT (9/2/2010):
To specify the order of a custom post type's edit screen using this method, you need to know the URL of the edit screen. I most cases, it will be http://blog.url/wp-admin/edit.php?post_type=POST_TYPE
. This depends on how WordPress is set up on your site (if it's installed in the root or in a subfolder) and the slug of the custom post type you're using.
For example...
Let's say you have a custom post type for 'Stack Exchange Questions' and you want the editor to appear in the same section as the dashboard directly below the dashboard icon. You'd use the following code in your theme's functions.php
file:
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array('index.php', 'edit.php?post_type=stack_exchange_questions');
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
The rest of the menu will be unaffected, but your custom edit page will be moved to the same section as the dashboard and will appear immediately below it. You can use this to move your custom post types to any section of the admin menu and place them in any order. You can also move standard menu items around the same way.
Just make sure you specify the order of all menu items in the given section, otherwise your menu might be subject to some unexpected weirdness.