diff --git a/inc-arg-squel.php3 b/inc-arg-squel.php3 index 02704bba603031cd4b74b38064555b437a0f0b2a..87797b1403d543644fd802bb4c85cd0cd9ff84ff 100644 --- a/inc-arg-squel.php3 +++ b/inc-arg-squel.php3 @@ -26,10 +26,9 @@ function calculer_params($idb, &$boucles) { $params2[]=$param; $params = $params2; - $boucle->hierarchie = ' - $hierarchie = calculer_hierarchie(' + $boucle->hierarchie = '$hierarchie = calculer_hierarchie(' .calculer_argument_precedent($idb, 'id_rubrique', $boucles) - .", false);\n"; + .', false);'; } diff --git a/inc-calcul-squel.php3 b/inc-calcul-squel.php3 index deb7fc980b4bff4beaa2cd370a3ce6237e7d9c9e..76f1e10e9695198e986e98cfbe57d18e5cc106b6 100644 --- a/inc-calcul-squel.php3 +++ b/inc-calcul-squel.php3 @@ -1,9 +1,10 @@ <?php + // Ce fichier ne sera execute qu'une fois if (defined("_INC_CALCUL_SQUEL")) return; define("_INC_CALCUL_SQUEL", "1"); -# Fichier principal du compilateur de squelettes, incluant tous les autres. +// Fichier principal du compilateur de squelettes, incluant tous les autres. include_local("inc-bcl-squel.php3"); include_local("inc-arg-squel.php3"); @@ -16,27 +17,21 @@ include_local("inc-index-squel.php3"); include_local("inc-text-squel.php3"); include_local("inc-debug.php3"); -# Produit le corps PHP d'une boucle Spip, -# essentiellement une boucle while (ou une double en cas de hierarchie) -# remplissant une variable $t0 retourne'e en valeur +// Produit le corps PHP d'une boucle Spip, +// essentiellement une boucle while (ou une double en cas de hierarchie) +// remplissant une variable $t0 retourne'e en valeur -function calculer_boucle($id_boucle, &$boucles) -{ - global $table_primary, $table_des_tables; +function calculer_boucle($id_boucle, &$boucles) { + global $table_primary, $table_des_tables; $boucle = &$boucles[$id_boucle]; $type_boucle = $boucle->type_requete; - list($return,$corps) = $boucle->return; + list($return,$corps) = $boucle->return; // Boucle recursive : simplement appeler la boucle interieure - if ($type_boucle == 'boucle') - { - return ("$corps\n\treturn $return;"); - } - - $constant = ereg("^'[^']*'$",$return); + return ("$corps\n return $return;"); // La boucle doit-elle selectionner la langue ? // 1. par defaut @@ -53,124 +48,162 @@ function calculer_boucle($id_boucle, &$boucles) if ($lang_select) $boucle->select[] = (($id_table = $table_des_tables[$type_boucle]) ? $id_table.'.' : '') .'lang'; - $flag_parties = ($boucle->partie AND $boucle->total_parties); - $flag_cpt = $flag_parties || # pas '$compteur' a` cause du cas 0 - strpos($corps,'compteur_boucle') || - strpos($return,'compteur_boucle'); + // Qui sommes-nous ? $primary_key = $table_primary[$type_boucle]; -# invalidation des caches si c'est une boucle SPIP, non constante de surcroit + // Calculer les invalideurs si c'est une boucle non constante + $constant = ereg("^'[^']*'$",$return); if ((!$primary_key) || $constant) - $invalide = ''; - else - { - $id_table = $table_des_tables[$type_boucle]; - $boucle->select[] = "$id_table.$primary_key"; - - if ($primary_key == 'id_forum') - $invalide = 'include_ecrire("inc_forum.php3");'; - $invalide .= ' - $Cache["' . $primary_key . '"][' . - (($primary_key != 'id_forum') ? - ('$Pile[$SP]["' . $primary_key . '"]') : - ('calcul_index_forum(' . -# Retournera 4 [$SP] mais force la demande du champ au serveur SQL - index_pile($id_boucle, 'id_article', $boucles) . ',' . - index_pile($id_boucle, 'id_breve', $boucles) . ',' . - index_pile($id_boucle, 'id_rubrique', $boucles) .',' . - index_pile($id_boucle, 'id_syndic', $boucles) . ')')) . - '] = 1;'; - } - $debut = - ((!$flag_cpt) ? "" : "\n\t\t\$compteur_boucle++;") . - ((!$flag_parties) ? "" : ' - if ($compteur_boucle >= $debut_boucle AND - $compteur_boucle <= $fin_boucle) {') . - (((!$lang_select)||($constant)) ? "" : (' - if ($x = $Pile[$SP]["lang"]) $GLOBALS["spip_lang"] = $x;')) . - $invalide . - ((!$boucle->doublons) ? "" : - ("\n\t\t\$doublons['$type_boucle'] .= ','. " . - index_pile($id_boucle, $primary_key, $boucles) . - ";")) ; - $corps = $debut . $corps . - ((!$boucle->separateur) ? - (($constant && !$debut) ? $return : ("\n\t\t" . '$t0 .= ' . $return . ";")) : - ("\n\t\t" . '$t1 = ' . $return . ";\n\t\t" . - '$t0 .= (($t1 && $t0) ? \'' . $boucle->separateur . - "' : '') . \$t1;")). - ((!$flag_parties) ? "" : "\t\t}\n"); - - - // Initialisation du $texte - $texte = ''; + $invalide = ''; + else { + $id_table = $table_des_tables[$type_boucle]; + $boucle->select[] = "$id_table.$primary_key"; + + $invalide = "\n \$Cache['$primary_key']"; + if ($primary_key != 'id_forum') + $invalide .= "[\$Pile[\$SP]['$primary_key']] = 1;"; + else + $invalide .= "[calcul_index_forum(" . + // Retournera 4 [$SP] mais force la demande du champ a MySQL + index_pile($id_boucle, 'id_article', $boucles) . ',' . + index_pile($id_boucle, 'id_breve', $boucles) . ',' . + index_pile($id_boucle, 'id_rubrique', $boucles) .',' . + index_pile($id_boucle, 'id_syndic', $boucles) . ")] = 1;"; + $invalide .= ' // invalideurs'; + } - # hack doublons documents : s'il y a quelque chose dans - # $GLOBALS['doublons_documents'], c'est que des documents ont - # ete vus par integre_image() ou autre fournisseur officiel de - # doublons : on les transfere alors vers la vraie variable + + // Cas {1/3} {1,4} {n-2,1}... + $flag_parties = ($boucle->partie AND $boucle->total_parties); + $flag_cpt = $flag_parties || // pas '$compteur' a cause du cas 0 + strpos($corps,'compteur_boucle') || + strpos($return,'compteur_boucle'); + + // + // Creer le debut du corps de la boucle : + // + if ($flag_cpt) + $debut = "\n \$compteur_boucle++;"; + + if ($flag_parties) + $debut .= ' + if ($compteur_boucle >= $debut_boucle + AND $compteur_boucle <= $fin_boucle) {'; + + if ($lang_select AND !$constant) + $debut .= ' + if ($x = $Pile[$SP]["lang"]) $GLOBALS["spip_lang"] = $x; // langue'; + + $debut .= $invalide; + + if ($boucle->doublons) + $debut .= "\n \$doublons['$type_boucle'] .= ','. " . + index_pile($id_boucle, $primary_key, $boucles) . "; // doublons"; + + + // + // L'ajouter au corps + // + $corps = $debut . $corps; + + // Separateur ? + if ($boucle->separateur) { + $corps .= "\n \$t1 = $return; + \$t0 .= ((\$t1 && \$t0) ? '" + . $boucle->separateur + . "' : '') + . \$t1;"; + } else if ($constant && !$debut) { + $corps .= $return; + } else { + $corps .= "\n \$t0 .= $return;"; + } + + // Fin de parties + if ($flag_parties) + $corps .= "\n }\n"; + + + // Gestion de la hierarchie (voir inc-arg-squel) + if ($boucle->hierarchie) + $texte .= "\n ".$boucle->hierarchie; + + // hack doublons documents : s'il y a quelque chose dans + // $GLOBALS['doublons_documents'], c'est que des documents ont + // ete vus par integre_image() ou autre fournisseur officiel de + // doublons : on les transfere alors vers la vraie variable $texte .= ' - $doublons[\'documents\'] .= $GLOBALS[\'doublons_documents\']; - unset($GLOBALS[\'doublons_documents\']);'; + $doublons[\'documents\'] .= $GLOBALS[\'doublons_documents\']; + unset($GLOBALS[\'doublons_documents\']);'; // Recherche : recuperer les hash a partir de la chaine de recherche if ($boucle->hash) { $texte .= ' - list($hash_recherche, $hash_recherche_strict) = requete_hash($GLOBALS["recherche"]); - if (!$hash_recherche) $stop_query = true;'; + // RECHERCHE + list($hash_recherche, $hash_recherche_strict) = requete_hash($GLOBALS["recherche"]);'; } - // Gestion de la hierarchie (voir inc-arg-squel) - $texte .= $boucle->hierarchie; - - # si le corps est une constante, ne plus appeler le serveur - if (!ereg("^'[^']*'$",$corps)) - { - $corps = ' - while ($Pile[$SP] = @spip_fetch_array($result)) ' . - "\n\t\{$corps\n\t}"; - if ($lang_select) { - $corps = ' - $old_lang = $GLOBALS[\'spip_lang\'];' . - $corps . ' - $GLOBALS["spip_lang"] = $old_lang;'; + // si le corps est une constante, ne plus appeler le serveur + if (ereg("^'[^']*'$",$corps)) { + // vide ? + if ($corps == "''") { + if (!$boucle->numrows) + return 'return "";'; + else + $corps = ""; + } else { + $boucle->numrows = true; + $corps = "\n ".'for($x=$Numrows["'.$id_boucle.'"];$x>0;$x--) + $t0 .= ' . $corps .';'; } - } else { - if ($corps != "''") - { - $boucle->numrows = true; - $corps = ' - for($x=$Numrows["' . $id_boucle . '"];$x>0;$x--) $t0.= ' . $corps .';'; - } - else if (!$boucle->numrows) return 'return "";'; else $corps = ""; + } else { + $corps = ' + + // RESULTATS + while ($objet = @spip_fetch_array($result)) {' + . "\n\t\t\$Pile[\$SP] = \$objet;" + . "\n$corps\n }\n"; + + // Memoriser la langue avant la boucle pour la restituer apres + if ($lang_select) { + $texte .= "\n \$old_lang = \$GLOBALS['spip_lang'];"; + $corps .= "\n \$GLOBALS['spip_lang'] = \$old_lang;"; + } } - return ($texte . ' - if (!$stop_query) $result = ' . calculer_requete($boucle) . ' - $t0 = ""; - $SP++;' . - (($flag_parties) ? - calculer_parties($boucle->partie, - $boucle->mode_partie, - $boucle->total_parties, - $id_boucle) : - ((!$boucle->numrows) ? '' : " - \$Numrows['$id_boucle'] = @spip_num_rows(\$result);")) . - ((!$flag_cpt) ? '' : "\n\t\$compteur_boucle = 0;") . - $corps . - ' - @spip_free_result($result);' . - (!($flag_h) ? ' - return $t0;' : (' - $SP--; - $h0 = $t0 .' . - ((!$boucle->separateur) ? "" : - ('(($h0 && $t0) ? \'' . $boucle->separateur . "' : '') .")) . - ' $h0;} - return $h0;'))); + // + // Requete + // + $init = "\n\n // REQUETE\n "; + + // hack critere recherche : ignorer la requete en cas de hash vide + if ($boucle->hash) + $init .= "if (\$hash_recherche) "; + + $init .= "\$result = " . calculer_requete($boucle); + $init .= "\n ".'$t0 = ""; + $SP++;'; + if ($flag_cpt) + $init .= "\n \$compteur_boucle = 0;"; + + + if ($flag_parties) + $init .= calculer_parties($boucle->partie, + $boucle->mode_partie, + $boucle->total_parties, + $id_boucle); + else if ($boucle->numrows) + $init .= "\n \$Numrows['$id_boucle'] = @spip_num_rows(\$result);"; + + // + // Conclusion et retour + // + $conclusion = "\n @spip_free_result(\$result);"; + $conclusion .= "\n return \$t0;"; + + return $texte . $init . $corps . $conclusion; } -// une grosse fonction pour un petit cas function calculer_parties($partie, $mode_partie, $total_parties, $id_boucle) { @@ -179,277 +212,311 @@ function calculer_parties($partie, $mode_partie, $total_parties, $id_boucle) { // et du dernier demandes dans la boucle : 0 pour le premier, // n-1 pour le dernier ; donc total_boucle = 1 + debut - fin - # nombre total avant partition - $retour = "\n\t".'$nombre_boucle = @spip_num_rows($result);'; + // nombre total avant partition + $retour = "\n\n // Partition\n " + .'$nombre_boucle = @spip_num_rows($result);'; ereg("([+-/])([+-/])?", $mode_partie, $regs); list(,$op1,$op2) = $regs; - # {1/3} + // {1/3} if ($op1 == '/') { - $retour .= "\n\t" + $retour .= "\n " .'$debut_boucle = 1 + ceil(($nombre_boucle * ' - . ($partie - 1) . ')/' . $total_parties . ");\n\t" + . ($partie - 1) . ')/' . $total_parties . ");\n " . '$fin_boucle = ceil (($nombre_boucle * ' . $partie . ')/' . $total_parties . ");"; } - # {1,x} + // {1,x} if ($op1 == '+') { - $retour .= "\n\t" + $retour .= "\n " . '$debut_boucle = ' . $partie . ';'; } - # {n-1,x} + // {n-1,x} if ($op1 == '-') { - $retour .= "\n\t" + $retour .= "\n " . '$debut_boucle = $nombre_boucle - ' . $partie . ';'; } - # {x,1} + // {x,1} if ($op2 == '+') { - $retour .= "\n\t" + $retour .= "\n " . '$fin_boucle = $debut_boucle + ' . $partie . ' - 1;'; } - # {x,n-1} + // {x,n-1} if ($op2 == '-') { - $retour .= "\n\t" + $retour .= "\n " . '$fin_boucle = $debut_boucle+($nombre_boucle-'.$partie.')-1;'; } - # Rabattre $fin_boucle sur le maximum - $retour .= "\n\t" + // Rabattre $fin_boucle sur le maximum + $retour .= "\n " .'$fin_boucle = min($fin_boucle, $nombre_boucle);'; - # calcul du total boucle final - $retour .= "\n\t" + // calcul du total boucle final + $retour .= "\n " .'$Numrows[\''.$id_boucle.'\'] = $fin_boucle - $debut_boucle + 1;'; return $retour; } -# Production du code PHP a` partir de la se'quence livre'e par le phraseur -# $boucles est passe' par re'fe'rence pour affectation par index_pile. -# Retourne un tableau de 2 e'le'ments: -# 1. une expression PHP, -# 2. une suite d'instructions PHP a` exe'cuter avant d'e'valuer l'expression. -# si cette suite est vide, on fusionne les se'quences d'expressions -# ce qui doit re'duire la me'moire ne'cessaire au processus -# En de'coule une combinatoire laborieuse mais sans difficulte' +// Production du code PHP a` partir de la se'quence livre'e par le phraseur +// $boucles est passe' par re'fe'rence pour affectation par index_pile. +// Retourne un tableau de 2 e'le'ments: +// 1. une expression PHP, +// 2. une suite d'instructions PHP a` exe'cuter avant d'e'valuer l'expression. +// si cette suite est vide, on fusionne les se'quences d'expressions +// ce qui doit re'duire la me'moire ne'cessaire au processus +// En de'coule une combinatoire laborieuse mais sans difficulte' -function calculer_liste($tableau, $prefix, $id_boucle, $niv, &$boucles, $id_mere) -{ +function calculer_liste($tableau, $prefix, $id_boucle, $niv, &$boucles, $id_mere) { if ((!$tableau)) return array("''",''); $texte = ''; $exp = ""; $process_ins = false; $firstset = true; $t = '$t' . ($niv+1); - reset($tableau); - while (list(, $objet) = each($tableau)) { - if ($objet->type == 'texte') { - $c = calculer_texte($objet->texte,$id_boucle, $boucles, $id_mere); - if (!$exp) - $exp = $c; - else - {if ((substr($exp,-1)=="'") && (substr($c,1,1)=="'")) - $exp = substr($exp,0,-1) . substr($c,2); - else - $exp .= (!$exp ? $c : (" .\n\t\t$c"));} - if (!(strpos($c,'<?') === false)) $pi = true; - } else { - if ($objet->type == 'include') { - $c = calculer_inclure($objet->fichier, - $objet->params, - $id_boucle, - $boucles); - $exp .= (!$exp ? $c : (" .\n\t\t$c")); - } else { - if ($objet->type == 'boucle') { - $nom = $objet->id_boucle; - list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, - $id_boucle, $niv+2, $boucles, $nom); - list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, - $id_boucle, $niv+2, $boucles, $nom); - list($oc,$om) = calculer_liste($objet->cond_altern, $prefix, - $id_boucle, $niv+1,$boucles, $nom); - $c = $prefix . - ereg_replace("-","_", $nom) . - '($Cache, $Pile, $doublons, $Numrows, $SP)'; - $m = ""; - } else { - list($c,$m) = - calculer_champ($objet->fonctions, - $objet->nom_champ, - $id_boucle, - $boucles, - $id_mere); - list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, $id_boucle, $niv+2,$boucles, $id_mere); - list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, $id_boucle, $niv+2,$boucles, $id_mere); - $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 se'quences $*m est vide - - if ($m) { - $texte .= "\n\n\t\t# MILIEU\n"; - // il faut achever le traitement de l'exp pre'ce'dente - if ($exp) { - $texte .= "\t\t\$t$niv " . - (($firstset) ? "=" : ".=") . - "$exp;$m" ; - $firstset = false; - $exp = ""; - } else { $texte .= $m;} - } - $texte .= "\n\n\t\t# CODE\n"; - if (!($bm || $am || $om)) { - // 3 se'quences vides: 'if' inutile - $a = (($bc == "''") ? "" : "$bc .") . - $t . - (($ac == "''") ? "" : " . $ac"); - // s'il y a un avant ou un apre`s ou un alternant, il faut '?' - if (($a != $t) || ($oc != "''")) - { $c = "(($t = $c) ? ($a) : ($oc))"; } - $exp = (!$exp ? $c : ("$exp .\n\t\t$c")); - } else { - // il faut achever le traitement de l'exp pre'ce'dente - if ($exp) { - $texte .= "\n\t\t\$t$niv " . - (($firstset) ? "=" : ".=") . - "$exp;" ; - $firstset = false; - } - $exp = (($bc == "''") ? $t : "($bc . $t)"); - $texte .= "\n\t\tif ($t = $c) \n{" . $bm; - if ($am) { - $texte .= "$t = $exp;\n\t$am"; - $exp = $t; } - if ($ac != "''") $exp = "($exp . $ac)"; - $texte .= (($exp == $t) ? '' : ("$t = $exp;")) . ";}"; - if ($om || ($oc != "''")) - { $texte .= " else {" . $om . "$t = ($oc);}"; } - $exp = $t; - } - } - } - } // while - if (!$exp) $exp ="''"; + + foreach ($tableau as $objet) { + + switch($objet->type) { + // texte seul + case 'texte': + $c = calculer_texte($objet->texte,$id_boucle, $boucles, $id_mere); + if (!$exp) + $exp = $c; + else { + if ((substr($exp,-1)=="'") && (substr($c,1,1)=="'")) + $exp = substr($exp,0,-1) . substr($c,2); + else + $exp .= (!$exp ? $c : (" .\n $c")); + } + if (!(strpos($c,'<'.'?') === false)) + $pi = true; + $traitement_champ = false; + break; + + // inclure + case 'include': + $c = calculer_inclure($objet->fichier, + $objet->params, + $id_boucle, + $boucles); + $exp .= (!$exp ? $c : (" .\n $c")); + $traitement_champ = false; + break; + + // boucle + case 'boucle': + $nom = $objet->id_boucle; + list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, + $id_boucle, $niv+2, $boucles, $nom); + list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, + $id_boucle, $niv+2, $boucles, $nom); + list($oc,$om) = calculer_liste($objet->cond_altern, $prefix, + $id_boucle, $niv+1,$boucles, $nom); + $c = $prefix . ereg_replace("-","_", $nom) + . '($Cache, $Pile, $doublons, $Numrows, $SP)'; + $m = ""; + $traitement_champ = true; + $commentaire = "/* BOUCLE$nom */"; + break; + + // balise SPIP + default: + list($c,$m) = calculer_champ($objet->fonctions, + $objet->nom_champ, + $id_boucle, + $boucles, + $id_mere); + $commentaire = "/* #$objet->nom_champ */"; + list($bc,$bm) = calculer_liste($objet->cond_avant, $prefix, + $id_boucle, $niv+2,$boucles, $id_mere); + list($ac,$am) = calculer_liste($objet->cond_apres, $prefix, + $id_boucle, $niv+2,$boucles, $id_mere); + $oc = "''"; + $om = ""; + $traitement_champ = true; + break; + + } // switch + + + // 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 se'quences $*m est vide + + if ($traitement_champ) { + if ($m) { + // il faut achever le traitement de l'exp pre'ce'dente + if ($exp) { + $texte .= "\n \$t$niv " . + (($firstset) ? "=" : ".=") . $exp.';'; + $firstset = false; + $exp = ""; + } + $texte .= "\n$commentaire\n$m//\n"; + } + + # alternative a la branche ci-dessus ? + # if ($m) $c = "eval('".texte_script($m)."').$c"; + # if ($m) $c = "{$m}.$c"; ne marche pas + + // 3 sequences vides: 'if' inutile + if (!($bm || $am || $om)) { + if ($exp) + $exp .= ' . '; + $a = (($bc == "''") ? "" : "$bc .") . + $t . + (($ac == "''") ? "" : " . $ac"); + // s'il y a un avant ou un apre`s ou un alternant, il faut '?' + if (($a != $t) || ($oc != "''")) + $exp .= "(($t = $c$commentaire) ?\n ($a) : ($oc))"; + else + $exp .= "$c$commentaire"; + } else { + // il faut achever le traitement de l'exp pre'ce'dente + if ($exp) { + $texte .= "\n \$t$niv " . + (($firstset) ? "=" : ".=") . + "$exp;"; + $firstset = false; + } + $exp = (($bc == "''") ? $t : "($bc . $t)"); + $texte .= "\n if ($t = $c)\n{" . $bm; + if ($am) { + $texte .= "$t = $exp;\n $am"; + $exp = $t; + } + if ($ac != "''") + $exp = "($exp . $ac)"; + $texte .= (($exp == $t) ? '' : ("$t = $exp;")) . ";}"; + if ($om || ($oc != "''")) + $texte .= " else { $om$t = ($oc);}"; + $exp = $t; + } + } + } // foreach + + if (!$exp) + $exp ="''"; + return (!$texte ? array ($exp, "") : - array(($firstset ? $exp : ('$t'.$niv. ". $exp")),$texte)); + array(($firstset ? $exp : ('$t'.$niv. ". $exp")),$texte)); } -# Prend en argument le source d'un squelette, sa grammaire et un nom. -# Retourne une fonction PHP/SQL portant ce nom et calculant une page HTML. -# Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment: -# - 1er: element 'cache' => nom (du fichier ou` mettre la page) -# - 2e: element 0 contenant un environnement ('id_article => $id_article, etc) -# Elle retourne alors un tableau de 4 e'le'ments: -# - 'texte' => page HTML, application du squelette a` l'environnement; -# - 'squelette' => le nom du squelette -# - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique -# - 'invalideurs' => de'pendances de cette page, pour invalider son cache. -# (voir son utilisation, optionnelle, dans invalideur.php) -# En cas d'erreur, elle retourne un tableau des 2 premiers elements seulement +// Prend en argument le source d'un squelette, sa grammaire et un nom. +// Retourne une fonction PHP/SQL portant ce nom et calculant une page HTML. +// Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment: +// - 1er: element 'cache' => nom (du fichier ou` mettre la page) +// - 2e: element 0 contenant un environnement ('id_article => $id_article, etc) +// Elle retourne alors un tableau de 4 e'le'ments: +// - 'texte' => page HTML, application du squelette a` l'environnement; +// - 'squelette' => le nom du squelette +// - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique +// - 'invalideurs' => de'pendances de cette page, pour invalider son cache. +// (voir son utilisation, optionnelle, dans invalideur.php) +// En cas d'erreur, elle retourne un tableau des 2 premiers elements seulement function calculer_squelette($squelette, $nom, $gram) { -# Phraser le squelette, selon sa grammaire -# pour le moment: "html" seul connu (HTML+balises BOUCLE) - $boucles = ''; - include_local("inc-$gram-squel.php3"); - $racine = parser($squelette, '',$boucles); -# include_local('inc-debug.php3'); -# afftable($racine); -# affboucles($boucles); + // Phraser le squelette, selon sa grammaire + // pour le moment: "html" seul connu (HTML+balises BOUCLE) + $boucles = ''; + include_local("inc-$gram-squel.php3"); + $racine = parser($squelette, '',$boucles); + // include_local('inc-debug.php3'); + // afftable($racine); + // affboucles($boucles); -# Commencer par réperer les boucles appelées explicitement par d'autres -# car elles indexent leurs arguments de manière dérogatoire - - if ($boucles) - { - foreach($boucles as $id => $boucle) - { - if ($boucle->type_requete == 'boucle') - { - $rec = &$boucles[$boucle->param]; - if (!$rec) - { - return array(_T('info_erreur_squelette'), - ($boucle->param . _L(' : boucle récursive non définie'))); - } - - $rec->externe = $id; - $boucles[$id]->return = - calculer_liste(array($rec), - $nom, - $boucle->param, - 1, - $boucles, - $id); - } + // Commencer par reperer les boucles appelees explicitement par d'autres + // car elles indexent leurs arguments de maniere derogatoire + + if ($boucles) foreach($boucles as $id => $boucle) { + if ($boucle->type_requete == 'boucle') { + $rec = &$boucles[$boucle->param]; + if (!$rec) { + return array(_T('info_erreur_squelette'), + ($boucle->param . _L(' : boucle recursive non definie'))); + } + + $rec->externe = $id; + $boucles[$id]->return = + calculer_liste(array($rec), + $nom, + $boucle->param, + 1, + $boucles, + $id); + } } - foreach($boucles as $id => $boucle) - { - if ($boucle->type_requete != 'boucle') - { - $res = calculer_params($id, $boucles); - if (is_array($res)) return $res; - $boucles[$id]->return = - calculer_liste($boucle->milieu, - $nom, - $id, - 1, - $boucles, - $id); - } - } - } - - // idem pour la racine - - list($return,$corps) = - calculer_liste($racine, $nom, '',0, $boucles, ''); - - // Corps de toutes les fonctions PHP, - // en particulier les requetes SQL et TOTAL_BOUCLE - // de'terminables seulement maintenant - // Les 3 premiers parame`tres sont passe's par re'fe'rence - // (sorte d'environnements a` la Lisp 1.5) - // sauf pour la fonction principale qui recoit les initialisations - - $code = ''; - if ($boucles) - { - foreach($boucles as $id => $boucle) - { - $boucles[$id]->return = calculer_boucle($id, $boucles); + if ($boucles) foreach($boucles as $id => $boucle) { + if ($boucle->type_requete != 'boucle') { + $res = calculer_params($id, $boucles); + + // C'est quoi ca ??? + if (is_array($res)) + return $res; + + $boucles[$id]->return = calculer_liste($boucle->milieu, + $nom, + $id, + 1, + $boucles, + $id); + } } - - foreach($boucles as $id => $boucle) - { - $code .= "\n\n// BOUCLE".$id. - "\nfunction $nom" . ereg_replace("-","_",$id) . - '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' . - $boucle->return . - "\n}\n"; + + // idem pour la racine + list($return,$corps) = calculer_liste($racine, $nom, '',0, $boucles, ''); + + + // Corps de toutes les fonctions PHP, + // en particulier les requetes SQL et TOTAL_BOUCLE + // de'terminables seulement maintenant + // Les 3 premiers parame`tres sont passe's par re'fe'rence + // (sorte d'environnements a` la Lisp 1.5) + // sauf pour la fonction principale qui recoit les initialisations + + $code = ''; + if ($boucles) { + foreach($boucles as $id => $boucle) + $boucles[$id]->return = calculer_boucle($id, $boucles); + + foreach($boucles as $id => $boucle) { + + // Reproduire la boucle en commentaire + $pretty = "BOUCLE$id(".strtoupper($boucle->type_requete).")"; + if (is_array($boucle->param)) + $pretty .= " {".join("} {", $boucle->param)."}"; + $pretty = ereg_replace("[\r\n]", " ", $pretty); + + // Puis envoyer son code + $code .= "\n//\n// <$pretty>\n//\n" + ."function $nom" . ereg_replace("-","_",$id) . + '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' . + $boucle->return . + "\n}\n\n"; + } } - } - return $code . ' + + return $code . ' +// // Fonction principale du squelette +// function ' . $nom . '($Cache, $Pile, $doublons, $Numrows="", $SP=0) { -' . - $corps . "\n \$t0 = " . $return . '; - return array("texte" => $t0, +' . $corps . "\n \$t0 = " . $return . '; + return array("texte" => $t0, "squelette" => "' . $nom . '", "process_ins" => ((strpos($t0,\'<\'.\'?\')=== false) ? \'html\' : \'php\'), - "invalideurs" => $Cache);' . - "\n}\n" ; + "invalideurs" => $Cache);' . "\n}\n" ; + } + ?> diff --git a/inc-calcul.php3 b/inc-calcul.php3 index 94b70974e6f0a4bf65aa7502a5ec6f0c682fb179..91bd8fd195ddbae507f85c0fec696ebd351e87cd 100644 --- a/inc-calcul.php3 +++ b/inc-calcul.php3 @@ -14,6 +14,7 @@ include_ecrire("inc_texte.php3"); include_ecrire("inc_filtres.php3"); include_ecrire("inc_lang.php3"); include_ecrire("inc_documents.php3"); +include_ecrire("inc_forum.php3"); include_local("inc-calcul_mysql3.php"); include_local("inc-calcul_html4.php"); diff --git a/inc-index-squel.php3 b/inc-index-squel.php3 index 47476b2e65ed8c97b5b763f013abfcc4ed3eb48b..f08b187e68d8e86afe873d729f5a4f79af78afd7 100644 --- a/inc-index-squel.php3 +++ b/inc-index-squel.php3 @@ -83,28 +83,32 @@ function index_pile($idb, $nom_champ, &$boucles) { # on lui passe la main et elle est cense retourner le tableau ci-dessus # (Essayer de renvoyer une suite vide, ca diminue les allocations a l'exec) - +// cette fonction sert d'API pour demander le champ '$champ' dans la pile +function champ_sql($champ, $p) { + return index_pile($p->id_boucle, $champ, $p->boucles); +} function calculer_champ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) { // Preparer les parametres - $params = new ParamChamp; - $params->fonctions = $fonctions; - $params->nom_champ = $nom_champ; - $params->id_boucle = $id_boucle; - $params->boucles = $boucles; - $params->id_mere = $id_mere; - - // regarder s'il existe une fonction perso pour #NOM - $f = 'perso_' . $nom_champ; - if (function_exists($f)) - return $f($params); - - // regarder s'il existe une fonction new style pour #NOM - $f = 'calculer_balise_' . $nom_champ; - if (function_exists($f)) - return $f($params); - - // regarder s'il existe une fonction old style pour #NOM + $p = new ParamChamp; + $p->fonctions = $fonctions; + $p->nom_champ = $nom_champ; + $p->id_boucle = $id_boucle; + $p->boucles = $boucles; + $p->id_mere = $id_mere; + + // regarder s'il existe une fonction personnalisee balise_NOM() + $f = 'balise_' . $nom_champ; + if (function_exists($f) AND $p = $f($p)) + return $p->retour(); + + // regarder s'il existe une fonction standard balise_NOM_dist() + $f = 'balise_' . $nom_champ . '_dist'; + if (function_exists($f) AND $p = $f($p)) + return $p->retour(); + + # A SUPPRIMER + // regarder s'il existe une fonction old style calculer_champ_NOM() $f = 'calculer_champ_' . $nom_champ; if (function_exists($f)) return $f($fonctions, $nom_champ, $id_boucle, $boucles, $id_mere); diff --git a/inc-logo-squel.php3 b/inc-logo-squel.php3 index 0558b05046567e5763bf9d9d8ef74019131a7de6..a14df8d5e3d2f41b4fc5506a51a70b57a79a2f82 100644 --- a/inc-logo-squel.php3 +++ b/inc-logo-squel.php3 @@ -1,71 +1,101 @@ <?php + # Fonctions de traitement de champs Spip homonymes de champs SQL # mais non e'quivalent -function calculer_champ_EXTRA ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) -{ - $code = 'trim(' . index_pile($id_boucle, "extra", $boucles) . ')'; - if ($fonctions) { + +// #EXTRA [(#EXTRA|isbn)] +// Champs extra +// Non documentes, en voie d'obsolescence, cf. ecrire/inc_extra.php3 +function balise_EXTRA_dist ($p) { + $_extra = champ_sql('extra', $p); + $p->code = 'trim($_extra)'; + // Gerer la notation [(#EXTRA|isbn)] - include_ecrire("inc_extra.php3"); - reset($fonctions); - list($key, $champ_extra) = each($fonctions); - $type_extra = $boucles[$id_boucle]->type_requete; - if (extra_champ_valide($type_extra, $champ_extra)) { - unset($fonctions[$key]); - $code = "extra($code, '".addslashes($champ_extra )."')"; - } - // Appliquer les filtres definis par le webmestre - $filtres = extra_filtres($type_extra, $champ_extra); - if ($filtres) { - reset($filtres); - while (list(, $f) = each($filtres)) $code = "$f($code)"; - } - } - return applique_filtres($fonctions, $code, $id_boucle, $boucles, $id_mere); + if ($p->fonctions) { + include_ecrire("inc_extra.php3"); + foreach ($p->fonctions as $key => $champ_extra) + $type_extra = $p->boucles[$p->id_boucle]->type_requete; + // ci-dessus est sans doute un peu buggue : si on invoque #EXTRA + // depuis un sous-objet sans champ extra d'un objet a champ extra, + // on aura le type_extra du sous-objet (!) + if (extra_champ_valide($type_extra, $champ_extra)) { + unset($p->fonctions[$key]); + $p->code = "extra($p->code, '".addslashes($champ_extra)."')"; + } + // Appliquer les filtres definis par le webmestre + $filtres = extra_filtres($type_extra, $champ_extra); + if ($filtres) foreach ($filtres as $f) + $p->code = "$f($p->code)"; + } + return $p; } -function calculer_champ_LANG ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) - { - $code = '(($x = '.index_pile($id_boucle, "lang", $boucles).') ? $x : $GLOBALS[spip_lang])'; - return applique_filtres($fonctions, $code, $id_boucle, $boucles, $id_mere); + +// #LANG +// non documente ? +function balise_LANG_dist ($p) { + $_lang = champ_sql('lang', $p); + $p->code = '($_lang ? $_lang : $GLOBALS[spip_lang])'; + return $p; } -function calculer_champ_LESAUTEURS ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) -{ - $code = index_pile($id_boucle, 'lesauteurs', $boucles); - if ((!$code) || ($code == '$Pile[0][lesauteurs]')) - $code = 'sql_auteurs(' . - index_pile($id_boucle, "id_article", $boucles) . - ')'; - return applique_filtres($fonctions, $code, $id_boucle, $boucles, $id_mere); + +// #LESAUTEURS +// les auteurs d'un article (ou d'un article syndique) +// http://www.spip.net/fr_article902.html +// http://www.spip.net/fr_article911.html +function balise_LESAUTEURS_dist ($p) { + // Cherche le champ 'lesauteurs' dans la pile + $_lesauteurs = champ_sql('lesauteurs', $p); + + // Si le champ n'existe pas (cas de spip_articles), on donne la + // construction speciale sql_auteurs(id_article) ; + // dans le cas contraire on prend le champ 'les_auteurs' (cas de + // spip_syndic_articles) + if ($_lesauteurs AND $_lesauteurs != '$Pile[0][lesauteurs]') { + $p->code = $_lesauteurs; + } else { + $_id_article = champ_sql('id_article', $p); + $p->code = "sql_auteurs($_id_article)"; + } + + return $p; } -function calculer_champ_PETITION ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) - { - $code = 'sql_petitions(' . - index_pile($id_boucle, 'id_article', $boucles) - . '")) ? " " : "")'; - return applique_filtres($fonctions, $code, $id_boucle, $boucles, $id_mere); + +// #PETITION +// Champ testant la presence d'une petition +// non documente ??? +function balise_PETITION_dist ($p) { + $_id_article = champ_sql('id_article', $p); + $p->code = 'sql_petitions($_id_article)'; + return $p; } -function calculer_champ_POPULARITE ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) - { - $code = 'ceil(min(100, 100 * ' . - index_pile($id_boucle, "popularite", $boucles) . - '/ max(1 , 0 + lire_meta(\'popularite_max\'))))'; - return applique_filtres($fonctions, $code, $id_boucle, $boucles, $id_mere); - } + +// #POPULARITE +// http://www.spip.net/fr_article1846.html +function balise_POPULARITE_dist ($p) { + $_popularite = champ_sql('popularite', $p); + $p->code = "ceil(min(100, 100 * $_popularite + / max(1 , 0 + lire_meta('popularite_max'))))"; + return $p; +} -function calculer_champ_DATE ($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) { -# Uniquement hors-boucles, pour date passee dans l'URL ou contexte_inclus - return applique_filtres($fonctions, - index_pile($id_boucle, 'date', $boucles), - $id_boucle, $boucles, $id_mere); +// #DATE +// Cette fonction n'est utile que parce qu'on a besoin d'aller chercher +// dans le contexte general quand #DATE est en dehors des boucles +// http://www.spip.net/fr_article1971.html +function balise_DATE_dist ($p) { + $_date = champ_sql('date', $p); + $p->code = "$_date"; + return $p; } + # Fonction commune aux logos (rubriques, articles...) function calculer_champ_LOGO($fonctions, $nom_champ, $id_boucle, &$boucles, $id_mere) diff --git a/inc-reqsql-squel.php3 b/inc-reqsql-squel.php3 index 0135956b52648d5635f252df551622e244f87f23..364453092a51f21e1ccc4087cb2ff83d15d91c79 100644 --- a/inc-reqsql-squel.php3 +++ b/inc-reqsql-squel.php3 @@ -89,7 +89,6 @@ function calculer_requete(&$boucle) { case 'hierarchie': $boucle->from[] = "rubriques AS $id_table"; -# $boucle->select[] = "rubriques.id_parent"; break; case 'syndication': @@ -115,9 +114,9 @@ function calculer_requete(&$boucle) { // En absence de champ c'est un decompte : on prend la primary pour // avoir qqch (le marteau-pilon * est trop couteux, et le COUNT // incompatible avec le cas general) - return 'spip_abstract_select(array("'. + return "spip_abstract_select(\n\t\tarray(\"". ((!$boucle->select) ? $id_field : - join('", "', array_unique($boucle->select))) . + join("\",\n\t\t\"", array_unique($boucle->select))) . '"), # SELECT array("' . join('","', array_unique($boucle->from)) . diff --git a/inc-vrac-squel.php3 b/inc-vrac-squel.php3 index 98e3aecbb9269f7f0255046ec6f10c79250d4795..36f236d4dd09a5523c153b8c3e5f50bb1f9674a5 100644 --- a/inc-vrac-squel.php3 +++ b/inc-vrac-squel.php3 @@ -293,14 +293,14 @@ function calculer_champ_divers($fonctions, $nom_champ, $id_boucle, &$boucles, $i // Fonctions OK // -function calculer_balise_INTRODUCTION($params) { - $params->code = 'calcul_introduction(\'' . - $params->boucles[$params->id_boucle]->type_requete . "',\n" . - index_pile($params->id_boucle, "texte", $params->boucles) . ",\n" . - index_pile($params->id_boucle, "chapo", $params->boucles) . ",\n" . - index_pile($params->id_boucle, "descriptif", $params->boucles) . ")\n"; - - return $params->retour(); +function balise_INTRODUCTION_dist ($p) { + $_type = $p->boucles[$p->id_boucle]->type_requete; + $_texte = champ_sql('texte', $p); + $_chapo = champ_sql('chapo', $p); + $_descriptif = champ_sql('descriptif', $p); + $p->code = "calcul_introduction('$_type', $_texte, $_chapo, $_descriptif)"; + + return $p; } ?>