Le constat
Dotclear propose, via son langage de templates, un certain nombre de balises permettant d'afficher conditionnellement un contenu donné.
Exemple dans le home.html :
<!-- # Entry with an excerpt -->
<tpl:EntryIf extended="1">
<div class="post-content">{{tpl:EntryExcerpt}}</div>
<p class="read-it"><a href="{{tpl:EntryURL}}"
title="{{tpl:lang Continue reading}} {{tpl:EntryTitle encode_html="1"}}">{{tpl:lang Continue
reading}}</a>...</p>
</tpl:EntryIf>
<!-- # Entry without excerpt -->
<tpl:EntryIf extended="0">
<div class="post-content">{{tpl:EntryContent}}</div>
</tpl:EntryIf>
Ce bout de code teste si le billet a un extrait (via <tpl:EntryIf extended="1">...</tpl:EntryIf>).
- Si c'est le cas, on n'affiche que l'extrait du billet
- Sinon on affiche le contenu du billet.
Maintenant, une colle : je voudrais afficher le premier billet complètement si c'est le premier de la page, mais garder le comportement normal dans les autres billets. Je vous épargne le code complet à écrire, mais dans le dernier tpl:EntryIf, il faudrait pouvoir dire : "si le billet n'a pas d'extrait, ou s'il a un extrait mais qu'il est le premier de la liste"... difficile à exprimer simplement avec les balises existantes, à moins de faire quelques redites dans le code.
Une solution
Voici donc une nouvelle extension : ExpAt, c'est à dire "Expressions in Attributes". Il s'agit d'un nouveau moyen d'écrire les tests dans les balises dotclear.
Là où on écrivait avant :
<tpl:EntryIf selected="1" extended="1" operator="||">...</tpl:EntryIf>
On peut maintenant écrire :
<tpl:EntryIf expr="selected || extended">...</tpl:EntryIf>
Revenons au problème initial : afficher le premier billet complètement si c'est le premier de la page, mais garder le comportement normal dans les autres billets. Voilà le code template à effectuer :
<!-- # Entry with an excerpt -->
<tpl:EntryIf expr="extended">
<div class="post-content">{{tpl:EntryExcerpt}}</div>
<tpl:EntryIf expr="index!=0">
<p class="read-it"><a href="{{tpl:EntryURL}}"
title="{{tpl:lang Continue reading}} {{tpl:EntryTitle encode_html="1"}}">{{tpl:lang Continue
reading}}</a>...</p>
</tpl:EntryIf>
</tpl:EntryIf>
<!-- # Entry without excerpt -->
<tpl:EntryIf expr="!extended || (extended && index!=0)">
<div class="post-content">{{tpl:EntryContent}}</div>
</tpl:EntryIf>
Le moteur d'expressions
Le moteur d'expressions permet les opérations suivantes :
- Opérations arithmétiques : +, -, *, /, %
- Opérations logiques : || (or), && (and), ^^ (xor)
- Comparaisons : < ("<"), > (">"), ≤ ("<="), ≥ (">="), ==, !=
- Gestion des parenthèses
- négation logique : !expression
- Variables : voir référence pour la liste des variables définies
- Fonctions : voir référence pour la liste des fonctions définies
"One last thing..."
Au fait, pourquoi s'embêter avec <tpl:EntryIf>, <tpl:CategoryIf>, <tpl:SysIf>, ... ? ExpAt définit tout simplement <tpl:If>, il suffit alors de préfixer les attributs par l'objet souhaité : entry pour tpl:EntryIf, category pour tpl:CategoryIf. En clair, <EntryIf> permet d'omettre "entry", <categoryIf> permet d'omettre "category", ...
Ainsi :
<tpl:EntryIf expr="!extended || (extended && index!=0)">
équivaut à :
<tpl:If expr="!entry.extended || (entry.extended && entry.index!=0)">
Et on peut bien sûr combiner le tout, par exemple dans un category.html :
<tpl:If expr="entry.extended && category.nb_post==1">
"One very last thing..."
Sur le forum a été évoqué un souhait pertinent : je veux afficher le résumé d'un billet (ie. les 300 premiers caractères), et afficher "..." si le contenu du billet dépasse les 300 caractères. Comment faire ?
ExpAt introduit quelques petits concepts supplémentaires.
L'affichage
C'est bien beau de ne faire que des tests, l'idéal serait quand même de pouvoir afficher quelque chose. {{tpl:Echo expr="<expression>"}} est là pour ça :)
Les variables
ExpAt permet de stocker le résultat d'une expression dans une variable, via le template :
{{tpl:Set var="nomvariable" expr="expression"}}
La variable est ensuite déclarée comme attribut de l'objet "my", et donc accessible ensuite via my.variable.
Cas pratique
Bon, maintenant, un cas d'application: afficher l'extrait d'un billet, par exemple les 300 premiers caractères de ce billet, et afficher '...' ensuite si ce billet dépasse 300 caractères, en ajoutant un lien pour le lire en entier.
Voilà le code que ça peut donner :
{{tpl:Set var="content" expr="encode_html(remove_html(entry.content))"}}
{{tpl:Set var="content_length" expr="strlen(my.content)"}}
<div class="post-content">
{{tpl:Echo expr="substr(my.content,0,300)"}}
<tpl:If expr="my.content_length > 300"> [...]</tpl:If>
</div>
<tpl:If expr="my.content_length > 300">
<p class="read-it"><a href="{{tpl:EntryURL}}"
title="{{tpl:lang Continue reading}} {{tpl:EntryTitle
encode_html="1"}}">{{tpl:lang Continue
reading}}</a>...</p>
</tpl:If>
En clair :
- On stocke le contenu billet dans my.content et sa taille dans my.content_length
- On test la valeur de my.content_length, et on affiche les "..." seulement si on est supérieur à 300...
La suite
La version actuelle du plugin montre les choses qu'il est possible de faire, mais la liste des objets/fonctions est réduite. J'attends maintenant vos besoins pour les enrichir :)
Crédits
Le compilateur d'expression repose sur un analyseur syntaxique et sémantique généré avec LIME-php.
Téléchargement
Le plugin est pour l'instant disponible ici
Le support du plugin se fait sur le forum dotclear

11 réactions
1 De Tomtom - 17/09/2010, 16:00
Je fais "clap clap" mister!
2 De phil - 15/10/2010, 19:24
J'essayais de faire un truc tout bête et je pensais que expat allait faire ça fitn, mais malheureusement pas :(
au début de mon tpl je faisais une boucle dans laquelle je déclarais une variable :
{{tpl:Set var="maconstante" expr=1}}
ensuite je voulais tester plus loin dans mon template cela :
<tpl:If expr="my.maconstante == 1"> pour ajouter un truc si la condition était remplie.
là j'ai une méchante exception qui me dit :
Fatal error: Call to a member function toPHP() on a non-object in /dotclear/plugins/expat/_public.php on line 34
si je met le 1 entre "" dans le Set j'ai ce message d'expat :
<!-- expat Compilation error : No such object : -->
ce serait super de permettre à expat de faire cette chose si simple.
Merci
Philippe
3 De phil - 15/10/2010, 20:02
une autre varante qui ne marche pas non plus :
{{tpl:Echo expr="category.url"}}
me donne l'url de la catégorie
{{tpl:Set var="root_cat" expr="category.url"}}
donc l'assignation de la variable devrait marcher
ensuite je fais cette condition :
<tpl:If expr="my.root_cat == Mag">
mais ça ne marche pas, j'ai l'erreur expat :
<!-- expat Compilation error : No such object : -->
que je mette Mag entre '' ou entre "" ne change rien.
ça aussi ce serait cool de pouvoir le faire :)
Merci
Philippe
4 De Dsls - 15/10/2010, 20:16
Les chaines de caractères sont à renseigner entre quotes ('). Ca devrait fonctionner avec un <tpl:If expr="my.root_cat == 'Mag'">
5 De Dsls - 15/10/2010, 20:17
Pour le commentaire #2, il faut saisir :
{{tpl:Set var="maconstante" expr="1"}}
(ne pas oublier les " )
6 De phil - 15/10/2010, 21:10
oui en effet, j'ai du avoir un problème de cache, je me disais bien que ça devait marcher ;)
Merci beaucoup !
Philippe
7 De phil - 16/10/2010, 11:54
excuse moi Dsls, mais j'ai l'impression que entry.date est vide.
dans mon category.html lorsque je mets entre les balises <tpl:Entries></tpl:Entries>:
<p>{{tpl:Echo expr="entry.date"}}</p>
je devrai avoir la date du billet formatée comme fixé dans les paramètres du blog or là rien n'est affiché.
si j'utilise <p>{{tpl:EntryDate}}</p> la date s'affiche bien.
c'est dans expat qu'il y a un truc qui cloche ?
Philippe
8 De phil - 18/10/2010, 18:08
bon c'était bête mais ça mérite ton attention le truc c'est que les deux ne cohabitent pas :
<p>{{tpl:Echo expr="entry.date"}}</p>
et
{{tpl:Set var="content_date" expr="mktime(entry.date)"}}
si je mets ces deux lignes dans le même code entry.date devient vide !
Merci !
Philippe
9 De phil - 18/10/2010, 20:51
bon dernier message, j'arrète de flooder ton blog, mais finalement non ça ne marche pas j'avais pas fait un bon test.
entry.date est vide chez moi alors que le reste est ok entry.content, entry.url etc...
il y a un truc bizarre. Tu peux supprimer mes commentaires si tu veux.
Merci quand-même
Philippe
10 De Dsls - 19/10/2010, 08:00
phil : il y avait effectivement un bug dans la date. La version 0.4 devrait corriger le problème : http://www.morefnu.org/public/archi...
11 De wanfr - 05/12/2010, 15:12
Bonjour,
impossible d'utiliser "EntryCommentCount" ?
je voudrai faire un affichage diffèrent du nb de commentaire de 1 à 9 et de 10 à 99 et au dela de 100...
je suis passé à coté de quelque chose ou cela n'est pas prévu ?
merci