У меня есть пользовательский тип сообщения, 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 );
РЕДАКТИРОВАТЬ 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
ловушке запускает бесконечный цикл.
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;
}
источник
Итак, наконец-то я так и сделал: Ajax-вызов функции PHP, которая выполняет проверку, в некотором роде вдохновленный этим ответом и использующий умный совет из вопроса, который я задал в StackOverflow . Важно отметить, что проверка выполняется только тогда, когда мы хотим опубликовать, чтобы черновик всегда можно было сохранить без проверки. В конечном итоге это стало более простым решением для предотвращения публикации поста. Это может помочь кому-то еще, поэтому я написал это здесь.
Сначала добавьте необходимый Javascript:
Затем функция, которая обрабатывает проверку:
Эта функция возвращает,
true
если все в порядке, и отправляет форму для публикации сообщения по обычному каналу. В противном случае функция возвращает сообщение об ошибке, которое отображается какalert()
, и форма не отправляется.источник
delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish post
Большое спасибо.Я думаю, что лучший способ сделать это - не ПРЕДОТВРАТИТЬ изменение статуса от того, чтобы оно произошло так сильно, как ПРОЧИТАТЬ его, если оно произойдет. Например: вы перехватываете
save_post
с действительно высоким приоритетом (так что перехват будет срабатывать очень поздно, а именно после того, как вы сделаете вашу мета-вставку), затем проверяетеpost_status
только что сохраненный пост и обновляете его до ожидающего (или черновика или что угодно) если это не соответствует вашим критериям.Альтернативная стратегия заключается
wp_insert_post_data
в том, чтобы напрямую установить post_status. На мой взгляд, недостатком этого метода является то, что вы еще не вставили postmeta в базу данных, поэтому вам придется обрабатывать его и т. Д. Для проверки, а затем снова обрабатывать, чтобы вставить это в базу данных ... что может привести к большим накладным расходам, ни в производительности, ни в коде.источник
save_post
приоритет 1, чтобы сохранить мета-поля из метабоксов; то, что вы предлагаете, это иметь второй крюкsave_post
с приоритетом, скажем, 99? Будет ли это гарантировать целостность? Что если по какой-то причине сработает первый хук, метаданные будут вставлены, а публикация опубликована, а второй хук - нет, так что вы получите недопустимые поля?post_status
функцию « все в одной», запустив один вызов, если хотите.save_post
но это вызывает бесконечный цикл.if( get_post_status( $post_id ) == 'publish' )
, что вы хотите использовать, так как вы будете переопределять данные$wpdb->posts
, а не данные$_POST[]
.Лучший метод может быть JAVASCRIPT:
источник
Извините, я не могу дать вам прямой ответ, но я помню, что делал нечто подобное совсем недавно, я просто не могу вспомнить, как именно. Я думаю, что я, возможно, сделал это примерно так - как-то так, что у меня было значение по умолчанию, и если человек не изменил его, я поднял это в утверждении if, так что ->
if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }
извините, это не прямой ответ, но надежда это немного помогает.источник