[spip-dev] Problème avec foreach($boucles as $id => $boucle)

Bonjour,

J'ai repéré un petit problème dans le fichier
ecrire/public/compiler.php, qui empêche le fonctionnement de certains
plugins (comme acces_restreint_v3) sur certains hébergeurs (comme
Free). Version : SPIP 2.0.0 rc1 [13266]
Dans la fonction public_compiler_dist(), on a :

    foreach($boucles as $id => $boucle) {
        $boucle = pipeline('pre_boucle', $boucle);
        ...
    }

Or, il semblerait que sur certains serveurs, la variable $boucle ne
soit qu'une copie locale de l'objet contenu dans $boucles, et par
conséquent, la modifier (via la fonction pipeline, ou le "$boucle =")
n'a aucun effet.

Pour simplifier le problème, j'ai exécuté le fichier PHP suivant :

<pre><?php
class Boucle { var $where = array(); }

$bouc = new Boucle;
$bouc->where[] = "where1";
$boucles = array($bouc);

foreach ($boucles as $id => $boucle) {
  $boucle->where[] = "where2";
  print_r($boucle);
  print_r($boucles);
}
?></pre>

En local sous EasyPHP, aucun problème, l'affichage obtenu est :

Boucle Object
(
    [where] => Array
        (
            [0] => where1
            [1] => where2
        )
)
Array
(
    [0] => Boucle Object
        (
            [where] => Array
                (
                    [0] => where1
                    [1] => where2
                )
        )
)

Mais sur une page perso hébergée chez Free, j'obtiens :

boucle Object
(
    [where] => Array
        (
            [0] => where1
            [1] => where2
        )
)
Array
(
    [0] => boucle Object
        (
            [where] => Array
                (
                    [0] => where1
                )
        )
)

La clause where2 qu'on a voulu ajouter à notre boucle n'a pas été
prise en compte.

Je ne sais pas si c'est lié à une certaine version de PHP ou si c'est
un bug de Free, mais cela rend très dangereux l'utilisation de la
syntaxe "foreach ($boucles as $id => $boucle)" : on ne peut pas
utiliser la variable $boucle si on compte la modifier !!

Pour corriger la fonction posant problème, il suffit de remplacer
$boucle par $boucles[$id] :

888 foreach($boucles as $id => $boucle_variable_a_ne_pas_utiliser) {
889 $boucles[$id] = pipeline('pre_boucle', $boucles[$id]);
890
891 // appeler la fonction de definition de la boucle
892 $req = $boucles[$id]->type_requete;

J'ai testé, et ça fait fonctionner le plugin acces_restreint_v3.

Mais n'étant pas expert objet PHP, ni développeur Spip, je ne connais
pas les effets de bord susceptibles de se produire et je n'ai pas osé
touché à la branche svn.
De plus, il est possible que le même problème se retrouve à d'autres
endroits ... Le même bug peut aussi se produire avec la syntaxe
"foreach ($boucles as $boucle)".

Voilà, si quelqu'un a plus d'infos je suis preneur ...
(à la réflexion, le bug de free me paraît presque trop énorme pour
être réel ... )

Bonne journée !

Etienne.

Bonjour,
tu as parfaitement raison, et c'est une des différences entre PHP4 et PHP5, le premier faisant par défaut des copies des objets, alors que le deuxieme fait des references.
Je corrige le core sur ce point.

Cédric