Tout savoir sur WordPress

Utiliser le hook save_post pour définir le temps de lecture d’un article

Aujourd’hui je vais vous parler du hook save_post, qui permet de lancer une action au moment de l’enregistrement d’une page ou un article. Cela nous permettra entre autres de calculer le temps de lecture et générer un sommaire. Voyons dans un premier temps comment calculer le temps de lecture.

Certains préfèrent générer le sommaire à la volée lors de l’affichage de la page (par exemple en Js), et idem pour le comptage de mots. Je préfère partir du principe que c’est à l’enregistrement de l’article que tout ceci doit être généré, une bonne fois pour toutes.

L’avantage est que vous pourriez très bien envisager de classer les articles par temps de lecture, ou même afficher le sommaire d’un article dans une autre page (par exemple pour des cours, vous pourriez avoir une page qui liste tous les cours et aussi tous les sommaires).

Vous pouvez d’ailleurs voir à l’oeuvre le sommaire et le temps de lecture sur Xyoos :

sommaire et temps de lecture

 

C’est quoi déjà un hook ?

Le hook save_post permet de manipuler le contenu d’un article lors de son enregistrement

Un hook est une action que vous pouvez lancer à des moments clés de l’exécution de WordPress. Par exemple, comme on va le voir ici, il va nous permettre de lancer une de nos fonctions (générer un sommaire, un temps de lecture) au moment même où WordPress va enregistrer l’article.

WordPress a défini des centaines de ces moments clés sur lesquels vous allez pouvoir intervenir avec un code personnalisé. Le plus beau dans tout cela, c’est que n’avez pas besoin de toucher au code source du CMS (ne le faites jamais, toute modification du code serait perdue à la prochaine mise à jour du coeur).

Vous pourrez simplement déclarer votre fonction dans le fichier functions.php de votre thème (ou dans un fichier d’un plugin)

Voici la base du code pour déclarer une fonction personnalisée lors de l’enregistrement :

<?php 
function geekpress_reading_time($post_id, $post, $update)  {
	// Le code ira ici	
}
add_action('save_post', 'geekpress_reading_time', 10, 3);

On commence par déclarer une fonction qui va nous permettre d’accueillir notre calculateur de temps de lecture. Pensez à ne pas donner un nom trop générique afin d’éviter d’éventuels conflits de nom avec d’autres fonctions.

Les 3 paramètres vous seront fournis par WordPress : l’identifiant de l’article crée, les données de celui-ci et si c’est une création ou une mise à jour.

On va ensuite utiliser la fonction add_action pour définir qu’au moment du passage sur save_post, on veut lancer notre fonction geekpress_reading_time. Le paramètre 10 est la priorité d’exécution de la fonction : plus le chiffre est haut, plus la fonction sera exécutée tard (dans le cas ou plusieurs fonctions utiliseraient ce hook) et le dernier paramètre indique que l’on va recevoir 3 paramètres de WordPress (ceux énumérés plus haut).

Le Codex WordPress vous apportera également toute l’information nécessaire sur ce hook save_post.

Quelques précautions

On va déjà tester que la fonction se lance bien. Je vais placer un var_dump bien sale et un die pour terminer l’exécution du script PHP comme un bourrin.

function geekpress_reading_time($post_id, $post, $update)  {

	// Sinon la fonction se lance dès le clic sur "ajouter"
	if(!$update) {
		return;
	}

	var_dump('Coucou !'); die();
}
add_action('save_post', 'geekpress_reading_time', 10, 3);

Notez que j’ai aussi ajouté un premier test sur $update : WordPress a la facheuse tendance de lancer le hook lorsque vous cliquez sur Ajouter un article (ou une page). En fait WordPress crée directement un brouillon, et exécute donc la fonction une première fois. Grâce au paramètre $update on va pouvoir éviter cela : notre fonction ne se lancera que lorsque l’on clique sur Publier ou Mettre à jour, et plus lorsque l’on clique sur Ajouter.

Enregistrez votre article. Vous devriez voir une page blanche avec votre Coucou :

var dump

Votre fonction se lance bien !

On va ajouter une vérification afin d’éviter de lancer notre fonction lorsque WordPress crée une révision automatique de l’article. Ce n’est pas nécessaire d’alourdir l’enregistrement pour rien. Ajoutez ce code juste après le premier test.

	// On ne veut pas executer le code lorsque c'est une révision
	if(wp_is_post_revision($post_id)) {
		return;
	}

On veut éviter de lancer notre fonction lors des enregistrements automatiques, on ajoute donc :

	// On évite les sauvegardes automatiques
	if ( defined( 'DOING_AUTOSAVE' ) and DOING_AUTOSAVE ) {
 	  	return;
	}

Maintenant, essayez de créer une page, vous verrez que le hook se lance aussi à l’enregistrement. Il va donc falloir restreindre à un seul type de publication : un article, une page, ou tout autre custom post type crée par vos soins. Ajoutez ce code à la suite des précédents tests :

	// Seulement pour les articles	
	if ($post->post_type != 'post') {
    		return;
	}

Pour les pages, indiquez ‘page’ à la place de ‘post’, ou alors tout autre slug de custom post type.

Calculer le temps de lecture et l’enregistrer dans un post meta

Ajoutez ces lignes dans votre code après les vérifications  puis remplissez un nouvel article avec beaucoup de Lorem Ipsum  :

  // Calculer le temps de lecture
  $word_count = str_word_count(strip_tags($post->post_content));

  // On prend comme base 300 mots par minute
  $minutes = ceil($word_count / 300);

  var_dump("nombre de mots : ".$word_count);
  var_dump("Temps de lecture : ".$minutes);
  die();

Le contenu de l’article se trouve dans l’objet $post->post_content (vous pouvez d’ailleurs faire un var_dump de $post pour voir ce que contient l’objet), on utilise la fonction PHP str_word_count pour calculer le nombre de mots et on passe un coup de strip_tags pour retirer préalablement les balises HTML du compte.

On divise ensuite par le nombre de mots minute moyen que j’ai défini à 300 en me basant sur ce que dit Wikipédia  et on arrondi à l’entier supérieur avec ceil (afin de toujours au minimum avoir 1 minute de temps de lecture).

Maintenant que l’on a cette valeur, il va falloir la stocker quelque part. C’est là qu’interviennent les post metas. Ils vous permettent de stocker une valeur liée à l’article, et on va l’utiliser pour stocker notre temps de lecture. Ajoutez le code suivant :

 update_post_meta( $post_id, 'temps_lecture', $minutes );

Et retirez les var_dump, on en a désormais plus besoin !

Du coup pourquoi on utilise pas la fonction add_post_meta ? Car Update va créer la post meta, la première fois, si elle n’existe pas encore. Du coup il est conseillé d’utiliser toujours update_post_meta (Merci Julio pour la correction).

Au niveau des arguments :

  1. l’identifiant de l’article auquel lié la donnée
  2. le nom de la valeur, ici temps_lecture
  3. la valeur à stocker, ici notre temps en minutes
  4. valeur unique ou non : dans notre cas nous n’aurons qu’une valeur appelée temps_lecture. mais dans d’autres cas vous pourrez stocker plusieurs valeurs portant le même nom

La valeur apparaitra ensuite dans les champs personnalisés qui apparaissent en bas de votre article dans l’admin de WordPress :

champ-perso

 

Pour afficher le bloc champs personnalisés, cliquez sur Options de l’écran en haut à droite puis cochez Champs personnalisés.

Si vous ne souhaitez pas faire apparaitre le temps de lecture dans les champs personnalisés de l’administration, il faudra commencer son nom (paramètre 2) par un underscore, par exemple : _temps_lecture.

Les metas nommées ainsi n’apparaitront pas dans les champs personnalisés.

Voici le code complet  à mettre dans functions.php :

function geekpress_reading_time($post_id, $post, $update)  {

	// Sinon la fonction se lance dès le clic sur "ajouter"
	if(!$update) {
		return;
	}

	// On ne veut pas executer le code lorsque c'est une révision
	if(wp_is_post_revision($post_id)) {
		return;
	}

	// On évite les sauvegardes automatiques
	if ( defined( 'DOING_AUTOSAVE' ) and DOING_AUTOSAVE ) {
		return;
	}

	// Seulement pour les articles
	if ($post->post_type != 'post') {
    		return;
	}

	// Calculer le temps de lecture
	$word_count = str_word_count(strip_tags($post->post_content));

	// On prend comme base 300 mots par minute
	$minutes = ceil($word_count / 300);
	
	// On sauvegarde la meta
	update_post_meta( $post_id, 'temps_lecture', $minutes );

}
add_action('save_post', 'geekpress_reading_time', 10, 3);

Afficher la valeur dans le template

Pour afficher la valeur sur votre page, utilisez cette fonction dans single.php pour un article, ou page.php pour une page :

echo get_post_meta($post->ID, 'temps_lecture', true)." minutes";

Et voilà ! Vous savez maintenant utiliser le hook save_post pour calculer le temps de lecture.

Découvrez la suite du tutoriel pour générer un sommaire grâce au hook save_post.

 

Cet article a été mis à jour il y a 154 jours

Article écrit par Maxime BJ

Développeur, bloggeur et formateur Web spécialisé WordPress. 31 ans. Grenoblois. Co-fondateur de WPChef, l’organisme de formation WordPress.

Organisateur de WPInAlps, le meetup WordPress Grenoblois. Vous pouvez me rencontrer lors d’événements tels que WordCamp Paris et Europe. Traducteur Français de l’extension Advanced Custom Fields. Également développeur d’applications web avec MeteorJs. Je m’occupe un site pour apprendre l’informatique aux débutants gratuitement.

J’aime les jeux vidéo, la rando, la bouffe bien grasse et les voyages.

6 Commentaires

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

  1. Hello

    Avoir cette information est sympa pour savoir si tu peux lire l’article de suite ou le mettre à une lecture future.

    Avec ce code tu crées en base une valeur `temps_lecture` à chaque update de ton article au lieu de l’écraser.

    Il n’y a pas besoin de mettre de add || update, seul un update est suffisant pour faire le travail d’ajout/mise à jour automatiquement.

    Vérifie ta base de donnée et filtre sur ta clé, tu vas faire O_O

    Merci !

    • Oula my bad en effet grosse boulette de ma part que je m’empresse de corriger. Merci beaucoup pour ta contribution. Un mauvais point pour moi. (en plus c’est marqué dans la doc)

    • Ah après examen j’étais pas forcément dans le faux non plus ! Dans mon add j’ai le paramètre 4 à True, pour indiquer que c’est une meta unique. Donc pas de doublon en base. Cependant cette écriture est ancienne et ne sert plus à rien comme Update est capable de faire un ajout.