web-dev-qa-db-fra.com

ne publie pas de message de type message personnalisé si un champion de métadonnées n'est pas valide

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 un poste CPT sans toutes les informations nécessaires est-il la bonne façon de le 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

11
dashaluna

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 submit/publish et 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
    }
}

ensuite, nous créons la fonction pour effectuer la validation proprement dite:

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.

13
Bainternet

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

Étant 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).

J'ajoute aussi généralement des messages de notification personnalisés pour aider l'utilisateur à comprendre pourquoi son message n'a pas été publié, mais ceux-ci sont devenus un peu compliqués à 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 à grande échelle de type publication personnalisée.

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, récupérez plus de post_meta et effectuez plus de tests.

6
somatic

vous devez vérifier/valider la valeur de votre champ méta sur ajax, c.-à-d. 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();
}
1
Mohan Dere

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'] à l'aide de 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 }
0
Agus