Les hooks sont les alliés des développeurs lorsqu’il s’agit de créer des thèmes et extensions. Grâce au hook save_post, il est possible de lancer une action juste après l’enregistrement d’un article, ce qui va nous permettre de calculer le temps de lecture d’un article.
Sommaire du cours
Nous avons abordé les hooks un peu plus tôt dans cette formation. Ils nous ont été utiles dans le functions.php
pour configurer notre thème. Pour rappel voici leur définition :
Hooks
Définition
Et il y en a un qui s’avère particulièrement utile et qui va nous permettre de calculer le temps de lecture d’un article, ainsi que générer un sommaire. C’est le hook save_post
.
Celui-ci va se lancer juste après l’enregistrement d’une publication (article, page, CPT…) et renvoyer les données enregistrées.
Utiliser le hook Save Post
Voici la base du hook save_post
, à placer dans le functions.php
de votre thème :
Ce hook vous renvoie 3 paramètres : l’identifiant de l’article, ses données (titre, contenu…), et un booléen nous indiquant si on est dans le cas d’une création d’article, ou d’une mise à jour.
Comme notre fonction va être lancée à chaque fois qu’une publication est enregistrée, on va avoir besoin de mener quelques tests préalables afin d’être sûr qu’elle soit exécutée dans les bonnes conditions.
1 • Test création vs mise à jour
Justement, le hook est appelé dès lors que l’on créé un nouvel article (en cliquant sur Articles > Ajouter dans l’interface d’administration). Donc notre fonction va être exécutée une première fois à ce moment là. Mais cela ne nous intéresse pas car il n’y a pas encore de contenu à analyser.
C’est pourquoi on va tester le paramètre $update
qui va nous indiquer dans quel cas on se trouve :
$update
est égal àfalse
si on est dans le cas d’une première création ;$update
est égal àtrue
lorsqu’on enregistre un article.
Ainsi, lorsqu’on est dans le cas d’une première création, on appelle return
pour sortir de la fonction et éviter ainsi son exécution.
Par contre, dans le cas où vous voudriez assigner automatiquement une catégorie à la création d’un article, on testerait cette fois qu’update est bien à false
. Voici un exemple :
2 • Éviter les révisions
WordPress risque également d’entrer dans notre fonction lorsqu’il gère les révisions. Si c’est le cas, on arrête là aussi l’exécution de la fonction. Le test se fait grâce à wp_is_post_revision()
.
3 • Éviter l’autosave
WordPress enregistre automatiquement votre contenu à intervalles réguliers, ce qui va là aussi déclencher notre fonction. Mais là encore, on n’a pas besoin de l’exécuter.
En fait on a besoin d’enregistrer le temps de lecture seulement lorsque le rédacteur clique de lui même sur Publier / Mettre à jour.
Donc afin de ne pas trop alourdir l’enregistrement automatique, on vérifie avec la constante DOING_AUTOSAVE
si on est dans ce cas, auquel cas on sort de la fonction.
Afin de ne pas générer d’erreur, on teste préalablement si cette constante est définie.
4 • Tester le type de publication
Et enfin, il faut vérifier que l’on est bien sur le type de publication souhaité, sinon notre calcul se lancerait sur les articles, pages, et tout autre Custom Post Type créé dans votre thème.
Si ce n’est pas ce que vous souhaitez, on va ajouter un dernier test afin de contrôler qu’on est bien dans le cas d’un article.
Bien, une fois qu’on a testé tout ça, on s’est assuré qu’on est bien dans le bon cas de figure. Si je résume : le rédacteur est en train de rédiger un article et a bien cliqué lui-même sur le bouton Publier / Mettre à jour.
Calculer le temps de lecture d’un article
Maintenant, le but va être de récupérer le contenu de l’article, retirer les balises HTML, compter le nombre de mots et enfin calculer le temps de lecture.
Voici le code correspondant. Notez que j’ai écrit les tests et les return
sur une seule ligne afin de gagner un peu de place, sans perdre en lisibilité pour autant.
En premier lieu, je vais récupérer le contenu de l’article, accessible via $post->post_content
puis j’utilise en amont la fonction strip_tags()
qui permet de supprimer les balises HTML. Enfin, la fonction str_word_count()
permet de compter le nombre de mots.
À partir de là on peut calculer le temps de lecture. D’après Wikipedia, une personne lit en moyenne 250 mots par minute.
On divise donc le nombre de mots obtenus par 250 et on obtient notre temps de lecture exprimé en minutes. J’utilise ceil()
pour arrondir à la minute supérieure et ainsi éviter les nombres à virgule.
Il ne nous reste plus qu’à stocker cette valeur quelque part, et le plus judicieux est de l’enregistrer dans les méta-données de l’article, les fameuses post metas. Et pour cela on utilise la fonction update_post_meta()
. C’est d’ailleurs sur ce même principe que sont enregistrés les champs additionnels, qu’ils soient natifs ou issus d’ACF.
Le saviez-vous ?
Il existe la fonction add_post_meta
qui permet de créer une nouvelle méta-donnée, mais on utilise tout le temps update_post_meta
, car cette dernière est capable de créer la donnée si elle n’existe pas encore.
Aparté: Métas et base de données
Les méta-données d’un article sont enregistrées dans la table wp_postmeta
alors que les articles sont enregistrés dans wp_post
. Pour plus de détails sur la structure des données de WordPress, référez-vous au cours sur le coeur de WordPress et la base de données.
Afficher le temps de lecture dans le template
Maintenant, pour afficher le temps de lecture, il suffit d’utiliser la fonction get_post_meta
dans le template de notre publication, soit single.php
pour un article.
Le troisième paramètre, passé à true
, permet d’indiquer que la valeur est unique : il n’y a qu’un seul temps de lecture par article. C’est dû au fait que WordPress permet d’enregistrer plusieurs metas avec le même nom, et dans ce cas il retournerait un tableau.
Comme ce n’est pas utile dans notre cas, on lui indique qu’on a qu’une seule valeur, qui est retournée comme une string
et non pas comme un array
.
Vous savez désormais tirer parti du hook save_post
, et l’utiliser dans les bonnes conditions. Dans le prochain cours on va à nouveau utiliser ce hook, mais cette fois pour générer un sommaire. Et on aura de nouveaux défis puisqu’il faudra par exemple modifier le contenu tout juste enregistré.
Cisco
Le 4 février 2023
Bonjour, c’est top ! Que faut il rajouter à cela pour prendre les contenus ACF avec des flexible layouts ?
Maxime BJ
Le 6 février 2023
Il faudrait faire une boucle pour lire le contenu de tes champs flexibles. En définitive le code sera quasi identique à celui du cours sur le champ flexible ACF et tu utiliseras str_word_count( strip_tags( get_sub_field( ‘content’ ) pour récupérer les contenus et compter les mots.
Fred - FLQ
Le 24 janvier 2024
Toujours aussi passionnant ! Les explications détaillées sur les différents tests sont vraiment hyper utiles et on voit tout de suite leur intérêt de manière plus globale.
Petite question : as-tu eu à travailler sur des projets pour lesquels tu as choisi d’enregistrer des infos dans une/des tables supplémentaires que celles par défaut ? Si oui, quels critères sont selon toi déterminants pour faire ce choix ?
Encore un grand merci pour tout ton travail ! 🙂
Maxime BJ
Le 24 janvier 2024
En général quand tu bosses sur un projet assez gros, ça devient plus intéressant de faire des tables customs pour gérer les relations. Thomas Deneulin explique assez bien les limitations SQL de WordPress au WordCamp Biarritz si tu veux en savoir plus : https://wordpress.tv/2023/11/23/comprendre-et-optimiser-notre-base-de-donnees-wordpress/.
J’ai notamment pu utiliser des tables customs chez WPChef lors du développement de notre LMS, car on avait des stagiaires, des formations, des sessions, des évaluations, des compétences… Autant d’entités qu’il n’aurait pas été très agréable de manipuler en tant que Custom Post Type (notamment pour toutes les données enregistrées en postmeta).
Fred - FLQ
Le 24 janvier 2024
Merci pour ta réponse : je vais aller regarder ça avec intérêt !