не публиковать сообщение post post post, если поле метаданных недействительно

У меня есть пользовательский тип сообщения (CPT), называемый event . У меня есть мета-поле для типа с несколькими полями. Я хотел бы подтвердить некоторые поля перед публикацией события. Например, если дата события не указана, я хотел бы отобразить информативное сообщение об ошибке, сохранить событие для будущего редактирования, но запретить публикацию этого события. Является ли статус «ожидающий» для сообщения CPT без всякой необходимой информации правильным способом его лечения?

Какова наилучшая практика для проверки правильности полей CPT и предотвращения публикации публикации, но сохраните ее для будущего редактирования.

Большое спасибо, Даша

Вы можете остановить запись, чтобы сохранить все вместе с небольшими хаками JQuery и проверить поля перед сохранением на стороне клиента или сервера с помощью ajax:

сначала мы добавляем наш JavaScript, чтобы захватить событие submit / publish и использовать его для отправки нашей собственной функции ajax до фактического представления:

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

то мы создаем функцию для фактической проверки:

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

вы всегда можете немного изменить его, чтобы выполнить проверку только для вашего типа сообщения, добавив условную проверку в функцию my_publish_admin_hook для вашего типа сообщения и для проверки на стороне клиента, но я предпочитаю на стороне сервера.

Для этого метода есть два шага: во-первых, функция сохранения ваших пользовательских данных поля метабокса (привязана к save_post), а во-вторых, функция для чтения новой записи post_meta (которую вы только что сохранили), ее проверки и изменения результата сохраняя при необходимости (также подключен к save_post, но после первого). Функция валидатора, если проверка не выполняется, фактически изменяет post_status на «ожидающий», эффективно предотвращая публикацию публикации.

Поскольку функция save_post вызывается много, каждая функция имеет проверки только для выполнения, когда пользователь означает публикацию, и только для вашего пользовательского типа сообщения (mycustomtype).

Я также обычно добавляю некоторые пользовательские уведомления, чтобы помочь пользователю узнать, почему их публикация не публиковалась, но те, которые были немного сложнее включить сюда …

Я не тестировал этот точный код, но это упрощенная версия того, что я сделал в крупномасштабных настраиваемых настройках почтового типа.

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

Для нескольких полей метабокса просто добавьте больше маркеров завершения и получите больше post_meta и сделайте больше тестов.

вам нужно проверить / проверить значение метаданных на ajax, т.е. когда пользователь нажал кнопку «Опубликовать / обновить». Здесь я проверяю продукт woocommerce, имеющий мета-поле «product_number» для пустого значения.

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

После этого добавьте функцию обработчика 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(); } 

Просто хотел добавить, что для чтения пост-переменных, используя решение Bainternet, вам придется разбирать строку в $_POST['form_data'] с parse_str функции PHP parse_str (просто для того, чтобы сэкономить время исследований).

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

Затем вы можете получить доступ к каждой переменной только с помощью $varname . Например, если у вас есть мета-поле под названием «my_meta», вы получите доступ к нему следующим образом:

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