Completed
Push — master ( f3de26...01d751 )
by cam
04:56
created
ecrire/public/compiler.php 1 patch
Indentation   +1162 added lines, -1162 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
  **/
19 19
 
20 20
 if (!defined('_ECRIRE_INC_VERSION')) {
21
-	return;
21
+    return;
22 22
 }
23 23
 
24 24
 /** Repérer un code ne calculant rien, meme avec commentaire */
@@ -60,91 +60,91 @@  discard block
 block discarded – undo
60 60
 
61 61
 // https://code.spip.net/@argumenter_inclure
62 62
 function argumenter_inclure(
63
-	$params,
64
-	$rejet_filtres,
65
-	$p,
66
-	&$boucles,
67
-	$id_boucle,
68
-	$echap = true,
69
-	$lang = '',
70
-	$fond1 = false
63
+    $params,
64
+    $rejet_filtres,
65
+    $p,
66
+    &$boucles,
67
+    $id_boucle,
68
+    $echap = true,
69
+    $lang = '',
70
+    $fond1 = false
71 71
 ) {
72
-	$l = array();
73
-	$erreur_p_i_i = '';
74
-	if (!is_array($params)) {
75
-		return $l;
76
-	}
77
-	foreach ($params as $k => $couple) {
78
-		// la liste d'arguments d'inclusion peut se terminer par un filtre
79
-		$filtre = array_shift($couple);
80
-		if ($filtre) {
81
-			break;
82
-		}
83
-		foreach ($couple as $n => $val) {
84
-			$var = $val[0];
85
-			if ($var->type != 'texte') {
86
-				if ($n or $k or $fond1) {
87
-					$erreur_p_i_i = array(
88
-						'zbug_parametres_inclus_incorrects',
89
-						array('param' => $var->nom_champ)
90
-					);
91
-					erreur_squelette($erreur_p_i_i, $p);
92
-					break;
93
-				} else {
94
-					$l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
95
-				}
96
-			} else {
97
-				preg_match(",^([^=]*)(=?)(.*)$,m", $var->texte, $m);
98
-				$m = array_pad($m, 3, null);
99
-				$var = $m[1];
100
-				$auto = false;;
101
-				if ($m[2]) {
102
-					$v = $m[3];
103
-					if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
104
-						$v = $m[1];
105
-					}
106
-					$val[0] = new Texte;
107
-					$val[0]->texte = $v;
108
-				} elseif ($k or $n or $fond1) {
109
-					$auto = true;
110
-				} else {
111
-					$var = 1;
112
-				}
113
-
114
-				if ($var == 'lang') {
115
-					$lang = !$auto
116
-						? calculer_liste($val, $p->descr, $boucles, $id_boucle)
117
-						: '$GLOBALS["spip_lang"]';
118
-				} else {
119
-					$val = $auto
120
-						? index_pile($id_boucle, $var, $boucles)
121
-						: calculer_liste($val, $p->descr, $boucles, $id_boucle);
122
-					if ($var !== 1) {
123
-						$val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
124
-							. $val . ($echap ? ") . '" : " ");
125
-					} else {
126
-						$val = $echap ? "'.$val.'" : $val;
127
-					}
128
-					$l[$var] = $val;
129
-				}
130
-			}
131
-		}
132
-	}
133
-	if ($erreur_p_i_i) {
134
-		return false;
135
-	}
136
-	// Cas particulier de la langue : si {lang=xx} est definie, on
137
-	// la passe, sinon on passe la langue courante au moment du calcul
138
-	// sauf si on n'en veut pas 
139
-	if ($lang === false) {
140
-		return $l;
141
-	}
142
-	if (!$lang) {
143
-		$lang = '$GLOBALS["spip_lang"]';
144
-	}
145
-	$l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : " ");
146
-
147
-	return $l;
72
+    $l = array();
73
+    $erreur_p_i_i = '';
74
+    if (!is_array($params)) {
75
+        return $l;
76
+    }
77
+    foreach ($params as $k => $couple) {
78
+        // la liste d'arguments d'inclusion peut se terminer par un filtre
79
+        $filtre = array_shift($couple);
80
+        if ($filtre) {
81
+            break;
82
+        }
83
+        foreach ($couple as $n => $val) {
84
+            $var = $val[0];
85
+            if ($var->type != 'texte') {
86
+                if ($n or $k or $fond1) {
87
+                    $erreur_p_i_i = array(
88
+                        'zbug_parametres_inclus_incorrects',
89
+                        array('param' => $var->nom_champ)
90
+                    );
91
+                    erreur_squelette($erreur_p_i_i, $p);
92
+                    break;
93
+                } else {
94
+                    $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
95
+                }
96
+            } else {
97
+                preg_match(",^([^=]*)(=?)(.*)$,m", $var->texte, $m);
98
+                $m = array_pad($m, 3, null);
99
+                $var = $m[1];
100
+                $auto = false;;
101
+                if ($m[2]) {
102
+                    $v = $m[3];
103
+                    if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
104
+                        $v = $m[1];
105
+                    }
106
+                    $val[0] = new Texte;
107
+                    $val[0]->texte = $v;
108
+                } elseif ($k or $n or $fond1) {
109
+                    $auto = true;
110
+                } else {
111
+                    $var = 1;
112
+                }
113
+
114
+                if ($var == 'lang') {
115
+                    $lang = !$auto
116
+                        ? calculer_liste($val, $p->descr, $boucles, $id_boucle)
117
+                        : '$GLOBALS["spip_lang"]';
118
+                } else {
119
+                    $val = $auto
120
+                        ? index_pile($id_boucle, $var, $boucles)
121
+                        : calculer_liste($val, $p->descr, $boucles, $id_boucle);
122
+                    if ($var !== 1) {
123
+                        $val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
124
+                            . $val . ($echap ? ") . '" : " ");
125
+                    } else {
126
+                        $val = $echap ? "'.$val.'" : $val;
127
+                    }
128
+                    $l[$var] = $val;
129
+                }
130
+            }
131
+        }
132
+    }
133
+    if ($erreur_p_i_i) {
134
+        return false;
135
+    }
136
+    // Cas particulier de la langue : si {lang=xx} est definie, on
137
+    // la passe, sinon on passe la langue courante au moment du calcul
138
+    // sauf si on n'en veut pas 
139
+    if ($lang === false) {
140
+        return $l;
141
+    }
142
+    if (!$lang) {
143
+        $lang = '$GLOBALS["spip_lang"]';
144
+    }
145
+    $l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : " ");
146
+
147
+    return $l;
148 148
 }
149 149
 
150 150
 /**
@@ -168,71 +168,71 @@  discard block
 block discarded – undo
168 168
  **/
169 169
 function calculer_inclure($p, &$boucles, $id_boucle) {
170 170
 
171
-	$_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
172
-	if (is_string($p->texte)) {
173
-		$fichier = $p->texte;
174
-		$code = "\"".str_replace('"','\"',$fichier)."\"";
175
-
176
-	} else {
177
-		$code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
178
-		if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
179
-			$fichier = $r[1];
180
-		} else {
181
-			$fichier = '';
182
-		}
183
-	}
184
-	if (!$code or $code === '""') {
185
-		$erreur_p_i_i = array(
186
-			'zbug_parametres_inclus_incorrects',
187
-			array('param' => $code)
188
-		);
189
-		erreur_squelette($erreur_p_i_i, $p);
190
-
191
-		return false;
192
-	}
193
-	$compil = texte_script(memoriser_contexte_compil($p));
194
-
195
-	if (is_array($_contexte)) {
196
-		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
197
-		if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
198
-			unset($_contexte['env']);
199
-		}
200
-
201
-		// noter les doublons dans l'appel a public.php
202
-		if (isset($_contexte['doublons'])) {
203
-			$_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
204
-		}
205
-
206
-		if ($ajax = isset($_contexte['ajax'])) {
207
-			$ajax = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
208
-			unset($_contexte['ajax']);
209
-		}
210
-
211
-		$_contexte = join(",\n\t", $_contexte);
212
-	} else {
213
-		return false;
214
-	} // j'aurais voulu toucher le fond ...
215
-
216
-	$contexte = 'array(' . $_contexte . ')';
217
-
218
-	if ($env) {
219
-		$contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
220
-	}
221
-
222
-	// s'il y a une extension .php, ce n'est pas un squelette
223
-	if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
224
-		$code = sandbox_composer_inclure_php($fichier, $p, $contexte);
225
-	} else {
226
-		$_options[] = "\"compil\"=>array($compil)";
227
-		if ($ajax) {
228
-			$_options[] = $ajax;
229
-		}
230
-		$code = " ' . argumenter_squelette($code) . '";
231
-		$code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',', $_options),
232
-				"_request(\"connect\")") . ';';
233
-	}
234
-
235
-	return "\n'<'.'" . "?php " . $code . "\n?'." . "'>'";
171
+    $_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
172
+    if (is_string($p->texte)) {
173
+        $fichier = $p->texte;
174
+        $code = "\"".str_replace('"','\"',$fichier)."\"";
175
+
176
+    } else {
177
+        $code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
178
+        if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
179
+            $fichier = $r[1];
180
+        } else {
181
+            $fichier = '';
182
+        }
183
+    }
184
+    if (!$code or $code === '""') {
185
+        $erreur_p_i_i = array(
186
+            'zbug_parametres_inclus_incorrects',
187
+            array('param' => $code)
188
+        );
189
+        erreur_squelette($erreur_p_i_i, $p);
190
+
191
+        return false;
192
+    }
193
+    $compil = texte_script(memoriser_contexte_compil($p));
194
+
195
+    if (is_array($_contexte)) {
196
+        // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
197
+        if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
198
+            unset($_contexte['env']);
199
+        }
200
+
201
+        // noter les doublons dans l'appel a public.php
202
+        if (isset($_contexte['doublons'])) {
203
+            $_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
204
+        }
205
+
206
+        if ($ajax = isset($_contexte['ajax'])) {
207
+            $ajax = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
208
+            unset($_contexte['ajax']);
209
+        }
210
+
211
+        $_contexte = join(",\n\t", $_contexte);
212
+    } else {
213
+        return false;
214
+    } // j'aurais voulu toucher le fond ...
215
+
216
+    $contexte = 'array(' . $_contexte . ')';
217
+
218
+    if ($env) {
219
+        $contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
220
+    }
221
+
222
+    // s'il y a une extension .php, ce n'est pas un squelette
223
+    if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
224
+        $code = sandbox_composer_inclure_php($fichier, $p, $contexte);
225
+    } else {
226
+        $_options[] = "\"compil\"=>array($compil)";
227
+        if ($ajax) {
228
+            $_options[] = $ajax;
229
+        }
230
+        $code = " ' . argumenter_squelette($code) . '";
231
+        $code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',', $_options),
232
+                "_request(\"connect\")") . ';';
233
+    }
234
+
235
+    return "\n'<'.'" . "?php " . $code . "\n?'." . "'>'";
236 236
 }
237 237
 
238 238
 
@@ -250,7 +250,7 @@  discard block
 block discarded – undo
250 250
  *     true pour ne tester que le cas publie et ignorer l'eventuel var_mode=preview de la page
251 251
  */
252 252
 function instituer_boucle(&$boucle, $echapper = true, $ignore_previsu = false) {
253
-	/*
253
+    /*
254 254
 	$show['statut'][] = array(
255 255
 		'champ'=>'statut',  // champ de la table sur lequel porte le filtrage par le statut
256 256
 		'publie'=>'publie', // valeur ou liste de valeurs, qui definissent l'objet comme publie.
@@ -274,71 +274,71 @@  discard block
 block discarded – undo
274 274
 	champstatut est alors le champ statut sur la tablen
275 275
 	dans les jointures, clen peut etre un tableau pour une jointure complexe : array('id_objet','id_article','objet','article')
276 276
 */
277
-	$id_table = $boucle->id_table;
278
-	$show = $boucle->show;
279
-	if (isset($show['statut']) and $show['statut']) {
280
-		foreach ($show['statut'] as $k => $s) {
281
-			// Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
282
-			$filtrer = true;
283
-			if (isset($s['exception'])) {
284
-				foreach (is_array($s['exception']) ? $s['exception'] : array($s['exception']) as $m) {
285
-					if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
286
-						$filtrer = false;
287
-						break;
288
-					}
289
-				}
290
-			}
291
-
292
-			if ($filtrer) {
293
-				if (is_array($s['champ'])) {
294
-					$statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
295
-					$jointures = array();
296
-					// indiquer la description de chaque table dans le tableau de jointures,
297
-					// ce qui permet d'eviter certains GROUP BY inutiles.
298
-					$trouver_table = charger_fonction('trouver_table', 'base');
299
-					foreach ($s['champ'] as $j) {
300
-						$id = reset($j);
301
-						$def = $trouver_table($id);
302
-						$jointures[] = array('', array($id, $def), end($j));
303
-					}
304
-					$jointures[0][0] = $id_table;
305
-					if (!array_search($id, $boucle->from)) {
306
-						include_spip('public/jointures');
307
-						fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
308
-					}
309
-					// trouver l'alias de la table d'arrivee qui porte le statut
310
-					$id = array_search($id, $boucle->from);
311
-				} else {
312
-					$id = $id_table;
313
-					$statut = preg_replace(',\W,', '', $s['champ']); // securite
314
-				}
315
-				$mstatut = $id . '.' . $statut;
316
-
317
-				$arg_ignore_previsu = ($ignore_previsu ? ",true" : '');
318
-				include_spip('public/quete');
319
-				if (isset($s['post_date']) and $s['post_date']
320
-					and $GLOBALS['meta']["post_dates"] == 'non'
321
-				) {
322
-					$date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
323
-					array_unshift($boucle->where,
324
-						$echapper ?
325
-							"\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
326
-							:
327
-							quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
328
-					);
329
-				}
330
-				array_unshift($boucle->where,
331
-					$echapper ?
332
-						"\nquete_condition_statut('$mstatut',"
333
-						. _q($s['previsu']) . ","
334
-						. _q($s['publie']) . ","
335
-						. _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
336
-						:
337
-						quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
338
-				);
339
-			}
340
-		}
341
-	}
277
+    $id_table = $boucle->id_table;
278
+    $show = $boucle->show;
279
+    if (isset($show['statut']) and $show['statut']) {
280
+        foreach ($show['statut'] as $k => $s) {
281
+            // Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
282
+            $filtrer = true;
283
+            if (isset($s['exception'])) {
284
+                foreach (is_array($s['exception']) ? $s['exception'] : array($s['exception']) as $m) {
285
+                    if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
286
+                        $filtrer = false;
287
+                        break;
288
+                    }
289
+                }
290
+            }
291
+
292
+            if ($filtrer) {
293
+                if (is_array($s['champ'])) {
294
+                    $statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
295
+                    $jointures = array();
296
+                    // indiquer la description de chaque table dans le tableau de jointures,
297
+                    // ce qui permet d'eviter certains GROUP BY inutiles.
298
+                    $trouver_table = charger_fonction('trouver_table', 'base');
299
+                    foreach ($s['champ'] as $j) {
300
+                        $id = reset($j);
301
+                        $def = $trouver_table($id);
302
+                        $jointures[] = array('', array($id, $def), end($j));
303
+                    }
304
+                    $jointures[0][0] = $id_table;
305
+                    if (!array_search($id, $boucle->from)) {
306
+                        include_spip('public/jointures');
307
+                        fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
308
+                    }
309
+                    // trouver l'alias de la table d'arrivee qui porte le statut
310
+                    $id = array_search($id, $boucle->from);
311
+                } else {
312
+                    $id = $id_table;
313
+                    $statut = preg_replace(',\W,', '', $s['champ']); // securite
314
+                }
315
+                $mstatut = $id . '.' . $statut;
316
+
317
+                $arg_ignore_previsu = ($ignore_previsu ? ",true" : '');
318
+                include_spip('public/quete');
319
+                if (isset($s['post_date']) and $s['post_date']
320
+                    and $GLOBALS['meta']["post_dates"] == 'non'
321
+                ) {
322
+                    $date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
323
+                    array_unshift($boucle->where,
324
+                        $echapper ?
325
+                            "\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
326
+                            :
327
+                            quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
328
+                    );
329
+                }
330
+                array_unshift($boucle->where,
331
+                    $echapper ?
332
+                        "\nquete_condition_statut('$mstatut',"
333
+                        . _q($s['previsu']) . ","
334
+                        . _q($s['publie']) . ","
335
+                        . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
336
+                        :
337
+                        quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
338
+                );
339
+            }
340
+        }
341
+    }
342 342
 }
343 343
 
344 344
 /**
@@ -357,29 +357,29 @@  discard block
 block discarded – undo
357 357
  */
358 358
 function calculer_boucle($id_boucle, &$boucles) {
359 359
 
360
-	$boucle = &$boucles[$id_boucle];
361
-	instituer_boucle($boucle);
362
-	$boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
363
-
364
-	// en mode debug memoriser les premiers passages dans la boucle,
365
-	// mais pas tous, sinon ca pete.
366
-	if (_request('var_mode_affiche') != 'resultat') {
367
-		$trace = '';
368
-	} else {
369
-		$_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
370
-		$_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
371
-		$trace = "
360
+    $boucle = &$boucles[$id_boucle];
361
+    instituer_boucle($boucle);
362
+    $boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
363
+
364
+    // en mode debug memoriser les premiers passages dans la boucle,
365
+    // mais pas tous, sinon ca pete.
366
+    if (_request('var_mode_affiche') != 'resultat') {
367
+        $trace = '';
368
+    } else {
369
+        $_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
370
+        $_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
371
+        $trace = "
372 372
 		if (empty($_trace)) { 
373 373
 			$_trace = []; 
374 374
 		}
375 375
 		if (count($_trace) < 3) { 
376 376
 			$_trace" . "[] = \$t0; 
377 377
 		}";
378
-	}
378
+    }
379 379
 
380
-	return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
381
-		? calculer_boucle_rec($id_boucle, $boucles, $trace)
382
-		: calculer_boucle_nonrec($id_boucle, $boucles, $trace);
380
+    return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
381
+        ? calculer_boucle_rec($id_boucle, $boucles, $trace)
382
+        : calculer_boucle_nonrec($id_boucle, $boucles, $trace);
383 383
 }
384 384
 
385 385
 
@@ -402,15 +402,15 @@  discard block
 block discarded – undo
402 402
  *    Code PHP compilé de la boucle récursive
403 403
  **/
404 404
 function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
405
-	$nom = $boucles[$id_boucle]->param[0];
406
-
407
-	return
408
-		// Numrows[$nom] peut ne pas être encore defini
409
-		"\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
410
-		. "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";"
411
-		. "\n\t\$Numrows['$nom'] = (\$save_numrows);"
412
-		. $trace
413
-		. "\n\treturn \$t0;";
405
+    $nom = $boucles[$id_boucle]->param[0];
406
+
407
+    return
408
+        // Numrows[$nom] peut ne pas être encore defini
409
+        "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
410
+        . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";"
411
+        . "\n\t\$Numrows['$nom'] = (\$save_numrows);"
412
+        . $trace
413
+        . "\n\treturn \$t0;";
414 414
 }
415 415
 
416 416
 /**
@@ -464,170 +464,170 @@  discard block
 block discarded – undo
464 464
  **/
465 465
 function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
466 466
 
467
-	$boucle = &$boucles[$id_boucle];
468
-	$return = $boucle->return;
469
-	$type_boucle = $boucle->type_requete;
470
-	$primary = $boucle->primary;
471
-	$constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
472
-	$flag_cpt = $boucle->mode_partie || $boucle->cptrows;
473
-	$corps = '';
474
-
475
-	// faudrait expanser le foreach a la compil, car y en a souvent qu'un 
476
-	// et puis faire un [] plutot qu'un "','."
477
-	if ($boucle->doublons) {
478
-		$corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
479
-			index_pile($id_boucle, $primary, $boucles)
480
-			. "; // doublons\n";
481
-	}
482
-
483
-	// La boucle doit-elle selectionner la langue ?
484
-	// - par defaut, les boucles suivantes le font
485
-	//    (sauf si forcer_lang==true ou si le titre contient <multi>).
486
-	// - a moins d'une demande explicite via {!lang_select}
487
-	if (!$constant && $boucle->lang_select != 'non' &&
488
-		(($boucle->lang_select == 'oui') ||
489
-			in_array($type_boucle, array(
490
-				'articles',
491
-				'rubriques',
492
-				'hierarchie',
493
-				'breves'
494
-			)))
495
-	) {
496
-		// Memoriser la langue avant la boucle et la restituer apres
497
-		// afin que le corps de boucle affecte la globale directement
498
-		$init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
499
-		$fin_lang = "lang_select();\n\t";
500
-		$fin_lang_select_public = "\n\t\tlang_select();";
501
-
502
-		$corps .=
503
-			"\n\t\tlang_select_public("
504
-			. index_pile($id_boucle, 'lang', $boucles)
505
-			. ", '" . $boucle->lang_select . "'"
506
-			. (in_array($type_boucle, array(
507
-				'articles',
508
-				'rubriques',
509
-				'hierarchie',
510
-				'breves'
511
-			)) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
512
-			. ');';
513
-	} else {
514
-		$init_lang = '';
515
-		$fin_lang = '';
516
-		$fin_lang_select_public = '';
517
-		// sortir les appels au traducteur (invariants de boucle)
518
-		if (strpos($return, '?php') === false
519
-			and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
520
-		) {
521
-			$i = 1;
522
-			foreach ($r[1] as $t) {
523
-				$init_lang .= "\n\t\$l$i = $t;";
524
-				$return = str_replace($t, "\$l$i", $return);
525
-				$i++;
526
-			}
527
-		}
528
-	}
529
-
530
-	// gestion optimale des separateurs et des boucles constantes
531
-	if (count($boucle->separateur)) {
532
-		$code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
533
-	}
534
-
535
-	$corps .=
536
-		((!$boucle->separateur) ?
537
-			(($constant && !$corps && !$flag_cpt) ? $return :
538
-				(($return === "''") ? '' :
539
-					("\n\t\t" . '$t0 .= ' . $return . ";"))) :
540
-			("\n\t\t\$t1 " .
541
-				((strpos($return, '$t1.') === 0) ?
542
-					(".=" . substr($return, 4)) :
543
-					('= ' . $return)) .
544
-				";\n\t\t" .
545
-				'$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
546
-
547
-	// Calculer les invalideurs si c'est une boucle non constante et si on
548
-	// souhaite invalider ces elements
549
-	if (!$constant and $primary) {
550
-		include_spip('inc/invalideur');
551
-		$corps = calcul_invalideurs($corps, $primary,$boucles, $id_boucle);
552
-	}
553
-
554
-	// gerer le compteur de boucle 
555
-	// avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
556
-
557
-	if ($boucle->partie or $boucle->cptrows) {
558
-		$corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
559
-			. $boucle->partie
560
-			. $corps;
561
-	}
562
-
563
-	// depiler la lang de la boucle si besoin
564
-	$corps .= $fin_lang_select_public;
565
-
566
-	// si le corps est une constante, ne pas appeler le serveur N fois!
567
-
568
-	if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
569
-		if (!isset($r[2]) or (!$r[2])) {
570
-			if (!$boucle->numrows) {
571
-				return "\n\t\$t0 = '';";
572
-			} else {
573
-				$corps = "";
574
-			}
575
-		} else {
576
-			$boucle->numrows = true;
577
-			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
578
-		}
579
-	} else {
580
-		$corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
581
-	}
582
-
583
-	$count = '';
584
-	if (!$boucle->select) {
585
-		if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
586
-			$count = '1';
587
-		} else {
588
-			$count = 'count(*)';
589
-		}
590
-		$boucles[$id_boucle]->select[] = $count;
591
-	}
592
-
593
-	if ($flag_cpt) {
594
-		$nums = "\n\t// COMPTEUR\n\t"
595
-			. "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
596
-	} else {
597
-		$nums = '';
598
-	}
599
-
600
-	if ($boucle->numrows or $boucle->mode_partie) {
601
-		$nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
602
-			. "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
603
-			. $boucle->mode_partie
604
-			. "\n\t";
605
-	}
606
-
607
-	// Ne calculer la requete que maintenant
608
-	// car ce qui precede appelle index_pile qui influe dessus
609
-
610
-	$init = (($init = $boucles[$id_boucle]->doublons)
611
-			? ("\n\t$init = array();") : '')
612
-		. calculer_requete_sql($boucles[$id_boucle]);
613
-
614
-	$contexte = memoriser_contexte_compil($boucle);
615
-
616
-	$a = sprintf(CODE_CORPS_BOUCLE,
617
-		$init,
618
-		$boucle->iterateur,
619
-		"\$command",
620
-		$contexte,
621
-		$nums,
622
-		$init_lang,
623
-		$corps,
624
-		$fin_lang,
625
-		$trace,
626
-		'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
627
-	);
467
+    $boucle = &$boucles[$id_boucle];
468
+    $return = $boucle->return;
469
+    $type_boucle = $boucle->type_requete;
470
+    $primary = $boucle->primary;
471
+    $constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
472
+    $flag_cpt = $boucle->mode_partie || $boucle->cptrows;
473
+    $corps = '';
474
+
475
+    // faudrait expanser le foreach a la compil, car y en a souvent qu'un 
476
+    // et puis faire un [] plutot qu'un "','."
477
+    if ($boucle->doublons) {
478
+        $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
479
+            index_pile($id_boucle, $primary, $boucles)
480
+            . "; // doublons\n";
481
+    }
482
+
483
+    // La boucle doit-elle selectionner la langue ?
484
+    // - par defaut, les boucles suivantes le font
485
+    //    (sauf si forcer_lang==true ou si le titre contient <multi>).
486
+    // - a moins d'une demande explicite via {!lang_select}
487
+    if (!$constant && $boucle->lang_select != 'non' &&
488
+        (($boucle->lang_select == 'oui') ||
489
+            in_array($type_boucle, array(
490
+                'articles',
491
+                'rubriques',
492
+                'hierarchie',
493
+                'breves'
494
+            )))
495
+    ) {
496
+        // Memoriser la langue avant la boucle et la restituer apres
497
+        // afin que le corps de boucle affecte la globale directement
498
+        $init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
499
+        $fin_lang = "lang_select();\n\t";
500
+        $fin_lang_select_public = "\n\t\tlang_select();";
501
+
502
+        $corps .=
503
+            "\n\t\tlang_select_public("
504
+            . index_pile($id_boucle, 'lang', $boucles)
505
+            . ", '" . $boucle->lang_select . "'"
506
+            . (in_array($type_boucle, array(
507
+                'articles',
508
+                'rubriques',
509
+                'hierarchie',
510
+                'breves'
511
+            )) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
512
+            . ');';
513
+    } else {
514
+        $init_lang = '';
515
+        $fin_lang = '';
516
+        $fin_lang_select_public = '';
517
+        // sortir les appels au traducteur (invariants de boucle)
518
+        if (strpos($return, '?php') === false
519
+            and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
520
+        ) {
521
+            $i = 1;
522
+            foreach ($r[1] as $t) {
523
+                $init_lang .= "\n\t\$l$i = $t;";
524
+                $return = str_replace($t, "\$l$i", $return);
525
+                $i++;
526
+            }
527
+        }
528
+    }
529
+
530
+    // gestion optimale des separateurs et des boucles constantes
531
+    if (count($boucle->separateur)) {
532
+        $code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
533
+    }
534
+
535
+    $corps .=
536
+        ((!$boucle->separateur) ?
537
+            (($constant && !$corps && !$flag_cpt) ? $return :
538
+                (($return === "''") ? '' :
539
+                    ("\n\t\t" . '$t0 .= ' . $return . ";"))) :
540
+            ("\n\t\t\$t1 " .
541
+                ((strpos($return, '$t1.') === 0) ?
542
+                    (".=" . substr($return, 4)) :
543
+                    ('= ' . $return)) .
544
+                ";\n\t\t" .
545
+                '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
546
+
547
+    // Calculer les invalideurs si c'est une boucle non constante et si on
548
+    // souhaite invalider ces elements
549
+    if (!$constant and $primary) {
550
+        include_spip('inc/invalideur');
551
+        $corps = calcul_invalideurs($corps, $primary,$boucles, $id_boucle);
552
+    }
553
+
554
+    // gerer le compteur de boucle 
555
+    // avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
556
+
557
+    if ($boucle->partie or $boucle->cptrows) {
558
+        $corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
559
+            . $boucle->partie
560
+            . $corps;
561
+    }
562
+
563
+    // depiler la lang de la boucle si besoin
564
+    $corps .= $fin_lang_select_public;
565
+
566
+    // si le corps est une constante, ne pas appeler le serveur N fois!
567
+
568
+    if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
569
+        if (!isset($r[2]) or (!$r[2])) {
570
+            if (!$boucle->numrows) {
571
+                return "\n\t\$t0 = '';";
572
+            } else {
573
+                $corps = "";
574
+            }
575
+        } else {
576
+            $boucle->numrows = true;
577
+            $corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
578
+        }
579
+    } else {
580
+        $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
581
+    }
582
+
583
+    $count = '';
584
+    if (!$boucle->select) {
585
+        if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
586
+            $count = '1';
587
+        } else {
588
+            $count = 'count(*)';
589
+        }
590
+        $boucles[$id_boucle]->select[] = $count;
591
+    }
592
+
593
+    if ($flag_cpt) {
594
+        $nums = "\n\t// COMPTEUR\n\t"
595
+            . "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
596
+    } else {
597
+        $nums = '';
598
+    }
599
+
600
+    if ($boucle->numrows or $boucle->mode_partie) {
601
+        $nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
602
+            . "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
603
+            . $boucle->mode_partie
604
+            . "\n\t";
605
+    }
606
+
607
+    // Ne calculer la requete que maintenant
608
+    // car ce qui precede appelle index_pile qui influe dessus
609
+
610
+    $init = (($init = $boucles[$id_boucle]->doublons)
611
+            ? ("\n\t$init = array();") : '')
612
+        . calculer_requete_sql($boucles[$id_boucle]);
613
+
614
+    $contexte = memoriser_contexte_compil($boucle);
615
+
616
+    $a = sprintf(CODE_CORPS_BOUCLE,
617
+        $init,
618
+        $boucle->iterateur,
619
+        "\$command",
620
+        $contexte,
621
+        $nums,
622
+        $init_lang,
623
+        $corps,
624
+        $fin_lang,
625
+        $trace,
626
+        'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
627
+    );
628 628
 
629 629
 #	var_dump($a);exit;
630
-	return $a;
630
+    return $a;
631 631
 }
632 632
 
633 633
 
@@ -643,43 +643,43 @@  discard block
 block discarded – undo
643 643
  *     Code PHP compilé définissant les informations de requête
644 644
  **/
645 645
 function calculer_requete_sql($boucle) {
646
-	$init = array();
647
-	$init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
648
-	$init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
649
-	# En absence de champ c'est un decompte :
650
-	$init[] = calculer_dec('from', calculer_from($boucle));
651
-	$init[] = calculer_dec('type', calculer_from_type($boucle));
652
-	$init[] = calculer_dec('groupby',
653
-		'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ")");
654
-	$init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . "\")");
655
-	$init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ")");
656
-	$init[] = calculer_dec('where', calculer_dump_array($boucle->where));
657
-	$init[] = calculer_dec('join', calculer_dump_join($boucle->join));
658
-	$init[] = calculer_dec('limit',
659
-		(strpos($boucle->limit, 'intval') === false ?
660
-			"'" . $boucle->limit . "'"
661
-			:
662
-			$boucle->limit));
663
-	$init[] = calculer_dec('having', calculer_dump_array($boucle->having));
664
-	$s = $d = "";
665
-	// l'index 0 de $i indique si l'affectation est statique (contenu)
666
-	// ou recalculée à chaque passage (vide)
667
-	foreach ($init as $i) {
668
-		if (reset($i)) {
669
-			$s .= "\n\t\t" . end($i);
670
-		} # statique
671
-		else {
672
-			$d .= "\n\t" . end($i);
673
-		} # dynamique
674
-	}
675
-
676
-	return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
677
-	. $boucle->in
678
-	. $boucle->hash
679
-	. "\n\t" . 'if (!isset($command[\'table\'])) {'
680
-	. $s
681
-	. "\n\t}"
682
-	. $d;
646
+    $init = array();
647
+    $init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
648
+    $init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
649
+    # En absence de champ c'est un decompte :
650
+    $init[] = calculer_dec('from', calculer_from($boucle));
651
+    $init[] = calculer_dec('type', calculer_from_type($boucle));
652
+    $init[] = calculer_dec('groupby',
653
+        'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ")");
654
+    $init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . "\")");
655
+    $init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ")");
656
+    $init[] = calculer_dec('where', calculer_dump_array($boucle->where));
657
+    $init[] = calculer_dec('join', calculer_dump_join($boucle->join));
658
+    $init[] = calculer_dec('limit',
659
+        (strpos($boucle->limit, 'intval') === false ?
660
+            "'" . $boucle->limit . "'"
661
+            :
662
+            $boucle->limit));
663
+    $init[] = calculer_dec('having', calculer_dump_array($boucle->having));
664
+    $s = $d = "";
665
+    // l'index 0 de $i indique si l'affectation est statique (contenu)
666
+    // ou recalculée à chaque passage (vide)
667
+    foreach ($init as $i) {
668
+        if (reset($i)) {
669
+            $s .= "\n\t\t" . end($i);
670
+        } # statique
671
+        else {
672
+            $d .= "\n\t" . end($i);
673
+        } # dynamique
674
+    }
675
+
676
+    return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
677
+    . $boucle->in
678
+    . $boucle->hash
679
+    . "\n\t" . 'if (!isset($command[\'table\'])) {'
680
+    . $s
681
+    . "\n\t}"
682
+    . $d;
683 683
 }
684 684
 
685 685
 /**
@@ -697,13 +697,13 @@  discard block
 block discarded – undo
697 697
  *     qui peut être utilisé pour la production d'un tableau array()
698 698
  **/
699 699
 function memoriser_contexte_compil($p) {
700
-	return join(',', array(
701
-		_q(isset($p->descr['sourcefile']) ? $p->descr['sourcefile'] : ''),
702
-		_q(isset($p->descr['nom']) ? $p->descr['nom'] : ''),
703
-		_q(isset($p->id_boucle) ? $p->id_boucle : null),
704
-		intval($p->ligne),
705
-		'$GLOBALS[\'spip_lang\']'
706
-	));
700
+    return join(',', array(
701
+        _q(isset($p->descr['sourcefile']) ? $p->descr['sourcefile'] : ''),
702
+        _q(isset($p->descr['nom']) ? $p->descr['nom'] : ''),
703
+        _q(isset($p->id_boucle) ? $p->id_boucle : null),
704
+        intval($p->ligne),
705
+        '$GLOBALS[\'spip_lang\']'
706
+    ));
707 707
 }
708 708
 
709 709
 /**
@@ -721,19 +721,19 @@  discard block
 block discarded – undo
721 721
  *     Objet Contexte
722 722
  **/
723 723
 function reconstruire_contexte_compil($context_compil) {
724
-	if (!is_array($context_compil)) {
725
-		return $context_compil;
726
-	}
727
-	$p = new Contexte;
728
-	$p->descr = array(
729
-		'sourcefile' => $context_compil[0],
730
-		'nom' => $context_compil[1]
731
-	);
732
-	$p->id_boucle = $context_compil[2];
733
-	$p->ligne = $context_compil[3];
734
-	$p->lang = $context_compil[4];
735
-
736
-	return $p;
724
+    if (!is_array($context_compil)) {
725
+        return $context_compil;
726
+    }
727
+    $p = new Contexte;
728
+    $p->descr = array(
729
+        'sourcefile' => $context_compil[0],
730
+        'nom' => $context_compil[1]
731
+    );
732
+    $p->id_boucle = $context_compil[2];
733
+    $p->ligne = $context_compil[3];
734
+    $p->lang = $context_compil[4];
735
+
736
+    return $p;
737 737
 }
738 738
 
739 739
 /**
@@ -759,12 +759,12 @@  discard block
 block discarded – undo
759 759
  *    - index 1 : Code de l'affectation
760 760
  **/
761 761
 function calculer_dec($nom, $val) {
762
-	$static = 'if (!isset($command[\'' . $nom . '\'])) ';
763
-	// si une variable apparait dans le calcul de la clause
764
-	// il faut la re-evaluer a chaque passage
765
-	if (
766
-		strpos($val, '$') !== false
767
-		/*
762
+    $static = 'if (!isset($command[\'' . $nom . '\'])) ';
763
+    // si une variable apparait dans le calcul de la clause
764
+    // il faut la re-evaluer a chaque passage
765
+    if (
766
+        strpos($val, '$') !== false
767
+        /*
768 768
 		OR strpos($val, 'sql_') !== false
769 769
 		OR (
770 770
 			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
@@ -772,11 +772,11 @@  discard block
 block discarded – undo
772 772
 			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
773 773
 			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
774 774
 		)*/
775
-	) {
776
-		$static = "";
777
-	}
775
+    ) {
776
+        $static = "";
777
+    }
778 778
 
779
-	return array($static, '$command[\'' . $nom . '\'] = ' . $val . ';');
779
+    return array($static, '$command[\'' . $nom . '\'] = ' . $val . ';');
780 780
 }
781 781
 
782 782
 /**
@@ -796,32 +796,32 @@  discard block
 block discarded – undo
796 796
  *     Expression PHP décrivant un texte ou un tableau
797 797
  **/
798 798
 function calculer_dump_array($a) {
799
-	if (!is_array($a)) {
800
-		return $a;
801
-	}
802
-	$res = "";
803
-	if ($a and $a[0] == "'?'") {
804
-		return ("(" . calculer_dump_array($a[1]) .
805
-			" ? " . calculer_dump_array($a[2]) .
806
-			" : " . calculer_dump_array($a[3]) .
807
-			")");
808
-	} else {
809
-		foreach ($a as $v) {
810
-			$res .= ", " . calculer_dump_array($v);
811
-		}
812
-
813
-		return "\n\t\t\tarray(" . substr($res, 2) . ')';
814
-	}
799
+    if (!is_array($a)) {
800
+        return $a;
801
+    }
802
+    $res = "";
803
+    if ($a and $a[0] == "'?'") {
804
+        return ("(" . calculer_dump_array($a[1]) .
805
+            " ? " . calculer_dump_array($a[2]) .
806
+            " : " . calculer_dump_array($a[3]) .
807
+            ")");
808
+    } else {
809
+        foreach ($a as $v) {
810
+            $res .= ", " . calculer_dump_array($v);
811
+        }
812
+
813
+        return "\n\t\t\tarray(" . substr($res, 2) . ')';
814
+    }
815 815
 }
816 816
 
817 817
 // https://code.spip.net/@calculer_dump_join
818 818
 function calculer_dump_join($a) {
819
-	$res = "";
820
-	foreach ($a as $k => $v) {
821
-		$res .= ", '$k' => array(" . implode(',', $v) . ")";
822
-	}
819
+    $res = "";
820
+    foreach ($a as $k => $v) {
821
+        $res .= ", '$k' => array(" . implode(',', $v) . ")";
822
+    }
823 823
 
824
-	return 'array(' . substr($res, 2) . ')';
824
+    return 'array(' . substr($res, 2) . ')';
825 825
 }
826 826
 
827 827
 /**
@@ -833,12 +833,12 @@  discard block
 block discarded – undo
833 833
  *     Code PHP construisant un tableau des alias et noms des tables du FROM
834 834
  **/
835 835
 function calculer_from(&$boucle) {
836
-	$res = "";
837
-	foreach ($boucle->from as $k => $v) {
838
-		$res .= ",'$k' => '$v'";
839
-	}
836
+    $res = "";
837
+    foreach ($boucle->from as $k => $v) {
838
+        $res .= ",'$k' => '$v'";
839
+    }
840 840
 
841
-	return 'array(' . substr($res, 1) . ')';
841
+    return 'array(' . substr($res, 1) . ')';
842 842
 }
843 843
 
844 844
 /**
@@ -851,30 +851,30 @@  discard block
 block discarded – undo
851 851
  *     Code PHP construisant un tableau des alias et type de jointure du FROM
852 852
  **/
853 853
 function calculer_from_type(&$boucle) {
854
-	$res = "";
855
-	foreach ($boucle->from_type as $k => $v) {
856
-		$res .= ",'$k' => '$v'";
857
-	}
854
+    $res = "";
855
+    foreach ($boucle->from_type as $k => $v) {
856
+        $res .= ",'$k' => '$v'";
857
+    }
858 858
 
859
-	return 'array(' . substr($res, 1) . ')';
859
+    return 'array(' . substr($res, 1) . ')';
860 860
 }
861 861
 
862 862
 // https://code.spip.net/@calculer_order
863 863
 function calculer_order(&$boucle) {
864
-	if (!$order = $boucle->order
865
-		and !$order = $boucle->default_order
866
-	) {
867
-		$order = array();
868
-	}
864
+    if (!$order = $boucle->order
865
+        and !$order = $boucle->default_order
866
+    ) {
867
+        $order = array();
868
+    }
869 869
 
870
-	/*if (isset($boucle->modificateur['collate'])){
870
+    /*if (isset($boucle->modificateur['collate'])){
871 871
 		$col = "." . $boucle->modificateur['collate'];
872 872
 		foreach($order as $k=>$o)
873 873
 			if (strpos($order[$k],'COLLATE')===false)
874 874
 				$order[$k].= $col;
875 875
 	}*/
876 876
 
877
-	return join(', ', $order);
877
+    return join(', ', $order);
878 878
 }
879 879
 
880 880
 // Production du code PHP a partir de la sequence livree par le phraseur
@@ -884,59 +884,59 @@  discard block
 block discarded – undo
884 884
 
885 885
 // https://code.spip.net/@calculer_liste
886 886
 function calculer_liste($tableau, $descr, &$boucles, $id_boucle = '') {
887
-	if (!$tableau) {
888
-		return "''";
889
-	}
890
-	if (is_string($descr)) {
891
-		if (isset($boucles[$descr])) {
892
-			$idb = $descr;
893
-			$descr = [];
894
-			if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
895
-				$descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
896
-			}
897
-			if (isset($boucles[$idb]->descr['sourcefile'])) {
898
-				$descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
899
-			}
900
-		}
901
-		else {
902
-			$descr = array();
903
-		}
904
-	}
905
-	if (!isset($descr['niv'])) {
906
-		$descr['niv'] = 0;
907
-	}
908
-	$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
909
-	if ($codes === false) {
910
-		return false;
911
-	}
912
-	$n = count($codes);
913
-	if (!$n) {
914
-		return "''";
915
-	}
916
-	$tab = str_repeat("\t", $descr['niv']);
917
-	if (_request('var_mode_affiche') != 'validation') {
918
-		if ($n == 1) {
919
-			return $codes[0];
920
-		} else {
921
-			$res = '';
922
-			foreach ($codes as $code) {
923
-				if (!preg_match("/^'[^']*'$/", $code)
924
-					or substr($res, -1, 1) !== "'"
925
-				) {
926
-					$res .= " .\n$tab$code";
927
-				} else {
928
-					$res = substr($res, 0, -1) . substr($code, 1);
929
-				}
930
-			}
931
-
932
-			return '(' . substr($res, 2 + $descr['niv']) . ')';
933
-		}
934
-	} else {
935
-		$nom = $descr['nom'] . $id_boucle . ($descr['niv'] ? $descr['niv'] : '');
936
-
937
-		return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(" ,\n$tab",
938
-			$codes) . ")))";
939
-	}
887
+    if (!$tableau) {
888
+        return "''";
889
+    }
890
+    if (is_string($descr)) {
891
+        if (isset($boucles[$descr])) {
892
+            $idb = $descr;
893
+            $descr = [];
894
+            if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
895
+                $descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
896
+            }
897
+            if (isset($boucles[$idb]->descr['sourcefile'])) {
898
+                $descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
899
+            }
900
+        }
901
+        else {
902
+            $descr = array();
903
+        }
904
+    }
905
+    if (!isset($descr['niv'])) {
906
+        $descr['niv'] = 0;
907
+    }
908
+    $codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
909
+    if ($codes === false) {
910
+        return false;
911
+    }
912
+    $n = count($codes);
913
+    if (!$n) {
914
+        return "''";
915
+    }
916
+    $tab = str_repeat("\t", $descr['niv']);
917
+    if (_request('var_mode_affiche') != 'validation') {
918
+        if ($n == 1) {
919
+            return $codes[0];
920
+        } else {
921
+            $res = '';
922
+            foreach ($codes as $code) {
923
+                if (!preg_match("/^'[^']*'$/", $code)
924
+                    or substr($res, -1, 1) !== "'"
925
+                ) {
926
+                    $res .= " .\n$tab$code";
927
+                } else {
928
+                    $res = substr($res, 0, -1) . substr($code, 1);
929
+                }
930
+            }
931
+
932
+            return '(' . substr($res, 2 + $descr['niv']) . ')';
933
+        }
934
+    } else {
935
+        $nom = $descr['nom'] . $id_boucle . ($descr['niv'] ? $descr['niv'] : '');
936
+
937
+        return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(" ,\n$tab",
938
+            $codes) . ")))";
939
+    }
940 940
 }
941 941
 
942 942
 
@@ -947,203 +947,203 @@  discard block
 block discarded – undo
947 947
 // https://code.spip.net/@compile_cas
948 948
 function compile_cas($tableau, $descr, &$boucles, $id_boucle) {
949 949
 
950
-	$codes = array();
951
-	// cas de la boucle recursive
952
-	if (is_array($id_boucle)) {
953
-		$id_boucle = $id_boucle[0];
954
-	}
955
-	$type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
956
-	$tab = str_repeat("\t", ++$descr['niv']);
957
-	$mode = _request('var_mode_affiche');
958
-	$err_e_c = '';
959
-	// chaque commentaire introduit dans le code doit commencer
960
-	// par un caractere distinguant le cas, pour exploitation par debug.
961
-	foreach ($tableau as $p) {
962
-
963
-		switch ($p->type) {
964
-			// texte seul
965
-			case 'texte':
966
-				$code = sandbox_composer_texte($p->texte, $p);
967
-				$commentaire = strlen($p->texte) . " signes";
968
-				$avant = '';
969
-				$apres = '';
970
-				$altern = "''";
971
-				break;
972
-
973
-			case 'polyglotte':
974
-				$code = "";
975
-				foreach ($p->traductions as $k => $v) {
976
-					$code .= ",'" .
977
-						str_replace(array("\\", "'"), array("\\\\", "\\'"), $k) .
978
-						"' => '" .
979
-						str_replace(array("\\", "'"), array("\\\\", "\\'"), $v) .
980
-						"'";
981
-				}
982
-				$code = "choisir_traduction(array(" .
983
-					substr($code, 1) .
984
-					"))";
985
-				$commentaire = '&';
986
-				$avant = '';
987
-				$apres = '';
988
-				$altern = "''";
989
-				break;
990
-
991
-			// inclure
992
-			case 'include':
993
-				$p->descr = $descr;
994
-				$code = calculer_inclure($p, $boucles, $id_boucle);
995
-				if ($code === false) {
996
-					$err_e_c = true;
997
-					$code = "''";
998
-				} else {
999
-					$commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1000
-					$avant = '';
1001
-					$apres = '';
1002
-					$altern = "''";
1003
-				}
1004
-				break;
1005
-
1006
-			// boucle
1007
-			case TYPE_RECURSIF:
1008
-				$nom = $p->id_boucle;
1009
-				$newdescr = $descr;
1010
-				$newdescr['id_mere'] = $nom;
1011
-				$newdescr['niv']++;
1012
-				$preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1013
-				$avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1014
-				$apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1015
-				$postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1016
-				$newdescr['niv']--;
1017
-				$altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1018
-				if ($preaff === false
1019
-					or $avant === false
1020
-					or $apres === false
1021
-					or $altern === false
1022
-					or $postaff === false) {
1023
-					$err_e_c = true;
1024
-					$code = "''";
1025
-				} else {
1026
-					$code = 'BOUCLE' .
1027
-						str_replace("-", "_", $nom) . $descr['nom'] .
1028
-						'($Cache, $Pile, $doublons, $Numrows, $SP)';
1029
-					$commentaire = "?$nom";
1030
-					if (!$boucles[$nom]->milieu
1031
-						and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1032
-					) {
1033
-						if ($preaff != "''") {
1034
-							$code .= "\n. $preaff";
1035
-						}
1036
-						if ($altern != "''") {
1037
-							$code .= "\n. $altern";
1038
-						}
1039
-						if ($postaff != "''") {
1040
-							$code .= "\n. $postaff";
1041
-						}
1042
-						if ($avant <> "''" or $apres <> "''") {
1043
-							spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1044
-						}
1045
-						$avant = $apres = $altern = "''";
1046
-					} else {
1047
-						if ($preaff != "''") {
1048
-							$avant = compile_concatene_parties_codes($preaff, $avant);
1049
-							$altern = compile_concatene_parties_codes($preaff, $altern);
1050
-						}
1051
-						if ($postaff != "''") {
1052
-							$apres = compile_concatene_parties_codes($apres, $postaff);
1053
-							$altern = compile_concatene_parties_codes($altern, $postaff);
1054
-						}
1055
-						if ($altern != "''") {
1056
-							$altern = "($altern)";
1057
-						}
1058
-					}
1059
-				}
1060
-				break;
1061
-
1062
-			case 'idiome':
1063
-				$l = array();
1064
-				$code = '';
1065
-				foreach ($p->arg as $k => $v) {
1066
-					$_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1067
-					if ($k) {
1068
-						$l[] = _q($k) . ' => ' . $_v;
1069
-					} else {
1070
-						$code = $_v;
1071
-					}
1072
-				}
1073
-				// Si le module n'est pas fourni, l'expliciter sauf si calculé
1074
-				if ($p->module) {
1075
-					$m = $p->module . ':' . $p->nom_champ;
1076
-				} elseif ($p->nom_champ) {
1077
-					$m = MODULES_IDIOMES . ':' . $p->nom_champ;
1078
-				} else {
1079
-					$m = '';
1080
-				}
1081
-
1082
-				$code = (!$code ? "'$m'" :
1083
-						($m ? "'$m' . $code" :
1084
-							("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1085
-					. (!$l ? '' : (", array(" . implode(",\n", $l) . ")"));
1086
-				$code = "_T($code)";
1087
-				if ($p->param) {
1088
-					$p->id_boucle = $id_boucle;
1089
-					$p->boucles = &$boucles;
1090
-					$code = compose_filtres($p, $code);
1091
-				}
1092
-				$commentaire = ":";
1093
-				$avant = '';
1094
-				$apres = '';
1095
-				$altern = "''";
1096
-				break;
1097
-
1098
-			case 'champ':
1099
-
1100
-				// cette structure pourrait etre completee des le phrase' (a faire)
1101
-				$p->id_boucle = $id_boucle;
1102
-				$p->boucles = &$boucles;
1103
-				$p->descr = $descr;
1104
-				#$p->interdire_scripts = true;
1105
-				$p->type_requete = $type;
1106
-
1107
-				$code = calculer_champ($p);
1108
-				$commentaire = '#' . $p->nom_champ . $p->etoile;
1109
-				$avant = calculer_liste($p->avant,
1110
-					$descr, $boucles, $id_boucle);
1111
-				$apres = calculer_liste($p->apres,
1112
-					$descr, $boucles, $id_boucle);
1113
-				$altern = "''";
1114
-				// Si la valeur est destinee a une comparaison a ''
1115
-				// forcer la conversion en une chaine par strval
1116
-				// si ca peut etre autre chose qu'une chaine
1117
-				if (($avant != "''" or $apres != "''")
1118
-					and $code[0] != "'"
950
+    $codes = array();
951
+    // cas de la boucle recursive
952
+    if (is_array($id_boucle)) {
953
+        $id_boucle = $id_boucle[0];
954
+    }
955
+    $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
956
+    $tab = str_repeat("\t", ++$descr['niv']);
957
+    $mode = _request('var_mode_affiche');
958
+    $err_e_c = '';
959
+    // chaque commentaire introduit dans le code doit commencer
960
+    // par un caractere distinguant le cas, pour exploitation par debug.
961
+    foreach ($tableau as $p) {
962
+
963
+        switch ($p->type) {
964
+            // texte seul
965
+            case 'texte':
966
+                $code = sandbox_composer_texte($p->texte, $p);
967
+                $commentaire = strlen($p->texte) . " signes";
968
+                $avant = '';
969
+                $apres = '';
970
+                $altern = "''";
971
+                break;
972
+
973
+            case 'polyglotte':
974
+                $code = "";
975
+                foreach ($p->traductions as $k => $v) {
976
+                    $code .= ",'" .
977
+                        str_replace(array("\\", "'"), array("\\\\", "\\'"), $k) .
978
+                        "' => '" .
979
+                        str_replace(array("\\", "'"), array("\\\\", "\\'"), $v) .
980
+                        "'";
981
+                }
982
+                $code = "choisir_traduction(array(" .
983
+                    substr($code, 1) .
984
+                    "))";
985
+                $commentaire = '&';
986
+                $avant = '';
987
+                $apres = '';
988
+                $altern = "''";
989
+                break;
990
+
991
+            // inclure
992
+            case 'include':
993
+                $p->descr = $descr;
994
+                $code = calculer_inclure($p, $boucles, $id_boucle);
995
+                if ($code === false) {
996
+                    $err_e_c = true;
997
+                    $code = "''";
998
+                } else {
999
+                    $commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1000
+                    $avant = '';
1001
+                    $apres = '';
1002
+                    $altern = "''";
1003
+                }
1004
+                break;
1005
+
1006
+            // boucle
1007
+            case TYPE_RECURSIF:
1008
+                $nom = $p->id_boucle;
1009
+                $newdescr = $descr;
1010
+                $newdescr['id_mere'] = $nom;
1011
+                $newdescr['niv']++;
1012
+                $preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1013
+                $avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1014
+                $apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1015
+                $postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1016
+                $newdescr['niv']--;
1017
+                $altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1018
+                if ($preaff === false
1019
+                    or $avant === false
1020
+                    or $apres === false
1021
+                    or $altern === false
1022
+                    or $postaff === false) {
1023
+                    $err_e_c = true;
1024
+                    $code = "''";
1025
+                } else {
1026
+                    $code = 'BOUCLE' .
1027
+                        str_replace("-", "_", $nom) . $descr['nom'] .
1028
+                        '($Cache, $Pile, $doublons, $Numrows, $SP)';
1029
+                    $commentaire = "?$nom";
1030
+                    if (!$boucles[$nom]->milieu
1031
+                        and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1032
+                    ) {
1033
+                        if ($preaff != "''") {
1034
+                            $code .= "\n. $preaff";
1035
+                        }
1036
+                        if ($altern != "''") {
1037
+                            $code .= "\n. $altern";
1038
+                        }
1039
+                        if ($postaff != "''") {
1040
+                            $code .= "\n. $postaff";
1041
+                        }
1042
+                        if ($avant <> "''" or $apres <> "''") {
1043
+                            spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1044
+                        }
1045
+                        $avant = $apres = $altern = "''";
1046
+                    } else {
1047
+                        if ($preaff != "''") {
1048
+                            $avant = compile_concatene_parties_codes($preaff, $avant);
1049
+                            $altern = compile_concatene_parties_codes($preaff, $altern);
1050
+                        }
1051
+                        if ($postaff != "''") {
1052
+                            $apres = compile_concatene_parties_codes($apres, $postaff);
1053
+                            $altern = compile_concatene_parties_codes($altern, $postaff);
1054
+                        }
1055
+                        if ($altern != "''") {
1056
+                            $altern = "($altern)";
1057
+                        }
1058
+                    }
1059
+                }
1060
+                break;
1061
+
1062
+            case 'idiome':
1063
+                $l = array();
1064
+                $code = '';
1065
+                foreach ($p->arg as $k => $v) {
1066
+                    $_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1067
+                    if ($k) {
1068
+                        $l[] = _q($k) . ' => ' . $_v;
1069
+                    } else {
1070
+                        $code = $_v;
1071
+                    }
1072
+                }
1073
+                // Si le module n'est pas fourni, l'expliciter sauf si calculé
1074
+                if ($p->module) {
1075
+                    $m = $p->module . ':' . $p->nom_champ;
1076
+                } elseif ($p->nom_champ) {
1077
+                    $m = MODULES_IDIOMES . ':' . $p->nom_champ;
1078
+                } else {
1079
+                    $m = '';
1080
+                }
1081
+
1082
+                $code = (!$code ? "'$m'" :
1083
+                        ($m ? "'$m' . $code" :
1084
+                            ("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1085
+                    . (!$l ? '' : (", array(" . implode(",\n", $l) . ")"));
1086
+                $code = "_T($code)";
1087
+                if ($p->param) {
1088
+                    $p->id_boucle = $id_boucle;
1089
+                    $p->boucles = &$boucles;
1090
+                    $code = compose_filtres($p, $code);
1091
+                }
1092
+                $commentaire = ":";
1093
+                $avant = '';
1094
+                $apres = '';
1095
+                $altern = "''";
1096
+                break;
1097
+
1098
+            case 'champ':
1099
+
1100
+                // cette structure pourrait etre completee des le phrase' (a faire)
1101
+                $p->id_boucle = $id_boucle;
1102
+                $p->boucles = &$boucles;
1103
+                $p->descr = $descr;
1104
+                #$p->interdire_scripts = true;
1105
+                $p->type_requete = $type;
1106
+
1107
+                $code = calculer_champ($p);
1108
+                $commentaire = '#' . $p->nom_champ . $p->etoile;
1109
+                $avant = calculer_liste($p->avant,
1110
+                    $descr, $boucles, $id_boucle);
1111
+                $apres = calculer_liste($p->apres,
1112
+                    $descr, $boucles, $id_boucle);
1113
+                $altern = "''";
1114
+                // Si la valeur est destinee a une comparaison a ''
1115
+                // forcer la conversion en une chaine par strval
1116
+                // si ca peut etre autre chose qu'une chaine
1117
+                if (($avant != "''" or $apres != "''")
1118
+                    and $code[0] != "'"
1119 1119
 #			AND (strpos($code,'interdire_scripts') !== 0)
1120
-					and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1121
-					and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1122
-					and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1123
-				) {
1124
-					$code = "strval($code)";
1125
-				}
1126
-				break;
1127
-
1128
-			default:
1129
-				// Erreur de construction de l'arbre de syntaxe abstraite
1130
-				$code = "''";
1131
-				$p->descr = $descr;
1132
-				$err_e_c = _T('zbug_erreur_compilation');
1133
-				erreur_squelette($err_e_c, $p);
1134
-		} // switch
1135
-
1136
-		if ($code != "''") {
1137
-			$code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1138
-			$codes[] = (($mode == 'validation') ?
1139
-				"array($code, '$commentaire', " . $p->ligne . ")"
1140
-				: (($mode == 'code') ?
1141
-					"\n// $commentaire\n$code" :
1142
-					$code));
1143
-		}
1144
-	} // foreach
1145
-
1146
-	return $err_e_c ? false : $codes;
1120
+                    and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1121
+                    and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1122
+                    and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1123
+                ) {
1124
+                    $code = "strval($code)";
1125
+                }
1126
+                break;
1127
+
1128
+            default:
1129
+                // Erreur de construction de l'arbre de syntaxe abstraite
1130
+                $code = "''";
1131
+                $p->descr = $descr;
1132
+                $err_e_c = _T('zbug_erreur_compilation');
1133
+                erreur_squelette($err_e_c, $p);
1134
+        } // switch
1135
+
1136
+        if ($code != "''") {
1137
+            $code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1138
+            $codes[] = (($mode == 'validation') ?
1139
+                "array($code, '$commentaire', " . $p->ligne . ")"
1140
+                : (($mode == 'code') ?
1141
+                    "\n// $commentaire\n$code" :
1142
+                    $code));
1143
+        }
1144
+    } // foreach
1145
+
1146
+    return $err_e_c ? false : $codes;
1147 1147
 }
1148 1148
 
1149 1149
 /**
@@ -1153,13 +1153,13 @@  discard block
 block discarded – undo
1153 1153
  * @return string
1154 1154
  */
1155 1155
 function compile_concatene_parties_codes($partie1, $partie2) {
1156
-	if ($partie1 === "''") {
1157
-		return $partie2;
1158
-	}
1159
-	if ($partie2 === "''") {
1160
-		return $partie1;
1161
-	}
1162
-	return "$partie1\n. $partie2";
1156
+    if ($partie1 === "''") {
1157
+        return $partie2;
1158
+    }
1159
+    if ($partie2 === "''") {
1160
+        return $partie1;
1161
+    }
1162
+    return "$partie1\n. $partie2";
1163 1163
 }
1164 1164
 
1165 1165
 
@@ -1184,57 +1184,57 @@  discard block
 block discarded – undo
1184 1184
  * @return mixed|string
1185 1185
  */
1186 1186
 function compile_retour($code, $avant, $apres, $altern, $tab, $n) {
1187
-	if ($avant === "''") {
1188
-		$avant = '';
1189
-	}
1190
-	if ($apres === "''") {
1191
-		$apres = '';
1192
-	}
1193
-	if ($avant or $apres or ($altern !== "''")){
1194
-		if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)){
1195
-			$t = $code;
1196
-			$cond = '';
1197
-		} elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1198
-			$t = $r[2];
1199
-			$cond = '!' . $r[1];
1200
-		} else {
1201
-			if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)){
1202
-				$t = $r[2];
1203
-				$cond = $r[1];
1204
-			} else {
1205
-				$t = '$t' . $n;
1206
-				$cond = "($t = $code)!==''";
1207
-			}
1208
-		}
1209
-
1210
-		$res = (!$avant ? "" : "$avant . ") .
1211
-			$t .
1212
-			(!$apres ? "" : " . $apres");
1213
-
1214
-		if ($res!==$t){
1215
-			$res = "($res)";
1216
-		}
1217
-
1218
-		$code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1219
-	}
1220
-
1221
-	return $code;
1187
+    if ($avant === "''") {
1188
+        $avant = '';
1189
+    }
1190
+    if ($apres === "''") {
1191
+        $apres = '';
1192
+    }
1193
+    if ($avant or $apres or ($altern !== "''")){
1194
+        if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)){
1195
+            $t = $code;
1196
+            $cond = '';
1197
+        } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1198
+            $t = $r[2];
1199
+            $cond = '!' . $r[1];
1200
+        } else {
1201
+            if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)){
1202
+                $t = $r[2];
1203
+                $cond = $r[1];
1204
+            } else {
1205
+                $t = '$t' . $n;
1206
+                $cond = "($t = $code)!==''";
1207
+            }
1208
+        }
1209
+
1210
+        $res = (!$avant ? "" : "$avant . ") .
1211
+            $t .
1212
+            (!$apres ? "" : " . $apres");
1213
+
1214
+        if ($res!==$t){
1215
+            $res = "($res)";
1216
+        }
1217
+
1218
+        $code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1219
+    }
1220
+
1221
+    return $code;
1222 1222
 
1223 1223
 }
1224 1224
 
1225 1225
 
1226 1226
 function compile_inclure_doublons($lexemes) {
1227
-	foreach ($lexemes as $v) {
1228
-		if ($v->type === 'include' and $v->param) {
1229
-			foreach ($v->param as $r) {
1230
-				if (trim($r[0]) === 'doublons') {
1231
-					return true;
1232
-				}
1233
-			}
1234
-		}
1235
-	}
1236
-
1237
-	return false;
1227
+    foreach ($lexemes as $v) {
1228
+        if ($v->type === 'include' and $v->param) {
1229
+            foreach ($v->param as $r) {
1230
+                if (trim($r[0]) === 'doublons') {
1231
+                    return true;
1232
+                }
1233
+            }
1234
+        }
1235
+    }
1236
+
1237
+    return false;
1238 1238
 }
1239 1239
 
1240 1240
 // Prend en argument le texte d'un squelette, le nom de son fichier d'origine,
@@ -1254,348 +1254,348 @@  discard block
 block discarded – undo
1254 1254
 
1255 1255
 // https://code.spip.net/@public_compiler_dist
1256 1256
 function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect = '') {
1257
-	// Pre-traitement : reperer le charset du squelette, et le convertir
1258
-	// Bonus : supprime le BOM
1259
-	include_spip('inc/charsets');
1260
-	$squelette = transcoder_page($squelette);
1261
-
1262
-	// rendre inertes les echappements de #[](){}<>
1263
-	$i = 0;
1264
-	while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1265
-		$i++;
1266
-	}
1267
-	$squelette = preg_replace_callback(',\\\\([#[()\]{}<>]),',
1268
-		function($a) use ($inerte) {
1269
-			return "$inerte-" . ord($a[1]) . '-';
1270
-		},
1271
-		$squelette,
1272
-		-1,
1273
-		$esc
1274
-	);
1275
-
1276
-	$descr = array(
1277
-		'nom' => $nom,
1278
-		'gram' => $gram,
1279
-		'sourcefile' => $sourcefile,
1280
-		'squelette' => $squelette
1281
-	);
1282
-
1283
-	// Phraser le squelette, selon sa grammaire
1284
-
1285
-	$boucles = array();
1286
-	$f = charger_fonction('phraser_' . $gram, 'public');
1287
-
1288
-	$squelette = $f($squelette, '', $boucles, $descr);
1289
-
1290
-	$boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1291
-
1292
-	// restituer les echappements
1293
-	if ($esc) {
1294
-		foreach ($boucles as $i => $boucle) {
1295
-			$boucles[$i]->return = preg_replace_callback(
1296
-				",$inerte-(\d+)-,",
1297
-				function($a) {
1298
-					return chr($a[1]);
1299
-				},
1300
-				$boucle->return
1301
-			);
1302
-			$boucles[$i]->descr['squelette'] = preg_replace_callback(
1303
-				",$inerte-(\d+)-,",
1304
-				function($a) {
1305
-					return "\\\\" . chr($a[1]);
1306
-				},
1307
-				$boucle->descr['squelette']
1308
-			);
1309
-		}
1310
-	}
1311
-
1312
-	$debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1313
-	if ($debug) {
1314
-		include_spip('public/decompiler');
1315
-		foreach ($boucles as $id => $boucle) {
1316
-			if ($id) {
1317
-				$decomp = "\n/* BOUCLE " .
1318
-					$boucle->type_requete .
1319
-					" " .
1320
-					str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1321
-					($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1322
-					" */\n";
1323
-			} else {
1324
-				$decomp = ("\n/*\n" .
1325
-					str_replace('*/', '* /', public_decompiler($squelette, $gram))
1326
-					. "\n*/");
1327
-			}
1328
-			$boucles[$id]->return = $decomp . $boucle->return;
1329
-			$GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1330
-		}
1331
-	}
1332
-
1333
-	return $boucles;
1257
+    // Pre-traitement : reperer le charset du squelette, et le convertir
1258
+    // Bonus : supprime le BOM
1259
+    include_spip('inc/charsets');
1260
+    $squelette = transcoder_page($squelette);
1261
+
1262
+    // rendre inertes les echappements de #[](){}<>
1263
+    $i = 0;
1264
+    while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1265
+        $i++;
1266
+    }
1267
+    $squelette = preg_replace_callback(',\\\\([#[()\]{}<>]),',
1268
+        function($a) use ($inerte) {
1269
+            return "$inerte-" . ord($a[1]) . '-';
1270
+        },
1271
+        $squelette,
1272
+        -1,
1273
+        $esc
1274
+    );
1275
+
1276
+    $descr = array(
1277
+        'nom' => $nom,
1278
+        'gram' => $gram,
1279
+        'sourcefile' => $sourcefile,
1280
+        'squelette' => $squelette
1281
+    );
1282
+
1283
+    // Phraser le squelette, selon sa grammaire
1284
+
1285
+    $boucles = array();
1286
+    $f = charger_fonction('phraser_' . $gram, 'public');
1287
+
1288
+    $squelette = $f($squelette, '', $boucles, $descr);
1289
+
1290
+    $boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1291
+
1292
+    // restituer les echappements
1293
+    if ($esc) {
1294
+        foreach ($boucles as $i => $boucle) {
1295
+            $boucles[$i]->return = preg_replace_callback(
1296
+                ",$inerte-(\d+)-,",
1297
+                function($a) {
1298
+                    return chr($a[1]);
1299
+                },
1300
+                $boucle->return
1301
+            );
1302
+            $boucles[$i]->descr['squelette'] = preg_replace_callback(
1303
+                ",$inerte-(\d+)-,",
1304
+                function($a) {
1305
+                    return "\\\\" . chr($a[1]);
1306
+                },
1307
+                $boucle->descr['squelette']
1308
+            );
1309
+        }
1310
+    }
1311
+
1312
+    $debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1313
+    if ($debug) {
1314
+        include_spip('public/decompiler');
1315
+        foreach ($boucles as $id => $boucle) {
1316
+            if ($id) {
1317
+                $decomp = "\n/* BOUCLE " .
1318
+                    $boucle->type_requete .
1319
+                    " " .
1320
+                    str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1321
+                    ($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1322
+                    " */\n";
1323
+            } else {
1324
+                $decomp = ("\n/*\n" .
1325
+                    str_replace('*/', '* /', public_decompiler($squelette, $gram))
1326
+                    . "\n*/");
1327
+            }
1328
+            $boucles[$id]->return = $decomp . $boucle->return;
1329
+            $GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1330
+        }
1331
+    }
1332
+
1333
+    return $boucles;
1334 1334
 }
1335 1335
 
1336 1336
 // Point d'entree pour arbre de syntaxe abstraite fourni en premier argument
1337 1337
 // Autres specifications comme ci-dessus
1338 1338
 
1339 1339
 function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect = '') {
1340
-	static $trouver_table;
1341
-	spip_timer('calcul_skel');
1342
-
1343
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1344
-		$GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1345
-		$GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1346
-
1347
-		if (!isset($GLOBALS['debug_objets']['principal'])) {
1348
-			$GLOBALS['debug_objets']['principal'] = $nom;
1349
-		}
1350
-	}
1351
-	foreach ($boucles as $id => $boucle) {
1352
-		$GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1353
-	}
1354
-	$descr['documents'] = compile_inclure_doublons($squelette);
1355
-
1356
-	// Demander la description des tables une fois pour toutes
1357
-	if (!$trouver_table) {
1358
-		$trouver_table = charger_fonction('trouver_table', 'base');
1359
-	}
1360
-
1361
-	// reperer si les doublons sont demandes
1362
-	// pour un inclure ou une boucle document
1363
-	// c'est utile a la fonction champs_traitements
1364
-	foreach ($boucles as $id => $boucle) {
1365
-		if (!($type = $boucle->type_requete)) {
1366
-			continue;
1367
-		}
1368
-		if (!$descr['documents'] and (
1369
-				(($type == 'documents') and $boucle->doublons) or
1370
-				compile_inclure_doublons($boucle->avant) or
1371
-				compile_inclure_doublons($boucle->apres) or
1372
-				compile_inclure_doublons($boucle->milieu) or
1373
-				compile_inclure_doublons($boucle->altern))
1374
-		) {
1375
-			$descr['documents'] = true;
1376
-		}
1377
-		if ($type != TYPE_RECURSIF) {
1378
-			if (!$boucles[$id]->sql_serveur and $connect) {
1379
-				$boucles[$id]->sql_serveur = $connect;
1380
-			}
1381
-
1382
-			// chercher dans les iterateurs du repertoire iterateur/
1383
-			if ($g = charger_fonction(
1384
-				preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true)
1385
-			) {
1386
-				$boucles[$id] = $g($boucle);
1387
-
1388
-				// sinon, en cas de requeteur d'un type predefini,
1389
-				// utiliser les informations donnees par le requeteur
1390
-				// cas "php:xx" et "data:xx".
1391
-			} else {
1392
-				if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1393
-					$requeteur($boucles, $boucle, $id);
1394
-
1395
-					// utiliser la description des champs transmis
1396
-				} else {
1397
-					$show = $trouver_table($type, $boucles[$id]->sql_serveur);
1398
-					// si la table n'existe pas avec le connecteur par defaut,
1399
-					// c'est peut etre une table qui necessite son connecteur dedie fourni
1400
-					// permet une ecriture allegee (GEO) -> (geo:GEO)
1401
-					if (!$show
1402
-						and $show = $trouver_table($type, strtolower($type))
1403
-					) {
1404
-						$boucles[$id]->sql_serveur = strtolower($type);
1405
-					}
1406
-					if ($show) {
1407
-						$boucles[$id]->show = $show;
1408
-						// recopie les infos les plus importantes
1409
-						$boucles[$id]->primary = isset($show['key']["PRIMARY KEY"]) ? $show['key']["PRIMARY KEY"] : '';
1410
-						$boucles[$id]->id_table = $x = preg_replace(",^spip_,", "", $show['id_table']);
1411
-						$boucles[$id]->from[$x] = $nom_table = $show['table'];
1412
-						$boucles[$id]->iterateur = 'SQL';
1413
-
1414
-						if (empty($boucles[$id]->descr)) {
1415
-							$boucles[$id]->descr = &$descr;
1416
-						}
1417
-						if ((!$boucles[$id]->jointures)
1418
-							and is_array($show['tables_jointures'])
1419
-							and count($x = $show['tables_jointures'])
1420
-						) {
1421
-							$boucles[$id]->jointures = $x;
1422
-						}
1423
-						if ($boucles[$id]->jointures_explicites) {
1424
-							$jointures = preg_split("/\s+/", $boucles[$id]->jointures_explicites);
1425
-							while ($j = array_pop($jointures)) {
1426
-								array_unshift($boucles[$id]->jointures, $j);
1427
-							}
1428
-						}
1429
-					} else {
1430
-						// Pas une erreur si la table est optionnelle
1431
-						if ($boucles[$id]->table_optionnelle) {
1432
-							$boucles[$id]->type_requete = '';
1433
-						} else {
1434
-							$boucles[$id]->type_requete = false;
1435
-							$boucle = $boucles[$id];
1436
-							$x = (!$boucle->sql_serveur ? '' :
1437
-									($boucle->sql_serveur . ":")) .
1438
-								$type;
1439
-							$msg = array(
1440
-								'zbug_table_inconnue',
1441
-								array('table' => $x)
1442
-							);
1443
-							erreur_squelette($msg, $boucle);
1444
-						}
1445
-					}
1446
-				}
1447
-			}
1448
-		}
1449
-	}
1450
-
1451
-	// Commencer par reperer les boucles appelees explicitement 
1452
-	// car elles indexent les arguments de maniere derogatoire
1453
-	foreach ($boucles as $id => $boucle) {
1454
-		if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1455
-			$boucles[$id]->descr = &$descr;
1456
-			$rec = &$boucles[$boucle->param[0]];
1457
-			if (!$rec) {
1458
-				$msg = array(
1459
-					'zbug_boucle_recursive_undef',
1460
-					array('nom' => $boucle->param[0])
1461
-				);
1462
-				erreur_squelette($msg, $boucle);
1463
-				$boucles[$id]->type_requete = false;
1464
-			} else {
1465
-				$rec->externe = $id;
1466
-				$descr['id_mere'] = $id;
1467
-				$boucles[$id]->return =
1468
-					calculer_liste(array($rec),
1469
-						$descr,
1470
-						$boucles,
1471
-						$boucle->param);
1472
-			}
1473
-		}
1474
-	}
1475
-	foreach ($boucles as $id => $boucle) {
1476
-		$id = strval($id); // attention au type dans index_pile
1477
-		$type = $boucle->type_requete;
1478
-		if ($type and $type != TYPE_RECURSIF) {
1479
-			$res = '';
1480
-			if ($boucle->param) {
1481
-				// retourne un tableau en cas d'erreur
1482
-				$res = calculer_criteres($id, $boucles);
1483
-			}
1484
-			$descr['id_mere'] = $id;
1485
-			$boucles[$id]->return =
1486
-				calculer_liste($boucle->milieu,
1487
-					$descr,
1488
-					$boucles,
1489
-					$id);
1490
-			// Si les criteres se sont mal compiles
1491
-			// ne pas tenter d'assembler le code final
1492
-			// (mais compiler le corps pour detection d'erreurs)
1493
-			if (is_array($res)) {
1494
-				$boucles[$id]->type_requete = false;
1495
-			}
1496
-		}
1497
-	}
1498
-
1499
-	// idem pour la racine
1500
-	$descr['id_mere'] = '';
1501
-	$corps = calculer_liste($squelette, $descr, $boucles);
1502
-
1503
-
1504
-	// Calcul du corps de toutes les fonctions PHP,
1505
-	// en particulier les requetes SQL et TOTAL_BOUCLE
1506
-	// de'terminables seulement maintenant
1507
-
1508
-	foreach ($boucles as $id => $boucle) {
1509
-		$boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1510
-		if ($boucle->return === false) {
1511
-			$corps = false;
1512
-			continue;
1513
-		}
1514
-		// appeler la fonction de definition de la boucle
1515
-
1516
-		if ($req = $boucle->type_requete) {
1517
-			// boucle personnalisée ?
1518
-			$table = strtoupper($boucle->type_requete);
1519
-			$serveur = strtolower($boucle->sql_serveur);
1520
-			if (
1521
-				// fonction de boucle avec serveur & table
1522
-				(!$serveur or
1523
-					((!function_exists($f = "boucle_" . $serveur . "_" . $table))
1524
-						and (!function_exists($f = $f . "_dist"))
1525
-					)
1526
-				)
1527
-				// fonction de boucle avec table
1528
-				and (!function_exists($f = "boucle_" . $table))
1529
-				and (!function_exists($f = $f . "_dist"))
1530
-			) {
1531
-				// fonction de boucle standard 
1532
-				if (!function_exists($f = 'boucle_DEFAUT')) {
1533
-					$f = 'boucle_DEFAUT_dist';
1534
-				}
1535
-			}
1536
-
1537
-			$req = "\n\n\tstatic \$command = array();\n\t" .
1538
-				"static \$connect;\n\t" .
1539
-				"\$command['connect'] = \$connect = " .
1540
-				_q($boucle->sql_serveur) .
1541
-				";" .
1542
-				$f($id, $boucles);
1543
-		} else {
1544
-			$req = ("\n\treturn '';");
1545
-		}
1546
-
1547
-		$boucles[$id]->return =
1548
-			"\n\nfunction BOUCLE" . strtr($id, "-", "_") . $nom .
1549
-			'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1550
-			$req .
1551
-			"\n}\n";
1552
-	}
1553
-
1554
-	// Au final, si le corps ou un critere au moins s'est mal compile
1555
-	// retourner False, sinon inserer leur decompilation
1556
-	if (is_bool($corps)) {
1557
-		return false;
1558
-	}
1559
-
1560
-	$principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1340
+    static $trouver_table;
1341
+    spip_timer('calcul_skel');
1342
+
1343
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1344
+        $GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1345
+        $GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1346
+
1347
+        if (!isset($GLOBALS['debug_objets']['principal'])) {
1348
+            $GLOBALS['debug_objets']['principal'] = $nom;
1349
+        }
1350
+    }
1351
+    foreach ($boucles as $id => $boucle) {
1352
+        $GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1353
+    }
1354
+    $descr['documents'] = compile_inclure_doublons($squelette);
1355
+
1356
+    // Demander la description des tables une fois pour toutes
1357
+    if (!$trouver_table) {
1358
+        $trouver_table = charger_fonction('trouver_table', 'base');
1359
+    }
1360
+
1361
+    // reperer si les doublons sont demandes
1362
+    // pour un inclure ou une boucle document
1363
+    // c'est utile a la fonction champs_traitements
1364
+    foreach ($boucles as $id => $boucle) {
1365
+        if (!($type = $boucle->type_requete)) {
1366
+            continue;
1367
+        }
1368
+        if (!$descr['documents'] and (
1369
+                (($type == 'documents') and $boucle->doublons) or
1370
+                compile_inclure_doublons($boucle->avant) or
1371
+                compile_inclure_doublons($boucle->apres) or
1372
+                compile_inclure_doublons($boucle->milieu) or
1373
+                compile_inclure_doublons($boucle->altern))
1374
+        ) {
1375
+            $descr['documents'] = true;
1376
+        }
1377
+        if ($type != TYPE_RECURSIF) {
1378
+            if (!$boucles[$id]->sql_serveur and $connect) {
1379
+                $boucles[$id]->sql_serveur = $connect;
1380
+            }
1381
+
1382
+            // chercher dans les iterateurs du repertoire iterateur/
1383
+            if ($g = charger_fonction(
1384
+                preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true)
1385
+            ) {
1386
+                $boucles[$id] = $g($boucle);
1387
+
1388
+                // sinon, en cas de requeteur d'un type predefini,
1389
+                // utiliser les informations donnees par le requeteur
1390
+                // cas "php:xx" et "data:xx".
1391
+            } else {
1392
+                if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1393
+                    $requeteur($boucles, $boucle, $id);
1394
+
1395
+                    // utiliser la description des champs transmis
1396
+                } else {
1397
+                    $show = $trouver_table($type, $boucles[$id]->sql_serveur);
1398
+                    // si la table n'existe pas avec le connecteur par defaut,
1399
+                    // c'est peut etre une table qui necessite son connecteur dedie fourni
1400
+                    // permet une ecriture allegee (GEO) -> (geo:GEO)
1401
+                    if (!$show
1402
+                        and $show = $trouver_table($type, strtolower($type))
1403
+                    ) {
1404
+                        $boucles[$id]->sql_serveur = strtolower($type);
1405
+                    }
1406
+                    if ($show) {
1407
+                        $boucles[$id]->show = $show;
1408
+                        // recopie les infos les plus importantes
1409
+                        $boucles[$id]->primary = isset($show['key']["PRIMARY KEY"]) ? $show['key']["PRIMARY KEY"] : '';
1410
+                        $boucles[$id]->id_table = $x = preg_replace(",^spip_,", "", $show['id_table']);
1411
+                        $boucles[$id]->from[$x] = $nom_table = $show['table'];
1412
+                        $boucles[$id]->iterateur = 'SQL';
1413
+
1414
+                        if (empty($boucles[$id]->descr)) {
1415
+                            $boucles[$id]->descr = &$descr;
1416
+                        }
1417
+                        if ((!$boucles[$id]->jointures)
1418
+                            and is_array($show['tables_jointures'])
1419
+                            and count($x = $show['tables_jointures'])
1420
+                        ) {
1421
+                            $boucles[$id]->jointures = $x;
1422
+                        }
1423
+                        if ($boucles[$id]->jointures_explicites) {
1424
+                            $jointures = preg_split("/\s+/", $boucles[$id]->jointures_explicites);
1425
+                            while ($j = array_pop($jointures)) {
1426
+                                array_unshift($boucles[$id]->jointures, $j);
1427
+                            }
1428
+                        }
1429
+                    } else {
1430
+                        // Pas une erreur si la table est optionnelle
1431
+                        if ($boucles[$id]->table_optionnelle) {
1432
+                            $boucles[$id]->type_requete = '';
1433
+                        } else {
1434
+                            $boucles[$id]->type_requete = false;
1435
+                            $boucle = $boucles[$id];
1436
+                            $x = (!$boucle->sql_serveur ? '' :
1437
+                                    ($boucle->sql_serveur . ":")) .
1438
+                                $type;
1439
+                            $msg = array(
1440
+                                'zbug_table_inconnue',
1441
+                                array('table' => $x)
1442
+                            );
1443
+                            erreur_squelette($msg, $boucle);
1444
+                        }
1445
+                    }
1446
+                }
1447
+            }
1448
+        }
1449
+    }
1450
+
1451
+    // Commencer par reperer les boucles appelees explicitement 
1452
+    // car elles indexent les arguments de maniere derogatoire
1453
+    foreach ($boucles as $id => $boucle) {
1454
+        if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1455
+            $boucles[$id]->descr = &$descr;
1456
+            $rec = &$boucles[$boucle->param[0]];
1457
+            if (!$rec) {
1458
+                $msg = array(
1459
+                    'zbug_boucle_recursive_undef',
1460
+                    array('nom' => $boucle->param[0])
1461
+                );
1462
+                erreur_squelette($msg, $boucle);
1463
+                $boucles[$id]->type_requete = false;
1464
+            } else {
1465
+                $rec->externe = $id;
1466
+                $descr['id_mere'] = $id;
1467
+                $boucles[$id]->return =
1468
+                    calculer_liste(array($rec),
1469
+                        $descr,
1470
+                        $boucles,
1471
+                        $boucle->param);
1472
+            }
1473
+        }
1474
+    }
1475
+    foreach ($boucles as $id => $boucle) {
1476
+        $id = strval($id); // attention au type dans index_pile
1477
+        $type = $boucle->type_requete;
1478
+        if ($type and $type != TYPE_RECURSIF) {
1479
+            $res = '';
1480
+            if ($boucle->param) {
1481
+                // retourne un tableau en cas d'erreur
1482
+                $res = calculer_criteres($id, $boucles);
1483
+            }
1484
+            $descr['id_mere'] = $id;
1485
+            $boucles[$id]->return =
1486
+                calculer_liste($boucle->milieu,
1487
+                    $descr,
1488
+                    $boucles,
1489
+                    $id);
1490
+            // Si les criteres se sont mal compiles
1491
+            // ne pas tenter d'assembler le code final
1492
+            // (mais compiler le corps pour detection d'erreurs)
1493
+            if (is_array($res)) {
1494
+                $boucles[$id]->type_requete = false;
1495
+            }
1496
+        }
1497
+    }
1498
+
1499
+    // idem pour la racine
1500
+    $descr['id_mere'] = '';
1501
+    $corps = calculer_liste($squelette, $descr, $boucles);
1502
+
1503
+
1504
+    // Calcul du corps de toutes les fonctions PHP,
1505
+    // en particulier les requetes SQL et TOTAL_BOUCLE
1506
+    // de'terminables seulement maintenant
1507
+
1508
+    foreach ($boucles as $id => $boucle) {
1509
+        $boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1510
+        if ($boucle->return === false) {
1511
+            $corps = false;
1512
+            continue;
1513
+        }
1514
+        // appeler la fonction de definition de la boucle
1515
+
1516
+        if ($req = $boucle->type_requete) {
1517
+            // boucle personnalisée ?
1518
+            $table = strtoupper($boucle->type_requete);
1519
+            $serveur = strtolower($boucle->sql_serveur);
1520
+            if (
1521
+                // fonction de boucle avec serveur & table
1522
+                (!$serveur or
1523
+                    ((!function_exists($f = "boucle_" . $serveur . "_" . $table))
1524
+                        and (!function_exists($f = $f . "_dist"))
1525
+                    )
1526
+                )
1527
+                // fonction de boucle avec table
1528
+                and (!function_exists($f = "boucle_" . $table))
1529
+                and (!function_exists($f = $f . "_dist"))
1530
+            ) {
1531
+                // fonction de boucle standard 
1532
+                if (!function_exists($f = 'boucle_DEFAUT')) {
1533
+                    $f = 'boucle_DEFAUT_dist';
1534
+                }
1535
+            }
1536
+
1537
+            $req = "\n\n\tstatic \$command = array();\n\t" .
1538
+                "static \$connect;\n\t" .
1539
+                "\$command['connect'] = \$connect = " .
1540
+                _q($boucle->sql_serveur) .
1541
+                ";" .
1542
+                $f($id, $boucles);
1543
+        } else {
1544
+            $req = ("\n\treturn '';");
1545
+        }
1546
+
1547
+        $boucles[$id]->return =
1548
+            "\n\nfunction BOUCLE" . strtr($id, "-", "_") . $nom .
1549
+            '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1550
+            $req .
1551
+            "\n}\n";
1552
+    }
1553
+
1554
+    // Au final, si le corps ou un critere au moins s'est mal compile
1555
+    // retourner False, sinon inserer leur decompilation
1556
+    if (is_bool($corps)) {
1557
+        return false;
1558
+    }
1559
+
1560
+    $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1561 1561
 '
1562
-		// reporter de maniere securisee les doublons inclus
1563
-		. '
1562
+        // reporter de maniere securisee les doublons inclus
1563
+        . '
1564 1564
 	if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"]))
1565 1565
 		$doublons = nettoyer_env_doublons($Pile[0]["doublons"]);
1566 1566
 
1567 1567
 	$connect = ' .
1568
-		_q($connect) . ';
1568
+        _q($connect) . ';
1569 1569
 	$page = ' .
1570
-		// ATTENTION, le calcul de l'expression $corps affectera $Cache
1571
-		// c'est pourquoi on l'affecte a la variable auxiliaire $page.
1572
-		// avant de referencer $Cache
1573
-		$corps . ";
1570
+        // ATTENTION, le calcul de l'expression $corps affectera $Cache
1571
+        // c'est pourquoi on l'affecte a la variable auxiliaire $page.
1572
+        // avant de referencer $Cache
1573
+        $corps . ";
1574 1574
 
1575 1575
 	return analyse_resultat_skel(" . var_export($nom, true)
1576
-		. ", \$Cache, \$page, " . var_export($sourcefile, true) . ");
1576
+        . ", \$Cache, \$page, " . var_export($sourcefile, true) . ");
1577 1577
 }";
1578 1578
 
1579
-	$secondes = spip_timer('calcul_skel');
1580
-	spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1581
-	// $connect n'est pas sûr : on nettoie
1582
-	$connect = preg_replace(',[^\w],', '', $connect);
1579
+    $secondes = spip_timer('calcul_skel');
1580
+    spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1581
+    // $connect n'est pas sûr : on nettoie
1582
+    $connect = preg_replace(',[^\w],', '', $connect);
1583 1583
 
1584
-	// Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1585
-	$code = new Boucle;
1586
-	$code->descr = $descr;
1587
-	$code->return = '
1584
+    // Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1585
+    $code = new Boucle;
1586
+    $code->descr = $descr;
1587
+    $code->return = '
1588 1588
 //
1589 1589
 // Fonction principale du squelette ' .
1590
-		$sourcefile .
1591
-		($connect ? " pour $connect" : '') .
1592
-		(!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1593
-		"\n//\n" .
1594
-		$principal;
1590
+        $sourcefile .
1591
+        ($connect ? " pour $connect" : '') .
1592
+        (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1593
+        "\n//\n" .
1594
+        $principal;
1595 1595
 
1596
-	$boucles[''] = $code;
1596
+    $boucles[''] = $code;
1597 1597
 
1598
-	return $boucles;
1598
+    return $boucles;
1599 1599
 }
1600 1600
 
1601 1601
 
@@ -1612,18 +1612,18 @@  discard block
 block discarded – undo
1612 1612
  *
1613 1613
  **/
1614 1614
 function requeteur_php_dist(&$boucles, &$boucle, &$id) {
1615
-	if (class_exists($boucle->type_requete)) {
1616
-		$g = charger_fonction('php', 'iterateur');
1617
-		$boucles[$id] = $g($boucle, $boucle->type_requete);
1618
-	} else {
1619
-		$x = $boucle->type_requete;
1620
-		$boucle->type_requete = false;
1621
-		$msg = array(
1622
-			'zbug_iterateur_inconnu',
1623
-			array('iterateur' => $x)
1624
-		);
1625
-		erreur_squelette($msg, $boucle);
1626
-	}
1615
+    if (class_exists($boucle->type_requete)) {
1616
+        $g = charger_fonction('php', 'iterateur');
1617
+        $boucles[$id] = $g($boucle, $boucle->type_requete);
1618
+    } else {
1619
+        $x = $boucle->type_requete;
1620
+        $boucle->type_requete = false;
1621
+        $msg = array(
1622
+            'zbug_iterateur_inconnu',
1623
+            array('iterateur' => $x)
1624
+        );
1625
+        erreur_squelette($msg, $boucle);
1626
+    }
1627 1627
 }
1628 1628
 
1629 1629
 
@@ -1641,23 +1641,23 @@  discard block
 block discarded – undo
1641 1641
  *
1642 1642
  **/
1643 1643
 function requeteur_data_dist(&$boucles, &$boucle, &$id) {
1644
-	include_spip('iterateur/data');
1645
-	if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1646
-		$g = charger_fonction('data', 'iterateur');
1647
-		$boucles[$id] = $g($boucle);
1648
-		// from[0] stocke le type de data (rss, yql, ...)
1649
-		$boucles[$id]->from[] = $boucle->type_requete;
1650
-
1651
-	} else {
1652
-		$x = $boucle->type_requete;
1653
-		$boucle->type_requete = false;
1654
-		$msg = array(
1655
-			'zbug_requeteur_inconnu',
1656
-			array(
1657
-				'requeteur' => 'data',
1658
-				'type' => $x
1659
-			)
1660
-		);
1661
-		erreur_squelette($msg, $boucle);
1662
-	}
1644
+    include_spip('iterateur/data');
1645
+    if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1646
+        $g = charger_fonction('data', 'iterateur');
1647
+        $boucles[$id] = $g($boucle);
1648
+        // from[0] stocke le type de data (rss, yql, ...)
1649
+        $boucles[$id]->from[] = $boucle->type_requete;
1650
+
1651
+    } else {
1652
+        $x = $boucle->type_requete;
1653
+        $boucle->type_requete = false;
1654
+        $msg = array(
1655
+            'zbug_requeteur_inconnu',
1656
+            array(
1657
+                'requeteur' => 'data',
1658
+                'type' => $x
1659
+            )
1660
+        );
1661
+        erreur_squelette($msg, $boucle);
1662
+    }
1663 1663
 }
Please login to merge, or discard this patch.