Mam niestandardowy typ postu Event
zawierający początkowe i końcowe pola niestandardowej daty / godziny (jako metaboksy na ekranie edycji postów).
Chciałbym się upewnić, że wydarzenie nie może zostać opublikowane (lub zaplanowane) bez wypełnienia dat, ponieważ spowoduje to problemy z szablonami wyświetlającymi dane zdarzenia (poza tym, że jest to konieczny wymóg!). Chciałbym jednak mieć możliwość organizowania wydarzeń Draft, które nie zawierają prawidłowej daty podczas ich przygotowywania.
Myślałem o save_post
sprawdzeniu, ale jak mogę zapobiec zmianie statusu?
EDYCJA 1: To jest hak, którego używam teraz do zapisania 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 );
EDYCJA 2: i właśnie tego próbuję użyć do sprawdzenia danych postu po zapisaniu w bazie danych.
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;
}
}
}
Głównym problemem jest problem, który został opisany w innym pytaniu : użycie wp_update_post()
w obrębie save_post
haka uruchamia nieskończoną pętlę.
EDYCJA 3: Wymyśliłem sposób na zrobienie tego, zaczepiając wp_insert_post_data
zamiast save_post
. Jedyny problem polega na tym, że teraz post_status
jest on cofany, ale teraz pojawia się mylący komunikat „Opublikuj opublikowany” (poprzez dodanie &message=6
do przekierowanego adresu URL), ale status jest ustawiony na Wersja robocza.
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;
}
źródło
OK, tak w końcu to zrobiłem: wywołanie Ajax do funkcji PHP, która wykonuje sprawdzanie, niejako inspirowane tą odpowiedzią i używając sprytnej wskazówki z pytania, które zadałem na StackOverflow . Co ważne, upewniam się, że tylko wtedy, gdy chcemy opublikować sprawdzanie jest zakończone, aby Szkic można zawsze zapisać bez sprawdzania. Skończyło się to łatwiejszym rozwiązaniem, które faktycznie uniemożliwi publikację postu. To może pomóc komuś innemu, więc napisałem to tutaj.
Najpierw dodaj niezbędny Javascript:
Następnie funkcja, która obsługuje sprawdzanie:
Ta funkcja zwraca,
true
jeśli wszystko jest w porządku, i przesyła formularz do opublikowania postu normalnym kanałem. W przeciwnym razie funkcja zwraca komunikat o błędzie wyświetlany jakoalert()
i formularz nie zostanie przesłany.źródło
delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish post
dzięki.Myślę, że najlepszym sposobem na to nie jest ZAPOBIEGANIE zmianie stanu, a raczej ZWRÓCENIE go, jeśli tak się stanie. Na przykład: Przechwytujesz
save_post
z naprawdę wysokim priorytetem (aby hak zadziałał bardzo późno, a mianowicie po wykonaniu wstawienia meta), następnie sprawdźpost_status
wpis, który właśnie został zapisany, i zaktualizuj go do oczekującego (lub wersji roboczej lub cokolwiek), jeśli nie spełnia twoich kryteriów.Alternatywną strategią byłoby zaczepienie w
wp_insert_post_data
celu ustawienia bezpośrednio post_status. Moim zdaniem wadą tej metody jest to, że nie wstawiłeś jeszcze postmeta do bazy danych, więc będziesz musiał ją przetworzyć itp. W celu wykonania kontroli, a następnie przetworzyć ją ponownie, aby wstawić w bazie danych ... co może stać się dużym obciążeniem, zarówno pod względem wydajności, jak i kodu.źródło
save_post
do priorytetu 1, aby zapisać pola meta przed metaboxami; to, co proponujesz, to mieć drugi haksave_post
z priorytetem, powiedzmy 99? Czy to zapewni integralność? Co się stanie, jeśli z jakiegoś powodu pierwszy hak zostanie uruchomiony, metadane zostaną wstawione, a post opublikowany, ale drugi hak się nie powiedzie, więc otrzymacie nieprawidłowe pola?post_status
all in one po uruchomieniu pojedynczego połączenia, jeśli chcesz.save_post
ale to wyzwala nieskończoną pętlę.if( get_post_status( $post_id ) == 'publish' )
tego chcesz używać, ponieważ przedefiniujesz dane$wpdb->posts
, a nie dane$_POST[]
.Najlepszą metodą może być JAVASCRIPT:
źródło
Przepraszam, nie mogę dać ci prostej odpowiedzi, ale pamiętam, że ostatnio zrobiłem coś podobnego. Po prostu nie pamiętam dokładnie jak. Myślę, że może zrobiłem to na swój sposób - coś takiego, jakbym miał wartość domyślną, a jeśli osoba tego nie zmieniła, podniosłem to w instrukcji if ->
if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }
przepraszam, to nie jest prosta odpowiedź, ale mam nadzieję to trochę pomaga.źródło