WEBLOG

WordPress > サイト毎の設定

WordPress管理画面のサイドメニューをプラグインなしでカスタマイズ

Create:

Update:

Category:WordPressサイト毎の設定

Series:WordPressサイト毎の設定

[ Version.19 ]

概要

WordPress管理画面のサイドメニューを管理者と各ユーザー別に設定。

プラグインは使用しません。

functions.php には設定値のみ記載して functions_setup.php に記述しinclude。

functions.php

設定定数「WPADMIN_NAV」については下部にサンプルがあります。

const WPADMIN_NAV = [
	'サンプル投稿タイプ名' => [
		'type' => 'posttype',
		'path' => 'edit.php?post_type=xxx',
		'user' => [2],
	],
	'サンプル固定ページ名' => [
		'type' => 'page',
		'path' => 'post.php?post=999&action=edit',
		'user' => [2],
	],
	'メディア' => [
		'type' => 'media',
		'user' => [],
	],
	'ユーザー' => [
		'type' => 'user',
		'user' => [],
	]
];
include_once 'xxx/functions_setup.php';

type

サイドメニューのタイプ

type には「posttype(カスタム投稿タイプ)」「page(固定ページ)」「other(その他)」の中から選択。

「一覧」と「新規追加」、関連づいた「カスタムタクソノミー」はposttypeの場合自動で表示されます。

path

サイドメニューのリンク先

  • 「http」「//」 で始まるのものはそのまま
  • 「/」で始まるものは「URL/PUBLICDIR」自動付与
  • 上記以外は「URL」と「/wp/wp-admin/」を自動付与

user

ユーザーID(数値)を設定することで管理権限付与 ※ 管理者にはすべて表示

multisite

マルチサイトの slug ※ 記入がなくても可

マルチサイトで各ブログ共通メニューにする場合に使用します。

add_submenu と remove_submenu

サブメニューを追加・削除する場合に使用 ※ 記入がなくても可

path、user、multisite に関しては上記に同じです。

functions_setup.php

マルチサイトの場合、各子テーマなら個別設定値を読み込みます。

子テーマで「WPADMIN_NAV_CHILD」を設定しない場合は、親テーマの「WPADMIN_NAV」で全管理画面全てのサイドメニューが共通になります。

/* multisite_adjust */
define('WPADMIN_NAV_FIXED', defined('WPADMIN_NAV_CHILD') ? WPADMIN_NAV_CHILD : WPADMIN_NAV);

メインの処理

管理画面のサイドメニューを設置する際にダッシュボードも同じ設定値で作成されます。

add_action('wp_dashboard_setup', function () {
	global $wp_meta_boxes;
	$metabox_title = '更新管理メニュー';
	wp_add_dashboard_widget('nav_dashboard_widget', $metabox_title, function () {
		$tag = '';
		$tb = '';
		$tag .= $tb . '' . '<div>' . "\n";
		$tag .= $tb . "\t" . '<ul class="oo_dashboard_navi">' . "\n";
		foreach (WPADMIN_NAV_FIXED as $k => $v) {
			if (oo_has_cap($v['user'])) {
				switch ($v['type']) {
					case 'heading_dashboard':
						$tag .= $tb . "\t\t" . '<li class="separate">' . $k . '</li>' . "\n";
						break;
					case 'posttype':
					case 'page':
					case 'other':
						if (isset($v['option_disp_submenu_dashbord']) && isset($v['add_submenu']) && $v['option_disp_submenu_dashbord']) {
							foreach ($v['add_submenu'] as $kk => $vv) {
								$blog_slug = $vv['multisite'] ?? false;
								$href = adjust_menu_path($vv['path'], $blog_slug);
								$tag .= $tb . "\t\t" . '<li><a href="' . $href . '" class="wp-ui-highlight">' . $kk . '</a></li>' . "\n";
							}
						} else {
							$blog_slug = $v['multisite'] ?? false;
							$href = adjust_menu_path($v['path'], $blog_slug);
							$tag .= $tb . "\t\t" . '<li><a href="' . $href . '" class="wp-ui-highlight">' . $k . '</a></li>' . "\n";
						}
						break;
				}
			}
		}
		$tag .= $tb . "\t" . '</ul>' . "\n";
		$tag .= $tb . '' . '</div>' . "\n";
		echo $tag;
	});
	$normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
	$nav_widget_backup = ['nav_dashboard_widget' => $normal_dashboard['nav_dashboard_widget']];
	unset($normal_dashboard['nav_dashboard_widget']);
	$sorted_dashboard = array_merge($nav_widget_backup, $normal_dashboard);
	$wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard;
});

サイドメニューの処理

// sidemenu
add_action('admin_menu', function () {
	global $menu, $submenu;
	$current_user_id = get_current_user_id();
	$ok_user_ids = []; // 管理画面の設定に含まれている user_ids
	foreach (WPADMIN_NAV_FIXED as $k => $v) {
		if ($v['type'] === 'heading_dashboard') {
			continue;
		}
		$blog_slug = $v['multisite'] ?? false;
		if (oo_has_cap($v['user'])) {
			$ok_user_ids = array_unique(array_merge($v['user'], $ok_user_ids));
			$dashicon = $v['option_dashicon'] ?? 'dashicons-arrow-right';
			switch ($v['type']) {
				case 'posttype':
					if (isset($blog_slug['slug'])) {
						$blog_slug = $blog_slug['slug'];
					}
					if (!$blog_slug || $blog_slug === MULTISITEBLOGNAME) {
						remove_menu_page($v['path']);
					}
					$v['path'] = adjust_menu_path($v['path'], $blog_slug);
					add_menu_page($k, $k, 'edit_posts', $v['path'], '', $dashicon);
					break;
				case 'page':
					$v['path'] = adjust_menu_path($v['path'], $blog_slug);
					add_menu_page($k, $k, 'edit_posts', $v['path'], '', $dashicon);
					break;
				case 'other':
					$v['path'] = adjust_menu_path($v['path']);
					add_menu_page($k, $k, 'edit_posts', adjust_menu_path($v['path']), '', $dashicon);
					break;
			}
			// submenu : add
			if (isset($v['add_submenu'])) {
				foreach ($v['add_submenu'] as $kk => $vv) {
					if (oo_has_cap($vv['user'])) {
						$blog_slug_for_sub = $vv['multisite'] ?? false;
						$vv['path'] = adjust_menu_path($vv['path'], $blog_slug_for_sub);
						if (isset($blog_slug_for_sub['slug'])) {
							$blog_slug_for_sub = $blog_slug_for_sub['slug'];
						}
						remove_submenu_page($v['path'], htmlspecialchars($vv['path']));
						add_submenu_page($v['path'], $kk, $kk, 'edit_posts', $vv['path']);
					}
				}
			}
			// submenu : remove
			if (isset($v['remove_submenu'])) {
				foreach ($v['remove_submenu'] as $vv) {
					if (isset($vv['user']) && in_array($current_user_id, array_merge($vv['user']))) {
						remove_submenu_page($v['path'], htmlspecialchars($vv['path']));
					}
				}
			}
		} else {
			switch ($v['type']) {
				case 'posttype':
					if (!$blog_slug || $blog_slug === MULTISITEBLOGNAME) {
						remove_menu_page($v['path']);
					}
					break;
				case 'media':
					remove_menu_page('upload.php');
					break;
				case 'user':
					if (oo_has_cap($v['user'])) {
						remove_menu_page('users.php');
					}
					break;
			}
		}
	}
	if (!current_user_can('manage_options')) {
		remove_menu_page('edit.php?post_type=page'); // 固定ページ
		remove_menu_page('edit-comments.php'); // コメント
		remove_menu_page('themes.php'); // 外観
		remove_menu_page('plugins.php'); // プラグイン
		remove_menu_page('tools.php'); // ツール
		remove_menu_page('options-general.php'); // 設定
	} elseif (!in_array($current_user_id, $ok_user_ids)) {
		remove_menu_page('index.php'); // ダッシュボード
		remove_menu_page('edit.php'); // 投稿
	}
});

サイドメニューの並び替え

以下は、共通の設定を二か所に add_filter するため、無名関数を使用していません。

add_filter('custom_menu_order', 'sidemenu_order');
add_filter('menu_order', 'sidemenu_order');
function sidemenu_order($menu_order)
{
	global $menu;
	$arr = [];
	$arr[] = 'index.php'; //ダッシュボード
	$arr[] = 'separator1';
	$count = 1;
	foreach (WPADMIN_NAV_FIXED as $v) {
		if (in_array($v['type'], ['posttype', 'page', 'other'])) {
			$blog_slug = $v['multisite'] ?? false;
			$v['path'] = adjust_menu_path($v['path'], $blog_slug);
			$arr[] = $v['path'];
		}
	}
	$arr[] = 'separator2';
	$arr[] = 'separator3';
	$arr[] = 'separator4';
	$arr[] = 'separator5';
	$arr[] = 'edit.php'; //投稿
	$arr[] = 'edit.php?post_type=page'; //固定ページ
	$arr[] = 'upload.php'; //メディア
	$arr[] = 'edit-comments.php'; //コメント
	if (current_user_can('manage_options')) {
		$arr[] = 'separator-last'; //最後のセパレータ
	}
	$arr[] = 'themes.php'; //外観
	$arr[] = 'users.php'; //ユーザー
	$arr[] = 'plugins.php'; //プラグイン
	$arr[] = 'tools.php'; //ツール
	$arr[] = 'options-general.php'; //設定
	return $arr;
}

wp_admin_barの処理

add_action('admin_bar_menu', function ($wpadminbar) {
	if (!current_user_can('manage_options')) {
		$wpadminbar->remove_menu('wp-logo');
		$wpadminbar->remove_menu('wporg');
		$wpadminbar->remove_menu('documentation');
		$wpadminbar->remove_menu('support-forums');
		$wpadminbar->remove_menu('feedback');
		$wpadminbar->remove_menu('search');
		$wpadminbar->remove_menu('edit-profile');
		$wpadminbar->remove_menu('new-content');
		$wpadminbar->remove_menu('updates');
		$wpadminbar->remove_menu('comments');
		$wpadminbar->remove_menu('new-user');
		$wpadminbar->remove_menu('user-info');
	}
}, 90);

管理画面用 共通 パス変換関数

function adjust_menu_path($path, $blog_slug = false)
{
	$path = htmlspecialchars($path);
	$scheme = is_ssl() ? 'https' : 'http';
	if (is_multisite() && $blog_slug && defined('MULTISITEBLOGNAME')) {
		// 設定値 multisite の 型 により調整
		if (isset($blog_slug['slug'])) {
			$blog_slug = $blog_slug['slug'];
		}
		if ($blog_slug != MULTISITEBLOGNAME) {
			if ($blog_slug === 'base') {
				$temp_blog_id = 1;
			} else {
				$temp_arr = array_flip(MULTISITE_BLOG);
				$temp_blog_id = $temp_arr[$blog_slug];
			}
			$multisite_blog_url = get_site_url($temp_blog_id, '/', $scheme);
			$path = $multisite_blog_url . 'wp-admin/' . $path;
		}
	} elseif (substr($path, 0, 1) === '/') {
		$global_home_url = network_home_url('', $scheme);
		$global_home_url = substr($global_home_url, -1) === '/' ? substr($global_home_url, 0, -1) : $global_home_url; // 念のため「/」を削除
		$path = $global_home_url . $path;
	}
	return $path;
}

設定定数 WPADMIN_NAV サンプル

const WPADMIN_NAV = [
	'投稿タイプ名' => [
		'type' => 'posttype',
		'path' => 'edit.php?post_type=xxx',
		'user' => [2],
		'multisite' => 'base',
		'add_submenu' => [
			'追加サブメニュー' => [
				'path' => 'post.php?post=8&action=edit',
				'user' => [2],
				'multisite' => 'base'
			]
		],
		'remove_submenu' => [
			'タクソノミー01' => [
				'path' => 'edit-tags.php?taxonomy=cat_xxx&post_type=xxx',
				'user' => [2]
			]
		]
	],
	'固定ページ名' => [
		'type' => 'page',
		'path' => 'post.php?post=999&action=edit',
		'user' => [2],
		'multisite' => 'base',
		'add_submenu' => [
			'追加サブメニュー' => [
				'path' => 'post.php?post=45&action=edit',
				'user' => [2],
				'multisite' => 'base'
			]
		],
		'remove_submenu' => [
			'タクソノミー01' => [
				'path' => 'edit-tags.php?taxonomy=cat_add01&post_type=xxx',
				'user' => [2],
				'multisite' => 'base'
			]
		]
	],
	'その他' => [
		'type' => 'other',
		'path' => 'https://www.oldoffice.com/',
		'user' => [2],
	],
	'区切り見出し' => [
		'type' => 'heading_dashboard', // ダッシュボード用区切り見出し
		'user' => [2]
	],
];
pagetop
loading