Add separator to admin submenu

Admin menu & submenu separators

After going over it and extending the core API to allow main menu separators in custom positions, I did a quick run through core menu files, dumped the hell out of everything’s that in there and found a solution that allows to use the core API also for custom submenu separators.

The result

This is how our menu will look like, after we added the separators.

Admin menu and sub menu separators

To make this happen, simply add a small plugin, or throw this snippet in your plugins file or functions.php. Here’s an example plugin. As you can see, you’ll have to add the parent page where you want your separator to appear. Then you have to add the identifier wp-menu-separator. You can adjust the visibility for user by changing the read-capability to whatever the other items in this menu have. The 11 is just the priority. Adjust it to wherever you want the separator to appear inside the menu.

<?php
defined( 'ABSPATH' ) OR exit;
/** Plugin Name: Example Admin Menu Separator */

add_action( 'admin_menu', 'add_admin_menu_separator' );
function add_admin_menu_separator()
{
    add_menu_page( '', '', 'read', 'wp-menu-separator', '', '', '21' );
    add_submenu_page( 'edit.php?post_type=page', 'wp-menu-separator', '', 'read', '11', '' );
}

The Plugin itself

Again this plugin can be used as plugin, part of another plugin or (best) as muplugin.

To follow any updates

Please subscribe/star this GitHub Gist. I will post updates only there.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: Admin Menu Separator
 * Description: Adds a separator on whatver priority is needed.
 */

add_filter( 'parent_file', 'admin_menu_separator' );
function admin_menu_separator( $parent_file )
{
    $menu = &$GLOBALS['menu'];
    $submenu = &$GLOBALS['submenu'];
    foreach( $submenu as $key => $item )
    {
        foreach ( $item as $index => $data )
        {
            // Check if we got the identifier
            if ( in_array( 'wp-menu-separator', $data, true ) )
            {
                // Set the MarkUp, so it gets used instead of the menu title
                $data[0] = '<div class="separator"></div>';
                // Grab our index and temporarily save it, so we can safely overrid it
                $new_index = $data[2];
                // Set the parent file as new index, so core attaches the "current" class
                $data[2] = $GLOBALS['parent_file'];
                // Reattach to the global with the new index
                $submenu[ $key ][ $new_index ] = $data;
                // Prevent duplicate
                unset( $submenu[ $key ][ $index ] );
                // Get back into the right order
                ksort( $submenu[ $key ] );
            }
        }
    }
    foreach( $menu as $key => $item )
    {
        if (
            in_array( 'wp-menu-separator', $item )
            AND 5 < count( $item )
            )
        {
            $menu[ $key ][2] = 'separator0';
            $menu[ $key ][4] = 'wp-menu-separator';
            unset(
                 $menu[ $key ][5]
                ,$menu[ $key ][6]
            );
        }
    }
    return $parent_file;
}

Leave a Comment