Come impedire la pubblicazione di un custom post type se un campo meta non è valido

25 apr 2011, 16:35:01
Visualizzazioni: 19K
Voti: 14

Ho un custom post type (CPT) chiamato event. Ho un meta box per questo tipo con diversi campi. Vorrei validare alcuni campi prima di pubblicare un evento. Ad esempio, se la data di un evento non è specificata, vorrei mostrare un messaggio di errore informativo, salvare l'evento per modifiche future, ma impedire che quell'evento venga pubblicato. È corretto usare lo stato 'pending' per un post CPT senza tutte le informazioni necessarie?

Qual è la best practice per validare i campi di un CPT e impedire la pubblicazione di un post, ma salvarlo per modifiche future.

Grazie mille, Dasha

1
Commenti

Un gentile promemoria per ricordarti che questa domanda ha ancora bisogno di una risposta accettata.. ;) Se nessuna delle risposte ha affrontato la tua domanda, ti invitiamo a considerare l'aggiornamento della domanda con commenti aggiuntivi che dettaglino ciò che non è stato affrontato (o dove potresti aver bisogno di aiuto, se applicabile).

t31os t31os
28 lug 2011 12:14:26
Tutte le risposte alla domanda 4
6
15

Puoi impedire completamente il salvataggio del post con piccoli hack jQuery e validare i campi prima del salvataggio lato client o lato server con ajax:

per prima cosa aggiungiamo il nostro JavaScript per catturare l'evento di submit/pubblicazione e usarlo per inviare la nostra funzione ajax prima dell'effettivo submit:

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("correggi i seguenti errori: " + response);
                            jQuery('#ajax-loading').hide();
                            jQuery('#publish').removeClass('button-primary-disabled');
                            return false;
                        }
                    });
                    return false;
                });
            });
        </script>
        <?php
    }
}

poi creiamo la funzione per effettuare la vera e propria validazione:

add_action('wp_ajax_my_pre_submit_validation', 'pre_submit_validation');
function pre_submit_validation(){
    //semplice controllo di sicurezza
    check_ajax_referer( 'pre_publish_validation', 'security' );

    //fai qui la tua validazione
    //tutti i campi del form sono nell'array $_POST['form_data']
    //e restituisci true per inviare: echo 'true'; die();
    //oppure il tuo messaggio di errore: echo 'bal bla bla'; die();
}

puoi sempre modificarlo un po' per fare la validazione solo per il tuo post type aggiungendo un controllo condizionale alla funzione my_publish_admin_hook per il tuo post type e per validare lato client, ma io preferisco farlo lato server.

26 apr 2011 15:20:59
Commenti

Non esiste un modo lato server per farlo?

Jeff Jeff
5 lug 2014 00:58:15

Questo è un metodo lato server per farlo.

Bainternet Bainternet
5 lug 2014 07:59:18

Forse sto fraintendendo qualcosa. Sembra che tu stia usando PHP solo per renderizzare JavaScript che fa la validazione. Questa non è una validazione lato server. Non capisco bene come si inserisca il pre_submit_validation in questo contesto.

Jeff Jeff
7 lug 2014 19:42:26

Il primo blocco my_publish_admin_hook intercetta l'invio del post lato client - ma poi effettua una chiamata AJAX al server (pre-invio ufficiale in pre_submit_validation) che esegue la validazione lato server.

emc emc
3 mar 2015 03:46:12

Questa è ancora una validazione lato client, anche se utilizza AJAX per eseguire la validazione. Il client deve comunque eseguire il JavaScript in primo luogo affinché avvenga qualsiasi validazione.

Tuttavia... ho trovato comunque utile questa risposta per la validazione pre-invio. Grazie!

cr0ybot cr0ybot
15 ago 2016 21:35:00

Peccato non esista un modo nativo in WordPress per fare una cosa così tipica

Fanky Fanky
24 ott 2019 15:02:11
Mostra i restanti 1 commenti
0

Ci sono due passaggi per questo metodo: prima, una funzione per salvare i dati del tuo campo metabox personalizzato (agganciata a save_post), e secondo, una funzione per leggere quel nuovo post_meta (che hai appena salvato), validarlo e modificare il risultato del salvataggio se necessario (anch'essa agganciata a save_post, ma dopo la prima). La funzione di validazione, se la validazione fallisce, cambia effettivamente lo stato del post nuovamente in "pending", impedendo di fatto la pubblicazione del post.

Poiché la funzione save_post viene chiamata spesso, ogni funzione ha dei controlli per eseguirsi solo quando l'utente intende pubblicare e solo per il tuo tipo di post personalizzato (mycustomtype).

In genere aggiungo anche alcuni messaggi di notifica personalizzati per aiutare l'utente a capire perché il suo post non è stato pubblicato, ma quelli sono diventati un po' complicati da includere qui...

Non ho testato questo codice esatto, ma è una versione semplificata di ciò che ho fatto in configurazioni di tipi di post personalizzati su larga scala.

add_action('save_post', 'save_my_fields', 10, 2);
add_action('save_post', 'completion_validator', 20, 2);

function save_my_fields($pid, $post) {
    // non eseguire durante l'autosalvataggio o quando i nuovi post vengono creati per la prima volta
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // interrompi se non è il mio tipo personalizzato
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // salva post_meta con il contenuto del campo personalizzato
    update_post_meta($pid, 'mymetafield', $_POST['mymetafield']);
}


function completion_validator($pid, $post) {
    // non eseguire durante l'autosalvataggio o quando i nuovi post vengono creati per la prima volta
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // interrompi se non è il mio tipo personalizzato
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // inizializza il marcatore di completamento (aggiungine altri se necessario)
    $meta_missing = false;

    // recupera i meta da validare
    $mymeta = get_post_meta( $pid, 'mymetafield', true );
    // verifica solo che non sia vuoto - potresti fare altri test...
    if ( empty( $mymeta ) ) {
        $meta_missing = true;
    }

    // al tentativo di pubblicazione - verifica il completamento e intervieni se necessario
    if ( ( isset( $_POST['publish'] ) || isset( $_POST['save'] ) ) && $_POST['post_status'] == 'publish' ) {
        // non permettere la pubblicazione mentre uno di questi è incompleto
        if ( $meta_missing ) {
            global $wpdb;
            $wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $pid ) );
            // filtra l'URL della query per cambiare il messaggio di pubblicazione
            add_filter( 'redirect_post_location', create_function( '$location','return add_query_arg("message", "4", $location);' ) );
        }
    }
}

Per più campi metabox, basta aggiungere più marcatori di completamento e recuperare più post_meta e fare più test...

26 apr 2011 00:24:03
0

Devi verificare/validare il valore del tuo campo meta via AJAX, cioè quando l'utente clicca sul pulsante "Pubblica/Aggiorna". Qui sto validando un prodotto WooCommerce che ha un campo meta "product_number" per verificare che non sia vuoto.

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

                        //nasconde l'icona di caricamento, ripristina il pulsante Pubblica
                        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("Errore: " + response.data.message );
                                jQuery("#post").data( "valid", false );

                            }
                            //nasconde l'icona di caricamento, ripristina il pulsante Pubblica
                            jQuery('#publish').removeClass('button-primary-disabled');
                            jQuery('#save-post').removeClass('button-disabled');
                        });
                        return false;
                    });
                });
            })(jQuery);
        </script>
        <?php
    }
}

Successivamente aggiungi la funzione di gestione AJAX,

add_action('wp_ajax_ep_pre_product_submit', 'ep_pre_product_submit_func');
function ep_pre_product_submit_func() {
    //semplice controllo di sicurezza
    check_ajax_referer( 'pre_publish_validation', 'security' );

    if ( empty( $_POST['product_number'] ) || empty( $_POST['file_attachment'] ) ) {
         $data = array(
            'message' => __('Inserisci il numero di parte e il documento di specifica.'),
        );
        wp_send_json_error( $data );
    }
    wp_send_json_success();
}
1 ott 2015 14:31:47
0

Volevo solo aggiungere che per leggere le variabili del post, utilizzando la soluzione di Bainternet, dovrai analizzare la stringa in $_POST['form_data'] usando la funzione PHP parse_str (solo per farti risparmiare un po' di tempo di ricerca).

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

Poi puoi accedere a ogni variabile semplicemente usando $varname. Per esempio, se hai un meta campo chiamato "my_meta" potrai accedervi così:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "qualcosa" ) { // fai qualcosa }
22 ago 2011 09:28:00