jangan publikasikan jenis posting pos khusus jika bidang data meta tidak valid

12

Saya memiliki jenis pos kustom (CPT) yang disebut event. Saya memiliki kotak meta untuk tipe dengan beberapa bidang. Saya ingin memvalidasi beberapa bidang sebelum menerbitkan acara. Misalnya, jika tanggal suatu acara tidak ditentukan, saya ingin menampilkan pesan kesalahan yang informatif, menyimpan acara untuk diedit di masa depan, tetapi mencegah agar acara tersebut tidak dipublikasikan. Apakah status 'tertunda' untuk posting CPT tanpa semua info yang diperlukan adalah cara yang tepat untuk mengobatinya?

Apa praktik terbaik untuk melakukan validasi bidang CPT dan mencegah posting tidak dipublikasikan, tetapi simpan untuk diedit di masa mendatang.

Terima kasih banyak, Dasha

dashaluna
sumber
Dorongan lembut untuk mengingatkan Anda pertanyaan ini masih membutuhkan jawaban yang diterima ..;) Jika tidak ada jawaban yang menjawab pertanyaan Anda, harap pertimbangkan untuk memperbarui pertanyaan Anda dengan komentar tambahan yang merinci apa yang belum diatasi (atau di mana Anda mungkin perlu bantuan, jika berlaku).
t31os

Jawaban:

14

Anda dapat menghentikan kiriman dari menyimpan semua bersama-sama dengan peretasan JQuery kecil dan memvalidasi bidang sebelum menyimpan di sisi klien atau sisi server dengan ajax:

pertama-tama kita menambahkan JavaScript untuk menangkap acara kirim / terbitkan dan menggunakannya untuk mengirimkan fungsi ajax kita sendiri sebelum pengiriman yang sebenarnya:

 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
    }
}

lalu kita buat fungsi untuk melakukan validasi aktual:

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();
}

Anda selalu dapat mengubahnya sedikit untuk melakukan validasi hanya untuk jenis posting Anda dengan menambahkan pemeriksaan bersyarat untuk my_publish_admin_hookfungsi untuk jenis posting Anda dan untuk memvalidasi di sisi klien tetapi saya lebih suka di sisi server.

Bainternet
sumber
Apakah tidak ada cara sisi server untuk melakukan ini?
Jeff
1
Ini adalah cara sisi server untuk melakukannya.
Bainternet
1
Mungkin saya salah paham akan sesuatu. Sepertinya Anda hanya menggunakan PHP untuk merender JavaScript yang melakukan validasi. Itu bukan validasi sisi server. Saya tidak begitu mengerti bagaimana pre_submit_validationcocoknya.
Jeff
my_publish_admin_hookBlok pertama memang memotong sisi klien pengiriman kiriman - tetapi kemudian membuat panggilan AJAX ke server (pra-resmi-kirim masuk pre_submit_validation) yang melakukan validasi sisi server.
emc
1
Ini masih validasi sisi klien, bahkan jika itu menggunakan AJAX untuk melakukan validasi. Klien harus menjalankan JavaScript di tempat pertama agar validasi dapat terjadi. Namun ... Saya masih menemukan jawaban ini berguna untuk validasi pra-pengiriman. Terima kasih!
cr0ybot
7

Ada dua langkah untuk metode ini: pertama, fungsi untuk menyimpan data lapangan metabox khusus Anda (terhubung ke save_post), dan kedua, fungsi untuk membaca post_meta baru (yang baru saja Anda simpan), validasi, dan modifikasi hasil dari menyimpan sesuai kebutuhan (juga terhubung ke save_post, tetapi setelah yang pertama). Fungsi validator, jika validasi gagal, sebenarnya mengubah post_status segera kembali ke "pending", secara efektif mencegah posting dipublikasikan.

Karena fungsi save_post dipanggil banyak, setiap fungsi memiliki pemeriksaan untuk hanya mengeksekusi ketika pengguna bermaksud untuk mempublikasikan, dan hanya untuk jenis posting khusus Anda (mycustomtype).

Saya juga biasanya menambahkan beberapa pesan pemberitahuan khusus untuk membantu pengguna mengetahui mengapa posting mereka tidak dipublikasikan, tetapi yang agak rumit untuk dimasukkan di sini ...

Saya belum menguji kode persis ini, tetapi ini adalah versi yang disederhanakan dari apa yang telah saya lakukan dalam pengaturan jenis pos kustom berskala besar.

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);' ) );
        }
    }
}

Untuk beberapa bidang metabox, cukup tambahkan lebih banyak penanda penyelesaian dan ambil lebih banyak post_meta dan lakukan lebih banyak tes ..

somatik
sumber
1

Anda harus memeriksa / memvalidasi nilai bidang meta Anda di ajax yaitu ketika pengguna menekan tombol "Terbitkan / Perbarui". Di sini saya memvalidasi produk woocommerce yang memiliki bidang meta "product_number" untuk nilai kosong.

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
    }
}

Setelah itu tambahkan fungsi ajax handler,

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();
}
Mohan Dere
sumber
0

Hanya ingin menambahkan itu untuk membaca variabel posting, menggunakan solusi Bainternet, Anda harus menguraikan string dalam $_POST['form_data']menggunakan parse_strfungsi PHP (hanya untuk menghemat waktu penelitian).

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

Kemudian Anda dapat mengakses setiap variabel hanya menggunakan $varname. Misalnya, jika Anda memiliki bidang meta yang disebut "my_meta" Anda akan mengaksesnya seperti ini:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
Agus
sumber