WordPressで投稿時にバリデーションを行う方法

WordPressで投稿時に、投稿した記事の中に特定の文字が入っているか確認し、入っていればそのまま保存し、入っていなければ警告を表示して保存を中断するというバリデーションの処理方法を紹介したいと思います。

save_postでは無理

この処理を考え始めた当初は、save_postにバリデーション用の関数をフックすれば良いかと考えました。しかし調べていると、save_postはDBにデータをインサート後に実行されるようなので、そこでチェックをしても”時すでに遅し”であることが判明しました。ついでに言うとsave_postにフックした関数で仮にバリデーションエラーとしてfalseをリターンしてもWordPress側では戻り値の確認をしていないので、そのまま処理が続行されてしまいます。

Ajaxを利用する

そこで今回紹介するのはAjaxを利用する方法です。
原理としては、公開ボタンを押したときに動作するAjaxを定義し、そこから呼ばれたPHP側の処理で投稿された記事のバリデーションを行います。

以下は投稿された記事に「hoge」という文字が入っているか確認する場合の例です。functions.phpに記述しています。

add_action('admin_head-post-new.php', 'my_publish_admin_hook'); // 新規投稿画面でのみ関数を呼び出す
add_action('admin_head-post.php', 'my_publish_admin_hook'); // 投稿編集画面でのみ関数を呼び出す
function my_publish_admin_hook(){

    global $post;

    if (is_admin() && $post->post_type == 'post'){ //投稿の場合
    ?>
    <script language="javascript" type="text/javascript">
        jQuery(document).ready(function() {
            jQuery('#publish').click(function() {
                if(jQuery(this).data("valid")) {
                    return true;
                }
                var form_data = jQuery('#post').serializeArray();
                var data = {
                    action: 'my_pre_submit_validation',
                    security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
                    form_data: jQuery.param(form_data),
                };
                jQuery.post(ajaxurl, data, function(response) {
                    if (response.indexOf('true') > -1 || response == true) {
                        jQuery('#publish').data("valid", true).trigger('click');
                    } else {
                        alert("エラー: " + response);
                        jQuery("#publish").data("valid", false);
                    }
                    jQuery('#ajax-loading').hide();
                    jQuery('#publish').removeClass('button-primary-disabled');
                    jQuery('#save-post').removeClass('button-disabled');
                });
                return false;
            });
        });
    </script>
    <?php
    }
}

add_action('wp_ajax_my_pre_submit_validation', 'pre_submit_validation');
function pre_submit_validation(){
    //簡単なセキュリティのチェック
    check_ajax_referer( 'pre_publish_validation', 'security' );

    parse_str( $_POST['form_data'], $vars );
	
	//含まれているべき文字列
	$must_text = 'hoge';

	//バリデーションの実行
	if(strpos($vars['content'], $must_text) === false){
		echo '投稿記事中に"' . $must_text . '"が見つかりませんでした。';
		die();
	}

    //問題が無い場合はtrueを返す
    echo 'true';
    die();
}

最後に

今回は記事を投稿する前に、記事の中身を確認する方法をご紹介しました。
今回紹介した方法を応用すれば、必須の文字列の存在確認だけではなく、記事の長さの確認や、カスタムフィールドがある場合は、その中身の確認もできますね。