Skip to content

fix: resolve nav menu item validation to check for published status#9192

Open
kushagra-goyal-14 wants to merge 3 commits intoWordPress:trunkfrom
kushagra-goyal-14:fix/menu-item-unpublish
Open

fix: resolve nav menu item validation to check for published status#9192
kushagra-goyal-14 wants to merge 3 commits intoWordPress:trunkfrom
kushagra-goyal-14:fix/menu-item-unpublish

Conversation

@kushagra-goyal-14
Copy link
Copy Markdown

@kushagra-goyal-14 kushagra-goyal-14 commented Jul 4, 2025

Menu items that get unpublished still appear.

Overview

This pull request updates the logic for rendering menu items in WordPress navigation menus. It ensures that only items linked to published posts or pages are displayed on the frontend, improving consistency and preventing dead links.

Previously, menu items tied to draft, pending, and private content would still appear on the frontend, leading to broken or inaccessible navigation links.

Trac Ticket: #13822


Issue Fixed

Menu Items Linked to Unpublished Posts Still Show Publicly

  • Problem:
    Menu items remain visible on the frontend even when the linked post is no longer published (e.g., moved to trash or reverted to draft).

  • Solution:
    Updated the condition to check for is_post_viewable and if private post then show based on user capability


Code Changes

Previous behavior (only hiding trashed items)

if ( 'trash' === get_post_status( $menu_item->object_id ) ) {
    $menu_item->_invalid = true;
}

Updated behavior (hides all non-published items)

if ( 'private' === $post_status && ! current_user_can( 'read_private_posts' ) ) {
    $menu_item->_invalid = true;
} elseif ( 'private' !== $post_status && ! is_post_status_viewable( $post_status ) ) {
    $menu_item->_invalid = true;
}

This ensures the menu item is only considered valid when the linked object is in the 'publish' state.


Admin Behavior

  • The admin menu editor already displays visual indicators for unpublished items, such as:
    • (Draft)
    • (Pending)
    • (Trash)
    • (Private)
  • A yellow notice such as:
    “Click Save Menu to make unsaved menu items public.”
    already informs users that certain items won't be visible on the live site.

No changes were made to the admin UI — it already handles this use case effectively.


Testing Instructions

Test Case 1: Hide Non-Published Menu Items

  1. Create a post or page and publish it.
  2. Add it to a navigation menu.
  3. View the frontend — the menu item should be visible.
  4. Edit the post and change its status to one of the following:
    • Draft
    • Pending Review
    • Private
    • Trashed
  5. Refresh the frontend.

Expected Results

  • The menu item is no longer shown on the frontend.
  • In the admin menu editor, the item:
    • Remains listed
    • Displays a status indicator such as “(Draft)” or “(Inactive)”
    • Shows a warning if needed

Test Case 2: Private Posts - Anonymous Users

Objective: Verify private posts are hidden from non-authenticated users

Steps:

  1. Create a post with status "Private"
  2. Add the post to a navigation menu
  3. View the frontend while logged out

Expected Results:

  • ❌ Menu item hidden from anonymous users

Test Case 3: Private Posts - Subscribers

Objective: Verify private posts are hidden from users without read_private_posts capability

Steps:

  1. Create a post with status "Private"
  2. Add the post to a navigation menu
  3. View the frontend as a subscriber

Expected Results:

  • ❌ Menu item hidden from subscribers

Test Case 4: Private Posts - Admins/Editors

Objective: Verify private posts are visible to users with read_private_posts capability

Steps:

  1. Create a post with status "Private"
  2. Add the post to a navigation menu
  3. View the frontend as an admin or editor

Expected Results:

  • ✅ Menu item visible to admins
  • ✅ Menu item visible to editors
  • ✅ Menu item links to the post correctly
  • ✅ Menu item visible in admin menu editor with "(Private)" label

Test Case 5: Custom Public Post Status (Backward compatbility)

Objective: Verify custom public post statuses work correctly

Prerequisites: Register a custom public post status

register_post_status( 'featured', array(
    'label'                     => 'Featured',
    'public'                    => true,
    'exclude_from_search'       => false,
    'show_in_admin_all_list'    => true,
    'show_in_admin_status_list' => true,
    'label_count'               => _n_noop( 'Featured <span class="count">(%s)</span>', 'Featured <span class="count">(%s)</span>' ),
) );

Steps:

  1. Create a post with the publish status
  2. Add the post to a navigation menu
  3. Change the status to custom "featured" status
  4. View the frontend as different user roles

Expected Results:

  • ✅ Menu item visible to anonymous users
  • ✅ Menu item visible to subscribers
  • ✅ Menu item visible to admins/editors
  • ✅ Menu item links to the post correctly

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jul 4, 2025

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@kushagra-goyal-14 kushagra-goyal-14 marked this pull request as ready for review July 4, 2025 08:28
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jul 4, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props kush123, peterwilsoncc.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

}

if ( 'trash' === get_post_status( $menu_item->object_id ) ) {
if ( 'publish' !== get_post_status( $menu_item->object_id ) ) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to account for custom post statuses that are public.

It should probably check is_post_status_viewable( get_post_status( $menu_item->object_id ) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants