This application is not used any more and exists only for history. Post new tickets on the Github account.
Cette application n'est plus utilisée, et existe uniquement pour son historique. Postez les nouveaux tickets sur le compte github.

Ticket #1449 (confirmed new feature)

Opened 3 years ago

Last modified 3 years ago

Permettre à un plugin de template d'accéder à la variable _blockStack de jTplCompiler.

Reported by: flav Owned by:
Priority: normal Milestone:
Component: jelix:tpl Version: 1.3.1
Severity: normal Keywords:
Cc: Blocked By:
Blocking: Documentation needed: no
Hosting Provider: Php version:

Description

Allow a template plugin to access to jTplCompiler blockStack.

Dans certains cas très rares, il peut être utile, voire même necessaire de creer un id à partir de _blockStack. Or cette variable est privée.

Proposition de modification :

'public $_blockStack = array ();'

au lieu de

'private $_blockStack = array ();'

ligne 114 lib/jelix/tpl/jTPLCompiler.class.php

Attachments

patch.txt (406 bytes) - added by flav 3 years ago.
block.mloop.php (2.2 KB) - added by flav 3 years ago.
plugin de template ayant besoin du blockstack
cfunction.mloop_recursive.php (945 bytes) - added by flav 3 years ago.

Change History

Changed 3 years ago by flav

comment:1 Changed 3 years ago by flav

  • Component changed from jelix to jelix:tpl

comment:2 follow-up: ↓ 4 Changed 3 years ago by laurentj

  • Status changed from new to confirmed

Je préfère une méthode qui permet de renvoyer le dernier élément de blockstack.

comment:3 Changed 3 years ago by laurentj

et si possible (sauf si tu ne connais pas git) passer par github - pull request pour proposer un patch...

comment:4 in reply to: ↑ 2 Changed 3 years ago by flav

Replying to laurentj:

Je préfère une méthode qui permet de renvoyer le dernier élément de blockstack.

Dans mon cas ça suffit pas. En fait, l'idée c'est d'avoir une clef unique pour un block de type 'loop'(ce que je suis en train de developper...). J'ai deux possibilité. Une très lourde : générer une clef. Ou mieux : récupérer l'intégralité du blockstack pour le sérialiser et le hasher. Si je récupère que le dernier, ma clef est toujours la même (md5(serialize('loop'))). Resultat : mon code marche plus...

Explications :

==============

Le plugin loop est un plugin qui produit des listes récursives et doit lui même pouvoir contenir des block loop. Je dois jouer avec le nom de fonction. La fonction contient un foreach, et une fois foreach refermé (à la fin du block), la fonction est appeller.

Pour appeller la fonction, elle doit avoir le même nom que lorsque je l'ai définie. Or si j'ai définie un autre block loop dans mon block loop, comment vais-je pouvoir récupérer le nom de la bonne fonction. Si je génère une clef pour nommer la fonction, je résouds pas le problème : je ne peux pas la récupérer.

Je penses donc que la solution la plus propre et la plus performante (et la seule) est de récupérer le blockstack. (et là ça fonctionne impécable)

Peut-être est-ce le fait d'avoir des infos qui ne sont pas forcéments utiles qui te dérange (le tableau blockstack tel quel)? Je peut faire une méthode getStackId(), c'est mieux?

Replying to laurentj:

et si possible (sauf si tu ne connais pas git) passer par github - pull request pour proposer un patch...

Je connais pas. J'vais essayer ;)

comment:5 Changed 3 years ago by laurentj

je ne comprend pas ton histoire de fonction. de quelle fonction parles-tu ? est-ce possible de voir le code source de ton plugin ?

Changed 3 years ago by flav

plugin de template ayant besoin du blockstack

Changed 3 years ago by flav

comment:6 follow-up: ↓ 10 Changed 3 years ago by flav

Quand je dis :

Peut-être est-ce le fait d'avoir des infos qui ne sont pas forcéments utiles qui te dérange
(le tableau blockstack tel quel)? Je peut faire une méthode getStackId(), c'est mieux?

je me trompe. Ca ne peut pas être getStackId() mais getStackKey(). En effet, stackBlock peut prendre la même valeur plusieur fois dans un même template. Parler d'identifiant prête alors à confusion.

C'est dur à expliquer. Je vais retenter.

Lorsqu'on veut faire de la récursivité, une méthode consiste à écrire une fonction contenant un foreach, puis d'appeller cette fonction à la fin.

Or, mon block loop est un block récursif. (lorsque je place la balise {loop_recursive} dans mon block loop).

Jusque là pas de problème. Seulement, il faut, en plus, si je le souhaite, que je puisse ajouter un block loop dans un block loop (ce n'est plus de la récursivité dont il s'agit, c'est d'une autre fonctionnalité). C'est là que le nommage de fonction pose problème...

Je doit, pour chaque block loop donner un nom spécifique à la fonction. Sinon, ma boucle ne fonctionnera pas correctement. Il y'aura confusion dès lors qu'un block loop sera contenu dans un autre block loop. Si la fonction a toujours le même nom, c'est la dernière définition de la fonction qui sera défini (car j'ai choisi d'utiliser des fonction utilisateur). Ma boucle oubliera simplement la suite de ce qu'elle devait entreprendre.

Pour nommer cette fonction j'avais au début penser qu'il suffisait de générer une clef. Alors je génère une clef, {loop} est compiler, la fonction est nommée, et puis {/loop} est compilé, et là, je dois appeller la fonction, mais... Je ne peux pas récupérer son nom. A moins de refaire un blockstack spécifique aux block loop. Or il y'a déjà un blockStack, je suis donc plus tenté de l'utiliser...

comment:7 Changed 3 years ago by flav

En fait, le principe que je reproduit c'est ça : http://www.spip.net/fr_article914.html

comment:8 Changed 3 years ago by flav

Sauf qu'au lieu de ça :

<BOUCLE_forum(FORUMS){id_article}>
   #TITRE
   <B_reponses>
   <UL>
   <BOUCLE_reponses(FORUMS){id_parent}>
      <LI>#TITRE
      <BOUCLE_recursive(BOUCLE_reponses)>
      </BOUCLE_recursive>
      </LI>
   </BOUCLE_reponses>
   </UL>
   </B_reponses>
</BOUCLE_forum>

On a un truc comme ça

<ul>
{loop '$varName(jDao)->$element', array('name'=>'forums')}
   <li>{display_value $element, 'titre'}
   <!-- Valeur réelle de titre : {$element->titre} -->
      <ul>
      {loop_recursive}
      </ul>
   </li>
</ul>
{/loop}

comment:9 Changed 3 years ago by flav

(finalement le pull request, je sais pas encore m'en servir, ça a l'air pratique, mais ça a pas l'air de se comprendre en 5 minutes...je me sens pas apte à le faire pour l'instant :/ )

comment:10 in reply to: ↑ 6 Changed 3 years ago by flav

Replying to flav:

Alors je génère une clef, {loop} est compiler, la fonction est nommée, et puis {/loop} est compilé, et là, je dois appeller la fonction, mais... Je ne peux pas récupérer son nom. A moins de refaire un blockstack spécifique aux block loop. Or il y'a déjà un blockStack, je suis donc plus tenté de l'utiliser...

Et si je voulais faire un blockStack spécifique à mes blocks loop, je serais obligé de le stocker dans une variable global! (TRES SALE!) :/

Du coup je vois que 3 solutions :

public $_blockStack = array ();

ou :

getBlockStack() {return $this->_blockStack;}   // Garantie qu'on écrira pas dans le blockStack

ou :

getStackKey() {return md5(serialize($this->_blockStack));}    // Le moins d'informations possibles transmises.

comment:11 Changed 3 years ago by flav

J'ai parlé un peu vite. Je pense que l'idéal c'est ça :

    /**
     * for plugins, it return the number of blocks containing the current block.
     * @return int value, number of blocks.
     */
    public function getBlockStackingLevel()	{
		return count($this->_blockStack);
	}

Plus simple, plus performant, et ça fonctionne!

comment:12 Changed 3 years ago by laurentj

tu n'as même pas besoin de faire ça. met une variable dans le tableau _privateVars de jTpl (le plugin form l'utilise si je me souviens bien), que tu incrementes quand le block commence, et que tu décrementes quand il se termine. Tu te génères ainsi ton propre compteur d'imbrication, et que tu peux accéder à partir de ton plugin looprecursive.

comment:13 Changed 3 years ago by flav

J'y ai pensé mais l'objet jTpl $t n'est disponible que pour le code compilé. Or c'est avant la compilation que j'en ai besoin.

Quoiqu'après réflexion c'est vrai que ça doit pas être impossible en utilisant le nommage dynamique de variables (parce qu'il y'a aussi des variables à nommer) et de fonction, mais mon code deviendrait complètement illisible... Et il est déjà pas facile à lire.

comment:14 Changed 3 years ago by flav

Non, je délire un peu, c'est pas un petit dollard de plus dans les noms de variables qui va complexifier les choses. Je vais essayer, quand j'aurais réussi je fermerais ce ticket (on sait jamais).

Merci pour ton aide ;)

comment:15 Changed 3 years ago by flav

Je n'y parviens pas, et je pense que c'est impossible. Tout ce passe bien pour la récursivité, mais si par malheur je place un block loop dans un autre block loop, rien ne va plus. Le nommage des variable et des fonctions doit forcément s'effectuer avant la compilation. L'utilisation d'un compteur d'imbrication et du nommage dynamique n'y changent rien, et alourdissent considérablement un code déjà difficile à lire. Je devrais utiliser une variable globale si ce ticket est refusé... :/

Note: See TracTickets for help on using tickets.