Tengo un tipo de publicación personalizada Event
que contiene campos personalizados de fecha / hora de inicio y finalización (como metaboxes en la pantalla de edición de publicaciones).
Me gustaría asegurarme de que un Evento no se pueda publicar (o programar) sin que se completen las fechas, ya que eso causará problemas con las plantillas que muestran los datos del Evento (¡además del hecho de que es un requisito necesario!). Sin embargo, me gustaría poder tener eventos de borrador que no contengan una fecha válida mientras están en preparación.
Estaba pensando en conectarme save_post
para hacer la verificación, pero ¿cómo puedo evitar que ocurra el cambio de estado?
EDITAR1: Este es el gancho que estoy usando ahora para guardar el 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: y esto es lo que estoy tratando de usar para verificar los datos de la publicación después de guardarlos en la base de datos.
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;
}
}
}
El problema principal con esto es un problema que en realidad se describió en otra pregunta : el uso wp_update_post()
dentro de un save_post
gancho desencadena un bucle infinito.
EDITAR3: pensé en una forma de hacerlo, enganchando en wp_insert_post_data
lugar de hacerlo save_post
. El único problema es que ahora post_status
se revierte, pero ahora aparece un mensaje engañoso que dice "Publicación publicada" (agregando &message=6
a la URL redirigida), pero el estado se establece en Borrador.
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;
}
fuente
Bien, finalmente así es como terminé haciéndolo: una llamada de Ajax a una función PHP que realiza la comprobación, inspirada en esta respuesta y usando un consejo inteligente de una pregunta que hice en StackOverflow . Es importante destacar que solo me aseguro de que cuando deseamos publicar la verificación se realice, de modo que un borrador siempre se pueda guardar sin la verificación. Esto terminó siendo la solución más fácil para prevenir la publicación de la publicación. Podría ayudar a alguien más, así que lo escribí aquí.
Primero, agregue el Javascript necesario:
Luego, la función que maneja la comprobación:
Esta función se devuelve
true
si todo está bien y envía el formulario para publicar la publicación por el canal normal. De lo contrario, la función devuelve un mensaje de error que se muestra como unalert()
, y el formulario no se envía.fuente
delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish post
muchas gracias.Creo que la mejor manera de hacerlo es NO EVITAR que el cambio de estado se produzca, sino REVERTIRLO si es así. Por ejemplo: engancha
save_post
, con una prioridad realmente alta (para que el enganche se dispare muy tarde, es decir, después de hacer su meta inserción), luego verifiquepost_status
la publicación que acaba de guardar y actualícela como pendiente (o borrador o lo que sea) si no cumple con sus criterios.Una estrategia alternativa sería enganchar
wp_insert_post_data
para establecer el post_status directamente. La desventaja de este método, en lo que a mí respecta, es que todavía no habrá insertado el postmeta en la base de datos, por lo que tendrá que procesarlo, etc. para realizar sus comprobaciones, luego procesarlo nuevamente para insertarlo. en la base de datos ... lo que podría convertirse en una sobrecarga, ya sea en rendimiento o en código.fuente
save_post
con prioridad 1 para guardar los metacampos de los metaboxes; entonces lo que está proponiendo es tener un segundo gancho parasave_post
con prioridad, digamos, 99? ¿Esto garantizaría la integridad? ¿Qué sucede si por alguna razón se dispara el primer gancho, se insertan los metadatos y se publica la publicación, pero el segundo gancho no, por lo que terminas con campos no válidos?post_status
todo en uno que se ejecuta de una sola llamada a un enlace si lo prefiere.save_post
pero eso desencadena un bucle infinito.if( get_post_status( $post_id ) == 'publish' )
es lo que desea utilizar, ya que redefinirá los datos$wpdb->posts
, no los datos$_POST[]
.El mejor método puede ser JAVASCRIPT:
fuente
Lo siento, no puedo darte una respuesta directa, pero recuerdo haber hecho algo similar muy recientemente. No puedo recordar exactamente cómo. Creo que tal vez lo hice de manera aproximada, algo así como que tenía un valor predeterminado y si la persona no lo había cambiado, lo recogí en una declaración if, así que>
if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }
perdón, esta no es una respuesta directa, pero espero Ayuda un poco.fuente