段田です。
WordPress案件で「投稿画面カテゴリーで親カテゴリーのチェックボックスを非表示にして欲しい」と要望があり対応しました。
なので今回は投稿画面のカテゴリーカスタマイズについて書きたいと思います。
■実行プログラムについて
カテゴリータブの表示制御は
/wp-admin/includes/template.phpの
wp_terms_checklistメソッドを使っています。
function wp_terms_checklist($post_id = 0, $args = array()) {
$defaults = array(
'descendants_and_self' => 0,
'selected_cats' => false,
'popular_cats' => false,
'walker' => null,
'taxonomy' => 'category',
'checked_ontop' => true
);
$args = apply_filters( 'wp_terms_checklist_args', $args, $post_id );
extract( wp_parse_args($args, $defaults), EXTR_SKIP );
//ここでWalker引数に設定なければWalker_Category_Checklistを生成します。
if ( empty($walker) || !is_a($walker, 'Walker') )
$walker = new Walker_Category_Checklist;
$descendants_and_self = (int) $descendants_and_self;
$args = array('taxonomy' => $taxonomy);
$tax = get_taxonomy($taxonomy);
$args['disabled'] = !current_user_can($tax->cap->assign_terms);
if ( is_array( $selected_cats ) )
$args['selected_cats'] = $selected_cats;
elseif ( $post_id )
$args['selected_cats'] = wp_get_object_terms($post_id, $taxonomy, array_merge($args, array('fields' => 'ids')));
else
$args['selected_cats'] = array();
if ( is_array( $popular_cats ) )
$args['popular_cats'] = $popular_cats;
else
$args['popular_cats'] = get_terms( $taxonomy, array( 'fields' => 'ids', 'orderby' => 'count', 'order' => 'DESC', 'number' => 10, 'hierarchical' => false ) );
if ( $descendants_and_self ) {
$categories = (array) get_terms($taxonomy, array( 'child_of' => $descendants_and_self, 'hierarchical' => 0, 'hide_empty' => 0 ) );
$self = get_term( $descendants_and_self, $taxonomy );
array_unshift( $categories, $self );
} else {
$categories = (array) get_terms($taxonomy, array('get' => 'all'));
}
if ( $checked_ontop ) {
// Post process $categories rather than adding an exclude to the get_terms() query to keep the query the same across all posts (for any query cache)
$checked_categories = array();
$keys = array_keys( $categories );
foreach( $keys as $k ) {
if ( in_array( $categories[$k]->term_id, $args['selected_cats'] ) ) {
$checked_categories[] = $categories[$k];
unset( $categories[$k] );
}
}
//先ほど生成したインスタンスを使い実行
// Put checked cats on top
echo call_user_func_array(array(&$walker, 'walk'), array($checked_categories, 0, $args));
}
//先ほど生成したインスタンスを使い実行
// Then the rest of them
echo call_user_func_array(array(&$walker, 'walk'), array($categories, 0, $args));
}
引数「walker」にnullを設定している場合、
wp_terms_checklist内部でWalkerクラスを継承したWalker_Category_Checklistクラスを実行していました。
Walker_Category_Checklistクラスを見てみるとカテゴリのHTML出力していることがわかります。
class Walker_Category_Checklist extends Walker {
var $tree_type = 'category';
var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this
function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent<ul class='children'>\n";
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}
function start_el( &$output, $category, $depth, $args, $id = 0 ) {
extract($args);
if ( empty($taxonomy) )
$taxonomy = 'category';
if ( $taxonomy == 'category' )
$name = 'post_category';
else
$name = 'tax_input['.$taxonomy.']';
$class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : '';
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
}
function end_el( &$output, $category, $depth = 0, $args = array() ) {
$output .= "</li>\n";
}
}
WalkerクラスはHTML出力用の基本クラスです。
Walkerクラスを継承させたクラス(もしくはWalker_Category_Checklistを継承したクラス)をwp_terms_checklistの引数「walker」に渡すことでカスタマイズが可能になります。
【WordPressリファレンス参照】
http://codex.wordpress.org/Function_Reference/Walker_Class
■実装
今回はfunction.phpに
Walker_Category_Checklistクラスを継承した子クラスを作成し、
チェックボックスをカスタマイズします。
(Walker_Category_Checklistクラスがあるtemplate.phpを読み込みます。)
require_once(ABSPATH . '/wp-admin/includes/template.php');
class Danda_Category_Checklist extends Walker_Category_Checklist {
function start_el( &$output, $category, $depth, $args, $id = 0 ) {
extract($args);
if ( empty($taxonomy) )
$taxonomy = 'category';
if ( $taxonomy == 'category' )
$name = 'post_category';
else
$name = 'tax_input['.$taxonomy.']';
$class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : '';
//親カテゴリの時はチェックボックス表示しない
if($category->parent == 0){
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit">' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
}else{
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
}
}
}
そしてfunction.php内に
フック関数を作り、$args[‘walker’]に先ほど作成したクラスのインスタンスを設定
wp_terms_checklist_argsでadd_actionして完了です。
function lig_wp_category_terms_checklist_no_top( $args, $post_id = null ) {
$args['checked_ontop'] = false;
$args['walker'] = new Danda_Category_Checklist();
return $args;
}
add_action( 'wp_terms_checklist_args', 'lig_wp_category_terms_checklist_no_top' );
投稿画面で親カテゴリーのチェックボックスが消えていることが確認できました。
今度はチェックボックスからラジオボタンにしてみましょう。
下記のようにtypeをcheckboxからradioに変更します。
require_once(ABSPATH . '/wp-admin/includes/template.php');
class Danda_Category_Checklist extends Walker_Category_Checklist{
function start_el( &$output, $category, $depth, $args, $id = 0 ) {
extract($args);
if ( empty($taxonomy) )
$taxonomy = 'category';
if ( $taxonomy == 'category' )
$name = 'post_category';
else
$name = 'tax_input['.$taxonomy.']';
$class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : '';
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" . '<label class="selectit"><input value="' . $category->term_id . '" type="radio" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $category->term_id . '"' . checked( in_array( $category->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $category->name )) . '</label>';
}
}
投稿画面でラジオボタンになっていることが確認できました。
これでカスタマイズは以上になります。
装飾等色々捗りそうですね。ではでは。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。