[spip-dev] bug compilation ?

SPIP svn me dit ceci avec un squelette qui fonctionnait sur la version
d'il y a une semaine :

        Parse error: syntax error, unexpected '(', expecting ')'
        in /home/urbagora/urbagora.be/www/ecrire/public/composer.php(66) : eval()'d code on line 27

        Erreur(s) dans le squelette
        1 Erreur sur le site boucle critère inconnu id_rubrique
        2 Erreur de compilation squelettes/inc/header.html

Le squelette incriminé est ici :
http://urbagora.be/squelettes/inc/header.html

François

Voilà la boucle qui bloque (le critère {id_article} sur une boucle
DOCUMENTS, semble-t-il) :

  <BOUCLE_entetes(DOCUMENTS){id_article=1497}{par hasard}{0,1}>

L'autre erreur vient d'un plugin.

François

Désolé:

http://trac.rezo.net/trac/spip/changeset/12127

Committo,Ergo:Sum

Merci. Ca fonctionne.

Une question au passage : je constate que le critère {id_rubrique} du
plugin agenda ne fonctionne plus sur la boucle EVENEMENTS. Est-ce lié à
une évolution récente dans SPIP ?

Par exemple cette boucle fonctionnait il y a une semaine :

  <BOUCLE_agenda(EVENEMENTS){id_rubrique}{par date}{age<1}>

Elle renvoie maintenant le message d'erreur suivant :

  1 Erreur sur le site boucle critère inconnu id_rubrique

François

* franz tapuscrivait, le 21/07/2008 22:57:

* franz tapuscrivait, le 21/07/2008 22:57:

Désolé:

http://trac.rezo.net/trac/spip/changeset/12127

Merci. Ca fonctionne.

Une question au passage : je constate que le critère {id_rubrique} du
plugin agenda ne fonctionne plus sur la boucle EVENEMENTS. Est-ce lié à
une évolution récente dans SPIP ?

Avec le plugin accès restreint, on a le même bug (je donne l'info pour frantz)
Parse error: syntax error, unexpected '(', expecting ')' in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(66) : eval()'d code on line 29

Avec du débug, j'arrive à :

17 static $where =
18 array(
19 array('=', 'rubriques.statut', '\'publie\''),
20 array('=', 'L2.titre',
21 // 8 signes
22 "'MenuHaut'"), AccesRestreint_rubriques_accessibles_where("rubriques.id_rubrique"));

donc, si je comprends bien, le même cas que celui en principe corrigé par http://trac.rezo.net/trac/spip/changeset/12127

function calculer_dec($nom, $val)
{
- $dyn = (strpos($val, '$') !== false OR strpos($val, 'sql_') !== false);
+ $dyn = (strpos($val, '$') !== false OR strpos($val, 'sql_') !== false OR strpos($val, 'AccesRestreint_') !== false);
   return "\n\t" . ($dyn ? '' : 'static ') . $nom . ' = ' . $val . ';';
}

Résout le bug php, mais laisse le plugin accès restreint en état cassé (toutes les rubriques sont considérées comme restreintes).

??? Mais pourquoi un fork du compilateur ?
Le but ici est de réperer si une valeur est un tableau de constantes, c'est-à-dire sans aller chercher la valeur d'une variable $XXXX ou de calculer un sql_quote.
Que fait cette fonction AccesRestreint_rubriques_accessibles_where ? Elle doit pouvoir être appelée à la compilation plutot que d'être réappliquée à chaque éxécution.

Committo,Ergo:Sum

* Committo,Ergo:sum tapuscrivait, le 22/07/2008 00:04:

Avec du débug, j'arrive à :

17 static $where =
18 array(
19 array('=', 'rubriques.statut', '\'publie\''),
20 array('=', 'L2.titre',
21 // 8 signes
22 "'MenuHaut'"), AccesRestreint_rubriques_accessibles_where("rubriques.id_rubrique"));

donc, si je comprends bien, le même cas que celui en principe corrigé par http://trac.rezo.net/trac/spip/changeset/12127

function calculer_dec($nom, $val)
{
- $dyn = (strpos($val, '$') !== false OR strpos($val, 'sql_') !== false);
+ $dyn = (strpos($val, '$') !== false OR strpos($val, 'sql_') !== false OR strpos($val, 'AccesRestreint_') !== false);
return "\n\t" . ($dyn ? '' : 'static ') . $nom . ' = ' . $val . ';';
}

??? Mais pourquoi un fork du compilateur ?

Parce que c'est tout ce que j'ai su faire.
J'ai dû en faire un 2e : enlever ton optimisation avec count * en remettant le 1.
Le fork complet (seulement 2 lignes) : Connexion · GitLab

Le but ici est de réperer si une valeur est un tableau de constantes, c'est-à-dire sans aller chercher la valeur d'une variable $XXXX ou de calculer un sql_quote.
Que fait cette fonction AccesRestreint_rubriques_accessibles_where ? Elle doit pouvoir être appelée à la compilation plutot que d'être réappliquée à chaque éxécution.

C'est une bonne question. Malheureusement, ça dépasse ma compétence.
La surcharge des boucles est faite ici : Connexion · GitLab

Et la fonction est ici :

Si tu vois comment optimiser (et réparer le plugin qui ne marche pas avec le count *)... N'hésite pas :wink:

??? Mais pourquoi un fork du compilateur ?

Parce que c'est tout ce que j'ai su faire.
J'ai dû en faire un 2e : enlever ton optimisation avec count * en remettant le 1.

pourquoi ?

Que fait cette fonction AccesRestreint_rubriques_accessibles_where ? Elle doit pouvoir être appelée à la compilation plutot que d'être réappliquée à chaque éxécution.

C'est une bonne question. Malheureusement, ça dépasse ma compétence.

bah faut pas se lancer dans un patch du compilateur si on ne le comprend pas.

Si tu vois comment optimiser

débrouille toi pour que "sql_in(..." apparaisse dans le code compilé ça suffira.

Committo,Ergo:Sum

* Committo,Ergo:sum tapuscrivait, le 22/07/2008 00:27:

??? Mais pourquoi un fork du compilateur ?

Parce que c'est tout ce que j'ai su faire.
J'ai dû en faire un 2e : enlever ton optimisation avec count * en remettant le 1.

pourquoi ?

Pour une raison que j'ignore, avec le count *, c'est toutes les rubriques du site qui sont considérées en accès restreint.

Que fait cette fonction AccesRestreint_rubriques_accessibles_where ? Elle doit pouvoir être appelée à la compilation plutot que d'être réappliquée à chaque éxécution.

C'est une bonne question. Malheureusement, ça dépasse ma compétence.

bah faut pas se lancer dans un patch du compilateur si on ne le comprend pas.

C'est bien pour ça que c'est un hack et non un patch :wink:

Si tu vois comment optimiser

débrouille toi pour que "sql_in(..." apparaisse dans le code compilé ça suffira.

Merci pour la piste.

Merci.

Cela dit, je n'ai pas compris la raison de cette régression (car c'en
est bien une il me semble : cet usage était admis dans la passé) qui
risque de poser quelques problèmes, il me semble.

Au passage, je me dis qu'il serait vraiment bien de faire des EVENEMENTS
des objets à part entière, situés dans l'arborescence et dotés de tout
l'attirail des autres objets (logos, mots-clés,...) plutôt que des
sous-éléments des articles, ce qui est fort déconcertant.

François

Non, pas du tout :
la liste des zones restreintes peut etre modifiees dans l'admin, et cela doit etre pris en compte sans necessiter de recompiler les squelettes.

Conceptuellement ton optimisation pose un vrai probleme, car elle considère invariant uniquement ce qui contient une variable, mais ignore les fonctions, qui ne sont pas forcement invariantes.
L'idée est bonne, mais il me semble qu'elle meriterait un peu plus de recul.

Cédric

la liste des zones restreintes peut etre modifiees dans l'admin, et cela
doit etre pris en compte sans necessiter de recompiler les squelettes.

Je dirais même plus, elle peut être calculée à la volée en fonction de
ta session (selon la géolocalisation de ton numéro IP par exemple).

-- Fil

- ou alors il faut un marqueur sur la boucle pour signaler de ne pas l'optimiser en static, sauf que la ou l'optimisation est faite, on n'a plus cette info.
- ou cela oblige à ecrire en deux temps avec un hash, ou ($toto=AccesRestreint_rubriques_accessibles_where("rubriques.id_rubrique")) juste pour que le compilo se prenne pas les pieds dans le tapis.
- ou à définir un repere dans le nom de la fonction pour ce genre de cas test

Le but ici est de réperer si une valeur est un tableau de constantes, c'est-à-dire sans aller chercher la valeur d'une variable $XXXX ou de calculer un sql_quote.
Que fait cette fonction AccesRestreint_rubriques_accessibles_where ? Elle doit pouvoir être appelée à la compilation plutot que d'être réappliquée à chaque éxécution.

Non, pas du tout :
la liste des zones restreintes peut etre modifiees dans l'admin, et cela doit etre pris en compte sans necessiter de recompiler les squelettes.

Conceptuellement ton optimisation pose un vrai probleme, car elle considère invariant uniquement ce qui contient une variable,

Non pas du tout :wink:

mais ignore les fonctions, qui ne sont pas forcement invariantes.

Oui, j'en tiens compte mais le problème est justement de savoir repérer celle qui sont exécutables à la compil et les autres.
On tombe ici sur l' absence de Macro en PHP, une des marques de l'amateurisme de sa conception.

Actuellement, pour définir ces variables donnant les clauses de la requête, ne soient utilisées comme fonctions non exécutables à la compil que celles de l'interface SPIP-SQL, c'est-à-dire commençant par sql_ (donc en pratique sql_quote et sql_in, je ne vois pas autre chose à première vue).

Si on ne veut pas se plier à ça, il suffit d'utiliser une variable supplémentaire, c'est-à-dire au lieu de produire

$boucle->where = foo();

on produit

$boucle->where = $init_where;
et on met "$init_where = foo();" en début de code (par exemple dans boucle->in ça devrait le faire).

Committo,Ergo:Sum

Attention, vous n'avez pas bien vu la problématique ici: l'invariance concerne la durée de chaque exécution du squelette, pas la durée de vie du squelette.
Comme le disait le message du dépot (hum hum) l'optimisation n'a d'intérêt que pour les boucles imbriquées ou récursives, c'est ici qu'on veut de l'invariance, pas entre 2 exécutions du squelette.

Committo,Ergo:Sum

* cedric.morin@yterium.com tapuscrivait, le 22/07/2008 10:48:

Non, pas du tout :
la liste des zones restreintes peut etre modifiees dans l'admin, et cela doit etre pris en compte sans necessiter de recompiler les squelettes.

Et si on se contentait de rajouter un $GLOBALS['marqueur'] sur le MD5 de la liste des rubriques concernées par l'accès restreint ?

les gros mots sont interdits sur cette liste.

Committo,Ergo:Sum

oui, mais en première objection tu demandais pourquoi la fonction n'était pas calculée à la compilation, d'où la réponse.
Si j'ai bien tout compris, je retiens donc en substance que :
conceptuellement cela marcherait si php ne plantait pas lamentablement sur les expressions du type
static $var = fonction_init();
Tu as contourné en detectant la présence des fonctions ajoutées par le core qui sont toutes de la forme sql_xxx, mais tu coup, si un plugin ajoute une fonction dans une clause where(), le compilo génère du code php pas executable.

Il faut peut être juste decomposer l'écriture pour qu'elle passe partout :
static $where = null;
if (!$where) $where = ...;

Cédric

comme une cautère sur une jambe de bois ?