Add an admin page, but don’t show it on the admin menu

I have a custom plugin ‘Charts’ that has it’s own menu. In that menu are links to the 3 pages for the plugin – ‘Charts’, ‘Add Chart’ and ‘Edit Chart’. However, I don’t want to display the link to ‘Edit Chart’.

Here is how I add the page in question –

Read More
$this->pagehook = add_submenu_page('charts', __('Edit Chart'), __('Edit Chart'), 'edit_charts', 'edit-chart', array(&$this, 'on_show_page'));

I’ve scoured the internet, and cannot find a way to do this (that works). It’s possible to remove whole top level menus (not what I need), and you can remove individual entries from the $submenu global (but doing that also removes the registered capability), so no one can access the page –

global $submenu;
if(!empty($submenu['charts'])) : foreach($submenu['charts'] as $key => $page) :
        if($page[0] === 'Edit Chart') :

            /** Removes all permissions to access the page */
            //unset($submenu['charts'][$key]);              
            /** Removes the title, but the menu entry still exists, so it looks odd */
            $submenu['charts'][$key][0] = '';

        endif;
    endforeach;
endif;

I’ve looked in to hiding it via CSS, but can’t see a way to do that through the HTML that WordPress generates –

<li><a href="admin.php?page=edit-chart" tabindex="1">Edit Chart</a></li>

I’ve also considered jQuery, but that has similar limitations to the CSS route, plus I refust to believe that I am the only one that has ever wished to do this – there must be a way, I just can’t find it!

Any hints and tips appriciated.

Thanks.

Related posts

Leave a Reply

3 comments

  1. Use a submenu page as parent slug. The admin menu has just two levels, so the imaginary third level will be hidden.

    Sample code, tested:

    add_action( 'admin_menu', 'wpse_73622_register_hidden_page' );
    
    function wpse_73622_register_hidden_page()
    {
        add_submenu_page(
            'options-writing.php',
            'Hidden!',
            'Hidden!',
            'exists',
            'wpse_73622',
            'wpse_73622_render_hidden_page'
        );
        # /wp-admin/admin.php?page=wpse_73622
    }
    
    function wpse_73622_render_hidden_page()
    {
        echo '<p>hello world</p>';
    }
    
  2. From the docs on add_submenu_page(), you see that you can hide your submenu link from a top level menu item to which it belongs be setting the slug (1st argument) to null:

    add_action( 'admin_menu', 'register_my_custom_submenu_page' );
    
    function register_my_custom_submenu_page() {
        add_submenu_page( 
            null,
            'My Custom Submenu Page',
            'My Custom Submenu Page',
            'manage_options',
            'my-custom-submenu-page',
            'my_custom_submenu_page_callback',
        );
    }
    

    To highlight the desired menu item (e.g. ‘all charts’ when accessing the hidden ‘edit chart’ page), you can do the following:

    add_filter( 'submenu_file', function($submenu_file){
        $screen = get_current_screen();
        if($screen->id === 'id-of-page-to-hide'){
            $submenu_file = 'id-of-page-to-higlight';
        }
        return $submenu_file;
    });
    
  3. You could use CSS, and you will be able to access it through the URL in the href tag:

    #adminmenu a[href="admin.php?page=edit-chart"] { 
        display: none;
    }
    

    There are no extra paddings or spacings for the parent LI element, so you don’t need to hide it. You will also still be able to access the submenu.