【WordPress】投稿画面に確認チェックボックスを追加して公開前の確認を促す方法

【WordPress】投稿画面に確認チェックボックスを追加して公開前の確認を促す方法 WordPress

WordPressで複数人が投稿するサイトや、誤投稿を防ぎたい運用では、「タイトルは記入済みか」「アイキャッチ画像は設定されているか」などを投稿者に確認してもらう仕組みが重要です。

この記事では、投稿画面に「公開前にチェックを入れてください」といった確認用のチェックボックスを追加し、それがオンでないと投稿できないよう制限する方法を紹介します。

スポンサーリンク

確認チェックボックスを投稿画面に追加する

まず、functions.phpに以下のコードを追加して、投稿画面の右サイドバーに確認チェックボックスを表示させます。

functions.php:確認チェックボックスの追加と保存
<?php
// チェックボックスを追加
function add_confirmation_checkbox_meta_box() {
    add_meta_box(
        'confirm_before_publish',
        '公開前チェック',
        'render_confirmation_checkbox',
        'post',
        'side',
        'high'
    );
}
add_action('add_meta_boxes', 'add_confirmation_checkbox_meta_box');

function render_confirmation_checkbox($post) {
    $value = get_post_meta($post->ID, '_confirm_before_publish', true);
    wp_nonce_field('confirm_checkbox_nonce_action', 'confirm_checkbox_nonce');
    echo '<label><input type="checkbox" name="confirm_checkbox" value="1"' . checked($value, '1', false) . ' /> 公開前に確認しました</label>';
}

// 保存時にチェック状態を保存
function save_confirmation_checkbox($post_id) {
    if (
        defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ||
        !isset($_POST['confirm_checkbox_nonce']) ||
        !wp_verify_nonce($_POST['confirm_checkbox_nonce'], 'confirm_checkbox_nonce_action')
    ) {
        return;
    }

    $checked = isset($_POST['confirm_checkbox']) ? '1' : '';
    update_post_meta($post_id, '_confirm_before_publish', $checked);
}
add_action('save_post', 'save_confirmation_checkbox');
?>

これにより、投稿画面の「公開」エリアの下部に「公開前に確認しました」というチェックボックスが表示されるようになります。

クラシックエディタ:チェックされていないと公開できないように制御する

次に、チェックが入っていない場合は公開・更新をブロックし、エラーメッセージを表示する処理を追加します。

functions.php:クラシックエディタでの公開制限
<?php
function block_publish_if_unchecked($post_data, $post_array) {
    if (
        $post_data['post_status'] === 'publish' ||
        $post_data['post_status'] === 'future'
    ) {
        // postmetaは今回のリクエストではまだ更新されていない
        // (save_postはこのフィルターより後に発火するため)ので、
        // 今回送信された$_POSTを直接確認する
        $nonce_ok = isset($_POST['confirm_checkbox_nonce'])
            && wp_verify_nonce($_POST['confirm_checkbox_nonce'], 'confirm_checkbox_nonce_action');

        if (!$nonce_ok || !isset($_POST['confirm_checkbox'])) {
            wp_die('公開前の確認チェックを行ってください。<br><a href="' . esc_url(admin_url('post.php?post=' . $post_array['ID'] . '&action=edit')) . '">戻る</a>');
        }
    }
    return $post_data;
}
add_filter('wp_insert_post_data', 'block_publish_if_unchecked', 10, 2);
?>
postmetaを見る方式は「チェックして即公開」で必ず失敗する
WordPressコアのwp_insert_post()内では、wp_insert_post_dataフィルターがデータベースへの書き込みより前に発火し、save_postアクションはその後に発火します。そのため、保存済みの_confirm_before_publish postmetaを参照する方式では、チェックボックスを入れてそのまま「公開」をクリックしても、その回のチェック状態を保存するsave_postがまだ実行されておらず、常に「未確認」として判定されてしまいます。wp_die()が処理を中断するため、その回のチェック状態も保存されません。上記コードでは、postmetaではなく今回送信された$_POSTを直接確認することでこの問題を回避しています。

このコードにより、チェックが入っていない状態で「公開」や「予約投稿」を実行しようとすると、公開処理が中断され、注意メッセージが表示されます。

ブロックエディタ:PluginPrePublishPanelで公開ボタン自体をロックする

ブロックエディタではサーバー側のチェックだけでは信頼できない
Gutenberg(ブロックエディタ)で「公開」をクリックすると、実際に投稿ステータスを変更するRESTリクエストと、クラシックメタボックスの$_POSTを運ぶ別のレガシーフォーム送信という、2つの非同期・非協調なリクエストに分かれます(Gutenberg開発者自身がこれを既知の競合状態として認めています)。どちらが先に完了するか保証がないため、$_POSTを直接読む方式に修正しても、ブロックエディタでは信頼して機能しません。ブロックエディタでは、公開前パネルにチェックボックスを追加し、チェックが入るまで公開ボタン自体をJavaScript側でロックする方式が確実です。

まず、エディタ画面専用のスクリプトを読み込みます。

functions.php:エディタ用スクリプトの読み込み
<?php
function enqueue_confirm_prepublish_panel() {
    wp_enqueue_script(
        'confirm-prepublish-panel',
        get_template_directory_uri() . '/block-template/confirm-prepublish-panel.js',
        array( 'wp-plugins', 'wp-editor', 'wp-element', 'wp-components', 'wp-data' ),
        filemtime( get_template_directory() . '/block-template/confirm-prepublish-panel.js' )
    );
}
add_action( 'enqueue_block_editor_assets', 'enqueue_confirm_prepublish_panel' );
?>

次に、テーマ内に block-template/confirm-prepublish-panel.js を作成し、以下の内容を記述します。

block-template/confirm-prepublish-panel.js
(function (plugins, editor, components, element, data) {
    var registerPlugin = plugins.registerPlugin;
    var PluginPrePublishPanel = editor.PluginPrePublishPanel;
    var CheckboxControl = components.CheckboxControl;
    var useState = element.useState;
    var useEffect = element.useEffect;
    var useDispatch = data.useDispatch;
    var el = element.createElement;

    var LOCK_NAME = 'confirm-checklist-lock';

    function ConfirmPrePublishCheck() {
        var state = useState(false);
        var isChecked = state[0];
        var setIsChecked = state[1];
        var editorDispatch = useDispatch('core/editor');

        useEffect(function () {
            if (isChecked) {
                editorDispatch.unlockPostSaving(LOCK_NAME);
            } else {
                editorDispatch.lockPostSaving(LOCK_NAME);
            }
        }, [isChecked]);

        return el(
            PluginPrePublishPanel,
            { title: '公開前チェック', initialOpen: true },
            el(CheckboxControl, {
                label: '公開前に確認しました',
                checked: isChecked,
                onChange: setIsChecked
            })
        );
    }

    registerPlugin('confirm-pre-publish-check', {
        render: ConfirmPrePublishCheck
    });
})(
    window.wp.plugins,
    window.wp.editor,
    window.wp.components,
    window.wp.element,
    window.wp.data
);

これにより、公開前パネルに確認用チェックボックスが表示され、チェックを入れるまで「公開」ボタンが無効化されます。lockPostSaving()・unlockPostSaving()はロック名(LOCK_NAME)ごとに独立して管理されるため、他のプラグインが設定するロックと衝突する心配もありません。

カスタム投稿タイプにも対応させるには?

add_meta_box() の対象投稿タイプに 'post' だけでなく 'custom_post_type' を追加すれば、任意のカスタム投稿でも同様のチェックを行えます。

‘post’ を配列にする例
array('post', 'custom_post_type')

よくある質問(FAQ)

Q記事公開前にチェックボックスで確認を必須にするには?
AブロックエディタではPluginPrePublishPanelでReactコンポーネントを追加し、チェックボックスがONになるまでwp.data.dispatch(‘core/editor’).lockPostSaving()で公開ボタンをロックします。クラシックエディタではwp_insert_post_dataフィルターで今回送信された$_POSTを直接確認する方式が必要です(保存済みのpostmetaは公開処理より後にしか更新されないため参照できません)。
Qクラシックエディターでの公開前確認ダイアログを実装するには?
A管理画面にJavaScriptを追加してpost.phpのsubmitボタンのクリックイベントをフックし、confirm()でダイアログを表示してキャンセルの場合はsubmitを止めます。
Q確認チェックボックスの状態をカスタムフィールドに保存するには?
AGutenbergの場合はuseSelect・useDispatch・getEditedPostAttribute()でpost_metaを読み書きします。確認済みフラグをpost_metaに保存することでサーバーサイドでの検証も可能になります。

まとめ

WordPressの投稿画面に確認チェックボックスを追加することで、公開前のチェックを徹底し、誤投稿や内容不足を防ぐ仕組みを簡単に構築できます。

ただし、公開を実際にブロックする処理は、クラシックエディタとブロックエディタで別々の実装が必要です。クラシックエディタでは$_POSTを直接確認する方式、ブロックエディタではPluginPrePublishPanelとlockPostSaving()によるクライアントサイドでのロックを組み合わせることで、どちらのエディタでも確実に機能する仕組みを構築できます。