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


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.