it-swarm.com.de

veröffentlichen Sie keine verfügbaren Posts, wenn ein Metadatenfeld nicht gültig ist

Ich habe einen benutzerdefinierten Beitragstyp (CPT) namens event. Ich habe eine Meta-Box für den Typ mit mehreren Feldern. Ich möchte einige Felder validieren, bevor ich eine Veranstaltung veröffentliche. Wenn zum Beispiel das Datum eines Ereignisses nicht angegeben ist, möchte ich eine informative Fehlermeldung anzeigen, das Ereignis zur späteren Bearbeitung speichern, aber die Veröffentlichung dieses Ereignisses verhindern. Ist der Status "Ausstehend" für einen CPT-Beitrag ohne alle erforderlichen Informationen der richtige Weg, ihn zu behandeln?

Was ist die beste Vorgehensweise, um die Überprüfung von CPT-Feldern durchzuführen und zu verhindern, dass ein Beitrag veröffentlicht wird, aber für die spätere Bearbeitung zu speichern?.

Vielen Dank, Dasha

11
dashaluna

Sie können das Speichern aller Posts zusammen mit kleineren JQuery-Hacks unterbinden und die Felder validieren, bevor Sie sie mit Ajax auf der Client- oder Serverseite speichern:

zuerst fügen wir unser JavaScript hinzu, um das Submit/Publish-Ereignis zu erfassen und verwenden es, um unsere eigene Ajax-Funktion vor dem eigentlichen Submit einzureichen:

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

dann erstellen wir die Funktion für die eigentliche Validierung:

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

sie können es immer ein wenig ändern, um die Validierung nur für Ihren Beitragstyp durchzuführen, indem Sie der my_publish_admin_hook -Funktion für Ihren Beitragstyp eine bedingte Prüfung hinzufügen und auf der Clientseite validieren, aber ich bevorzuge auf der Serverseite.

13
Bainternet

Die Methode besteht aus zwei Schritten: Erstens einer Funktion zum Speichern Ihrer benutzerdefinierten Metabox-Felddaten (verknüpft mit save_post) und zweitens einer Funktion zum Lesen der neuen post_meta (die Sie gerade gespeichert haben), zum Validieren und Ändern des Ergebnisses von Speichern nach Bedarf (auch an save_post angehängt, aber nach dem ersten). Wenn die Validierung fehlschlägt, ändert die Validierungsfunktion tatsächlich den post_status wieder auf "ausstehend", wodurch die Veröffentlichung des Posts effektiv verhindert wird.

Da die Funktion save_post häufig aufgerufen wird, wird jede Funktion nur dann ausgeführt, wenn der Benutzer sie veröffentlichen möchte, und nur für Ihren benutzerdefinierten Beitragstyp (mycustomtype).

Normalerweise füge ich auch einige benutzerdefinierte Mitteilungen hinzu, um dem Benutzer zu erklären, warum der Beitrag nicht veröffentlicht wurde, aber die Aufnahme hier wurde etwas kompliziert ...

Ich habe nicht genau diesen Code getestet, aber es ist eine vereinfachte Version von dem, was ich in großen benutzerdefinierten Post-Typ-Setups getan habe.

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

Fügen Sie für mehrere Metabox-Felder einfach weitere Vervollständigungsmarkierungen hinzu, rufen Sie mehr post_meta ab und führen Sie weitere Tests durch.

6
somatic

sie müssen Ihren Metafeldwert in Ajax überprüfen/validieren, d. h., wenn der Benutzer auf die Schaltfläche "Veröffentlichen/Aktualisieren" klickt. Hier validiere ich ein Woocommerce-Produkt mit dem Metafeld "product_number" für einen leeren Wert.

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

Danach fügen Sie die Ajax-Handler-Funktion hinzu,

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

Wollte nur hinzufügen, dass zum Lesen der Post-Variablen unter Verwendung der Bainternet-Lösung die Zeichenfolge in $_POST['form_data'] mit der Funktion PHP parse_str analysiert werden muss (nur um Recherchezeit zu sparen).

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

Dann können Sie mit $varname auf jede Variable zugreifen. Wenn Sie beispielsweise ein Metafeld mit dem Namen "my_meta" haben, würden Sie folgendermaßen darauf zugreifen:

$vars = parse_str ( $_POST['form_data'] ) 
if ( $my_meta == "something" ) { // do something }
0
Agus