Web制作・開発会社 プレスマンのスタッフブログ

PRESSMAN*Tech

WordPressの一括操作をカスタマイズする

使いそうで使わないhookについてのお話です。

はじめに

一括操作あるじゃないですか。一覧画面に。
WordPressをブログツールではなく、業務用のCMSなんかとして利用する場合は、余計な操作をさせない為に落としておく機能の一つなんですが、
「投稿記事のステータスとかpostmetaのフラグをまとめて変更したい」という要望を 一括操作をカスタマイズして実現したことがあったので残しておこうと思います。

やること

複数の投稿記事のステータスを変更する機能を追加してみようと思います
(一括編集でもできますけどね)。 やることは大きく分けて以下の3点です。
  • 一括操作に非公開のアクションを追加する (アクションの追加)
  • アクションを実行後に投稿ステータスを非公開にする (ハンドラの追加)
  • 非公開が完了した時にnoticeを表示する (noticeの追加)

アクションの追加

一括操作のプルダウンにアクションを追加します。
今回は簡単にステータスを一括非公開にするアクションを追加してみます。
// bulk_actions-{$screen} でfilterする (今回は投稿ページ)
add_filter( 'bulk_actions-edit-post', 'add_bulk_private', 10, 1 );
function add_bulk_private( $actions ) {
    $actions['private'] = esc_html( '非公開' );

    return $actions;
}
やっていることは、$actionsの配列にprivateというアクションを追加しているだけです(下図)。

ハンドラの追加

privateのアクションに対するハンドラを追加します。
// handle_bulk_actions-{$screen} でfilterする
add_filter( 'handle_bulk_actions-edit-post', 'handle_bulk_private', 10, 3 );
function handle_bulk_private( $redirect_to, $doaction, $post_ids ) {
    // 1. 適用されたアクションかどうかを判定する
    if ( 'private' !== $doaction ) {
        return $redirect_to;
    }

    $counter = 0;
    foreach ( $post_ids as $post_id ) {
        // 2. 記事毎に非公開の処理を行う
        wp_private_post( $post_id ) ? ++ $counter : $counter;
    }
    // 3. noticeで使うパラメータをつける
    $redirect_to = add_query_arg( 'private_done', $counter, $redirect_to );

    return $redirect_to;
}
処理としては、以下の3点となります。
  1. 適用されたアクションかどうかを判定する
  2. 記事毎に非公開の処理を行う
  3. noticeで使うパラメータをつける
3については、後述します。
ついでに非公開処理の内容も記載しておきます (ほぼ wp_publish_post からのパクリ)。
function wp_private_post( $post ) {
    global $wpdb;

    if ( ! $post = get_post( $post ) ) {
        return false;
    }

    if ( 'private' == $post->post_status ) {
        return false;
    }

    $wpdb->update( $wpdb->posts, [ 'post_status' => 'private' ], [ 'ID' => $post->ID ] );

    clean_post_cache( $post->ID );

    $old_status        = $post->post_status;
    $post->post_status = 'private';
    wp_transition_post_status( 'private', $old_status, $post );

    return true;
}

noticeの追加

admin_noticesを使って、noticeを表示させる処理を追加します。
ハンドラで用意しておいたパラメータをここで利用します。
add_action( 'admin_notices', 'bulk_private_notice' );
function bulk_private_notice() {
    if ( $count = filter_input( INPUT_GET, 'private_done' ) ) {
        echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( $count ) . ' 件の投稿を非公開に変更しました</p></div>';
        remove_query_arg( 'private_done' );
    }
}
GETで引き渡した値を処理を実行した件数として表示に利用してます。
ちなみにここでclassを notice-error とすると、赤帯のnoticeが表示されます。
ケースに合わせて使い分けると良いでしょう。

おわりに

というお話がこの辺に書かれている、というオチなんですけどね。すみません。
ただ、有名な公開プラグインでやり方が異なっていたり、日本語記事があんまりなかったので、備忘録として残しておきます。