元ネタは、本家 Forums です。何千もある投稿のカテゴリー間違いを手作業で直しているそうなので助けてあげましょう。
一括操作をフックできる所を探す
機能を拡張させるにはフックを使います。元々プラグイン用な雰囲気ですが、プラグイン作って配布したらサポートでエラいことになりそうで怖いです。プラグイン作者様ってすごい、尊敬するぜ。みんな積極的に donate しようぜ!
- [一括操作]で[投稿を更新]をクリックする。
- wp-admin/edit.php からスタート。ざっと見るとフックは使用されていないので、呼び出している関数を見てみます。
- 25行目
check_admin_referer('bulk-posts');
edit.php が管理画面から実行されているかチェックする関数です。内部で以下のアクションを実行しています。 wp-includes/pluggable.php
810行目do_action('check_admin_referer', $action, $result);
- 89行目
$done = bulk_edit_posts($_GET);
「一括操作」を処理する関数です。内部を見ても投稿を更新する wp_update_post までフックはありません。 wp-admin/includes/post.php
307行目$updated[] = wp_update_post( $post_data );
使えるフックは check_admin_referer アクションだけです。これをフックしてカテゴリー削除しましょう。本来の目的とはまったく違う使い方なのでイレギュラーなカスタマイズです。ご利用は at your own risk でよろしく。
「カテゴリーを削除する」UI を追加する
熟慮の結果、カテゴリーチェックボックス群に[選択したカテゴリーを削除する]チェックボックスを追加する事にします。
- カテゴリーチェックボックス群は <ul class="cat-checklist"> のリストになっている。
- リストを出力しているのは wp-admin/includes/template.php 1108行目の wp_category_checklist。
- wp_category_checklist を調べて、とメンドクサくなってきたので javascript で追加することに決定。
admin-script.js を作成して以下を記述。
jQuery(document).ready(function($){
$('.cat-checklist')
.prepend(
'<li>
<label class="selectit"><input value="1" type="checkbox"
name="remove_categories" id="remove_categories"/> 選択したカテゴリーを削除する</label>
</li>'
);
});
そして functions.php に以下を追加します。
function my_enqueue() {
wp_enqueue_script('my_admin_script', get_bloginfo('template_url') . '/admin-script.js', array('jquery'), false, true);
}
add_action('admin_init', 'my_enqueue');
これで[選択したカテゴリーを削除する]チェックボックスが表示されました。
選択されたカテゴリー達を選択された投稿達から削除する
以下を functions.php に追加すれば OK。一括操作で[選択したカテゴリーを削除する]といくつかのカテゴリーにチェックがあった場合にのみ、カテゴリー削除をします。
function my_bulk_edit($action, $result){
if('bulk-posts' == $action && isset($_GET['remove_categories']) && isset($_GET['post_category'])){
if(($_GET['action'] != -1 || $_GET['action2'] != -1 ) && ( isset($_GET['post']) || isset($_GET['ids']))){
$post_ids = isset($_GET['post']) ? array_map( 'intval', (array) $_GET['post'] ) : explode(',', $_GET['ids']);
$doaction = ($_GET['action'] != -1) ? $_GET['action'] : $_GET['action2'];
}
if('edit' == $doaction){
if(isset($_GET['post_type']) && 'page' == $_GET['post_type']){
if(! current_user_can('edit_pages'))
wp_die( __('You are not allowed to edit pages.'));
} else {
if(! current_user_can( 'edit_posts' ))
wp_die( __('You are not allowed to edit posts.'));
}
$post_IDs = array_map('intval', (array) $_GET['post']);
if(is_array($_GET['post_category']) && ! empty($_GET['post_category'])){
$remove_cats = array_map('absint', $_GET['post_category']);
unset($_GET['post_category']);
foreach($post_IDs as $post_ID){
if(wp_check_post_lock($post_ID)) continue;
$cats = (array) wp_get_post_categories($post_ID);
$post_data['post_category'] = array_diff($cats, $remove_cats);
$post_data['ID'] = $post_ID;
wp_update_post($post_data);
}
}
}
}
}
add_action('check_admin_referer', 'my_bulk_edit', 10, 2);
チェックされたカテゴリーの ID は $_GET['post_category']
配列に入っています。選択された各々の投稿について、その投稿のカテゴリー達と $_GET['post_category']
との差分(array_diff)で投稿のカテゴリーを更新します。unset($_GET['post_category']);
することで、この後の通常の一括操作処理で 選択されたカテゴリーが「追加」されないようにします。
参照:Forum
Remove Categories with bulk edit動作確認バージョン
- WordPress 2.9.1
バージョン 3.2.1では
function my_bulk_edit内の$_GETを$_REQUESTに変更すると動作しますよ。
きゃー!そうなんですね、ありがとうございます!!感謝☆
一括操作をフックできる所を探す