Contenu principal

Le bouton « Répondre au commentaire » également sur le dernier niveau

Ce que je vais partager aujourd’hui est le système que j’ai mis en place ici sur le blog quant au bouton « Répondre » en regard de chaque commentaire. En somme, les commentaires imbriqués sont limités en profondeur, et pourtant il y a toujours un bouton pour répondre, même sur le niveau le plus profond.

Limiter les niveaux imbriqués, et leur affichage

Ici sur le blog, j’ai voulu limiter à 2 le nombre de niveaux dans les conversations, pour en finir avec les sous-niveaux imbriqués qui n’en finissent pas. Pour cela il y a, à ma connaissance, 2 façons de faire :

  1. Mettre une limite très élevée au paramètre « Activer les commentaires imbriqués jusqu’à XX niveaux » (Réglages => Discussion), puis côté CSS du thème, ne pas créer de décalage supplémentaire pour les niveaux supérieurs à la limite souhaitée. Ainsi, on aurait visuellement l’impression qu’il n’y a que XX niveaux. Le soucis est alors lorsque vous changerez de thème, il faudra à nouveau modifier le CSS. À la fois, ce n’est pas bien grave, mais on va se trainer des discussions de profondeur infinie durant toute la vie du blog.
  2. Mettre simplement la limite souhaitée dans le réglage cité plus haut. Là, l’inconvénient est que le bouton « répondre » disparait sur les commentaires ayant atteint la limite de profondeur. Il faut alors scroller jusqu’au commentaire parent et cliquer sur le bouton « Répondre » de ce commentaire. Pas vraiment ergonomique. Il faut donc trouver un moyen de remettre ce bouton, sans créer un niveau supplémentaire, c’est ce que nous allons voir aujourd’hui.

Il y a une autre différence entre ces 2 méthodes : l’emplacement de votre réponse dans le fil de discussion. En effet, on va imaginer qu’une discussion est déjà en cours et qu’un message a déjà 10 réponses. Vous souhaitez alors répondre à la 5ème réponse, donc au beau milieu de la discussion. Dans le 1er cas (limite très élevée) votre réponse se placera juste sous le message auquel vous répondez. Dans le second cas, votre message se placera à la fin du fil de discussion (comprendre : à la fin du niveau).
Là, chacun retiendra le comportement qui lui parait le plus logique. Pour ma part, je trouve le second cas plus logique. En effet, nous sommes au niveau le plus profond, mon message ne sera pas décalé visuellement par rapport aux autres, donc on ne comprendra pas que c’est une « sous-discussion ». Dans ce cas, il me parait logique de placer ma réponse à la fin, et non pas sous le message auquel je répond.

À la limite, et cette idée me vient à l’instant en écrivant l’article, on pourrait imaginer un troisième cas : cas identique au second, mais le bouton « Répondre » serait placé uniquement sur le dernier message de la « sous-discussion ». Je trouve que cela aurait du sens et il n’y aurait pas de « mauvaise surprise » quant au placement du message. Cas à étudier ;)

Afficher et modifier le bouton de réponse

Bref, passons à ce qui nous intéresse, le moyen d’ajouter ce bouton.
Nous allons avoir un problème dès le début. Ce bouton est généré avec la fonction get_comment_reply_link() (ou sa copine comment_reply_link()). Celle-ci dispose d’un filtre en sortie, super ! Sauf que lorsque le message est au dernier niveau, la fonction est stoppée avant d’atteindre ce filtre, il nous est donc parfaitement inutile :(
La seule solution est donc d’agir avant, au niveau du thème lui-même hélas, et cela va être plus compliqué pour certains thèmes, cela dépend de la façon dont les commentaires sont générés. Je prend par exemple TwentyFourteen : (comments.php)

404142434445464748

<ol class="comment-list">
	<?php
		wp_list_comments( array(
			'style'      => 'ol',
			'short_ping' => true,
			'avatar_size'=> 34,
		) );
	?>
</ol>

Ça, cela veut dire que le thème utilise le template par défaut de WordPress : (wp-includes/comment-template.php)

177417751776177717781779178017811782178317841785

protected function comment( $comment, $depth, $args ) {
	if ( 'div' == $args['style'] ) {
		$tag = 'div';
		$add_below = 'comment';
	} else {
		$tag = 'li';
		$add_below = 'div-comment';
	}
	// ...
	comment_reply_link( array_merge( $args, array( 'add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) );
	// ...
}

Là, la seule chose à faire est de créer le template dans le thème, car le lien est inexploitable comme il est actuellement :|

Pour ceux qui utilisent un template personnalisé, cela se passe en gros comme ça :

010203040506070809101112

<?php
function my_comments_callback( $comment, $args, $depth ) {
	$add_below = $args['style'] == 'div' ? 'comment' : 'div-comment';
	// ...
	comment_reply_link( array_merge( $args, array( 'add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) );
	// ...
}
?>

<ol class="commentlist">
	<?php wp_list_comments( array( 'callback' => 'my_comments_callback' ) ); ?>
</ol>

Il ne reste qu’à effectuer nos modifications. Nous allons utiliser get_comment_reply_link() et remplacer des chaines de caractères.
Voici à quoi ressemble un bouton « Répondre » :

1

<a class="comment-reply-link" onclick="return addComment.moveForm('div-comment-1805', '1805', 'respond', '2184')" href="/blog/i-see-dead-people-02184/?replytocom=1805#respond" rel="nofollow">Répondre</a>

Ce bouton permet de répondre au commentaire n°1805 qui a été posté sur l’article n°2184. Il va falloir s’occuper du paramètre replytocom dans l’url et du JavaScript dans l’attribut onclick.

Pour faire simple, voici comment on procède :

  1. Si nous sommes au niveau maximum, nous devons augmenter le paramètre 'max_depth' que nous passons à la fonction. Sans ça, la fonction ne retournera aucun bouton. Là on lui fait croire que nous n’avons pas atteint la limite de profondeur.
  2. Par des remplacements de chaines de caractères, on doit indiquer que le commentaire auquel l’utilisateur répond est le commentaire parent. La boite de réponse devra tout de même se placer sous le commentaire en question, et non sous le commentaire parent.

Voici le résultat, j’ai englobé tout ça dans une fonction (que j’utilise dans mon thème pro, mais simplifiée ici) et je vous montre son utilisation :

010203040506070809101112131415161718192021222324252627282930313233343536373839404142

<?php
if ( ! function_exists( 'mash_comment_reply_link' ) ) :
function mash_comment_reply_link( $args = array(), $comment = null, $post = null ) {
	echo mash_get_comment_reply_link( $args, $comment, $post );
}
endif;


if ( ! function_exists( 'mash_get_comment_reply_link' ) ) :
function mash_get_comment_reply_link( $args = array(), $comment = null, $post = null ) {
	$args['depth']     = isset( $args['depth'] )     ? absint( $args['depth'] )     : 0;
	$args['max_depth'] = isset( $args['max_depth'] ) ? absint( $args['max_depth'] ) : $args['depth'];
	$args['add_below'] = isset( $args['style'] ) && $args['style'] === 'div' ? 'comment' : 'div-comment';

	if ( $args['max_depth'] !== $args['depth'] ) {
		return get_comment_reply_link( $args, $comment, $post );
	}

	$comment = get_comment( $comment );
	$from    = array( 'replytocom=' . $comment->comment_ID . '#',     '"' . $args['add_below'] . '-' . $comment->comment_ID . '", "' . $comment->comment_ID . '",'     );
	$to      = array( 'replytocom=' . $comment->comment_parent . '#', '"' . $args['add_below'] . '-' . $comment->comment_ID . '", "' . $comment->comment_parent . '",' );
	$args['max_depth']++;
		
	$link = get_comment_reply_link( $args, $comment, $post );
	return str_replace( $from, $to, $link );
}
endif;


if ( ! function_exists( 'mash_comment' ) ) :
function mash_comment( $comment, $args, $depth ) {
	$args['depth'] = absint( $depth );
	// ...
	mash_comment_reply_link( $args );
	// ...
}
endif;
?>

<ol id="commentlist" class="commentlist clearfix">
	<?php wp_list_comments( array( 'mash_comment', ) ); ?>
</ol>

Cela donnera ceci, avec des XXXX pour l’ID du commentaire parent :

1

<a class="comment-reply-link" onclick="return addComment.moveForm('div-comment-1805', 'XXXX', 'respond', '2184')" href="/blog/i-see-dead-people-02184/?replytocom=XXXX#respond" rel="nofollow">Répondre</a>

Nota : si l’on ne touche pas au 'div-comment-1805' c’est pour que la boite de réponse se place au bon endroit, et pas sous le commentaire parent.

Conclusion

Au final, l’utilisateur va, sans le savoir, répondre au commentaire parent, sans que cela ne gêne la discussion en cours. De votre côté, cela vous permet d’avoir un nombre de niveaux de « sous-discussions » très réduit tout en permettant à vos lecteurs d’avoir des conversations « normales », où chacun peut répondre à n’importe qui.
Bon, bien sûr, les SEO-Jedi nous diront qu’il est déconseillé d’avoir des conversations imbriquées, et certainement à juste titre, c’est leur domaine, pas le mien. De mon côté, je préfère garder cette imbrication, même limitée, cela me parait plus naturel pour nos conversations, mais c’est un autre sujet ;)

Complément

L’ami Julio a une façon un peu différente d’appréhender les commentaires sur son blog, et vient justement de sortir un article (hasard ? Sûrement ;) ) où il explique comment éviter la multiplication des commentaires de niveau 0 d’un même utilisateur, et préfère les regrouper.

See ya!