Metoda składa się z dwóch etapów: po pierwsze, funkcja zapisywania niestandardowych danych pola metaboksu (podpięta do save_post), a po drugie, funkcja odczytywania nowego post_meta (właśnie zapisanego), sprawdzania go i modyfikowania wyniku zapisywanie w razie potrzeby (również podpięte do save_post, ale po pierwszym). Funkcja sprawdzania poprawności, jeśli sprawdzanie poprawności się nie powiedzie, faktycznie zmienia stan post_status z powrotem na „oczekujący”, skutecznie zapobiegając opublikowaniu posta.
Ponieważ funkcja save_post jest często wywoływana, każda funkcja musi sprawdzać, czy jest wykonywana tylko wtedy, gdy użytkownik chce opublikować, i tylko w przypadku niestandardowego typu postu (typ niestandardowy).
Zazwyczaj dodaję też niestandardowe komunikaty z powiadomieniami, aby pomóc użytkownikowi dowiedzieć się, dlaczego jego post nie został opublikowany, ale dodanie ich tutaj jest nieco skomplikowane ...
Nie testowałem dokładnie tego kodu, ale jest to uproszczona wersja tego, co zrobiłem w niestandardowych konfiguracjach typu post na dużą skalę.
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);' ) );
}
}
}
W przypadku wielu pól metaboksu wystarczy dodać więcej znaczników ukończenia i pobrać więcej post_meta i wykonać więcej testów.