WordPressのフロントページ設定時にカスタムナビメニューのcurrent_page_parentクラスがおかしくなる件を修正してみた

長ったらしいタイトルですみません。。

大なごやWeb会議の運営メンバーで、スライム色のニョロニョロのキャラを持ち、「マイペースクリエイター」とよく間違われるマイペースクリエイターさんがゆるぼっていたので、ちょいと調べてみました。

まずは、ゆるぼツイートだけでは具体的なことが分からなかったので、聞いてみると、

とのこと。

どうやら、

  1. 表示設定のフロントページの表示で投稿ページの設定を行っていて、なおかつその投稿ページがナビメニューに登録されている場合、カスタム投稿タイプのページを表示している際にも、投稿ページのメニューに current_page_parent のクラスが付いてしまっているので消したい。
  2. 施工実績という固定ページにてテンプレート内でクエリーを発行しカスタム投稿タイプの一覧を表示させているが、カスタム投稿タイプの詳細表示において、施工実績の固定ページのナビメニューに current_page_parent が付くようにしたい。

ということらしいです。

で、小一時間で作成したコードがこれ。ナビメニューの各リストに付くclass属性をフィルタリングできるnav_menu_css_classにフックし、条件に応じてcurrent_page_parentの削除・追加をするようにしています。

function mypace_custom_navi_menu( $classes, $item, $args ) {
	$page_for_posts = get_option( 'page_for_posts' );
	if ( is_singular( 'construction' ) ) {
		if ( is_numeric( $page_for_posts ) && $item->object_id == $page_for_posts && $item->object == 'page' && $key = array_search( 'current_page_parent', $classes ) ) {
				unset( $classes[$key] );
		} elseif ( $item->title == '施工実績' && $item->object == 'page' ) {
			$classes[] = 'current_page_parent';
		}
	}
	return $classes;
}
add_filter( 'nav_menu_css_class', 'mypace_custom_navi_menu', 10, 3 );

一応、これで運用環境では問題ないようなのですが、カスタム投稿タイプの表示でも、投稿ページのメニューに current_page_parent が付いてしまうのが、解せなかったため、どういうロジックで投稿ページの current_page_parent が付くのかソースを追ってみることにしました。

該当箇所は、wp-includes/nav-menu-template.phpの396-398行目(ver 3.1.2)、_wp_menu_item_classes_by_context関数にあるコードです。

		// back-compat with wp_page_menu: add "current_page_parent" to static home page link for any non-page query
		if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id )
			$classes[] = 'current_page_parent';

ここで、$home_page_id は投稿ページのIDなので、投稿ページのメニューか否かの判断以外では、$wp_query->is_pageがない、つまり固定ページでなければ current_page_parent を付けるというロジックになっています。
カテゴリーやタグはまだしも、カスタム投稿タイプ、カスタム分類、アタッチメントや検索結果の表示でも、投稿ページのメニューに current_page_parent が付いてしまうって、どういうことなのさ。。。

事実、WordPressのtracでも、この件は報告されているので、今後のバージョンでは、修正されるかもしれません。

Ticket #16382 Menus adds “current_page_parent” class to the blog page when viewing a custom post type entry

ただ、Milestone が Future Release になっていて、すぐさま直される可能性は高くないので、最初のコードをリファクタリングして、他の状況(カスタム分類とかね)においても正しく動作するようにしてみました。

function mypace_custom_navi_menu( $classes, $item ) {
	global $wp_query;

	$singular_slug = 'construction';
	$page_for_custom_type_title = '施工実績';
	$page_for_posts = get_option( 'page_for_posts' );
	$post_type_query = $wp_query->query_vars['post_type'];
	$del_flag = true;
	$add_flag = false;

	if ( is_singular( 'post' ) || is_category() || is_tag() ) {
		$del_flag = false;
	} elseif ( ( is_author() || is_date() || is_author() ) ) {
		if ( in_array( $post_type_query, array ( '', 'post' ) ) ) {
			$del_flag = false;
		} elseif ( $post_type_query == $custom_post_type ) {
			$add_flag = true;
		}
	} elseif ( is_tax() ) {
		$taxonomy = get_taxonomy( $wp_query->query_vars['taxonomy'] );
		if ( count( $taxonomy->object_type ) == 1 && $taxonomy->object_type[0] == 'post' ) {
			$del_flag = false;
		} elseif ( count( $taxonomy->object_type ) == 1 && $taxonomy->object_type[0] == $singular_slug ) {
			$add_flag = true;
		}
	} elseif ( is_singular( $singular_slug ) ) {
		$add_flag = true;
	}

	if ( $del_flag && is_numeric( $page_for_posts ) && $item->object_id == $page_for_posts && $item->object == 'page' && $key = array_search( 'current_page_parent', $classes ) ) {
			unset( $classes[$key] );
	} elseif ( $add_flag && $item->title == $page_for_custom_type_title && $item->object == 'page' ) {
		$classes[] = 'current_page_parent';
	}
	return $classes;
}
add_filter( 'nav_menu_css_class', 'mypace_custom_navi_menu', 10, 2 );

上記は、マイペースクリエイターさん独自の環境(【改正版】カスタム投稿タイプの表示用のページを作る-WordPress備忘録-)に合わせたコードなので、単に投稿ページのメニューから current_page_parent を削除したいだけなら、下記のコードだけで大丈夫なはずです。(検証不十分。。

function mypace_custom_navi_menu( $classes, $item ) {
	global $wp_query;

	$page_for_posts = get_option( 'page_for_posts' );
	$post_type_query = $wp_query->query_vars['post_type'];
	$del_flag = true;

	if ( is_singular( 'post' ) || is_category() || is_tag() ) {
		$del_flag = false;
	} elseif ( ( is_author() || is_date() || is_author() ) ) {
		if ( in_array( $post_type_query, array ( '', 'post' ) ) ) {
			$del_flag = false;
		}
	} elseif ( is_tax() ) {
		$taxonomy = get_taxonomy( $wp_query->query_vars['taxonomy'] );
		if ( count( $taxonomy->object_type ) == 1 && $taxonomy->object_type[0] == 'post' ) {
			$del_flag = false;
		}
	}

	if ( $del_flag && is_numeric( $page_for_posts ) && $item->object_id == $page_for_posts && $item->object == 'page' && $key = array_search( 'current_page_parent', $classes ) ) {
			unset( $classes[$key] );
	}
	return $classes;
}
add_filter( 'nav_menu_css_class', 'mypace_custom_navi_menu', 10, 2 );

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です