কাস্টম ক্ষেত্রগুলি ভরাট না হলে পোস্ট প্রকাশ হতে বাধা দিন


17

আমার একটি কাস্টম পোস্ট টাইপ Eventরয়েছে যার মধ্যে একটি প্রারম্ভিক এবং শেষের তারিখ / বার কাস্টম ক্ষেত্র রয়েছে (পোস্ট সম্পাদনা পর্দার মেটাবক্স হিসাবে)।

আমি নিশ্চিত করতে চাই যে তারিখগুলি পূরণ না করে কোনও ইভেন্ট প্রকাশিত (বা নির্ধারিত) হতে পারে না, কারণ এটি ইভেন্টের ডেটা প্রদর্শনকারী টেমপ্লেটগুলিতে সমস্যা সৃষ্টি করবে (এটি একটি প্রয়োজনীয় প্রয়োজনীয়তা ছাড়াও!)! তবে আমি খসড়া ইভেন্টগুলি প্রস্তুত করতে সক্ষম হতে চাই যেগুলি প্রস্তুতির সময় কোনও বৈধ তারিখ ধারণ করে না।

আমি save_postচেকিং করতে হুকিংয়ের কথা ভাবছিলাম , তবে আমি কীভাবে স্থিতি পরিবর্তনটি রোধ করতে পারি?

সম্পাদনা 1: পোস্ট_মেটা সংরক্ষণ করার জন্য আমি এখন এটি ব্যবহার করছি h

// 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 );

সম্পাদনা 2: এবং এটিই আমি ডাটাবেজে সংরক্ষণের পরে পোস্ট ডেটা পরীক্ষা করার জন্য ব্যবহার করার চেষ্টা করছি।

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হুকের মধ্যে ব্যবহার করা অসীম লুপকে ট্রিগার করে।

সম্পাদনা 3:wp_insert_post_data পরিবর্তে হুক করে আমি এটি করার একটি উপায় অনুভব করেছি save_post। একমাত্র সমস্যাটি হ'ল এখন post_statusফেরত দেওয়া হয়েছে তবে এখন "পোস্ট প্রকাশিত" বলে একটি বিভ্রান্তিমূলক বার্তা প্রদর্শিত হবে ( &message=6পুনঃনির্দেশিত ইউআরএল যোগ করে) তবে স্থিতিটি খসড়াতে সেট করা আছে।

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

আমি পরীক্ষা করে দেখিনি, তবে কোডটি দেখে, প্রতিক্রিয়া বার্তাটি পোস্টটি প্রকাশিত হয়েছিল এমন ভুল বার্তাটি প্রদর্শন করবে। এটি কারণ ওয়ার্ডপ্রেস আমাদের একটি ইউআরএলে পুনঃনির্দেশ করে যেখানে 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 লাইনে, এই পুনঃনির্দেশ_পোস্ট_লোকেশন ফিল্টার ট্রিকটি হ'ল আমার যা প্রয়োজন। ধন্যবাদ!
ম্যাডটাউনলেমস

@ ম্যাডটাউনলিমস ঠিক করেছেন :)
স্টিফেন হ্যারিস

9

সাজানোর দ্বারা অনুপ্রাণিত একটি পিএইচপি ফাংশন যে পরীক্ষণ করে একটি Ajax কল: ঠিক আছে, এই পরিশেষে আমি এরকম শেষ পর্যন্ত হয় এই উত্তরটি এবং একটি থেকে একটি চালাক ডগা ব্যবহার প্রশ্ন আমি 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হ'ল পোস্ট_স্ট্যাটাসটি সরাসরি সেট করতে হবে । এই পদ্ধতির অসুবিধাগুলি, যতদূর আমি উদ্বিগ্ন তা হ'ল আপনি এখনও ডাটাবেসে পোস্টমেটা sertedোকাতে পারবেন না, সুতরাং আপনার চেকগুলি করার জন্য আপনাকে এটিকে আবার প্রসেস করতে হবে, তারপরে আবার প্রবেশ করার জন্য প্রক্রিয়া করুন এটি ডাটাবেসে ... যা কার্য সম্পাদনে বা কোডে অনেকগুলি ওভারহেড হয়ে উঠতে পারে।


save_postমেটা ক্ষেত্রগুলি মেটাবক্স থেকে বাঁচাতে আমি বর্তমানে অগ্রাধিকার 1 দিয়ে আছি; আপনি যা প্রস্তাব করছেন তারপরে save_postঅগ্রাধিকারের সাথে দ্বিতীয় হুক করা উচিত , বলুন, 99? এটি কি সততা নিশ্চিত করবে? যদি কোনও কারণে প্রথম হুক জ্বলে, মেটাটাটা isোকানো হয় এবং পোস্ট প্রকাশিত হয়, তবে দ্বিতীয় হুকটি না ঘটে, তাই আপনি অবৈধ ক্ষেত্রগুলি দিয়ে শেষ করেন?
englebip

আমি এমন পরিস্থিতির কথা ভাবতে পারি না যেখানে প্রথম হুক জ্বলে উঠবে তবে দ্বিতীয়টি নয় ... আপনি কী ধরনের পরিস্থিতি নিয়ে ভাবছেন যা এর কারণ হতে পারে? যদি আপনি এটি নিয়ে উদ্বিগ্ন হন তবে আপনি পোস্ট মেটা সন্নিবেশ করতে পারেন, পোস্ট মেটাটি পরীক্ষা করতে পারেন এবং তারপরে post_statusআপনি চাইলে একক কল বন্ধ হয়ে একটি ফাংশনে সমস্ত আপডেট করতে পারেন।
মরিফায়ার

আমি আমার প্রশ্নের সম্পাদনা হিসাবে আমার কোড পোস্ট করেছি; আমি দ্বিতীয় হুকটি ব্যবহার করার চেষ্টা করেছি save_postকিন্তু এটি একটি অসীম লুপকে ট্রিগার করে।
englebip

আপনার সমস্যাটি হ'ল আপনার তৈরি করা পোস্টটি পরীক্ষা করা উচিত। সুতরাং if( get_post_status( $post_id ) == 'publish' ), আপনি যা ব্যবহার করা আপনার ডেটা redefining করা হবে না যেহেতু চাই $wpdb->postsনা ডেটা $_POST[]
মরিফায়ার

0

সেরা পদ্ধতি জাভাস্ক্রিপ্ট হতে পারে:

<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; }দুঃখিত এটি কোনও সোজা উত্তর নয় তবে আশা এটি কিছুটা সাহায্য করে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.