WordPress possède un formulaire de commentaire adapté à la plupart des blogs. Cependant, comment s’y prendre si vous souhaitez ajouter ou supprimer des champs et personnaliser l’affichage des commentaires ?

WordPress prévoit la possibilité de personnaliser le formulaire de commentaire grâce à la fonction comment_form( $args, $post_id ), cette fonction est intéressante mais quelque peu limitée. Nous allons plutôt aborder quelques crochets (hooks) s’y rapprochant.

Concrètement, il faut procéder en trois étapes :

  • insérer ou supprimer un champ dans le formulaire
  • permettre l’insertion des données renseignées dans la base de données
  • afficher les nouvelles données dans les commentaires

Je vous invite à éditer votre fichier functions.php pour effectuer des tests avec les codes que je vais fournir.
Allez, c’parti !

Insérer et supprimer des champs dans le formulaire de commentaire

Cette première étape va utiliser le hook comment_form_defaults et se présente sous la forme d’une manipulation de tableau PHP.
Les champs sont enregistrés dans l’entrée « fields » du tableau et peuvent être manipulés assez simplement. Ils contiennent du code HTML que nous allons reproduire pour nos champs personnalisés.

add_filter( 'comment_form_defaults', 'juiz_manage_default_fields');
 
// $default contient tous les messages du formulaire de commentaire
// il contient également "comment_field", le textarea du message
 
if ( !function_exists('juiz_manage_default_fields')) {
   function juiz_manage_default_fields( $default ) {
 
      // Récupération des infos connues sur le visiteur
      // Permet de pré-remplir nos nouveaux champs
 	
      $commenter = wp_get_current_commenter();
 
      // Suppression d'un champ par défaut parmi : author, email, url
 	
      unset ( $default['fields']['url'] );
 	
      // Ajout des champs dans le tableau "fields"
      // $commenter[] contient les infos sur le visiteur
 	
      $default['fields']['job'] = '<p class="comment-form-author-job comment-form-author">
      <label for="job">'. __('Your job') . '</label>
      <span class="required">*</span>
      <input id="job" name="job" value="'.$commenter['comment_author_job'].'" aria-required="true" size="30" type="text" />
      </p>';
 	
      $sel_female = $sel_male = '';
      if ( $commenter['comment_author_gender'] != '') ${'sel_'.$commenter['comment_author_gender']} = ' checked="checked"';
 	
      $default['fields']['gender'] = '<p class="comment-form-author-gender">
      <span class="label_like">'. __('Your gender') . '</span>
      <label for="female">F</label> <input '. $sel_female .' id="female" name="gender" value="female" type="radio" />
      <label for="male">M</label> <input '. $sel_male .' id="male" name="gender" value="male" type="radio" />
      </p>';
 	
      // On retourne le tableau des champs
 	
      return $default;
   }
}

Quelques explications s’imposent :
Concernant le HTML produit, je copie et adapte la structure par défaut de mon thème sur les champs de formulaire (ici TwentyEleven) dans le but de limiter les modifications futures sur la CSS (d’où la copie de la classe comment-form-author sur comment-form-author-job).

Le tableau des champs (fields) ressemble à cela :

array(
   'author' => '<p class="comment-form-author">…',
   'email'  => '<p class="comment-form-email">…',
   'url'    => '<p class="comment-form-url">…'
);

Pour ajouter un champ il me suffit donc de faire (en remplaçant « slug » par quelque chose de pertinent) :

$default['fields']['slug'] = '<p class="comment-form-author-slug">…';

La ligne 12 récupère les cookies enregistrés lorsque qu’un commentaire est posté par un utilisateur. Ils n’existent donc pas lorsqu’un visiteur n’a jamais commenté sur votre blog, mais permettent ensuite de pré-remplir les champs (ligne 26 et 30) si l’utilisateur revient poster un commentaire.
Nous verrons plus loin comment nous enregistrons les cookies pour nos nouveaux champs de formulaire.

À noter : Il existe le hook comment_form_defaults_fields qui permet de manipuler directement les champs (ex : unset($default['url']). Cependant j’ai une légère préférence pour le hook comment_form_defaults car il permet d’atteindre d’autres éléments du formulaire.
Par contre, si votre objectif est de supprimer simplement le champ url par exemple :

add_filter('comment_form_default_fields','juiz_remove_url_field'); 
if ( !function_exists('juiz_remove_url_field')) {
   function juiz_remove_url_field( $fields ) { 
      unset($fields['url']); return $fields;
   }
}

Enregistrer les données des champs personnalisés

Cette seconde étape se découpe en deux sous-étapes si certains de vos champs sont obligatoires.
Le premier hook utilisé est comment_post qui permet d’intervenir lorsque le commentaire a été enregistré.
Le second est preprocess_comment qui intervient avant l’enregistrement des données en base, notamment pour les contrôler.

Nous allons donc d’abord contrôler notre champ obligatoire ‘job’ pour retourner une erreur s’il est vide :

add_filter( 'preprocess_comment', 'juiz_verify_comment_data' );
if ( !function_exists('juiz_verify_comment_data') ) {
   function juiz_verify_comment_data( $commentdata ) {
 
      // si job est vide on affiche une erreur
      if ( ! isset( $_POST['job'] ) )
         wp_die( __( 'Error: please fill the required field (job).' ) );
 
      // si job dépasse 45 caractères (arbitraire) on affiche une erreur
      elseif ( isset( $_POST['job'] ) AND strlen ( $_POST['job'] ) > 45 )
         wp_die( __( 'Error: 45 maximum char. for "job" field.' ) );
 
      return $commentdata;
   }
}

Une fois la donnée obligatoire contrôlée, nous enregistrons les données du commentaire :

add_action( 'comment_post', 'juiz_save_comment_data' );
if ( !function_exists('juiz_save_comment_data') ) {
   function juiz_save_comment_data( $comment_id ) {
 
      // définition de la durée de vie des cookies
      $comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
 
      if (isset($_POST['job'])) {
 
         // on enregistre l'info en base de données
         add_comment_meta( $comment_id, 'job', esc_html( $_POST['job'] ) );
 
         // on enregistre un cookie
         setcookie('comment_author_job_' . COOKIEHASH, esc_html( $_POST['job'] ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
      }
 
      // on vérifie que le champ gender respecte les valeurs prévues
      if (isset($_POST['gender']) AND in_array ( $_POST['gender'] , array('male', 'female'))) {
         // même schéma que précédemment
         add_comment_meta( $comment_id, 'gender', esc_html($_POST['gender']) );
         setcookie('comment_author_gender_' . COOKIEHASH, esc_html( $_POST['gender']), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
      }
   }
}

Le cookie est optionnel mais il permet de reproduire le comportement de WordPress qui ajoute un cookie par champ du formulaire de commentaire pour se souvenir des données entrées par le visiteur.

En l’état, nous avons ajouté les infos en base de données, nous avons créé des cookies, et nous avons pris soin, dans l’étape précédente, de récupérer ces cookies grâce à la fonction wp_get_current_commenter(). Sauf qu’en fait cette fonction récupère uniquement les cookies pour les champs « classiques » (Nom, url, e-mail). Il faut donc compléter cette fonction pour l’inviter à piocher dans nos cookies fraichement créés :

add_filter('wp_get_current_commenter', 'juiz_add_custom_comment_cookies');
function juiz_add_custom_comment_cookies($cookies) {
 
	$comment_author_job = '';
	if ( isset($_COOKIE['comment_author_job_'.COOKIEHASH]) )
		$comment_author_job = $_COOKIE['comment_author_job_'.COOKIEHASH];
 	
	$comment_author_gender = '';
	if ( isset($_COOKIE['comment_author_gender_'.COOKIEHASH]) )
		$comment_author_gender = $_COOKIE['comment_author_gender_'.COOKIEHASH];
 	
 
	$cookies['comment_author_job'] = $comment_author_job;
	$cookies['comment_author_gender'] = $comment_author_gender;
 
	return $cookies;
}

La variable $cookies est un tableau associatif (clé + valeur), dont la clé est le nom du cookie (sans le _cookiehash) et la valeur est la valeur du cookie que l’on récupère s’il existe.

Maintenant il faut afficher ces informations dans notre liste de commentaire !

Afficher les données personnalisées dans la liste de commentaires

Cette dernière étape permet d’afficher les informations dans la liste de commentaires. Il existe un certain nombre de hooks qui permettent d’intervenir sur des zones précises d’un commentaire. Je vais en utiliser deux ici qui sont : get_comment_author_link et get_avatar.

Je souhaite afficher le job à côté du nom de l’auteur d’un commentaire.

add_filter( 'get_comment_author_link', 'juiz_attach_custom_info_to_comments_list' );
if ( !function_exists('juiz_attach_custom_info_to_comments_list') ) {
   function juiz_attach_custom_info_to_comments_list( $author ) {
 
      // on récupère l'info job
      $job = get_comment_meta( get_comment_ID(), 'job', true );
 
      // si l'info existe, on l'ajoute entre parenthèse après l'auteur
      if ( $job )
         $author .= ' (' . $job . ')';
 
      // on retourne l'info
      return $author;
   }
}

La variable $author contient le code HTML qui affiche le nom de l’auteur (avec ou sans lien vers son site). On ne fait donc que rajouter du contenu à la suite de cette chaine.
Cette technique a l’avantage d’ajouter l’information également dans le widget qui traite des derniers commentaires postés.

Pour afficher la valeur de gender, j’aurais très bien pu faire la même chose en ajoutant l’information à la suite après l’avoir récupérée avec get_comment_meta(). Mais comme j’aime bien me compliquer la vie, j’ai décidé d’ajouter une classe autour de l’avatar de l’utilisateur.

add_filter ( 'get_avatar', 'juiz_attach_custom_gender_to_avatar');
if ( !function_exists('juiz_attach_custom_gender_to_avatar') ) {
   function juiz_attach_custom_gender_to_avatar( $avatar ) {
 		
      $gender = get_comment_meta( get_comment_ID(), 'gender', true );
      $gender = $gender ? $gender : 'undefined';
      $avatar = '<span class="gender ' . $gender . '">' . $avatar . '</span>';
 		
      return $avatar;
   }
}

La variable $avatar contient le code HTML de l’avatar de l’utilisateur, une simple image par défaut. Ici on englobe l’avatar d’un élément span porteur du classe gender ainsi que d’une classe dynamique qui peut être male, female ou undefined en fonction de l’info que l’on récupère en base de données.

Le métier placé à côté du nom d'auteur, et l'avatar customisé avec un symbole en fonction du sexe.

Et voilà, c’est tout pour cette longue astuce, pour le reste c’est à vous d’imaginer.

Option bonux 1 : éditer un champ existant

En restant dans le premier hook (comment_form_defaults) il est possible d’éditer les champs existants en les manipulants avec des expressions régulières, ou en les réécrivant :

$default['fields']['author'] = '
   <p class="comment-form-author">  
      <label for="author">'. __('Name') . '</label>
      <span class="required">*</span> 
      <input id="author" name="author" value="'.$commenter['comment_author'].'" placeholder="Votre nom ou pseudo" aria-required="true" size="30" type="text" /> 
   </p>
';

Ici je rajouter un attribut placeholder par exemple.
Inutile de changer quoi que ce soit dans le traitement des données, WordPress le prévoit déjà.
Merci à Nicolas pour la suggestion.

Option bonux 2 : redirection après un commentaire

J’ai croisé dans le cœur de WordPress le hook comment_post_redirect qui permet de choisir la page de redirection lorsqu’un utilisateur a posté un commentaire.
Par défaut cette page redirige vers le commentaire de l’utilisateur avec une ancre.
Voici comment la fonction se présente :

add_action('comment_post_redirect', 'juiz_new_comment_redirection');
if ( !function_exists('juiz_new_comment_redirection') ) {
   function juiz_new_comment_redirection( $location ) {
      // valeur par défaut donnée par WordPress
      // à vous de personnaliser $location en fonction de vos besoins
      $location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
      return $location;
   }
}

Option bonux 3 : le code complet

Pour ceux qui ont peur d’avoir raté une étape :

// ajout physique d'un champ
add_filter( 'comment_form_defaults', 'juiz_manage_default_fields');
 
// $default contient tous les messages du formulaire de commentaire
// il contient également "comment_field", le textarea du message
if ( !function_exists('juiz_manage_default_fields')) {
	function juiz_manage_default_fields( $default ) {
 
		$commenter = wp_get_current_commenter();
 
		// Suppression d'un champ par défaut parmi : author, email, url
 		
		//unset($default['fields']['url']);
 		
		// Ajout des champs dans le tableau "fields"
 		
		$default['fields']['job'] = '<p class="comment-form-job comment-form-author">
		<label for="job">'. __('Your job') . '</label>
		<span class="required">*</span>
		<input id="job" name="job" aria-required="true" size="30" type="text" value="' . esc_attr($commenter['comment_author_job']) . '" />
		</p>';
 		
		$sel_female = $sel_male = '';
		if ( $commenter['comment_author_gender'] != '') ${'sel_' . $commenter['comment_author_gender']} = ' checked="checked"';
 		
		$default['fields']['gender'] = '<p class="comment-form-gender">
		<span class="label_like">'. __('Your gender') . '</span>
		<label for="female">F</label> <input id="female" '. $sel_female .' name="gender" value="female" type="radio" />
		<label for="male">M</label> <input id="male" '. $sel_male .' name="gender" value="male" type="radio" />
		</p>';
 		
		// On retourne le tableau des champs
 		
		return $default;
	}
}
 
 
// controle des champs obligatoires à l'enregistrement
add_filter( 'preprocess_comment', 'juiz_verify_comment_data' );
if ( !function_exists('juiz_verify_comment_data') ) {
	function juiz_verify_comment_data( $commentdata ) {
 
		if ( ! isset( $_POST['job'] ) )
			wp_die( __( 'Error: please fill the required field (job).' ) );
		elseif ( isset( $_POST['job'] ) AND strlen ( $_POST['job'] ) > 45 )
			wp_die( __( 'Error: 45 maximum char. for "job" field.' ) );
 		
		return $commentdata;
	}
}
 
//ajout en base de données des champs
add_action( 'comment_post', 'juiz_save_comment_data' );
if ( !function_exists('juiz_save_comment_data') ) {
	function juiz_save_comment_data( $comment_id ) {
 
		$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
 	
		if (isset($_POST['job']) AND strlen ($_POST['job']) < 45) {
			add_comment_meta( $comment_id, 'job', esc_html( $_POST['job'] ) );
			setcookie('comment_author_job_' . COOKIEHASH, esc_html( $_POST['job'] ), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
		}
 	
		if (isset($_POST['gender']) AND in_array ( $_POST['gender'] , array('male', 'female'))) {
			add_comment_meta( $comment_id, 'gender', esc_html($_POST['gender']) );
			setcookie('comment_author_gender_' . COOKIEHASH, esc_html( $_POST['gender']), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
		}
	}
}
 
 
// pour que get_commenter retourne nos cookies custom
add_filter('wp_get_current_commenter', 'juiz_add_custom_comment_cookies');
function juiz_add_custom_comment_cookies($cookies) {
 	
	$comment_author_job = '';
	if ( isset($_COOKIE['comment_author_job_'.COOKIEHASH]) )
		$comment_author_job = $_COOKIE['comment_author_job_'.COOKIEHASH];
 		
	$comment_author_gender = '';
	if ( isset($_COOKIE['comment_author_gender_'.COOKIEHASH]) )
		$comment_author_gender = $_COOKIE['comment_author_gender_'.COOKIEHASH];
	
 	
	$cookies['comment_author_job'] = $comment_author_job;
	$cookies['comment_author_gender'] = $comment_author_gender;
 	
	return $cookies;
}
 
 
// afficher l'info job dans la liste des commentaires
add_filter( 'get_comment_author_link', 'juiz_attach_custom_info_to_comments_list' );
if ( !function_exists('juiz_attach_custom_info_to_comments_list') ) {
	function juiz_attach_custom_info_to_comments_list( $author ) {
 	
		$job = get_comment_meta( get_comment_ID(), 'job', true );
		if ( $job )
			$author .= ' (' . $job . ')';
 		
		return $author;
	}
}
 
// afficher l'info gender graphiquement pas loin de l'avatar
add_filter ( 'get_avatar', 'juiz_attach_custom_gender_to_avatar');
if ( !function_exists('juiz_attach_custom_gender_to_avatar') ) {
	function juiz_attach_custom_gender_to_avatar( $avatar ) {
 		
		$gender = get_comment_meta( get_comment_ID(), 'gender', true );
		$gender = $gender ? $gender : 'undefined';
			$avatar = '<span class="gender ' . $gender . '">' . $avatar . '</span>';
 		
		return $avatar;
	}
}
 
// redirection personnalisée après un post de commentaire
add_action('comment_post_redirect', 'juiz_new_comment_redirection');
if ( !function_exists('juiz_new_comment_redirection') ) {
	function juiz_new_comment_redirection( $location ) {
		$location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
		return $location;
	}
}

L’espace de commentaire et là pour vous 😉
Cet article a une suite !

Sommaire

  1. WordPress – Personnaliser les champs du formulaire de commentaire
  2. WordPress – Des champs personnalisés dans l’administration des commentaires