no publicar publicaciones de tipo de publicación personalizadas si un campo de metadatos no es válido

11

Tengo un tipo de publicación personalizada (CPT) llamado event . Tengo un cuadro de meta para el tipo con varios campos. Me gustaría validar algunos campos antes de publicar un evento. Por ejemplo, si no se especifica la fecha de un evento, me gustaría mostrar un mensaje de error informativo, guardar el evento para editarlo en el futuro, pero evitar que ese evento se publique. ¿El estado "pendiente" para una publicación de CPT sin toda la información necesaria es la forma correcta de tratarlo?

¿Cuál es la mejor práctica para realizar la validación de los campos CPT y evitar que se publique una publicación, pero guárdela para futuras ediciones?

Muchas gracias, Dasha

    
pregunta dashaluna 25.04.2011 - 15:35

4 respuestas

13

Puede evitar que la publicación guarde todos junto con hacks menores de JQuery y validar los campos antes de guardar en el lado del cliente o del lado del servidor con ajax:

primero agregamos nuestro JavaScript para capturar el evento de envío / publicación y lo usamos para enviar nuestra propia función ajax antes del envío real:

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

luego creamos la función para hacer la validación real:

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

siempre puedes cambiarlo un poco para hacer la validación solo para tu tipo de publicación agregando una verificación condicional a la función my_publish_admin_hook para tu tipo de publicación y para validar en el lado del cliente, pero prefiero en el lado del servidor.

    
respondido por el Bainternet 26.04.2011 - 14:20
6

Hay dos pasos en el método: primero, una función para guardar tus datos de campo metabox personalizados (enganchado a save_post), y segundo, una función para leer esa nueva post_meta (que acabas de guardar), validarla y modificarla el resultado de guardar como sea necesario (también enganchado a save_post, pero después del primero). La función del validador, si la validación falla, en realidad cambia el post_status de nuevo a "pendiente", lo que impide efectivamente que se publique la publicación.

Como la función save_post se llama mucho, cada función tiene controles que solo se ejecutan cuando el usuario quiere publicar, y solo para su tipo de publicación personalizada (mycustomtype).

Por lo general, también agrego algunos mensajes de aviso personalizados para ayudar al usuario a saber por qué no se publicó su publicación, pero es más complicado incluirlos aquí ...

No he probado este código exacto, pero es una versión simplificada de lo que he hecho en configuraciones de tipo de publicaciones personalizadas a gran escala.

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

Para varios campos de metabox, solo agregue más marcadores de finalización y recupere más post_meta y realice más pruebas ..

    
respondido por el somatic 25.04.2011 - 23:24
1

tienes que verificar / validar el valor de tu meta campo en ajax, es decir, cuando el usuario pulsa el botón "Publicar / Actualizar". Aquí estoy validando el producto de woocommerce que tiene un campo meta "product_number" para un valor vacío.

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

Después de eso, agregue la función de controlador 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();
}
    
respondido por el Mohan Dere 01.10.2015 - 13:31
0

Solo quería agregar eso para leer las variables de la publicación, usando la solución de Bainternet, tendrás que analizar la cadena en $_POST['form_data'] usando la función PHP parse_str (solo para ahorrarte algo de tiempo de investigación).

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

Luego puedes acceder a cada variable simplemente usando $varname . Por ejemplo, si tiene un meta campo llamado "my_meta", podría acceder a él de esta manera:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
    
respondido por el Agus 22.08.2011 - 08:28

Lea otras preguntas en las etiquetas