Search code examples
phpwordpresswp-insert-post

How to Hide Menu Items in WordPress After Creating Pages with Shortcodes?


I'm currently working on a WordPress plugin development project in PHP, where I've created several shortcodes to implement different functionalities, like a login page, an unauthorized page, and a dashboard. To navigate to these functionalities, I've created pages with the corresponding shortcodes.

I've successfully created these pages using the following code in my activation hook:

function my_plugin_activation() {
    $pageData = array(
        'post_title' => 'Dashboard',
        'post_content' => '[dashboard]', // shortcode
        'post_status' => 'publish',
        'post_type' => 'page',
        'post_name' => 'dashboard',
    );

    // Insert the new page
    $pageId = wp_insert_post($pageData);
}
register_activation_hook(__FILE__, 'my_plugin_activation');

As a result, after activating the plugin, WordPress automatically adds these pages to the header menu. However, I would like to achieve two specific goals:

  • Hide the menu items for "Dashboard" and "Unauthorized" pages.
  • Hide the pre-login menus and show only menu items which is associated with post-login functionalities, which might include "Dashboard," "Profile," and "Logout."

Could someone provide code-level solutions to achieve these objectives within the plugin's activation block, ensuring that these changes work automatically for anyone using the plugin?

Before Plugin Activation:

enter image description here

After Plugin Activation:

enter image description here

I have tried following code, but nothing works

Approach #1:

// If the page should not be linked to any menu
// Remove it from the default header menu
$menu_name = 'twentytwentytwo'; // Replace with the name of your menu
$menu = wp_get_nav_menu_object($menu_name);

if ($menu) {
    $menu_id = $menu->term_id;
                    
    // Find and remove the page from the default menu
    $menuItems = wp_get_nav_menu_items($menu_id);
    foreach ($menuItems as $menuItem) {
        if ($menuItem->object_id == $pageId) {
            wp_delete_post($menuItem->ID);
        }
    }
}

Approach #2:

function my_plugin_activation() {
    $pageData = array(
        'post_title' => 'Dashboard',
        'post_content' => '[dashboard]', // shortcode
        'post_status' => 'publish',
        'post_type' => 'page',
        'post_name' => 'dashboard',
    );

    // Insert the new page
    $pageId = wp_insert_post($pageData);

    // Register a function to modify the menu items
    add_filter('wp_nav_menu_objects', 'my_remove_menu_items');
}
register_activation_hook(__FILE__, 'my_plugin_activation');


function my_remove_menu_items($items) {
    // Menu item slugs to be removed
    $menu_item_slugs = array('dashboard'); // Replace with actual slugs
    
    foreach ($items as $key => $item) {
        if (in_array($item->post_name, $menu_item_slugs)) {
            unset($items[$key]);
        }
    }
    
    return $items;
}

Solution

  • Finally I found the answer!

    In WordPress, the post_status field is used to define the current status of a post or page.

    Private (private):

    • Purpose: Represents a post or page that is private and not visible to the public.
    • Menu Item: Doesn't add a menu item.

    So, using this option we can solve the scenario which is explained in the question.

    Resultant Code:

    function my_plugin_activation() {
        $pageData = array(
            'post_title' => 'Dashboard',
            'post_content' => '[dashboard]', // shortcode
            'post_status' => 'private',
            'post_type' => 'page',
            'post_name' => 'dashboard',
        );
    
        // Insert the new page
        $pageId = wp_insert_post($pageData);
    }
    register_activation_hook(__FILE__, 'my_plugin_activation');
    

    In respective to Post login menus I created a custom template layout for those pages.