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 : &lt; ("<"), &gt; (">"), &le; ("<="), &ge; (">="), ==, !=
  • 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 &gt; 300">&nbsp; [...]</tpl:If>
</div>
<tpl:If expr="my.content_length &gt; 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