J'ai un type de publication personnalisé Event
qui contient des champs personnalisés de date / heure de début et de fin (sous forme de métaboxes dans l'écran d'édition de publication).
Je voudrais m'assurer qu'un événement ne peut pas être publié (ou programmé) sans que les dates soient remplies, car cela entraînera des problèmes avec les modèles affichant les données de l'événement (en plus du fait que c'est une condition nécessaire!). Cependant, je souhaiterais pouvoir disposer de projets d'événements qui ne contiennent pas de date valide pendant leur préparation.
Je pensais accrocher save_post
pour faire la vérification, mais comment puis-je empêcher le changement de statut de se produire?
EDIT1: Ceci est le crochet que j'utilise maintenant pour enregistrer le 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: et c'est ce que j'essaie d'utiliser pour vérifier les données de publication après l'enregistrement dans la base de données.
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;
}
}
}
Le principal problème est un problème qui a été décrit dans une autre question : l'utilisation wp_update_post()
dans un save_post
crochet déclenche une boucle infinie.
EDIT3: J'ai trouvé un moyen de le faire, en accrochant wp_insert_post_data
au lieu de save_post
. Le seul problème est que maintenant le post_status
est inversé, mais maintenant un message trompeur disant "Publication publiée" apparaît (en ajoutant &message=6
à l'URL redirigée), mais le statut est défini sur Brouillon.
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;
}
la source
OK, c'est finalement ainsi que j'ai fini par le faire: un appel Ajax à une fonction PHP qui vérifie, en quelque sorte inspiré par cette réponse et en utilisant un astuce intelligent d'une question que j'ai posée sur StackOverflow . Surtout, je m'assure que ce n'est que lorsque nous voulons publier que la vérification est effectuée, afin qu'un brouillon puisse toujours être enregistré sans la vérification. Cela a fini par être la solution la plus simple pour empêcher la publication du message. Cela pourrait aider quelqu'un d'autre, alors je l'ai écrit ici.
Tout d'abord, ajoutez le Javascript nécessaire:
Ensuite, la fonction qui gère la vérification:
Cette fonction retourne
true
si tout va bien et soumet le formulaire pour publier le message par le canal normal. Sinon, la fonction renvoie un message d'erreur qui s'affiche sousalert()
la forme d' un et le formulaire n'est pas soumis.la source
delayed_autosave(); //get data from textarea/tinymce field jQuery('#publish').data("valid", true).trigger('click'); //publish post
Merci beaucoup.Je pense que la meilleure façon de procéder est de ne pas empêcher le changement de statut de se produire autant que de le RÉVERVER s'il le fait. Par exemple: vous accrochez
save_post
, avec une priorité très élevée (pour que le crochet se déclenche très tard, c'est-à-dire après avoir fait votre méta-insert), puis vérifiezpost_status
le message qui vient d'être enregistré, et mettez-le à jour en attente (ou brouillon ou peu importe) s'il ne répond pas à vos critères.Une autre stratégie consisterait à accrocher
wp_insert_post_data
pour définir directement le post_status. L'inconvénient de cette méthode, en ce qui me concerne, est que vous n'aurez pas encore inséré le postmeta dans la base de données, vous devrez donc le traiter, etc. en place pour faire vos vérifications, puis le traiter à nouveau pour insérer il dans la base de données ... qui pourrait devenir beaucoup de frais généraux, soit en performances ou en code.la source
save_post
à la priorité 1 pour enregistrer les champs méta des métaboxes; ce que vous proposez alors, c'est d'avoir un deuxième crochetsave_post
avec la priorité, disons, 99? Cela garantirait-il l'intégrité? Que se passe-t-il si, pour une raison quelconque, le premier crochet se déclenche, les métadonnées sont insérées et la publication publiée, mais pas le deuxième crochet, vous vous retrouvez donc avec des champs invalides?post_status
tout en un à partir d'un seul appel vers un hook si vous préférez.save_post
déclencher une boucle infinie.if( get_post_status( $post_id ) == 'publish' )
ce que vous voulez utiliser, car vous redéfinirez les données dans$wpdb->posts
, pas les données dans$_POST[]
.La meilleure méthode peut être JAVASCRIPT:
la source
Désolé, je ne peux pas vous donner une réponse directe, mais je me souviens d'avoir fait quelque chose de similaire très récemment, je ne peux pas me rappeler exactement comment. Je pense que je l'ai peut-être fait sur le chemin - quelque chose comme si je l'avais comme valeur par défaut et si la personne ne l'avait pas changé, je l'ai ramassé dans une instruction if donc ->
if(category==default category) {echo "You didn't pick a category!"; return them to the post creation page; }
désolé, ce n'est pas une réponse directe mais j'espère ça aide un peu.la source