कस्टम फ़ील्ड न भरे जाने पर पोस्ट को प्रकाशित होने से रोकें


17

मेरे पास एक कस्टम पोस्ट प्रकार Eventहै जिसमें एक प्रारंभिक और समाप्ति तिथि / बार कस्टम फ़ील्ड शामिल हैं (पोस्ट एडिट स्क्रीन में मेटाबॉक्सेस के रूप में)।

मैं यह सुनिश्चित करना चाहूंगा कि कोई ईवेंट तारीखों को भरे बिना प्रकाशित (या अनुसूचित) नहीं हो सकता है, क्योंकि इससे ईवेंट डेटा प्रदर्शित करने वाले टेम्प्लेट के साथ समस्याएँ आएंगी (इस तथ्य के अलावा कि यह एक आवश्यक आवश्यकता है!)। हालाँकि, मैं चाहता हूं कि ड्राफ्ट ईवेंट्स हो सकें, जिनकी तैयारी के दौरान उनके पास कोई वैध दिनांक न हो।

मैं save_postजाँच करने के लिए हुक करने के बारे में सोच रहा था , लेकिन मैं स्थिति को बदलने से कैसे रोक सकता हूँ?

EDIT1: यह वह हुक है जिसका उपयोग मैं अब post_meta को बचाने के लिए कर रहा हूं।

// Save the Metabox Data
function ep_eventposts_save_meta( $post_id, $post ) {

if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
    return;

if ( !isset( $_POST['ep_eventposts_nonce'] ) )
    return;

if ( !wp_verify_nonce( $_POST['ep_eventposts_nonce'], plugin_basename( __FILE__ ) ) )
    return;

// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ) )
    return;

// OK, we're authenticated: we need to find and save the data
// We'll put it into an array to make it easier to loop though

//debug
//print_r($_POST);

$metabox_ids = array( '_start', '_end' );

foreach ($metabox_ids as $key ) {
    $events_meta[$key . '_date'] = $_POST[$key . '_date'];
    $events_meta[$key . '_time'] = $_POST[$key . '_time'];
    $events_meta[$key . '_timestamp'] = $events_meta[$key . '_date'] . ' ' . $events_meta[$key . '_time'];
}

$events_meta['_location'] = $_POST['_location'];

if (array_key_exists('_end_timestamp', $_POST))
    $events_meta['_all_day'] = $_POST['_all_day'];

// Add values of $events_meta as custom fields

foreach ( $events_meta as $key => $value ) { // Cycle through the $events_meta array!
    if ( $post->post_type == 'revision' ) return; // Don't store custom data twice
    $value = implode( ',', (array)$value ); // If $value is an array, make it a CSV (unlikely)
    if ( get_post_meta( $post->ID, $key, FALSE ) ) { // If the custom field already has a value
        update_post_meta( $post->ID, $key, $value );
    } else { // If the custom field doesn't have a value
        add_post_meta( $post->ID, $key, $value );
    }
    if ( !$value ) 
                delete_post_meta( $post->ID, $key ); // Delete if blank
}

}

add_action( 'save_post', 'ep_eventposts_save_meta', 1, 2 );

EDIT2: और यह मैं डेटाबेस को सहेजने के बाद पोस्ट डेटा की जांच करने के लिए उपयोग करने की कोशिश कर रहा हूं।

add_action( 'save_post', 'ep_eventposts_check_meta', 99, 2 );
function ep_eventposts_check_meta( $post_id, $post ) {
//check that metadata is complete when a post is published
//print_r($_POST);

if ( $_POST['post_status'] == 'publish' ) {

    $custom = get_post_custom($post_id);

    //make sure both dates are filled
    if ( !array_key_exists('_start_timestamp', $custom ) || !array_key_exists('_end_timestamp', $custom )) {
        $post->post_status = 'draft';
        wp_update_post($post);

    }
    //make sure start < end
    elseif ( $custom['_start_timestamp'] > $custom['_end_timestamp'] ) {
        $post->post_status = 'draft';
        wp_update_post($post);
    }
    else {
        return;
    }
}
}

इसके साथ मुख्य मुद्दा एक समस्या है जिसे वास्तव में एक और प्रश्न में वर्णित किया गया था : उपयोग करनाwp_update_post()save_post हुक के भीतर अनंत लूप को ट्रिगर करता है।

EDIT3: मैंने wp_insert_post_dataइसके बजाय हुक करके, इसे करने का एक तरीका निकालाsave_post । एकमात्र समस्या यह है कि अब post_statusवापस आ गया है, लेकिन अब "पोस्ट प्रकाशित" कह रहा एक भ्रामक संदेश दिखाता है ( &message=6रीडायरेक्ट किए गए URL को जोड़कर ), लेकिन स्थिति ड्रॉफ्ट पर सेट है।

add_filter( 'wp_insert_post_data', 'ep_eventposts_check_meta', 99, 2 );
function ep_eventposts_check_meta( $data, $postarr ) {
//check that metadata is complete when a post is published, otherwise revert to draft
if ( $data['post_type'] != 'event' ) {
    return $data;
}
if ( $postarr['post_status'] == 'publish' ) {
    $custom = get_post_custom($postarr['ID']);

    //make sure both dates are filled
    if ( !array_key_exists('_start_timestamp', $custom ) || !array_key_exists('_end_timestamp', $custom )) {
        $data['post_status'] = 'draft';
    }
    //make sure start < end
    elseif ( $custom['_start_timestamp'] > $custom['_end_timestamp'] ) {
        $data['post_status'] = 'draft';
    }
    //everything fine!
    else {
        return $data;
    }
}

return $data;
}

जवाबों:


16

जैसा कि m0r7if3r ने बताया, हुक का उपयोग करके किसी पोस्ट को प्रकाशित होने से रोकने का कोई तरीका नहीं है save_post, क्योंकि जब तक हुक को निकाल दिया जाता है, तब तक पोस्ट पहले से ही सहेजा जाता है। हालांकि, निम्नलिखित, आपको wp_insert_post_dataबिना लूप का उपयोग किए बिना और बिना स्थिति को वापस करने की अनुमति देगा ।

निम्नलिखित का परीक्षण नहीं किया गया है, लेकिन काम करना चाहिए।

<?php
add_action('save_post', 'my_save_post');
function my_save_post($post_id) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
         return;

    if ( !isset( $_POST['ep_eventposts_nonce'] ) )
         return;

    if ( !wp_verify_nonce( $_POST['ep_eventposts_nonce'], plugin_basename( __FILE__ ) ) )
         return;

    // Is the user allowed to edit the post or page?
     if ( !current_user_can( 'edit_post', $post->ID ) )
         return;

   // Now perform checks to validate your data. 
   // Note custom fields (different from data in custom metaboxes!) 
   // will already have been saved.
    $prevent_publish= false;//Set to true if data was invalid.
    if ($prevent_publish) {
        // unhook this function to prevent indefinite loop
        remove_action('save_post', 'my_save_post');

        // update the post to change post status
        wp_update_post(array('ID' => $post_id, 'post_status' => 'draft'));

        // re-hook this function again
        add_action('save_post', 'my_save_post');
    }
}
?>

मैंने जाँच नहीं की है, लेकिन कोड को देखकर, प्रतिक्रिया संदेश गलत संदेश प्रदर्शित करेगा जो पोस्ट प्रकाशित किया गया था। इसका कारण यह है कि वर्डप्रेस हमें एक url पर पुनर्निर्देशित करता है जहां messageचर अब गलत है।

इसे बदलने के लिए, हम redirect_post_locationफ़िल्टर का उपयोग कर सकते हैं :

add_filter('redirect_post_location','my_redirect_location',10,2);
function my_redirect_location($location,$post_id){
    //If post was published...
    if (isset($_POST['publish'])){
        //obtain current post status
        $status = get_post_status( $post_id );

        //The post was 'published', but if it is still a draft, display draft message (10).
        if($status=='draft')
            $location = add_query_arg('message', 10, $location);
    }

    return $location;
}

उपरोक्त पुनर्निर्देशित फ़िल्टर को संक्षेप में प्रस्तुत करने के लिए: यदि कोई पोस्ट प्रकाशित होने के लिए सेट है, लेकिन अभी भी एक मसौदा है तो हम तदनुसार संदेश को बदल देते हैं (जो है message=10)। फिर, यह अप्रयुक्त है, लेकिन काम करना चाहिए। कोडेक्स का add_query_argसुझाव है कि जब एक चर पहले से ही सेट है, तो फ़ंक्शन इसे बदल देता है (लेकिन जैसा कि मैं कहता हूं, मैंने यह परीक्षण नहीं किया है)।


लापता के अलावा अन्य; आपकी add_query_arg लाइन पर, यह रीडायरेक्ट_पोस्ट_लोकेशन फ़िल्टर ट्रिक वही है जिसकी मुझे ज़रूरत थी। धन्यवाद!
MadtownLems 19

@MadtownLems तय :)
स्टीफन हैरिस

9

ठीक है, यह अंत में है कि मैंने इसे कैसे समाप्त किया: एक PHP फ़ंक्शन को एक अजाक्स कॉल, जो इस उत्तर से प्रेरित, एक प्रकार का चेक करता है, और एक प्रश्न से एक चतुर टिप का उपयोग करके मैंने StackOverflow पर पूछा । महत्वपूर्ण रूप से, मैं यह सुनिश्चित करता हूं कि केवल जब हम प्रकाशन को प्रकाशित करना चाहते हैं तब किया जाता है, ताकि चेक के बिना एक ड्राफ्ट को हमेशा बचाया जा सके। यह वास्तव में पोस्ट के प्रकाशन को रोकने के लिए आसान समाधान होने के कारण समाप्त हो गया । यह किसी और की मदद कर सकता है, इसलिए मैंने इसे यहाँ लिखा है।

सबसे पहले, आवश्यक जावास्क्रिप्ट जोड़ें:

//AJAX to validate event before publishing
//adapted from /wordpress/15546/dont-publish-custom-post-type-post-if-a-meta-data-field-isnt-valid
add_action('admin_enqueue_scripts-post.php', 'ep_load_jquery_js');   
add_action('admin_enqueue_scripts-post-new.php', 'ep_load_jquery_js');   
function ep_load_jquery_js(){
global $post;
if ( $post->post_type == 'event' ) {
    wp_enqueue_script('jquery');
}
}

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 == 'event' ){
    ?>
    <script language="javascript" type="text/javascript">
        jQuery(document).ready(function() {
            jQuery('#publish').click(function() {
                if(jQuery(this).data("valid")) {
                    return true;
                }
                var form_data = jQuery('#post').serializeArray();
                var data = {
                    action: 'ep_pre_submit_validation',
                    security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
                    form_data: jQuery.param(form_data),
                };
                jQuery.post(ajaxurl, data, function(response) {
                    if (response.indexOf('true') > -1 || response == true) {
                        jQuery("#post").data("valid", true).submit();
                    } else {
                        alert("Error: " + response);
                        jQuery("#post").data("valid", false);

                    }
                    //hide loading icon, return Publish button to normal
                    jQuery('#ajax-loading').hide();
                    jQuery('#publish').removeClass('button-primary-disabled');
                    jQuery('#save-post').removeClass('button-disabled');
                });
                return false;
            });
        });
    </script>
    <?php
}
}

फिर, वह फ़ंक्शन जो चेकिंग को हैंडल करता है:

add_action('wp_ajax_ep_pre_submit_validation', 'ep_pre_submit_validation');
function ep_pre_submit_validation() {
//simple Security check
check_ajax_referer( 'pre_publish_validation', 'security' );

//convert the string of data received to an array
//from /wordpress//a/26536/10406
parse_str( $_POST['form_data'], $vars );

//check that are actually trying to publish a post
if ( $vars['post_status'] == 'publish' || 
    (isset( $vars['original_publish'] ) && 
     in_array( $vars['original_publish'], array('Publish', 'Schedule', 'Update') ) ) ) {
    if ( empty( $vars['_start_date'] ) || empty( $vars['_end_date'] ) ) {
        _e('Both Start and End date need to be filled');
        die();
    }
    //make sure start < end
    elseif ( $vars['_start_date'] > $vars['_end_date'] ) {
        _e('Start date cannot be after End date');
        die();
    }
    //check time is also inputted in case of a non-all-day event
    elseif ( !isset($vars['_all_day'] ) ) {
        if ( empty($vars['_start_time'] ) || empty( $vars['_end_time'] ) ) {
            _e('Both Start time and End time need to be specified if the event is not an all-day event');
            die();              
        }
        elseif ( strtotime( $vars['_start_date']. ' ' .$vars['_start_time'] ) > strtotime( $vars['_end_date']. ' ' .$vars['_end_time'] ) ) {
            _e('Start date/time cannot be after End date/time');
            die();
        }
    }
}

//everything ok, allow submission
echo 'true';
die();
}

यह फ़ंक्शन वापस आता है trueयदि सब कुछ ठीक है, और सामान्य चैनल द्वारा पोस्ट प्रकाशित करने के लिए फ़ॉर्म सबमिट करता है। अन्यथा, फ़ंक्शन एक त्रुटि संदेश देता है जिसे एक के रूप में दिखाया गया है alert(), और फॉर्म सबमिट नहीं किया गया है।


मैंने उसी दृष्टिकोण का पालन किया है और सत्यापन कार्य के सही होने पर "प्रकाशित करें" के बजाय पोस्ट को "ड्राफ्ट" के रूप में सहेजा जा रहा है। अजाक्स कॉल के दौरान निश्चित नहीं है कि इसे कैसे ठीक किया जाए? <br/> साथ ही टेक्स्टएरिया फ़ील्ड (उदा। पोस्ट_ कॉन्टेंट, कोई अन्य टेक्स्ट क्षेत्र कस्टम फ़ील्ड) के लिए डेटा नहीं मिल रहा है?
महमदुर

1
मैंने इस समाधान को थोड़ा अलग तरीके से लागू किया है: सबसे पहले मैंने सफलता के मामले में जावास्क्रिप्ट में नीचे दिए गए कोड का उपयोग किया है: delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish postबहुत धन्यवाद।
महमूद

3

मुझे लगता है कि इसके बारे में जाने का सबसे अच्छा तरीका यह है कि अगर यह होता है तो इसे बदलने से स्थिति बदलने की स्थिति में नहीं आना चाहिए। उदाहरण के लिए: आप हुक save_post, वास्तव में उच्च प्राथमिकता के साथ (ताकि हुक बहुत देर से फायर करे, अर्थात् जब आप अपना मेटा इंसर्ट करेंगे), तो post_statusउस पोस्ट की जाँच करें जिसे अभी बचाया गया है, और इसे लंबित (या ड्राफ्ट या) में अपडेट करें जो भी हो) अगर यह आपके मानदंडों को पूरा नहीं करता है।

एक वैकल्पिक रणनीति wp_insert_post_dataसीधे पोस्ट_स्टैटस को सेट करने के लिए हुक करना होगा । इस पद्धति का नुकसान, जहाँ तक मेरा सवाल है, कि आपने अभी तक डेटाबेस में पोस्टमेट को सम्मिलित नहीं किया है, इसलिए आपको इसकी जाँच करने के लिए इसे संसाधित करना होगा, आदि। फिर इसे सम्मिलित करने के लिए फिर से प्रक्रिया करें यह डेटाबेस में ... जो बहुत अधिक ओवरहेड बन सकता है, या तो प्रदर्शन में या कोड में।


मैं वर्तमान save_postमें मेटाबोक्स से मेटा फ़ील्ड्स को बचाने के लिए प्राथमिकता 1 के साथ हुक कर रहा हूं ; फिर आप जो प्रस्ताव कर रहे हैं save_post, वह प्राथमिकता के साथ एक दूसरा हुक है , कहते हैं, ९९? क्या इससे अखंडता सुनिश्चित होगी? क्या होगा अगर किसी कारण से पहले हुक में आग लग जाती है, मेटाडेटा डाला जाता है और पोस्ट प्रकाशित होता है, लेकिन दूसरा हुक नहीं होता है, तो आप अमान्य फ़ील्ड के साथ समाप्त होते हैं?
englebip

मैं ऐसी स्थिति के बारे में नहीं सोच सकता जहां पहला हुक आग लगाएगा लेकिन दूसरा नहीं ... आप किस तरह का परिदृश्य सोच रहे हैं जो इसका कारण बन सकता है? यदि आप इसके बारे में चिंतित हैं, तो आप पोस्ट मेटा सम्मिलित कर सकते हैं, पोस्ट मेटा की जांच कर सकते हैं, और फिर post_statusयदि आप चाहें तो किसी एक कॉल में एक हुक से चल रहे सभी फ़ंक्शन को अपडेट कर सकते हैं।
mor7ifer

मैंने अपने कोड को अपने प्रश्न के संपादन के रूप में पोस्ट किया; मैंने एक दूसरे हुक का उपयोग करने की कोशिश की, save_postलेकिन यह एक अनंत लूप को ट्रिगर करता है।
19

आपका मुद्दा यह है कि आपको निर्मित पोस्ट की जाँच करनी चाहिए। तो if( get_post_status( $post_id ) == 'publish' )क्या आप उपयोग करना चाहते हैं, क्योंकि आप डेटा को फिर से परिभाषित कर रहे हैं $wpdb->posts, न कि डेटा को $_POST[]
mor7ifer 21

0

सर्वोत्तम विधि JAVASCRIPT हो सकती है:

<script type="text/javascript">
var field_id =  "My_field_div__ID";    // <----------------- CHANGE THIS

var SubmitButton = document.getElementById("save-post") || false;
var PublishButton = document.getElementById("publish")  || false; 
if (SubmitButton)   {SubmitButton.addEventListener("click", SubmCLICKED, false);}
if (PublishButton)  {PublishButton.addEventListener("click", SubmCLICKED, false);}
function SubmCLICKED(e){   
  var passed= false;
  if(!document.getElementById(field_id)) { alert("I cant find that field ID !!"); }
  else {
      var Enabled_Disabled= document.getElementById(field_id).value;
      if (Enabled_Disabled == "" ) { alert("Field is Empty");   }  else{passed=true;}
  }
  if (!passed) { e.preventDefault();  return false;  }
}
</script>

-1

क्षमा करें, मैं आपको सीधे उत्तर नहीं दे सकता, लेकिन मुझे याद है कि कुछ ऐसा ही हाल ही में किया गया था, मुझे अभी ठीक से याद नहीं है। मुझे लगता है कि मैंने शायद इसके बारे में ऐसा ही किया है - कुछ ऐसा है जो मेरे लिए एक डिफ़ॉल्ट मूल्य था और अगर व्यक्ति ने इसे नहीं बदला था तो मैंने इसे एक स्टेटमेंट में उठाया था -> if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }माफ करना, यह सीधे उत्तर नहीं है, लेकिन आशा है कि यह थोड़ा मदद करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.