メタデータフィールドが有効でない場合、カスタム投稿タイプの投稿を公開しない


12

というカスタム投稿タイプ(CPT)がありeventます。いくつかのフィールドを持つタイプのメタボックスがあります。イベントを公開する前に、いくつかのフィールドを検証したいと思います。たとえば、イベントの日付が指定されていない場合、有益なエラーメッセージを表示し、将来の編集のためにイベントを保存しますが、そのイベントは公開されません。必要なすべての情報がないCPT投稿の「保留中」ステータスは、それを処理する正しい方法ですか?

CPTフィールドの検証を行い、投稿が公開されないようにするが、将来の編集のために保存するためのベストプラクティスは何ですか。

どうもありがとう、ダーシャ


この質問がまだ承認された回答を必要としていることを思い出させるために穏やかな微調整..;)どちらの回答もあなたの質問に対処しなかった場合は、対処されていないもの(または該当する場合は助けが必要な場所)を詳述する追加のコメントで質問を更新することを検討してください。
t31os

回答:


14

ajaxを使用してクライアント側またはサーバー側で保存する前に、マイナーなJQueryハックと一緒に投稿がすべてを保存しないようにしてフィールドを検証できます。

最初にJavaScriptを追加して、送信/発行イベントをキャプチャし、実際の送信の前にそれを使用して独自のajax関数を送信します。

 add_action('wp_print_scripts','my_publish_admin_hook');

function my_publish_admin_hook(){
if (is_admin()){
        ?>
        <script language="javascript" type="text/javascript">
            jQuery(document).ready(function() {
                jQuery('#post').submit(function() {

                    var form_data = jQuery('#post').serializeArray();
                    form_data = jQuery.param(form_data);
                    var data = {
                        action: 'my_pre_submit_validation',
                        security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
                        form_data: form_data
                    };
                    jQuery.post(ajaxurl, data, function(response) {
                        if (response.indexOf('True') > -1 || response.indexOf('true') > -1 || response === true ||  response) {
                            jQuery('#ajax-loading').hide();
                            jQuery('#publish').removeClass('button-primary-disabled');
                            return true;
                        }else{
                            alert("please correct the following errors: " + response);
                            jQuery('#ajax-loading').hide();
                            jQuery('#publish').removeClass('button-primary-disabled');
                            return false;
                        }
                    });
                    return false;
                });
            });
        </script>
        <?php
    }
}

次に、実際の検証を行う関数を作成します。

add_action('wp_ajax_my_pre_submit_validation', 'pre_submit_validation');
function pre_submit_validation(){
    //simple Security check
    check_ajax_referer( 'pre_publish_validation', 'security' );

    //do your validation here
    //all of the form fields are in $_POST['form_data'] array
    //and return true to submit: echo 'true'; die();
    //or your error message: echo 'bal bla bla'; die();
}

常にそれを少し変更して、投稿タイプに対してmy_publish_admin_hook機能する条件付きチェックを追加することで、投稿タイプに対してのみ検証を実行し、クライアント側で検証することができますが、サーバー側で優先します。


これを行うサーバー側の方法はありませんか?
ジェフ

1
これは、サーバー側の方法です。
Bainternet 2014

1
多分私は何かを誤解しています。PHPを使用して、検証を行うJavaScriptをレンダリングしているようです。これはサーバー側の検証ではありません。私は実際にどのように理解していないよpre_submit_validationフィットインチ
ジェフ

最初のmy_publish_admin_hookブロックはクライアント側で投稿後の送信をインターセプトしますが、サーバーpre_submit_validation側の検証を実行するサーバー(のpre-official-submit )に対してAJAX呼び出しを行います。
2015

1
これは、AJAXを使用して検証を行っている場合でも、クライアント側の検証です。検証を行うには、クライアントが最初にJavaScriptを実行する必要があります。ただし...この回答は、提出前の検証に役立ちます。ありがとう!
cr0ybot

7

メソッドには2つのステップがあります。1つはカスタムメタボックスフィールドデータを保存する関数(save_postにフック)、2つ目はその新しいpost_meta(保存したばかり)を読み取り、それを検証して結果を変更する関数です。必要に応じて保存します(save_postにもフックされますが、最初の後で)。バリデーター関数は、検証が失敗した場合、実際にはpost_statusを「保留」に戻し、投稿の公開を効果的に防ぎます。

save_post関数は頻繁に呼び出されるため、各関数には、ユーザーがパブリッシュする意味がある場合にのみ実行するチェックがあり、カスタム投稿タイプ(mycustomtype)に対してのみ実行されます。

私は通常、投稿が公開されなかった理由をユーザーに知らせるためにいくつかのカスタム通知メッセージも追加しますが、それらをここに含めるには少し複雑になりました...

私はこの正確なコードをテストしていませんが、大規模なカスタム投稿タイプのセットアップで行ったものを簡略化したバージョンです。

add_action('save_post', 'save_my_fields', 10, 2);
add_action('save_post', 'completion_validator', 20, 2);

function save_my_fields($pid, $post) {
    // don't do on autosave or when new posts are first created
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // abort if not my custom type
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // save post_meta with contents of custom field
    update_post_meta($pid, 'mymetafield', $_POST['mymetafield']);
}


function completion_validator($pid, $post) {
    // don't do on autosave or when new posts are first created
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // abort if not my custom type
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // init completion marker (add more as needed)
    $meta_missing = false;

    // retrieve meta to be validated
    $mymeta = get_post_meta( $pid, 'mymetafield', true );
    // just checking it's not empty - you could do other tests...
    if ( empty( $mymeta ) ) {
        $meta_missing = true;
    }

    // on attempting to publish - check for completion and intervene if necessary
    if ( ( isset( $_POST['publish'] ) || isset( $_POST['save'] ) ) && $_POST['post_status'] == 'publish' ) {
        //  don't allow publishing while any of these are incomplete
        if ( $meta_missing ) {
            global $wpdb;
            $wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $pid ) );
            // filter the query URL to change the published message
            add_filter( 'redirect_post_location', create_function( '$location','return add_query_arg("message", "4", $location);' ) );
        }
    }
}

複数のメタボックスフィールドの場合は、補完マーカーを追加して、post_metaをさらに取得し、テストを実行するだけです。


1

ajaxでメタフィールド値を確認/検証する必要があります。つまり、ユーザーが[公開/更新]ボタンをクリックしたときです。ここでは、空の値のメタフィールド「product_number」を持つwoocommerce製品を検証しています。

add_action('admin_head-post.php','ep_publish_admin_hook');
add_action('admin_head-post-new.php','ep_publish_admin_hook');

function ep_publish_admin_hook(){
    global $post;
    if ( is_admin() && $post->post_type == 'product' ){
        ?>
        <script language="javascript" type="text/javascript">
            (function($){
                jQuery(document).ready(function() {

                    jQuery('#publish').click(function() {
                        if(jQuery(this).data("valid")) {
                            return true;
                        }

                        //hide loading icon, return Publish button to normal
                        jQuery('#publishing-action .spinner').addClass('is-active');
                        jQuery('#publish').addClass('button-primary-disabled');
                        jQuery('#save-post').addClass('button-disabled');

                        var data = {
                            action: 'ep_pre_product_submit',
                            security: '<?php echo wp_create_nonce( "pre_publish_validation" ); ?>',
                            'product_number': jQuery('#acf-field-product_number').val()
                        };
                        jQuery.post(ajaxurl, data, function(response) {

                            jQuery('#publishing-action .spinner').removeClass('is-active');
                            if ( response.success ){
                                jQuery("#post").data("valid", true).submit();
                            } else {
                                alert("Error: " + response.data.message );
                                jQuery("#post").data( "valid", false );

                            }
                            //hide loading icon, return Publish button to normal
                            jQuery('#publish').removeClass('button-primary-disabled');
                            jQuery('#save-post').removeClass('button-disabled');
                        });
                        return false;
                    });
                });
            })(jQuery);
        </script>
        <?php
    }
}

その後、ajaxハンドラー関数を追加します。

add_action('wp_ajax_ep_pre_product_submit', 'ep_pre_product_submit_func');
function ep_pre_product_submit_func() {
    //simple Security check
    check_ajax_referer( 'pre_publish_validation', 'security' );

    if ( empty( $_POST['product_number'] ) || empty( $_POST['file_attachment'] ) ) {
         $data = array(
            'message' => __('Please enter part number and specification document.'),
        );
        wp_send_json_error( $data );
    }
    wp_send_json_success();
}

0

Bainternetのソリューションを使用して投稿変数を読み取るためにそれを追加したいだけで$_POST['form_data']、PHP parse_str関数を使用して文字列を解析する必要があります(調査時間を節約するためだけです)。

$vars = parse_str( $_POST['form_data'] );

その後、を使用するだけで各変数にアクセスできます$varname。たとえば、「my_meta」というメタフィールドがある場合、次のようにアクセスします。

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.