не публікувати власну публікацію типу публікації, якщо поле метаданих недійсне


12

У мене є власний тип публікації (CPT) event. У мене мета-вікно для типу з кількома полями. Я хотів би підтвердити деякі поля перед публікацією події. Наприклад, якщо дата події не вказана, я б хотів відобразити інформаційне повідомлення про помилку, збережіть подію для подальшого редагування, але запобігайте публікації цієї події. Чи є статус "в очікуванні" для публікації CPT без усієї необхідної інформації правильним способом лікування?

Найкраща практика робити перевірку полів CPT і запобігати публікації публікації, але зберегти її для подальшого редагування.

Велике спасибі, Даша


Ніжно натисніть, щоб нагадати вам, що це питання все ще потребує прийнятої відповіді ..;) Якщо жодна з відповідей не відповіла на ваше запитання, будь ласка, попробуйте оновити своє запитання додатковими коментарями, де детально вказано, на що не зверталися (або де вам може знадобитися допомога, якщо це застосовується).
— t31os

Відповіді:


14

Ви можете запобігти збереженню публікації разом із незначними хаками JQuery і перевірити поля перед збереженням на стороні клієнта чи сервера за допомогою ajax:

спочатку ми додаємо наш 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

1
Можливо, я щось нерозумію. Схоже, ви просто використовуєте PHP для візуалізації JavaScript, що робить перевірку. Це не перевірка на сервері. Я не дуже розумію, як pre_submit_validationвписується.
— Джефф

Перший my_publish_admin_hookблок перехоплює клієнтську сторону, яка надсилає повідомлення, але потім здійснює виклик AJAX на сервер (попередньо офіційне надсилання pre_submit_validation), який виконує перевірку на стороні сервера.
— emc

1
Це все ще перевірка на стороні клієнта, навіть якщо для перевірки використовується AJAX. Клієнт повинен запустити JavaScript в першу чергу для того, щоб відбулася будь-яка перевірка. Однак ... я все-таки вважаю цю відповідь корисною для перевірки перед поданням. Спасибі!
— cr0ybot

7

До методу є два етапи: по-перше, це функція збереження власних даних поля поля метабокса (підключена до save_post), а по-друге, функція для зчитування нового 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, тобто коли користувач натисне кнопку "Опублікувати / оновити". Тут я перевіряю продукт woocommerce, що має мета-поле "product_number" для порожнього значення.

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']допомогою parse_strфункції PHP (просто щоб заощадити час на дослідження).

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

Тоді ви можете отримати доступ до кожної змінної лише за допомогою $varname. Наприклад, якщо у вас є мета-поле під назвою "my_meta", ви отримаєте доступ до нього так:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.