WordPressのナビゲーションメニューは、管理画面上からドラッグ&ドロップで設定できて便利なのですが、非公開設定となっている投稿や固定ページなどが含まれている場合でも、表示の調整は行ってくれず全てが表示されてしまいます。このため、閲覧権限がないユーザーが非公開記事のメニューをクリックした場合「リンク切れか?」と思われてしまうことになります。

これでは、ユーザーエクスペリエンスもだだ下がりになってしまうので、メニューの記事が非公開の場合、自動的に表示されないようにしてみましょう。
ナビゲーションメニューには、wp_nav_menu_objects という、登録されたメニューをフィルタリングできるフックが存在しています。
今回は、ここで
- メニューが投稿タイプかどうかをチェック
- メニューの記事が非公開で、なおかつユーザーの閲覧権限がない場合、メニューを削除し、削除済みリストにメニューのIDを保持
- 子メニューだけが表示されることを防ぐため、メニューの親ID(menu_item_parent)が、削除済みリストに含まれていた場合も、メニューを削除
という処理を行います。
具体的なコードが、CODE 1。
CODE 1
function remove_private_post_menu( $sorted_menu_items ) {
$unset_ids = array();
foreach ( $sorted_menu_items as $key => $item ) {
if ( $item->type == 'post_type' ) {
$post = get_post( $item->object_id );
$post_type = get_post_type_object( $post->post_type );
if ( $post->post_status == 'private' && ! current_user_can( $post_type->cap->read_private_posts ) ) {
unset( $sorted_menu_items[$key] );
$unset_ids[] = $item->ID;
continue;
}
}
if ( in_array( $item->menu_item_parent, $unset_ids ) ) {
unset( $sorted_menu_items[$key] );
$unset_ids[] = $item->ID;
}
}
return $sorted_menu_items;
}
add_filter( 'wp_nav_menu_objects', 'remove_private_post_menu' );
テーマの functions.php や プラグインに記述していただければ、閲覧権限がないユーザーの場合、メニューが子メニューごとキレイさっぱり表示されなくなります。

ログイン機構を持ったサイトなどで、ユーザーの状況次第でメニューの表示を変えることにも応用が利くのではないでしょうか。