WordPress ナビゲーションメニューに最近の投稿を追加

WordPress のナビゲーションメニューに、動的に最近の投稿のメニュー項目を追加する方法を紹介します。

当初は、管理画面から細かく設定できるようにしてプラグインにしようと思っていたのですが、ナビゲーションメニューの設定画面を設けるのが意外と面倒だったので、プラグイン化は先送りにして設定画面なしのシンプルなものを先行して紹介することにした次第です。

仕様

  • 管理画面のメニュー設定に [最近の投稿] メニュー項目を追加する。
  • 最近の投稿メニューは表示時にサブメニューを追加しサブメニューには最近の投稿へのメニューを10件表示する。
  • 投稿日が30日以内の場合は「NEW!」マークを表示する。

スクリーンショット

メニュー設定

Twenty Seventeen テーマの表示例

Twenty Sixteen テーマの表示例

コード

functions.php に下記コードを追加します。

class Recent_Posts_Nav_Menu {
	function __construct() {
		add_action( 'admin_head-nav-menus.php', array( $this, 'add_meta_box' ) );
		add_filter( 'wp_setup_nav_menu_item', array( $this, 'setup_nav_menu_item' ) );
		add_filter( 'wp_get_nav_menu_items', array( $this, 'get_nav_menu_items' ) );
	}

	function add_meta_box() {
		add_meta_box( 'add-recent-posts', '最近の投稿', array( $this, 'meta_box_content' ), 'nav-menus', 'side', 'default' );
	}

	function setup_nav_menu_item( $menu_item ) {
		if ( isset( $menu_item) ) {
			if ($menu_item->object == 'recent_posts') {
		        $menu_item->type_label = '最近の投稿';
		    }
		}
		return $menu_item;
	}

	function meta_box_content() {
		global $nav_menu_selected_id;

		$items = array();
		$item = new stdClass();
		$item->classes = array();
		$item->type = 'recent_post';
		$item->object_id = 1;
		$item->object = 'recent_posts';
		$item->title = '最近の投稿';
		$item->menu_item_parent = null;
		$item->url = null;
		$item->target = null;
		$item->attr_title = null;
		$item->xfn = null;
		$item->db_id = 0;
		$item->description = null;
		$items[] = $item;

		$walker = new Walker_Nav_Menu_Checklist( array() );

		echo '<div id="recent-posts" class="posttypediv">';
		echo '<div id="tabs-panel-recent-posts" class="tabs-panel tabs-panel-active">';
		echo '<ul id="recent-posts-checklist" class="categorychecklist form-no-clear">';
		echo walk_nav_menu_tree( array_map( 'wp_setup_nav_menu_item', $items ), 0, (object)array( 'walker' => $walker ) );
		echo '</ul>';
		echo '</div>';
		echo '</div>';
		echo '<p class="button-controls">';
		echo '<span class="add-to-menu">';
		echo '<input type="submit"' . wp_nav_menu_disabled_check( $nav_menu_selected_id ) . ' class="button-secondary submit-add-to-menu" value="' . esc_attr__( 'Add to Menu' ) . '" name="add-recent-posts-menu-item" id="submit-recent-posts" />';
		echo '</span>';
		echo '</p>';
	}

	function get_nav_menu_items( $items ) {
	    if ( is_admin() ) {
			return $items;
		}

		$new_days = 30;	// 最新の日数

		$menu_order = count( $items );
		$add_item_count = 0;
		$today = date( 'U' );
		foreach ( $items as $item ) {
			if ( $item->post_type == 'nav_menu_item' && $item->object == 'recent_posts' ) {
				$child_items = array();
				$posts = get_posts( array(
					'post_type' => 'post',
					'posts_per_page' => 10,
					'orderby' => 'date',
					'order' => 'DESC',
				) );
				foreach( $posts as $post ) {
					++$add_item_count;

					$days = date( 'U', ( $today - date( 'U', strtotime( $post->post_date ) ) ) ) / 86400;

					$child_item = new stdClass();
					$child_item->ID = 1000000 + $add_item_count;
					$child_item->type = $item->type;
					$child_item->object_id = $post->id;
					$child_item->object = 'recent-posts-child';
					$child_item->title = $post->post_title;
					$child_item->menu_item_parent = $item->ID;
					$child_item->url = get_permalink( $post->ID );
					$child_item->target = null;
					$child_item->attr_title = null;
					$child_item->xfn = null;
					$child_item->db_id = 0;
					$child_item->description = null;
					$child_item->post_type = 'nav_menu_item';

					$child_item->current = false;
					$child_item->classes = array();

					$child_item->menu_order = $menu_order + $add_item_count;
					if ( get_the_ID() == $post->ID ) {
						$child_item->classes[] = 'current-menu-item';
						$child_item->current = true;
					}
					if ( $new_days > $days ) {
						$child_item->classes[] = 'menu-item-new';
					}

					$child_items[] = $child_item;
				}
				$items = array_merge( $items, $child_items );
			}
		}
		return $items;
	}
}

new Recent_Posts_Nav_Menu();

スタイル (CSS)

style.css 等に下記スタイルを追加します。

/*
最近の投稿メニュー
*/
.main-navigation li.menu-item-new a:after {
	content: "NEW!";
	margin-left: 0.5rem;
	padding: 1px 2px;
	vertical-align: middle;
	font-size: .6rem;
	color: #fff;
	font-weight: bold;
	border-radius: 3px;
	background-color: #f02020;
}
.main-navigation ul ul li {
	min-width: 250px;
	white-space: nowrap;
	width: 100%;
}
.main-navigation ul ul a {
	width: auto;
	white-space: nowrap;
}

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。