Une fiche « bien à vendre » sans la moindre photo ne sert à rien : elle décourage le visiteur avant même qu’il ne lise la description. Pourtant, dans une agence où plusieurs agents saisissent leurs mandats directement depuis le terrain, l’oubli arrive régulièrement, surtout en fin de journée ou depuis un mobile.
La tentation est de rappeler la règle par mail ou par affichage dans l’intranet. Cela fonctionne deux semaines, puis l’oubli revient. La solution la plus fiable reste un contrôle côté serveur, exécuté au moment précis où l’annonce quitte l’état brouillon pour devenir publique.
Pourquoi la validation à la saisie ne suffit pas
Beaucoup de développeurs cherchent d’abord à rendre le champ image obligatoire dans le formulaire de saisie, via JavaScript ou une contrainte du plugin de champs personnalisés. C’est utile pour l’ergonomie, mais totalement inefficace contre un enregistrement automatique, un import, ou un agent qui contourne le formulaire pour aller directement dans l’administration WordPress.
Le seul point de passage obligé, quel que soit le chemin emprunté par l’utilisateur, c’est l’enregistrement en base avec un statut publish. C’est donc là qu’il faut intercepter.
Le hook à utiliser : wp_insert_post_data

Le filtre wp_insert_post_data s’exécute juste avant l’écriture en base de données et permet de modifier ou de refuser silencieusement le changement de statut. Contrairement à save_post, il intervient avant l’enregistrement, ce qui permet de forcer un retour à l’état draft sans jamais laisser l’annonce passer, même une fraction de seconde, en ligne.
add_filter( 'wp_insert_post_data', function( $data, $postarr ) {
if ( $data['post_type'] !== 'annonce_immo' ) {
return $data;
}
if ( $data['post_status'] !== 'publish' ) {
return $data;
}
$has_thumbnail = has_post_thumbnail( $postarr['ID'] );
$gallery = get_post_meta( $postarr['ID'], 'galerie_photos', true );
if ( ! $has_thumbnail && empty( $gallery ) ) {
$data['post_status'] = 'draft';
}
return $data;
}, 10, 2 );
Ce filtre reçoit deux tableaux : les données destinées à la base ($data) et les données brutes de la requête ($postarr). On y vérifie à la fois l’image mise en avant et une éventuelle galerie stockée en champ personnalisé, car certaines agences utilisent l’une, d’autres l’autre, parfois les deux.
Prévenir l’agent au lieu de le laisser deviner
Bloquer silencieusement une publication sans expliquer pourquoi est le meilleur moyen de générer un ticket de support inutile. Il faut donc coupler le filtre à une notice d’administration claire, affichée sur l’écran d’édition du contenu concerné.
- Stocker un indicateur temporaire (transient lié à l’utilisateur) au moment du blocage
- Afficher une notice rouge via
admin_noticesexpliquant la raison exacte - Proposer un lien direct vers l’onglet médias de l’annonce
Distinguer l’image à la une de la galerie
Certaines agences exigent uniquement une image à la une pour la vignette de liste, d’autres exigent une galerie complète avant publication. Le choix mérite d’être documenté dans le code lui-même, car c’est souvent la première question posée six mois plus tard par un nouveau développeur qui reprend le projet.
Un contrôle de publication sans message d’erreur associé n’est pas un contrôle, c’est un piège. Toujours prévoir la notice avant le filtre, jamais l’inverse.
Variantes utiles
Autoriser une exception pour certains rôles
Un administrateur qui reprend une annonce en cours de rédaction peut vouloir la publier temporairement sans photo, le temps d’un test d’affichage. Ajouter une condition sur current_user_can( 'manage_options' ) permet de contourner la règle pour ce seul rôle, sans toucher au comportement des agents.
Étendre le contrôle à d’autres champs obligatoires
La même logique s’applique à un prix renseigné, une localisation choisie ou un type de bien sélectionné. Plutôt que de multiplier les filtres, on peut construire un tableau de règles et les parcourir en boucle, ce qui facilite grandement l’ajout d’une nouvelle contrainte plus tard.
En résumé
Un simple filtre sur wp_insert_post_data, combiné à une notice explicite, suffit à garantir qu’aucune annonce incomplète ne passe en ligne, sans dépendre d’une extension tierce ni d’une discipline manuelle des agents. Le redimensionnement ou l’optimisation des photos jointes reste, lui, un sujet à part entière.