Hay dos pasos en el método: primero, una función para guardar tus datos de campo metabox personalizados (enganchado a save_post), y segundo, una función para leer esa nueva post_meta (que acabas de guardar), validarla y modificarla el resultado de guardar como sea necesario (también enganchado a save_post, pero después del primero). La función del validador, si la validación falla, en realidad cambia el post_status de nuevo a "pendiente", lo que impide efectivamente que se publique la publicación.
Como la función save_post se llama mucho, cada función tiene controles que solo se ejecutan cuando el usuario quiere publicar, y solo para su tipo de publicación personalizada (mycustomtype).
Por lo general, también agrego algunos mensajes de aviso personalizados para ayudar al usuario a saber por qué no se publicó su publicación, pero es más complicado incluirlos aquí ...
No he probado este código exacto, pero es una versión simplificada de lo que he hecho en configuraciones de tipo de publicaciones personalizadas a gran escala.
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);' ) );
}
}
}
Para varios campos de metabox, solo agregue más marcadores de finalización y recupere más post_meta y realice más pruebas ..