WordPress管理画面カスタマイズあれこれ10選

段田


WordPress管理画面カスタマイズあれこれ10選

こんにちわ、最近は右下のデブと言われることが多い段田です。

今回はWordPress管理画面のカスタマイズを紹介したいと思います。

WordPress管理画面カスタマイズあれこれ10選

1.左メニューのカスタムタクソノミーメニューを消す。

カスタムタクソノミーを追加した際、
管理画面では投稿やカスタム投稿タイプのメニューの中にサブメニューという形で
カスタムタクソノミーメニューが表示されます。

submenu2

このメニューを特定のアカウント時は
表示させないようにするカスタマイズ方法を記載します。

サブメニューはremove_submenu_page関数を使うことで削除出来ます。
remove_submenu_page関数はグローバル変数の$submenuの配列データを操作する形になります。

function remove_submenu_page( $menu_slug, $submenu_slug ) {
	global $submenu;

	if ( !isset( $submenu[$menu_slug] ) )
		return false;

	foreach ( $submenu[$menu_slug] as $i => $item ) {
		if ( $submenu_slug == $item[2] ) {
			unset( $submenu[$menu_slug][$i] );
			return $item;
		}
	}

	return false;
}

第一引数はメニューのスラッグになり、第二引数に削除したいサブメニューのスラッグを入れます。

※スラッグは管理画面URLのwp-admin以降のファイル名とパラメータになります。

例えばカスタム投稿がニュース(news)で
カスタムタクソノミーはニュースカテゴリー(news_category)と設定している場合、
第一引数はカスタム投稿・ニュース(news)のスラッグを指定する形になります。
第二引数はカスタムタクソノミー・ニュースカテゴリー(news_category)のスラッグを指定する形になります。

edit.php?post_type=news(第一引数)
edit-tags.php?taxonomy=news_category&post_type=news(第二引数)

ここで注意しないといけないのは
グローバル変数$submenuの配列データはURLエンコードしているため、
引数は予めURLエンコードしないといけないことです。


add_action( 'admin_menu', 'remove_customer_submenu_page' );

function remove_customer_submenu_page(){
     //ここらへんにアカウントチェックを入れる

     remove_submenu_page( 'edit.php?post_type=news', "edit-tags.php?taxonomy=news_category&post_type=news");
     //URLエンコードしたスラッグを設定する
}

これにより、カスタムタクソノミーのニュースカテゴリーは削除されました。

submenu3

\(^o^)/オワタ

2.投稿画面のパーマリンクを消したい。

稀なケースだと思うのですが、
投稿画面のパーマリンクを消したいという対応が以前にありました。

permlink1

ちょうどget_sample_permalink_htmlフィルターというのがありましたので、
こちらを使って対応しました。

add_filter( 'get_sample_permalink_html' , '__return_false' );

__return_falseはWordPress側で用意されている関数でfalseを返すだけの関数です。

function __return_false() {
	return false;
}

これにより投稿画面からパーマリンクの表示がなくなりました。
(特定のアカウントだけ使いたい場合は__return_falseではなく、関数を作って対応して下さい)

permlink2

\(^o^)/オワタ

3.投稿画面のカテゴリ新規追加とよく使うものを消したい

投稿画面の「カテゴリ新規追加」と「よく使うもの」消したいと思います。

category

強引ですが、CSSを追加して対応しました。

※カスタム投稿がニュース(news)で
カスタムタクソノミーはニュースカテゴリー(news_category)と設定している場合のソースコードになっています。
ID名、post_typeの指定は各自で利用する投稿タイプ、タクソノミーを指定して下さい

function hide_category_add() {
   global $pagenow;
   global $post_type;//投稿タイプで切り分けたいときに使う
   if (is_admin() && ($pagenow=='post-new.php' || $pagenow=='post.php') && $post_type=="news"){
       echo '<style type="text/css">
       #news_category-adder{display:none;}
       #news_category-tabs li.hide-if-no-js{display:none;}
       </style>';
   }
}
  add_action( 'admin_head', 'hide_category_add'  );

「カテゴリ新規追加」はタクソノミー名-adderという名前のIDが作られるので、これを非表示にします。
「よく使うもの」はタクソノミー名-tabsという名前のIDのulタグの下にhide-if-no-jsという名前のクラスで作られるので、これを非表示にします。
category2

消えましたね!

タブ全体を消したい場合はタクソノミー名-tabsだけ指定すればいいです。

function hide_category_add() {
   global $pagenow;
   global $post_type;//投稿タイプで切り分けたいときに使う
   if (is_admin() && ($pagenow=='post-new.php' || $pagenow=='post.php') && $post_type=="news"){
       echo '<style type="text/css">
       #news_category-adder{display:none;}
       #news_category-tabs{display:none;}
       </style>';
   }
}
  add_action( 'admin_head', 'hide_category_add'  );

category3

\(^o^)/オワタ

4.投稿記事の並び順を変更したい。

投稿記事の並び順変更はプラグインで解決出来ます。
プラグインは色々とありますが、
今回はintuitive-custom-post-orderプラグインを利用します。

intuitive-custom-post-orderプラグインを有効化後、
記事一覧画面で記事にカーソルを合わせるとカーソルが変化します。
これをドラッグアンドドロップで上下に移動することで並び順を変更できます。

sort

↓↓↓↓↓↓↓

sort3

直感的なので、操作が苦手な人に優しいです。

フロント画面で出力する際はorderbyでmenu_orderを指定すればOKです。

query_posts(
             array( 'orderby' => 'menu_order',
                    'order' => 'ASC',
                   ),

             );

※2013年7月22日 追記  プラグインの製作者様からorderby指定することなくそのままでいけることを教えて頂きました。ありがとうございます!

\(^o^)/オワタ、ほ、ほーっ、ホアアーッ ホアーッ

5.投稿画面のカテゴリーが投稿時に並び順が変更になる現象を止める

投稿画面のカテゴリーは記事投稿時に
並び順が変更になる現象があります。

並び順が変わらないようにするやり方を
以前にプログラマの小林さんが書いていますので、
こちらをご参考下さい

助かりました!

\(^o^)/ミズマシシタ

6.投稿画面のカテゴリーをラジオボタンにしたい

投稿画面のカテゴリーは元々チェックボックスなんですけど、
ラジオボタンにしたり、親カテゴリにチェックを入れられなくしたり、
カスタマイズができたりします。

以前に私が記事を書いていますので、
こちらをご参考下さい

\(^o^)/サラニミズマシシタ

7.投稿画面でiframeタグを使えるようにしたい

Youtubeやグーグルマップのタグ埋め込みで利用するiframeタグですが、
特権管理者権限以外ではiframeタグが使えません。
これを変更することとができます。

以前にCTOのづやさんが記事を書いていますので、
こちらをご参考下さい

助かりました!

\(^o^)/マタマタミズマシシタ

8.メディアライブラリで他人の画像がでないようにしたい

自分でアップロードした画像やファイルを
他のアカウントでは閲覧できないように変更できます。

以前にCTOのづやさんが記事を書いていますので、
こちらをご参考下さい

助かりました!

\(^o^)/ミズマシシタ モンクアルカ

9.投稿時のアクションフック

投稿時に独自処理を入れたい場合のアクションフックを
CTOのづやさんがここで解説しています。

\(^-^)/ ・・・・

10.記事一覧画面のあいつ(公開数、下書き)の件数をアカウント毎の件数にしたい

とある案件で記事一覧画面の公開数、下書きの記事数を全体の投稿件数からアカウント毎で投稿した件数にする必要がありました。

aitsu

調べた結果、この記事views_スクリーンID名というフィルターで直接弄れることがわかりました。アリガテェアリガテェ

※スクリーンIDは管理画面の各画面に割り振られたID

実際に出力させている関数みるとフィルターありますね!

function views() {
		$views = $this->get_views();
		$views = apply_filters( 'views_' . $this->screen->id, $views );

		if ( empty( $views ) )
			return;

		echo "<ul class='subsubsub'>\n";
		foreach ( $views as $class => $view ) {
			$views[ $class ] = "\t<li class='$class'>$view";
		}
		echo implode( " |</li>\n", $views ) . "</li>\n";
		echo "</ul>";
	}

このフィルターを弄れば表示数もアカウント毎の件数にできそうだし、
独自の項目も追加できそうな感じです。

ググると下記のフォーラムや記事で
先人の方々がやっていました。
先人の方々本当に有難うございます。

http://ja.forums.wordpress.org/topic/11720
plug ‘em in
http://wordpress.stackexchange.com/questions/1482/restricting-users-to-view-only-media-library-items-they-have-uploaded

各記事を参考に作りました。

add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
    global $current_user;
    //管理画面であること  edit_others_posts権限がないこと post_typeがacfでないこと(Advanced Custom Fieldsないときは外して良い)
    if( is_admin() && !current_user_can('edit_others_posts')  && $wp_query->query_vars['post_type'] != 'acf') {
        $wp_query->set( 'author', $current_user->ID );
        $screen = get_current_screen();
        add_filter('views_'.$screen->id, 'fix_post_counts');
        add_filter('views_upload', 'fix_media_counts');
    }
}

// Fix post counts
function fix_post_counts($views) {
    global $current_user, $wp_query,$post_type;
    unset($views['mine']);
    $types = array(
        array( 'status' =>  NULL ),
        array( 'status' => 'publish' ),
        array( 'status' => 'draft' ),
        array( 'status' => 'pending' ),
        array( 'status' => 'trash' )
    );
    foreach( $types as $type ) {
                $query = array(
                    'author'      => $current_user->ID,
                    'post_type'   => $post_type,//全投稿タイプで対応できるようにするため、ここは投稿タイプで取得する
                    'post_status' => $type['status']
                );
                $result = new WP_Query($query);
                if($type['status'] == NULL):
               $class = ($wp_query->query_vars['post_status'] == NULL)  ? ' class="current"' : '';
               $views['all'] = sprintf(__('<a href="%s"'. $class  .'>' . __('All') . ' <span class="count">(%d)</span></a>', 'all'),
                    admin_url('edit.php?post_type='.$post_type),
                    $result->found_posts);
          elseif($type['status'] == 'publish'):
               $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
               $views['publish'] = sprintf(__('<a href="%s"'. $class .'>' . __('Published') . ' <span class="count">(%d)</span></a>', 'publish'),
                    admin_url('edit.php? post_status=publish&post_type='.$post_type),
                    $result->found_posts);
          elseif($type['status'] == 'draft'):
               $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
               $views['draft'] = sprintf(__('<a href="%s"'. $class .'>'. __('Draft') . ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                    admin_url('edit.php?post_status=draft&post_type='.$post_type),
                    $result->found_posts);
          elseif($type['status'] == 'pending'):
               $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
               $views['pending'] = sprintf(__('<a href="%s"'. $class .'>'. __('Pending') .' <span class="count">(%d)</span></a>', 'pending'),
                    admin_url('edit.php?post_status=pending&post_type='.$post_type),
                    $result->found_posts);
          elseif($type['status'] == 'trash'):
               $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
               $views['trash'] = sprintf(__('<a href="%s"'. $class .'>'. __('Trash') .' <span class="count">(%d)</span></a>', 'trash'),
                    admin_url('edit.php?post_status=trash&post_type='.$post_type),
                    $result->found_posts);
          endif;
    }
    return $views;
}

// Fix media counts
function fix_media_counts($views) {
     global $wpdb, $current_user, $post_mime_types,  $avail_post_mime_types;
     $views = array();
     $count = $wpdb->get_results("
          SELECT post_mime_type, COUNT( * ) AS num_posts
          FROM $wpdb->posts
          WHERE post_type = 'attachment'
          AND post_author = $current_user->ID
          AND post_status != 'trash'
          GROUP BY post_mime_type
     ", ARRAY_A );
     foreach($count as $row)
          if ($count && $row != 0) {
               $_num_posts[$row['post_mime_type']] = $row['num_posts'];
               $_total_posts = array_sum($_num_posts);
               $detached = isset($_REQUEST['detached']) || isset($_REQUEST['find_detached']);
          };
     if (!isset($total_orphans))
          $total_orphans = $wpdb->get_var("
               SELECT COUNT( * )
               FROM $wpdb->posts
               WHERE post_type = 'attachment'
               AND post_author = $current_user->ID
               AND post_status != 'trash'
               AND post_parent < 1
          ");
     $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
     foreach ($matches as $type => $reals)
          foreach ($reals as $real)
               $num_posts[$type] = ( isset($num_posts[$type])) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
     $class = (empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status'])) ? ' class="current"' : '';
     $views['all'] = "<a href='upload.php'$class>" . sprintf(__(__('All') .' <span class="count">(%s)</span>', 'uploaded files'), number_format_i18n($_total_posts)) . '</a>';
     foreach ( $post_mime_types as $mime_type => $label ) {
          $class = '';
          if (!wp_match_mime_types($mime_type, $avail_post_mime_types))
               continue;
          if (!empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']))
               $class = ' class="current"';
          if (!empty( $num_posts[$mime_type]))
               $views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf(translate_nooped_plural($label[2], $num_posts[$mime_type]), $num_posts[$mime_type]) . '</a>';
     }
     $views['detached'] = '<a href="upload.php?detached=1"' . ($detached ? ' class="current"' : '') . '>' . sprintf(_x('Unattached <span class="count">(%s)</span>', 'detached files'), $total_orphans) . '</a>';
     return $views;
}

全アカウントの投稿数だったのが
アカウント毎の投稿数になりました。
(構成まで変えちゃいましたが・・・)

aitsu2

↓↓↓↓↓↓↓

aitsu3

\(^o^)/ゼンブオワタ

まとめ

いかがでしたでしょうか?
紹介した内容の半分が水増しという酷い内容ですが、
皆さんのご参考になれば嬉しいです。

それではー。


LIGでは、エンジニアを絶賛募集中!
http://liginc.co.jp/recruit/mid_career

段田
この記事を書いた人
段田

エンジニア兼段田商会店主

関連記事