[spip-dev] un filtre |set ?

Salut,

à l’usage, le fait de devoir faire
[(#SET{toto,[(#BALISE|calculs…|filtres…)]})]

est parfois un peu lourdingue, à cause notamment des tas de crochets qu’il faut saisir, et j’ajouterais bien à SPIP la possibilité de coder la même chose sous la forme d’un filtre final :

[(#BALISE|calculs…|filtres…|set{toto})]

Le code est simple, mais ce n’est pas juste un filtre qu’on peut installer dans mes_fonctions.php ; en effet, ça demande une exception dans public/references.php (ligne 447 du plugin itérateurs, par exemple) :

// le filtre |set a besoin d’acceder a la $Pile
// proto: filtre_set($val, &$Pile, $args…)
elseif (in_array($fonc, array(‘set’))
AND $f = chercher_filtre($fonc)) {
$code = “$f($code,$Pile$arglist)”;
}

J’ai mis l’exception sous forme d’un in_array() histoire de pouvoir facilement l’étendre, si besoin.

Votre avis, sur la fonctionnalité ou le code/prototype de la fonction ?

Par ailleurs je me demande si |set{} doit vider le résultat ou non, ou encore le vider par défaut et avoir une option/une variante pour continuer à afficher le résultat.

PS: Si vous voulez tester, outre le patch ci-dessus, le code suivant est à ajouter dans mes_fonctions.php

function filtre_set($val, &$Pile, $key) {
$Pile[‘vars’][$key] = $val;
return ‘’; # vider le résultat
}

– Fil

Est ce que l'on peut immaginer un filtre qui viderai le résultat:
ce qui permettrait d'avoir :
[(#BALISE|calculs....|filtres...|set{toto}|vider)] pour laisser le
choix.

En fait, si on veut afficher le résultat, on peut toujours utiliser
#GET{toto} après.

Bonne journée
Grégoire

Est ce que l'on peut immaginer un filtre qui viderai le résultat:
ce qui permettrait d'avoir :
[(#BALISE|calculs....|filtres...|set{toto}|vider)] pour laisser le
choix.

oui |vider existe déjà ; mais |set{toto} devrait sans doute vider quand même

En fait, si on veut afficher le résultat, on peut toujours utiliser
#GET{toto} après.

L'idée est de pouvoir faire un "set and continue" pour faire par exemple :
[(#BALISE|set_and_continue{brut}|replace{\W}|set_and_continue{nettoye}|...)]

Mais peut-être que ce serait alors |set{brut,continue}|............

-- Fil

sur suggestion (irc) de marcimat, j'ai ressayé de recoder la chose avec un
réflecteur :

            elseif ($f = chercher_filtre($fonc)) {
                $refs = (new ReflectionFunction($f))->getParameters();
                switch(true) {
                    case $refs[0]->name == 'Pile':
                        $code = "$f(\$Pile,$code$arglist)";
                        break;
                    case $refs[1]->name == 'Pile':
                        $code = "$f($code,\$Pile$arglist)";
                        break;
                    case $refs[count($refs)-1]->name == 'Pile':
                        $code = "$f($code$arglist,\$Pile)";
                        break;
                    default:
                        $code = "$f($code$arglist)";
                        break;
                }
            }

C'est vrai que c'est joli, sympa mais hélas ça ferait sauter la
compatibilité PHP 4.4.4 qu'on annonce encore pour SPIP 2.1. A voir ce qu'on
veut faire pour SPIP 3. Du coup j'ai commité dans SPIP 2.1, ce qui n'est
pas idéal :slight_smile:

Pour répondre à l'autre question, |set{x} va enregistrer la valeur dans x
et vider, et |set{x,continue} enregistre et affiche la valeur.

J'en profite même si ça n'a rien à voir pour ajouter un filtre |debug qui
logue la valeur qu'on lui passe dans debug.log, et l'affiche en direct si
on est webmestre. Très utile pour observer une valeur lors de la mise au
point d'un squelette.

Usage :
      [(#TRUC|debug{avant}|calcul|debug{apres}|etc)]

affichera :
   'avant' = 'truc'
   'après' = 'truc calculé'

-- Fil

sur suggestion (irc) de marcimat, j'ai ressayé de recoder la chose avec
un réflecteur :

             elseif ($f = chercher_filtre($fonc)) {
                 $refs = (new ReflectionFunction($f))->getParameters();
                 switch(true) {
                     case $refs[0]->name == 'Pile':
                         $code = "$f(\$Pile,$code$arglist)";
                         break;
                     case $refs[1]->name == 'Pile':
                         $code = "$f($code,\$Pile$arglist)";
                         break;
                     case $refs[count($refs)-1]->name == 'Pile':
                         $code = "$f($code$arglist,\$Pile)";
                         break;
                     default:
                         $code = "$f($code$arglist)";
                         break;
                 }
             }

C'est vrai que c'est joli, sympa mais hélas ça ferait sauter la
compatibilité PHP 4.4.4 qu'on annonce encore pour SPIP 2.1. A voir ce
qu'on veut faire pour SPIP 3. Du coup j'ai commité dans SPIP 2.1, ce qui
n'est pas idéal :slight_smile:

Pour info, il y a une autre possibilité pour de tester la chose, en utilisant directement ReflectionParameter. Ce n'est pas forcément mieux, mais c'est juste pour montrer un exemple :

<?php

function test($me, $Pile, $toto = '') {}
function test2($me, $toto = '') {}

$func = 'test';

foreach (array('test', 'test2') as $func) {
  try {
    $param = new ReflectionParameter($func, 'Pile');
    $pos = $param->getPosition();

    echo "$func a \$Pile en position $pos<br />\n";

  } catch (Exception $e) {
    // paramètre $Pile introuvable
    echo "$func n'a pas \$Pile<br />\n";
  }
}

?>

[...]

J'en profite même si ça n'a rien à voir pour ajouter un filtre |debug
qui logue la valeur qu'on lui passe dans debug.log, et l'affiche en
direct si on est webmestre. Très utile pour observer une valeur lors de
la mise au point d'un squelette.

Usage :
[(#TRUC|debug{avant}|calcul|debug{apres}|etc)]

affichera :
    'avant' = 'truc'
    'après' = 'truc calculé'

Ah, c'est pas sot ça… Ça peut être pratique tout plein !

MM.

est ce que l'on ne va pas créer des confusions avec #SET{x,valeur}
mais l'idée est alléchante.

Grégoire

Un peu dans le genre je définis souvent un filtre |debug_assert
qui logue le 2eme argument dans un assert.log
si le premier = 0.
Et ça reste durablement dans le code pour détecter les situations
ou les évolutions aux conséquences imprévues .

JLuc

La suite logique : le filtre |setenv

[(#VAL{ohhhhh}|strlen|setenv{héhé})] #ENV{héhé}

  [...]

Pour répondre à l'autre question,|set{x} va enregistrer la valeur
dans x et vider, et |set{x,continue} enregistre et affiche la valeur.

Est-ce idiot de penser à une syntaxe genre |!set{x} ou |?set{x} ?
    (si c'est implémentable sans difficulté)

Est-ce idiot de penser à une syntaxe genre |!set{x} ou |?set{x} ?

c'est jamais idiot de penser :wink: mais ça voudrait faire quoi ?

   (si c'est implémentable sans difficulté)

comme ça, ce serait très difficile ; mais quelque chose du type |set_if{}
ou |unset{} pourrait fonctionner

-- Fil

Bonjour Fil,

>
> Est-ce idiot de penser à une syntaxe genre |!set{x} ou

?set{x} ?

>
> c'est jamais idiot de penser :wink: mais ça voudrait faire quoi ?
C'etait pour proposer une solution de contournement : reprendre
> Par ailleurs je me demande si |set{} doit vider le résultat ou non, ou encore le vider par défaut et avoir une option/une variante pour continuer à afficher le résultat.
Pour répondre à l'autre question,|set{x} va enregistrer la valeur
dans x et vider, et |set{x,continue} enregistre et affiche la valeur.

> est ce que l'on ne va pas créer des confusions avec #SET{x,valeur}
>
> (si c'est implémentable sans difficulté)
>
> comme ça, ce serait très difficile ; mais quelque chose du type

set_if{} ou |unset{} pourrait fonctionner

Différences cognitives d'interpretation du "? " : je pensais plutot au sens 'echo' qu'au sens 'if'
> -- Fil
Donc |set{x} et |set_p{x}

PS je veux bien volontiers rajouter les docs dans spip.net, mais faudra aussi que ce soit relu avant publication..

PPS : y'a-t-il une possibilité simple de rajouter un comportement
    "duplicator-in-place" pour préparer une modification d'un article existant,
     publié par un rédacteur et respectant le work-flow normal
     mais qui ne perde pas tous les référencements ( id_article [->NN] et URLs publiques ?
   /je ne maitrise pas assez les tenants des #AUTORISER internes pour savoir faire /

Merci

Salut YannX,

>
> Est-ce idiot de penser à une syntaxe genre |!set{x} ou |?set{x} ?
>
> c'est jamais idiot de penser :wink: mais ça voudrait faire quoi ?
C'etait pour proposer une solution de contournement : reprendre

Heu, je n'ai rien compris à ta réponse.

> Par ailleurs je me demande si |set{} doit vider le résultat ou non, ou
encore le vider par défaut et avoir une option/une variante pour continuer
à afficher le résultat.
Pour répondre à l'autre question,|set{x} va enregistrer la valeur
dans x et vider, et |set{x,continue} enregistre et affiche la valeur.

> est ce que l'on ne va pas créer des confusions avec #SET{x,valeur}
>
> (si c'est implémentable sans difficulté)
>
> comme ça, ce serait très difficile ; mais quelque chose du type
>set_if{} ou |unset{} pourrait fonctionner
Différences cognitives d'interpretation du "? " : je pensais plutot au
sens 'echo' qu'au sens 'if'
> -- Fil
Donc |set{x} et |set_p{x}

c'est quoit set_p() ? 'p' pour 'print' ?
Tu as un cas concret où ça serait intéressant ?

PS je veux bien volontiers rajouter les docs dans spip.net, mais faudra
aussi que ce soit relu avant publication..

PPS : y'a-t-il une possibilité simple de rajouter un comportement
   "duplicator-in-place" pour préparer une modification d'un article
existant,
    publié par un rédacteur et respectant le work-flow normal
    mais qui ne perde pas tous les référencements ( id_article [->NN] et
URLs publiques ?
  /je ne maitrise pas assez les tenants des #AUTORISER internes pour
savoir faire /

ça je ne pense pas que ce soit possible. Il faut préparer le futur article
et copier/coller dans l'ancien si tu veux garder les bons liens. C'est un
inconvénient du mécanisme de statut "publié" qui ne peut revenir en "publié
mais en cours de modification" -- même si ça pourrait se gérer assez
facilement avec les versions des articles, je pense.

Merci Gilles. d'avoir clarifié.
Y a tout de même un mode 'triche' : créer une traduction de l'article dans la même langue.

MM.