ne publie pas de publication de type publication personnalisée si un champ de métadonnées n'est pas valide

11

J'ai un type de message personnalisé (CPT) appelé event . J'ai une meta box pour le type avec plusieurs champs. J'aimerais valider certains champs avant de publier un événement. Par exemple, si la date d'un événement n'est pas spécifiée, je voudrais afficher un message d'erreur informatif, enregistrer l'événement pour le modifier ultérieurement, mais empêcher sa publication. Le statut "en attente" pour une publication CPT sans toutes les informations nécessaires est-il la bonne façon de la traiter?

Quelle est la meilleure pratique pour valider les champs CPT et empêcher une publication d'être publiée, mais enregistrez-la pour une modification ultérieure.

Merci beaucoup, Dasha

    
posée dashaluna 25.04.2011 - 15:35

4 réponses

13

Vous pouvez empêcher la publication de tout enregistrer avec des hacks mineurs de JQuery et valider les champs avant de sauvegarder côté client ou côté serveur avec ajax:

D'abord, nous ajoutons notre code JavaScript pour capturer l'événement de soumission / publication et nous l'utilisons pour soumettre notre propre fonction ajax avant la soumission:

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

alors nous créons la fonction pour effectuer la validation réelle:

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

vous pouvez toujours le modifier un peu pour effectuer la validation uniquement pour votre type de publication en ajoutant une vérification conditionnelle à la fonction my_publish_admin_hook pour votre type de publication et pour la valider côté client, mais je préfère le côté serveur.

    
réponse donnée Bainternet 26.04.2011 - 14:20
6

La méthode comporte deux étapes: premièrement, une fonction pour enregistrer les données de votre champ métabox personnalisé (relié à save_post), et deuxièmement, une fonction pour lire le nouveau post_meta (que vous venez de sauvegarder), le valider et le modifier. le résultat de la sauvegarde si nécessaire (également relié à save_post, mais après le premier). Si la validation échoue, la fonction validateur remet le post_status à "en attente", empêchant ainsi la publication de la publication.

Etant donné que la fonction save_post est appelée beaucoup, chaque fonction a des vérifications à exécuter uniquement lorsque l'utilisateur veut publier, et uniquement pour votre type de publication personnalisé (mycustomtype).

En règle générale, j'ajoute également des messages de notification personnalisés pour aider l'utilisateur à comprendre pourquoi sa publication n'a pas été publiée, mais il est un peu compliqué de l'inclure ici.

Je n'ai pas testé ce code exact, mais c'est une version simplifiée de ce que j'ai fait dans les configurations de type publication personnalisée à grande échelle.

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

Pour plusieurs champs metabox, ajoutez simplement plus de marqueurs de complétion et récupérez plus de post_meta et effectuez plus de tests ..

    
réponse donnée somatic 25.04.2011 - 23:24
1

vous devez vérifier / valider la valeur de votre champ meta sur ajax, c’est-à-dire lorsque l’utilisateur clique sur le bouton "Publier / Mettre à jour". Ici, je valide le produit woocommerce ayant le champ méta "numéro_produit" pour une valeur vide.

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

Après cela, ajoutez la fonction de gestionnaire 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();
}
    
réponse donnée Mohan Dere 01.10.2015 - 13:31
0

Je voulais juste ajouter que pour lire les variables de publication, en utilisant la solution de Bainternet, vous devrez analyser la chaîne dans $_POST['form_data'] en utilisant la fonction PHP parse_str (juste pour vous faire gagner du temps de recherche).

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

Ensuite, vous pouvez accéder à chaque variable en utilisant simplement $varname . Par exemple, si vous avez un champ méta appelé "my_meta", vous y accéderez comme suit:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
    
réponse donnée Agus 22.08.2011 - 08:28

Lire d'autres questions sur les étiquettes