Eu tenho um tipo de postagem personalizado Event
que contém os campos personalizados de data / hora inicial e final (como metaboxes na tela de edição de postagem).
Gostaria de garantir que um Evento não possa ser publicado (ou agendado) sem que as datas sejam preenchidas, pois isso causará problemas nos modelos que exibem os dados do Evento (além do fato de que é um requisito necessário!). No entanto, eu gostaria de poder ter eventos de rascunho que não contenham uma data válida enquanto estão em preparação.
Eu estava pensando em ligar save_post
para fazer a verificação, mas como posso impedir que a alteração de status aconteça?
EDIT1: Este é o gancho que estou usando agora para salvar o 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 );
EDIT2: e é isso que estou tentando usar para verificar os dados da postagem depois de salvar no banco de dados.
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;
}
}
}
O principal problema com isso é um problema que foi realmente descrito em outra pergunta : o uso wp_update_post()
dentro de um save_post
gancho aciona um loop infinito.
EDIT3: Eu descobri uma maneira de fazê-lo, conectando em wp_insert_post_data
vez de save_post
. O único problema é que agora o post_status
item é revertido, mas agora aparece uma mensagem enganosa dizendo "Postagem publicada" (adicionando &message=6
ao URL redirecionado), mas o status está definido como Rascunho.
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;
}
fonte
OK, foi finalmente como eu acabei fazendo isso: uma chamada do Ajax para uma função PHP que faz a verificação, meio que inspirada por esta resposta e usando uma dica inteligente de uma pergunta que fiz no StackOverflow . É importante ressaltar que somente quando queremos publicar a verificação é feita, para que um rascunho possa sempre ser salvo sem a verificação. Essa acabou sendo a solução mais fácil para realmente impedir a publicação do post. Pode ajudar alguém, então eu escrevi aqui.
Primeiro, adicione o Javascript necessário:
Em seguida, a função que lida com a verificação:
Essa função retorna
true
se tudo estiver bem e envia o formulário para publicar a postagem pelo canal normal. Caso contrário, a função retornará uma mensagem de erro exibida como umalert()
e o formulário não será enviado.fonte
delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish post
Muito obrigado.Eu acho que a melhor maneira de fazer isso é não impedir que a mudança de status aconteça tanto quanto revertê-lo, se acontecer. Por exemplo: você conecta
save_post
, com uma prioridade muito alta (para que o gancho seja acionado muito tarde, ou seja, após a inserção meta), verifiquepost_status
a postagem que acabou de ser salva e atualize-a para pendente (ou rascunho ou o que for) se não atender aos seus critérios.Uma estratégia alternativa seria ligar
wp_insert_post_data
para definir o post_status diretamente. A desvantagem desse método, no que me diz respeito, é que você ainda não inseriu o postmeta no banco de dados; portanto, você terá que processá-lo, etc. no lugar para fazer suas verificações, depois processá-lo novamente para inserir no banco de dados ... o que pode se tornar um monte de sobrecarga, no desempenho ou no código.fonte
save_post
a prioridade 1 para salvar os meta campos dos metaboxes; o que você está propondo é ter um segundo ganchosave_post
com prioridade, digamos, 99? Isso garantiria integridade? E se, por algum motivo, o primeiro gancho for acionado, os metadados forem inseridos e a postagem publicada, mas o segundo gancho não, então você terá campos inválidos?post_status
função tudo em uma executando uma única chamada para um gancho, se preferir.save_post
mas que desencadeia um loop infinito.if( get_post_status( $post_id ) == 'publish' )
é isso que você quer usar, desde que você estará redefinindo os dados no$wpdb->posts
, não os dados em$_POST[]
.O melhor método pode ser JAVASCRIPT:
fonte
Desculpe, não posso lhe dar uma resposta direta, mas lembro-me de fazer algo semelhante muito recentemente. Não consigo me lembrar exatamente como. Eu acho que talvez tenha feito isso de alguma maneira - algo como se eu tivesse um valor padrão e se a pessoa não o tivesse alterado, peguei isso em uma declaração if ->
if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }
desculpe, isso não é uma resposta direta, mas espero isso ajuda um pouco.fonte