không xuất bản bài đăng loại bài đăng tùy chỉnh nếu trường dữ liệu meta không hợp lệ


12

Tôi có một loại bài tùy chỉnh (CPT) được gọi event. Tôi có một hộp meta cho loại có nhiều trường. Tôi muốn xác nhận một số lĩnh vực trước khi xuất bản một sự kiện. Ví dụ: nếu ngày của sự kiện không được chỉ định, tôi muốn hiển thị thông báo lỗi thông tin, lưu sự kiện để chỉnh sửa trong tương lai, nhưng ngăn sự kiện đó được xuất bản. Là trạng thái 'đang chờ xử lý' cho bài đăng CPT mà không có tất cả thông tin cần thiết là cách phù hợp để xử lý?

Cách tốt nhất để thực hiện xác thực trường CPT và ngăn bài đăng được xuất bản, nhưng lưu nó để chỉnh sửa trong tương lai.

Rất cám ơn, Dasha


Nhẹ nhàng để nhắc nhở bạn câu hỏi này vẫn cần một câu trả lời được chấp nhận ..;) Nếu không trả lời câu hỏi của bạn, vui lòng xem xét cập nhật câu hỏi của bạn với các bình luận bổ sung chi tiết những gì chưa được giải quyết (hoặc nơi bạn có thể cần trợ giúp, nếu có thể).
t31os

Câu trả lời:


14

Bạn có thể ngăn bài đăng lưu tất cả cùng với các bản hack JQuery nhỏ và xác thực các trường trước khi lưu ở phía máy khách hoặc phía máy chủ bằng ajax:

đầu tiên chúng tôi thêm JavaScript của chúng tôi để nắm bắt sự kiện gửi / xuất bản và sử dụng nó để gửi chức năng ajax của riêng chúng tôi trước khi gửi thực tế:

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

sau đó chúng ta tạo hàm để thực hiện xác nhận thực tế:

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

bạn luôn có thể thay đổi nó một chút để thực hiện xác thực chỉ cho loại bài đăng của mình bằng cách thêm kiểm tra có điều kiện để my_publish_admin_hookhoạt động cho loại bài đăng của bạn và để xác thực ở phía máy khách nhưng tôi thích ở phía máy chủ hơn.


Không có cách phía máy chủ để làm điều này?
Jeff

1
Đây là một cách máy chủ để làm điều đó.
Bai Internet

1
Có lẽ tôi đang hiểu nhầm điều gì đó. Có vẻ như bạn chỉ đang sử dụng PHP để kết xuất JavaScript để xác thực. Đó không phải là xác nhận phía máy chủ. Tôi thực sự không hiểu làm thế nào pre_submit_validationphù hợp.
Jeff

Khối đầu tiên my_publish_admin_hookchặn chặn phía máy khách gửi bài - nhưng sau đó, nó thực hiện cuộc gọi AJAX đến máy chủ (gửi trước chính thức pre_submit_validation) để thực hiện xác thực phía máy chủ.
emc

1
Đây vẫn là xác thực phía máy khách, ngay cả khi nó sử dụng AJAX để thực hiện xác thực. Máy khách phải chạy JavaScript ở vị trí đầu tiên để có bất kỳ xác thực nào diễn ra. Tuy nhiên ... tôi vẫn thấy câu trả lời này hữu ích cho việc xác thực trước khi nộp. Cảm ơn!
cr0ybot

7

Có hai bước cho phương thức: thứ nhất, một chức năng lưu dữ liệu trường metabox tùy chỉnh của bạn (được nối với save_post) và thứ hai, một chức năng để đọc post_meta mới (mà bạn vừa lưu), xác thực nó và sửa đổi kết quả của tiết kiệm khi cần thiết (cũng được nối với save_post, nhưng sau lần đầu tiên). Hàm xác thực, nếu xác thực không thành công, thực sự thay đổi post_status trở lại "đang chờ xử lý", ngăn chặn hiệu quả bài đăng được xuất bản.

Vì hàm save_post được gọi rất nhiều, mỗi hàm có kiểm tra để chỉ thực thi khi người dùng có nghĩa là xuất bản và chỉ cho loại bài đăng tùy chỉnh của bạn (mycustomtype).

Tôi cũng thường thêm một số thông báo thông báo tùy chỉnh để giúp người dùng biết lý do tại sao bài đăng của họ không được xuất bản, nhưng chúng có một chút phức tạp để đưa vào đây ...

Tôi đã không kiểm tra mã chính xác này, nhưng đó là phiên bản đơn giản hóa những gì tôi đã thực hiện trong các thiết lập loại bài đăng tùy chỉnh quy mô lớn.

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

Đối với nhiều trường metabox, chỉ cần thêm nhiều dấu hoàn thành và truy xuất thêm post_meta và thực hiện thêm các bài kiểm tra ..


1

bạn phải kiểm tra / xác thực giá trị trường meta của mình trên ajax tức là khi người dùng nhấn nút "Xuất bản / Cập nhật". Ở đây tôi đang xác thực sản phẩm thương mại điện tử có trường meta "sản phẩm" cho giá trị trống.

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

Sau đó thêm chức năng xử lý 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

Chỉ muốn thêm nó để đọc các biến bài đăng, sử dụng giải pháp của BaiNET, bạn sẽ phải phân tích chuỗi trong $_POST['form_data']việc sử dụng parse_strhàm PHP (chỉ để giúp bạn tiết kiệm thời gian nghiên cứu).

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

Sau đó, bạn có thể truy cập từng biến chỉ bằng cách sử dụng $varname . Ví dụ: nếu bạn có một trường meta gọi là "my_meta", bạn sẽ truy cập nó như thế này:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.