type_requete; list($return,$corps) = $boucle->return; // Boucle recursive : simplement appeler la boucle interieure if ($type_boucle == 'boucle') { return ("$corps\n\treturn $return;"); } $texte = ''; $lang_select = ($boucle->lang_select != "non") && ($type_boucle == 'articles' OR $type_boucle == 'rubriques' OR $type_boucle == 'hierarchie' OR $type_boucle == 'breves'); // enrichissement du corps de boucle $flag_parties = ($boucle->partie AND $boucle->total_parties); $flag_cpt = $flag_parties || # pas '$compteur' à cause du cas 0 strpos($corps,'compteur_boucle') || strpos($return,'compteur_boucle'); $corps = ((!$flag_cpt) ? "" : "\n\t\t\$compteur_boucle++;") . ((!$flag_parties) ? "" : ' if ($compteur_boucle >= $debut_boucle AND $compteur_boucle <= $fin_boucle) {') . (((!$lang_select)||(!$corps)) ? "" : (' if ($x = $PileRow[$SP]["lang"]) $GLOBALS["spip_lang"] = $x;')) . ((!$boucle->doublons) ? "" : ("\n\t\t\$id_doublons['" . $boucle->doublons . "'] .= ','.\$PileRow[\$SP]['". $table_primary[$type_boucle]. "'];")) . $corps . (($return == "''") ? "" : ((!$boucle->separateur) ? ("\n\t\t" . '$t0 .= ' . $return . ";") : ("\n\t\t" . '$t1 = ' . $return . ";\n\t\t" . '$t0 .= (($t1 && $t0) ? \'' . $boucle->separateur . "' : '') . \$t1;"))). ((!$flag_parties) ? "" : "\t\t}\n"); // Recherche : recuperer les hash a partir de la chaine de recherche if ($boucle->hash) { $texte .= ' global $recherche, $hash_recherche; if (!$hash_recherche) $hash_recherche = requete_hash($recherche);';} if ($type_boucle == 'forums') $texte .= "\n\tcache_forum(" . index_pile($id_boucle, 'id_article') . ", " . index_pile($id_boucle, 'id_rubrique') . ", " . index_pile($id_boucle, 'id_breve') . ", " . index_pile($id_boucle, 'id_forum') . ");"; if ($type_boucle == 'hierarchie') { $texte .= ' $hierarchie = construire_hierarchie(' . ($boucle->tout ? $boucle->tout : // sinon, paramètre passé par include. // même code, mais à inexécutable à la compilation: '(($PileRow[0]["id_article"] || $PileRow[0]["id_sndic"]) ? $PileRow[0]["id_rubrique"] : $PileRow[0]["id_parent"])') . ");"; } return ($texte . ' $t0 = "' . calculer_requete($id_boucle) . '"; if (!($result = @spip_query($t0))) { include_local("inc-debug-squel.php3"); return erreur_requete_boucle($t0, "' . $id_boucle . '", "'. $type_boucle . '"); } $t0 = ""; $SP++;' . ((!$flag_parties) ? ((!$boucle->numrows) ? '' : ' $PileNum[$SP] = @spip_num_rows($result);') : (' $fin_boucle = @spip_num_rows($result);' . (($boucle->mode_partie == '/') ? (' $debut_boucle = 1+floor(($fin_boucle * ' . ($boucle->partie - 1) . ' + ' . ($boucle->total_parties - 1) . ')/' . $boucle->total_parties . ");\n\t" . '$fin_boucle = floor(($fin_boucle * ' . $boucle->partie . ' + ' . ($boucle->total_parties - 1) . ')/' . $boucle->total_parties . ");") : (($boucle->mode_partie == '+') ? (' $debut_boucle = ' . $boucle->partie . '; $fin_boucle -= ' . $boucle->total_parties) : (' $debut_boucle = $fin_boucle - ' . $boucle->partie . '; $fin_boucle -= ' . ($boucle->partie - $boucle->total_parties)) . ';')) . ' $PileNum[$SP] = $fin_boucle - $debut_boucle + 1;')) . ((!$flag_cpt) ? '' : "\n\t\$compteur_boucle = 0;") . ((!$corps) ? "" : ( ((!$lang_select) ? "" : ' $old_lang = $GLOBALS[\'spip_lang\'];') . ' while ($PileRow[$SP] = @spip_fetch_array($result)) {' . $corps . "\n\t}" . ((!$lang_select) ? "" : ' $GLOBALS["spip_lang"] = $old_lang;'))) . " @spip_free_result(\$result); \$SP--; return \$t0;"); } // Generer le code PHP correspondant a une liste d'objets syntaxiques function calculer_liste($tableau, $prefix, $id_boucle, $niv) { global $champs; if (!$tableau) return array("''",''); $texte = ''; $exp = ""; $firstset = true; $t = '$t' . ($niv+1); reset($tableau); while (list(, $objet) = each($tableau)) { if ($objet->type == 'texte') { $c = calculer_texte($objet->texte, $id_boucle); $exp .= (!$exp ? $c : (" .\n\t\t$c")); } else { if ($objet->type == 'boucle') { list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, $objet->id_boucle, $niv+2); list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, $objet->id_boucle, $niv+2); list($oc,$om) = calculer_liste($objet->cond_altern, $prefix, $objet->id_boucle, $niv+1); $c = $prefix.$objet->id_boucle.'()'; $m = ""; } else { list($c,$m) = calculer_champ($champs[$objet->id_champ]->fonctions, $champs[$objet->id_champ]->nom_champ, $id_boucle); list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, $id_boucle, $niv+2); list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, $id_boucle, $niv+2); $oc = "''"; $om = ""; } // traitement commun des champs et boucles. // Produit: // m ; if (Tniv+1 = v) // { bm; Tniv+1 = $bc . Tniv+1; am; Tniv+1 .= $ac } // else { om; $Tniv+1 = $oc } // Tniv .= Tniv+1 // Optimisations si une au moins des 4 séquences $*m est vide if ($m) { // il faut achever le traitement de l'exp précédente if ($exp) { $texte .= "\n\t\t\$t$niv " . (($firstset) ? "=" : ".=") . "$exp;$m" ; $firstset = false; $exp = ""; } else { $texte .= $m;} } if (!($bm || $am || $om)) { // 3 séquences vides: 'if' inutile $a = (($bc == "''") ? "" : "$bc .") . $t . (($ac == "''") ? "" : " . $ac"); // s'il y a un avant ou un après ou un alternant, il faut '?' if (($a != $t) || ($oc != "''")) $c = "(($t = $c) ? (" . $a . ") : ($oc))"; $exp .= (!$exp ? $c : (" .\n\t\t$c")); } else { // il faut achever le traitement de l'exp précédente if ($exp) { $texte .= "\n\t\t\$t$niv " . (($firstset) ? "=" : ".=") . "$exp;$m" ; $firstset = false; $exp = ""; } else { $texte .= $m;} $texte .= "\n\t\tif ($t = $c) {\n" . $bm; $texte .= "\n\t\t$t = $bc . $t"; if (!$am) { $texte .= " . $ac"; } else $texte .= "; $am $t .= $ac"; $texte .= ";}"; if (!$om) { $texte .= " else {" . $om . "$t = $oc;}"; } $exp = $t; } } } // while if (!$exp) $exp ="''"; return (!$texte ? array ($exp, "") : array('$t'.$niv. ". $exp",$texte)); } // Phraser le pseudo .html puis traduire en PHP // $contexte n'est utilisé que pour controler que les variables PHP // demandées dans le squelette figureront effectivement dans REQUEST_URI // ou le squelette incluant function calculer_squelette($squelette, $fichier, $contexte) { global $boucles, $from_request, $boucle_courante; $boucles = ''; $from_request= $contexte; $racine = parser(join(file("$squelette.html"), "")); $squelette_nom = ereg_replace("[^a-zA-Z0-9_]", "_", $squelette); $func = 'squelette_'.$squelette_nom.'_executer'; $prefix = $func.'_boucle'; // Calculer le code PHP de la racine $boucle_courante = ''; list($return,$corps) = calculer_liste($racine, $prefix, $boucle_courante,0); // calculer les corps des boucles PHP if ($boucles) { foreach($boucles as $id => $boucle) { $boucle_courante = $id; calculer_params($boucle->type_requete, $boucle->param, $id); $boucles[$id]->return = calculer_liste(($boucle->type_requete == 'boucle') ? array($boucles[$boucle->param]) : $boucle->milieu, $prefix, $id, 1); } // En déduire le corps de toutes les fonctions PHP, // en particulier les requetes SQL déterminables seulement maintenant foreach($boucles as $id => $boucle) { $boucles[$id]->return = calculer_boucle($id); } } $f = fopen($fichier, "wb"); $define = strtoupper("_SKEL_$squelette_nom"); fwrite($f, "<"."?php\n\n"); fwrite($f, "\$func_squelette_executer = '$func';\n\n"); fwrite($f, "if (defined(\"$define\")) return;\n"); fwrite($f, "define(\"$define\", \"1\");"); if ($boucles) { foreach($boucles as $id => $boucle) { sauve_fonction($f, "$prefix$id()", $boucle->return); } } sauve_fonction($f, "$func(\$contexte)", " \$SP = 0; \$PileRow[0] = \$contexte;" . $corps . "\n\treturn $return;\n"); fwrite($f, '?'.'>'); fclose($f); } function sauve_fonction($f, $nom, $corps) { fwrite($f, "\n\nfunction $nom { global \$SP, \$PileRow, \$PileNum, \$id_doublons, \$rubriques_publiques;\n"); fwrite($f, $corps); fwrite($f, "\n}\n"); } ?>