How To Add Separators To The Admin Menu

As you may already know, WordPress stores top-level menus in a global $menu array. The array indexes correspond to menu positions, and each array item contains the properties of a single menu – the menu title, required capability, URL, and so on. Separator items are structured just like normal menus, except they also have a special CSS class – wp-menu-separator.

So to add a separator, you need to add a new item to the $menu, place it at an index that’s between the indexes of the menus you want to separate, and give it the right class name.

To simplify the task, here’s an add_admin_menu_separator() function that will create a new separator for you. You can either specify the position explicitly, or you can pass it the slug or URL of an existing top-level menu and it will automatically figure out its position and add the separator right after that menu.

function add_admin_menu_separator($position) {
	global $menu;
	static $uid = 0;

	if ( !is_int($position) ) {
		//Find the position of the menu that matches
		//the specified file name or URL.
		$menuPosition = 0;
		foreach($menu as $menuPosition => $item) {
			if ( $item[2] === $position ) {
				break;
			}
		}
		//We'll insert the separator just after the target menu.
		$position = $menuPosition + 1;
	}

	$menuFile = 'separator-custom-' . $uid++;
	$menu[$position] = array(
		'',                  //Menu title (ignored)
		'read',              //Required capability
		$menuFile,           //URL or file (ignored, but must be unique)
		'',                  //Page title (ignored)
		'wp-menu-separator', //CSS class. Identifies this item as a separator.
	);
	ksort($menu);
}

Inspired by this WPSE answer by Mike Schnikel, with some changes of my own.

Usage example:

function add_example_separators() {
	//Add a separator after the "Pages" menu.
	add_admin_menu_separator('edit.php?post_type=page');
	//...and at position 62 (after "Appearance").
	add_admin_menu_separator(62);
}
add_action('admin_menu', 'add_example_separators');

And here’s a screenshot of the result:

A word of warning: if you try to add a separator at a position that is already occupied, the add_admin_menu_separator() function will happily overwrite the existing menu item. So pick the position carefully.

One way to avoid this problem would be to modify the function to check if the target position is in use and move the existing menus down to make room:

if ( !is_int($position) ) {
	/* omitted */
}

if ( isset($menu[$position]) ) {
	//Free up some space.
	$newMenu = array();
	foreach($menu as $index => $item) {
		if ($index < $position) {
			$newMenu[$index] = $item;
		} else {
			$newMenu[$index + 1] = $item;
		}
	}
	$menu = $newMenu;
}

//...Continue with inserting the separator...

The downside is that this will change the position of all menus that come after the separator, which can break plugins and themes that expect WordPress menus to be in their default positions. Still, that’s probably better than unintentionally overwriting a menu.

Related posts :

Leave a Reply