4 |
david |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
/***************************************************************************\
|
|
|
4 |
* SPIP, Systeme de publication pour l'internet *
|
|
|
5 |
* *
|
|
|
6 |
* Copyright (c) 2001-2005 *
|
|
|
7 |
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
|
|
|
8 |
* *
|
|
|
9 |
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
|
|
|
10 |
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
|
|
|
11 |
\***************************************************************************/
|
|
|
12 |
|
|
|
13 |
|
|
|
14 |
//
|
|
|
15 |
// Fichier principal du compilateur de squelettes
|
|
|
16 |
//
|
|
|
17 |
|
|
|
18 |
// Ce fichier ne sera execute qu'une fois
|
|
|
19 |
if (defined("_INC_COMPILO")) return;
|
|
|
20 |
define("_INC_COMPILO", "1");
|
|
|
21 |
|
|
|
22 |
// reperer un code ne calculant rien, meme avec commentaire
|
|
|
23 |
define('CODE_MONOTONE', "^(\n//[^\n]*\n)?\(?'([^'])*'\)?$");
|
|
|
24 |
|
|
|
25 |
// Definition de la structure $p, et fonctions de recherche et de reservation
|
|
|
26 |
// dans l'arborescence des boucles
|
|
|
27 |
include_local("inc-compilo-index.php3"); # index ? structure ? pile ?
|
|
|
28 |
|
|
|
29 |
// definition des boucles
|
|
|
30 |
include_local("inc-boucles.php3");
|
|
|
31 |
|
|
|
32 |
// definition des criteres
|
|
|
33 |
include_local("inc-criteres.php3");
|
|
|
34 |
|
|
|
35 |
// definition des balises
|
|
|
36 |
include_local("inc-balises.php3");
|
|
|
37 |
|
|
|
38 |
// definition de l'API
|
|
|
39 |
include_local("inc-compilo-api.php3");
|
|
|
40 |
|
|
|
41 |
# definition des tables
|
|
|
42 |
include_ecrire('inc_serialbase.php3');
|
|
|
43 |
|
|
|
44 |
// outils pour debugguer le compilateur
|
|
|
45 |
#include_local("inc-compilo-debug.php3"); # desactive
|
|
|
46 |
|
|
|
47 |
//
|
|
|
48 |
// Calculer un <INCLURE()>
|
|
|
49 |
//
|
|
|
50 |
function calculer_inclure($struct, $descr, &$boucles, $id_boucle) {
|
|
|
51 |
$fichier = $struct->texte;
|
|
|
52 |
|
|
|
53 |
if (!($path = find_in_path($fichier)))
|
|
|
54 |
{
|
|
|
55 |
spip_log("ERREUR: <INCLURE($fichier)> impossible");
|
|
|
56 |
erreur_squelette(_T('zbug_info_erreur_squelette'),
|
|
|
57 |
"<INCLURE($fichier)> - "
|
|
|
58 |
._T('fichier_introuvable', array('fichier' => $fichier)));
|
|
|
59 |
return "'<!-- Erreur INCLURE(".texte_script($fichier).") -->'";
|
|
|
60 |
}
|
|
|
61 |
|
|
|
62 |
$l = array();
|
|
|
63 |
foreach($struct->param as $val) {
|
|
|
64 |
$var = array_shift($val);
|
|
|
65 |
$l[] = "\'$var\' => \'' . addslashes(" .
|
|
|
66 |
($val ? calculer_liste($val[0], $descr, $boucles, $id_boucle) :
|
|
|
67 |
(($var =='lang') ?
|
|
|
68 |
'$GLOBALS["spip_lang"]' :
|
|
|
69 |
index_pile($id_boucle, $var, $boucles)))
|
|
|
70 |
. ") . '\\'";
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
return "\n'<".
|
|
|
74 |
"?php\n\t\$contexte_inclus = array(" .
|
|
|
75 |
join(",\n\t",$l) .
|
|
|
76 |
");" .
|
|
|
77 |
"\n\tinclude(\\'$path\\');" .
|
|
|
78 |
"\n?'." . "'>'";
|
|
|
79 |
}
|
|
|
80 |
|
|
|
81 |
//
|
|
|
82 |
// calculer_boucle() produit le corps PHP d'une boucle Spip
|
|
|
83 |
// Sauf pour les recursives, ce corps est un Select SQL + While PHP
|
|
|
84 |
// remplissant une variable $t0 retournee en valeur
|
|
|
85 |
//
|
|
|
86 |
function calculer_boucle($id_boucle, &$boucles) {
|
|
|
87 |
|
|
|
88 |
$boucle = &$boucles[$id_boucle];
|
|
|
89 |
$return = $boucle->return;
|
|
|
90 |
$type_boucle = $boucle->type_requete;
|
|
|
91 |
|
|
|
92 |
if ($type_boucle == 'boucle') {
|
|
|
93 |
$corps = "\n \$t0 = " . $return . ";";
|
|
|
94 |
$init = "";
|
|
|
95 |
} else {
|
|
|
96 |
$primary = $boucle->primary;
|
|
|
97 |
$constant = ereg(CODE_MONOTONE,$return);
|
|
|
98 |
|
|
|
99 |
// Cas {1/3} {1,4} {n-2,1}...
|
|
|
100 |
|
|
|
101 |
$flag_cpt = $boucle->mode_partie || // pas '$compteur' a cause du cas 0
|
|
|
102 |
strpos($return,'compteur_boucle');
|
|
|
103 |
|
|
|
104 |
//
|
|
|
105 |
// Creer le debut du corps de la boucle :
|
|
|
106 |
//
|
|
|
107 |
$corps = '';
|
|
|
108 |
if ($flag_cpt)
|
|
|
109 |
$corps = "\n \$Numrows['$id_boucle']['compteur_boucle']++;";
|
|
|
110 |
|
|
|
111 |
if ($boucle->mode_partie)
|
|
|
112 |
$corps .= "
|
|
|
113 |
if (\$Numrows['$id_boucle']['compteur_boucle']-1 >= \$debut_boucle
|
|
|
114 |
AND \$Numrows['$id_boucle']['compteur_boucle']-1 <= \$fin_boucle) {";
|
|
|
115 |
|
|
|
116 |
// Calculer les invalideurs si c'est une boucle non constante
|
|
|
117 |
|
|
|
118 |
if ($primary && !$constant)
|
|
|
119 |
$corps .= "\n\t\t\$Cache['$primary'][" .
|
|
|
120 |
(($primary != 'id_forum') ?
|
|
|
121 |
index_pile($id_boucle, $primary, $boucles) :
|
|
|
122 |
("calcul_index_forum(" .
|
|
|
123 |
// Retournera 4 [$SP] mais force la demande du champ a MySQL
|
|
|
124 |
index_pile($id_boucle, 'id_article', $boucles) . ',' .
|
|
|
125 |
index_pile($id_boucle, 'id_breve', $boucles) . ',' .
|
|
|
126 |
index_pile($id_boucle, 'id_rubrique', $boucles) .',' .
|
|
|
127 |
index_pile($id_boucle, 'id_syndic', $boucles) .
|
|
|
128 |
")")) .
|
|
|
129 |
"] = 1; // invalideurs\n";
|
|
|
130 |
|
|
|
131 |
if ($boucle->doublons)
|
|
|
132 |
$corps .= " \$doublons[".$boucle->doublons."] .= ','. " .
|
|
|
133 |
index_pile($id_boucle, $primary, $boucles)
|
|
|
134 |
. "; // doublons\n";
|
|
|
135 |
|
|
|
136 |
|
|
|
137 |
if (count($boucle->separateur))
|
|
|
138 |
$code_sep = ("'" . ereg_replace("'","\'",join('',$boucle->separateur)) . "'");
|
|
|
139 |
|
|
|
140 |
$init = '';
|
|
|
141 |
$fin = '';
|
|
|
142 |
|
|
|
143 |
// La boucle doit-elle selectionner la langue ?
|
|
|
144 |
// -. par defaut, les boucles suivantes le font
|
|
|
145 |
// "peut-etre", c'est-a-dire si forcer_lang == false.
|
|
|
146 |
// - . a moins d'une demande explicite
|
|
|
147 |
if (!$constant && $boucle->lang_select != 'non' &&
|
|
|
148 |
(($boucle->lang_select == 'oui') ||
|
|
|
149 |
(
|
|
|
150 |
$type_boucle == 'articles'
|
|
|
151 |
OR $type_boucle == 'rubriques'
|
|
|
152 |
OR $type_boucle == 'hierarchie'
|
|
|
153 |
OR $type_boucle == 'breves'
|
|
|
154 |
)))
|
|
|
155 |
{
|
|
|
156 |
$corps .=
|
|
|
157 |
(($boucle->lang_select != 'oui') ?
|
|
|
158 |
"\t\tif (!\$GLOBALS['forcer_lang'])\n\t " : '')
|
|
|
159 |
. "\t\t\$GLOBALS['spip_lang'] = (\$x = "
|
|
|
160 |
. index_pile($id_boucle, 'lang', $boucles)
|
|
|
161 |
. ') ? $x : $old_lang;';
|
|
|
162 |
// Memoriser la langue avant la boucle pour la restituer apres
|
|
|
163 |
$init .= "\n \$old_lang = \$GLOBALS['spip_lang'];";
|
|
|
164 |
$fin .= "\n \$GLOBALS['spip_lang'] = \$old_lang;";
|
|
|
165 |
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
// gestion optimale des separateurs et des boucles constantes
|
|
|
169 |
$corps .=
|
|
|
170 |
((!$boucle->separateur) ?
|
|
|
171 |
(($constant && !$corps) ? $return :
|
|
|
172 |
("\n\t\t" . '$t0 .= ' . $return . ";")) :
|
|
|
173 |
("\n\t\t\$t1 " .
|
|
|
174 |
((strpos($return, '$t1.') === 0) ?
|
|
|
175 |
(".=" . substr($return,4)) :
|
|
|
176 |
('= ' . $return)) .
|
|
|
177 |
";\n\t\t" .
|
|
|
178 |
'$t0 .= (($t1 && $t0) ? ' . $code_sep . " : '') . \$t1;"));
|
|
|
179 |
|
|
|
180 |
// Fin de parties
|
|
|
181 |
if ($boucle->mode_partie)
|
|
|
182 |
$corps .= "\n }\n";
|
|
|
183 |
|
|
|
184 |
// Gestion de la hierarchie (voir inc-boucles.php3)
|
|
|
185 |
if ($boucle->hierarchie)
|
|
|
186 |
$init .= "\n ".$boucle->hierarchie;
|
|
|
187 |
|
|
|
188 |
// si le corps est une constante, ne pas appeler le serveur N fois!
|
|
|
189 |
if (ereg(CODE_MONOTONE,$corps, $r)) {
|
|
|
190 |
if (!$r[2]) {
|
|
|
191 |
if (!$boucle->numrows)
|
|
|
192 |
return 'return "";';
|
|
|
193 |
else
|
|
|
194 |
$corps = "";
|
|
|
195 |
} else {
|
|
|
196 |
$boucle->numrows = true;
|
|
|
197 |
$corps = "\n ".'for($x=$Numrows["'.$id_boucle.'"]["total"];$x>0;$x--)
|
|
|
198 |
$t0 .= ' . $corps .';';
|
|
|
199 |
}
|
|
|
200 |
} else {
|
|
|
201 |
|
|
|
202 |
$corps = '
|
|
|
203 |
|
|
|
204 |
// RESULTATS
|
|
|
205 |
while ($Pile[$SP] = @spip_abstract_fetch($result,"' .
|
|
|
206 |
$boucle->sql_serveur .
|
|
|
207 |
'")) {' .
|
|
|
208 |
"\n$corps\n }\n" .
|
|
|
209 |
$fin ;
|
|
|
210 |
}
|
|
|
211 |
|
|
|
212 |
//
|
|
|
213 |
// Requete
|
|
|
214 |
//
|
|
|
215 |
|
|
|
216 |
if (!$order = $boucle->order
|
|
|
217 |
AND !$order = $boucle->default_order)
|
|
|
218 |
$order = array();
|
|
|
219 |
|
|
|
220 |
$init .= $boucle->hash .
|
|
|
221 |
"\n\n // REQUETE
|
|
|
222 |
\$result = spip_abstract_select(\n\t\tarray(\"".
|
|
|
223 |
# En absence de champ c'est un decompte :
|
|
|
224 |
# prendre la primary pour avoir qqch
|
|
|
225 |
# (COUNT incompatible avec le cas general
|
|
|
226 |
($boucle->select ?
|
|
|
227 |
join("\",\n\t\t\"", $boucle->select) :
|
|
|
228 |
($boucle->id_table . "." .
|
|
|
229 |
(($p = strpos($primary, ',')) ?
|
|
|
230 |
substr($primary, 0, $p) : $primary))) .
|
|
|
231 |
'"), # SELECT
|
|
|
232 |
array("' .
|
|
|
233 |
join('","', array_unique($boucle->from)) .
|
|
|
234 |
'"), # FROM
|
|
|
235 |
array(' .
|
|
|
236 |
(!$boucle->where ? '' : ( '"' . join('",
|
|
|
237 |
"', $boucle->where) . '"')) .
|
|
|
238 |
"), # WHERE
|
|
|
239 |
'".addslashes($boucle->group)."', # GROUP
|
|
|
240 |
array(" .
|
|
|
241 |
join(', ', $order) .
|
|
|
242 |
"), # ORDER
|
|
|
243 |
" . (strpos($boucle->limit, 'intval') === false ?
|
|
|
244 |
"'".$boucle->limit."'" :
|
|
|
245 |
$boucle->limit). ", # LIMIT
|
|
|
246 |
'".$boucle->sous_requete."', # sous
|
|
|
247 |
'" . (!$boucle->having ? "" : "(COUNT(*)> $boucle->having)")."', # HAVING
|
|
|
248 |
'".$boucle->id_table."', # table
|
|
|
249 |
'".$boucle->id_boucle."', # boucle
|
|
|
250 |
'".$boucle->sql_serveur."'); # serveur";
|
|
|
251 |
|
|
|
252 |
$init .= "\n ".'$t0 = "";
|
|
|
253 |
$SP++;';
|
|
|
254 |
if ($flag_cpt)
|
|
|
255 |
$init .= "\n \$Numrows['$id_boucle']['compteur_boucle'] = 0;";
|
|
|
256 |
|
|
|
257 |
if ($boucle->mode_partie)
|
|
|
258 |
$init .= calculer_parties($boucles, $id_boucle);
|
|
|
259 |
else if ($boucle->numrows)
|
|
|
260 |
$init .= "\n \$Numrows['" .
|
|
|
261 |
$id_boucle .
|
|
|
262 |
"']['total'] = @spip_abstract_count(\$result,'" .
|
|
|
263 |
$boucle->sql_serveur .
|
|
|
264 |
"');";
|
|
|
265 |
|
|
|
266 |
//
|
|
|
267 |
// Conclusion et retour
|
|
|
268 |
//
|
|
|
269 |
$corps .= "\n @spip_abstract_free(\$result,'" .
|
|
|
270 |
$boucle->sql_serveur . "');";
|
|
|
271 |
|
|
|
272 |
}
|
|
|
273 |
|
|
|
274 |
return $init . $corps .
|
|
|
275 |
## inserer le code d'envoi au debusqueur du resultat de la fonction
|
|
|
276 |
(($GLOBALS['var_mode_affiche'] != 'resultat') ? "" : "
|
|
|
277 |
boucle_debug_resultat('$id_boucle', 'resultat', \$t0);") .
|
|
|
278 |
"\n return \$t0;";
|
|
|
279 |
|
|
|
280 |
|
|
|
281 |
}
|
|
|
282 |
|
|
|
283 |
|
|
|
284 |
//
|
|
|
285 |
// fonction traitant les criteres {1,n} (analyses dans inc-criteres)
|
|
|
286 |
//
|
|
|
287 |
## a deplacer dans inc-criteres ??
|
|
|
288 |
function calculer_parties($boucles, $id_boucle) {
|
|
|
289 |
|
|
|
290 |
$boucle = &$boucles[$id_boucle];
|
|
|
291 |
$partie = $boucle->partie;
|
|
|
292 |
$mode_partie = $boucle->mode_partie;
|
|
|
293 |
$total_parties = $boucle->total_parties;
|
|
|
294 |
|
|
|
295 |
// Notes :
|
|
|
296 |
// $debut_boucle et $fin_boucle sont les indices SQL du premier
|
|
|
297 |
// et du dernier demandes dans la boucle : 0 pour le premier,
|
|
|
298 |
// n-1 pour le dernier ; donc total_boucle = 1 + debut - fin
|
|
|
299 |
|
|
|
300 |
// nombre total avant partition
|
|
|
301 |
$retour = "\n\n // Partition\n " .
|
|
|
302 |
'$nombre_boucle = @spip_abstract_count($result,"' .
|
|
|
303 |
$boucle->sql_serveur .
|
|
|
304 |
'");';
|
|
|
305 |
|
|
|
306 |
ereg("([+-/])([+-/])?", $mode_partie, $regs);
|
|
|
307 |
list(,$op1,$op2) = $regs;
|
|
|
308 |
|
|
|
309 |
// {1/3}
|
|
|
310 |
if ($op1 == '/') {
|
|
|
311 |
$pmoins1 = is_numeric($partie) ? ($partie-1) : "($partie-1)";
|
|
|
312 |
$totpos = is_numeric($total_parties) ? ($total_parties) :
|
|
|
313 |
"($total_parties ? $total_parties : 1)";
|
|
|
314 |
$retour .= "\n "
|
|
|
315 |
.'$debut_boucle = ceil(($nombre_boucle * '
|
|
|
316 |
. $pmoins1 . ')/' . $totpos . ");";
|
|
|
317 |
$fin = 'ceil (($nombre_boucle * '
|
|
|
318 |
. $partie . ')/' . $totpos . ") - 1";
|
|
|
319 |
}
|
|
|
320 |
|
|
|
321 |
// {1,x}
|
|
|
322 |
elseif ($op1 == '+') {
|
|
|
323 |
$retour .= "\n "
|
|
|
324 |
. '$debut_boucle = ' . $partie . ';';
|
|
|
325 |
}
|
|
|
326 |
// {n-1,x}
|
|
|
327 |
elseif ($op1 == '-') {
|
|
|
328 |
$retour .= "\n "
|
|
|
329 |
. '$debut_boucle = $nombre_boucle - ' . $partie . ';';
|
|
|
330 |
}
|
|
|
331 |
// {x,1}
|
|
|
332 |
if ($op2 == '+') {
|
|
|
333 |
$fin = '$debut_boucle'
|
|
|
334 |
. (is_numeric($total_parties) ?
|
|
|
335 |
(($total_parties==1) ? "" :(' + ' . ($total_parties-1))):
|
|
|
336 |
('+' . $total_parties . ' - 1'));
|
|
|
337 |
}
|
|
|
338 |
// {x,n-1}
|
|
|
339 |
elseif ($op2 == '-') {
|
|
|
340 |
$fin = '$debut_boucle + $nombre_boucle - '
|
|
|
341 |
. (is_numeric($total_parties) ? ($total_parties+1) :
|
|
|
342 |
($total_parties . ' - 1'));
|
|
|
343 |
}
|
|
|
344 |
|
|
|
345 |
// Rabattre $fin_boucle sur le maximum
|
|
|
346 |
$retour .= "\n "
|
|
|
347 |
.'$fin_boucle = min(' . $fin . ', $nombre_boucle - 1);';
|
|
|
348 |
|
|
|
349 |
// calcul du total boucle final
|
|
|
350 |
$retour .= "\n "
|
|
|
351 |
.'$Numrows[\''.$id_boucle.'\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);';
|
|
|
352 |
|
|
|
353 |
return $retour;
|
|
|
354 |
}
|
|
|
355 |
|
|
|
356 |
// Production du code PHP a partir de la sequence livree par le phraseur
|
|
|
357 |
// $boucles est passe par reference pour affectation par index_pile.
|
|
|
358 |
// Retourne une expression PHP,
|
|
|
359 |
// (qui sera argument d'un Return ou la partie droite d'une affectation).
|
|
|
360 |
|
|
|
361 |
function calculer_liste($tableau, $descr, &$boucles, $id_boucle='') {
|
|
|
362 |
if (!$tableau) return "''";
|
|
|
363 |
$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
|
|
|
364 |
$n = count($codes);
|
|
|
365 |
if (!$n) return "''";
|
|
|
366 |
if ($GLOBALS['var_mode_affiche'] != 'validation')
|
|
|
367 |
return
|
|
|
368 |
(($n==1) ? $codes[0] :
|
|
|
369 |
"(" . join (" .\n$tab", $codes) . ")");
|
|
|
370 |
else return "debug_sequence('$id_boucle', '" .
|
|
|
371 |
($descr['nom']) .
|
|
|
372 |
"', " .
|
|
|
373 |
intval($descr['niv']) .
|
|
|
374 |
", array(" .
|
|
|
375 |
join(" ,\n$tab", $codes) . "))";
|
|
|
376 |
}
|
|
|
377 |
|
|
|
378 |
function compile_cas($tableau, $descr, &$boucles, $id_boucle='') {
|
|
|
379 |
$codes = array();
|
|
|
380 |
// cas de la boucle recursive
|
|
|
381 |
if (is_array($id_boucle))
|
|
|
382 |
$id_boucle = $id_boucle[0];
|
|
|
383 |
$type = $boucles[$id_boucle]->type_requete;
|
|
|
384 |
$descr['niv']++;
|
|
|
385 |
for ($i=0; $i<=$descr['niv']; $i++) $tab .= "\t";
|
|
|
386 |
|
|
|
387 |
// chaque commentaire introduit dans le code doit commencer
|
|
|
388 |
// par un caractere distinguant le cas, pour exploitation par debug.
|
|
|
389 |
foreach ($tableau as $p) {
|
|
|
390 |
|
|
|
391 |
switch($p->type) {
|
|
|
392 |
// texte seul
|
|
|
393 |
case 'texte':
|
|
|
394 |
$code = "'".ereg_replace("([\\\\'])", "\\\\1", $p->texte)."'";
|
|
|
395 |
|
|
|
396 |
$commentaire= strlen($p->texte) . " signes";
|
|
|
397 |
$avant='';
|
|
|
398 |
$apres='';
|
|
|
399 |
$altern = "''";
|
|
|
400 |
break;
|
|
|
401 |
|
|
|
402 |
case 'polyglotte':
|
|
|
403 |
$code = "";
|
|
|
404 |
foreach($p->traductions as $k => $v) {
|
|
|
405 |
$code .= ",'" .
|
|
|
406 |
ereg_replace("([\\\\'])", "\\\\1", $k) .
|
|
|
407 |
"' => '" .
|
|
|
408 |
ereg_replace("([\\\\'])", "\\\\1", $v) .
|
|
|
409 |
"'";
|
|
|
410 |
}
|
|
|
411 |
$code = "multi_trad(array(" .
|
|
|
412 |
substr($code,1) .
|
|
|
413 |
"))";
|
|
|
414 |
$commentaire= '&';
|
|
|
415 |
$avant='';
|
|
|
416 |
$apres='';
|
|
|
417 |
$altern = "''";
|
|
|
418 |
break;
|
|
|
419 |
|
|
|
420 |
// inclure
|
|
|
421 |
case 'include':
|
|
|
422 |
$code = calculer_inclure($p, $descr, $boucles, $id_boucle);
|
|
|
423 |
$commentaire = '!' . $p->texte;
|
|
|
424 |
$avant='';
|
|
|
425 |
$apres='';
|
|
|
426 |
$altern = "''";
|
|
|
427 |
break;
|
|
|
428 |
|
|
|
429 |
// boucle
|
|
|
430 |
case 'boucle':
|
|
|
431 |
$nom = $p->id_boucle;
|
|
|
432 |
$newdescr = $descr;
|
|
|
433 |
$newdescr['id_mere'] = $nom;
|
|
|
434 |
$newdescr['niv']++;
|
|
|
435 |
$code = 'BOUCLE' .
|
|
|
436 |
ereg_replace("-","_", $nom) . $descr['nom'] .
|
|
|
437 |
'($Cache, $Pile, $doublons, $Numrows, $SP)';
|
|
|
438 |
$commentaire= "?$nom";
|
|
|
439 |
$avant = calculer_liste($p->avant,
|
|
|
440 |
$newdescr, $boucles, $id_boucle);
|
|
|
441 |
$apres = calculer_liste($p->apres,
|
|
|
442 |
$newdescr, $boucles, $id_boucle);
|
|
|
443 |
$newdescr['niv']--;
|
|
|
444 |
$altern = calculer_liste($p->altern,
|
|
|
445 |
$newdescr, $boucles, $id_boucle);
|
|
|
446 |
break;
|
|
|
447 |
|
|
|
448 |
case 'idiome':
|
|
|
449 |
$p->code = "_T('" . $p->module . ":" .$p->nom_champ . "')";
|
|
|
450 |
$p->id_boucle = $id_boucle;
|
|
|
451 |
$p->boucles = &$boucles;
|
|
|
452 |
$p->statut = 'php'; // ne pas manger les espaces avec trim()
|
|
|
453 |
$commentaire = ":";
|
|
|
454 |
$code = applique_filtres($p);
|
|
|
455 |
$avant='';
|
|
|
456 |
$apres='';
|
|
|
457 |
$altern = "''";
|
|
|
458 |
break;
|
|
|
459 |
|
|
|
460 |
case 'champ';
|
|
|
461 |
|
|
|
462 |
// cette structure pourrait etre completee des le phrase' (a faire)
|
|
|
463 |
$p->id_boucle = $id_boucle;
|
|
|
464 |
$p->boucles = &$boucles;
|
|
|
465 |
$p->descr = $descr;
|
|
|
466 |
$p->statut = 'html';
|
|
|
467 |
$p->type_requete = $type;
|
|
|
468 |
|
|
|
469 |
$code = calculer_champ($p);
|
|
|
470 |
$commentaire = '#' . $p->nom_champ . $p->etoile;
|
|
|
471 |
$avant = calculer_liste($p->avant,
|
|
|
472 |
$descr, $boucles, $id_boucle);
|
|
|
473 |
$apres = calculer_liste($p->apres,
|
|
|
474 |
$descr, $boucles, $id_boucle);
|
|
|
475 |
$altern = "''";
|
|
|
476 |
break;
|
|
|
477 |
|
|
|
478 |
default:
|
|
|
479 |
erreur_squelette(_T('zbug_info_erreur_squelette'));
|
|
|
480 |
} // switch
|
|
|
481 |
|
|
|
482 |
if ($avant == "''") $avant = '';
|
|
|
483 |
if ($apres == "''") $apres = '';
|
|
|
484 |
if ($avant||$apres||($altern!="''"))
|
|
|
485 |
{
|
|
|
486 |
$t = '$t' . $descr['niv'];
|
|
|
487 |
$res = (!$avant ? "" : "$avant . ") .
|
|
|
488 |
$t .
|
|
|
489 |
(!$apres ? "" : " . $apres");
|
|
|
490 |
$code = "(($t = $code) ?\n\t$tab($res) :\n\t$tab($altern))";
|
|
|
491 |
}
|
|
|
492 |
if ($code != "''")
|
|
|
493 |
$codes[]= (($GLOBALS['var_mode_affiche'] == 'validation') ?
|
|
|
494 |
"array(" . $p->ligne . ", '$commentaire', $code)"
|
|
|
495 |
: (($GLOBALS['var_mode_affiche'] == 'code') ?
|
|
|
496 |
"\n// $commentaire\n$code" :
|
|
|
497 |
$code));
|
|
|
498 |
} // foreach
|
|
|
499 |
return $codes;
|
|
|
500 |
}
|
|
|
501 |
|
|
|
502 |
// affichage du code produit
|
|
|
503 |
|
|
|
504 |
function code_boucle(&$boucles, $id, $nom)
|
|
|
505 |
{
|
|
|
506 |
$boucle = &$boucles[$id];
|
|
|
507 |
|
|
|
508 |
// Indiquer la boucle en commentaire
|
|
|
509 |
$pretty = '';
|
|
|
510 |
|
|
|
511 |
if ($boucle->type_requete != 'boucle')
|
|
|
512 |
{
|
|
|
513 |
// Resynthetiser les criteres
|
|
|
514 |
foreach ($boucle->param as $param) {
|
|
|
515 |
$s = "";
|
|
|
516 |
$sep = "";
|
|
|
517 |
foreach ($param as $t) {
|
|
|
518 |
if (is_array($t)) { // toujours vrai normalement
|
|
|
519 |
$s .= $sep;
|
|
|
520 |
$c = $t[0];
|
|
|
521 |
if ($c->apres)
|
|
|
522 |
$s .= ($c->apres . $c->texte . $c->apres);
|
|
|
523 |
else {
|
|
|
524 |
// faudrait decompiler aussi les balises...
|
|
|
525 |
foreach ($t as $c)
|
|
|
526 |
$s .= ($c->type == 'texte') ? $c->texte : '#...';
|
|
|
527 |
}
|
|
|
528 |
$sep = ", ";
|
|
|
529 |
}
|
|
|
530 |
}
|
|
|
531 |
$pretty .= ' {' . $s . '}';
|
|
|
532 |
}
|
|
|
533 |
}
|
|
|
534 |
|
|
|
535 |
$pretty = "BOUCLE$id(".strtoupper($boucle->type_requete) . ")" .
|
|
|
536 |
ereg_replace("[\r\n]", " ", $pretty);
|
|
|
537 |
|
|
|
538 |
return $pretty;
|
|
|
539 |
}
|
|
|
540 |
|
|
|
541 |
|
|
|
542 |
// Prend en argument le source d'un squelette, sa grammaire et un nom.
|
|
|
543 |
// Retourne une fonction PHP/SQL portant ce nom et calculant une page HTML.
|
|
|
544 |
// Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment:
|
|
|
545 |
// - 1er: element 'cache' => nom (du fichier ou` mettre la page)
|
|
|
546 |
// - 2e: element 0 contenant un environnement ('id_article => $id_article, etc)
|
|
|
547 |
// Elle retourne alors un tableau de 4 e'le'ments:
|
|
|
548 |
// - 'texte' => page HTML, application du squelette a` l'environnement;
|
|
|
549 |
// - 'squelette' => le nom du squelette
|
|
|
550 |
// - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique
|
|
|
551 |
// - 'invalideurs' => de'pendances de cette page, pour invalider son cache.
|
|
|
552 |
// (voir son utilisation, optionnelle, dans invalideur.php)
|
|
|
553 |
// En cas d'erreur, elle retourne un tableau des 2 premiers elements seulement
|
|
|
554 |
|
|
|
555 |
function calculer_squelette($squelette, $nom, $gram, $sourcefile) {
|
|
|
556 |
# 3 variables qui sont en fait des constantes après chargement
|
|
|
557 |
global $table_primary, $table_des_tables, $tables_des_serveurs_sql;
|
|
|
558 |
// Phraser le squelette, selon sa grammaire
|
|
|
559 |
// pour le moment: "html" seul connu (HTML+balises BOUCLE)
|
|
|
560 |
$boucles = array();
|
|
|
561 |
spip_timer('calcul_skel');
|
|
|
562 |
|
|
|
563 |
include_local("inc-$gram-squel.php3");
|
|
|
564 |
|
|
|
565 |
$racine = phraser($squelette, '',$boucles, $nom);
|
|
|
566 |
|
|
|
567 |
// tableau des informations sur le squelette
|
|
|
568 |
$descr = array('nom' => $nom, 'documents' => false, 'sourcefile' => $sourcefile);
|
|
|
569 |
|
|
|
570 |
// une boucle documents est conditionnee par tout le reste!
|
|
|
571 |
foreach($boucles as $idb => $boucle) {
|
|
|
572 |
if (($boucle->type_requete == 'documents') && $boucle->doublons)
|
|
|
573 |
{ $descr['documents'] = true; break; }
|
|
|
574 |
}
|
|
|
575 |
// Commencer par reperer les boucles appelees explicitement
|
|
|
576 |
// car elles indexent les arguments de maniere derogatoire
|
|
|
577 |
foreach($boucles as $id => $boucle) {
|
|
|
578 |
if ($boucle->type_requete == 'boucle') {
|
|
|
579 |
$rec = &$boucles[$boucle->param[0]];
|
|
|
580 |
if (!$rec) {
|
|
|
581 |
return array(_T('zbug_info_erreur_squelette'),
|
|
|
582 |
($boucle->param[0]
|
|
|
583 |
. ' '. _T('zbug_boucle_recursive_undef')));
|
|
|
584 |
} else {
|
|
|
585 |
$rec->externe = $id;
|
|
|
586 |
$descr['id_mere'] = $id;
|
|
|
587 |
$boucles[$id]->return =
|
|
|
588 |
calculer_liste(array($rec),
|
|
|
589 |
$descr,
|
|
|
590 |
$boucles,
|
|
|
591 |
$boucle->param);
|
|
|
592 |
}
|
|
|
593 |
}
|
|
|
594 |
}
|
|
|
595 |
foreach($boucles as $id => $boucle) {
|
|
|
596 |
$type = $boucle->type_requete;
|
|
|
597 |
if ($type != 'boucle') {
|
|
|
598 |
$boucles[$id]->id_table = $table_des_tables[$type];
|
|
|
599 |
if ($boucles[$id]->id_table) {
|
|
|
600 |
$boucles[$id]->primary = $table_primary[$type];
|
|
|
601 |
} else {
|
|
|
602 |
// table non Spip.
|
|
|
603 |
$boucles[$id]->id_table = $type;
|
|
|
604 |
$serveur = $boucle->sql_serveur;
|
|
|
605 |
$x = &$tables_des_serveurs_sql[$serveur ? $serveur : 'localhost'][$type]['key'];
|
|
|
606 |
$boucles[$id]->primary = ($x["PRIMARY KEY"] ? $x["PRIMARY KEY"] : $x["KEY"]);
|
|
|
607 |
}
|
|
|
608 |
if ($boucle->param) {
|
|
|
609 |
$res = calculer_criteres($id, $boucles);
|
|
|
610 |
if (is_array($res)) return $res; # erreur
|
|
|
611 |
}
|
|
|
612 |
$descr['id_mere'] = $id;
|
|
|
613 |
$boucles[$id]->return =
|
|
|
614 |
calculer_liste($boucle->milieu,
|
|
|
615 |
$descr,
|
|
|
616 |
$boucles,
|
|
|
617 |
$id);
|
|
|
618 |
}
|
|
|
619 |
}
|
|
|
620 |
|
|
|
621 |
// idem pour la racine
|
|
|
622 |
$descr['id_mere'] = '';
|
|
|
623 |
$corps = calculer_liste($racine, $descr, $boucles);
|
|
|
624 |
|
|
|
625 |
// Calcul du corps de toutes les fonctions PHP,
|
|
|
626 |
// en particulier les requetes SQL et TOTAL_BOUCLE
|
|
|
627 |
// de'terminables seulement maintenant
|
|
|
628 |
// Les 4 premiers parame`tres sont passe's par re'fe'rence
|
|
|
629 |
// (les 1er et 3e pour modif, les 2 et 4 pour gain de place)
|
|
|
630 |
|
|
|
631 |
foreach($boucles as $id => $boucle) {
|
|
|
632 |
// appeler la fonction de definition de la boucle
|
|
|
633 |
$f = 'boucle_'.strtoupper($boucle->type_requete);
|
|
|
634 |
// si pas de definition perso, definition spip
|
|
|
635 |
if (!function_exists($f)) $f = $f.'_dist';
|
|
|
636 |
// laquelle a une definition par defaut
|
|
|
637 |
if (!function_exists($f)) $f = 'boucle_DEFAUT';
|
|
|
638 |
$boucles[$id]->return =
|
|
|
639 |
"function BOUCLE" . ereg_replace("-","_",$id) . $nom .
|
|
|
640 |
'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
|
|
|
641 |
$f($id, $boucles) .
|
|
|
642 |
"\n}\n\n";
|
|
|
643 |
if ($GLOBALS['var_mode'] == 'debug')
|
|
|
644 |
boucle_debug_compile ($id, $nom, $boucles[$id]->return);
|
|
|
645 |
|
|
|
646 |
}
|
|
|
647 |
|
|
|
648 |
$code = "";
|
|
|
649 |
foreach($boucles as $id => $boucle) {
|
|
|
650 |
$code .= "\n//\n// <BOUCLE " .
|
|
|
651 |
# code_boucle($boucles, $id, $nom). # pas au point
|
|
|
652 |
$boucle->type_requete .
|
|
|
653 |
">\n//\n" .
|
|
|
654 |
$boucle->return;
|
|
|
655 |
}
|
|
|
656 |
|
|
|
657 |
$secondes = spip_timer('calcul_skel');
|
|
|
658 |
spip_log("calcul skel $sourcefile ($secondes)");
|
|
|
659 |
|
|
|
660 |
$squelette_compile = "<"."?php
|
|
|
661 |
/*
|
|
|
662 |
* Squelette : $sourcefile
|
|
|
663 |
* Date : ".http_gmoddate(@filemtime($sourcefile))." GMT
|
|
|
664 |
* Compile : ".http_gmoddate(time())." GMT ($secondes)
|
|
|
665 |
* " . (!$boucles ? "Pas de boucle" :
|
|
|
666 |
("Boucles : " . join (', ', array_keys($boucles)))) ."
|
|
|
667 |
*/ " .
|
|
|
668 |
$code . "
|
|
|
669 |
|
|
|
670 |
//
|
|
|
671 |
// Fonction principale du squelette $sourcefile
|
|
|
672 |
//
|
|
|
673 |
function $nom (\$Cache, \$Pile, \$doublons=array(), \$Numrows='', \$SP=0) {
|
|
|
674 |
\$t0 = $corps;
|
|
|
675 |
|
|
|
676 |
return array(
|
|
|
677 |
'texte' => \$t0,
|
|
|
678 |
'squelette' => '$nom',
|
|
|
679 |
'process_ins' => ((strpos(\$t0,'<'.'?')=== false) ? 'html' : 'php'),
|
|
|
680 |
'invalideurs' => \$Cache
|
|
|
681 |
);
|
|
|
682 |
}
|
|
|
683 |
|
|
|
684 |
?".">";
|
|
|
685 |
|
|
|
686 |
if ($GLOBALS['var_mode'] == 'debug')
|
|
|
687 |
squelette_debug_compile($nom, $sourcefile, $squelette_compile, $squelette);
|
|
|
688 |
return $squelette_compile;
|
|
|
689 |
|
|
|
690 |
}
|
|
|
691 |
|
|
|
692 |
?>
|