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 や プラグインに記述していただければ、閲覧権限がないユーザーの場合、メニューが子メニューごとキレイさっぱり表示されなくなります。

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