Completed
Push — master ( f21f4b...d3c14a )
by cam
01:00
created
ecrire/install/etape_3b.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -11,172 +11,172 @@
 block discarded – undo
11 11
 \***************************************************************************/
12 12
 
13 13
 if (!defined('_ECRIRE_INC_VERSION')) {
14
-	return;
14
+    return;
15 15
 }
16 16
 
17 17
 include_spip('inc/headers');
18 18
 
19 19
 function install_etape_3b_dist() {
20
-	$auth_spip = null;
21
-	$session = null;
22
-	$row = null;
23
-	$login = _request('login');
24
-	$email = _request('email');
25
-	$nom = _request('nom');
26
-	$pass = _request('pass');
27
-	$pass_verif = _request('pass_verif');
28
-
29
-	$server_db = defined('_INSTALL_SERVER_DB')
30
-		? _INSTALL_SERVER_DB
31
-		: _request('server_db');
32
-
33
-	if (!defined('_PASS_LONGUEUR_MINI')) {
34
-		define('_PASS_LONGUEUR_MINI', 6);
35
-	}
36
-	if (!defined('_LOGIN_TROP_COURT')) {
37
-		define('_LOGIN_TROP_COURT', 4);
38
-	}
39
-	if ($login) {
40
-		$echec = ($pass != $pass_verif) ?
41
-			_T('info_passes_identiques')
42
-			: ((strlen($pass) < _PASS_LONGUEUR_MINI) ?
43
-				_T('info_passe_trop_court_car_pluriel', ['nb' => _PASS_LONGUEUR_MINI])
44
-				: ((strlen($login) < _LOGIN_TROP_COURT) ?
45
-					_T('info_login_trop_court')
46
-					: ''));
47
-		include_spip('inc/filtres');
48
-		if (!$echec and $email and !email_valide($email)) {
49
-			$echec = _T('form_email_non_valide');
50
-		}
51
-		if ($echec) {
52
-			echouer_etape_3b($echec);
53
-		}
54
-	}
55
-
56
-	if (@file_exists(_FILE_CHMOD_TMP)) {
57
-		include(_FILE_CHMOD_TMP);
58
-	} else {
59
-		redirige_url_ecrire('install');
60
-	}
61
-
62
-	if (!@file_exists(_FILE_CONNECT_TMP)) {
63
-		redirige_url_ecrire('install');
64
-	}
65
-
66
-	# maintenant on connait le vrai charset du site s'il est deja configure
67
-	# sinon par defaut lire_meta reglera _DEFAULT_CHARSET
68
-	# (les donnees arrivent de toute facon postees en _DEFAULT_CHARSET)
69
-
70
-	lire_metas();
71
-	if ($login) {
72
-		include_spip('inc/charsets');
73
-
74
-		$nom = (importer_charset($nom, _DEFAULT_CHARSET));
75
-		$login = (importer_charset($login, _DEFAULT_CHARSET));
76
-		$email = (importer_charset($email, _DEFAULT_CHARSET));
77
-		# pour le passwd, bizarrement il faut le convertir comme s'il avait
78
-		# ete tape en iso-8859-1 ; car c'est en fait ce que voit md5.js
79
-		$pass = unicode2charset(utf_8_to_unicode($pass), 'iso-8859-1');
80
-
81
-		include_spip('auth/spip');
82
-		// prelablement, creer le champ webmestre si il n'existe pas (install neuve
83
-		// sur une vieille base
84
-		$t = sql_showtable('spip_auteurs', true);
85
-		if (!isset($t['field']['webmestre'])) {
86
-			@sql_alter("TABLE spip_auteurs ADD webmestre varchar(3)  DEFAULT 'non' NOT NULL");
87
-		}
88
-
89
-		// il faut avoir une cle des auth valide pour creer un nouvel auteur webmestre
90
-		$cles = \Spip\Chiffrer\SpipCles::instance();
91
-		$secret = $cles->getSecretAuth();
92
-
93
-		$id_auteur = sql_getfetsel('id_auteur', 'spip_auteurs', 'login=' . sql_quote($login));
94
-		if ($id_auteur !== null) {
95
-			// c'est un auteur connu : si on a pas de secret il faut absolument qu'il se reconnecte avec le meme mot de passe
96
-			// pour restaurer la copie des cles
97
-			if (!$secret and !auth_spip_initialiser_secret()) {
98
-				$row = sql_fetsel('backup_cles, pass', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
99
-				if (empty($row['backup_cles']) or !$cles->restore($row['backup_cles'], $pass, $row['pass'], $id_auteur)) {
100
-					$echec = _T('avis_connexion_erreur_fichier_cle_manquant_1');
101
-					echouer_etape_3b($echec);
102
-				}
103
-				spip_log("Les cles secretes ont ete restaurées avec le backup du webmestre #$id_auteur", 'auth' . _LOG_INFO_IMPORTANTE);
104
-				$cles->save();
105
-			}
106
-
107
-			sql_updateq('spip_auteurs', [
108
-				'nom' => $nom,
109
-				'email' => $email,
110
-				'login' => $login,
111
-				'statut' => '0minirezo'
112
-			], 'id_auteur=' . intval($id_auteur));
113
-			// le passer webmestre separement du reste, au cas ou l'alter n'aurait pas fonctionne
114
-			@sql_updateq('spip_auteurs', ['webmestre' => 'oui'], "id_auteur=$id_auteur");
115
-			if (!auth_spip_modifier_pass($login, $pass, $id_auteur)) {
116
-				$echec = _T('avis_erreur_creation_compte');
117
-				echouer_etape_3b($echec);
118
-			}
119
-		} else {
120
-			// Si on a pas de cle et qu'on ne sait pas la creer, on ne peut pas creer de nouveau compte :
121
-			// il faut qu'un webmestre avec un backup fasse l'install
122
-			if (!$secret and !auth_spip_initialiser_secret()) {
123
-				$echec = _T('avis_connexion_erreur_fichier_cle_manquant_2');
124
-				echouer_etape_3b($echec);
125
-			}
126
-
127
-			$id_auteur = sql_insertq('spip_auteurs', [
128
-				'nom' => $nom,
129
-				'email' => $email,
130
-				'login' => $login,
131
-				'statut' => '0minirezo'
132
-			]);
133
-			// le passer webmestre separrement du reste, au cas ou l'alter n'aurait pas fonctionne
134
-			@sql_updateq('spip_auteurs', ['webmestre' => 'oui'], "id_auteur=$id_auteur");
135
-			if (!auth_spip_modifier_pass($login, $pass, $id_auteur)) {
136
-				$echec = _T('avis_erreur_creation_compte');
137
-				echouer_etape_3b($echec);
138
-			}
139
-		}
140
-
141
-		// inserer email comme email webmaster principal
142
-		// (sauf s'il est vide: cas de la re-installation)
143
-		if ($email) {
144
-			ecrire_meta('email_webmaster', $email);
145
-		}
146
-
147
-		// Connecter directement celui qui vient de (re)donner son login
148
-		// mais sans cookie d'admin ni connexion longue
149
-		include_spip('inc/auth');
150
-		if (
151
-			!$auteur = auth_identifier_login($login, $pass)
152
-			or !auth_loger($auteur)
153
-		) {
154
-			spip_log("login automatique impossible $auth_spip $session" . (is_countable($row) ? count($row) : 0));
155
-		}
156
-	}
157
-
158
-	// installer les metas
159
-	$config = charger_fonction('config', 'inc');
160
-	$config();
161
-
162
-	// activer les plugins
163
-	// leur installation ne peut pas se faire sur le meme hit, il faudra donc
164
-	// poursuivre au hit suivant
165
-	include_spip('inc/plugin');
166
-	actualise_plugins_actifs();
167
-
168
-
169
-	include_spip('inc/distant');
170
-	redirige_par_entete(parametre_url(self(), 'etape', '4', '&'));
20
+    $auth_spip = null;
21
+    $session = null;
22
+    $row = null;
23
+    $login = _request('login');
24
+    $email = _request('email');
25
+    $nom = _request('nom');
26
+    $pass = _request('pass');
27
+    $pass_verif = _request('pass_verif');
28
+
29
+    $server_db = defined('_INSTALL_SERVER_DB')
30
+        ? _INSTALL_SERVER_DB
31
+        : _request('server_db');
32
+
33
+    if (!defined('_PASS_LONGUEUR_MINI')) {
34
+        define('_PASS_LONGUEUR_MINI', 6);
35
+    }
36
+    if (!defined('_LOGIN_TROP_COURT')) {
37
+        define('_LOGIN_TROP_COURT', 4);
38
+    }
39
+    if ($login) {
40
+        $echec = ($pass != $pass_verif) ?
41
+            _T('info_passes_identiques')
42
+            : ((strlen($pass) < _PASS_LONGUEUR_MINI) ?
43
+                _T('info_passe_trop_court_car_pluriel', ['nb' => _PASS_LONGUEUR_MINI])
44
+                : ((strlen($login) < _LOGIN_TROP_COURT) ?
45
+                    _T('info_login_trop_court')
46
+                    : ''));
47
+        include_spip('inc/filtres');
48
+        if (!$echec and $email and !email_valide($email)) {
49
+            $echec = _T('form_email_non_valide');
50
+        }
51
+        if ($echec) {
52
+            echouer_etape_3b($echec);
53
+        }
54
+    }
55
+
56
+    if (@file_exists(_FILE_CHMOD_TMP)) {
57
+        include(_FILE_CHMOD_TMP);
58
+    } else {
59
+        redirige_url_ecrire('install');
60
+    }
61
+
62
+    if (!@file_exists(_FILE_CONNECT_TMP)) {
63
+        redirige_url_ecrire('install');
64
+    }
65
+
66
+    # maintenant on connait le vrai charset du site s'il est deja configure
67
+    # sinon par defaut lire_meta reglera _DEFAULT_CHARSET
68
+    # (les donnees arrivent de toute facon postees en _DEFAULT_CHARSET)
69
+
70
+    lire_metas();
71
+    if ($login) {
72
+        include_spip('inc/charsets');
73
+
74
+        $nom = (importer_charset($nom, _DEFAULT_CHARSET));
75
+        $login = (importer_charset($login, _DEFAULT_CHARSET));
76
+        $email = (importer_charset($email, _DEFAULT_CHARSET));
77
+        # pour le passwd, bizarrement il faut le convertir comme s'il avait
78
+        # ete tape en iso-8859-1 ; car c'est en fait ce que voit md5.js
79
+        $pass = unicode2charset(utf_8_to_unicode($pass), 'iso-8859-1');
80
+
81
+        include_spip('auth/spip');
82
+        // prelablement, creer le champ webmestre si il n'existe pas (install neuve
83
+        // sur une vieille base
84
+        $t = sql_showtable('spip_auteurs', true);
85
+        if (!isset($t['field']['webmestre'])) {
86
+            @sql_alter("TABLE spip_auteurs ADD webmestre varchar(3)  DEFAULT 'non' NOT NULL");
87
+        }
88
+
89
+        // il faut avoir une cle des auth valide pour creer un nouvel auteur webmestre
90
+        $cles = \Spip\Chiffrer\SpipCles::instance();
91
+        $secret = $cles->getSecretAuth();
92
+
93
+        $id_auteur = sql_getfetsel('id_auteur', 'spip_auteurs', 'login=' . sql_quote($login));
94
+        if ($id_auteur !== null) {
95
+            // c'est un auteur connu : si on a pas de secret il faut absolument qu'il se reconnecte avec le meme mot de passe
96
+            // pour restaurer la copie des cles
97
+            if (!$secret and !auth_spip_initialiser_secret()) {
98
+                $row = sql_fetsel('backup_cles, pass', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
99
+                if (empty($row['backup_cles']) or !$cles->restore($row['backup_cles'], $pass, $row['pass'], $id_auteur)) {
100
+                    $echec = _T('avis_connexion_erreur_fichier_cle_manquant_1');
101
+                    echouer_etape_3b($echec);
102
+                }
103
+                spip_log("Les cles secretes ont ete restaurées avec le backup du webmestre #$id_auteur", 'auth' . _LOG_INFO_IMPORTANTE);
104
+                $cles->save();
105
+            }
106
+
107
+            sql_updateq('spip_auteurs', [
108
+                'nom' => $nom,
109
+                'email' => $email,
110
+                'login' => $login,
111
+                'statut' => '0minirezo'
112
+            ], 'id_auteur=' . intval($id_auteur));
113
+            // le passer webmestre separement du reste, au cas ou l'alter n'aurait pas fonctionne
114
+            @sql_updateq('spip_auteurs', ['webmestre' => 'oui'], "id_auteur=$id_auteur");
115
+            if (!auth_spip_modifier_pass($login, $pass, $id_auteur)) {
116
+                $echec = _T('avis_erreur_creation_compte');
117
+                echouer_etape_3b($echec);
118
+            }
119
+        } else {
120
+            // Si on a pas de cle et qu'on ne sait pas la creer, on ne peut pas creer de nouveau compte :
121
+            // il faut qu'un webmestre avec un backup fasse l'install
122
+            if (!$secret and !auth_spip_initialiser_secret()) {
123
+                $echec = _T('avis_connexion_erreur_fichier_cle_manquant_2');
124
+                echouer_etape_3b($echec);
125
+            }
126
+
127
+            $id_auteur = sql_insertq('spip_auteurs', [
128
+                'nom' => $nom,
129
+                'email' => $email,
130
+                'login' => $login,
131
+                'statut' => '0minirezo'
132
+            ]);
133
+            // le passer webmestre separrement du reste, au cas ou l'alter n'aurait pas fonctionne
134
+            @sql_updateq('spip_auteurs', ['webmestre' => 'oui'], "id_auteur=$id_auteur");
135
+            if (!auth_spip_modifier_pass($login, $pass, $id_auteur)) {
136
+                $echec = _T('avis_erreur_creation_compte');
137
+                echouer_etape_3b($echec);
138
+            }
139
+        }
140
+
141
+        // inserer email comme email webmaster principal
142
+        // (sauf s'il est vide: cas de la re-installation)
143
+        if ($email) {
144
+            ecrire_meta('email_webmaster', $email);
145
+        }
146
+
147
+        // Connecter directement celui qui vient de (re)donner son login
148
+        // mais sans cookie d'admin ni connexion longue
149
+        include_spip('inc/auth');
150
+        if (
151
+            !$auteur = auth_identifier_login($login, $pass)
152
+            or !auth_loger($auteur)
153
+        ) {
154
+            spip_log("login automatique impossible $auth_spip $session" . (is_countable($row) ? count($row) : 0));
155
+        }
156
+    }
157
+
158
+    // installer les metas
159
+    $config = charger_fonction('config', 'inc');
160
+    $config();
161
+
162
+    // activer les plugins
163
+    // leur installation ne peut pas se faire sur le meme hit, il faudra donc
164
+    // poursuivre au hit suivant
165
+    include_spip('inc/plugin');
166
+    actualise_plugins_actifs();
167
+
168
+
169
+    include_spip('inc/distant');
170
+    redirige_par_entete(parametre_url(self(), 'etape', '4', '&'));
171 171
 }
172 172
 
173 173
 function echouer_etape_3b($echec) {
174
-	echo minipres(
175
-		'AUTO',
176
-		info_progression_etape(3, 'etape_', 'install/', true) .
177
-		"<div class='error'><h3>$echec</h3>\n" .
178
-		'<p>' . _T('avis_connexion_echec_2') . '</p>' .
179
-		'</div>'
180
-	);
181
-	exit;
174
+    echo minipres(
175
+        'AUTO',
176
+        info_progression_etape(3, 'etape_', 'install/', true) .
177
+        "<div class='error'><h3>$echec</h3>\n" .
178
+        '<p>' . _T('avis_connexion_echec_2') . '</p>' .
179
+        '</div>'
180
+    );
181
+    exit;
182 182
 }
Please login to merge, or discard this patch.
ecrire/public/compiler.php 1 patch
Indentation   +1212 added lines, -1212 removed lines patch added patch discarded remove patch
@@ -21,7 +21,7 @@  discard block
 block discarded – undo
21 21
  **/
22 22
 
23 23
 if (!defined('_ECRIRE_INC_VERSION')) {
24
-	return;
24
+    return;
25 25
 }
26 26
 
27 27
 /** Repérer un code ne calculant rien, meme avec commentaire */
@@ -62,92 +62,92 @@  discard block
 block discarded – undo
62 62
 
63 63
 
64 64
 function argumenter_inclure(
65
-	$params,
66
-	$rejet_filtres,
67
-	$p,
68
-	&$boucles,
69
-	$id_boucle,
70
-	$echap = true,
71
-	$lang = '',
72
-	$fond1 = false
65
+    $params,
66
+    $rejet_filtres,
67
+    $p,
68
+    &$boucles,
69
+    $id_boucle,
70
+    $echap = true,
71
+    $lang = '',
72
+    $fond1 = false
73 73
 ) {
74
-	$l = [];
75
-	$erreur_p_i_i = '';
76
-	if (!is_array($params)) {
77
-		return $l;
78
-	}
79
-	foreach ($params as $k => $couple) {
80
-		// la liste d'arguments d'inclusion peut se terminer par un filtre
81
-		$filtre = array_shift($couple);
82
-		if ($filtre) {
83
-			break;
84
-		}
85
-		foreach ($couple as $n => $val) {
86
-			$var = $val[0];
87
-			if ($var->type != 'texte') {
88
-				if ($n or $k or $fond1) {
89
-					$erreur_p_i_i = [
90
-						'zbug_parametres_inclus_incorrects',
91
-						['param' => $var->nom_champ]
92
-					];
93
-					erreur_squelette($erreur_p_i_i, $p);
94
-					break;
95
-				} else {
96
-					$l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
97
-				}
98
-			} else {
99
-				preg_match(',^([^=]*)(=?)(.*)$,m', $var->texte, $m);
100
-				$m = array_pad($m, 3, null);
101
-				$var = $m[1];
102
-				$auto = false;
103
-
104
-				if ($m[2]) {
105
-					$v = $m[3];
106
-					if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
107
-						$v = $m[1];
108
-					}
109
-					$val[0] = new Texte();
110
-					$val[0]->texte = $v;
111
-				} elseif ($k or $n or $fond1) {
112
-					$auto = true;
113
-				} else {
114
-					$var = 1;
115
-				}
116
-
117
-				if ($var == 'lang') {
118
-					$lang = !$auto
119
-						? calculer_liste($val, $p->descr, $boucles, $id_boucle)
120
-						: '$GLOBALS["spip_lang"]';
121
-				} else {
122
-					$val = $auto
123
-						? index_pile($id_boucle, $var, $boucles)
124
-						: calculer_liste($val, $p->descr, $boucles, $id_boucle);
125
-					if ($var !== 1) {
126
-						$val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
127
-							. $val . ($echap ? ") . '" : ' ');
128
-					} else {
129
-						$val = $echap ? "'.$val.'" : $val;
130
-					}
131
-					$l[$var] = $val;
132
-				}
133
-			}
134
-		}
135
-	}
136
-	if ($erreur_p_i_i) {
137
-		return false;
138
-	}
139
-	// Cas particulier de la langue : si {lang=xx} est definie, on
140
-	// la passe, sinon on passe la langue courante au moment du calcul
141
-	// sauf si on n'en veut pas
142
-	if ($lang === false) {
143
-		return $l;
144
-	}
145
-	if (!$lang) {
146
-		$lang = '$GLOBALS["spip_lang"]';
147
-	}
148
-	$l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : ' ');
149
-
150
-	return $l;
74
+    $l = [];
75
+    $erreur_p_i_i = '';
76
+    if (!is_array($params)) {
77
+        return $l;
78
+    }
79
+    foreach ($params as $k => $couple) {
80
+        // la liste d'arguments d'inclusion peut se terminer par un filtre
81
+        $filtre = array_shift($couple);
82
+        if ($filtre) {
83
+            break;
84
+        }
85
+        foreach ($couple as $n => $val) {
86
+            $var = $val[0];
87
+            if ($var->type != 'texte') {
88
+                if ($n or $k or $fond1) {
89
+                    $erreur_p_i_i = [
90
+                        'zbug_parametres_inclus_incorrects',
91
+                        ['param' => $var->nom_champ]
92
+                    ];
93
+                    erreur_squelette($erreur_p_i_i, $p);
94
+                    break;
95
+                } else {
96
+                    $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
97
+                }
98
+            } else {
99
+                preg_match(',^([^=]*)(=?)(.*)$,m', $var->texte, $m);
100
+                $m = array_pad($m, 3, null);
101
+                $var = $m[1];
102
+                $auto = false;
103
+
104
+                if ($m[2]) {
105
+                    $v = $m[3];
106
+                    if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
107
+                        $v = $m[1];
108
+                    }
109
+                    $val[0] = new Texte();
110
+                    $val[0]->texte = $v;
111
+                } elseif ($k or $n or $fond1) {
112
+                    $auto = true;
113
+                } else {
114
+                    $var = 1;
115
+                }
116
+
117
+                if ($var == 'lang') {
118
+                    $lang = !$auto
119
+                        ? calculer_liste($val, $p->descr, $boucles, $id_boucle)
120
+                        : '$GLOBALS["spip_lang"]';
121
+                } else {
122
+                    $val = $auto
123
+                        ? index_pile($id_boucle, $var, $boucles)
124
+                        : calculer_liste($val, $p->descr, $boucles, $id_boucle);
125
+                    if ($var !== 1) {
126
+                        $val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
127
+                            . $val . ($echap ? ") . '" : ' ');
128
+                    } else {
129
+                        $val = $echap ? "'.$val.'" : $val;
130
+                    }
131
+                    $l[$var] = $val;
132
+                }
133
+            }
134
+        }
135
+    }
136
+    if ($erreur_p_i_i) {
137
+        return false;
138
+    }
139
+    // Cas particulier de la langue : si {lang=xx} est definie, on
140
+    // la passe, sinon on passe la langue courante au moment du calcul
141
+    // sauf si on n'en veut pas
142
+    if ($lang === false) {
143
+        return $l;
144
+    }
145
+    if (!$lang) {
146
+        $lang = '$GLOBALS["spip_lang"]';
147
+    }
148
+    $l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : ' ');
149
+
150
+    return $l;
151 151
 }
152 152
 
153 153
 /**
@@ -171,84 +171,84 @@  discard block
 block discarded – undo
171 171
  **/
172 172
 function calculer_inclure($p, &$boucles, $id_boucle) {
173 173
 
174
-	$_options = [];
175
-	$_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
176
-	if (is_string($p->texte)) {
177
-		$fichier = $p->texte;
178
-		$code = '"' . str_replace('"', '\"', $fichier) . '"';
179
-	} else {
180
-		$code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
181
-		if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
182
-			$fichier = $r[1];
183
-		} else {
184
-			$fichier = '';
185
-		}
186
-	}
187
-	if (!$code or $code === '""' or $code === "''") {
188
-		$trace = $p->fonctions;
189
-		while (
190
-			is_array($trace)
191
-			and $trace = array_filter($trace)
192
-			and count($trace) == 1
193
-		) {
194
-			$trace = reset($trace);
195
-		}
196
-		$erreur_p_i_i = [
197
-			'zbug_parametres_inclus_incorrects',
198
-			['param' => print_r($trace, true)]
199
-		];
200
-		erreur_squelette($erreur_p_i_i, $p);
201
-
202
-		return "''";
203
-	}
204
-	$compil = texte_script(memoriser_contexte_compil($p));
205
-
206
-	if (is_array($_contexte)) {
207
-		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
208
-		if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
209
-			unset($_contexte['env']);
210
-		}
211
-
212
-		// noter les doublons dans l'appel a public.php
213
-		if (isset($_contexte['doublons'])) {
214
-			$_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
215
-		}
216
-
217
-		if ($ajax = isset($_contexte['ajax'])) {
218
-			$ajax = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
219
-			unset($_contexte['ajax']);
220
-		}
221
-
222
-		$_contexte = join(",\n\t", $_contexte);
223
-	} else {
224
-		return false;
225
-	} // j'aurais voulu toucher le fond ...
226
-
227
-	$contexte = 'array(' . $_contexte . ')';
228
-
229
-	if ($env) {
230
-		$contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
231
-	}
232
-
233
-	// s'il y a une extension .php, ce n'est pas un squelette
234
-	if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
235
-		$code = sandbox_composer_inclure_php($fichier, $p, $contexte);
236
-	} else {
237
-		$_options[] = "\"compil\"=>array($compil)";
238
-		if ($ajax) {
239
-			$_options[] = $ajax;
240
-		}
241
-		$code = " ' . argumenter_squelette($code) . '";
242
-		$code = 'echo ' . sprintf(
243
-			CODE_RECUPERER_FOND,
244
-			$code,
245
-			$contexte,
246
-			implode(',', $_options),
247
-			"_request(\\'connect\\') ?? \\'\\'"
248
-		) . ';';
249
-	}
250
-
251
-	return "\n'<'.'" . '?php ' . $code . "\n?'." . "'>'";
174
+    $_options = [];
175
+    $_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
176
+    if (is_string($p->texte)) {
177
+        $fichier = $p->texte;
178
+        $code = '"' . str_replace('"', '\"', $fichier) . '"';
179
+    } else {
180
+        $code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
181
+        if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
182
+            $fichier = $r[1];
183
+        } else {
184
+            $fichier = '';
185
+        }
186
+    }
187
+    if (!$code or $code === '""' or $code === "''") {
188
+        $trace = $p->fonctions;
189
+        while (
190
+            is_array($trace)
191
+            and $trace = array_filter($trace)
192
+            and count($trace) == 1
193
+        ) {
194
+            $trace = reset($trace);
195
+        }
196
+        $erreur_p_i_i = [
197
+            'zbug_parametres_inclus_incorrects',
198
+            ['param' => print_r($trace, true)]
199
+        ];
200
+        erreur_squelette($erreur_p_i_i, $p);
201
+
202
+        return "''";
203
+    }
204
+    $compil = texte_script(memoriser_contexte_compil($p));
205
+
206
+    if (is_array($_contexte)) {
207
+        // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
208
+        if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
209
+            unset($_contexte['env']);
210
+        }
211
+
212
+        // noter les doublons dans l'appel a public.php
213
+        if (isset($_contexte['doublons'])) {
214
+            $_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
215
+        }
216
+
217
+        if ($ajax = isset($_contexte['ajax'])) {
218
+            $ajax = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
219
+            unset($_contexte['ajax']);
220
+        }
221
+
222
+        $_contexte = join(",\n\t", $_contexte);
223
+    } else {
224
+        return false;
225
+    } // j'aurais voulu toucher le fond ...
226
+
227
+    $contexte = 'array(' . $_contexte . ')';
228
+
229
+    if ($env) {
230
+        $contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
231
+    }
232
+
233
+    // s'il y a une extension .php, ce n'est pas un squelette
234
+    if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
235
+        $code = sandbox_composer_inclure_php($fichier, $p, $contexte);
236
+    } else {
237
+        $_options[] = "\"compil\"=>array($compil)";
238
+        if ($ajax) {
239
+            $_options[] = $ajax;
240
+        }
241
+        $code = " ' . argumenter_squelette($code) . '";
242
+        $code = 'echo ' . sprintf(
243
+            CODE_RECUPERER_FOND,
244
+            $code,
245
+            $contexte,
246
+            implode(',', $_options),
247
+            "_request(\\'connect\\') ?? \\'\\'"
248
+        ) . ';';
249
+    }
250
+
251
+    return "\n'<'.'" . '?php ' . $code . "\n?'." . "'>'";
252 252
 }
253 253
 
254 254
 
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
  *     true pour ne tester que le cas publie et ignorer l'eventuel var_mode=preview de la page
267 267
  */
268 268
 function instituer_boucle(&$boucle, $echapper = true, $ignore_previsu = false) {
269
-	/*
269
+    /*
270 270
 	$show['statut'][] = array(
271 271
 		'champ'=>'statut',  // champ de la table sur lequel porte le filtrage par le statut
272 272
 		'publie'=>'publie', // valeur ou liste de valeurs, qui definissent l'objet comme publie.
@@ -290,74 +290,74 @@  discard block
 block discarded – undo
290 290
 	champstatut est alors le champ statut sur la tablen
291 291
 	dans les jointures, clen peut etre un tableau pour une jointure complexe : array('id_objet','id_article','objet','article')
292 292
 	*/
293
-	$id_table = $boucle->id_table;
294
-	$show = $boucle->show;
295
-	if (isset($show['statut']) and $show['statut']) {
296
-		foreach ($show['statut'] as $k => $s) {
297
-			// Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
298
-			$filtrer = true;
299
-			if (isset($s['exception'])) {
300
-				foreach (is_array($s['exception']) ? $s['exception'] : [$s['exception']] as $m) {
301
-					if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
302
-						$filtrer = false;
303
-						break;
304
-					}
305
-				}
306
-			}
307
-
308
-			if ($filtrer) {
309
-				if (is_array($s['champ'])) {
310
-					$statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
311
-					$jointures = [];
312
-					// indiquer la description de chaque table dans le tableau de jointures,
313
-					// ce qui permet d'eviter certains GROUP BY inutiles.
314
-					$trouver_table = charger_fonction('trouver_table', 'base');
315
-					foreach ($s['champ'] as $j) {
316
-						$id = reset($j);
317
-						$def = $trouver_table($id);
318
-						$jointures[] = ['', [$id, $def], end($j)];
319
-					}
320
-					$jointures[0][0] = $id_table;
321
-					if (!array_search($id, $boucle->from)) {
322
-						include_spip('public/jointures');
323
-						fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
324
-					}
325
-					// trouver l'alias de la table d'arrivee qui porte le statut
326
-					$id = array_search($id, $boucle->from);
327
-				} else {
328
-					$id = $id_table;
329
-					$statut = preg_replace(',\W,', '', $s['champ']); // securite
330
-				}
331
-				$mstatut = $id . '.' . $statut;
332
-
333
-				$arg_ignore_previsu = ($ignore_previsu ? ',true' : '');
334
-				include_spip('public/quete');
335
-				if (
336
-					isset($s['post_date']) and $s['post_date']
337
-					and $GLOBALS['meta']['post_dates'] == 'non'
338
-				) {
339
-					$date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
340
-					array_unshift(
341
-						$boucle->where,
342
-						$echapper ?
343
-							"\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
344
-							:
345
-							quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
346
-					);
347
-				}
348
-				array_unshift(
349
-					$boucle->where,
350
-					$echapper ?
351
-						"\nquete_condition_statut('$mstatut',"
352
-						. _q($s['previsu']) . ','
353
-						. _q($s['publie']) . ','
354
-						. _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
355
-						:
356
-						quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
357
-				);
358
-			}
359
-		}
360
-	}
293
+    $id_table = $boucle->id_table;
294
+    $show = $boucle->show;
295
+    if (isset($show['statut']) and $show['statut']) {
296
+        foreach ($show['statut'] as $k => $s) {
297
+            // Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
298
+            $filtrer = true;
299
+            if (isset($s['exception'])) {
300
+                foreach (is_array($s['exception']) ? $s['exception'] : [$s['exception']] as $m) {
301
+                    if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
302
+                        $filtrer = false;
303
+                        break;
304
+                    }
305
+                }
306
+            }
307
+
308
+            if ($filtrer) {
309
+                if (is_array($s['champ'])) {
310
+                    $statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
311
+                    $jointures = [];
312
+                    // indiquer la description de chaque table dans le tableau de jointures,
313
+                    // ce qui permet d'eviter certains GROUP BY inutiles.
314
+                    $trouver_table = charger_fonction('trouver_table', 'base');
315
+                    foreach ($s['champ'] as $j) {
316
+                        $id = reset($j);
317
+                        $def = $trouver_table($id);
318
+                        $jointures[] = ['', [$id, $def], end($j)];
319
+                    }
320
+                    $jointures[0][0] = $id_table;
321
+                    if (!array_search($id, $boucle->from)) {
322
+                        include_spip('public/jointures');
323
+                        fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
324
+                    }
325
+                    // trouver l'alias de la table d'arrivee qui porte le statut
326
+                    $id = array_search($id, $boucle->from);
327
+                } else {
328
+                    $id = $id_table;
329
+                    $statut = preg_replace(',\W,', '', $s['champ']); // securite
330
+                }
331
+                $mstatut = $id . '.' . $statut;
332
+
333
+                $arg_ignore_previsu = ($ignore_previsu ? ',true' : '');
334
+                include_spip('public/quete');
335
+                if (
336
+                    isset($s['post_date']) and $s['post_date']
337
+                    and $GLOBALS['meta']['post_dates'] == 'non'
338
+                ) {
339
+                    $date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
340
+                    array_unshift(
341
+                        $boucle->where,
342
+                        $echapper ?
343
+                            "\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
344
+                            :
345
+                            quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
346
+                    );
347
+                }
348
+                array_unshift(
349
+                    $boucle->where,
350
+                    $echapper ?
351
+                        "\nquete_condition_statut('$mstatut',"
352
+                        . _q($s['previsu']) . ','
353
+                        . _q($s['publie']) . ','
354
+                        . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
355
+                        :
356
+                        quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
357
+                );
358
+            }
359
+        }
360
+    }
361 361
 }
362 362
 
363 363
 /**
@@ -376,29 +376,29 @@  discard block
 block discarded – undo
376 376
  */
377 377
 function calculer_boucle($id_boucle, &$boucles) {
378 378
 
379
-	$boucle = &$boucles[$id_boucle];
380
-	instituer_boucle($boucle);
381
-	$boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
382
-
383
-	// en mode debug memoriser les premiers passages dans la boucle,
384
-	// mais pas tous, sinon ca pete.
385
-	if (_request('var_mode_affiche') != 'resultat') {
386
-		$trace = '';
387
-	} else {
388
-		$_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
389
-		$_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
390
-		$trace = "
379
+    $boucle = &$boucles[$id_boucle];
380
+    instituer_boucle($boucle);
381
+    $boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
382
+
383
+    // en mode debug memoriser les premiers passages dans la boucle,
384
+    // mais pas tous, sinon ca pete.
385
+    if (_request('var_mode_affiche') != 'resultat') {
386
+        $trace = '';
387
+    } else {
388
+        $_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
389
+        $_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
390
+        $trace = "
391 391
 		if (empty($_trace)) {
392 392
 			$_trace = [];
393 393
 		}
394 394
 		if (count($_trace) < 3) {
395 395
 			$_trace" . '[] = $t0;
396 396
 		}';
397
-	}
397
+    }
398 398
 
399
-	return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
400
-		? calculer_boucle_rec($id_boucle, $boucles, $trace)
401
-		: calculer_boucle_nonrec($id_boucle, $boucles, $trace);
399
+    return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
400
+        ? calculer_boucle_rec($id_boucle, $boucles, $trace)
401
+        : calculer_boucle_nonrec($id_boucle, $boucles, $trace);
402 402
 }
403 403
 
404 404
 
@@ -421,15 +421,15 @@  discard block
 block discarded – undo
421 421
  *    Code PHP compilé de la boucle récursive
422 422
  **/
423 423
 function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
424
-	$nom = $boucles[$id_boucle]->param[0];
425
-
426
-	return
427
-		// Numrows[$nom] peut ne pas Ăªtre encore defini
428
-		"\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
429
-		. "\n\t\$t0 = " . $boucles[$id_boucle]->return . ';'
430
-		. "\n\t\$Numrows['$nom'] = (\$save_numrows);"
431
-		. $trace
432
-		. "\n\treturn \$t0;";
424
+    $nom = $boucles[$id_boucle]->param[0];
425
+
426
+    return
427
+        // Numrows[$nom] peut ne pas Ăªtre encore defini
428
+        "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
429
+        . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ';'
430
+        . "\n\t\$Numrows['$nom'] = (\$save_numrows);"
431
+        . $trace
432
+        . "\n\treturn \$t0;";
433 433
 }
434 434
 
435 435
 /**
@@ -482,173 +482,173 @@  discard block
 block discarded – undo
482 482
  **/
483 483
 function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
484 484
 
485
-	$code_sep = null;
486
-	$boucle = &$boucles[$id_boucle];
487
-	$return = $boucle->return;
488
-	$type_boucle = $boucle->type_requete;
489
-	$primary = $boucle->primary;
490
-	$constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
491
-	$flag_cpt = $boucle->mode_partie || $boucle->cptrows;
492
-	$corps = '';
493
-
494
-	// faudrait expanser le foreach a la compil, car y en a souvent qu'un
495
-	// et puis faire un [] plutot qu'un "','."
496
-	if ($boucle->doublons) {
497
-		$corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
498
-			index_pile($id_boucle, $primary, $boucles)
499
-			. "; // doublons\n";
500
-	}
501
-
502
-	// La boucle doit-elle selectionner la langue ?
503
-	// - par defaut, les boucles suivantes le font
504
-	//    (sauf si forcer_lang==true ou si le titre contient <multi>).
505
-	// - a moins d'une demande explicite via {!lang_select}
506
-	if (
507
-		!$constant && $boucle->lang_select != 'non' &&
508
-		(($boucle->lang_select == 'oui') ||
509
-			in_array($type_boucle, [
510
-				'articles',
511
-				'rubriques',
512
-				'hierarchie',
513
-				'breves'
514
-			]))
515
-	) {
516
-		// Memoriser la langue avant la boucle et la restituer apres
517
-		// afin que le corps de boucle affecte la globale directement
518
-		$init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
519
-		$fin_lang = "lang_select();\n\t";
520
-		$fin_lang_select_public = "\n\t\tlang_select();";
521
-
522
-		$corps .=
523
-			"\n\t\tlang_select_public("
524
-			. index_pile($id_boucle, 'lang', $boucles)
525
-			. ", '" . $boucle->lang_select . "'"
526
-			. (in_array($type_boucle, [
527
-				'articles',
528
-				'rubriques',
529
-				'hierarchie',
530
-				'breves'
531
-			]) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
532
-			. ');';
533
-	} else {
534
-		$init_lang = '';
535
-		$fin_lang = '';
536
-		$fin_lang_select_public = '';
537
-		// sortir les appels au traducteur (invariants de boucle)
538
-		if (
539
-			strpos($return, '?php') === false
540
-			and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
541
-		) {
542
-			$i = 1;
543
-			foreach ($r[1] as $t) {
544
-				$init_lang .= "\n\t\$l$i = $t;";
545
-				$return = str_replace($t, "\$l$i", $return);
546
-				$i++;
547
-			}
548
-		}
549
-	}
550
-
551
-	// gestion optimale des separateurs et des boucles constantes
552
-	if (is_countable($boucle->separateur) ? count($boucle->separateur) : 0) {
553
-		$code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
554
-	}
555
-
556
-	$corps .=
557
-		((!$boucle->separateur) ?
558
-			(($constant && !$corps && !$flag_cpt) ? $return :
559
-				(($return === "''") ? '' :
560
-					("\n\t\t" . '$t0 .= ' . $return . ';'))) :
561
-			("\n\t\t\$t1 " .
562
-				((strpos($return, '$t1.') === 0) ?
563
-					('.=' . substr($return, 4)) :
564
-					('= ' . $return)) .
565
-				";\n\t\t" .
566
-				'$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
567
-
568
-	// Calculer les invalideurs si c'est une boucle non constante et si on
569
-	// souhaite invalider ces elements
570
-	if (!$constant and $primary) {
571
-		include_spip('inc/invalideur');
572
-		$corps = calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
573
-	}
574
-
575
-	// gerer le compteur de boucle
576
-	// avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
577
-
578
-	if ($boucle->partie or $boucle->cptrows) {
579
-		$corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
580
-			. $boucle->partie
581
-			. $corps;
582
-	}
583
-
584
-	// depiler la lang de la boucle si besoin
585
-	$corps .= $fin_lang_select_public;
586
-
587
-	// si le corps est une constante, ne pas appeler le serveur N fois!
588
-
589
-	if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
590
-		if (!isset($r[2]) or (!$r[2])) {
591
-			if (!$boucle->numrows) {
592
-				return "\n\t\$t0 = '';";
593
-			} else {
594
-				$corps = '';
595
-			}
596
-		} else {
597
-			$boucle->numrows = true;
598
-			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
599
-		}
600
-	} else {
601
-		$corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
602
-	}
603
-
604
-	$count = '';
605
-	if (!$boucle->select) {
606
-		if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
607
-			$count = '1';
608
-		} else {
609
-			$count = 'count(*)';
610
-		}
611
-		$boucles[$id_boucle]->select[] = $count;
612
-	}
613
-
614
-	if ($flag_cpt) {
615
-		$nums = "\n\t// COMPTEUR\n\t"
616
-			. "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
617
-	} else {
618
-		$nums = '';
619
-	}
620
-
621
-	if ($boucle->numrows or $boucle->mode_partie) {
622
-		$nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
623
-			. "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
624
-			. $boucle->mode_partie
625
-			. "\n\t";
626
-	}
627
-
628
-	// Ne calculer la requete que maintenant
629
-	// car ce qui precede appelle index_pile qui influe dessus
630
-
631
-	$init = (($init = $boucles[$id_boucle]->doublons)
632
-			? ("\n\t$init = array();") : '')
633
-		. calculer_requete_sql($boucles[$id_boucle]);
634
-
635
-	$contexte = memoriser_contexte_compil($boucle);
636
-
637
-	$a = sprintf(
638
-		CODE_CORPS_BOUCLE,
639
-		$init,
640
-		$boucle->iterateur,
641
-		'$command',
642
-		$contexte,
643
-		$nums,
644
-		$init_lang,
645
-		$corps,
646
-		$fin_lang,
647
-		$trace,
648
-		'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
649
-	);
650
-
651
-	return $a;
485
+    $code_sep = null;
486
+    $boucle = &$boucles[$id_boucle];
487
+    $return = $boucle->return;
488
+    $type_boucle = $boucle->type_requete;
489
+    $primary = $boucle->primary;
490
+    $constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
491
+    $flag_cpt = $boucle->mode_partie || $boucle->cptrows;
492
+    $corps = '';
493
+
494
+    // faudrait expanser le foreach a la compil, car y en a souvent qu'un
495
+    // et puis faire un [] plutot qu'un "','."
496
+    if ($boucle->doublons) {
497
+        $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
498
+            index_pile($id_boucle, $primary, $boucles)
499
+            . "; // doublons\n";
500
+    }
501
+
502
+    // La boucle doit-elle selectionner la langue ?
503
+    // - par defaut, les boucles suivantes le font
504
+    //    (sauf si forcer_lang==true ou si le titre contient <multi>).
505
+    // - a moins d'une demande explicite via {!lang_select}
506
+    if (
507
+        !$constant && $boucle->lang_select != 'non' &&
508
+        (($boucle->lang_select == 'oui') ||
509
+            in_array($type_boucle, [
510
+                'articles',
511
+                'rubriques',
512
+                'hierarchie',
513
+                'breves'
514
+            ]))
515
+    ) {
516
+        // Memoriser la langue avant la boucle et la restituer apres
517
+        // afin que le corps de boucle affecte la globale directement
518
+        $init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
519
+        $fin_lang = "lang_select();\n\t";
520
+        $fin_lang_select_public = "\n\t\tlang_select();";
521
+
522
+        $corps .=
523
+            "\n\t\tlang_select_public("
524
+            . index_pile($id_boucle, 'lang', $boucles)
525
+            . ", '" . $boucle->lang_select . "'"
526
+            . (in_array($type_boucle, [
527
+                'articles',
528
+                'rubriques',
529
+                'hierarchie',
530
+                'breves'
531
+            ]) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
532
+            . ');';
533
+    } else {
534
+        $init_lang = '';
535
+        $fin_lang = '';
536
+        $fin_lang_select_public = '';
537
+        // sortir les appels au traducteur (invariants de boucle)
538
+        if (
539
+            strpos($return, '?php') === false
540
+            and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
541
+        ) {
542
+            $i = 1;
543
+            foreach ($r[1] as $t) {
544
+                $init_lang .= "\n\t\$l$i = $t;";
545
+                $return = str_replace($t, "\$l$i", $return);
546
+                $i++;
547
+            }
548
+        }
549
+    }
550
+
551
+    // gestion optimale des separateurs et des boucles constantes
552
+    if (is_countable($boucle->separateur) ? count($boucle->separateur) : 0) {
553
+        $code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
554
+    }
555
+
556
+    $corps .=
557
+        ((!$boucle->separateur) ?
558
+            (($constant && !$corps && !$flag_cpt) ? $return :
559
+                (($return === "''") ? '' :
560
+                    ("\n\t\t" . '$t0 .= ' . $return . ';'))) :
561
+            ("\n\t\t\$t1 " .
562
+                ((strpos($return, '$t1.') === 0) ?
563
+                    ('.=' . substr($return, 4)) :
564
+                    ('= ' . $return)) .
565
+                ";\n\t\t" .
566
+                '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
567
+
568
+    // Calculer les invalideurs si c'est une boucle non constante et si on
569
+    // souhaite invalider ces elements
570
+    if (!$constant and $primary) {
571
+        include_spip('inc/invalideur');
572
+        $corps = calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
573
+    }
574
+
575
+    // gerer le compteur de boucle
576
+    // avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
577
+
578
+    if ($boucle->partie or $boucle->cptrows) {
579
+        $corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
580
+            . $boucle->partie
581
+            . $corps;
582
+    }
583
+
584
+    // depiler la lang de la boucle si besoin
585
+    $corps .= $fin_lang_select_public;
586
+
587
+    // si le corps est une constante, ne pas appeler le serveur N fois!
588
+
589
+    if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
590
+        if (!isset($r[2]) or (!$r[2])) {
591
+            if (!$boucle->numrows) {
592
+                return "\n\t\$t0 = '';";
593
+            } else {
594
+                $corps = '';
595
+            }
596
+        } else {
597
+            $boucle->numrows = true;
598
+            $corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
599
+        }
600
+    } else {
601
+        $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
602
+    }
603
+
604
+    $count = '';
605
+    if (!$boucle->select) {
606
+        if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
607
+            $count = '1';
608
+        } else {
609
+            $count = 'count(*)';
610
+        }
611
+        $boucles[$id_boucle]->select[] = $count;
612
+    }
613
+
614
+    if ($flag_cpt) {
615
+        $nums = "\n\t// COMPTEUR\n\t"
616
+            . "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
617
+    } else {
618
+        $nums = '';
619
+    }
620
+
621
+    if ($boucle->numrows or $boucle->mode_partie) {
622
+        $nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
623
+            . "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
624
+            . $boucle->mode_partie
625
+            . "\n\t";
626
+    }
627
+
628
+    // Ne calculer la requete que maintenant
629
+    // car ce qui precede appelle index_pile qui influe dessus
630
+
631
+    $init = (($init = $boucles[$id_boucle]->doublons)
632
+            ? ("\n\t$init = array();") : '')
633
+        . calculer_requete_sql($boucles[$id_boucle]);
634
+
635
+    $contexte = memoriser_contexte_compil($boucle);
636
+
637
+    $a = sprintf(
638
+        CODE_CORPS_BOUCLE,
639
+        $init,
640
+        $boucle->iterateur,
641
+        '$command',
642
+        $contexte,
643
+        $nums,
644
+        $init_lang,
645
+        $corps,
646
+        $fin_lang,
647
+        $trace,
648
+        'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
649
+    );
650
+
651
+    return $a;
652 652
 }
653 653
 
654 654
 
@@ -664,48 +664,48 @@  discard block
 block discarded – undo
664 664
  *     Code PHP compilĂ© dĂ©finissant les informations de requĂªte
665 665
  **/
666 666
 function calculer_requete_sql($boucle) {
667
-	$init = [];
668
-	$init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
669
-	$init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
670
-	# En absence de champ c'est un decompte :
671
-	$init[] = calculer_dec('from', calculer_from($boucle));
672
-	$init[] = calculer_dec('type', calculer_from_type($boucle));
673
-	$init[] = calculer_dec(
674
-		'groupby',
675
-		'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ')'
676
-	);
677
-	$init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . '")');
678
-	$init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ')');
679
-	$init[] = calculer_dec('where', calculer_dump_array($boucle->where));
680
-	$init[] = calculer_dec('join', calculer_dump_join($boucle->join));
681
-	$init[] = calculer_dec(
682
-		'limit',
683
-		(
684
-			strpos($boucle->limit, 'intval') === false ?
685
-			"'" . ($boucle->limit) . "'" :
686
-			$boucle->limit
687
-		)
688
-	);
689
-	$init[] = calculer_dec('having', calculer_dump_array($boucle->having));
690
-	$s = $d = '';
691
-	// l'index 0 de $i indique si l'affectation est statique (contenu)
692
-	// ou recalculée à chaque passage (vide)
693
-	foreach ($init as $i) {
694
-		if (reset($i)) {
695
-			$s .= "\n\t\t" . end($i);
696
-		} # statique
697
-		else {
698
-			$d .= "\n\t" . end($i);
699
-		} # dynamique
700
-	}
701
-
702
-	return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
703
-	. $boucle->in
704
-	. $boucle->hash
705
-	. "\n\t" . 'if (!isset($command[\'table\'])) {'
706
-	. $s
707
-	. "\n\t}"
708
-	. $d;
667
+    $init = [];
668
+    $init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
669
+    $init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
670
+    # En absence de champ c'est un decompte :
671
+    $init[] = calculer_dec('from', calculer_from($boucle));
672
+    $init[] = calculer_dec('type', calculer_from_type($boucle));
673
+    $init[] = calculer_dec(
674
+        'groupby',
675
+        'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ')'
676
+    );
677
+    $init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . '")');
678
+    $init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ')');
679
+    $init[] = calculer_dec('where', calculer_dump_array($boucle->where));
680
+    $init[] = calculer_dec('join', calculer_dump_join($boucle->join));
681
+    $init[] = calculer_dec(
682
+        'limit',
683
+        (
684
+            strpos($boucle->limit, 'intval') === false ?
685
+            "'" . ($boucle->limit) . "'" :
686
+            $boucle->limit
687
+        )
688
+    );
689
+    $init[] = calculer_dec('having', calculer_dump_array($boucle->having));
690
+    $s = $d = '';
691
+    // l'index 0 de $i indique si l'affectation est statique (contenu)
692
+    // ou recalculée à chaque passage (vide)
693
+    foreach ($init as $i) {
694
+        if (reset($i)) {
695
+            $s .= "\n\t\t" . end($i);
696
+        } # statique
697
+        else {
698
+            $d .= "\n\t" . end($i);
699
+        } # dynamique
700
+    }
701
+
702
+    return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
703
+    . $boucle->in
704
+    . $boucle->hash
705
+    . "\n\t" . 'if (!isset($command[\'table\'])) {'
706
+    . $s
707
+    . "\n\t}"
708
+    . $d;
709 709
 }
710 710
 
711 711
 /**
@@ -723,13 +723,13 @@  discard block
 block discarded – undo
723 723
  *     qui peut Ăªtre utilisĂ© pour la production d'un tableau array()
724 724
  **/
725 725
 function memoriser_contexte_compil($p) {
726
-	return join(',', [
727
-		_q($p->descr['sourcefile'] ?? ''),
728
-		_q($p->descr['nom'] ?? ''),
729
-		_q($p->id_boucle ?? ''),
730
-		intval($p->ligne),
731
-		'$GLOBALS[\'spip_lang\']'
732
-	]);
726
+    return join(',', [
727
+        _q($p->descr['sourcefile'] ?? ''),
728
+        _q($p->descr['nom'] ?? ''),
729
+        _q($p->id_boucle ?? ''),
730
+        intval($p->ligne),
731
+        '$GLOBALS[\'spip_lang\']'
732
+    ]);
733 733
 }
734 734
 
735 735
 /**
@@ -747,20 +747,20 @@  discard block
 block discarded – undo
747 747
  *     Objet Contexte
748 748
  **/
749 749
 function reconstruire_contexte_compil($context_compil) {
750
-	if (!is_array($context_compil)) {
751
-		return $context_compil;
752
-	}
753
-	$p = new Contexte();
754
-	$p->descr = [
755
-		'sourcefile' => $context_compil[0] ?? '',
756
-		'nom' => $context_compil[1] ?? '',
757
-	];
758
-
759
-	$p->id_boucle = $context_compil[2] ?? '';
760
-	$p->ligne = (int)($context_compil[3] ?? 0);
761
-	$p->lang = $context_compil[4] ?? '';
762
-
763
-	return $p;
750
+    if (!is_array($context_compil)) {
751
+        return $context_compil;
752
+    }
753
+    $p = new Contexte();
754
+    $p->descr = [
755
+        'sourcefile' => $context_compil[0] ?? '',
756
+        'nom' => $context_compil[1] ?? '',
757
+    ];
758
+
759
+    $p->id_boucle = $context_compil[2] ?? '';
760
+    $p->ligne = (int)($context_compil[3] ?? 0);
761
+    $p->lang = $context_compil[4] ?? '';
762
+
763
+    return $p;
764 764
 }
765 765
 
766 766
 /**
@@ -786,12 +786,12 @@  discard block
 block discarded – undo
786 786
  *    - index 1 : Code de l'affectation
787 787
  **/
788 788
 function calculer_dec($nom, $val) {
789
-	$static = 'if (!isset($command[\'' . $nom . '\'])) ';
790
-	// si une variable apparait dans le calcul de la clause
791
-	// il faut la re-evaluer a chaque passage
792
-	if (
793
-		str_contains($val, '$')
794
-		/*
789
+    $static = 'if (!isset($command[\'' . $nom . '\'])) ';
790
+    // si une variable apparait dans le calcul de la clause
791
+    // il faut la re-evaluer a chaque passage
792
+    if (
793
+        str_contains($val, '$')
794
+        /*
795 795
 		OR str_contains($val, 'sql_')
796 796
 		OR (
797 797
 			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
@@ -799,11 +799,11 @@  discard block
 block discarded – undo
799 799
 			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
800 800
 			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
801 801
 		)*/
802
-	) {
803
-		$static = '';
804
-	}
802
+    ) {
803
+        $static = '';
804
+    }
805 805
 
806
-	return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
806
+    return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
807 807
 }
808 808
 
809 809
 /**
@@ -823,32 +823,32 @@  discard block
 block discarded – undo
823 823
  *     Expression PHP décrivant un texte ou un tableau
824 824
  **/
825 825
 function calculer_dump_array($a) {
826
-	if (!is_array($a)) {
827
-		return $a;
828
-	}
829
-	$res = '';
830
-	if ($a and $a[0] == "'?'") {
831
-		return ('(' . calculer_dump_array($a[1]) .
832
-			' ? ' . calculer_dump_array($a[2]) .
833
-			' : ' . calculer_dump_array($a[3]) .
834
-			')');
835
-	} else {
836
-		foreach ($a as $k => $v) {
837
-			$showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
838
-			$res .= ', ' . $showk . calculer_dump_array($v);
839
-		}
840
-
841
-		return "\n\t\t\tarray(" . substr($res, 2) . ')';
842
-	}
826
+    if (!is_array($a)) {
827
+        return $a;
828
+    }
829
+    $res = '';
830
+    if ($a and $a[0] == "'?'") {
831
+        return ('(' . calculer_dump_array($a[1]) .
832
+            ' ? ' . calculer_dump_array($a[2]) .
833
+            ' : ' . calculer_dump_array($a[3]) .
834
+            ')');
835
+    } else {
836
+        foreach ($a as $k => $v) {
837
+            $showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
838
+            $res .= ', ' . $showk . calculer_dump_array($v);
839
+        }
840
+
841
+        return "\n\t\t\tarray(" . substr($res, 2) . ')';
842
+    }
843 843
 }
844 844
 
845 845
 function calculer_dump_join($a) {
846
-	$res = '';
847
-	foreach ($a as $k => $v) {
848
-		$res .= ", '$k' => array(" . implode(',', $v) . ')';
849
-	}
846
+    $res = '';
847
+    foreach ($a as $k => $v) {
848
+        $res .= ", '$k' => array(" . implode(',', $v) . ')';
849
+    }
850 850
 
851
-	return 'array(' . substr($res, 2) . ')';
851
+    return 'array(' . substr($res, 2) . ')';
852 852
 }
853 853
 
854 854
 /**
@@ -860,12 +860,12 @@  discard block
 block discarded – undo
860 860
  *     Code PHP construisant un tableau des alias et noms des tables du FROM
861 861
  **/
862 862
 function calculer_from(&$boucle) {
863
-	$res = '';
864
-	foreach ($boucle->from as $k => $v) {
865
-		$res .= ",'$k' => '$v'";
866
-	}
863
+    $res = '';
864
+    foreach ($boucle->from as $k => $v) {
865
+        $res .= ",'$k' => '$v'";
866
+    }
867 867
 
868
-	return 'array(' . substr($res, 1) . ')';
868
+    return 'array(' . substr($res, 1) . ')';
869 869
 }
870 870
 
871 871
 /**
@@ -878,30 +878,30 @@  discard block
 block discarded – undo
878 878
  *     Code PHP construisant un tableau des alias et type de jointure du FROM
879 879
  **/
880 880
 function calculer_from_type(&$boucle) {
881
-	$res = '';
882
-	foreach ($boucle->from_type as $k => $v) {
883
-		$res .= ",'$k' => '$v'";
884
-	}
881
+    $res = '';
882
+    foreach ($boucle->from_type as $k => $v) {
883
+        $res .= ",'$k' => '$v'";
884
+    }
885 885
 
886
-	return 'array(' . substr($res, 1) . ')';
886
+    return 'array(' . substr($res, 1) . ')';
887 887
 }
888 888
 
889 889
 function calculer_order(&$boucle) {
890
-	if (
891
-		!$order = $boucle->order
892
-		and !$order = $boucle->default_order
893
-	) {
894
-		$order = [];
895
-	}
896
-
897
-	/*if (isset($boucle->modificateur['collate'])){
890
+    if (
891
+        !$order = $boucle->order
892
+        and !$order = $boucle->default_order
893
+    ) {
894
+        $order = [];
895
+    }
896
+
897
+    /*if (isset($boucle->modificateur['collate'])){
898 898
 		$col = "." . $boucle->modificateur['collate'];
899 899
 		foreach($order as $k=>$o)
900 900
 			if (strpos($order[$k],'COLLATE')===false)
901 901
 				$order[$k].= $col;
902 902
 	}*/
903 903
 
904
-	return join(', ', $order);
904
+    return join(', ', $order);
905 905
 }
906 906
 
907 907
 // Production du code PHP a partir de la sequence livree par le phraseur
@@ -910,62 +910,62 @@  discard block
 block discarded – undo
910 910
 // (qui sera argument d'un Return ou la partie droite d'une affectation).
911 911
 
912 912
 function calculer_liste($tableau, $descr, &$boucles, $id_boucle = '') {
913
-	if (!$tableau) {
914
-		return "''";
915
-	}
916
-	if (is_string($descr)) {
917
-		if (isset($boucles[$descr])) {
918
-			$idb = $descr;
919
-			$descr = [];
920
-			if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
921
-				$descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
922
-			}
923
-			if (isset($boucles[$idb]->descr['sourcefile'])) {
924
-				$descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
925
-			}
926
-		}
927
-		else {
928
-			$descr = [];
929
-		}
930
-	}
931
-	if (!isset($descr['niv'])) {
932
-		$descr['niv'] = 0;
933
-	}
934
-	$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
935
-	if ($codes === false) {
936
-		return false;
937
-	}
938
-	$n = is_countable($codes) ? count($codes) : 0;
939
-	if (!$n) {
940
-		return "''";
941
-	}
942
-	$tab = str_repeat("\t", $descr['niv']);
943
-	if (_request('var_mode_affiche') != 'validation') {
944
-		if ($n == 1) {
945
-			return $codes[0];
946
-		} else {
947
-			$res = '';
948
-			foreach ($codes as $code) {
949
-				if (
950
-					!preg_match("/^'[^']*'$/", $code)
951
-					or substr($res, -1, 1) !== "'"
952
-				) {
953
-					$res .= " .\n$tab$code";
954
-				} else {
955
-					$res = substr($res, 0, -1) . substr($code, 1);
956
-				}
957
-			}
958
-
959
-			return '(' . substr($res, 2 + $descr['niv']) . ')';
960
-		}
961
-	} else {
962
-		$nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
963
-
964
-		return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
965
-			" ,\n$tab",
966
-			$codes
967
-		) . ')))';
968
-	}
913
+    if (!$tableau) {
914
+        return "''";
915
+    }
916
+    if (is_string($descr)) {
917
+        if (isset($boucles[$descr])) {
918
+            $idb = $descr;
919
+            $descr = [];
920
+            if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
921
+                $descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
922
+            }
923
+            if (isset($boucles[$idb]->descr['sourcefile'])) {
924
+                $descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
925
+            }
926
+        }
927
+        else {
928
+            $descr = [];
929
+        }
930
+    }
931
+    if (!isset($descr['niv'])) {
932
+        $descr['niv'] = 0;
933
+    }
934
+    $codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
935
+    if ($codes === false) {
936
+        return false;
937
+    }
938
+    $n = is_countable($codes) ? count($codes) : 0;
939
+    if (!$n) {
940
+        return "''";
941
+    }
942
+    $tab = str_repeat("\t", $descr['niv']);
943
+    if (_request('var_mode_affiche') != 'validation') {
944
+        if ($n == 1) {
945
+            return $codes[0];
946
+        } else {
947
+            $res = '';
948
+            foreach ($codes as $code) {
949
+                if (
950
+                    !preg_match("/^'[^']*'$/", $code)
951
+                    or substr($res, -1, 1) !== "'"
952
+                ) {
953
+                    $res .= " .\n$tab$code";
954
+                } else {
955
+                    $res = substr($res, 0, -1) . substr($code, 1);
956
+                }
957
+            }
958
+
959
+            return '(' . substr($res, 2 + $descr['niv']) . ')';
960
+        }
961
+    } else {
962
+        $nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
963
+
964
+        return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
965
+            " ,\n$tab",
966
+            $codes
967
+        ) . ')))';
968
+    }
969 969
 }
970 970
 
971 971
 
@@ -984,213 +984,213 @@  discard block
 block discarded – undo
984 984
  */
985 985
 function compile_cas($tableau, $descr, &$boucles, $id_boucle) {
986 986
 
987
-	$codes = [];
988
-	// cas de la boucle recursive
989
-	if (is_array($id_boucle)) {
990
-		$id_boucle = $id_boucle[0];
991
-	}
992
-	$type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
993
-	$tab = str_repeat("\t", ++$descr['niv']);
994
-	$mode = _request('var_mode_affiche');
995
-	$err_e_c = '';
996
-	// chaque commentaire introduit dans le code doit commencer
997
-	// par un caractere distinguant le cas, pour exploitation par debug.
998
-	foreach ($tableau as $p) {
999
-		switch ($p->type) {
1000
-			// texte seul
1001
-			case 'texte':
1002
-				$code = sandbox_composer_texte($p->texte, $p);
1003
-				$commentaire = strlen($p->texte) . ' signes';
1004
-				$avant = '';
1005
-				$apres = '';
1006
-				$altern = "''";
1007
-				break;
1008
-
1009
-			case 'polyglotte':
1010
-				$code = '';
1011
-				foreach ($p->traductions as $k => $v) {
1012
-					$code .= ",'" .
1013
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1014
-						"' => '" .
1015
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1016
-						"'";
1017
-				}
1018
-				$code = 'choisir_traduction(array(' .
1019
-					substr($code, 1) .
1020
-					'))';
1021
-				$commentaire = '&';
1022
-				$avant = '';
1023
-				$apres = '';
1024
-				$altern = "''";
1025
-				break;
1026
-
1027
-			// inclure
1028
-			case 'include':
1029
-				$p->descr = $descr;
1030
-				$code = calculer_inclure($p, $boucles, $id_boucle);
1031
-				if ($code === false) {
1032
-					$err_e_c = true;
1033
-					$code = "''";
1034
-				} else {
1035
-					$commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1036
-					$avant = '';
1037
-					$apres = '';
1038
-					$altern = "''";
1039
-				}
1040
-				break;
1041
-
1042
-			// boucle
1043
-			case TYPE_RECURSIF:
1044
-				$nom = $p->id_boucle;
1045
-				$newdescr = $descr;
1046
-				$newdescr['id_mere'] = $nom;
1047
-				$newdescr['niv']++;
1048
-				$preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1049
-				$avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1050
-				$apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1051
-				$postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1052
-				$newdescr['niv']--;
1053
-				$altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1054
-				if (
1055
-					$preaff === false
1056
-					or $avant === false
1057
-					or $apres === false
1058
-					or $altern === false
1059
-					or $postaff === false
1060
-				) {
1061
-					$err_e_c = true;
1062
-					$code = "''";
1063
-				} else {
1064
-					$code = 'BOUCLE' .
1065
-						str_replace('-', '_', $nom) . $descr['nom'] .
1066
-						'($Cache, $Pile, $doublons, $Numrows, $SP)';
1067
-					$commentaire = "?$nom";
1068
-					if (
1069
-						!$boucles[$nom]->milieu
1070
-						and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1071
-					) {
1072
-						if ($preaff != "''") {
1073
-							$code .= "\n. $preaff";
1074
-						}
1075
-						if ($altern != "''") {
1076
-							$code .= "\n. $altern";
1077
-						}
1078
-						if ($postaff != "''") {
1079
-							$code .= "\n. $postaff";
1080
-						}
1081
-						if ($avant <> "''" or $apres <> "''") {
1082
-							spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1083
-						}
1084
-						$avant = $apres = $altern = "''";
1085
-					} else {
1086
-						if ($preaff != "''") {
1087
-							$avant = compile_concatene_parties_codes($preaff, $avant);
1088
-							$altern = compile_concatene_parties_codes($preaff, $altern);
1089
-						}
1090
-						if ($postaff != "''") {
1091
-							$apres = compile_concatene_parties_codes($apres, $postaff);
1092
-							$altern = compile_concatene_parties_codes($altern, $postaff);
1093
-						}
1094
-						if ($altern != "''") {
1095
-							$altern = "($altern)";
1096
-						}
1097
-					}
1098
-				}
1099
-				break;
1100
-
1101
-			case 'idiome':
1102
-				$l = [];
1103
-				$code = '';
1104
-				foreach ($p->arg as $k => $v) {
1105
-					$_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1106
-					if ($k) {
1107
-						$l[] = _q($k) . ' => ' . $_v;
1108
-					} else {
1109
-						$code = $_v;
1110
-					}
1111
-				}
1112
-				// Si le module n'est pas fourni, l'expliciter sauf si calculé
1113
-				if ($p->module) {
1114
-					$m = $p->module . ':' . $p->nom_champ;
1115
-				} elseif ($p->nom_champ) {
1116
-					$m = MODULES_IDIOMES . ':' . $p->nom_champ;
1117
-				} else {
1118
-					$m = '';
1119
-				}
1120
-
1121
-				$code = (!$code ? "'$m'" :
1122
-						($m ? "'$m' . $code" :
1123
-							("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1124
-					. (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1125
-				$code = "_T($code)";
1126
-				if ($p->param) {
1127
-					$p->id_boucle = $id_boucle;
1128
-					$p->boucles = &$boucles;
1129
-					$code = compose_filtres($p, $code);
1130
-				}
1131
-				$commentaire = ':';
1132
-				$avant = '';
1133
-				$apres = '';
1134
-				$altern = "''";
1135
-				break;
1136
-
1137
-			case 'champ':
1138
-				// cette structure pourrait etre completee des le phrase' (a faire)
1139
-				$p->id_boucle = $id_boucle;
1140
-				$p->boucles = &$boucles;
1141
-				$p->descr = $descr;
1142
-				#$p->interdire_scripts = true;
1143
-				$p->type_requete = $type;
1144
-
1145
-				$code = calculer_champ($p);
1146
-				$commentaire = '#' . $p->nom_champ . $p->etoile;
1147
-				$avant = calculer_liste(
1148
-					$p->avant,
1149
-					$descr,
1150
-					$boucles,
1151
-					$id_boucle
1152
-				);
1153
-				$apres = calculer_liste(
1154
-					$p->apres,
1155
-					$descr,
1156
-					$boucles,
1157
-					$id_boucle
1158
-				);
1159
-				$altern = "''";
1160
-				// Si la valeur est destinee a une comparaison a ''
1161
-				// forcer la conversion en une chaine par strval
1162
-				// si ca peut etre autre chose qu'une chaine
1163
-				if (
1164
-					($avant != "''" or $apres != "''")
1165
-					and $code[0] != "'"
1166
-					# AND (strpos($code,'interdire_scripts') !== 0)
1167
-					and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1168
-					and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1169
-					and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1170
-				) {
1171
-					$code = "strval($code)";
1172
-				}
1173
-				break;
1174
-
1175
-			default:
1176
-				// Erreur de construction de l'arbre de syntaxe abstraite
1177
-				$code = "''";
1178
-				$p->descr = $descr;
1179
-				$err_e_c = _T('zbug_erreur_compilation');
1180
-				erreur_squelette($err_e_c, $p);
1181
-		} // switch
1182
-
1183
-		if ($code != "''") {
1184
-			$code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1185
-			$codes[] = (($mode == 'validation') ?
1186
-				"array($code, '$commentaire', " . $p->ligne . ')'
1187
-				: (($mode == 'code') ?
1188
-					"\n// $commentaire\n$code" :
1189
-					$code));
1190
-		}
1191
-	} // foreach
1192
-
1193
-	return $err_e_c ? false : $codes;
987
+    $codes = [];
988
+    // cas de la boucle recursive
989
+    if (is_array($id_boucle)) {
990
+        $id_boucle = $id_boucle[0];
991
+    }
992
+    $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
993
+    $tab = str_repeat("\t", ++$descr['niv']);
994
+    $mode = _request('var_mode_affiche');
995
+    $err_e_c = '';
996
+    // chaque commentaire introduit dans le code doit commencer
997
+    // par un caractere distinguant le cas, pour exploitation par debug.
998
+    foreach ($tableau as $p) {
999
+        switch ($p->type) {
1000
+            // texte seul
1001
+            case 'texte':
1002
+                $code = sandbox_composer_texte($p->texte, $p);
1003
+                $commentaire = strlen($p->texte) . ' signes';
1004
+                $avant = '';
1005
+                $apres = '';
1006
+                $altern = "''";
1007
+                break;
1008
+
1009
+            case 'polyglotte':
1010
+                $code = '';
1011
+                foreach ($p->traductions as $k => $v) {
1012
+                    $code .= ",'" .
1013
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1014
+                        "' => '" .
1015
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1016
+                        "'";
1017
+                }
1018
+                $code = 'choisir_traduction(array(' .
1019
+                    substr($code, 1) .
1020
+                    '))';
1021
+                $commentaire = '&';
1022
+                $avant = '';
1023
+                $apres = '';
1024
+                $altern = "''";
1025
+                break;
1026
+
1027
+            // inclure
1028
+            case 'include':
1029
+                $p->descr = $descr;
1030
+                $code = calculer_inclure($p, $boucles, $id_boucle);
1031
+                if ($code === false) {
1032
+                    $err_e_c = true;
1033
+                    $code = "''";
1034
+                } else {
1035
+                    $commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1036
+                    $avant = '';
1037
+                    $apres = '';
1038
+                    $altern = "''";
1039
+                }
1040
+                break;
1041
+
1042
+            // boucle
1043
+            case TYPE_RECURSIF:
1044
+                $nom = $p->id_boucle;
1045
+                $newdescr = $descr;
1046
+                $newdescr['id_mere'] = $nom;
1047
+                $newdescr['niv']++;
1048
+                $preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1049
+                $avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1050
+                $apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1051
+                $postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1052
+                $newdescr['niv']--;
1053
+                $altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1054
+                if (
1055
+                    $preaff === false
1056
+                    or $avant === false
1057
+                    or $apres === false
1058
+                    or $altern === false
1059
+                    or $postaff === false
1060
+                ) {
1061
+                    $err_e_c = true;
1062
+                    $code = "''";
1063
+                } else {
1064
+                    $code = 'BOUCLE' .
1065
+                        str_replace('-', '_', $nom) . $descr['nom'] .
1066
+                        '($Cache, $Pile, $doublons, $Numrows, $SP)';
1067
+                    $commentaire = "?$nom";
1068
+                    if (
1069
+                        !$boucles[$nom]->milieu
1070
+                        and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1071
+                    ) {
1072
+                        if ($preaff != "''") {
1073
+                            $code .= "\n. $preaff";
1074
+                        }
1075
+                        if ($altern != "''") {
1076
+                            $code .= "\n. $altern";
1077
+                        }
1078
+                        if ($postaff != "''") {
1079
+                            $code .= "\n. $postaff";
1080
+                        }
1081
+                        if ($avant <> "''" or $apres <> "''") {
1082
+                            spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1083
+                        }
1084
+                        $avant = $apres = $altern = "''";
1085
+                    } else {
1086
+                        if ($preaff != "''") {
1087
+                            $avant = compile_concatene_parties_codes($preaff, $avant);
1088
+                            $altern = compile_concatene_parties_codes($preaff, $altern);
1089
+                        }
1090
+                        if ($postaff != "''") {
1091
+                            $apres = compile_concatene_parties_codes($apres, $postaff);
1092
+                            $altern = compile_concatene_parties_codes($altern, $postaff);
1093
+                        }
1094
+                        if ($altern != "''") {
1095
+                            $altern = "($altern)";
1096
+                        }
1097
+                    }
1098
+                }
1099
+                break;
1100
+
1101
+            case 'idiome':
1102
+                $l = [];
1103
+                $code = '';
1104
+                foreach ($p->arg as $k => $v) {
1105
+                    $_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1106
+                    if ($k) {
1107
+                        $l[] = _q($k) . ' => ' . $_v;
1108
+                    } else {
1109
+                        $code = $_v;
1110
+                    }
1111
+                }
1112
+                // Si le module n'est pas fourni, l'expliciter sauf si calculé
1113
+                if ($p->module) {
1114
+                    $m = $p->module . ':' . $p->nom_champ;
1115
+                } elseif ($p->nom_champ) {
1116
+                    $m = MODULES_IDIOMES . ':' . $p->nom_champ;
1117
+                } else {
1118
+                    $m = '';
1119
+                }
1120
+
1121
+                $code = (!$code ? "'$m'" :
1122
+                        ($m ? "'$m' . $code" :
1123
+                            ("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1124
+                    . (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1125
+                $code = "_T($code)";
1126
+                if ($p->param) {
1127
+                    $p->id_boucle = $id_boucle;
1128
+                    $p->boucles = &$boucles;
1129
+                    $code = compose_filtres($p, $code);
1130
+                }
1131
+                $commentaire = ':';
1132
+                $avant = '';
1133
+                $apres = '';
1134
+                $altern = "''";
1135
+                break;
1136
+
1137
+            case 'champ':
1138
+                // cette structure pourrait etre completee des le phrase' (a faire)
1139
+                $p->id_boucle = $id_boucle;
1140
+                $p->boucles = &$boucles;
1141
+                $p->descr = $descr;
1142
+                #$p->interdire_scripts = true;
1143
+                $p->type_requete = $type;
1144
+
1145
+                $code = calculer_champ($p);
1146
+                $commentaire = '#' . $p->nom_champ . $p->etoile;
1147
+                $avant = calculer_liste(
1148
+                    $p->avant,
1149
+                    $descr,
1150
+                    $boucles,
1151
+                    $id_boucle
1152
+                );
1153
+                $apres = calculer_liste(
1154
+                    $p->apres,
1155
+                    $descr,
1156
+                    $boucles,
1157
+                    $id_boucle
1158
+                );
1159
+                $altern = "''";
1160
+                // Si la valeur est destinee a une comparaison a ''
1161
+                // forcer la conversion en une chaine par strval
1162
+                // si ca peut etre autre chose qu'une chaine
1163
+                if (
1164
+                    ($avant != "''" or $apres != "''")
1165
+                    and $code[0] != "'"
1166
+                    # AND (strpos($code,'interdire_scripts') !== 0)
1167
+                    and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1168
+                    and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1169
+                    and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1170
+                ) {
1171
+                    $code = "strval($code)";
1172
+                }
1173
+                break;
1174
+
1175
+            default:
1176
+                // Erreur de construction de l'arbre de syntaxe abstraite
1177
+                $code = "''";
1178
+                $p->descr = $descr;
1179
+                $err_e_c = _T('zbug_erreur_compilation');
1180
+                erreur_squelette($err_e_c, $p);
1181
+        } // switch
1182
+
1183
+        if ($code != "''") {
1184
+            $code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1185
+            $codes[] = (($mode == 'validation') ?
1186
+                "array($code, '$commentaire', " . $p->ligne . ')'
1187
+                : (($mode == 'code') ?
1188
+                    "\n// $commentaire\n$code" :
1189
+                    $code));
1190
+        }
1191
+    } // foreach
1192
+
1193
+    return $err_e_c ? false : $codes;
1194 1194
 }
1195 1195
 
1196 1196
 /**
@@ -1200,13 +1200,13 @@  discard block
 block discarded – undo
1200 1200
  * @return string
1201 1201
  */
1202 1202
 function compile_concatene_parties_codes($partie1, $partie2) {
1203
-	if ($partie1 === "''") {
1204
-		return $partie2;
1205
-	}
1206
-	if ($partie2 === "''") {
1207
-		return $partie1;
1208
-	}
1209
-	return "$partie1\n. $partie2";
1203
+    if ($partie1 === "''") {
1204
+        return $partie2;
1205
+    }
1206
+    if ($partie2 === "''") {
1207
+        return $partie1;
1208
+    }
1209
+    return "$partie1\n. $partie2";
1210 1210
 }
1211 1211
 
1212 1212
 
@@ -1230,56 +1230,56 @@  discard block
 block discarded – undo
1230 1230
  * @return mixed|string
1231 1231
  */
1232 1232
 function compile_retour($code, $avant, $apres, $altern, $tab, $n) {
1233
-	if ($avant === "''") {
1234
-		$avant = '';
1235
-	}
1236
-	if ($apres === "''") {
1237
-		$apres = '';
1238
-	}
1239
-	if ($avant or $apres or ($altern !== "''")) {
1240
-		if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1241
-			$t = $code;
1242
-			$cond = '';
1243
-		} elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1244
-			$t = $r[2];
1245
-			$cond = '!' . $r[1];
1246
-		} else {
1247
-			if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1248
-				$t = $r[2];
1249
-				$cond = $r[1];
1250
-			} else {
1251
-				$t = '$t' . $n;
1252
-				$cond = "($t = $code)!==''";
1253
-			}
1254
-		}
1255
-
1256
-		$res = (!$avant ? '' : "$avant . ") .
1257
-			$t .
1258
-			(!$apres ? '' : " . $apres");
1259
-
1260
-		if ($res !== $t) {
1261
-			$res = "($res)";
1262
-		}
1263
-
1264
-		$code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1265
-	}
1266
-
1267
-	return $code;
1233
+    if ($avant === "''") {
1234
+        $avant = '';
1235
+    }
1236
+    if ($apres === "''") {
1237
+        $apres = '';
1238
+    }
1239
+    if ($avant or $apres or ($altern !== "''")) {
1240
+        if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1241
+            $t = $code;
1242
+            $cond = '';
1243
+        } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1244
+            $t = $r[2];
1245
+            $cond = '!' . $r[1];
1246
+        } else {
1247
+            if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1248
+                $t = $r[2];
1249
+                $cond = $r[1];
1250
+            } else {
1251
+                $t = '$t' . $n;
1252
+                $cond = "($t = $code)!==''";
1253
+            }
1254
+        }
1255
+
1256
+        $res = (!$avant ? '' : "$avant . ") .
1257
+            $t .
1258
+            (!$apres ? '' : " . $apres");
1259
+
1260
+        if ($res !== $t) {
1261
+            $res = "($res)";
1262
+        }
1263
+
1264
+        $code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1265
+    }
1266
+
1267
+    return $code;
1268 1268
 }
1269 1269
 
1270 1270
 
1271 1271
 function compile_inclure_doublons($lexemes) {
1272
-	foreach ($lexemes as $v) {
1273
-		if ($v->type === 'include' and $v->param) {
1274
-			foreach ($v->param as $r) {
1275
-				if (trim($r[0]) === 'doublons') {
1276
-					return true;
1277
-				}
1278
-			}
1279
-		}
1280
-	}
1281
-
1282
-	return false;
1272
+    foreach ($lexemes as $v) {
1273
+        if ($v->type === 'include' and $v->param) {
1274
+            foreach ($v->param as $r) {
1275
+                if (trim($r[0]) === 'doublons') {
1276
+                    return true;
1277
+                }
1278
+            }
1279
+        }
1280
+    }
1281
+
1282
+    return false;
1283 1283
 }
1284 1284
 
1285 1285
 // Prend en argument le texte d'un squelette, le nom de son fichier d'origine,
@@ -1298,354 +1298,354 @@  discard block
 block discarded – undo
1298 1298
 // En cas d'erreur, elle retournera un tableau des 2 premiers elements seulement
1299 1299
 
1300 1300
 function public_compiler_dist($squelette, $nom, $gram, $sourcefile, string $connect = '') {
1301
-	// Pre-traitement : reperer le charset du squelette, et le convertir
1302
-	// Bonus : supprime le BOM
1303
-	include_spip('inc/charsets');
1304
-	$squelette = transcoder_page($squelette);
1305
-
1306
-	// rendre inertes les echappements de #[](){}<>
1307
-	$i = 0;
1308
-	while (str_contains($squelette, $inerte = '-INERTE' . $i)) {
1309
-		$i++;
1310
-	}
1311
-	$squelette = preg_replace_callback(
1312
-		',\\\\([#[()\]{}<>]),',
1313
-		fn($a) => "$inerte-" . ord($a[1]) . '-',
1314
-		$squelette,
1315
-		-1,
1316
-		$esc
1317
-	);
1318
-
1319
-	$descr = [
1320
-		'nom' => $nom,
1321
-		'gram' => $gram,
1322
-		'sourcefile' => $sourcefile,
1323
-		'squelette' => $squelette
1324
-	];
1325
-
1326
-	// Phraser le squelette, selon sa grammaire
1327
-
1328
-	$boucles = [];
1329
-	$f = charger_fonction('phraser_' . $gram, 'public');
1330
-
1331
-	$squelette = $f($squelette, '', $boucles, $descr);
1332
-
1333
-	$boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1334
-
1335
-	// restituer les echappements
1336
-	if ($esc) {
1337
-		foreach ($boucles as $i => $boucle) {
1338
-			$boucles[$i]->return = preg_replace_callback(
1339
-				",$inerte-(\d+)-,",
1340
-				fn($a) => chr($a[1]),
1341
-				$boucle->return
1342
-			);
1343
-			$boucles[$i]->descr['squelette'] = preg_replace_callback(
1344
-				",$inerte-(\d+)-,",
1345
-				fn($a) => '\\\\' . chr($a[1]),
1346
-				$boucle->descr['squelette']
1347
-			);
1348
-		}
1349
-	}
1350
-
1351
-	$debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1352
-	if ($debug) {
1353
-		include_spip('public/decompiler');
1354
-		foreach ($boucles as $id => $boucle) {
1355
-			if ($id) {
1356
-				$decomp = "\n/* BOUCLE " .
1357
-					$boucle->type_requete .
1358
-					' ' .
1359
-					str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1360
-					($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1361
-					" */\n";
1362
-			} else {
1363
-				$decomp = ("\n/*\n" .
1364
-					str_replace('*/', '* /', public_decompiler($squelette, $gram))
1365
-					. "\n*/");
1366
-			}
1367
-			$boucles[$id]->return = $decomp . $boucle->return;
1368
-			$GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1369
-		}
1370
-	}
1371
-
1372
-	return $boucles;
1301
+    // Pre-traitement : reperer le charset du squelette, et le convertir
1302
+    // Bonus : supprime le BOM
1303
+    include_spip('inc/charsets');
1304
+    $squelette = transcoder_page($squelette);
1305
+
1306
+    // rendre inertes les echappements de #[](){}<>
1307
+    $i = 0;
1308
+    while (str_contains($squelette, $inerte = '-INERTE' . $i)) {
1309
+        $i++;
1310
+    }
1311
+    $squelette = preg_replace_callback(
1312
+        ',\\\\([#[()\]{}<>]),',
1313
+        fn($a) => "$inerte-" . ord($a[1]) . '-',
1314
+        $squelette,
1315
+        -1,
1316
+        $esc
1317
+    );
1318
+
1319
+    $descr = [
1320
+        'nom' => $nom,
1321
+        'gram' => $gram,
1322
+        'sourcefile' => $sourcefile,
1323
+        'squelette' => $squelette
1324
+    ];
1325
+
1326
+    // Phraser le squelette, selon sa grammaire
1327
+
1328
+    $boucles = [];
1329
+    $f = charger_fonction('phraser_' . $gram, 'public');
1330
+
1331
+    $squelette = $f($squelette, '', $boucles, $descr);
1332
+
1333
+    $boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1334
+
1335
+    // restituer les echappements
1336
+    if ($esc) {
1337
+        foreach ($boucles as $i => $boucle) {
1338
+            $boucles[$i]->return = preg_replace_callback(
1339
+                ",$inerte-(\d+)-,",
1340
+                fn($a) => chr($a[1]),
1341
+                $boucle->return
1342
+            );
1343
+            $boucles[$i]->descr['squelette'] = preg_replace_callback(
1344
+                ",$inerte-(\d+)-,",
1345
+                fn($a) => '\\\\' . chr($a[1]),
1346
+                $boucle->descr['squelette']
1347
+            );
1348
+        }
1349
+    }
1350
+
1351
+    $debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1352
+    if ($debug) {
1353
+        include_spip('public/decompiler');
1354
+        foreach ($boucles as $id => $boucle) {
1355
+            if ($id) {
1356
+                $decomp = "\n/* BOUCLE " .
1357
+                    $boucle->type_requete .
1358
+                    ' ' .
1359
+                    str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1360
+                    ($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1361
+                    " */\n";
1362
+            } else {
1363
+                $decomp = ("\n/*\n" .
1364
+                    str_replace('*/', '* /', public_decompiler($squelette, $gram))
1365
+                    . "\n*/");
1366
+            }
1367
+            $boucles[$id]->return = $decomp . $boucle->return;
1368
+            $GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1369
+        }
1370
+    }
1371
+
1372
+    return $boucles;
1373 1373
 }
1374 1374
 
1375 1375
 // Point d'entree pour arbre de syntaxe abstraite fourni en premier argument
1376 1376
 // Autres specifications comme ci-dessus
1377 1377
 
1378 1378
 function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, string $connect = '') {
1379
-	static $trouver_table;
1380
-	spip_timer('calcul_skel');
1381
-
1382
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1383
-		$GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1384
-		$GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1385
-
1386
-		if (!isset($GLOBALS['debug_objets']['principal'])) {
1387
-			$GLOBALS['debug_objets']['principal'] = $nom;
1388
-		}
1389
-	}
1390
-	foreach ($boucles as $id => $boucle) {
1391
-		$GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1392
-	}
1393
-	$descr['documents'] = compile_inclure_doublons($squelette);
1394
-
1395
-	// Demander la description des tables une fois pour toutes
1396
-	if (!$trouver_table) {
1397
-		$trouver_table = charger_fonction('trouver_table', 'base');
1398
-	}
1399
-
1400
-	// reperer si les doublons sont demandes
1401
-	// pour un inclure ou une boucle document
1402
-	// c'est utile a la fonction champs_traitements
1403
-	foreach ($boucles as $id => $boucle) {
1404
-		if (!($type = $boucle->type_requete)) {
1405
-			continue;
1406
-		}
1407
-		if (
1408
-			!$descr['documents'] and (
1409
-				(($type == 'documents') and $boucle->doublons) or
1410
-				compile_inclure_doublons($boucle->avant) or
1411
-				compile_inclure_doublons($boucle->apres) or
1412
-				compile_inclure_doublons($boucle->milieu) or
1413
-				compile_inclure_doublons($boucle->altern))
1414
-		) {
1415
-			$descr['documents'] = true;
1416
-		}
1417
-		if ($type != TYPE_RECURSIF) {
1418
-			if (!$boucles[$id]->sql_serveur and $connect) {
1419
-				$boucles[$id]->sql_serveur = $connect;
1420
-			}
1421
-
1422
-			// chercher dans les iterateurs du repertoire iterateur/
1423
-			if (
1424
-				$g = charger_fonction(
1425
-					preg_replace('/\W/', '_', $boucle->type_requete),
1426
-					'iterateur',
1427
-					true
1428
-				)
1429
-			) {
1430
-				$boucles[$id] = $g($boucle);
1431
-
1432
-				// sinon, en cas de requeteur d'un type predefini,
1433
-				// utiliser les informations donnees par le requeteur
1434
-				// cas "php:xx" et "data:xx".
1435
-			} else {
1436
-				if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1437
-					$requeteur($boucles, $boucle, $id);
1438
-
1439
-					// utiliser la description des champs transmis
1440
-				} else {
1441
-					$show = $trouver_table($type, $boucles[$id]->sql_serveur);
1442
-					// si la table n'existe pas avec le connecteur par defaut,
1443
-					// c'est peut etre une table qui necessite son connecteur dedie fourni
1444
-					// permet une ecriture allegee (GEO) -> (geo:GEO)
1445
-					if (
1446
-						!$show
1447
-						and $show = $trouver_table($type, strtolower($type))
1448
-					) {
1449
-						$boucles[$id]->sql_serveur = strtolower($type);
1450
-					}
1451
-					if ($show) {
1452
-						$boucles[$id]->show = $show;
1453
-						// recopie les infos les plus importantes
1454
-						$boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1455
-						$boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1456
-						$boucles[$id]->from[$x] = $nom_table = $show['table'];
1457
-						$boucles[$id]->iterateur = 'SQL';
1458
-
1459
-						if (empty($boucles[$id]->descr)) {
1460
-							$boucles[$id]->descr = &$descr;
1461
-						}
1462
-						if (
1463
-							(!$boucles[$id]->jointures)
1464
-							and is_array($show['tables_jointures'])
1465
-							and count($x = $show['tables_jointures'])
1466
-						) {
1467
-							$boucles[$id]->jointures = $x;
1468
-						}
1469
-						if ($boucles[$id]->jointures_explicites) {
1470
-							$jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1471
-							while ($j = array_pop($jointures)) {
1472
-								array_unshift($boucles[$id]->jointures, $j);
1473
-							}
1474
-						}
1475
-					} else {
1476
-						// Pas une erreur si la table est optionnelle
1477
-						if ($boucles[$id]->table_optionnelle) {
1478
-							$boucles[$id]->type_requete = '';
1479
-						} else {
1480
-							$boucles[$id]->type_requete = false;
1481
-							$boucle = $boucles[$id];
1482
-							$x = (!$boucle->sql_serveur ? '' :
1483
-									($boucle->sql_serveur . ':')) .
1484
-								$type;
1485
-							$msg = [
1486
-								'zbug_table_inconnue',
1487
-								['table' => $x]
1488
-							];
1489
-							erreur_squelette($msg, $boucle);
1490
-						}
1491
-					}
1492
-				}
1493
-			}
1494
-		}
1495
-	}
1496
-
1497
-	// Commencer par reperer les boucles appelees explicitement
1498
-	// car elles indexent les arguments de maniere derogatoire
1499
-	foreach ($boucles as $id => $boucle) {
1500
-		if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1501
-			$boucles[$id]->descr = &$descr;
1502
-			$rec = &$boucles[$boucle->param[0]];
1503
-			if (!$rec) {
1504
-				$msg = [
1505
-					'zbug_boucle_recursive_undef',
1506
-					['nom' => $boucle->param[0]]
1507
-				];
1508
-				erreur_squelette($msg, $boucle);
1509
-				$boucles[$id]->type_requete = false;
1510
-			} else {
1511
-				$rec->externe = $id;
1512
-				$descr['id_mere'] = $id;
1513
-				$boucles[$id]->return =
1514
-					calculer_liste(
1515
-						[$rec],
1516
-						$descr,
1517
-						$boucles,
1518
-						$boucle->param
1519
-					);
1520
-			}
1521
-		}
1522
-	}
1523
-	foreach ($boucles as $id => $boucle) {
1524
-		$id = strval($id); // attention au type dans index_pile
1525
-		$type = $boucle->type_requete;
1526
-		if ($type and $type != TYPE_RECURSIF) {
1527
-			$res = '';
1528
-			if ($boucle->param) {
1529
-				// retourne un tableau en cas d'erreur
1530
-				$res = calculer_criteres($id, $boucles);
1531
-			}
1532
-			$descr['id_mere'] = $id;
1533
-			$boucles[$id]->return =
1534
-				calculer_liste(
1535
-					$boucle->milieu,
1536
-					$descr,
1537
-					$boucles,
1538
-					$id
1539
-				);
1540
-			// Si les criteres se sont mal compiles
1541
-			// ne pas tenter d'assembler le code final
1542
-			// (mais compiler le corps pour detection d'erreurs)
1543
-			if (is_array($res)) {
1544
-				$boucles[$id]->type_requete = false;
1545
-			}
1546
-		}
1547
-	}
1548
-
1549
-	// idem pour la racine
1550
-	$descr['id_mere'] = '';
1551
-	$corps = calculer_liste($squelette, $descr, $boucles);
1552
-
1553
-
1554
-	// Calcul du corps de toutes les fonctions PHP,
1555
-	// en particulier les requetes SQL et TOTAL_BOUCLE
1556
-	// de'terminables seulement maintenant
1557
-
1558
-	foreach ($boucles as $id => $boucle) {
1559
-		$boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1560
-		if ($boucle->return === false) {
1561
-			$corps = false;
1562
-			continue;
1563
-		}
1564
-		// appeler la fonction de definition de la boucle
1565
-
1566
-		if ($req = $boucle->type_requete) {
1567
-			// boucle personnalisée ?
1568
-			$table = strtoupper($boucle->type_requete);
1569
-			$serveur = strtolower($boucle->sql_serveur);
1570
-			if (
1571
-				// fonction de boucle avec serveur & table
1572
-				(!$serveur or
1573
-					((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1574
-						and (!function_exists($f = $f . '_dist'))
1575
-					)
1576
-				)
1577
-				// fonction de boucle avec table
1578
-				and (!function_exists($f = 'boucle_' . $table))
1579
-				and (!function_exists($f = $f . '_dist'))
1580
-			) {
1581
-				// fonction de boucle standard
1582
-				if (!function_exists($f = 'boucle_DEFAUT')) {
1583
-					$f = 'boucle_DEFAUT_dist';
1584
-				}
1585
-			}
1586
-
1587
-			$req = "\n\n\tstatic \$command = array();\n\t" .
1588
-				"static \$connect;\n\t" .
1589
-				"\$command['connect'] = \$connect = " .
1590
-				_q($boucle->sql_serveur) .
1591
-				';' .
1592
-				$f($id, $boucles);
1593
-		} else {
1594
-			$req = ("\n\treturn '';");
1595
-		}
1596
-
1597
-		$boucles[$id]->return =
1598
-			"\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1599
-			'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1600
-			$req .
1601
-			"\n}\n";
1602
-	}
1603
-
1604
-	// Au final, si le corps ou un critere au moins s'est mal compile
1605
-	// retourner False, sinon inserer leur decompilation
1606
-	if (is_bool($corps)) {
1607
-		return false;
1608
-	}
1609
-
1610
-	$principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1379
+    static $trouver_table;
1380
+    spip_timer('calcul_skel');
1381
+
1382
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1383
+        $GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1384
+        $GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1385
+
1386
+        if (!isset($GLOBALS['debug_objets']['principal'])) {
1387
+            $GLOBALS['debug_objets']['principal'] = $nom;
1388
+        }
1389
+    }
1390
+    foreach ($boucles as $id => $boucle) {
1391
+        $GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1392
+    }
1393
+    $descr['documents'] = compile_inclure_doublons($squelette);
1394
+
1395
+    // Demander la description des tables une fois pour toutes
1396
+    if (!$trouver_table) {
1397
+        $trouver_table = charger_fonction('trouver_table', 'base');
1398
+    }
1399
+
1400
+    // reperer si les doublons sont demandes
1401
+    // pour un inclure ou une boucle document
1402
+    // c'est utile a la fonction champs_traitements
1403
+    foreach ($boucles as $id => $boucle) {
1404
+        if (!($type = $boucle->type_requete)) {
1405
+            continue;
1406
+        }
1407
+        if (
1408
+            !$descr['documents'] and (
1409
+                (($type == 'documents') and $boucle->doublons) or
1410
+                compile_inclure_doublons($boucle->avant) or
1411
+                compile_inclure_doublons($boucle->apres) or
1412
+                compile_inclure_doublons($boucle->milieu) or
1413
+                compile_inclure_doublons($boucle->altern))
1414
+        ) {
1415
+            $descr['documents'] = true;
1416
+        }
1417
+        if ($type != TYPE_RECURSIF) {
1418
+            if (!$boucles[$id]->sql_serveur and $connect) {
1419
+                $boucles[$id]->sql_serveur = $connect;
1420
+            }
1421
+
1422
+            // chercher dans les iterateurs du repertoire iterateur/
1423
+            if (
1424
+                $g = charger_fonction(
1425
+                    preg_replace('/\W/', '_', $boucle->type_requete),
1426
+                    'iterateur',
1427
+                    true
1428
+                )
1429
+            ) {
1430
+                $boucles[$id] = $g($boucle);
1431
+
1432
+                // sinon, en cas de requeteur d'un type predefini,
1433
+                // utiliser les informations donnees par le requeteur
1434
+                // cas "php:xx" et "data:xx".
1435
+            } else {
1436
+                if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1437
+                    $requeteur($boucles, $boucle, $id);
1438
+
1439
+                    // utiliser la description des champs transmis
1440
+                } else {
1441
+                    $show = $trouver_table($type, $boucles[$id]->sql_serveur);
1442
+                    // si la table n'existe pas avec le connecteur par defaut,
1443
+                    // c'est peut etre une table qui necessite son connecteur dedie fourni
1444
+                    // permet une ecriture allegee (GEO) -> (geo:GEO)
1445
+                    if (
1446
+                        !$show
1447
+                        and $show = $trouver_table($type, strtolower($type))
1448
+                    ) {
1449
+                        $boucles[$id]->sql_serveur = strtolower($type);
1450
+                    }
1451
+                    if ($show) {
1452
+                        $boucles[$id]->show = $show;
1453
+                        // recopie les infos les plus importantes
1454
+                        $boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1455
+                        $boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1456
+                        $boucles[$id]->from[$x] = $nom_table = $show['table'];
1457
+                        $boucles[$id]->iterateur = 'SQL';
1458
+
1459
+                        if (empty($boucles[$id]->descr)) {
1460
+                            $boucles[$id]->descr = &$descr;
1461
+                        }
1462
+                        if (
1463
+                            (!$boucles[$id]->jointures)
1464
+                            and is_array($show['tables_jointures'])
1465
+                            and count($x = $show['tables_jointures'])
1466
+                        ) {
1467
+                            $boucles[$id]->jointures = $x;
1468
+                        }
1469
+                        if ($boucles[$id]->jointures_explicites) {
1470
+                            $jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1471
+                            while ($j = array_pop($jointures)) {
1472
+                                array_unshift($boucles[$id]->jointures, $j);
1473
+                            }
1474
+                        }
1475
+                    } else {
1476
+                        // Pas une erreur si la table est optionnelle
1477
+                        if ($boucles[$id]->table_optionnelle) {
1478
+                            $boucles[$id]->type_requete = '';
1479
+                        } else {
1480
+                            $boucles[$id]->type_requete = false;
1481
+                            $boucle = $boucles[$id];
1482
+                            $x = (!$boucle->sql_serveur ? '' :
1483
+                                    ($boucle->sql_serveur . ':')) .
1484
+                                $type;
1485
+                            $msg = [
1486
+                                'zbug_table_inconnue',
1487
+                                ['table' => $x]
1488
+                            ];
1489
+                            erreur_squelette($msg, $boucle);
1490
+                        }
1491
+                    }
1492
+                }
1493
+            }
1494
+        }
1495
+    }
1496
+
1497
+    // Commencer par reperer les boucles appelees explicitement
1498
+    // car elles indexent les arguments de maniere derogatoire
1499
+    foreach ($boucles as $id => $boucle) {
1500
+        if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1501
+            $boucles[$id]->descr = &$descr;
1502
+            $rec = &$boucles[$boucle->param[0]];
1503
+            if (!$rec) {
1504
+                $msg = [
1505
+                    'zbug_boucle_recursive_undef',
1506
+                    ['nom' => $boucle->param[0]]
1507
+                ];
1508
+                erreur_squelette($msg, $boucle);
1509
+                $boucles[$id]->type_requete = false;
1510
+            } else {
1511
+                $rec->externe = $id;
1512
+                $descr['id_mere'] = $id;
1513
+                $boucles[$id]->return =
1514
+                    calculer_liste(
1515
+                        [$rec],
1516
+                        $descr,
1517
+                        $boucles,
1518
+                        $boucle->param
1519
+                    );
1520
+            }
1521
+        }
1522
+    }
1523
+    foreach ($boucles as $id => $boucle) {
1524
+        $id = strval($id); // attention au type dans index_pile
1525
+        $type = $boucle->type_requete;
1526
+        if ($type and $type != TYPE_RECURSIF) {
1527
+            $res = '';
1528
+            if ($boucle->param) {
1529
+                // retourne un tableau en cas d'erreur
1530
+                $res = calculer_criteres($id, $boucles);
1531
+            }
1532
+            $descr['id_mere'] = $id;
1533
+            $boucles[$id]->return =
1534
+                calculer_liste(
1535
+                    $boucle->milieu,
1536
+                    $descr,
1537
+                    $boucles,
1538
+                    $id
1539
+                );
1540
+            // Si les criteres se sont mal compiles
1541
+            // ne pas tenter d'assembler le code final
1542
+            // (mais compiler le corps pour detection d'erreurs)
1543
+            if (is_array($res)) {
1544
+                $boucles[$id]->type_requete = false;
1545
+            }
1546
+        }
1547
+    }
1548
+
1549
+    // idem pour la racine
1550
+    $descr['id_mere'] = '';
1551
+    $corps = calculer_liste($squelette, $descr, $boucles);
1552
+
1553
+
1554
+    // Calcul du corps de toutes les fonctions PHP,
1555
+    // en particulier les requetes SQL et TOTAL_BOUCLE
1556
+    // de'terminables seulement maintenant
1557
+
1558
+    foreach ($boucles as $id => $boucle) {
1559
+        $boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1560
+        if ($boucle->return === false) {
1561
+            $corps = false;
1562
+            continue;
1563
+        }
1564
+        // appeler la fonction de definition de la boucle
1565
+
1566
+        if ($req = $boucle->type_requete) {
1567
+            // boucle personnalisée ?
1568
+            $table = strtoupper($boucle->type_requete);
1569
+            $serveur = strtolower($boucle->sql_serveur);
1570
+            if (
1571
+                // fonction de boucle avec serveur & table
1572
+                (!$serveur or
1573
+                    ((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1574
+                        and (!function_exists($f = $f . '_dist'))
1575
+                    )
1576
+                )
1577
+                // fonction de boucle avec table
1578
+                and (!function_exists($f = 'boucle_' . $table))
1579
+                and (!function_exists($f = $f . '_dist'))
1580
+            ) {
1581
+                // fonction de boucle standard
1582
+                if (!function_exists($f = 'boucle_DEFAUT')) {
1583
+                    $f = 'boucle_DEFAUT_dist';
1584
+                }
1585
+            }
1586
+
1587
+            $req = "\n\n\tstatic \$command = array();\n\t" .
1588
+                "static \$connect;\n\t" .
1589
+                "\$command['connect'] = \$connect = " .
1590
+                _q($boucle->sql_serveur) .
1591
+                ';' .
1592
+                $f($id, $boucles);
1593
+        } else {
1594
+            $req = ("\n\treturn '';");
1595
+        }
1596
+
1597
+        $boucles[$id]->return =
1598
+            "\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1599
+            '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1600
+            $req .
1601
+            "\n}\n";
1602
+    }
1603
+
1604
+    // Au final, si le corps ou un critere au moins s'est mal compile
1605
+    // retourner False, sinon inserer leur decompilation
1606
+    if (is_bool($corps)) {
1607
+        return false;
1608
+    }
1609
+
1610
+    $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1611 1611
 '
1612
-		// reporter de maniere securisee les doublons inclus
1613
-		. '
1612
+        // reporter de maniere securisee les doublons inclus
1613
+        . '
1614 1614
 	if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"]))
1615 1615
 		$doublons = nettoyer_env_doublons($Pile[0]["doublons"]);
1616 1616
 
1617 1617
 	$connect = ' .
1618
-		_q($connect) . ';
1618
+        _q($connect) . ';
1619 1619
 	$page = ' .
1620
-		// ATTENTION, le calcul de l'expression $corps affectera $Cache
1621
-		// c'est pourquoi on l'affecte a la variable auxiliaire $page.
1622
-		// avant de referencer $Cache
1623
-		$corps . ';
1620
+        // ATTENTION, le calcul de l'expression $corps affectera $Cache
1621
+        // c'est pourquoi on l'affecte a la variable auxiliaire $page.
1622
+        // avant de referencer $Cache
1623
+        $corps . ';
1624 1624
 
1625 1625
 	return analyse_resultat_skel(' . var_export($nom, true)
1626
-		. ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1626
+        . ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1627 1627
 }';
1628 1628
 
1629
-	$secondes = spip_timer('calcul_skel');
1630
-	spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1631
-	// $connect n'est pas sûr : on nettoie
1632
-	$connect = preg_replace(',[^\w],', '', $connect);
1629
+    $secondes = spip_timer('calcul_skel');
1630
+    spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1631
+    // $connect n'est pas sûr : on nettoie
1632
+    $connect = preg_replace(',[^\w],', '', $connect);
1633 1633
 
1634
-	// Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1635
-	$code = new Boucle();
1636
-	$code->descr = $descr;
1637
-	$code->return = '
1634
+    // Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1635
+    $code = new Boucle();
1636
+    $code->descr = $descr;
1637
+    $code->return = '
1638 1638
 //
1639 1639
 // Fonction principale du squelette ' .
1640
-		$sourcefile .
1641
-		($connect ? " pour $connect" : '') .
1642
-		(!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1643
-		"\n//\n" .
1644
-		$principal;
1640
+        $sourcefile .
1641
+        ($connect ? " pour $connect" : '') .
1642
+        (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1643
+        "\n//\n" .
1644
+        $principal;
1645 1645
 
1646
-	$boucles[''] = $code;
1646
+    $boucles[''] = $code;
1647 1647
 
1648
-	return $boucles;
1648
+    return $boucles;
1649 1649
 }
1650 1650
 
1651 1651
 
@@ -1662,18 +1662,18 @@  discard block
 block discarded – undo
1662 1662
  *
1663 1663
  **/
1664 1664
 function requeteur_php_dist(&$boucles, &$boucle, &$id) {
1665
-	if (class_exists($boucle->type_requete)) {
1666
-		$g = charger_fonction('php', 'iterateur');
1667
-		$boucles[$id] = $g($boucle, $boucle->type_requete);
1668
-	} else {
1669
-		$x = $boucle->type_requete;
1670
-		$boucle->type_requete = false;
1671
-		$msg = [
1672
-			'zbug_iterateur_inconnu',
1673
-			['iterateur' => $x]
1674
-		];
1675
-		erreur_squelette($msg, $boucle);
1676
-	}
1665
+    if (class_exists($boucle->type_requete)) {
1666
+        $g = charger_fonction('php', 'iterateur');
1667
+        $boucles[$id] = $g($boucle, $boucle->type_requete);
1668
+    } else {
1669
+        $x = $boucle->type_requete;
1670
+        $boucle->type_requete = false;
1671
+        $msg = [
1672
+            'zbug_iterateur_inconnu',
1673
+            ['iterateur' => $x]
1674
+        ];
1675
+        erreur_squelette($msg, $boucle);
1676
+    }
1677 1677
 }
1678 1678
 
1679 1679
 
@@ -1691,22 +1691,22 @@  discard block
 block discarded – undo
1691 1691
  *
1692 1692
  **/
1693 1693
 function requeteur_data_dist(&$boucles, &$boucle, &$id) {
1694
-	include_spip('iterateur/data');
1695
-	if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1696
-		$g = charger_fonction('data', 'iterateur');
1697
-		$boucles[$id] = $g($boucle);
1698
-		// from[0] stocke le type de data (rss, yql, ...)
1699
-		$boucles[$id]->from[] = $boucle->type_requete;
1700
-	} else {
1701
-		$x = $boucle->type_requete;
1702
-		$boucle->type_requete = false;
1703
-		$msg = [
1704
-			'zbug_requeteur_inconnu',
1705
-			[
1706
-				'requeteur' => 'data',
1707
-				'type' => $x
1708
-			]
1709
-		];
1710
-		erreur_squelette($msg, $boucle);
1711
-	}
1694
+    include_spip('iterateur/data');
1695
+    if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1696
+        $g = charger_fonction('data', 'iterateur');
1697
+        $boucles[$id] = $g($boucle);
1698
+        // from[0] stocke le type de data (rss, yql, ...)
1699
+        $boucles[$id]->from[] = $boucle->type_requete;
1700
+    } else {
1701
+        $x = $boucle->type_requete;
1702
+        $boucle->type_requete = false;
1703
+        $msg = [
1704
+            'zbug_requeteur_inconnu',
1705
+            [
1706
+                'requeteur' => 'data',
1707
+                'type' => $x
1708
+            ]
1709
+        ];
1710
+        erreur_squelette($msg, $boucle);
1711
+    }
1712 1712
 }
Please login to merge, or discard this patch.
ecrire/public/references.php 1 patch
Indentation   +561 added lines, -561 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
  * @package SPIP\Core\Compilateur\References
20 20
  **/
21 21
 if (!defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 /**
@@ -44,14 +44,14 @@  discard block
 block discarded – undo
44 44
  *     - '' si une référence explicite incorrecte est envoyée
45 45
  */
46 46
 function index_boucle($p) {
47
-	if (strlen($p->nom_boucle)) {
48
-		// retourne l’index explicite demandé s’il existe
49
-		if (!empty($p->boucles[$p->nom_boucle])) {
50
-			return $p->nom_boucle;
51
-		}
52
-		return '';
53
-	}
54
-	return $p->id_boucle;
47
+    if (strlen($p->nom_boucle)) {
48
+        // retourne l’index explicite demandé s’il existe
49
+        if (!empty($p->boucles[$p->nom_boucle])) {
50
+            return $p->nom_boucle;
51
+        }
52
+        return '';
53
+    }
54
+    return $p->id_boucle;
55 55
 }
56 56
 
57 57
 
@@ -74,17 +74,17 @@  discard block
 block discarded – undo
74 74
  *     - '' si une référence explicite incorrecte est envoyée
75 75
  */
76 76
 function index_boucle_mere($p) {
77
-	if (strlen($p->nom_boucle)) {
78
-		// retourne l’index explicite demandé s’il existe
79
-		if (!empty($p->boucles[$p->nom_boucle])) {
80
-			return $p->nom_boucle;
81
-		}
82
-		return '';
83
-	}
84
-	if (!empty($p->descr['id_mere'])) {
85
-		return $p->descr['id_mere'];
86
-	}
87
-	return '';
77
+    if (strlen($p->nom_boucle)) {
78
+        // retourne l’index explicite demandé s’il existe
79
+        if (!empty($p->boucles[$p->nom_boucle])) {
80
+            return $p->nom_boucle;
81
+        }
82
+        return '';
83
+    }
84
+    if (!empty($p->descr['id_mere'])) {
85
+        return $p->descr['id_mere'];
86
+    }
87
+    return '';
88 88
 }
89 89
 
90 90
 /**
@@ -118,74 +118,74 @@  discard block
 block discarded – undo
118 118
  *     Code PHP pour obtenir le champ SQL
119 119
  */
120 120
 function index_pile(
121
-	$idb,
122
-	$nom_champ,
123
-	&$boucles,
124
-	$explicite = '',
125
-	$defaut = null,
126
-	$remonte_pile = true,
127
-	$select = true
121
+    $idb,
122
+    $nom_champ,
123
+    &$boucles,
124
+    $explicite = '',
125
+    $defaut = null,
126
+    $remonte_pile = true,
127
+    $select = true
128 128
 ) {
129
-	if (!is_string($defaut)) {
130
-		$defaut = '($Pile[0][\'' . strtolower($nom_champ) . '\'] ?? null)';
131
-	}
132
-
133
-	$idb_origine = $idb;
134
-	$nom_champ_origine = $nom_champ;
135
-
136
-	$i = 0;
137
-	if (strlen($explicite)) {
138
-		// Recherche d'un champ dans un etage superieur
139
-		while (($idb !== $explicite) && ($idb !== '')) {
140
-			#	spip_log("Cherchexpl: $nom_champ '$explicite' '$idb' '$i'");
141
-			$i++;
142
-			$idb = $boucles[$idb]->id_parent;
143
-		}
144
-	}
145
-
146
-	#	spip_log("Cherche: $nom_champ a partir de '$idb'");
147
-	$nom_champ = strtolower($nom_champ);
148
-	$conditionnel = [];
149
-	// attention: entre la boucle nommee 0, "" et le tableau vide,
150
-	// il y a incoherences qu'il vaut mieux eviter
151
-	while (isset($boucles[$idb])) {
152
-		$joker = true;
153
-		// modifie $joker si tous les champs sont autorisés.
154
-		// $t = le select pour le champ, si on l'a trouvé (ou si joker)
155
-		// $c = le nom du champ demandé
156
-		[$t, $c] = index_tables_en_pile($idb, $nom_champ, $boucles, $joker);
157
-		if ($t) {
158
-			if ($select and !in_array($t, $boucles[$idb]->select)) {
159
-				$boucles[$idb]->select[] = $t;
160
-			}
161
-			// renseigner la boucle source de ce champ pour les traitements
162
-			$boucles[$idb_origine]->index_champ[$nom_champ_origine] = $idb;
163
-			$champ = '$Pile[$SP' . ($i ? "-$i" : '') . '][\'' . $c . '\']';
164
-			if (!$joker) {
165
-				return index_compose($conditionnel, $champ);
166
-			}
167
-
168
-			// tant que l'on trouve des tables avec joker, on continue
169
-			// avec la boucle parente et on conditionne à l'exécution
170
-			// la présence du champ. Si le champ existe à l'exécution
171
-			// dans une boucle, il est pris, sinon on le cherche dans le parent...
172
-			$conditionnel[] = "isset($champ)?$champ";
173
-		}
174
-
175
-		if ($remonte_pile) {
176
-			#	spip_log("On remonte vers $i");
177
-			// Sinon on remonte d'un cran
178
-			$idb = $boucles[$idb]->id_parent;
179
-			$i++;
180
-		} else {
181
-			$idb = null;
182
-		}
183
-	}
184
-
185
-	#	spip_log("Pas vu $nom_champ");
186
-	// esperons qu'il y sera
187
-	// ou qu'on a fourni une valeur par "defaut" plus pertinent
188
-	return index_compose($conditionnel, $defaut);
129
+    if (!is_string($defaut)) {
130
+        $defaut = '($Pile[0][\'' . strtolower($nom_champ) . '\'] ?? null)';
131
+    }
132
+
133
+    $idb_origine = $idb;
134
+    $nom_champ_origine = $nom_champ;
135
+
136
+    $i = 0;
137
+    if (strlen($explicite)) {
138
+        // Recherche d'un champ dans un etage superieur
139
+        while (($idb !== $explicite) && ($idb !== '')) {
140
+            #	spip_log("Cherchexpl: $nom_champ '$explicite' '$idb' '$i'");
141
+            $i++;
142
+            $idb = $boucles[$idb]->id_parent;
143
+        }
144
+    }
145
+
146
+    #	spip_log("Cherche: $nom_champ a partir de '$idb'");
147
+    $nom_champ = strtolower($nom_champ);
148
+    $conditionnel = [];
149
+    // attention: entre la boucle nommee 0, "" et le tableau vide,
150
+    // il y a incoherences qu'il vaut mieux eviter
151
+    while (isset($boucles[$idb])) {
152
+        $joker = true;
153
+        // modifie $joker si tous les champs sont autorisés.
154
+        // $t = le select pour le champ, si on l'a trouvé (ou si joker)
155
+        // $c = le nom du champ demandé
156
+        [$t, $c] = index_tables_en_pile($idb, $nom_champ, $boucles, $joker);
157
+        if ($t) {
158
+            if ($select and !in_array($t, $boucles[$idb]->select)) {
159
+                $boucles[$idb]->select[] = $t;
160
+            }
161
+            // renseigner la boucle source de ce champ pour les traitements
162
+            $boucles[$idb_origine]->index_champ[$nom_champ_origine] = $idb;
163
+            $champ = '$Pile[$SP' . ($i ? "-$i" : '') . '][\'' . $c . '\']';
164
+            if (!$joker) {
165
+                return index_compose($conditionnel, $champ);
166
+            }
167
+
168
+            // tant que l'on trouve des tables avec joker, on continue
169
+            // avec la boucle parente et on conditionne à l'exécution
170
+            // la présence du champ. Si le champ existe à l'exécution
171
+            // dans une boucle, il est pris, sinon on le cherche dans le parent...
172
+            $conditionnel[] = "isset($champ)?$champ";
173
+        }
174
+
175
+        if ($remonte_pile) {
176
+            #	spip_log("On remonte vers $i");
177
+            // Sinon on remonte d'un cran
178
+            $idb = $boucles[$idb]->id_parent;
179
+            $i++;
180
+        } else {
181
+            $idb = null;
182
+        }
183
+    }
184
+
185
+    #	spip_log("Pas vu $nom_champ");
186
+    // esperons qu'il y sera
187
+    // ou qu'on a fourni une valeur par "defaut" plus pertinent
188
+    return index_compose($conditionnel, $defaut);
189 189
 }
190 190
 
191 191
 /**
@@ -199,12 +199,12 @@  discard block
 block discarded – undo
199 199
  * @return string              Code PHP complet de recherche d'un champ
200 200
  */
201 201
 function index_compose($conditionnel, $defaut) {
202
-	while ($c = array_pop($conditionnel)) {
203
-		// si on passe defaut = '', ne pas générer d'erreur de compilation.
204
-		$defaut = "($c:(" . ($defaut ?: "''") . '))';
205
-	}
202
+    while ($c = array_pop($conditionnel)) {
203
+        // si on passe defaut = '', ne pas générer d'erreur de compilation.
204
+        $defaut = "($c:(" . ($defaut ?: "''") . '))';
205
+    }
206 206
 
207
-	return $defaut;
207
+    return $defaut;
208 208
 }
209 209
 
210 210
 /**
@@ -240,97 +240,97 @@  discard block
 block discarded – undo
240 240
  **/
241 241
 function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) {
242 242
 
243
-	$r = $boucles[$idb]->type_requete;
244
-	// boucle recursive, c'est foutu...
245
-	if ($r == TYPE_RECURSIF) {
246
-		return [];
247
-	}
248
-	if (!$r) {
249
-		$joker = false; // indiquer a l'appelant
250
-		# continuer pour chercher l'erreur suivante
251
-		return ["'#" . $r . ':' . $nom_champ . "'", ''];
252
-	}
253
-
254
-	$desc = $boucles[$idb]->show;
255
-	// le nom du champ est il une exception de la table ? un alias ?
256
-	$excep = $GLOBALS['exceptions_des_tables'][$r] ?? '';
257
-	if ($excep) {
258
-		$excep = $excep[$nom_champ] ?? '';
259
-	}
260
-
261
-	// il y a un alias connu pour ce champ
262
-	if ($excep) {
263
-		$joker = false; // indiquer a l'appelant
264
-		return index_exception($boucles[$idb], $desc, $nom_champ, $excep);
265
-	}
266
-
267
-	// le champ existe dans la table, on le prend.
268
-	if (isset($desc['field'][$nom_champ])) {
269
-		$t = $boucles[$idb]->id_table ?? '';
270
-		$joker = false; // indiquer a l'appelant
271
-		// note: dans certains cas ('valeur' d’une boucle DATA, sans id_table), retourne ['.valeur', 'valeur'] …
272
-		return ["$t.$nom_champ", $nom_champ];
273
-	}
274
-
275
-	// Tous les champs sont-ils acceptés ?
276
-	// Si oui, on retourne le champ, et on lève le flag joker
277
-	// C'est le cas des itérateurs DATA qui acceptent tout
278
-	// et testent la présence du champ à l'exécution et non à la compilation
279
-	// car ils ne connaissent pas ici leurs contenus.
280
-	if (
281
-		/*$joker AND */
282
-		isset($desc['field']['*'])
283
-	) {
284
-		$joker = true; // indiquer a l'appelant
285
-		return [$nom_champ, $nom_champ];
286
-	}
287
-
288
-	$joker = false; // indiquer a l'appelant
289
-
290
-	// la table de jointure est explicitement indiquée (rubrique.titre)
291
-	if (preg_match('/^(.*)\.(.*)$/', $nom_champ, $r)) {
292
-		[, $_table, $_nom_champ] = $r;
293
-		if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) {
294
-			$_alias = $cle . '_' . $_nom_champ;
295
-			return index_exception(
296
-				$boucles[$idb],
297
-				$desc,
298
-				$_alias,
299
-				[$_table, $_nom_champ]
300
-			);
301
-		}
302
-		return ['', ''];
303
-	}
304
-
305
-	// pas d'alias, pas de champ, pas de joker...
306
-	// tenter via une jointure...
307
-
308
-	// regarder si le champ est deja dans une jointure existante
309
-	// sinon, si il y a des joitures explicites, la construire
310
-	if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) {
311
-		if ($boucles[$idb]->jointures_explicites) {
312
-			// [todo] Ne pas lancer que lorsque il y a des jointures explicites !!!!
313
-			// fonctionnel, il suffit d'utiliser $boucles[$idb]->jointures au lieu de jointures_explicites
314
-			// mais est-ce ce qu'on veut ?
315
-			$jointures = preg_split('/\s+/', $boucles[$idb]->jointures_explicites);
316
-			if ($cle = trouver_jointure_champ($nom_champ, $boucles[$idb], $jointures)) {
317
-				$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb]);
318
-			}
319
-		}
320
-	}
321
-
322
-	if ($t) {
323
-		// si on a trouvé une jointure possible, on fait comme
324
-		// si c'était une exception pour le champ demandé
325
-		return index_exception(
326
-			$boucles[$idb],
327
-			$desc,
328
-			$nom_champ,
329
-			[$t[1]['id_table'], reset($t[2])]
330
-		);
331
-	}
332
-
333
-	return ['', ''];
243
+    $r = $boucles[$idb]->type_requete;
244
+    // boucle recursive, c'est foutu...
245
+    if ($r == TYPE_RECURSIF) {
246
+        return [];
247
+    }
248
+    if (!$r) {
249
+        $joker = false; // indiquer a l'appelant
250
+        # continuer pour chercher l'erreur suivante
251
+        return ["'#" . $r . ':' . $nom_champ . "'", ''];
252
+    }
253
+
254
+    $desc = $boucles[$idb]->show;
255
+    // le nom du champ est il une exception de la table ? un alias ?
256
+    $excep = $GLOBALS['exceptions_des_tables'][$r] ?? '';
257
+    if ($excep) {
258
+        $excep = $excep[$nom_champ] ?? '';
259
+    }
260
+
261
+    // il y a un alias connu pour ce champ
262
+    if ($excep) {
263
+        $joker = false; // indiquer a l'appelant
264
+        return index_exception($boucles[$idb], $desc, $nom_champ, $excep);
265
+    }
266
+
267
+    // le champ existe dans la table, on le prend.
268
+    if (isset($desc['field'][$nom_champ])) {
269
+        $t = $boucles[$idb]->id_table ?? '';
270
+        $joker = false; // indiquer a l'appelant
271
+        // note: dans certains cas ('valeur' d’une boucle DATA, sans id_table), retourne ['.valeur', 'valeur'] …
272
+        return ["$t.$nom_champ", $nom_champ];
273
+    }
274
+
275
+    // Tous les champs sont-ils acceptés ?
276
+    // Si oui, on retourne le champ, et on lève le flag joker
277
+    // C'est le cas des itérateurs DATA qui acceptent tout
278
+    // et testent la présence du champ à l'exécution et non à la compilation
279
+    // car ils ne connaissent pas ici leurs contenus.
280
+    if (
281
+        /*$joker AND */
282
+        isset($desc['field']['*'])
283
+    ) {
284
+        $joker = true; // indiquer a l'appelant
285
+        return [$nom_champ, $nom_champ];
286
+    }
287
+
288
+    $joker = false; // indiquer a l'appelant
289
+
290
+    // la table de jointure est explicitement indiquée (rubrique.titre)
291
+    if (preg_match('/^(.*)\.(.*)$/', $nom_champ, $r)) {
292
+        [, $_table, $_nom_champ] = $r;
293
+        if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) {
294
+            $_alias = $cle . '_' . $_nom_champ;
295
+            return index_exception(
296
+                $boucles[$idb],
297
+                $desc,
298
+                $_alias,
299
+                [$_table, $_nom_champ]
300
+            );
301
+        }
302
+        return ['', ''];
303
+    }
304
+
305
+    // pas d'alias, pas de champ, pas de joker...
306
+    // tenter via une jointure...
307
+
308
+    // regarder si le champ est deja dans une jointure existante
309
+    // sinon, si il y a des joitures explicites, la construire
310
+    if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) {
311
+        if ($boucles[$idb]->jointures_explicites) {
312
+            // [todo] Ne pas lancer que lorsque il y a des jointures explicites !!!!
313
+            // fonctionnel, il suffit d'utiliser $boucles[$idb]->jointures au lieu de jointures_explicites
314
+            // mais est-ce ce qu'on veut ?
315
+            $jointures = preg_split('/\s+/', $boucles[$idb]->jointures_explicites);
316
+            if ($cle = trouver_jointure_champ($nom_champ, $boucles[$idb], $jointures)) {
317
+                $t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb]);
318
+            }
319
+        }
320
+    }
321
+
322
+    if ($t) {
323
+        // si on a trouvé une jointure possible, on fait comme
324
+        // si c'était une exception pour le champ demandé
325
+        return index_exception(
326
+            $boucles[$idb],
327
+            $desc,
328
+            $nom_champ,
329
+            [$t[1]['id_table'], reset($t[2])]
330
+        );
331
+    }
332
+
333
+    return ['', ''];
334 334
 }
335 335
 
336 336
 
@@ -358,52 +358,52 @@  discard block
 block discarded – undo
358 358
  *     est une expression pour le SELECT de la boucle du style "mots.titre AS titre_mot"
359 359
  **/
360 360
 function index_exception(&$boucle, $desc, $nom_champ, $excep) {
361
-	static $trouver_table;
362
-	if (!$trouver_table) {
363
-		$trouver_table = charger_fonction('trouver_table', 'base');
364
-	}
365
-
366
-	if (is_array($excep)) {
367
-		// permettre aux plugins de gerer eux meme des jointures derogatoire ingerables
368
-		$t = null;
369
-		if (count($excep) == 3) {
370
-			$index_exception_derogatoire = array_pop($excep);
371
-			$t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep);
372
-		}
373
-		if ($t == null) {
374
-			[$e, $x] = $excep;  #PHP4 affecte de gauche a droite
375
-			$excep = $x;    #PHP5 de droite a gauche !
376
-			$j = $trouver_table($e, $boucle->sql_serveur);
377
-			if (!$j) {
378
-				return ['', ''];
379
-			}
380
-			$e = $j['table'];
381
-			if (!$t = array_search($e, $boucle->from)) {
382
-				$k = $j['key']['PRIMARY KEY'];
383
-				if (strpos($k, ',')) {
384
-					$l = (preg_split('/\s*,\s*/', $k));
385
-					$k = $desc['key']['PRIMARY KEY'];
386
-					if (!in_array($k, $l)) {
387
-						spip_log("jointure impossible $e " . join(',', $l));
388
-
389
-						return ['', ''];
390
-					}
391
-				}
392
-				$k = [$boucle->id_table, [$e], $k];
393
-				fabrique_jointures($boucle, [$k]);
394
-				$t = array_search($e, $boucle->from);
395
-			}
396
-		}
397
-	} else {
398
-		$t = $boucle->id_table;
399
-	}
400
-	// demander a SQL de gerer le synonyme
401
-	// ca permet que excep soit dynamique (Cedric, 2/3/06)
402
-	if ($excep != $nom_champ) {
403
-		$excep .= ' AS ' . $nom_champ;
404
-	}
405
-
406
-	return ["$t.$excep", $nom_champ];
361
+    static $trouver_table;
362
+    if (!$trouver_table) {
363
+        $trouver_table = charger_fonction('trouver_table', 'base');
364
+    }
365
+
366
+    if (is_array($excep)) {
367
+        // permettre aux plugins de gerer eux meme des jointures derogatoire ingerables
368
+        $t = null;
369
+        if (count($excep) == 3) {
370
+            $index_exception_derogatoire = array_pop($excep);
371
+            $t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep);
372
+        }
373
+        if ($t == null) {
374
+            [$e, $x] = $excep;  #PHP4 affecte de gauche a droite
375
+            $excep = $x;    #PHP5 de droite a gauche !
376
+            $j = $trouver_table($e, $boucle->sql_serveur);
377
+            if (!$j) {
378
+                return ['', ''];
379
+            }
380
+            $e = $j['table'];
381
+            if (!$t = array_search($e, $boucle->from)) {
382
+                $k = $j['key']['PRIMARY KEY'];
383
+                if (strpos($k, ',')) {
384
+                    $l = (preg_split('/\s*,\s*/', $k));
385
+                    $k = $desc['key']['PRIMARY KEY'];
386
+                    if (!in_array($k, $l)) {
387
+                        spip_log("jointure impossible $e " . join(',', $l));
388
+
389
+                        return ['', ''];
390
+                    }
391
+                }
392
+                $k = [$boucle->id_table, [$e], $k];
393
+                fabrique_jointures($boucle, [$k]);
394
+                $t = array_search($e, $boucle->from);
395
+            }
396
+        }
397
+    } else {
398
+        $t = $boucle->id_table;
399
+    }
400
+    // demander a SQL de gerer le synonyme
401
+    // ca permet que excep soit dynamique (Cedric, 2/3/06)
402
+    if ($excep != $nom_champ) {
403
+        $excep .= ' AS ' . $nom_champ;
404
+    }
405
+
406
+    return ["$t.$excep", $nom_champ];
407 407
 }
408 408
 
409 409
 /**
@@ -428,7 +428,7 @@  discard block
 block discarded – undo
428 428
  *     Code PHP pour retrouver le champ
429 429
  */
430 430
 function champ_sql($champ, $p, $defaut = null, $remonte_pile = true) {
431
-	return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle, $defaut, $remonte_pile);
431
+    return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle, $defaut, $remonte_pile);
432 432
 }
433 433
 
434 434
 
@@ -448,9 +448,9 @@  discard block
 block discarded – undo
448 448
  *     Code PHP pour d'exécution de la balise et de ses filtres
449 449
  **/
450 450
 function calculer_champ($p) {
451
-	$p = calculer_balise($p->nom_champ, $p);
451
+    $p = calculer_balise($p->nom_champ, $p);
452 452
 
453
-	return applique_filtres($p);
453
+    return applique_filtres($p);
454 454
 }
455 455
 
456 456
 
@@ -487,26 +487,26 @@  discard block
 block discarded – undo
487 487
  **/
488 488
 function calculer_balise(string $nom, Champ $p): Champ {
489 489
 
490
-	// S'agit-t-il d'une balise_XXXX[_dist]() ?
491
-	if ($f = charger_fonction($nom, 'balise', true)) {
492
-		$p->balise_calculee = true;
493
-		$res = $f($p);
494
-		if ($res !== null and is_object($res)) {
495
-			return $res;
496
-		}
497
-	}
498
-
499
-	// Certaines des balises comportant un _ sont generiques
500
-	if ($balise_generique = chercher_balise_generique($nom)) {
501
-		$res = $balise_generique['fonction_generique']($p);
502
-		if ($res !== null and is_object($res)) {
503
-			return $res;
504
-		}
505
-	}
506
-
507
-	$f = charger_fonction('DEFAUT', 'calculer_balise');
508
-
509
-	return $f($nom, $p);
490
+    // S'agit-t-il d'une balise_XXXX[_dist]() ?
491
+    if ($f = charger_fonction($nom, 'balise', true)) {
492
+        $p->balise_calculee = true;
493
+        $res = $f($p);
494
+        if ($res !== null and is_object($res)) {
495
+            return $res;
496
+        }
497
+    }
498
+
499
+    // Certaines des balises comportant un _ sont generiques
500
+    if ($balise_generique = chercher_balise_generique($nom)) {
501
+        $res = $balise_generique['fonction_generique']($p);
502
+        if ($res !== null and is_object($res)) {
503
+            return $res;
504
+        }
505
+    }
506
+
507
+    $f = charger_fonction('DEFAUT', 'calculer_balise');
508
+
509
+    return $f($nom, $p);
510 510
 }
511 511
 
512 512
 
@@ -534,37 +534,37 @@  discard block
 block discarded – undo
534 534
  **/
535 535
 function calculer_balise_DEFAUT_dist($nom, $p) {
536 536
 
537
-	// ca pourrait etre un champ SQL homonyme,
538
-	$p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle);
539
-
540
-	// compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
541
-	// il faut recracher {...} quand ce n'est finalement pas des args
542
-	if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
543
-		$code = addslashes($p->fonctions[0][1]);
544
-		$p->code .= " . '$code'";
545
-	}
546
-
547
-	// ne pas passer le filtre securite sur les id_xxx
548
-	if (strpos($nom, 'ID_') === 0) {
549
-		$p->interdire_scripts = false;
550
-	}
551
-
552
-	// Compatibilite ascendante avec les couleurs html (#FEFEFE) :
553
-	// SI le champ SQL n'est pas trouve
554
-	// ET si la balise a une forme de couleur
555
-	// ET s'il n'y a ni filtre ni etoile
556
-	// ALORS retourner la couleur.
557
-	// Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)]
558
-	if (
559
-		preg_match('/^[A-F]{1,6}$/i', $nom)
560
-		and !$p->etoile
561
-		and !$p->fonctions
562
-	) {
563
-		$p->code = "'#$nom'";
564
-		$p->interdire_scripts = false;
565
-	}
566
-
567
-	return $p;
537
+    // ca pourrait etre un champ SQL homonyme,
538
+    $p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle);
539
+
540
+    // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
541
+    // il faut recracher {...} quand ce n'est finalement pas des args
542
+    if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
543
+        $code = addslashes($p->fonctions[0][1]);
544
+        $p->code .= " . '$code'";
545
+    }
546
+
547
+    // ne pas passer le filtre securite sur les id_xxx
548
+    if (strpos($nom, 'ID_') === 0) {
549
+        $p->interdire_scripts = false;
550
+    }
551
+
552
+    // Compatibilite ascendante avec les couleurs html (#FEFEFE) :
553
+    // SI le champ SQL n'est pas trouve
554
+    // ET si la balise a une forme de couleur
555
+    // ET s'il n'y a ni filtre ni etoile
556
+    // ALORS retourner la couleur.
557
+    // Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)]
558
+    if (
559
+        preg_match('/^[A-F]{1,6}$/i', $nom)
560
+        and !$p->etoile
561
+        and !$p->fonctions
562
+    ) {
563
+        $p->code = "'#$nom'";
564
+        $p->interdire_scripts = false;
565
+    }
566
+
567
+    return $p;
568 568
 }
569 569
 
570 570
 
@@ -613,53 +613,53 @@  discard block
 block discarded – undo
613 613
  **/
614 614
 function calculer_balise_dynamique($p, $nom, $l, $supp = []) {
615 615
 
616
-	if (!balise_distante_interdite($p)) {
617
-		$p->code = "''";
618
-
619
-		return $p;
620
-	}
621
-	// compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
622
-	// il faut recracher {...} quand ce n'est finalement pas des args
623
-	if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
624
-		$p->fonctions = [];
625
-	}
626
-
627
-	if ($p->param and ($c = $p->param[0])) {
628
-		// liste d'arguments commence toujours par la chaine vide
629
-		array_shift($c);
630
-		// construire la liste d'arguments comme pour un filtre
631
-		$param = compose_filtres_args($p, $c, ',');
632
-	} else {
633
-		$param = '';
634
-	}
635
-	$collecte = collecter_balise_dynamique($l, $p, $nom);
636
-
637
-	$dans_un_modele = false;
638
-	if (!empty($p->descr['sourcefile'])
639
-	  and $f = $p->descr['sourcefile']
640
-	  and basename(dirname($f)) === 'modeles'
641
-	) {
642
-		$dans_un_modele = true;
643
-	}
644
-
645
-	// un modele est toujours inséré en texte dans son contenant
646
-	// donc si on est dans le public avec un cache on va perdre le dynamisme
647
-	// et on risque de mettre en cache les valeurs pre-remplies du formulaire
648
-	// on passe donc par une fonction proxy qui si besoin va collecter les arguments
649
-	// et injecter le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
650
-	// (dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave))
651
-	$p->code = sprintf(
652
-		$dans_un_modele ? CODE_EXECUTER_BALISE_MODELE : CODE_EXECUTER_BALISE,
653
-		$nom,
654
-		join(',', $collecte),
655
-		($collecte ? $param : substr($param, 1)), # virer la virgule
656
-		memoriser_contexte_compil($p),
657
-		(!$supp ? '' : (', ' . join(',', $supp)))
658
-	);
659
-
660
-	$p->interdire_scripts = false;
661
-
662
-	return $p;
616
+    if (!balise_distante_interdite($p)) {
617
+        $p->code = "''";
618
+
619
+        return $p;
620
+    }
621
+    // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
622
+    // il faut recracher {...} quand ce n'est finalement pas des args
623
+    if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
624
+        $p->fonctions = [];
625
+    }
626
+
627
+    if ($p->param and ($c = $p->param[0])) {
628
+        // liste d'arguments commence toujours par la chaine vide
629
+        array_shift($c);
630
+        // construire la liste d'arguments comme pour un filtre
631
+        $param = compose_filtres_args($p, $c, ',');
632
+    } else {
633
+        $param = '';
634
+    }
635
+    $collecte = collecter_balise_dynamique($l, $p, $nom);
636
+
637
+    $dans_un_modele = false;
638
+    if (!empty($p->descr['sourcefile'])
639
+      and $f = $p->descr['sourcefile']
640
+      and basename(dirname($f)) === 'modeles'
641
+    ) {
642
+        $dans_un_modele = true;
643
+    }
644
+
645
+    // un modele est toujours inséré en texte dans son contenant
646
+    // donc si on est dans le public avec un cache on va perdre le dynamisme
647
+    // et on risque de mettre en cache les valeurs pre-remplies du formulaire
648
+    // on passe donc par une fonction proxy qui si besoin va collecter les arguments
649
+    // et injecter le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
650
+    // (dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave))
651
+    $p->code = sprintf(
652
+        $dans_un_modele ? CODE_EXECUTER_BALISE_MODELE : CODE_EXECUTER_BALISE,
653
+        $nom,
654
+        join(',', $collecte),
655
+        ($collecte ? $param : substr($param, 1)), # virer la virgule
656
+        memoriser_contexte_compil($p),
657
+        (!$supp ? '' : (', ' . join(',', $supp)))
658
+    );
659
+
660
+    $p->interdire_scripts = false;
661
+
662
+    return $p;
663 663
 }
664 664
 
665 665
 
@@ -689,17 +689,17 @@  discard block
 block discarded – undo
689 689
  *     Liste des codes PHP d'éxecution des balises collectées
690 690
  **/
691 691
 function collecter_balise_dynamique(array $l, Champ &$p, string $nom): array {
692
-	$args = [];
693
-	foreach ($l as $c) {
694
-		if ($c === null) {
695
-			$args[] = 'null';
696
-		} else {
697
-			$x = calculer_balise($c, $p);
698
-			$args[] = $x->code;
699
-		}
700
-	}
701
-
702
-	return $args;
692
+    $args = [];
693
+    foreach ($l as $c) {
694
+        if ($c === null) {
695
+            $args[] = 'null';
696
+        } else {
697
+            $x = calculer_balise($c, $p);
698
+            $args[] = $x->code;
699
+        }
700
+    }
701
+
702
+    return $args;
703 703
 }
704 704
 
705 705
 
@@ -714,22 +714,22 @@  discard block
 block discarded – undo
714 714
  *     Nom de la connexion
715 715
  **/
716 716
 function trouver_nom_serveur_distant($p) {
717
-	$nom = $p->id_boucle;
718
-	if (
719
-		$nom
720
-		and isset($p->boucles[$nom])
721
-	) {
722
-		$s = $p->boucles[$nom]->sql_serveur;
723
-		if (
724
-			strlen($s)
725
-			and strlen($serveur = strtolower($s))
726
-			and !in_array($serveur, $GLOBALS['exception_des_connect'])
727
-		) {
728
-			return $serveur;
729
-		}
730
-	}
731
-
732
-	return '';
717
+    $nom = $p->id_boucle;
718
+    if (
719
+        $nom
720
+        and isset($p->boucles[$nom])
721
+    ) {
722
+        $s = $p->boucles[$nom]->sql_serveur;
723
+        if (
724
+            strlen($s)
725
+            and strlen($serveur = strtolower($s))
726
+            and !in_array($serveur, $GLOBALS['exception_des_connect'])
727
+        ) {
728
+            return $serveur;
729
+        }
730
+    }
731
+
732
+    return '';
733 733
 }
734 734
 
735 735
 
@@ -753,15 +753,15 @@  discard block
 block discarded – undo
753 753
  *     - false : La balise est interdite car le serveur est distant
754 754
  **/
755 755
 function balise_distante_interdite($p) {
756
-	$nom = $p->id_boucle;
756
+    $nom = $p->id_boucle;
757 757
 
758
-	if ($nom and trouver_nom_serveur_distant($p)) {
759
-		spip_log($nom . ':' . $p->nom_champ . ' ' . _T('zbug_distant_interdit'));
758
+    if ($nom and trouver_nom_serveur_distant($p)) {
759
+        spip_log($nom . ':' . $p->nom_champ . ' ' . _T('zbug_distant_interdit'));
760 760
 
761
-		return false;
762
-	}
761
+        return false;
762
+    }
763 763
 
764
-	return true;
764
+    return true;
765 765
 }
766 766
 
767 767
 
@@ -771,84 +771,84 @@  discard block
 block discarded – undo
771 771
 //
772 772
 function champs_traitements($p) {
773 773
 
774
-	if (isset($GLOBALS['table_des_traitements'][$p->nom_champ])) {
775
-		$ps = $GLOBALS['table_des_traitements'][$p->nom_champ];
776
-	} else {
777
-		// quand on utilise un traitement catch-all *
778
-		// celui-ci ne s'applique pas sur les balises calculees qui peuvent gerer
779
-		// leur propre securite
780
-		if (!$p->balise_calculee) {
781
-			$ps = $GLOBALS['table_des_traitements']['*'];
782
-		} else {
783
-			$ps = false;
784
-		}
785
-	}
786
-
787
-	if (is_array($ps)) {
788
-		// Recuperer le type de boucle (articles, DATA) et la table SQL sur laquelle elle porte
789
-		$idb = index_boucle($p);
790
-		// si le champ a ete trouve dans une boucle parente sa source est renseignee ici
791
-		if (!empty($p->boucles[$idb]->index_champ[$p->nom_champ])) {
792
-			$idb = $p->boucles[$idb]->index_champ[$p->nom_champ];
793
-		}
794
-
795
-		// mais on peut aussi etre hors boucle. Se mefier.
796
-		$type_requete = $p->boucles[$idb]->type_requete ?? false;
797
-		$table_sql = $p->boucles[$idb]->show['table_sql'] ?? false;
798
-
799
-		// bien prendre en compte les alias de boucles (hierarchie => rubrique, syndication => syncdic, etc.)
800
-		if ($type_requete and isset($GLOBALS['table_des_tables'][$type_requete])) {
801
-			$type_alias = $type_requete;
802
-			$type_requete = $GLOBALS['table_des_tables'][$type_requete];
803
-		} else {
804
-			$type_alias = false;
805
-		}
806
-
807
-		// le traitement peut n'etre defini que pour une table en particulier "spip_articles"
808
-		if ($table_sql and isset($ps[$table_sql])) {
809
-			$ps = $ps[$table_sql];
810
-		} // ou pour une boucle en particulier "DATA","articles"
811
-		elseif ($type_requete and isset($ps[$type_requete])) {
812
-			$ps = $ps[$type_requete];
813
-		} // ou pour une boucle utilisant un alias ("hierarchie")
814
-		elseif ($type_alias and isset($ps[$type_alias])) {
815
-			$ps = $ps[$type_alias];
816
-		} // ou pour indifféremment quelle que soit la boucle
817
-		elseif (isset($ps[0])) {
818
-			$ps = $ps[0];
819
-		} else {
820
-			$ps = false;
821
-		}
822
-	}
823
-
824
-	if (!$ps) {
825
-		return $p->code;
826
-	}
827
-
828
-	// Si une boucle DOCUMENTS{doublons} est presente dans le squelette,
829
-	// ou si in INCLURE contient {doublons}
830
-	// on insere une fonction de remplissage du tableau des doublons
831
-	// dans les filtres propre() ou typo()
832
-	// (qui traitent les raccourcis <docXX> referencant les docs)
833
-
834
-	if (
835
-		isset($p->descr['documents'])
836
-		and
837
-		$p->descr['documents']
838
-		and (
839
-			(strpos($ps, 'propre') !== false)
840
-			or
841
-			(strpos($ps, 'typo') !== false)
842
-		)
843
-	) {
844
-		$ps = 'traiter_doublons_documents($doublons, ' . $ps . ')';
845
-	}
846
-
847
-	// La protection des champs par |safehtml est assuree par les extensions
848
-	// dans la declaration des traitements des champs sensibles
849
-
850
-	// Remplacer enfin le placeholder %s par le vrai code de la balise
851
-	return str_replace('%s', $p->code, $ps);
774
+    if (isset($GLOBALS['table_des_traitements'][$p->nom_champ])) {
775
+        $ps = $GLOBALS['table_des_traitements'][$p->nom_champ];
776
+    } else {
777
+        // quand on utilise un traitement catch-all *
778
+        // celui-ci ne s'applique pas sur les balises calculees qui peuvent gerer
779
+        // leur propre securite
780
+        if (!$p->balise_calculee) {
781
+            $ps = $GLOBALS['table_des_traitements']['*'];
782
+        } else {
783
+            $ps = false;
784
+        }
785
+    }
786
+
787
+    if (is_array($ps)) {
788
+        // Recuperer le type de boucle (articles, DATA) et la table SQL sur laquelle elle porte
789
+        $idb = index_boucle($p);
790
+        // si le champ a ete trouve dans une boucle parente sa source est renseignee ici
791
+        if (!empty($p->boucles[$idb]->index_champ[$p->nom_champ])) {
792
+            $idb = $p->boucles[$idb]->index_champ[$p->nom_champ];
793
+        }
794
+
795
+        // mais on peut aussi etre hors boucle. Se mefier.
796
+        $type_requete = $p->boucles[$idb]->type_requete ?? false;
797
+        $table_sql = $p->boucles[$idb]->show['table_sql'] ?? false;
798
+
799
+        // bien prendre en compte les alias de boucles (hierarchie => rubrique, syndication => syncdic, etc.)
800
+        if ($type_requete and isset($GLOBALS['table_des_tables'][$type_requete])) {
801
+            $type_alias = $type_requete;
802
+            $type_requete = $GLOBALS['table_des_tables'][$type_requete];
803
+        } else {
804
+            $type_alias = false;
805
+        }
806
+
807
+        // le traitement peut n'etre defini que pour une table en particulier "spip_articles"
808
+        if ($table_sql and isset($ps[$table_sql])) {
809
+            $ps = $ps[$table_sql];
810
+        } // ou pour une boucle en particulier "DATA","articles"
811
+        elseif ($type_requete and isset($ps[$type_requete])) {
812
+            $ps = $ps[$type_requete];
813
+        } // ou pour une boucle utilisant un alias ("hierarchie")
814
+        elseif ($type_alias and isset($ps[$type_alias])) {
815
+            $ps = $ps[$type_alias];
816
+        } // ou pour indifféremment quelle que soit la boucle
817
+        elseif (isset($ps[0])) {
818
+            $ps = $ps[0];
819
+        } else {
820
+            $ps = false;
821
+        }
822
+    }
823
+
824
+    if (!$ps) {
825
+        return $p->code;
826
+    }
827
+
828
+    // Si une boucle DOCUMENTS{doublons} est presente dans le squelette,
829
+    // ou si in INCLURE contient {doublons}
830
+    // on insere une fonction de remplissage du tableau des doublons
831
+    // dans les filtres propre() ou typo()
832
+    // (qui traitent les raccourcis <docXX> referencant les docs)
833
+
834
+    if (
835
+        isset($p->descr['documents'])
836
+        and
837
+        $p->descr['documents']
838
+        and (
839
+            (strpos($ps, 'propre') !== false)
840
+            or
841
+            (strpos($ps, 'typo') !== false)
842
+        )
843
+    ) {
844
+        $ps = 'traiter_doublons_documents($doublons, ' . $ps . ')';
845
+    }
846
+
847
+    // La protection des champs par |safehtml est assuree par les extensions
848
+    // dans la declaration des traitements des champs sensibles
849
+
850
+    // Remplacer enfin le placeholder %s par le vrai code de la balise
851
+    return str_replace('%s', $p->code, $ps);
852 852
 }
853 853
 
854 854
 
@@ -860,110 +860,110 @@  discard block
 block discarded – undo
860 860
 //
861 861
 function applique_filtres($p) {
862 862
 
863
-	// Traitements standards (cf. supra)
864
-	if ($p->etoile == '') {
865
-		$code = champs_traitements($p);
866
-	} else {
867
-		$code = $p->code;
868
-	}
863
+    // Traitements standards (cf. supra)
864
+    if ($p->etoile == '') {
865
+        $code = champs_traitements($p);
866
+    } else {
867
+        $code = $p->code;
868
+    }
869 869
 
870
-	// Appliquer les filtres perso
871
-	if ($p->param) {
872
-		$code = compose_filtres($p, $code);
873
-	}
870
+    // Appliquer les filtres perso
871
+    if ($p->param) {
872
+        $code = compose_filtres($p, $code);
873
+    }
874 874
 
875
-	// S'il y a un lien avec la session, ajouter un code qui levera
876
-	// un drapeau dans la structure d'invalidation $Cache
877
-	if (isset($p->descr['session'])) {
878
-		$code = "invalideur_session(\$Cache, $code)";
879
-	}
875
+    // S'il y a un lien avec la session, ajouter un code qui levera
876
+    // un drapeau dans la structure d'invalidation $Cache
877
+    if (isset($p->descr['session'])) {
878
+        $code = "invalideur_session(\$Cache, $code)";
879
+    }
880 880
 
881
-	$code = sandbox_composer_interdire_scripts($code, $p);
881
+    $code = sandbox_composer_interdire_scripts($code, $p);
882 882
 
883
-	return $code;
883
+    return $code;
884 884
 }
885 885
 
886 886
 // Cf. function pipeline dans ecrire/inc_utils.php
887 887
 function compose_filtres(&$p, $code) {
888 888
 
889
-	$image_miette = false;
890
-	foreach ($p->param as $filtre) {
891
-		$fonc = array_shift($filtre);
892
-		if (!$fonc) {
893
-			continue;
894
-		} // normalement qu'au premier tour.
895
-		$is_filtre_image = ((substr($fonc, 0, 6) == 'image_') and $fonc != 'image_graver');
896
-		if ($image_miette and !$is_filtre_image) {
897
-			// il faut graver maintenant car apres le filtre en cours
898
-			// on est pas sur d'avoir encore le nom du fichier dans le pipe
899
-			$code = "filtrer('image_graver', $code)";
900
-			$image_miette = false;
901
-		}
902
-
903
-		// recuperer les arguments du filtre,
904
-		// a separer par "," ou ":" dans le cas du filtre "?{a,b}"
905
-		$countfiltre = is_countable($filtre) ? count($filtre) : 0;
906
-		if ($fonc !== '?') {
907
-			$sep = ',';
908
-		} else {
909
-			$sep = ':';
910
-			// |?{a,b} *doit* avoir exactement 2 arguments ; on les force
911
-			if ($countfiltre != 2) {
912
-				$filtre = [$filtre[0] ?? '', $filtre[1] ?? ''];
913
-				$countfiltre = 2;
914
-			}
915
-		}
916
-		$arglist = compose_filtres_args($p, $filtre, $sep);
917
-		$logique = filtre_logique($fonc, $code, substr($arglist, 1));
918
-		if ($logique) {
919
-			$code = $logique;
920
-		} else {
921
-			$code = sandbox_composer_filtre($fonc, $code, $arglist, $p, $countfiltre);
922
-			if ($is_filtre_image) {
923
-				$image_miette = true;
924
-			}
925
-		}
926
-	}
927
-	// ramasser les images intermediaires inutiles et graver l'image finale
928
-	if ($image_miette) {
929
-		$code = "filtrer('image_graver',$code)";
930
-	}
931
-
932
-	return $code;
889
+    $image_miette = false;
890
+    foreach ($p->param as $filtre) {
891
+        $fonc = array_shift($filtre);
892
+        if (!$fonc) {
893
+            continue;
894
+        } // normalement qu'au premier tour.
895
+        $is_filtre_image = ((substr($fonc, 0, 6) == 'image_') and $fonc != 'image_graver');
896
+        if ($image_miette and !$is_filtre_image) {
897
+            // il faut graver maintenant car apres le filtre en cours
898
+            // on est pas sur d'avoir encore le nom du fichier dans le pipe
899
+            $code = "filtrer('image_graver', $code)";
900
+            $image_miette = false;
901
+        }
902
+
903
+        // recuperer les arguments du filtre,
904
+        // a separer par "," ou ":" dans le cas du filtre "?{a,b}"
905
+        $countfiltre = is_countable($filtre) ? count($filtre) : 0;
906
+        if ($fonc !== '?') {
907
+            $sep = ',';
908
+        } else {
909
+            $sep = ':';
910
+            // |?{a,b} *doit* avoir exactement 2 arguments ; on les force
911
+            if ($countfiltre != 2) {
912
+                $filtre = [$filtre[0] ?? '', $filtre[1] ?? ''];
913
+                $countfiltre = 2;
914
+            }
915
+        }
916
+        $arglist = compose_filtres_args($p, $filtre, $sep);
917
+        $logique = filtre_logique($fonc, $code, substr($arglist, 1));
918
+        if ($logique) {
919
+            $code = $logique;
920
+        } else {
921
+            $code = sandbox_composer_filtre($fonc, $code, $arglist, $p, $countfiltre);
922
+            if ($is_filtre_image) {
923
+                $image_miette = true;
924
+            }
925
+        }
926
+    }
927
+    // ramasser les images intermediaires inutiles et graver l'image finale
928
+    if ($image_miette) {
929
+        $code = "filtrer('image_graver',$code)";
930
+    }
931
+
932
+    return $code;
933 933
 }
934 934
 
935 935
 // Filtres et,ou,oui,non,sinon,xou,xor,and,or,not,yes
936 936
 // et comparateurs
937 937
 function filtre_logique($fonc, $code, $arg) {
938 938
 
939
-	switch (true) {
940
-		case in_array($fonc, $GLOBALS['table_criteres_infixes']):
941
-			return "($code $fonc $arg)";
942
-		case ($fonc == 'and') or ($fonc == 'et'):
943
-			return "((($code) AND ($arg)) ?' ' :'')";
944
-		case ($fonc == 'or') or ($fonc == 'ou'):
945
-			return "((($code) OR ($arg)) ?' ' :'')";
946
-		case ($fonc == 'xor') or ($fonc == 'xou'):
947
-			return "((($code) XOR ($arg)) ?' ' :'')";
948
-		case ($fonc == 'sinon'):
949
-			return "(((\$a = $code) OR (is_string(\$a) AND strlen(\$a))) ? \$a : $arg)";
950
-		case ($fonc == 'not') or ($fonc == 'non'):
951
-			return "(($code) ?'' :' ')";
952
-		case ($fonc == 'yes') or ($fonc == 'oui'):
953
-			return "(($code) ?' ' :'')";
954
-	}
955
-
956
-	return '';
939
+    switch (true) {
940
+        case in_array($fonc, $GLOBALS['table_criteres_infixes']):
941
+            return "($code $fonc $arg)";
942
+        case ($fonc == 'and') or ($fonc == 'et'):
943
+            return "((($code) AND ($arg)) ?' ' :'')";
944
+        case ($fonc == 'or') or ($fonc == 'ou'):
945
+            return "((($code) OR ($arg)) ?' ' :'')";
946
+        case ($fonc == 'xor') or ($fonc == 'xou'):
947
+            return "((($code) XOR ($arg)) ?' ' :'')";
948
+        case ($fonc == 'sinon'):
949
+            return "(((\$a = $code) OR (is_string(\$a) AND strlen(\$a))) ? \$a : $arg)";
950
+        case ($fonc == 'not') or ($fonc == 'non'):
951
+            return "(($code) ?'' :' ')";
952
+        case ($fonc == 'yes') or ($fonc == 'oui'):
953
+            return "(($code) ?' ' :'')";
954
+    }
955
+
956
+    return '';
957 957
 }
958 958
 
959 959
 function compose_filtres_args($p, $args, $sep) {
960
-	$arglist = '';
961
-	foreach ($args as $arg) {
962
-		$arglist .= $sep .
963
-			calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle);
964
-	}
960
+    $arglist = '';
961
+    foreach ($args as $arg) {
962
+        $arglist .= $sep .
963
+            calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle);
964
+    }
965 965
 
966
-	return $arglist;
966
+    return $arglist;
967 967
 }
968 968
 
969 969
 
@@ -981,15 +981,15 @@  discard block
 block discarded – undo
981 981
  **/
982 982
 function calculer_argument_precedent($idb, $nom_champ, &$boucles, $defaut = null) {
983 983
 
984
-	// si recursif, forcer l'extraction du champ SQL mais ignorer le code
985
-	if ($boucles[$idb]->externe) {
986
-		index_pile($idb, $nom_champ, $boucles, '', $defaut);
987
-		// retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
988
-		// on ignore le defaut fourni dans ce cas
989
-		$defaut = "(\$Pile[\$SP]['$nom_champ'] ?? null)";
990
-	}
984
+    // si recursif, forcer l'extraction du champ SQL mais ignorer le code
985
+    if ($boucles[$idb]->externe) {
986
+        index_pile($idb, $nom_champ, $boucles, '', $defaut);
987
+        // retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
988
+        // on ignore le defaut fourni dans ce cas
989
+        $defaut = "(\$Pile[\$SP]['$nom_champ'] ?? null)";
990
+    }
991 991
 
992
-	return index_pile($boucles[$idb]->id_parent, $nom_champ, $boucles, '', $defaut);
992
+    return index_pile($boucles[$idb]->id_parent, $nom_champ, $boucles, '', $defaut);
993 993
 }
994 994
 
995 995
 //
@@ -1003,30 +1003,30 @@  discard block
 block discarded – undo
1003 1003
 //
1004 1004
 
1005 1005
 function rindex_pile($p, $champ, $motif) {
1006
-	$n = 0;
1007
-	$b = $p->id_boucle;
1008
-	$p->code = '';
1009
-	while ($b != '') {
1010
-		foreach ($p->boucles[$b]->criteres as $critere) {
1011
-			if ($critere->op == $motif) {
1012
-				$p->code = '$Pile[$SP' . (($n == 0) ? '' : "-$n") .
1013
-					"]['$champ']";
1014
-				$b = '';
1015
-				break 2;
1016
-			}
1017
-		}
1018
-		$n++;
1019
-		$b = $p->boucles[$b]->id_parent;
1020
-	}
1021
-
1022
-	// si on est hors d'une boucle de {recherche}, cette balise est vide
1023
-	if (!$p->code) {
1024
-		$p->code = "''";
1025
-	}
1026
-
1027
-	$p->interdire_scripts = false;
1028
-
1029
-	return $p;
1006
+    $n = 0;
1007
+    $b = $p->id_boucle;
1008
+    $p->code = '';
1009
+    while ($b != '') {
1010
+        foreach ($p->boucles[$b]->criteres as $critere) {
1011
+            if ($critere->op == $motif) {
1012
+                $p->code = '$Pile[$SP' . (($n == 0) ? '' : "-$n") .
1013
+                    "]['$champ']";
1014
+                $b = '';
1015
+                break 2;
1016
+            }
1017
+        }
1018
+        $n++;
1019
+        $b = $p->boucles[$b]->id_parent;
1020
+    }
1021
+
1022
+    // si on est hors d'une boucle de {recherche}, cette balise est vide
1023
+    if (!$p->code) {
1024
+        $p->code = "''";
1025
+    }
1026
+
1027
+    $p->interdire_scripts = false;
1028
+
1029
+    return $p;
1030 1030
 }
1031 1031
 
1032 1032
 /**
@@ -1036,7 +1036,7 @@  discard block
 block discarded – undo
1036 1036
  * @return string Nom de la balise, avec indication de boucle explicite si présent.
1037 1037
  */
1038 1038
 function zbug_presenter_champ($p, $champ = '') {
1039
-	$balise = $champ ?: $p->nom_champ;
1040
-	$explicite = $p->nom_boucle ? $p->nom_boucle . ':' : '';
1041
-	return "#{$explicite}{$balise}";
1039
+    $balise = $champ ?: $p->nom_champ;
1040
+    $explicite = $p->nom_boucle ? $p->nom_boucle . ':' : '';
1041
+    return "#{$explicite}{$balise}";
1042 1042
 }
Please login to merge, or discard this patch.
ecrire/public/interfaces.php 1 patch
Indentation   +85 added lines, -85 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 
@@ -48,90 +48,90 @@  discard block
 block discarded – undo
48 48
  */
49 49
 function declarer_interfaces() {
50 50
 
51
-	$GLOBALS['table_des_tables']['articles'] = 'articles';
52
-	$GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
53
-	$GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
54
-	$GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
55
-
56
-	// definition des statuts de publication
57
-	$GLOBALS['table_statut'] = [];
58
-
59
-	//
60
-	// tableau des tables de jointures
61
-	// Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
62
-	$GLOBALS['tables_jointures'] = [];
63
-	$GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
64
-
65
-	// $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
66
-	$GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
67
-
68
-
69
-	if (!defined('_TRAITEMENT_TYPO')) {
70
-		define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
71
-	}
72
-	if (!defined('_TRAITEMENT_RACCOURCIS')) {
73
-		define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
74
-	}
75
-	if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
76
-		define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
77
-	}
78
-	$GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
79
-	$GLOBALS['table_des_traitements']['NOM_SITE']['auteurs'] = 'entites_html(%s)';
80
-	$GLOBALS['table_des_traitements']['NOM']['auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
81
-	$GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
82
-	$GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
83
-	$GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
84
-	$GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
85
-	$GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
86
-	$GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
87
-	$GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
88
-	$GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
89
-	$GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
90
-	$GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
91
-	$GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
92
-	$GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
93
-	$GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
94
-	$GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
95
-	$GLOBALS['table_des_traitements']['TAGS'][] = '%s';
96
-	$GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
97
-	$GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
98
-	$GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
99
-	$GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
100
-	$GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
101
-	$GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
102
-
103
-	// valeur par defaut pour les balises non listees ci-dessus
104
-	$GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
105
-	// toujours securiser les DATA
106
-	$GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
107
-	// expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
108
-	$GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
109
-
110
-
111
-	// gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
112
-	$interfaces = pipeline(
113
-		'declarer_tables_interfaces',
114
-		[
115
-			'table_des_tables' => $GLOBALS['table_des_tables'],
116
-			'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
117
-			'table_date' => $GLOBALS['table_date'],
118
-			'table_titre' => $GLOBALS['table_titre'],
119
-			'tables_jointures' => $GLOBALS['tables_jointures'],
120
-			'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
121
-			'table_des_traitements' => $GLOBALS['table_des_traitements'],
122
-			'table_statut' => $GLOBALS['table_statut'],
123
-		]
124
-	);
125
-	if ($interfaces) {
126
-		$GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
127
-		$GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
128
-		$GLOBALS['table_date'] = $interfaces['table_date'];
129
-		$GLOBALS['table_titre'] = $interfaces['table_titre'];
130
-		$GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
131
-		$GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
132
-		$GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
133
-		$GLOBALS['table_statut'] = $interfaces['table_statut'];
134
-	}
51
+    $GLOBALS['table_des_tables']['articles'] = 'articles';
52
+    $GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
53
+    $GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
54
+    $GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
55
+
56
+    // definition des statuts de publication
57
+    $GLOBALS['table_statut'] = [];
58
+
59
+    //
60
+    // tableau des tables de jointures
61
+    // Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
62
+    $GLOBALS['tables_jointures'] = [];
63
+    $GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
64
+
65
+    // $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
66
+    $GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
67
+
68
+
69
+    if (!defined('_TRAITEMENT_TYPO')) {
70
+        define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
71
+    }
72
+    if (!defined('_TRAITEMENT_RACCOURCIS')) {
73
+        define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
74
+    }
75
+    if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
76
+        define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
77
+    }
78
+    $GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
79
+    $GLOBALS['table_des_traitements']['NOM_SITE']['auteurs'] = 'entites_html(%s)';
80
+    $GLOBALS['table_des_traitements']['NOM']['auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
81
+    $GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
82
+    $GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
83
+    $GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
84
+    $GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
85
+    $GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
86
+    $GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
87
+    $GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
88
+    $GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
89
+    $GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
90
+    $GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
91
+    $GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
92
+    $GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
93
+    $GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
94
+    $GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
95
+    $GLOBALS['table_des_traitements']['TAGS'][] = '%s';
96
+    $GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
97
+    $GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
98
+    $GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
99
+    $GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
100
+    $GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
101
+    $GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
102
+
103
+    // valeur par defaut pour les balises non listees ci-dessus
104
+    $GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
105
+    // toujours securiser les DATA
106
+    $GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
107
+    // expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
108
+    $GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
109
+
110
+
111
+    // gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
112
+    $interfaces = pipeline(
113
+        'declarer_tables_interfaces',
114
+        [
115
+            'table_des_tables' => $GLOBALS['table_des_tables'],
116
+            'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
117
+            'table_date' => $GLOBALS['table_date'],
118
+            'table_titre' => $GLOBALS['table_titre'],
119
+            'tables_jointures' => $GLOBALS['tables_jointures'],
120
+            'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
121
+            'table_des_traitements' => $GLOBALS['table_des_traitements'],
122
+            'table_statut' => $GLOBALS['table_statut'],
123
+        ]
124
+    );
125
+    if ($interfaces) {
126
+        $GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
127
+        $GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
128
+        $GLOBALS['table_date'] = $interfaces['table_date'];
129
+        $GLOBALS['table_titre'] = $interfaces['table_titre'];
130
+        $GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
131
+        $GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
132
+        $GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
133
+        $GLOBALS['table_statut'] = $interfaces['table_statut'];
134
+    }
135 135
 }
136 136
 
137 137
 declarer_interfaces();
Please login to merge, or discard this patch.
ecrire/public/composer.php 1 patch
Indentation   +768 added lines, -768 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
 include_spip('inc/texte');
@@ -41,234 +41,234 @@  discard block
 block discarded – undo
41 41
 
42 42
 function public_composer_dist($squelette, $mime_type, $gram, $source, string $connect = '') {
43 43
 
44
-	$skel = null;
45
-	$boucle = null;
46
-	$nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
47
-
48
-	//  si deja en memoire (INCLURE  a repetition) c'est bon.
49
-	if (function_exists($nom)) {
50
-		return $nom;
51
-	}
52
-
53
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
54
-		$GLOBALS['debug_objets']['courant'] = $nom;
55
-	}
56
-
57
-	$phpfile = sous_repertoire(_DIR_SKELS, '', false, true) . $nom . '.php';
58
-
59
-	// si squelette est deja compile et perenne, le charger
60
-	if (!squelette_obsolete($phpfile, $source)) {
61
-		include_once $phpfile;
62
-		#if (!squelette_obsolete($phpfile, $source)
63
-		#  AND lire_fichier ($phpfile, $skel_code,
64
-		#  array('critique' => 'oui', 'phpcheck' => 'oui'))){
65
-		## eval('?'.'>'.$skel_code);
66
-		#	 spip_log($skel_code, 'comp')
67
-		#}
68
-	}
69
-
70
-	if (file_exists($lib = $squelette . '_fonctions' . '.php')) {
71
-		include_once $lib;
72
-	}
73
-
74
-	// tester si le eval ci-dessus a mis le squelette en memoire
75
-
76
-	if (function_exists($nom)) {
77
-		return $nom;
78
-	}
79
-
80
-	// charger le source, si possible, et compiler
81
-	$skel_code = '';
82
-	if (lire_fichier($source, $skel)) {
83
-		$compiler = charger_fonction('compiler', 'public');
84
-		$skel_code = $compiler($skel, $nom, $gram, $source, $connect);
85
-	}
86
-
87
-	// Ne plus rien faire si le compilateur n'a pas pu operer.
88
-	if (!$skel_code) {
89
-		return false;
90
-	}
91
-
92
-	foreach ($skel_code as $id => $boucle) {
93
-		$f = $boucle->return;
94
-		try {
95
-			eval("return true; $f ;");
96
-		} catch (\ParseError $e) {
97
-			// Code syntaxiquement faux (critere etc mal programme')
98
-			$msg = _T('zbug_erreur_compilation') . ' | Line ' . $e->getLine() . ' : ' . $e->getMessage();
99
-			erreur_squelette($msg, $boucle);
100
-			// continuer pour trouver d'autres fautes eventuelles
101
-			// mais prevenir que c'est mort
102
-			$nom = '';
103
-		}
104
-
105
-		// contexte de compil inutile a present
106
-		// (mais la derniere valeur de $boucle est utilisee ci-dessous)
107
-		$skel_code[$id] = $f;
108
-	}
109
-
110
-	$code = '';
111
-	if ($nom) {
112
-		// Si le code est bon, concatener et mettre en cache
113
-		if (function_exists($nom)) {
114
-			$code = squelette_traduit($skel, $source, $phpfile, $skel_code);
115
-		} else {
116
-			// code semantiquement faux: bug du compilateur
117
-			// $boucle est en fait ici la fct principale du squelette
118
-			$msg = _T('zbug_erreur_compilation');
119
-			erreur_squelette($msg, $boucle);
120
-			$nom = '';
121
-		}
122
-	}
123
-
124
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
125
-		// Tracer ce qui vient d'etre compile
126
-		$GLOBALS['debug_objets']['code'][$nom . 'tout'] = $code;
127
-
128
-		// si c'est ce que demande le debusqueur, lui passer la main
129
-		if (
130
-			$GLOBALS['debug_objets']['sourcefile']
131
-			and (_request('var_mode_objet') == $nom)
132
-			and (_request('var_mode_affiche') == 'code')
133
-		) {
134
-			erreur_squelette();
135
-		}
136
-	}
137
-
138
-	return $nom ?: false;
44
+    $skel = null;
45
+    $boucle = null;
46
+    $nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
47
+
48
+    //  si deja en memoire (INCLURE  a repetition) c'est bon.
49
+    if (function_exists($nom)) {
50
+        return $nom;
51
+    }
52
+
53
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
54
+        $GLOBALS['debug_objets']['courant'] = $nom;
55
+    }
56
+
57
+    $phpfile = sous_repertoire(_DIR_SKELS, '', false, true) . $nom . '.php';
58
+
59
+    // si squelette est deja compile et perenne, le charger
60
+    if (!squelette_obsolete($phpfile, $source)) {
61
+        include_once $phpfile;
62
+        #if (!squelette_obsolete($phpfile, $source)
63
+        #  AND lire_fichier ($phpfile, $skel_code,
64
+        #  array('critique' => 'oui', 'phpcheck' => 'oui'))){
65
+        ## eval('?'.'>'.$skel_code);
66
+        #	 spip_log($skel_code, 'comp')
67
+        #}
68
+    }
69
+
70
+    if (file_exists($lib = $squelette . '_fonctions' . '.php')) {
71
+        include_once $lib;
72
+    }
73
+
74
+    // tester si le eval ci-dessus a mis le squelette en memoire
75
+
76
+    if (function_exists($nom)) {
77
+        return $nom;
78
+    }
79
+
80
+    // charger le source, si possible, et compiler
81
+    $skel_code = '';
82
+    if (lire_fichier($source, $skel)) {
83
+        $compiler = charger_fonction('compiler', 'public');
84
+        $skel_code = $compiler($skel, $nom, $gram, $source, $connect);
85
+    }
86
+
87
+    // Ne plus rien faire si le compilateur n'a pas pu operer.
88
+    if (!$skel_code) {
89
+        return false;
90
+    }
91
+
92
+    foreach ($skel_code as $id => $boucle) {
93
+        $f = $boucle->return;
94
+        try {
95
+            eval("return true; $f ;");
96
+        } catch (\ParseError $e) {
97
+            // Code syntaxiquement faux (critere etc mal programme')
98
+            $msg = _T('zbug_erreur_compilation') . ' | Line ' . $e->getLine() . ' : ' . $e->getMessage();
99
+            erreur_squelette($msg, $boucle);
100
+            // continuer pour trouver d'autres fautes eventuelles
101
+            // mais prevenir que c'est mort
102
+            $nom = '';
103
+        }
104
+
105
+        // contexte de compil inutile a present
106
+        // (mais la derniere valeur de $boucle est utilisee ci-dessous)
107
+        $skel_code[$id] = $f;
108
+    }
109
+
110
+    $code = '';
111
+    if ($nom) {
112
+        // Si le code est bon, concatener et mettre en cache
113
+        if (function_exists($nom)) {
114
+            $code = squelette_traduit($skel, $source, $phpfile, $skel_code);
115
+        } else {
116
+            // code semantiquement faux: bug du compilateur
117
+            // $boucle est en fait ici la fct principale du squelette
118
+            $msg = _T('zbug_erreur_compilation');
119
+            erreur_squelette($msg, $boucle);
120
+            $nom = '';
121
+        }
122
+    }
123
+
124
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
125
+        // Tracer ce qui vient d'etre compile
126
+        $GLOBALS['debug_objets']['code'][$nom . 'tout'] = $code;
127
+
128
+        // si c'est ce que demande le debusqueur, lui passer la main
129
+        if (
130
+            $GLOBALS['debug_objets']['sourcefile']
131
+            and (_request('var_mode_objet') == $nom)
132
+            and (_request('var_mode_affiche') == 'code')
133
+        ) {
134
+            erreur_squelette();
135
+        }
136
+    }
137
+
138
+    return $nom ?: false;
139 139
 }
140 140
 
141 141
 function squelette_traduit($squelette, $sourcefile, $phpfile, $boucles) {
142 142
 
143
-	$code = null;
144
-	// Le dernier index est '' (fonction principale)
145
-	$noms = substr(join(', ', array_keys($boucles)), 0, -2);
146
-	if (CODE_COMMENTE) {
147
-		$code = "
143
+    $code = null;
144
+    // Le dernier index est '' (fonction principale)
145
+    $noms = substr(join(', ', array_keys($boucles)), 0, -2);
146
+    if (CODE_COMMENTE) {
147
+        $code = "
148 148
 /*
149 149
  * Squelette : $sourcefile
150 150
  * Date :      " . gmdate('D, d M Y H:i:s', @filemtime($sourcefile)) . ' GMT
151 151
  * Compile :   ' . gmdate('D, d M Y H:i:s', time()) . ' GMT
152 152
  * ' . (!$boucles ? 'Pas de boucle' : ('Boucles :   ' . $noms)) . '
153 153
  */ ';
154
-	}
154
+    }
155 155
 
156
-	$code = '<' . "?php\n" . $code . join('', $boucles) . "\n";
157
-	if (!defined('_VAR_NOCACHE') or !_VAR_NOCACHE) {
158
-		ecrire_fichier($phpfile, $code);
159
-	}
156
+    $code = '<' . "?php\n" . $code . join('', $boucles) . "\n";
157
+    if (!defined('_VAR_NOCACHE') or !_VAR_NOCACHE) {
158
+        ecrire_fichier($phpfile, $code);
159
+    }
160 160
 
161
-	return $code;
161
+    return $code;
162 162
 }
163 163
 
164 164
 // Le squelette compile est-il trop vieux ?
165 165
 function squelette_obsolete($skel, $squelette) {
166
-	static $date_change = null;
167
-	// ne verifier la date de mes_fonctions et mes_options qu'une seule fois
168
-	// par hit
169
-	if (is_null($date_change)) {
170
-		if (@file_exists($fonc = 'mes_fonctions.php')) {
171
-			$date_change = @filemtime($fonc);
172
-		} # compatibilite
173
-		if (defined('_FILE_OPTIONS')) {
174
-			$date_change = max($date_change, @filemtime(_FILE_OPTIONS));
175
-		}
176
-	}
177
-
178
-	return (
179
-		(defined('_VAR_MODE') and in_array(_VAR_MODE, ['recalcul', 'preview', 'debug']))
180
-		or !@file_exists($skel)
181
-		or ((@file_exists($squelette) ? @filemtime($squelette) : 0)
182
-			> ($date = @filemtime($skel)))
183
-		or ($date_change > $date)
184
-	);
166
+    static $date_change = null;
167
+    // ne verifier la date de mes_fonctions et mes_options qu'une seule fois
168
+    // par hit
169
+    if (is_null($date_change)) {
170
+        if (@file_exists($fonc = 'mes_fonctions.php')) {
171
+            $date_change = @filemtime($fonc);
172
+        } # compatibilite
173
+        if (defined('_FILE_OPTIONS')) {
174
+            $date_change = max($date_change, @filemtime(_FILE_OPTIONS));
175
+        }
176
+    }
177
+
178
+    return (
179
+        (defined('_VAR_MODE') and in_array(_VAR_MODE, ['recalcul', 'preview', 'debug']))
180
+        or !@file_exists($skel)
181
+        or ((@file_exists($squelette) ? @filemtime($squelette) : 0)
182
+            > ($date = @filemtime($skel)))
183
+        or ($date_change > $date)
184
+    );
185 185
 }
186 186
 
187 187
 // Activer l'invalideur de session
188 188
 function invalideur_session(&$Cache, $code = null) {
189
-	$Cache['session'] = spip_session();
189
+    $Cache['session'] = spip_session();
190 190
 
191
-	return $code;
191
+    return $code;
192 192
 }
193 193
 
194 194
 
195 195
 function analyse_resultat_skel($nom, $cache, $corps, $source = '') {
196
-	static $filtres = [];
197
-	$headers = [];
198
-	$corps ??= '';
199
-
200
-	// Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
201
-	// note: on essaie d'attrapper aussi certains de ces entetes codes
202
-	// "a la main" dans les squelettes, mais evidemment sans exhaustivite
203
-	if (
204
-		stripos($corps, 'header') !== false
205
-		and preg_match_all(
206
-			'/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
207
-			$corps,
208
-			$regs,
209
-			PREG_SET_ORDER
210
-		)
211
-	) {
212
-		foreach ($regs as $r) {
213
-			$corps = str_replace($r[0], '', $corps);
214
-			# $j = Content-Type, et pas content-TYPE.
215
-			$j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
216
-
217
-			if ($j == 'X-Spip-Filtre' and isset($headers[$j])) {
218
-				$headers[$j] .= '|' . $r[3];
219
-			} else {
220
-				$headers[$j] = str_replace(['\\\\',"\\'",'\\"'], ['\\',"'",'"'], $r[3]);
221
-			}
222
-		}
223
-	}
224
-	// S'agit-il d'un resultat constant ou contenant du code php
225
-	$process_ins = (
226
-		strpos($corps, '<' . '?') === false
227
-		or
228
-		(strpos($corps, '<' . '?xml') !== false and
229
-			strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
230
-	)
231
-		? 'html'
232
-		: 'php';
233
-
234
-	$skel = [
235
-		'squelette' => $nom,
236
-		'source' => $source,
237
-		'process_ins' => $process_ins,
238
-		'invalideurs' => $cache,
239
-		'entetes' => $headers,
240
-		'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0
241
-	];
242
-
243
-	// traiter #FILTRE{} et filtres
244
-	if (!isset($filtres[$nom])) {
245
-		$filtres[$nom] = pipeline('declarer_filtres_squelettes', ['args' => $skel, 'data' => []]);
246
-	}
247
-	$filtres_headers = [];
248
-	if (isset($headers['X-Spip-Filtre']) and strlen($headers['X-Spip-Filtre'])) {
249
-		$filtres_headers = array_filter(explode('|', $headers['X-Spip-Filtre']));
250
-		unset($headers['X-Spip-Filtre']);
251
-	}
252
-	if (is_array($filtres[$nom]) || $filtres[$nom] instanceof \Countable ? count($filtres[$nom]) : 0 or count($filtres_headers)) {
253
-		include_spip('public/sandbox');
254
-		$corps = sandbox_filtrer_squelette($skel, $corps, $filtres_headers, $filtres[$nom]);
255
-
256
-		if ($process_ins == 'html') {
257
-			$skel['process_ins'] = (
258
-				strpos($corps, '<' . '?') === false
259
-				or
260
-				(strpos($corps, '<' . '?xml') !== false and
261
-					strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
262
-			)
263
-				? 'html'
264
-				: 'php';
265
-		}
266
-	}
267
-
268
-	$skel['entetes'] = $headers;
269
-	$skel['texte'] = $corps;
270
-
271
-	return $skel;
196
+    static $filtres = [];
197
+    $headers = [];
198
+    $corps ??= '';
199
+
200
+    // Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
201
+    // note: on essaie d'attrapper aussi certains de ces entetes codes
202
+    // "a la main" dans les squelettes, mais evidemment sans exhaustivite
203
+    if (
204
+        stripos($corps, 'header') !== false
205
+        and preg_match_all(
206
+            '/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
207
+            $corps,
208
+            $regs,
209
+            PREG_SET_ORDER
210
+        )
211
+    ) {
212
+        foreach ($regs as $r) {
213
+            $corps = str_replace($r[0], '', $corps);
214
+            # $j = Content-Type, et pas content-TYPE.
215
+            $j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
216
+
217
+            if ($j == 'X-Spip-Filtre' and isset($headers[$j])) {
218
+                $headers[$j] .= '|' . $r[3];
219
+            } else {
220
+                $headers[$j] = str_replace(['\\\\',"\\'",'\\"'], ['\\',"'",'"'], $r[3]);
221
+            }
222
+        }
223
+    }
224
+    // S'agit-il d'un resultat constant ou contenant du code php
225
+    $process_ins = (
226
+        strpos($corps, '<' . '?') === false
227
+        or
228
+        (strpos($corps, '<' . '?xml') !== false and
229
+            strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
230
+    )
231
+        ? 'html'
232
+        : 'php';
233
+
234
+    $skel = [
235
+        'squelette' => $nom,
236
+        'source' => $source,
237
+        'process_ins' => $process_ins,
238
+        'invalideurs' => $cache,
239
+        'entetes' => $headers,
240
+        'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0
241
+    ];
242
+
243
+    // traiter #FILTRE{} et filtres
244
+    if (!isset($filtres[$nom])) {
245
+        $filtres[$nom] = pipeline('declarer_filtres_squelettes', ['args' => $skel, 'data' => []]);
246
+    }
247
+    $filtres_headers = [];
248
+    if (isset($headers['X-Spip-Filtre']) and strlen($headers['X-Spip-Filtre'])) {
249
+        $filtres_headers = array_filter(explode('|', $headers['X-Spip-Filtre']));
250
+        unset($headers['X-Spip-Filtre']);
251
+    }
252
+    if (is_array($filtres[$nom]) || $filtres[$nom] instanceof \Countable ? count($filtres[$nom]) : 0 or count($filtres_headers)) {
253
+        include_spip('public/sandbox');
254
+        $corps = sandbox_filtrer_squelette($skel, $corps, $filtres_headers, $filtres[$nom]);
255
+
256
+        if ($process_ins == 'html') {
257
+            $skel['process_ins'] = (
258
+                strpos($corps, '<' . '?') === false
259
+                or
260
+                (strpos($corps, '<' . '?xml') !== false and
261
+                    strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
262
+            )
263
+                ? 'html'
264
+                : 'php';
265
+        }
266
+    }
267
+
268
+    $skel['entetes'] = $headers;
269
+    $skel['texte'] = $corps;
270
+
271
+    return $skel;
272 272
 }
273 273
 
274 274
 //
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
 inserer_balise_dynamique(balise_%s_dyn(%s), array(%s));
283 283
 if ($lang_select) lang_select();
284 284
 ?'
285
-	. '>');
285
+    . '>');
286 286
 
287 287
 /**
288 288
  * Synthétise une balise dynamique : crée l'appel à l'inclusion
@@ -302,35 +302,35 @@  discard block
 block discarded – undo
302 302
  *     Code PHP pour inclure le squelette de la balise dynamique
303 303
  **/
304 304
 function synthetiser_balise_dynamique($nom, $args, $file, $context_compil) {
305
-	if (
306
-		strncmp($file, '/', 1) !== 0
307
-		// pas de lien symbolique sous Windows
308
-		and !(stristr(PHP_OS, 'WIN') and str_contains($file, ':'))
309
-	) {
310
-		$file = './" . _DIR_RACINE . "' . $file;
311
-	}
312
-
313
-	$lang = $context_compil[4];
314
-	if (preg_match(',\W,', $lang)) {
315
-		$lang = '';
316
-	}
317
-
318
-	$args = array_map('argumenter_squelette', $args);
319
-	if (!empty($context_compil['appel_php_depuis_modele'])) {
320
-		$args[0] = 'arguments_balise_dyn_depuis_modele(' . $args[0] . ')';
321
-	}
322
-	$args = join(', ', $args);
323
-
324
-	$r = sprintf(
325
-		CODE_INCLURE_BALISE,
326
-		$file,
327
-		$lang,
328
-		$nom,
329
-		$args,
330
-		join(', ', array_map('_q', $context_compil))
331
-	);
332
-
333
-	return $r;
305
+    if (
306
+        strncmp($file, '/', 1) !== 0
307
+        // pas de lien symbolique sous Windows
308
+        and !(stristr(PHP_OS, 'WIN') and str_contains($file, ':'))
309
+    ) {
310
+        $file = './" . _DIR_RACINE . "' . $file;
311
+    }
312
+
313
+    $lang = $context_compil[4];
314
+    if (preg_match(',\W,', $lang)) {
315
+        $lang = '';
316
+    }
317
+
318
+    $args = array_map('argumenter_squelette', $args);
319
+    if (!empty($context_compil['appel_php_depuis_modele'])) {
320
+        $args[0] = 'arguments_balise_dyn_depuis_modele(' . $args[0] . ')';
321
+    }
322
+    $args = join(', ', $args);
323
+
324
+    $r = sprintf(
325
+        CODE_INCLURE_BALISE,
326
+        $file,
327
+        $lang,
328
+        $nom,
329
+        $args,
330
+        join(', ', array_map('_q', $context_compil))
331
+    );
332
+
333
+    return $r;
334 334
 }
335 335
 
336 336
 /**
@@ -348,18 +348,18 @@  discard block
 block discarded – undo
348 348
  **/
349 349
 function argumenter_squelette($v) {
350 350
 
351
-	if (is_object($v)) {
352
-		return var_export($v, true);
353
-	} elseif (!is_array($v)) {
354
-		return "'" . texte_script((string) $v) . "'";
355
-	} else {
356
-		$out = [];
357
-		foreach ($v as $k => $val) {
358
-			$out [] = argumenter_squelette($k) . '=>' . argumenter_squelette($val);
359
-		}
360
-
361
-		return 'array(' . join(', ', $out) . ')';
362
-	}
351
+    if (is_object($v)) {
352
+        return var_export($v, true);
353
+    } elseif (!is_array($v)) {
354
+        return "'" . texte_script((string) $v) . "'";
355
+    } else {
356
+        $out = [];
357
+        foreach ($v as $k => $val) {
358
+            $out [] = argumenter_squelette($k) . '=>' . argumenter_squelette($val);
359
+        }
360
+
361
+        return 'array(' . join(', ', $out) . ')';
362
+    }
363 363
 }
364 364
 
365 365
 /**
@@ -378,13 +378,13 @@  discard block
 block discarded – undo
378 378
  * @return string
379 379
  */
380 380
 function executer_balise_dynamique_dans_un_modele(...$args) {
381
-	if (test_espace_prive()) {
382
-		return executer_balise_dynamique(...$args);
383
-	}
384
-	else {
385
-		$str_args = base64_encode(serialize($args));
386
-		return "<?" . "php \$_zargs=unserialize(base64_decode('$str_args'));echo executer_balise_dynamique(...\$_zargs); ?".">\n";
387
-	}
381
+    if (test_espace_prive()) {
382
+        return executer_balise_dynamique(...$args);
383
+    }
384
+    else {
385
+        $str_args = base64_encode(serialize($args));
386
+        return "<?" . "php \$_zargs=unserialize(base64_decode('$str_args'));echo executer_balise_dynamique(...\$_zargs); ?".">\n";
387
+    }
388 388
 }
389 389
 
390 390
 
@@ -415,87 +415,87 @@  discard block
 block discarded – undo
415 415
  *     Code PHP d'exécutant l'inclusion du squelette (ou texte) de la balise dynamique
416 416
  **/
417 417
 function executer_balise_dynamique($nom, $args, $context_compil) {
418
-	/** @var string Nom de la balise à charger (balise demandée ou balise générique) */
419
-	$nom_balise = $nom;
420
-	/** @var string Nom de la balise générique (si utilisée) */
421
-	$nom_balise_generique = '';
422
-
423
-	$appel_php_depuis_modele = false;
424
-	if (
425
-		is_array($context_compil)
426
-		and !is_numeric($context_compil[3])
427
-		and empty($context_compil[0])
428
-		and empty($context_compil[1])
429
-		and empty($context_compil[2])
430
-		and empty($context_compil[3])
431
-	) {
432
-		$appel_php_depuis_modele = true;
433
-	}
434
-
435
-	if (!$fonction_balise = charger_fonction($nom_balise, 'balise', true)) {
436
-		// Calculer un nom générique (ie. 'formulaire_' dans 'formulaire_editer_article')
437
-		if ($balise_generique = chercher_balise_generique($nom)) {
438
-			// injecter en premier arg le nom de la balise
439
-			array_unshift($args, $nom);
440
-			$nom_balise_generique = $balise_generique['nom_generique'];
441
-			$fonction_balise = $balise_generique['fonction_generique'];
442
-			$nom_balise = $nom_balise_generique;
443
-		}
444
-		unset($balise_generique);
445
-	}
446
-
447
-	if (!$fonction_balise) {
448
-		$msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
449
-		erreur_squelette($msg, $context_compil);
450
-
451
-		return '';
452
-	}
453
-
454
-	// retrouver le fichier qui a déclaré la fonction
455
-	// mĂªme si la fonction dynamique est dĂ©clarĂ©e dans un fichier de fonctions.
456
-	// Attention sous windows, getFileName() retourne un antislash.
457
-	$reflector = new ReflectionFunction($fonction_balise);
458
-	$file = str_replace('\\', '/', $reflector->getFileName());
459
-	if (strncmp($file, str_replace('\\', '/', _ROOT_RACINE), strlen(_ROOT_RACINE)) === 0) {
460
-		$file = substr($file, strlen(_ROOT_RACINE));
461
-	}
462
-
463
-	// Y a-t-il une fonction de traitement des arguments ?
464
-	$f = 'balise_' . $nom_balise . '_stat';
465
-
466
-	$r = !function_exists($f) ? $args : $f($args, $context_compil);
467
-
468
-	if (!is_array($r)) {
469
-		return $r;
470
-	}
471
-
472
-	// verifier que la fonction dyn est la,
473
-	// sinon se replier sur la generique si elle existe
474
-	if (!function_exists('balise_' . $nom_balise . '_dyn')) {
475
-		if (
476
-			$balise_generique = chercher_balise_generique($nom)
477
-			and $nom_balise_generique = $balise_generique['nom_generique']
478
-			and $file = include_spip('balise/' . strtolower($nom_balise_generique))
479
-			and function_exists('balise_' . $nom_balise_generique . '_dyn')
480
-		) {
481
-			// et lui injecter en premier arg le nom de la balise
482
-			array_unshift($r, $nom);
483
-			$nom_balise = $nom_balise_generique;
484
-			if (!_DIR_RESTREINT) {
485
-				$file = _DIR_RESTREINT_ABS . $file;
486
-			}
487
-		} else {
488
-			$msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
489
-			erreur_squelette($msg, $context_compil);
490
-
491
-			return '';
492
-		}
493
-	}
494
-
495
-	if ($appel_php_depuis_modele) {
496
-		$context_compil['appel_php_depuis_modele'] = true;
497
-	}
498
-	return synthetiser_balise_dynamique($nom_balise, $r, $file, $context_compil);
418
+    /** @var string Nom de la balise à charger (balise demandée ou balise générique) */
419
+    $nom_balise = $nom;
420
+    /** @var string Nom de la balise générique (si utilisée) */
421
+    $nom_balise_generique = '';
422
+
423
+    $appel_php_depuis_modele = false;
424
+    if (
425
+        is_array($context_compil)
426
+        and !is_numeric($context_compil[3])
427
+        and empty($context_compil[0])
428
+        and empty($context_compil[1])
429
+        and empty($context_compil[2])
430
+        and empty($context_compil[3])
431
+    ) {
432
+        $appel_php_depuis_modele = true;
433
+    }
434
+
435
+    if (!$fonction_balise = charger_fonction($nom_balise, 'balise', true)) {
436
+        // Calculer un nom générique (ie. 'formulaire_' dans 'formulaire_editer_article')
437
+        if ($balise_generique = chercher_balise_generique($nom)) {
438
+            // injecter en premier arg le nom de la balise
439
+            array_unshift($args, $nom);
440
+            $nom_balise_generique = $balise_generique['nom_generique'];
441
+            $fonction_balise = $balise_generique['fonction_generique'];
442
+            $nom_balise = $nom_balise_generique;
443
+        }
444
+        unset($balise_generique);
445
+    }
446
+
447
+    if (!$fonction_balise) {
448
+        $msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
449
+        erreur_squelette($msg, $context_compil);
450
+
451
+        return '';
452
+    }
453
+
454
+    // retrouver le fichier qui a déclaré la fonction
455
+    // mĂªme si la fonction dynamique est dĂ©clarĂ©e dans un fichier de fonctions.
456
+    // Attention sous windows, getFileName() retourne un antislash.
457
+    $reflector = new ReflectionFunction($fonction_balise);
458
+    $file = str_replace('\\', '/', $reflector->getFileName());
459
+    if (strncmp($file, str_replace('\\', '/', _ROOT_RACINE), strlen(_ROOT_RACINE)) === 0) {
460
+        $file = substr($file, strlen(_ROOT_RACINE));
461
+    }
462
+
463
+    // Y a-t-il une fonction de traitement des arguments ?
464
+    $f = 'balise_' . $nom_balise . '_stat';
465
+
466
+    $r = !function_exists($f) ? $args : $f($args, $context_compil);
467
+
468
+    if (!is_array($r)) {
469
+        return $r;
470
+    }
471
+
472
+    // verifier que la fonction dyn est la,
473
+    // sinon se replier sur la generique si elle existe
474
+    if (!function_exists('balise_' . $nom_balise . '_dyn')) {
475
+        if (
476
+            $balise_generique = chercher_balise_generique($nom)
477
+            and $nom_balise_generique = $balise_generique['nom_generique']
478
+            and $file = include_spip('balise/' . strtolower($nom_balise_generique))
479
+            and function_exists('balise_' . $nom_balise_generique . '_dyn')
480
+        ) {
481
+            // et lui injecter en premier arg le nom de la balise
482
+            array_unshift($r, $nom);
483
+            $nom_balise = $nom_balise_generique;
484
+            if (!_DIR_RESTREINT) {
485
+                $file = _DIR_RESTREINT_ABS . $file;
486
+            }
487
+        } else {
488
+            $msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
489
+            erreur_squelette($msg, $context_compil);
490
+
491
+            return '';
492
+        }
493
+    }
494
+
495
+    if ($appel_php_depuis_modele) {
496
+        $context_compil['appel_php_depuis_modele'] = true;
497
+    }
498
+    return synthetiser_balise_dynamique($nom_balise, $r, $file, $context_compil);
499 499
 }
500 500
 
501 501
 /**
@@ -510,23 +510,23 @@  discard block
 block discarded – undo
510 510
  * @return array|null
511 511
  */
512 512
 function chercher_balise_generique($nom) {
513
-	if (!str_contains($nom, '_')) {
514
-		return null;
515
-	}
516
-	$nom_generique = $nom;
517
-	while (false !== ($p = strrpos($nom_generique, '_'))) {
518
-		$nom_generique = substr($nom_generique, 0, $p + 1);
519
-		$fonction_generique = charger_fonction($nom_generique, 'balise', true);
520
-		if ($fonction_generique) {
521
-			return [
522
-				'nom' => $nom,
523
-				'nom_generique' => $nom_generique,
524
-				'fonction_generique' => $fonction_generique,
525
-			];
526
-		}
527
-		$nom_generique = substr($nom_generique, 0, -1);
528
-	}
529
-	return null;
513
+    if (!str_contains($nom, '_')) {
514
+        return null;
515
+    }
516
+    $nom_generique = $nom;
517
+    while (false !== ($p = strrpos($nom_generique, '_'))) {
518
+        $nom_generique = substr($nom_generique, 0, $p + 1);
519
+        $fonction_generique = charger_fonction($nom_generique, 'balise', true);
520
+        if ($fonction_generique) {
521
+            return [
522
+                'nom' => $nom,
523
+                'nom_generique' => $nom_generique,
524
+                'fonction_generique' => $fonction_generique,
525
+            ];
526
+        }
527
+        $nom_generique = substr($nom_generique, 0, -1);
528
+    }
529
+    return null;
530 530
 }
531 531
 
532 532
 
@@ -550,50 +550,50 @@  discard block
 block discarded – undo
550 550
  * @return null;
551 551
  **/
552 552
 function lang_select_public($lang, $lang_select, $titre = null) {
553
-	// Cas 1. forcer_lang = true et pas de critere {lang_select}
554
-	if (
555
-		isset($GLOBALS['forcer_lang']) and $GLOBALS['forcer_lang']
556
-		and $lang_select !== 'oui'
557
-	) {
558
-		$lang = $GLOBALS['spip_lang'];
559
-	} // Cas 2. l'objet n'a pas de langue definie (ou definie a '')
560
-	elseif (!strlen($lang)) {
561
-		$lang = $GLOBALS['spip_lang'];
562
-	} // Cas 3. l'objet est multilingue !
563
-	elseif (
564
-		$lang_select !== 'oui'
565
-		and strlen($titre) > 10
566
-		and str_contains($titre, '<multi>')
567
-		and str_contains(echappe_html($titre), '<multi>')
568
-	) {
569
-		$lang = $GLOBALS['spip_lang'];
570
-	}
571
-
572
-	// faire un lang_select() eventuellement sur la langue inchangee
573
-	lang_select($lang);
574
-
575
-	return;
553
+    // Cas 1. forcer_lang = true et pas de critere {lang_select}
554
+    if (
555
+        isset($GLOBALS['forcer_lang']) and $GLOBALS['forcer_lang']
556
+        and $lang_select !== 'oui'
557
+    ) {
558
+        $lang = $GLOBALS['spip_lang'];
559
+    } // Cas 2. l'objet n'a pas de langue definie (ou definie a '')
560
+    elseif (!strlen($lang)) {
561
+        $lang = $GLOBALS['spip_lang'];
562
+    } // Cas 3. l'objet est multilingue !
563
+    elseif (
564
+        $lang_select !== 'oui'
565
+        and strlen($titre) > 10
566
+        and str_contains($titre, '<multi>')
567
+        and str_contains(echappe_html($titre), '<multi>')
568
+    ) {
569
+        $lang = $GLOBALS['spip_lang'];
570
+    }
571
+
572
+    // faire un lang_select() eventuellement sur la langue inchangee
573
+    lang_select($lang);
574
+
575
+    return;
576 576
 }
577 577
 
578 578
 
579 579
 // Si un tableau &doublons[articles] est passe en parametre,
580 580
 // il faut le nettoyer car il pourrait etre injecte en SQL
581 581
 function nettoyer_env_doublons($envd) {
582
-	foreach ($envd as $table => $liste) {
583
-		$n = '';
584
-		foreach (explode(',', $liste) as $val) {
585
-			if ($a = intval($val) and $val === strval($a)) {
586
-				$n .= ',' . $val;
587
-			}
588
-		}
589
-		if (strlen($n)) {
590
-			$envd[$table] = $n;
591
-		} else {
592
-			unset($envd[$table]);
593
-		}
594
-	}
595
-
596
-	return $envd;
582
+    foreach ($envd as $table => $liste) {
583
+        $n = '';
584
+        foreach (explode(',', $liste) as $val) {
585
+            if ($a = intval($val) and $val === strval($a)) {
586
+                $n .= ',' . $val;
587
+            }
588
+        }
589
+        if (strlen($n)) {
590
+            $envd[$table] = $n;
591
+        } else {
592
+            unset($envd[$table]);
593
+        }
594
+    }
595
+
596
+    return $envd;
597 597
 }
598 598
 
599 599
 /**
@@ -612,21 +612,21 @@  discard block
 block discarded – undo
612 612
  *     Opérateur trouvé (SELF ou SUBSELECT) sinon false.
613 613
  **/
614 614
 function match_self($w) {
615
-	if (is_string($w)) {
616
-		return false;
617
-	}
618
-	if (is_array($w)) {
619
-		if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
620
-			return $w;
621
-		}
622
-		foreach (array_filter($w, 'is_array') as $sw) {
623
-			if ($m = match_self($sw)) {
624
-				return $m;
625
-			}
626
-		}
627
-	}
628
-
629
-	return false;
615
+    if (is_string($w)) {
616
+        return false;
617
+    }
618
+    if (is_array($w)) {
619
+        if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
620
+            return $w;
621
+        }
622
+        foreach (array_filter($w, 'is_array') as $sw) {
623
+            if ($m = match_self($sw)) {
624
+                return $m;
625
+            }
626
+        }
627
+    }
628
+
629
+    return false;
630 630
 }
631 631
 
632 632
 /**
@@ -642,16 +642,16 @@  discard block
 block discarded – undo
642 642
  *     est remplacée par son code.
643 643
  **/
644 644
 function remplace_sous_requete($w, $sousrequete) {
645
-	if (is_array($w)) {
646
-		if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
647
-			return $sousrequete;
648
-		}
649
-		foreach ($w as $k => $sw) {
650
-			$w[$k] = remplace_sous_requete($sw, $sousrequete);
651
-		}
652
-	}
653
-
654
-	return $w;
645
+    if (is_array($w)) {
646
+        if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
647
+            return $sousrequete;
648
+        }
649
+        foreach ($w as $k => $sw) {
650
+            $w[$k] = remplace_sous_requete($sw, $sousrequete);
651
+        }
652
+    }
653
+
654
+    return $w;
655 655
 }
656 656
 
657 657
 /**
@@ -665,17 +665,17 @@  discard block
 block discarded – undo
665 665
  *     - Conditions avec des sous requĂªtes
666 666
  **/
667 667
 function trouver_sous_requetes($where) {
668
-	$where_simples = [];
669
-	$where_sous = [];
670
-	foreach ($where as $k => $w) {
671
-		if (match_self($w)) {
672
-			$where_sous[$k] = $w;
673
-		} else {
674
-			$where_simples[$k] = $w;
675
-		}
676
-	}
677
-
678
-	return [$where_simples, $where_sous];
668
+    $where_simples = [];
669
+    $where_sous = [];
670
+    foreach ($where as $k => $w) {
671
+        if (match_self($w)) {
672
+            $where_sous[$k] = $w;
673
+        } else {
674
+            $where_simples[$k] = $w;
675
+        }
676
+    }
677
+
678
+    return [$where_simples, $where_sous];
679 679
 }
680 680
 
681 681
 
@@ -701,292 +701,292 @@  discard block
 block discarded – undo
701 701
  * @return resource
702 702
  */
703 703
 function calculer_select(
704
-	$select = [],
705
-	$from = [],
706
-	$from_type = [],
707
-	$where = [],
708
-	$join = [],
709
-	$groupby = [],
710
-	$orderby = [],
711
-	$limit = '',
712
-	$having = [],
713
-	$table = '',
714
-	$id = '',
715
-	$serveur = '',
716
-	$requeter = true
704
+    $select = [],
705
+    $from = [],
706
+    $from_type = [],
707
+    $where = [],
708
+    $join = [],
709
+    $groupby = [],
710
+    $orderby = [],
711
+    $limit = '',
712
+    $having = [],
713
+    $table = '',
714
+    $id = '',
715
+    $serveur = '',
716
+    $requeter = true
717 717
 ) {
718 718
 
719
-	// retirer les criteres vides:
720
-	// {X ?} avec X absent de l'URL
721
-	// {par #ENV{X}} avec X absent de l'URL
722
-	// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
723
-	$menage = false;
724
-	foreach ($where as $k => $v) {
725
-		if (is_array($v) and count($v)) {
726
-			if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
727
-				$op = false;
728
-			} elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
729
-				$op = false;
730
-			} else {
731
-				$op = $v[0] ?: $v;
732
-			}
733
-		} else {
734
-			$op = $v;
735
-		}
736
-		if ((!$op) or ($op == 1) or ($op == '0=0')) {
737
-			unset($where[$k]);
738
-			$menage = true;
739
-		}
740
-	}
741
-
742
-	// evacuer les eventuels groupby vide issus d'un calcul dynamique
743
-	$groupby = array_diff($groupby, ['']);
744
-
745
-	// remplacer les sous requetes recursives au calcul
746
-	[$where_simples, $where_sous] = trouver_sous_requetes($where);
747
-	foreach ($where_sous as $k => $w) {
748
-		$menage = true;
749
-		// on recupere la sous requete
750
-		$sous = match_self($w);
751
-		if ($sous[0] == 'SELF') {
752
-			// c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
753
-			array_push($where_simples, $sous[2]);
754
-			$wheresub = [
755
-				$sous[2],
756
-				'0=0'
757
-			]; // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
758
-			$jsub = $join;
759
-			// trouver les jointures utiles a
760
-			// reinjecter dans le where de la sous requete les conditions supplementaires des jointures qui y sont mentionnees
761
-			// ie L1.objet='article'
762
-			// on construit le where une fois, puis on ajoute les where complentaires si besoin, et on reconstruit le where en fonction
763
-			$i = 0;
764
-			do {
765
-				$where[$k] = remplace_sous_requete($w, '(' . calculer_select(
766
-					[$sous[1] . ' AS id'],
767
-					$from,
768
-					$from_type,
769
-					$wheresub,
770
-					$jsub,
771
-					[],
772
-					[],
773
-					'',
774
-					$having,
775
-					$table,
776
-					$id,
777
-					$serveur,
778
-					false
779
-				) . ')');
780
-				if (!$i) {
781
-					$i = 1;
782
-					$wherestring = calculer_where_to_string($where[$k]);
783
-					foreach ($join as $cle => $wj) {
784
-						if (
785
-							(is_countable($wj) ? count($wj) : 0) == 4
786
-							and str_contains($wherestring, (string) "{$cle}.")
787
-						) {
788
-							$i = 0;
789
-							$wheresub[] = $wj[3];
790
-							unset($jsub[$cle][3]);
791
-						}
792
-					}
793
-				}
794
-			} while ($i++ < 1);
795
-		}
796
-		if ($sous[0] == 'SUBSELECT') {
797
-			// c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
798
-			array_push($where_simples, $sous[3]); // est-ce utile dans ce cas ?
799
-			$where[$k] = remplace_sous_requete($w, '(' . calculer_select(
800
-				$sous[1], # select
801
-				$sous[2], #from
802
-				[], #from_type
803
-				$sous[3] ? (is_array($sous[3]) ? $sous[3] : [$sous[3]]) : [],
804
-				#where, qui peut etre de la forme string comme dans sql_select
805
-					[], #join
806
-				$sous[4] ?: [], #groupby
807
-				$sous[5] ?: [], #orderby
808
-				$sous[6], #limit
809
-				$sous[7] ?: [], #having
810
-				$table,
811
-				$id,
812
-				$serveur,
813
-				false
814
-			) . ')');
815
-		}
816
-		array_pop($where_simples);
817
-	}
818
-
819
-	foreach ($having as $k => $v) {
820
-		if ((!$v) or ($v == 1) or ($v == '0=0')) {
821
-			unset($having[$k]);
822
-		}
823
-	}
824
-
825
-	// Installer les jointures.
826
-	// Retirer celles seulement utiles aux criteres finalement absents mais
827
-	// parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
828
-	// si elle est seulement utile a Ln+1 elle meme inutile
829
-
830
-	$afrom = [];
831
-	$equiv = [];
832
-	$k = count($join);
833
-	foreach (array_reverse($join, true) as $cledef => $j) {
834
-		$cle = $cledef;
835
-		// le format de join est :
836
-		// array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
837
-		$join[$cle] = array_values($join[$cle]); // recalculer les cles car des unset ont pu perturber
838
-		if (count($join[$cle]) == 2) {
839
-			$join[$cle][] = $join[$cle][1];
840
-		}
841
-		if ((is_array($join[$cle]) || $join[$cle] instanceof \Countable ? count($join[$cle]) : 0) == 3) {
842
-			$join[$cle][] = '';
843
-		}
844
-		[$t, $c, $carr, $and] = $join[$cle];
845
-		// si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
846
-		// pour compat avec ancienne convention
847
-		if (is_numeric($cle)) {
848
-			$cle = "L$k";
849
-		}
850
-		$cle_where_lie = "JOIN-$cle";
851
-		if (
852
-			!$menage
853
-			or isset($afrom[$cle])
854
-			or calculer_jointnul($cle, $select)
855
-			or calculer_jointnul($cle, array_diff_key($join, [$cle => $join[$cle]]))
856
-			or calculer_jointnul($cle, $having)
857
-			or calculer_jointnul($cle, array_diff_key($where_simples, [$cle_where_lie => '']))
858
-		) {
859
-			// corriger les references non explicites dans select
860
-			// ou groupby
861
-			foreach ($select as $i => $s) {
862
-				if ($s == $c) {
863
-					$select[$i] = "$cle.$c AS $c";
864
-					break;
865
-				}
866
-			}
867
-			foreach ($groupby as $i => $g) {
868
-				if ($g == $c) {
869
-					$groupby[$i] = "$cle.$c";
870
-					break;
871
-				}
872
-			}
873
-			// on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
874
-			// sans recours a preg_match
875
-			// un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
876
-			$afrom[$t][$cle] = [
877
-				"\n" .
878
-				($from_type[$cle] ?? 'INNER') . ' JOIN',
879
-				$from[$cle],
880
-				"AS $cle",
881
-				'ON (',
882
-				"$cle.$c",
883
-				'=',
884
-				"$t.$carr",
885
-				($and ? 'AND ' . $and : '') .
886
-				')'
887
-			];
888
-			if (isset($afrom[$cle])) {
889
-				$afrom[$t] = $afrom[$t] + $afrom[$cle];
890
-				unset($afrom[$cle]);
891
-			}
892
-			$equiv[] = $carr;
893
-		} else {
894
-			unset($join[$cledef]);
895
-			if (isset($where_simples[$cle_where_lie])) {
896
-				unset($where_simples[$cle_where_lie]);
897
-				unset($where[$cle_where_lie]);
898
-			}
899
-		}
900
-		unset($from[$cle]);
901
-		$k--;
902
-	}
903
-
904
-	if (count($afrom)) {
905
-		// Regarder si la table principale ne sert finalement a rien comme dans
906
-		//<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
907
-		//<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
908
-		//<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
909
-		// ou dans
910
-		//<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
911
-		// qui comporte plusieurs jointures
912
-		// ou dans
913
-		// <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
914
-		// <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
915
-		// penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
916
-		// <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
917
-		// penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
918
-		// <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
919
-
920
-		$t = key($from);
921
-		$c = current($from);
922
-		reset($from);
923
-		$e = '/\b(' . "$t\\." . join('|' . $t . '\.', $equiv) . ')\b/';
924
-		if (
925
-			!(strpos($t, ' ') or // jointure des le depart cf boucle_doc
926
-				calculer_jointnul($t, $select, $e) or
927
-				calculer_jointnul($t, $join, $e) or
928
-				calculer_jointnul($t, $where, $e) or
929
-				calculer_jointnul($t, $orderby, $e) or
930
-				calculer_jointnul($t, $groupby, $e) or
931
-				calculer_jointnul($t, $having, $e))
932
-			&& count($afrom[$t])
933
-		) {
934
-			$nfrom = reset($afrom[$t]);
935
-			$nt = array_key_first($afrom[$t]);
936
-			unset($from[$t]);
937
-			$from[$nt] = $nfrom[1];
938
-			unset($afrom[$t][$nt]);
939
-			$afrom[$nt] = $afrom[$t];
940
-			unset($afrom[$t]);
941
-			$e = '/\b' . preg_quote($nfrom[6]) . '\b/';
942
-			$t = $nfrom[4];
943
-			$alias = '';
944
-			// verifier que les deux cles sont homonymes, sinon installer un alias dans le select
945
-			$oldcle = explode('.', $nfrom[6]);
946
-			$oldcle = end($oldcle);
947
-			$newcle = explode('.', $nfrom[4]);
948
-			$newcle = end($newcle);
949
-			if ($newcle != $oldcle) {
950
-				// si l'ancienne cle etait deja dans le select avec un AS
951
-				// reprendre simplement ce AS
952
-				$as = '/\b' . preg_quote($nfrom[6]) . '\s+(AS\s+\w+)\b/';
953
-				if (preg_match($as, implode(',', $select), $m)) {
954
-					$alias = '';
955
-				} else {
956
-					$alias = ', ' . $nfrom[4] . " AS $oldcle";
957
-				}
958
-			}
959
-			$select = remplacer_jointnul($t . $alias, $select, $e);
960
-			$join = remplacer_jointnul($t, $join, $e);
961
-			$where = remplacer_jointnul($t, $where, $e);
962
-			$having = remplacer_jointnul($t, $having, $e);
963
-			$groupby = remplacer_jointnul($t, $groupby, $e);
964
-			$orderby = remplacer_jointnul($t, $orderby, $e);
965
-		}
966
-		$from = reinjecte_joint($afrom, $from);
967
-	}
968
-	if (empty($GLOBALS['debug']) or !is_array($GLOBALS['debug'])) {
969
-		$wasdebug = empty($GLOBALS['debug']) ? false : $GLOBALS['debug'];
970
-		$GLOBALS['debug'] = [];
971
-		if ($wasdebug) {
972
-			$GLOBALS['debug']['debug'] = true;
973
-		}
974
-	}
975
-	$GLOBALS['debug']['aucasou'] = [$table, $id, $serveur, $requeter];
976
-	$r = sql_select(
977
-		$select,
978
-		$from,
979
-		$where,
980
-		$groupby,
981
-		array_filter($orderby),
982
-		$limit,
983
-		$having,
984
-		$serveur,
985
-		$requeter
986
-	);
987
-	unset($GLOBALS['debug']['aucasou']);
988
-
989
-	return $r;
719
+    // retirer les criteres vides:
720
+    // {X ?} avec X absent de l'URL
721
+    // {par #ENV{X}} avec X absent de l'URL
722
+    // IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
723
+    $menage = false;
724
+    foreach ($where as $k => $v) {
725
+        if (is_array($v) and count($v)) {
726
+            if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
727
+                $op = false;
728
+            } elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
729
+                $op = false;
730
+            } else {
731
+                $op = $v[0] ?: $v;
732
+            }
733
+        } else {
734
+            $op = $v;
735
+        }
736
+        if ((!$op) or ($op == 1) or ($op == '0=0')) {
737
+            unset($where[$k]);
738
+            $menage = true;
739
+        }
740
+    }
741
+
742
+    // evacuer les eventuels groupby vide issus d'un calcul dynamique
743
+    $groupby = array_diff($groupby, ['']);
744
+
745
+    // remplacer les sous requetes recursives au calcul
746
+    [$where_simples, $where_sous] = trouver_sous_requetes($where);
747
+    foreach ($where_sous as $k => $w) {
748
+        $menage = true;
749
+        // on recupere la sous requete
750
+        $sous = match_self($w);
751
+        if ($sous[0] == 'SELF') {
752
+            // c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
753
+            array_push($where_simples, $sous[2]);
754
+            $wheresub = [
755
+                $sous[2],
756
+                '0=0'
757
+            ]; // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
758
+            $jsub = $join;
759
+            // trouver les jointures utiles a
760
+            // reinjecter dans le where de la sous requete les conditions supplementaires des jointures qui y sont mentionnees
761
+            // ie L1.objet='article'
762
+            // on construit le where une fois, puis on ajoute les where complentaires si besoin, et on reconstruit le where en fonction
763
+            $i = 0;
764
+            do {
765
+                $where[$k] = remplace_sous_requete($w, '(' . calculer_select(
766
+                    [$sous[1] . ' AS id'],
767
+                    $from,
768
+                    $from_type,
769
+                    $wheresub,
770
+                    $jsub,
771
+                    [],
772
+                    [],
773
+                    '',
774
+                    $having,
775
+                    $table,
776
+                    $id,
777
+                    $serveur,
778
+                    false
779
+                ) . ')');
780
+                if (!$i) {
781
+                    $i = 1;
782
+                    $wherestring = calculer_where_to_string($where[$k]);
783
+                    foreach ($join as $cle => $wj) {
784
+                        if (
785
+                            (is_countable($wj) ? count($wj) : 0) == 4
786
+                            and str_contains($wherestring, (string) "{$cle}.")
787
+                        ) {
788
+                            $i = 0;
789
+                            $wheresub[] = $wj[3];
790
+                            unset($jsub[$cle][3]);
791
+                        }
792
+                    }
793
+                }
794
+            } while ($i++ < 1);
795
+        }
796
+        if ($sous[0] == 'SUBSELECT') {
797
+            // c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
798
+            array_push($where_simples, $sous[3]); // est-ce utile dans ce cas ?
799
+            $where[$k] = remplace_sous_requete($w, '(' . calculer_select(
800
+                $sous[1], # select
801
+                $sous[2], #from
802
+                [], #from_type
803
+                $sous[3] ? (is_array($sous[3]) ? $sous[3] : [$sous[3]]) : [],
804
+                #where, qui peut etre de la forme string comme dans sql_select
805
+                    [], #join
806
+                $sous[4] ?: [], #groupby
807
+                $sous[5] ?: [], #orderby
808
+                $sous[6], #limit
809
+                $sous[7] ?: [], #having
810
+                $table,
811
+                $id,
812
+                $serveur,
813
+                false
814
+            ) . ')');
815
+        }
816
+        array_pop($where_simples);
817
+    }
818
+
819
+    foreach ($having as $k => $v) {
820
+        if ((!$v) or ($v == 1) or ($v == '0=0')) {
821
+            unset($having[$k]);
822
+        }
823
+    }
824
+
825
+    // Installer les jointures.
826
+    // Retirer celles seulement utiles aux criteres finalement absents mais
827
+    // parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
828
+    // si elle est seulement utile a Ln+1 elle meme inutile
829
+
830
+    $afrom = [];
831
+    $equiv = [];
832
+    $k = count($join);
833
+    foreach (array_reverse($join, true) as $cledef => $j) {
834
+        $cle = $cledef;
835
+        // le format de join est :
836
+        // array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
837
+        $join[$cle] = array_values($join[$cle]); // recalculer les cles car des unset ont pu perturber
838
+        if (count($join[$cle]) == 2) {
839
+            $join[$cle][] = $join[$cle][1];
840
+        }
841
+        if ((is_array($join[$cle]) || $join[$cle] instanceof \Countable ? count($join[$cle]) : 0) == 3) {
842
+            $join[$cle][] = '';
843
+        }
844
+        [$t, $c, $carr, $and] = $join[$cle];
845
+        // si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
846
+        // pour compat avec ancienne convention
847
+        if (is_numeric($cle)) {
848
+            $cle = "L$k";
849
+        }
850
+        $cle_where_lie = "JOIN-$cle";
851
+        if (
852
+            !$menage
853
+            or isset($afrom[$cle])
854
+            or calculer_jointnul($cle, $select)
855
+            or calculer_jointnul($cle, array_diff_key($join, [$cle => $join[$cle]]))
856
+            or calculer_jointnul($cle, $having)
857
+            or calculer_jointnul($cle, array_diff_key($where_simples, [$cle_where_lie => '']))
858
+        ) {
859
+            // corriger les references non explicites dans select
860
+            // ou groupby
861
+            foreach ($select as $i => $s) {
862
+                if ($s == $c) {
863
+                    $select[$i] = "$cle.$c AS $c";
864
+                    break;
865
+                }
866
+            }
867
+            foreach ($groupby as $i => $g) {
868
+                if ($g == $c) {
869
+                    $groupby[$i] = "$cle.$c";
870
+                    break;
871
+                }
872
+            }
873
+            // on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
874
+            // sans recours a preg_match
875
+            // un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
876
+            $afrom[$t][$cle] = [
877
+                "\n" .
878
+                ($from_type[$cle] ?? 'INNER') . ' JOIN',
879
+                $from[$cle],
880
+                "AS $cle",
881
+                'ON (',
882
+                "$cle.$c",
883
+                '=',
884
+                "$t.$carr",
885
+                ($and ? 'AND ' . $and : '') .
886
+                ')'
887
+            ];
888
+            if (isset($afrom[$cle])) {
889
+                $afrom[$t] = $afrom[$t] + $afrom[$cle];
890
+                unset($afrom[$cle]);
891
+            }
892
+            $equiv[] = $carr;
893
+        } else {
894
+            unset($join[$cledef]);
895
+            if (isset($where_simples[$cle_where_lie])) {
896
+                unset($where_simples[$cle_where_lie]);
897
+                unset($where[$cle_where_lie]);
898
+            }
899
+        }
900
+        unset($from[$cle]);
901
+        $k--;
902
+    }
903
+
904
+    if (count($afrom)) {
905
+        // Regarder si la table principale ne sert finalement a rien comme dans
906
+        //<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
907
+        //<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
908
+        //<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
909
+        // ou dans
910
+        //<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
911
+        // qui comporte plusieurs jointures
912
+        // ou dans
913
+        // <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
914
+        // <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
915
+        // penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
916
+        // <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
917
+        // penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
918
+        // <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
919
+
920
+        $t = key($from);
921
+        $c = current($from);
922
+        reset($from);
923
+        $e = '/\b(' . "$t\\." . join('|' . $t . '\.', $equiv) . ')\b/';
924
+        if (
925
+            !(strpos($t, ' ') or // jointure des le depart cf boucle_doc
926
+                calculer_jointnul($t, $select, $e) or
927
+                calculer_jointnul($t, $join, $e) or
928
+                calculer_jointnul($t, $where, $e) or
929
+                calculer_jointnul($t, $orderby, $e) or
930
+                calculer_jointnul($t, $groupby, $e) or
931
+                calculer_jointnul($t, $having, $e))
932
+            && count($afrom[$t])
933
+        ) {
934
+            $nfrom = reset($afrom[$t]);
935
+            $nt = array_key_first($afrom[$t]);
936
+            unset($from[$t]);
937
+            $from[$nt] = $nfrom[1];
938
+            unset($afrom[$t][$nt]);
939
+            $afrom[$nt] = $afrom[$t];
940
+            unset($afrom[$t]);
941
+            $e = '/\b' . preg_quote($nfrom[6]) . '\b/';
942
+            $t = $nfrom[4];
943
+            $alias = '';
944
+            // verifier que les deux cles sont homonymes, sinon installer un alias dans le select
945
+            $oldcle = explode('.', $nfrom[6]);
946
+            $oldcle = end($oldcle);
947
+            $newcle = explode('.', $nfrom[4]);
948
+            $newcle = end($newcle);
949
+            if ($newcle != $oldcle) {
950
+                // si l'ancienne cle etait deja dans le select avec un AS
951
+                // reprendre simplement ce AS
952
+                $as = '/\b' . preg_quote($nfrom[6]) . '\s+(AS\s+\w+)\b/';
953
+                if (preg_match($as, implode(',', $select), $m)) {
954
+                    $alias = '';
955
+                } else {
956
+                    $alias = ', ' . $nfrom[4] . " AS $oldcle";
957
+                }
958
+            }
959
+            $select = remplacer_jointnul($t . $alias, $select, $e);
960
+            $join = remplacer_jointnul($t, $join, $e);
961
+            $where = remplacer_jointnul($t, $where, $e);
962
+            $having = remplacer_jointnul($t, $having, $e);
963
+            $groupby = remplacer_jointnul($t, $groupby, $e);
964
+            $orderby = remplacer_jointnul($t, $orderby, $e);
965
+        }
966
+        $from = reinjecte_joint($afrom, $from);
967
+    }
968
+    if (empty($GLOBALS['debug']) or !is_array($GLOBALS['debug'])) {
969
+        $wasdebug = empty($GLOBALS['debug']) ? false : $GLOBALS['debug'];
970
+        $GLOBALS['debug'] = [];
971
+        if ($wasdebug) {
972
+            $GLOBALS['debug']['debug'] = true;
973
+        }
974
+    }
975
+    $GLOBALS['debug']['aucasou'] = [$table, $id, $serveur, $requeter];
976
+    $r = sql_select(
977
+        $select,
978
+        $from,
979
+        $where,
980
+        $groupby,
981
+        array_filter($orderby),
982
+        $limit,
983
+        $having,
984
+        $serveur,
985
+        $requeter
986
+    );
987
+    unset($GLOBALS['debug']['aucasou']);
988
+
989
+    return $r;
990 990
 }
991 991
 
992 992
 /**
@@ -997,79 +997,79 @@  discard block
 block discarded – undo
997 997
  * @return string
998 998
  */
999 999
 function calculer_where_to_string($v, $join = 'AND') {
1000
-	if (empty($v)) {
1001
-		return '';
1002
-	}
1003
-
1004
-	if (!is_array($v)) {
1005
-		return $v;
1006
-	} else {
1007
-		$exp = '';
1008
-		if (strtoupper($join) === 'AND') {
1009
-			return $exp . join(" $join ", array_map('calculer_where_to_string', $v));
1010
-		} else {
1011
-			return $exp . join($join, $v);
1012
-		}
1013
-	}
1000
+    if (empty($v)) {
1001
+        return '';
1002
+    }
1003
+
1004
+    if (!is_array($v)) {
1005
+        return $v;
1006
+    } else {
1007
+        $exp = '';
1008
+        if (strtoupper($join) === 'AND') {
1009
+            return $exp . join(" $join ", array_map('calculer_where_to_string', $v));
1010
+        } else {
1011
+            return $exp . join($join, $v);
1012
+        }
1013
+    }
1014 1014
 }
1015 1015
 
1016 1016
 
1017 1017
 //condition suffisante (mais non necessaire) pour qu'une table soit utile
1018 1018
 
1019 1019
 function calculer_jointnul($cle, $exp, $equiv = '') {
1020
-	if (!is_array($exp)) {
1021
-		if ($equiv) {
1022
-			$exp = preg_replace($equiv, '', $exp);
1023
-		}
1024
-
1025
-		return preg_match("/\\b$cle\\./", $exp);
1026
-	} else {
1027
-		foreach ($exp as $v) {
1028
-			if (calculer_jointnul($cle, $v, $equiv)) {
1029
-				return true;
1030
-			}
1031
-		}
1032
-
1033
-		return false;
1034
-	}
1020
+    if (!is_array($exp)) {
1021
+        if ($equiv) {
1022
+            $exp = preg_replace($equiv, '', $exp);
1023
+        }
1024
+
1025
+        return preg_match("/\\b$cle\\./", $exp);
1026
+    } else {
1027
+        foreach ($exp as $v) {
1028
+            if (calculer_jointnul($cle, $v, $equiv)) {
1029
+                return true;
1030
+            }
1031
+        }
1032
+
1033
+        return false;
1034
+    }
1035 1035
 }
1036 1036
 
1037 1037
 function reinjecte_joint($afrom, $from) {
1038
-	$from_synth = [];
1039
-	foreach ($from as $k => $v) {
1040
-		$from_synth[$k] = $from[$k];
1041
-		if (isset($afrom[$k])) {
1042
-			foreach ($afrom[$k] as $kk => $vv) {
1043
-				$afrom[$k][$kk] = implode(' ', $afrom[$k][$kk]);
1044
-			}
1045
-			$from_synth["$k@"] = implode(' ', $afrom[$k]);
1046
-			unset($afrom[$k]);
1047
-		}
1048
-	}
1049
-
1050
-	return $from_synth;
1038
+    $from_synth = [];
1039
+    foreach ($from as $k => $v) {
1040
+        $from_synth[$k] = $from[$k];
1041
+        if (isset($afrom[$k])) {
1042
+            foreach ($afrom[$k] as $kk => $vv) {
1043
+                $afrom[$k][$kk] = implode(' ', $afrom[$k][$kk]);
1044
+            }
1045
+            $from_synth["$k@"] = implode(' ', $afrom[$k]);
1046
+            unset($afrom[$k]);
1047
+        }
1048
+    }
1049
+
1050
+    return $from_synth;
1051 1051
 }
1052 1052
 
1053 1053
 function remplacer_jointnul($cle, $exp, $equiv = '') {
1054
-	if (!is_array($exp)) {
1055
-		return preg_replace($equiv, $cle, $exp);
1056
-	} else {
1057
-		foreach ($exp as $k => $v) {
1058
-			$exp[$k] = remplacer_jointnul($cle, $v, $equiv);
1059
-		}
1060
-
1061
-		return $exp;
1062
-	}
1054
+    if (!is_array($exp)) {
1055
+        return preg_replace($equiv, $cle, $exp);
1056
+    } else {
1057
+        foreach ($exp as $k => $v) {
1058
+            $exp[$k] = remplacer_jointnul($cle, $v, $equiv);
1059
+        }
1060
+
1061
+        return $exp;
1062
+    }
1063 1063
 }
1064 1064
 
1065 1065
 // calcul du nom du squelette
1066 1066
 function calculer_nom_fonction_squel($skel, $mime_type = 'html', string $connect = '') {
1067
-	// ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
1068
-	if ($l = strlen(_DIR_RACINE) and strncmp($skel, _DIR_RACINE, $l) == 0) {
1069
-		$skel = substr($skel, strlen(_DIR_RACINE));
1070
-	}
1071
-
1072
-	return $mime_type
1073
-	. (!$connect ? '' : preg_replace('/\W/', '_', $connect)) . '_'
1074
-	. md5($GLOBALS['spip_version_code'] . ' * ' . $skel . (isset($GLOBALS['marqueur_skel']) ? '*' . $GLOBALS['marqueur_skel'] : ''));
1067
+    // ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
1068
+    if ($l = strlen(_DIR_RACINE) and strncmp($skel, _DIR_RACINE, $l) == 0) {
1069
+        $skel = substr($skel, strlen(_DIR_RACINE));
1070
+    }
1071
+
1072
+    return $mime_type
1073
+    . (!$connect ? '' : preg_replace('/\W/', '_', $connect)) . '_'
1074
+    . md5($GLOBALS['spip_version_code'] . ' * ' . $skel . (isset($GLOBALS['marqueur_skel']) ? '*' . $GLOBALS['marqueur_skel'] : ''));
1075 1075
 }
Please login to merge, or discard this patch.
ecrire/public/styliser_par_z.php 1 patch
Indentation   +319 added lines, -319 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
  * @package SPIP\Core\Public\Styliser
20 20
  **/
21 21
 if (!defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 /**
@@ -29,193 +29,193 @@  discard block
 block discarded – undo
29 29
  * @return array Données modifiées du pipeline
30 30
  */
31 31
 function public_styliser_par_z_dist($flux) {
32
-	static $prefix_path = null;
33
-	static $prefix_length;
34
-	static $z_blocs;
35
-	static $apl_constant;
36
-	static $page;
37
-	static $disponible = [];
38
-	static $echafauder;
39
-	static $prepend = '';
40
-
41
-	if (!isset($prefix_path)) {
42
-		$z_blocs = z_blocs(test_espace_prive());
43
-		if (test_espace_prive()) {
44
-			$prefix_path = 'prive/squelettes/';
45
-			$prefix_length = strlen($prefix_path);
46
-			$apl_constant = '_ECRIRE_AJAX_PARALLEL_LOAD';
47
-			$page = 'exec';
48
-			$echafauder = charger_fonction('echafauder', 'prive', true);
49
-			define('_ZCORE_EXCLURE_PATH', '');
50
-		} else {
51
-			$prefix_path = '';
52
-			$prefix_length = 0;
53
-			$apl_constant = '_Z_AJAX_PARALLEL_LOAD';
54
-			$page = _SPIP_PAGE;
55
-			$echafauder = charger_fonction('echafauder', 'public', true);
56
-			define('_ZCORE_EXCLURE_PATH', '\bprive|\bsquelettes-dist' . (defined('_DIR_PLUGIN_DIST') ? '|\b' . rtrim(
57
-				_DIR_PLUGIN_DIST,
58
-				'/'
59
-			) : ''));
60
-		}
61
-		$prepend = (defined('_Z_PREPEND_PATH') ? _Z_PREPEND_PATH : '');
62
-	}
63
-	$z_contenu = reset($z_blocs); // contenu par defaut
64
-
65
-	$fond = $flux['args']['fond'];
66
-
67
-	if ($prepend or strncmp($fond, $prefix_path, $prefix_length) == 0) {
68
-		$fond = substr($fond, $prefix_length);
69
-		$squelette = $flux['data'];
70
-		$ext = $flux['args']['ext'];
71
-		// Ajax Parallel loading : ne pas calculer le bloc, mais renvoyer un js qui le loadera en ajax
72
-		if (
73
-			defined('_Z_AJAX_PARALLEL_LOAD_OK')
74
-			and $dir = explode('/', $fond)
75
-			and count($dir) == 2 // pas un sous repertoire
76
-			and $dir = reset($dir)
77
-			and in_array($dir, $z_blocs) // verifier deja qu'on est dans un bloc Z
78
-			and defined($apl_constant)
79
-			and in_array($dir, explode(',', constant($apl_constant))) // et dans un demande en APL
80
-			and $pipe = z_trouver_bloc($prefix_path . $prepend, $dir, 'z_apl', $ext) // et qui contient le squelette APL
81
-		) {
82
-			$flux['data'] = $pipe;
83
-
84
-			return $flux;
85
-		}
86
-
87
-		// surcharger aussi les squelettes venant de squelettes-dist/
88
-		if ($squelette and !z_fond_valide($squelette)) {
89
-			$squelette = '';
90
-			$echafauder = '';
91
-		}
92
-		if ($prepend) {
93
-			$squelette = substr(find_in_path($prefix_path . $prepend . "$fond.$ext"), 0, -strlen(".$ext"));
94
-			if ($squelette) {
95
-				$flux['data'] = $squelette;
96
-			}
97
-		}
98
-
99
-		// gerer les squelettes non trouves
100
-		// -> router vers les /dist.html
101
-		// ou scaffolding ou page automatique les contenus
102
-		if (!$squelette) {
103
-			// si on est sur un ?page=XX non trouve
104
-			if (
105
-				(isset($flux['args']['contexte'][$page])
106
-					and $flux['args']['contexte'][$page] == $fond)
107
-				or (isset($flux['args']['contexte']['type-page'])
108
-					and $flux['args']['contexte']['type-page'] == $fond)
109
-				or ($fond == 'sommaire'
110
-					and (!isset($flux['args']['contexte'][$page]) or !$flux['args']['contexte'][$page]))
111
-			) {
112
-				// si on est sur un ?page=XX non trouve
113
-				// se brancher sur contenu/xx si il existe
114
-				// ou si c'est un objet spip, associe a une table, utiliser le fond homonyme
115
-				if (!isset($disponible[$fond])) {
116
-					$disponible[$fond] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $fond, $ext, $echafauder);
117
-				}
118
-
119
-				if ($disponible[$fond]) {
120
-					$flux['data'] = substr(find_in_path($prefix_path . "page.$ext"), 0, -strlen(".$ext"));
121
-				}
122
-			}
123
-
124
-			// echafaudage :
125
-			// si c'est un fond de contenu d'un objet en base
126
-			// generer un fond automatique a la volee pour les webmestres
127
-			elseif (strncmp($fond, "$z_contenu/", strlen($z_contenu) + 1) == 0) {
128
-				$type = substr($fond, strlen($z_contenu) + 1);
129
-				if (($type == 'page') and isset($flux['args']['contexte'][$page])) {
130
-					$type = $flux['args']['contexte'][$page];
131
-				}
132
-				if (!isset($disponible[$type])) {
133
-					$disponible[$type] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $type, $ext, $echafauder);
134
-				}
135
-				if (is_string($disponible[$type])) {
136
-					$flux['data'] = $disponible[$type];
137
-				} elseif (
138
-					$echafauder
139
-					and include_spip('inc/autoriser')
140
-					and isset($GLOBALS['visiteur_session']['statut']) // performance
141
-					and autoriser('echafauder', $type)
142
-					and $is = $disponible[$type]
143
-					and is_array($is)
144
-				) {
145
-					$flux['data'] = $echafauder($type, $is[0], $is[1], $is[2], $ext);
146
-				} else {
147
-					$flux['data'] = ($disponible['404'] = z_contenu_disponible(
148
-						$prefix_path . $prepend,
149
-						$z_contenu,
150
-						'404',
151
-						$ext,
152
-						$echafauder
153
-					));
154
-				}
155
-			}
156
-
157
-			// sinon, si on demande un fond non trouve dans un des autres blocs
158
-			// et si il y a bien un contenu correspondant ou echafaudable
159
-			// se rabbatre sur le dist.html du bloc concerne
160
-			else {
161
-				if (
162
-					$dir = explode('/', $fond)
163
-					and $dir = reset($dir)
164
-					and $dir !== $z_contenu
165
-					and in_array($dir, $z_blocs)
166
-				) {
167
-					$type = substr($fond, strlen("$dir/"));
168
-					if (($type == 'page') and isset($flux['args']['contexte'][$page])) {
169
-						$type = $flux['args']['contexte'][$page];
170
-					}
171
-					if ($type !== 'page' and !isset($disponible[$type])) {
172
-						$disponible[$type] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $type, $ext, $echafauder);
173
-					}
174
-					if ($type == 'page' or $disponible[$type]) {
175
-						$flux['data'] = z_trouver_bloc($prefix_path . $prepend, $dir, 'dist', $ext);
176
-					}
177
-				}
178
-			}
179
-			$squelette = $flux['data'];
180
-		}
181
-		// layout specifiques par type et compositions :
182
-		// body-article.html
183
-		// body-sommaire.html
184
-		// pour des raisons de perfo, les declinaisons doivent etre dans le
185
-		// meme dossier que body.html
186
-		if ($fond == 'body' and substr($squelette, -strlen($fond)) == $fond) {
187
-			if (
188
-				isset($flux['args']['contexte']['type-page'])
189
-				and (
190
-					(isset($flux['args']['contexte']['composition'])
191
-						and file_exists(($f = $squelette . '-' . $flux['args']['contexte']['type-page'] . '-' . $flux['args']['contexte']['composition']) . ".$ext"))
192
-					or
193
-					file_exists(($f = $squelette . '-' . $flux['args']['contexte']['type-page']) . ".$ext")
194
-				)
195
-			) {
196
-				$flux['data'] = $f;
197
-			}
198
-		} elseif (
199
-			$fond == 'structure'
200
-			and z_sanitize_var_zajax()
201
-			and $f = find_in_path($prefix_path . $prepend . 'ajax' . ".$ext")
202
-		) {
203
-			$flux['data'] = substr($f, 0, -strlen(".$ext"));
204
-		} // chercher le fond correspondant a la composition
205
-		elseif (
206
-			isset($flux['args']['contexte']['composition'])
207
-			and (basename($fond) == 'page' or ($squelette and substr($squelette, -strlen($fond)) == $fond))
208
-			and $dir = substr($fond, $prefix_length)
209
-			and $dir = explode('/', $dir)
210
-			and $dir = reset($dir)
211
-			and in_array($dir, $z_blocs)
212
-			and $f = find_in_path($prefix_path . $prepend . $fond . '-' . $flux['args']['contexte']['composition'] . ".$ext")
213
-		) {
214
-			$flux['data'] = substr($f, 0, -strlen(".$ext"));
215
-		}
216
-	}
217
-
218
-	return $flux;
32
+    static $prefix_path = null;
33
+    static $prefix_length;
34
+    static $z_blocs;
35
+    static $apl_constant;
36
+    static $page;
37
+    static $disponible = [];
38
+    static $echafauder;
39
+    static $prepend = '';
40
+
41
+    if (!isset($prefix_path)) {
42
+        $z_blocs = z_blocs(test_espace_prive());
43
+        if (test_espace_prive()) {
44
+            $prefix_path = 'prive/squelettes/';
45
+            $prefix_length = strlen($prefix_path);
46
+            $apl_constant = '_ECRIRE_AJAX_PARALLEL_LOAD';
47
+            $page = 'exec';
48
+            $echafauder = charger_fonction('echafauder', 'prive', true);
49
+            define('_ZCORE_EXCLURE_PATH', '');
50
+        } else {
51
+            $prefix_path = '';
52
+            $prefix_length = 0;
53
+            $apl_constant = '_Z_AJAX_PARALLEL_LOAD';
54
+            $page = _SPIP_PAGE;
55
+            $echafauder = charger_fonction('echafauder', 'public', true);
56
+            define('_ZCORE_EXCLURE_PATH', '\bprive|\bsquelettes-dist' . (defined('_DIR_PLUGIN_DIST') ? '|\b' . rtrim(
57
+                _DIR_PLUGIN_DIST,
58
+                '/'
59
+            ) : ''));
60
+        }
61
+        $prepend = (defined('_Z_PREPEND_PATH') ? _Z_PREPEND_PATH : '');
62
+    }
63
+    $z_contenu = reset($z_blocs); // contenu par defaut
64
+
65
+    $fond = $flux['args']['fond'];
66
+
67
+    if ($prepend or strncmp($fond, $prefix_path, $prefix_length) == 0) {
68
+        $fond = substr($fond, $prefix_length);
69
+        $squelette = $flux['data'];
70
+        $ext = $flux['args']['ext'];
71
+        // Ajax Parallel loading : ne pas calculer le bloc, mais renvoyer un js qui le loadera en ajax
72
+        if (
73
+            defined('_Z_AJAX_PARALLEL_LOAD_OK')
74
+            and $dir = explode('/', $fond)
75
+            and count($dir) == 2 // pas un sous repertoire
76
+            and $dir = reset($dir)
77
+            and in_array($dir, $z_blocs) // verifier deja qu'on est dans un bloc Z
78
+            and defined($apl_constant)
79
+            and in_array($dir, explode(',', constant($apl_constant))) // et dans un demande en APL
80
+            and $pipe = z_trouver_bloc($prefix_path . $prepend, $dir, 'z_apl', $ext) // et qui contient le squelette APL
81
+        ) {
82
+            $flux['data'] = $pipe;
83
+
84
+            return $flux;
85
+        }
86
+
87
+        // surcharger aussi les squelettes venant de squelettes-dist/
88
+        if ($squelette and !z_fond_valide($squelette)) {
89
+            $squelette = '';
90
+            $echafauder = '';
91
+        }
92
+        if ($prepend) {
93
+            $squelette = substr(find_in_path($prefix_path . $prepend . "$fond.$ext"), 0, -strlen(".$ext"));
94
+            if ($squelette) {
95
+                $flux['data'] = $squelette;
96
+            }
97
+        }
98
+
99
+        // gerer les squelettes non trouves
100
+        // -> router vers les /dist.html
101
+        // ou scaffolding ou page automatique les contenus
102
+        if (!$squelette) {
103
+            // si on est sur un ?page=XX non trouve
104
+            if (
105
+                (isset($flux['args']['contexte'][$page])
106
+                    and $flux['args']['contexte'][$page] == $fond)
107
+                or (isset($flux['args']['contexte']['type-page'])
108
+                    and $flux['args']['contexte']['type-page'] == $fond)
109
+                or ($fond == 'sommaire'
110
+                    and (!isset($flux['args']['contexte'][$page]) or !$flux['args']['contexte'][$page]))
111
+            ) {
112
+                // si on est sur un ?page=XX non trouve
113
+                // se brancher sur contenu/xx si il existe
114
+                // ou si c'est un objet spip, associe a une table, utiliser le fond homonyme
115
+                if (!isset($disponible[$fond])) {
116
+                    $disponible[$fond] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $fond, $ext, $echafauder);
117
+                }
118
+
119
+                if ($disponible[$fond]) {
120
+                    $flux['data'] = substr(find_in_path($prefix_path . "page.$ext"), 0, -strlen(".$ext"));
121
+                }
122
+            }
123
+
124
+            // echafaudage :
125
+            // si c'est un fond de contenu d'un objet en base
126
+            // generer un fond automatique a la volee pour les webmestres
127
+            elseif (strncmp($fond, "$z_contenu/", strlen($z_contenu) + 1) == 0) {
128
+                $type = substr($fond, strlen($z_contenu) + 1);
129
+                if (($type == 'page') and isset($flux['args']['contexte'][$page])) {
130
+                    $type = $flux['args']['contexte'][$page];
131
+                }
132
+                if (!isset($disponible[$type])) {
133
+                    $disponible[$type] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $type, $ext, $echafauder);
134
+                }
135
+                if (is_string($disponible[$type])) {
136
+                    $flux['data'] = $disponible[$type];
137
+                } elseif (
138
+                    $echafauder
139
+                    and include_spip('inc/autoriser')
140
+                    and isset($GLOBALS['visiteur_session']['statut']) // performance
141
+                    and autoriser('echafauder', $type)
142
+                    and $is = $disponible[$type]
143
+                    and is_array($is)
144
+                ) {
145
+                    $flux['data'] = $echafauder($type, $is[0], $is[1], $is[2], $ext);
146
+                } else {
147
+                    $flux['data'] = ($disponible['404'] = z_contenu_disponible(
148
+                        $prefix_path . $prepend,
149
+                        $z_contenu,
150
+                        '404',
151
+                        $ext,
152
+                        $echafauder
153
+                    ));
154
+                }
155
+            }
156
+
157
+            // sinon, si on demande un fond non trouve dans un des autres blocs
158
+            // et si il y a bien un contenu correspondant ou echafaudable
159
+            // se rabbatre sur le dist.html du bloc concerne
160
+            else {
161
+                if (
162
+                    $dir = explode('/', $fond)
163
+                    and $dir = reset($dir)
164
+                    and $dir !== $z_contenu
165
+                    and in_array($dir, $z_blocs)
166
+                ) {
167
+                    $type = substr($fond, strlen("$dir/"));
168
+                    if (($type == 'page') and isset($flux['args']['contexte'][$page])) {
169
+                        $type = $flux['args']['contexte'][$page];
170
+                    }
171
+                    if ($type !== 'page' and !isset($disponible[$type])) {
172
+                        $disponible[$type] = z_contenu_disponible($prefix_path . $prepend, $z_contenu, $type, $ext, $echafauder);
173
+                    }
174
+                    if ($type == 'page' or $disponible[$type]) {
175
+                        $flux['data'] = z_trouver_bloc($prefix_path . $prepend, $dir, 'dist', $ext);
176
+                    }
177
+                }
178
+            }
179
+            $squelette = $flux['data'];
180
+        }
181
+        // layout specifiques par type et compositions :
182
+        // body-article.html
183
+        // body-sommaire.html
184
+        // pour des raisons de perfo, les declinaisons doivent etre dans le
185
+        // meme dossier que body.html
186
+        if ($fond == 'body' and substr($squelette, -strlen($fond)) == $fond) {
187
+            if (
188
+                isset($flux['args']['contexte']['type-page'])
189
+                and (
190
+                    (isset($flux['args']['contexte']['composition'])
191
+                        and file_exists(($f = $squelette . '-' . $flux['args']['contexte']['type-page'] . '-' . $flux['args']['contexte']['composition']) . ".$ext"))
192
+                    or
193
+                    file_exists(($f = $squelette . '-' . $flux['args']['contexte']['type-page']) . ".$ext")
194
+                )
195
+            ) {
196
+                $flux['data'] = $f;
197
+            }
198
+        } elseif (
199
+            $fond == 'structure'
200
+            and z_sanitize_var_zajax()
201
+            and $f = find_in_path($prefix_path . $prepend . 'ajax' . ".$ext")
202
+        ) {
203
+            $flux['data'] = substr($f, 0, -strlen(".$ext"));
204
+        } // chercher le fond correspondant a la composition
205
+        elseif (
206
+            isset($flux['args']['contexte']['composition'])
207
+            and (basename($fond) == 'page' or ($squelette and substr($squelette, -strlen($fond)) == $fond))
208
+            and $dir = substr($fond, $prefix_length)
209
+            and $dir = explode('/', $dir)
210
+            and $dir = reset($dir)
211
+            and in_array($dir, $z_blocs)
212
+            and $f = find_in_path($prefix_path . $prepend . $fond . '-' . $flux['args']['contexte']['composition'] . ".$ext")
213
+        ) {
214
+            $flux['data'] = substr($f, 0, -strlen(".$ext"));
215
+        }
216
+    }
217
+
218
+    return $flux;
219 219
 }
220 220
 
221 221
 /**
@@ -225,18 +225,18 @@  discard block
 block discarded – undo
225 225
  * @return array
226 226
  */
227 227
 function z_blocs($espace_prive = false) {
228
-	if ($espace_prive) {
229
-		return ($GLOBALS['z_blocs_ecrire'] ?? [
230
-			'contenu',
231
-			'navigation',
232
-			'extra',
233
-			'head',
234
-			'hierarchie',
235
-			'top'
236
-		]);
237
-	}
238
-
239
-	return ($GLOBALS['z_blocs'] ?? ['contenu']);
228
+    if ($espace_prive) {
229
+        return ($GLOBALS['z_blocs_ecrire'] ?? [
230
+            'contenu',
231
+            'navigation',
232
+            'extra',
233
+            'head',
234
+            'hierarchie',
235
+            'top'
236
+        ]);
237
+    }
238
+
239
+    return ($GLOBALS['z_blocs'] ?? ['contenu']);
240 240
 }
241 241
 
242 242
 /**
@@ -251,11 +251,11 @@  discard block
 block discarded – undo
251 251
  * @return mixed
252 252
  */
253 253
 function z_contenu_disponible($prefix_path, $z_contenu, $type, $ext, $echafauder = true) {
254
-	if ($d = z_trouver_bloc($prefix_path, $z_contenu, $type, $ext)) {
255
-		return $d;
256
-	}
254
+    if ($d = z_trouver_bloc($prefix_path, $z_contenu, $type, $ext)) {
255
+        return $d;
256
+    }
257 257
 
258
-	return $echafauder ? z_echafaudable($type) : false;
258
+    return $echafauder ? z_echafaudable($type) : false;
259 259
 }
260 260
 
261 261
 /**
@@ -269,14 +269,14 @@  discard block
 block discarded – undo
269 269
  *   `true` si on peut l'utiliser, `false` sinon.
270 270
  **/
271 271
 function z_fond_valide($squelette) {
272
-	if (
273
-		!_ZCORE_EXCLURE_PATH
274
-		or !preg_match(',(' . _ZCORE_EXCLURE_PATH . ')/,', $squelette)
275
-	) {
276
-		return true;
277
-	}
278
-
279
-	return false;
272
+    if (
273
+        !_ZCORE_EXCLURE_PATH
274
+        or !preg_match(',(' . _ZCORE_EXCLURE_PATH . ')/,', $squelette)
275
+    ) {
276
+        return true;
277
+    }
278
+
279
+    return false;
280 280
 }
281 281
 
282 282
 /**
@@ -294,14 +294,14 @@  discard block
 block discarded – undo
294 294
  * @return string
295 295
  */
296 296
 function z_trouver_bloc($prefix_path, $bloc, $fond, $ext) {
297
-	if (
298
-		(defined('_ZCORE_BLOC_PREFIX_SKEL') and $f = find_in_path("$prefix_path$bloc/$bloc.$fond.$ext") and z_fond_valide($f))
299
-		or ($f = find_in_path("$prefix_path$bloc/$fond.$ext") and z_fond_valide($f))
300
-	) {
301
-		return substr($f, 0, -strlen(".$ext"));
302
-	}
303
-
304
-	return '';
297
+    if (
298
+        (defined('_ZCORE_BLOC_PREFIX_SKEL') and $f = find_in_path("$prefix_path$bloc/$bloc.$fond.$ext") and z_fond_valide($f))
299
+        or ($f = find_in_path("$prefix_path$bloc/$fond.$ext") and z_fond_valide($f))
300
+    ) {
301
+        return substr($f, 0, -strlen(".$ext"));
302
+    }
303
+
304
+    return '';
305 305
 }
306 306
 
307 307
 /**
@@ -313,52 +313,52 @@  discard block
 block discarded – undo
313 313
  * @return bool
314 314
  */
315 315
 function z_echafaudable($type) {
316
-	static $pages = null;
317
-	static $echafaudable = [];
318
-	if (isset($echafaudable[$type])) {
319
-		return $echafaudable[$type];
320
-	}
321
-	if (preg_match(',[^\w],', $type)) {
322
-		return $echafaudable[$type] = false;
323
-	}
324
-
325
-	if (test_espace_prive()) {
326
-		if (!function_exists('trouver_objet_exec')) {
327
-			include_spip('inc/pipelines_ecrire');
328
-		}
329
-		if ($e = trouver_objet_exec($type)) {
330
-			return $echafaudable[$type] = [$e['table'], $e['table_objet_sql'], $e];
331
-		} else {
332
-			// peut etre c'est un exec=types qui liste tous les objets "type"
333
-			if (
334
-				($t = objet_type($type, false)) !== $type
335
-				and $e = trouver_objet_exec($t)
336
-			) {
337
-				return $echafaudable[$type] = [$e['table'], $e['table_objet_sql'], $t];
338
-			}
339
-		}
340
-	} else {
341
-		if (is_null($pages)) {
342
-			$pages = [];
343
-			$liste = lister_tables_objets_sql();
344
-			foreach ($liste as $t => $d) {
345
-				if ($d['page']) {
346
-					$pages[$d['page']] = [$d['table_objet'], $t];
347
-				}
348
-			}
349
-		}
350
-		if (!isset($pages[$type])) {
351
-			return $echafaudable[$type] = false;
352
-		}
353
-		if ((is_countable($pages[$type]) ? count($pages[$type]) : 0) == 2) {
354
-			$trouver_table = charger_fonction('trouver_table', 'base');
355
-			$pages[$type][] = $trouver_table(reset($pages[$type]));
356
-		}
357
-
358
-		return $echafaudable[$type] = $pages[$type];
359
-	}
360
-
361
-	return $echafaudable[$type] = false;
316
+    static $pages = null;
317
+    static $echafaudable = [];
318
+    if (isset($echafaudable[$type])) {
319
+        return $echafaudable[$type];
320
+    }
321
+    if (preg_match(',[^\w],', $type)) {
322
+        return $echafaudable[$type] = false;
323
+    }
324
+
325
+    if (test_espace_prive()) {
326
+        if (!function_exists('trouver_objet_exec')) {
327
+            include_spip('inc/pipelines_ecrire');
328
+        }
329
+        if ($e = trouver_objet_exec($type)) {
330
+            return $echafaudable[$type] = [$e['table'], $e['table_objet_sql'], $e];
331
+        } else {
332
+            // peut etre c'est un exec=types qui liste tous les objets "type"
333
+            if (
334
+                ($t = objet_type($type, false)) !== $type
335
+                and $e = trouver_objet_exec($t)
336
+            ) {
337
+                return $echafaudable[$type] = [$e['table'], $e['table_objet_sql'], $t];
338
+            }
339
+        }
340
+    } else {
341
+        if (is_null($pages)) {
342
+            $pages = [];
343
+            $liste = lister_tables_objets_sql();
344
+            foreach ($liste as $t => $d) {
345
+                if ($d['page']) {
346
+                    $pages[$d['page']] = [$d['table_objet'], $t];
347
+                }
348
+            }
349
+        }
350
+        if (!isset($pages[$type])) {
351
+            return $echafaudable[$type] = false;
352
+        }
353
+        if ((is_countable($pages[$type]) ? count($pages[$type]) : 0) == 2) {
354
+            $trouver_table = charger_fonction('trouver_table', 'base');
355
+            $pages[$type][] = $trouver_table(reset($pages[$type]));
356
+        }
357
+
358
+        return $echafaudable[$type] = $pages[$type];
359
+    }
360
+
361
+    return $echafaudable[$type] = false;
362 362
 }
363 363
 
364 364
 
@@ -375,46 +375,46 @@  discard block
 block discarded – undo
375 375
  * @return string
376 376
  */
377 377
 function prive_echafauder_dist($exec, $table, $table_sql, $desc_exec, $ext) {
378
-	$scaffold = '';
379
-
380
-	// page objet ou objet_edit
381
-	if (is_array($desc_exec)) {
382
-		$type = $desc_exec['type'];
383
-		$primary = $desc_exec['id_table_objet'];
384
-
385
-		if ($desc_exec['edition'] === false) {
386
-			$fond = 'objet';
387
-		} else {
388
-			$trouver_table = charger_fonction('trouver_table', 'base');
389
-			$desc = $trouver_table($table_sql);
390
-			if (isset($desc['field']['id_rubrique'])) {
391
-				$fond = 'objet_edit';
392
-			} else {
393
-				$fond = 'objet_edit.sans_rubrique';
394
-			}
395
-		}
396
-		$dir = z_blocs(test_espace_prive());
397
-		$dir = reset($dir);
398
-		$scaffold = "<INCLURE{fond=prive/echafaudage/$dir/" . $fond . ',objet=' . $type . ',id_objet=#' . strtoupper($primary) . ',env}>';
399
-	} // page objets
400
-	elseif ($type = $desc_exec and !str_contains($type, '/')) {
401
-		$dir = z_blocs(test_espace_prive());
402
-		$dir = reset($dir);
403
-		$scaffold = "<INCLURE{fond=prive/echafaudage/$dir/objets,objet=" . $type . ',env} />';
404
-	}
405
-	// morceau d'objet : on fournit le fond de sibstitution dans $desc_exec
406
-	// et objet et tire de $table
407
-	elseif ($fond = $desc_exec) {
408
-		$dir = md5(dirname($fond));
409
-		$scaffold = "<INCLURE{fond=$fond,objet=" . objet_type($table) . ',env} />';
410
-	}
411
-
412
-	$base_dir = sous_repertoire(_DIR_CACHE, 'scaffold', false);
413
-	$base_dir = sous_repertoire($base_dir, $dir, false);
414
-	$f = $base_dir . "$exec";
415
-	ecrire_fichier("$f.$ext", $scaffold);
416
-
417
-	return $f;
378
+    $scaffold = '';
379
+
380
+    // page objet ou objet_edit
381
+    if (is_array($desc_exec)) {
382
+        $type = $desc_exec['type'];
383
+        $primary = $desc_exec['id_table_objet'];
384
+
385
+        if ($desc_exec['edition'] === false) {
386
+            $fond = 'objet';
387
+        } else {
388
+            $trouver_table = charger_fonction('trouver_table', 'base');
389
+            $desc = $trouver_table($table_sql);
390
+            if (isset($desc['field']['id_rubrique'])) {
391
+                $fond = 'objet_edit';
392
+            } else {
393
+                $fond = 'objet_edit.sans_rubrique';
394
+            }
395
+        }
396
+        $dir = z_blocs(test_espace_prive());
397
+        $dir = reset($dir);
398
+        $scaffold = "<INCLURE{fond=prive/echafaudage/$dir/" . $fond . ',objet=' . $type . ',id_objet=#' . strtoupper($primary) . ',env}>';
399
+    } // page objets
400
+    elseif ($type = $desc_exec and !str_contains($type, '/')) {
401
+        $dir = z_blocs(test_espace_prive());
402
+        $dir = reset($dir);
403
+        $scaffold = "<INCLURE{fond=prive/echafaudage/$dir/objets,objet=" . $type . ',env} />';
404
+    }
405
+    // morceau d'objet : on fournit le fond de sibstitution dans $desc_exec
406
+    // et objet et tire de $table
407
+    elseif ($fond = $desc_exec) {
408
+        $dir = md5(dirname($fond));
409
+        $scaffold = "<INCLURE{fond=$fond,objet=" . objet_type($table) . ',env} />';
410
+    }
411
+
412
+    $base_dir = sous_repertoire(_DIR_CACHE, 'scaffold', false);
413
+    $base_dir = sous_repertoire($base_dir, $dir, false);
414
+    $f = $base_dir . "$exec";
415
+    ecrire_fichier("$f.$ext", $scaffold);
416
+
417
+    return $f;
418 418
 }
419 419
 
420 420
 /**
@@ -423,17 +423,17 @@  discard block
 block discarded – undo
423 423
  * @return bool|string
424 424
  */
425 425
 function z_sanitize_var_zajax() {
426
-	$z_ajax = _request('var_zajax');
427
-	if (!$z_ajax) {
428
-		return false;
429
-	}
430
-	if (
431
-		!$z_blocs = z_blocs(test_espace_prive())
432
-		or !in_array($z_ajax, $z_blocs)
433
-	) {
434
-		set_request('var_zajax'); // enlever cette demande incongrue
435
-		$z_ajax = false;
436
-	}
437
-
438
-	return $z_ajax;
426
+    $z_ajax = _request('var_zajax');
427
+    if (!$z_ajax) {
428
+        return false;
429
+    }
430
+    if (
431
+        !$z_blocs = z_blocs(test_espace_prive())
432
+        or !in_array($z_ajax, $z_blocs)
433
+    ) {
434
+        set_request('var_zajax'); // enlever cette demande incongrue
435
+        $z_ajax = false;
436
+    }
437
+
438
+    return $z_ajax;
439 439
 }
Please login to merge, or discard this patch.
ecrire/public/sandbox.php 1 patch
Indentation   +99 added lines, -99 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@  discard block
 block discarded – undo
23 23
  **/
24 24
 
25 25
 if (!defined('_ECRIRE_INC_VERSION')) {
26
-	return;
26
+    return;
27 27
 }
28 28
 
29 29
 /**
@@ -41,9 +41,9 @@  discard block
 block discarded – undo
41 41
  *     texte
42 42
  */
43 43
 function sandbox_composer_texte($texte, &$p) {
44
-	$code = "'" . str_replace(['\\', "'"], ['\\\\', "\\'"], $texte) . "'";
44
+    $code = "'" . str_replace(['\\', "'"], ['\\\\', "\\'"], $texte) . "'";
45 45
 
46
-	return $code;
46
+    return $code;
47 47
 }
48 48
 
49 49
 
@@ -59,42 +59,42 @@  discard block
 block discarded – undo
59 59
  * @return string
60 60
  */
61 61
 function sandbox_composer_filtre($fonc, $code, $arglist, &$p, $nb_arg_droite = 1000): string {
62
-	if (isset($GLOBALS['spip_matrice'][$fonc])) {
63
-		$code = "filtrer('$fonc',$code$arglist)";
64
-	}
65
-
66
-	// le filtre est defini sous forme de fonction ou de methode
67
-	// par ex. dans inc_texte, inc_filtres ou mes_fonctions
68
-	elseif ($f = chercher_filtre($fonc)) {
69
-		// cas particulier : le filtre |set doit acceder a la $Pile
70
-		// proto: filtre_set(&$Pile, $val, $args...)
71
-		if (strpbrk($f, ':')) { // Class::method
72
-			$refl = new ReflectionMethod($f);
73
-		} else {
74
-			$refl = new ReflectionFunction($f);
75
-		}
76
-		$refs = $refl->getParameters();
77
-		if (isset($refs[0]) and $refs[0]->name == 'Pile') {
78
-			$code = "$f(\$Pile,$code$arglist)";
79
-			$nb_arg_gauche = 2; // la balise Ă  laquelle s'applique le filtre + $Pile
80
-		} else {
81
-			$code = "$f($code$arglist)";
82
-			$nb_arg_gauche = 1; // la balise Ă  laquelle s'applique le filtre
83
-		}
84
-		$nb_args_f = $nb_arg_gauche + $nb_arg_droite;
85
-		$min_f = $refl->getNumberOfRequiredParameters();
86
-		if (($nb_args_f < $min_f)) {
87
-			$msg_args = ['filtre' => texte_script($fonc), 'nb' => $min_f - $nb_args_f];
88
-			erreur_squelette([ 'zbug_erreur_filtre_nbarg_min', $msg_args], $p);
89
-		}
90
-	}
91
-	// le filtre n'existe pas,
92
-	// on le notifie
93
-	else {
94
-		erreur_squelette(['zbug_erreur_filtre', ['filtre' => texte_script($fonc)]], $p);
95
-	}
96
-
97
-	return $code;
62
+    if (isset($GLOBALS['spip_matrice'][$fonc])) {
63
+        $code = "filtrer('$fonc',$code$arglist)";
64
+    }
65
+
66
+    // le filtre est defini sous forme de fonction ou de methode
67
+    // par ex. dans inc_texte, inc_filtres ou mes_fonctions
68
+    elseif ($f = chercher_filtre($fonc)) {
69
+        // cas particulier : le filtre |set doit acceder a la $Pile
70
+        // proto: filtre_set(&$Pile, $val, $args...)
71
+        if (strpbrk($f, ':')) { // Class::method
72
+            $refl = new ReflectionMethod($f);
73
+        } else {
74
+            $refl = new ReflectionFunction($f);
75
+        }
76
+        $refs = $refl->getParameters();
77
+        if (isset($refs[0]) and $refs[0]->name == 'Pile') {
78
+            $code = "$f(\$Pile,$code$arglist)";
79
+            $nb_arg_gauche = 2; // la balise Ă  laquelle s'applique le filtre + $Pile
80
+        } else {
81
+            $code = "$f($code$arglist)";
82
+            $nb_arg_gauche = 1; // la balise Ă  laquelle s'applique le filtre
83
+        }
84
+        $nb_args_f = $nb_arg_gauche + $nb_arg_droite;
85
+        $min_f = $refl->getNumberOfRequiredParameters();
86
+        if (($nb_args_f < $min_f)) {
87
+            $msg_args = ['filtre' => texte_script($fonc), 'nb' => $min_f - $nb_args_f];
88
+            erreur_squelette([ 'zbug_erreur_filtre_nbarg_min', $msg_args], $p);
89
+        }
90
+    }
91
+    // le filtre n'existe pas,
92
+    // on le notifie
93
+    else {
94
+        erreur_squelette(['zbug_erreur_filtre', ['filtre' => texte_script($fonc)]], $p);
95
+    }
96
+
97
+    return $code;
98 98
 }
99 99
 
100 100
 // Calculer un <INCLURE(xx.php)>
@@ -117,15 +117,15 @@  discard block
 block discarded – undo
117 117
  * @return string
118 118
  */
119 119
 function sandbox_composer_inclure_php($fichier, &$p, $_contexte) {
120
-	$compil = texte_script(memoriser_contexte_compil($p));
121
-	// si inexistant, on essaiera a l'execution
122
-	if ($path = find_in_path($fichier)) {
123
-		$path = "\"$path\"";
124
-	} else {
125
-		$path = "find_in_path(\"$fichier\")";
126
-	}
127
-
128
-	return sprintf(CODE_INCLURE_SCRIPT, $path, $fichier, $compil, $_contexte);
120
+    $compil = texte_script(memoriser_contexte_compil($p));
121
+    // si inexistant, on essaiera a l'execution
122
+    if ($path = find_in_path($fichier)) {
123
+        $path = "\"$path\"";
124
+    } else {
125
+        $path = "find_in_path(\"$fichier\")";
126
+    }
127
+
128
+    return sprintf(CODE_INCLURE_SCRIPT, $path, $fichier, $compil, $_contexte);
129 129
 }
130 130
 
131 131
 /**
@@ -137,20 +137,20 @@  discard block
 block discarded – undo
137 137
  * @return string
138 138
  */
139 139
 function sandbox_composer_interdire_scripts($code, &$p) {
140
-	// Securite
141
-	if (
142
-		$p->interdire_scripts
143
-		and $p->etoile != '**'
144
-	) {
145
-		if (!preg_match("/^sinon[(](.*),'([^']*)'[)]$/", $code, $r)) {
146
-			$code = "interdire_scripts($code)";
147
-		} else {
148
-			$code = interdire_scripts($r[2]);
149
-			$code = "sinon(interdire_scripts($r[1]),'$code')";
150
-		}
151
-	}
152
-
153
-	return $code;
140
+    // Securite
141
+    if (
142
+        $p->interdire_scripts
143
+        and $p->etoile != '**'
144
+    ) {
145
+        if (!preg_match("/^sinon[(](.*),'([^']*)'[)]$/", $code, $r)) {
146
+            $code = "interdire_scripts($code)";
147
+        } else {
148
+            $code = interdire_scripts($r[2]);
149
+            $code = "sinon(interdire_scripts($r[1]),'$code')";
150
+        }
151
+    }
152
+
153
+    return $code;
154 154
 }
155 155
 
156 156
 
@@ -169,30 +169,30 @@  discard block
 block discarded – undo
169 169
  * @return mixed|string
170 170
  */
171 171
 function sandbox_filtrer_squelette($skel, $corps, $filtres) {
172
-	$series_filtres = func_get_args();
173
-	array_shift($series_filtres);// skel
174
-	array_shift($series_filtres);// corps
175
-
176
-	// proteger les <INCLUDE> et tous les morceaux de php licites
177
-	if ($skel['process_ins'] == 'php') {
178
-		$corps = preg_replace_callback(',<[?](\s|php|=).*[?]>,UimsS', 'echapper_php_callback', $corps);
179
-	}
180
-
181
-	// recuperer les couples de remplacement
182
-	$replace = echapper_php_callback();
183
-
184
-	foreach ($series_filtres as $filtres) {
185
-		if (is_countable($filtres) ? count($filtres) : 0) {
186
-			foreach ($filtres as $filtre) {
187
-				if ($filtre and $f = chercher_filtre($filtre)) {
188
-					$corps = $f($corps);
189
-				}
190
-			}
191
-		}
192
-	}
193
-
194
-	// restaurer les echappements
195
-	return str_replace($replace[0], $replace[1], $corps);
172
+    $series_filtres = func_get_args();
173
+    array_shift($series_filtres);// skel
174
+    array_shift($series_filtres);// corps
175
+
176
+    // proteger les <INCLUDE> et tous les morceaux de php licites
177
+    if ($skel['process_ins'] == 'php') {
178
+        $corps = preg_replace_callback(',<[?](\s|php|=).*[?]>,UimsS', 'echapper_php_callback', $corps);
179
+    }
180
+
181
+    // recuperer les couples de remplacement
182
+    $replace = echapper_php_callback();
183
+
184
+    foreach ($series_filtres as $filtres) {
185
+        if (is_countable($filtres) ? count($filtres) : 0) {
186
+            foreach ($filtres as $filtre) {
187
+                if ($filtre and $f = chercher_filtre($filtre)) {
188
+                    $corps = $f($corps);
189
+                }
190
+            }
191
+        }
192
+    }
193
+
194
+    // restaurer les echappements
195
+    return str_replace($replace[0], $replace[1], $corps);
196 196
 }
197 197
 
198 198
 
@@ -211,21 +211,21 @@  discard block
 block discarded – undo
211 211
  *     - array : Liste( liste des codes PHP, liste des substitutions )
212 212
  **/
213 213
 function echapper_php_callback($r = null) {
214
-	static $src = [];
215
-	static $dst = [];
214
+    static $src = [];
215
+    static $dst = [];
216 216
 
217
-	// si on recoit un tableau, on est en mode echappement
218
-	// on enregistre le code a echapper dans dst, et le code echappe dans src
219
-	if (is_array($r)) {
220
-		$dst[] = $r[0];
217
+    // si on recoit un tableau, on est en mode echappement
218
+    // on enregistre le code a echapper dans dst, et le code echappe dans src
219
+    if (is_array($r)) {
220
+        $dst[] = $r[0];
221 221
 
222
-		return $src[] = '___' . md5($r[0]) . '___';
223
-	}
222
+        return $src[] = '___' . md5($r[0]) . '___';
223
+    }
224 224
 
225
-	// si on recoit pas un tableau, on renvoit les couples de substitution
226
-	// et on RAZ les remplacements
227
-	$r = [$src, $dst];
228
-	$src = $dst = [];
225
+    // si on recoit pas un tableau, on renvoit les couples de substitution
226
+    // et on RAZ les remplacements
227
+    $r = [$src, $dst];
228
+    $src = $dst = [];
229 229
 
230
-	return $r;
230
+    return $r;
231 231
 }
Please login to merge, or discard this patch.
ecrire/public/phraser_html.php 1 patch
Indentation   +1032 added lines, -1032 removed lines patch added patch discarded remove patch
@@ -28,7 +28,7 @@  discard block
 block discarded – undo
28 28
  **/
29 29
 
30 30
 if (!defined('_ECRIRE_INC_VERSION')) {
31
-	return;
31
+    return;
32 32
 }
33 33
 
34 34
 /** Début de la partie principale d'une boucle */
@@ -72,82 +72,82 @@  discard block
 block discarded – undo
72 72
 
73 73
 function phraser_inclure($texte, $ligne, $result) {
74 74
 
75
-	while (preg_match(BALISE_INCLURE, $texte, $match)) {
76
-		$match = array_pad($match, 3, null);
77
-		$p = strpos($texte, (string) $match[0]);
78
-		$debut = substr($texte, 0, $p);
79
-		if ($p) {
80
-			$result = phraser_idiomes($debut, $ligne, $result);
81
-		}
82
-		$ligne += substr_count($debut, "\n");
83
-		$champ = new Inclure();
84
-		$champ->ligne = $ligne;
85
-		$ligne += substr_count($match[0], "\n");
86
-		$fichier = $match[2];
87
-		# assurer ici la migration .php3 => .php
88
-		# et de l'ancienne syntaxe INCLURE(page.php3) devenue surperflue
89
-		if ($fichier and preg_match(',^(.*[.]php)3$,', $fichier, $r)) {
90
-			$fichier = $r[1];
91
-		}
92
-		$champ->texte = ($fichier !== 'page.php') ? $fichier : '';
93
-		$texte = substr($texte, $p + strlen($match[0]));
94
-		// on assimile {var=val} a une liste de un argument sans fonction
95
-		$pos_apres = 0;
96
-		phraser_args($texte, '/>', '', $result, $champ, $pos_apres);
97
-		if (!$champ->texte or (is_countable($champ->param) ? count($champ->param) : 0) > 1) {
98
-			if (!function_exists('normaliser_inclure')) {
99
-				include_spip('public/normaliser');
100
-			}
101
-			normaliser_inclure($champ);
102
-		}
103
-		$texte = substr($texte, strpos($texte, '>', $pos_apres) + 1);
104
-		$texte = preg_replace(',^</INCLU[DR]E>,', '', $texte);
105
-		$result[] = $champ;
106
-	}
107
-
108
-	return (($texte === '') ? $result : phraser_idiomes($texte, $ligne, $result));
75
+    while (preg_match(BALISE_INCLURE, $texte, $match)) {
76
+        $match = array_pad($match, 3, null);
77
+        $p = strpos($texte, (string) $match[0]);
78
+        $debut = substr($texte, 0, $p);
79
+        if ($p) {
80
+            $result = phraser_idiomes($debut, $ligne, $result);
81
+        }
82
+        $ligne += substr_count($debut, "\n");
83
+        $champ = new Inclure();
84
+        $champ->ligne = $ligne;
85
+        $ligne += substr_count($match[0], "\n");
86
+        $fichier = $match[2];
87
+        # assurer ici la migration .php3 => .php
88
+        # et de l'ancienne syntaxe INCLURE(page.php3) devenue surperflue
89
+        if ($fichier and preg_match(',^(.*[.]php)3$,', $fichier, $r)) {
90
+            $fichier = $r[1];
91
+        }
92
+        $champ->texte = ($fichier !== 'page.php') ? $fichier : '';
93
+        $texte = substr($texte, $p + strlen($match[0]));
94
+        // on assimile {var=val} a une liste de un argument sans fonction
95
+        $pos_apres = 0;
96
+        phraser_args($texte, '/>', '', $result, $champ, $pos_apres);
97
+        if (!$champ->texte or (is_countable($champ->param) ? count($champ->param) : 0) > 1) {
98
+            if (!function_exists('normaliser_inclure')) {
99
+                include_spip('public/normaliser');
100
+            }
101
+            normaliser_inclure($champ);
102
+        }
103
+        $texte = substr($texte, strpos($texte, '>', $pos_apres) + 1);
104
+        $texte = preg_replace(',^</INCLU[DR]E>,', '', $texte);
105
+        $result[] = $champ;
106
+    }
107
+
108
+    return (($texte === '') ? $result : phraser_idiomes($texte, $ligne, $result));
109 109
 }
110 110
 
111 111
 function phraser_polyglotte($texte, $ligne, $result) {
112 112
 
113
-	if (preg_match_all(BALISE_POLYGLOTTE, $texte, $m, PREG_SET_ORDER)) {
114
-		foreach ($m as $match) {
115
-			$p = strpos($texte, (string) $match[0]);
116
-			$debut = substr($texte, 0, $p);
117
-			if ($p) {
118
-				$champ = new Texte();
119
-				$champ->texte = $debut;
120
-				$champ->ligne = $ligne;
121
-				$result[] = $champ;
122
-				$ligne += substr_count($champ->texte, "\n");
123
-			}
124
-
125
-			$champ = new Polyglotte();
126
-			$champ->ligne = $ligne;
127
-			$ligne += substr_count($match[0], "\n");
128
-			$lang = '';
129
-			$bloc = $match[1];
130
-			$texte = substr($texte, $p + strlen($match[0]));
131
-			while (preg_match('/^[[:space:]]*([^[{]*)[[:space:]]*[[{]([a-z_]+)[]}](.*)$/si', $bloc, $regs)) {
132
-				$trad = $regs[1];
133
-				if ($trad or $lang) {
134
-					$champ->traductions[$lang] = $trad;
135
-				}
136
-				$lang = $regs[2];
137
-				$bloc = $regs[3];
138
-			}
139
-			$champ->traductions[$lang] = $bloc;
140
-			$result[] = $champ;
141
-		}
142
-	}
143
-	if ($texte !== '') {
144
-		$champ = new Texte();
145
-		$champ->texte = $texte;
146
-		$champ->ligne = $ligne;
147
-		$result[] = $champ;
148
-	}
149
-
150
-	return $result;
113
+    if (preg_match_all(BALISE_POLYGLOTTE, $texte, $m, PREG_SET_ORDER)) {
114
+        foreach ($m as $match) {
115
+            $p = strpos($texte, (string) $match[0]);
116
+            $debut = substr($texte, 0, $p);
117
+            if ($p) {
118
+                $champ = new Texte();
119
+                $champ->texte = $debut;
120
+                $champ->ligne = $ligne;
121
+                $result[] = $champ;
122
+                $ligne += substr_count($champ->texte, "\n");
123
+            }
124
+
125
+            $champ = new Polyglotte();
126
+            $champ->ligne = $ligne;
127
+            $ligne += substr_count($match[0], "\n");
128
+            $lang = '';
129
+            $bloc = $match[1];
130
+            $texte = substr($texte, $p + strlen($match[0]));
131
+            while (preg_match('/^[[:space:]]*([^[{]*)[[:space:]]*[[{]([a-z_]+)[]}](.*)$/si', $bloc, $regs)) {
132
+                $trad = $regs[1];
133
+                if ($trad or $lang) {
134
+                    $champ->traductions[$lang] = $trad;
135
+                }
136
+                $lang = $regs[2];
137
+                $bloc = $regs[3];
138
+            }
139
+            $champ->traductions[$lang] = $bloc;
140
+            $result[] = $champ;
141
+        }
142
+    }
143
+    if ($texte !== '') {
144
+        $champ = new Texte();
145
+        $champ->texte = $texte;
146
+        $champ->ligne = $ligne;
147
+        $result[] = $champ;
148
+    }
149
+
150
+    return $result;
151 151
 }
152 152
 
153 153
 
@@ -169,43 +169,43 @@  discard block
 block discarded – undo
169 169
  * @return array
170 170
  **/
171 171
 function phraser_idiomes($texte, $ligne, $result) {
172
-	while (preg_match(BALISE_IDIOMES, $texte, $match)) {
173
-		$match = array_pad($match, 8, null);
174
-		$p = strpos($texte, (string) $match[0]);
175
-		$ko = (!$match[3] && ($match[5][0] !== '='));
176
-		$debut = substr($texte, 0, $p + ($ko ? strlen($match[0]) : 0));
177
-		if ($debut) {
178
-			$result = phraser_champs($debut, $ligne, $result);
179
-		}
180
-		$texte = substr($texte, $p + strlen($match[0]));
181
-		$ligne += substr_count($debut, "\n");
182
-		if ($ko) {
183
-			continue;
184
-		} // faux idiome
185
-		$champ = new Idiome();
186
-		$champ->ligne = $ligne;
187
-		$ligne += substr_count($match[0], "\n");
188
-		// Stocker les arguments de la balise de traduction
189
-		$args = [];
190
-		$largs = $match[5];
191
-		while (preg_match(BALISE_IDIOMES_ARGS, $largs, $r)) {
192
-			$args[$r[1]] = phraser_champs($r[2], 0, []);
193
-			$largs = substr($largs, strlen($r[0]));
194
-		}
195
-		$champ->arg = $args;
196
-		$champ->nom_champ = strtolower($match[3]);
197
-		$champ->module = $match[2];
198
-		// pas d'imbrication pour les filtres sur langue
199
-		$pos_apres = 0;
200
-		phraser_args($match[7] ?? '', ':', '', [], $champ, $pos_apres);
201
-		$champ->apres = substr($match[7] ?? '', $pos_apres);
202
-		$result[] = $champ;
203
-	}
204
-	if ($texte !== '') {
205
-		$result = phraser_champs($texte, $ligne, $result);
206
-	}
207
-
208
-	return $result;
172
+    while (preg_match(BALISE_IDIOMES, $texte, $match)) {
173
+        $match = array_pad($match, 8, null);
174
+        $p = strpos($texte, (string) $match[0]);
175
+        $ko = (!$match[3] && ($match[5][0] !== '='));
176
+        $debut = substr($texte, 0, $p + ($ko ? strlen($match[0]) : 0));
177
+        if ($debut) {
178
+            $result = phraser_champs($debut, $ligne, $result);
179
+        }
180
+        $texte = substr($texte, $p + strlen($match[0]));
181
+        $ligne += substr_count($debut, "\n");
182
+        if ($ko) {
183
+            continue;
184
+        } // faux idiome
185
+        $champ = new Idiome();
186
+        $champ->ligne = $ligne;
187
+        $ligne += substr_count($match[0], "\n");
188
+        // Stocker les arguments de la balise de traduction
189
+        $args = [];
190
+        $largs = $match[5];
191
+        while (preg_match(BALISE_IDIOMES_ARGS, $largs, $r)) {
192
+            $args[$r[1]] = phraser_champs($r[2], 0, []);
193
+            $largs = substr($largs, strlen($r[0]));
194
+        }
195
+        $champ->arg = $args;
196
+        $champ->nom_champ = strtolower($match[3]);
197
+        $champ->module = $match[2];
198
+        // pas d'imbrication pour les filtres sur langue
199
+        $pos_apres = 0;
200
+        phraser_args($match[7] ?? '', ':', '', [], $champ, $pos_apres);
201
+        $champ->apres = substr($match[7] ?? '', $pos_apres);
202
+        $result[] = $champ;
203
+    }
204
+    if ($texte !== '') {
205
+        $result = phraser_champs($texte, $ligne, $result);
206
+    }
207
+
208
+    return $result;
209 209
 }
210 210
 
211 211
 /**
@@ -223,47 +223,47 @@  discard block
 block discarded – undo
223 223
  * @return array
224 224
  **/
225 225
 function phraser_champs($texte, $ligne, $result) {
226
-	while (preg_match('/' . NOM_DE_CHAMP . '/S', $texte, $match)) {
227
-		$p = strpos($texte, (string) $match[0]);
228
-		// texte après la balise
229
-		$suite = substr($texte, $p + strlen($match[0]));
230
-
231
-		$debut = substr($texte, 0, $p);
232
-		if ($p) {
233
-			$result = phraser_polyglotte($debut, $ligne, $result);
234
-		}
235
-		$ligne += substr_count($debut, "\n");
236
-		$champ = new Champ();
237
-		$champ->ligne = $ligne;
238
-		$ligne += substr_count($match[0], "\n");
239
-		$champ->nom_boucle = $match[2];
240
-		$champ->nom_champ = $match[3];
241
-		$champ->etoile = $match[5];
242
-
243
-		if ($suite and $suite[0] == '{') {
244
-			phraser_arg($suite, '', [], $champ);
245
-			// ce ltrim est une ereur de conception
246
-			// mais on le conserve par souci de compatibilite
247
-			$texte = ltrim($suite);
248
-			// Il faudrait le normaliser dans l'arbre de syntaxe abstraite
249
-			// pour faire sauter ce cas particulier a la decompilation.
250
-			/* Ce qui suit est malheureusement incomplet pour cela:
226
+    while (preg_match('/' . NOM_DE_CHAMP . '/S', $texte, $match)) {
227
+        $p = strpos($texte, (string) $match[0]);
228
+        // texte après la balise
229
+        $suite = substr($texte, $p + strlen($match[0]));
230
+
231
+        $debut = substr($texte, 0, $p);
232
+        if ($p) {
233
+            $result = phraser_polyglotte($debut, $ligne, $result);
234
+        }
235
+        $ligne += substr_count($debut, "\n");
236
+        $champ = new Champ();
237
+        $champ->ligne = $ligne;
238
+        $ligne += substr_count($match[0], "\n");
239
+        $champ->nom_boucle = $match[2];
240
+        $champ->nom_champ = $match[3];
241
+        $champ->etoile = $match[5];
242
+
243
+        if ($suite and $suite[0] == '{') {
244
+            phraser_arg($suite, '', [], $champ);
245
+            // ce ltrim est une ereur de conception
246
+            // mais on le conserve par souci de compatibilite
247
+            $texte = ltrim($suite);
248
+            // Il faudrait le normaliser dans l'arbre de syntaxe abstraite
249
+            // pour faire sauter ce cas particulier a la decompilation.
250
+            /* Ce qui suit est malheureusement incomplet pour cela:
251 251
 			if ($n = (strlen($suite) - strlen($texte))) {
252 252
 				$champ->apres = array(new Texte);
253 253
 				$champ->apres[0]->texte = substr($suite,0,$n);
254 254
 			}
255 255
 			*/
256
-		} else {
257
-			$texte = $suite;
258
-		}
259
-		phraser_vieux($champ);
260
-		$result[] = $champ;
261
-	}
262
-	if ($texte !== '') {
263
-		$result = phraser_polyglotte($texte, $ligne, $result);
264
-	}
265
-
266
-	return $result;
256
+        } else {
257
+            $texte = $suite;
258
+        }
259
+        phraser_vieux($champ);
260
+        $result[] = $champ;
261
+    }
262
+    if ($texte !== '') {
263
+        $result = phraser_polyglotte($texte, $ligne, $result);
264
+    }
265
+
266
+    return $result;
267 267
 }
268 268
 
269 269
 // Gestion des imbrications:
@@ -272,15 +272,15 @@  discard block
 block discarded – undo
272 272
 // on recommence tant qu'il y a des [...] en substituant a l'appel suivant
273 273
 
274 274
 function phraser_champs_etendus($texte, $ligne, $result) {
275
-	if ($texte === '') {
276
-		return $result;
277
-	}
278
-	$sep = '##';
279
-	while (strpos($texte, (string) $sep) !== false) {
280
-		$sep .= '#';
281
-	}
282
-
283
-	return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, []));
275
+    if ($texte === '') {
276
+        return $result;
277
+    }
278
+    $sep = '##';
279
+    while (strpos($texte, (string) $sep) !== false) {
280
+        $sep .= '#';
281
+    }
282
+
283
+    return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, []));
284 284
 }
285 285
 
286 286
 /**
@@ -299,275 +299,275 @@  discard block
 block discarded – undo
299 299
  * @return array
300 300
  */
301 301
 function phraser_args(string $texte, $fin, $sep, $result, &$pointeur_champ, &$pos_debut) {
302
-	$length = strlen($texte);
303
-	while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
304
-		$pos_debut++;
305
-	}
306
-	while (($pos_debut < $length) && !str_contains($fin, $texte[$pos_debut])) {
307
-		// phraser_arg modifie directement le $texte, on fait donc avec ici en passant par une sous chaine
308
-		$st = substr($texte, $pos_debut);
309
-		$result = phraser_arg($st, $sep, $result, $pointeur_champ);
310
-		$pos_debut = $length - strlen($st);
311
-		while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
312
-			$pos_debut++;
313
-		}
314
-	}
315
-
316
-	return $result;
302
+    $length = strlen($texte);
303
+    while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
304
+        $pos_debut++;
305
+    }
306
+    while (($pos_debut < $length) && !str_contains($fin, $texte[$pos_debut])) {
307
+        // phraser_arg modifie directement le $texte, on fait donc avec ici en passant par une sous chaine
308
+        $st = substr($texte, $pos_debut);
309
+        $result = phraser_arg($st, $sep, $result, $pointeur_champ);
310
+        $pos_debut = $length - strlen($st);
311
+        while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
312
+            $pos_debut++;
313
+        }
314
+    }
315
+
316
+    return $result;
317 317
 }
318 318
 
319 319
 function phraser_arg(&$texte, $sep, $result, &$pointeur_champ) {
320
-	preg_match(',^(\|?[^}{)|]*)(.*)$,ms', $texte, $match);
321
-	$suite = ltrim($match[2]);
322
-	$fonc = trim($match[1]);
323
-	if ($fonc && $fonc[0] == '|') {
324
-		$fonc = ltrim(substr($fonc, 1));
325
-	}
326
-	$res = [$fonc];
327
-	$err_f = '';
328
-	// cas du filtre sans argument ou du critere /
329
-	if (($suite && ($suite[0] != '{')) || ($fonc && $fonc[0] == '/')) {
330
-		// si pas d'argument, alors il faut une fonction ou un double |
331
-		if (!$match[1]) {
332
-			$err_f = ['zbug_erreur_filtre', ['filtre' => $texte]];
333
-			erreur_squelette($err_f, $pointeur_champ);
334
-			$texte = '';
335
-		} else {
336
-			$texte = $suite;
337
-		}
338
-		if ($err_f) {
339
-			$pointeur_champ->param = false;
340
-		} elseif ($fonc !== '') {
341
-			$pointeur_champ->param[] = $res;
342
-		}
343
-		// pour les balises avec faux filtres qui boudent ce dur larbeur
344
-		$pointeur_champ->fonctions[] = [$fonc, ''];
345
-
346
-		return $result;
347
-	}
348
-	$args = ltrim(substr($suite, 1)); // virer le '(' initial
349
-	$collecte = [];
350
-	while ($args && $args[0] != '}') {
351
-		if ($args[0] == '"') {
352
-			preg_match('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
353
-		} elseif ($args[0] == "'") {
354
-			preg_match("/^(')([^']*)(')(.*)$/ms", $args, $regs);
355
-		} else {
356
-			preg_match('/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^,}]*)([,}].*)$/ms', $args, $regs);
357
-			if (!isset($regs[2]) or !strlen($regs[2])) {
358
-				$err_f = ['zbug_erreur_filtre', ['filtre' => $args]];
359
-				erreur_squelette($err_f, $pointeur_champ);
360
-				$champ = new Texte();
361
-				$champ->apres = $champ->avant = $args = '';
362
-				break;
363
-			}
364
-		}
365
-		$arg = $regs[2];
366
-		if (trim($regs[1])) {
367
-			$champ = new Texte();
368
-			$champ->texte = $arg;
369
-			$champ->apres = $champ->avant = $regs[1];
370
-			$result[] = $champ;
371
-			$collecte[] = $champ;
372
-			$args = ltrim($regs[count($regs) - 1]);
373
-		} else {
374
-			if (!preg_match('/' . NOM_DE_CHAMP . '([{|])/', $arg, $r)) {
375
-				// 0 est un aveu d'impuissance. A completer
376
-				$arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
377
-
378
-				$args = ltrim($regs[count($regs) - 1]);
379
-				$collecte = array_merge($collecte, $arg);
380
-				$result = array_merge($result, $arg);
381
-			} else {
382
-				$n = strpos($args, (string) $r[0]);
383
-				$pred = substr($args, 0, $n);
384
-				$par = ',}';
385
-				if (preg_match('/^(.*)\($/', $pred, $m)) {
386
-					$pred = $m[1];
387
-					$par = ')';
388
-				}
389
-				if ($pred) {
390
-					$champ = new Texte();
391
-					$champ->texte = $pred;
392
-					$champ->apres = $champ->avant = '';
393
-					$result[] = $champ;
394
-					$collecte[] = $champ;
395
-				}
396
-				$rec = substr($args, $n + strlen($r[0]) - 1);
397
-				$champ = new Champ();
398
-				$champ->nom_boucle = $r[2];
399
-				$champ->nom_champ = $r[3];
400
-				$champ->etoile = $r[5];
401
-				$next = $r[6];
402
-				while ($next == '{') {
403
-					phraser_arg($rec, $sep, [], $champ);
404
-					$args = ltrim($rec);
405
-					$next = $args[0] ?? '';
406
-				}
407
-				while ($next == '|') {
408
-					$pos_apres = 0;
409
-					phraser_args($rec, $par, $sep, [], $champ, $pos_apres);
410
-					$args = substr($rec, $pos_apres);
411
-					$next = $args[0] ?? '';
412
-				}
413
-				// Si erreur de syntaxe dans un sous-argument, propager.
414
-				if ($champ->param === false) {
415
-					$err_f = true;
416
-				} else {
417
-					phraser_vieux($champ);
418
-				}
419
-				if ($par == ')') {
420
-					$args = substr($args, 1);
421
-				}
422
-				$collecte[] = $champ;
423
-				$result[] = $champ;
424
-			}
425
-		}
426
-		if (isset($args[0]) and $args[0] == ',') {
427
-			$args = ltrim(substr($args, 1));
428
-			if ($collecte) {
429
-				$res[] = $collecte;
430
-				$collecte = [];
431
-			}
432
-		}
433
-	}
434
-	if ($collecte) {
435
-		$res[] = $collecte;
436
-		$collecte = [];
437
-	}
438
-	$texte = substr($args, 1);
439
-	$source = substr($suite, 0, strlen($suite) - strlen($texte));
440
-	// propager les erreurs, et ignorer les param vides
441
-	if ($pointeur_champ->param !== false) {
442
-		if ($err_f) {
443
-			$pointeur_champ->param = false;
444
-		} elseif ($fonc !== '' || count($res) > 1) {
445
-			$pointeur_champ->param[] = $res;
446
-		}
447
-	}
448
-	// pour les balises avec faux filtres qui boudent ce dur larbeur
449
-	$pointeur_champ->fonctions[] = [$fonc, $source];
450
-
451
-	return $result;
320
+    preg_match(',^(\|?[^}{)|]*)(.*)$,ms', $texte, $match);
321
+    $suite = ltrim($match[2]);
322
+    $fonc = trim($match[1]);
323
+    if ($fonc && $fonc[0] == '|') {
324
+        $fonc = ltrim(substr($fonc, 1));
325
+    }
326
+    $res = [$fonc];
327
+    $err_f = '';
328
+    // cas du filtre sans argument ou du critere /
329
+    if (($suite && ($suite[0] != '{')) || ($fonc && $fonc[0] == '/')) {
330
+        // si pas d'argument, alors il faut une fonction ou un double |
331
+        if (!$match[1]) {
332
+            $err_f = ['zbug_erreur_filtre', ['filtre' => $texte]];
333
+            erreur_squelette($err_f, $pointeur_champ);
334
+            $texte = '';
335
+        } else {
336
+            $texte = $suite;
337
+        }
338
+        if ($err_f) {
339
+            $pointeur_champ->param = false;
340
+        } elseif ($fonc !== '') {
341
+            $pointeur_champ->param[] = $res;
342
+        }
343
+        // pour les balises avec faux filtres qui boudent ce dur larbeur
344
+        $pointeur_champ->fonctions[] = [$fonc, ''];
345
+
346
+        return $result;
347
+    }
348
+    $args = ltrim(substr($suite, 1)); // virer le '(' initial
349
+    $collecte = [];
350
+    while ($args && $args[0] != '}') {
351
+        if ($args[0] == '"') {
352
+            preg_match('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
353
+        } elseif ($args[0] == "'") {
354
+            preg_match("/^(')([^']*)(')(.*)$/ms", $args, $regs);
355
+        } else {
356
+            preg_match('/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^,}]*)([,}].*)$/ms', $args, $regs);
357
+            if (!isset($regs[2]) or !strlen($regs[2])) {
358
+                $err_f = ['zbug_erreur_filtre', ['filtre' => $args]];
359
+                erreur_squelette($err_f, $pointeur_champ);
360
+                $champ = new Texte();
361
+                $champ->apres = $champ->avant = $args = '';
362
+                break;
363
+            }
364
+        }
365
+        $arg = $regs[2];
366
+        if (trim($regs[1])) {
367
+            $champ = new Texte();
368
+            $champ->texte = $arg;
369
+            $champ->apres = $champ->avant = $regs[1];
370
+            $result[] = $champ;
371
+            $collecte[] = $champ;
372
+            $args = ltrim($regs[count($regs) - 1]);
373
+        } else {
374
+            if (!preg_match('/' . NOM_DE_CHAMP . '([{|])/', $arg, $r)) {
375
+                // 0 est un aveu d'impuissance. A completer
376
+                $arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
377
+
378
+                $args = ltrim($regs[count($regs) - 1]);
379
+                $collecte = array_merge($collecte, $arg);
380
+                $result = array_merge($result, $arg);
381
+            } else {
382
+                $n = strpos($args, (string) $r[0]);
383
+                $pred = substr($args, 0, $n);
384
+                $par = ',}';
385
+                if (preg_match('/^(.*)\($/', $pred, $m)) {
386
+                    $pred = $m[1];
387
+                    $par = ')';
388
+                }
389
+                if ($pred) {
390
+                    $champ = new Texte();
391
+                    $champ->texte = $pred;
392
+                    $champ->apres = $champ->avant = '';
393
+                    $result[] = $champ;
394
+                    $collecte[] = $champ;
395
+                }
396
+                $rec = substr($args, $n + strlen($r[0]) - 1);
397
+                $champ = new Champ();
398
+                $champ->nom_boucle = $r[2];
399
+                $champ->nom_champ = $r[3];
400
+                $champ->etoile = $r[5];
401
+                $next = $r[6];
402
+                while ($next == '{') {
403
+                    phraser_arg($rec, $sep, [], $champ);
404
+                    $args = ltrim($rec);
405
+                    $next = $args[0] ?? '';
406
+                }
407
+                while ($next == '|') {
408
+                    $pos_apres = 0;
409
+                    phraser_args($rec, $par, $sep, [], $champ, $pos_apres);
410
+                    $args = substr($rec, $pos_apres);
411
+                    $next = $args[0] ?? '';
412
+                }
413
+                // Si erreur de syntaxe dans un sous-argument, propager.
414
+                if ($champ->param === false) {
415
+                    $err_f = true;
416
+                } else {
417
+                    phraser_vieux($champ);
418
+                }
419
+                if ($par == ')') {
420
+                    $args = substr($args, 1);
421
+                }
422
+                $collecte[] = $champ;
423
+                $result[] = $champ;
424
+            }
425
+        }
426
+        if (isset($args[0]) and $args[0] == ',') {
427
+            $args = ltrim(substr($args, 1));
428
+            if ($collecte) {
429
+                $res[] = $collecte;
430
+                $collecte = [];
431
+            }
432
+        }
433
+    }
434
+    if ($collecte) {
435
+        $res[] = $collecte;
436
+        $collecte = [];
437
+    }
438
+    $texte = substr($args, 1);
439
+    $source = substr($suite, 0, strlen($suite) - strlen($texte));
440
+    // propager les erreurs, et ignorer les param vides
441
+    if ($pointeur_champ->param !== false) {
442
+        if ($err_f) {
443
+            $pointeur_champ->param = false;
444
+        } elseif ($fonc !== '' || count($res) > 1) {
445
+            $pointeur_champ->param[] = $res;
446
+        }
447
+    }
448
+    // pour les balises avec faux filtres qui boudent ce dur larbeur
449
+    $pointeur_champ->fonctions[] = [$fonc, $source];
450
+
451
+    return $result;
452 452
 }
453 453
 
454 454
 
455 455
 function phraser_champs_exterieurs($texte, $ligne, $sep, $nested) {
456
-	$res = [];
457
-	while (($p = strpos($texte, (string) "%$sep")) !== false) {
458
-		if (!preg_match(',^%' . preg_quote($sep) . '([0-9]+)@,', substr($texte, $p), $m)) {
459
-			break;
460
-		}
461
-		$debut = substr($texte, 0, $p);
462
-		$texte = substr($texte, $p + strlen($m[0]));
463
-		if ($p) {
464
-			$res = phraser_inclure($debut, $ligne, $res);
465
-		}
466
-		$ligne += substr_count($debut, "\n");
467
-		$res[] = $nested[$m[1]];
468
-	}
469
-
470
-	return (($texte === '') ? $res : phraser_inclure($texte, $ligne, $res));
456
+    $res = [];
457
+    while (($p = strpos($texte, (string) "%$sep")) !== false) {
458
+        if (!preg_match(',^%' . preg_quote($sep) . '([0-9]+)@,', substr($texte, $p), $m)) {
459
+            break;
460
+        }
461
+        $debut = substr($texte, 0, $p);
462
+        $texte = substr($texte, $p + strlen($m[0]));
463
+        if ($p) {
464
+            $res = phraser_inclure($debut, $ligne, $res);
465
+        }
466
+        $ligne += substr_count($debut, "\n");
467
+        $res[] = $nested[$m[1]];
468
+    }
469
+
470
+    return (($texte === '') ? $res : phraser_inclure($texte, $ligne, $res));
471 471
 }
472 472
 
473 473
 function phraser_champs_interieurs($texte, $ligne, $sep, $result) {
474
-	$i = 0; // en fait count($result)
475
-	$x = '';
476
-
477
-	while (true) {
478
-		$j = $i;
479
-		$n = $ligne;
480
-		while (preg_match(CHAMP_ETENDU, $texte, $match)) {
481
-			$p = strpos($texte, (string) $match[0]);
482
-			$debut = substr($texte, 0, $p);
483
-			if ($p) {
484
-				$result[$i] = $debut;
485
-				$i++;
486
-			}
487
-			$nom = $match[4];
488
-			$champ = new Champ();
489
-			// ca ne marche pas encore en cas de champ imbrique
490
-			$champ->ligne = $x ? 0 : ($n + substr_count($debut, "\n"));
491
-			$champ->nom_boucle = $match[3];
492
-			$champ->nom_champ = $nom;
493
-			$champ->etoile = $match[6];
494
-			// phraser_args indiquera ou commence apres
495
-			$pos_apres = 0;
496
-			$result = phraser_args($match[7], ')', $sep, $result, $champ, $pos_apres);
497
-			phraser_vieux($champ);
498
-			$champ->avant =	phraser_champs_exterieurs($match[1], $n, $sep, $result);
499
-			$debut = substr($match[7], $pos_apres + 1);
500
-			if (!empty($debut)) {
501
-				$n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
502
-			}
503
-			$champ->apres = phraser_champs_exterieurs($debut, $n, $sep, $result);
504
-
505
-			// reinjecter la boucle si c'en est une
506
-			phraser_boucle_placeholder($champ);
507
-
508
-			$result[$i] = $champ;
509
-			$i++;
510
-			$texte = substr($texte, $p + strlen($match[0]));
511
-		}
512
-		if ($texte !== '') {
513
-			$result[$i] = $texte;
514
-			$i++;
515
-		}
516
-		$x = '';
517
-
518
-		while ($j < $i) {
519
-			$z = $result[$j];
520
-			// j'aurais besoin de connaitre le nombre de lignes...
521
-			if (is_object($z)) {
522
-				$x .= "%$sep$j@";
523
-			} else {
524
-				$x .= $z;
525
-			}
526
-			$j++;
527
-		}
528
-		if (preg_match(CHAMP_ETENDU, $x)) {
529
-			$texte = $x;
530
-		} else {
531
-			return phraser_champs_exterieurs($x, $ligne, $sep, $result);
532
-		}
533
-	}
474
+    $i = 0; // en fait count($result)
475
+    $x = '';
476
+
477
+    while (true) {
478
+        $j = $i;
479
+        $n = $ligne;
480
+        while (preg_match(CHAMP_ETENDU, $texte, $match)) {
481
+            $p = strpos($texte, (string) $match[0]);
482
+            $debut = substr($texte, 0, $p);
483
+            if ($p) {
484
+                $result[$i] = $debut;
485
+                $i++;
486
+            }
487
+            $nom = $match[4];
488
+            $champ = new Champ();
489
+            // ca ne marche pas encore en cas de champ imbrique
490
+            $champ->ligne = $x ? 0 : ($n + substr_count($debut, "\n"));
491
+            $champ->nom_boucle = $match[3];
492
+            $champ->nom_champ = $nom;
493
+            $champ->etoile = $match[6];
494
+            // phraser_args indiquera ou commence apres
495
+            $pos_apres = 0;
496
+            $result = phraser_args($match[7], ')', $sep, $result, $champ, $pos_apres);
497
+            phraser_vieux($champ);
498
+            $champ->avant =	phraser_champs_exterieurs($match[1], $n, $sep, $result);
499
+            $debut = substr($match[7], $pos_apres + 1);
500
+            if (!empty($debut)) {
501
+                $n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
502
+            }
503
+            $champ->apres = phraser_champs_exterieurs($debut, $n, $sep, $result);
504
+
505
+            // reinjecter la boucle si c'en est une
506
+            phraser_boucle_placeholder($champ);
507
+
508
+            $result[$i] = $champ;
509
+            $i++;
510
+            $texte = substr($texte, $p + strlen($match[0]));
511
+        }
512
+        if ($texte !== '') {
513
+            $result[$i] = $texte;
514
+            $i++;
515
+        }
516
+        $x = '';
517
+
518
+        while ($j < $i) {
519
+            $z = $result[$j];
520
+            // j'aurais besoin de connaitre le nombre de lignes...
521
+            if (is_object($z)) {
522
+                $x .= "%$sep$j@";
523
+            } else {
524
+                $x .= $z;
525
+            }
526
+            $j++;
527
+        }
528
+        if (preg_match(CHAMP_ETENDU, $x)) {
529
+            $texte = $x;
530
+        } else {
531
+            return phraser_champs_exterieurs($x, $ligne, $sep, $result);
532
+        }
533
+    }
534 534
 }
535 535
 
536 536
 function phraser_vieux(&$champ) {
537
-	$nom = $champ->nom_champ;
538
-	if ($nom == 'EMBED_DOCUMENT') {
539
-		if (!function_exists('phraser_vieux_emb')) {
540
-			include_spip('public/normaliser');
541
-		}
542
-		phraser_vieux_emb($champ);
543
-	} elseif ($nom == 'EXPOSER') {
544
-		if (!function_exists('phraser_vieux_exposer')) {
545
-			include_spip('public/normaliser');
546
-		}
547
-		phraser_vieux_exposer($champ);
548
-	} elseif ($champ->param) {
549
-		if ($nom == 'FORMULAIRE_RECHERCHE') {
550
-			if (!function_exists('phraser_vieux_recherche')) {
551
-				include_spip('public/normaliser');
552
-			}
553
-			phraser_vieux_recherche($champ);
554
-		} elseif (preg_match(',^LOGO_[A-Z]+,', $nom)) {
555
-			if (!function_exists('phraser_vieux_logos')) {
556
-				include_spip('public/normaliser');
557
-			}
558
-			phraser_vieux_logos($champ);
559
-		} elseif ($nom == 'MODELE') {
560
-			if (!function_exists('phraser_vieux_modele')) {
561
-				include_spip('public/normaliser');
562
-			}
563
-			phraser_vieux_modele($champ);
564
-		} elseif ($nom == 'INCLURE' or $nom == 'INCLUDE') {
565
-			if (!function_exists('phraser_vieux_inclu')) {
566
-				include_spip('public/normaliser');
567
-			}
568
-			phraser_vieux_inclu($champ);
569
-		}
570
-	}
537
+    $nom = $champ->nom_champ;
538
+    if ($nom == 'EMBED_DOCUMENT') {
539
+        if (!function_exists('phraser_vieux_emb')) {
540
+            include_spip('public/normaliser');
541
+        }
542
+        phraser_vieux_emb($champ);
543
+    } elseif ($nom == 'EXPOSER') {
544
+        if (!function_exists('phraser_vieux_exposer')) {
545
+            include_spip('public/normaliser');
546
+        }
547
+        phraser_vieux_exposer($champ);
548
+    } elseif ($champ->param) {
549
+        if ($nom == 'FORMULAIRE_RECHERCHE') {
550
+            if (!function_exists('phraser_vieux_recherche')) {
551
+                include_spip('public/normaliser');
552
+            }
553
+            phraser_vieux_recherche($champ);
554
+        } elseif (preg_match(',^LOGO_[A-Z]+,', $nom)) {
555
+            if (!function_exists('phraser_vieux_logos')) {
556
+                include_spip('public/normaliser');
557
+            }
558
+            phraser_vieux_logos($champ);
559
+        } elseif ($nom == 'MODELE') {
560
+            if (!function_exists('phraser_vieux_modele')) {
561
+                include_spip('public/normaliser');
562
+            }
563
+            phraser_vieux_modele($champ);
564
+        } elseif ($nom == 'INCLURE' or $nom == 'INCLUDE') {
565
+            if (!function_exists('phraser_vieux_inclu')) {
566
+                include_spip('public/normaliser');
567
+            }
568
+            phraser_vieux_inclu($champ);
569
+        }
570
+    }
571 571
 }
572 572
 
573 573
 
@@ -595,200 +595,200 @@  discard block
 block discarded – undo
595 595
  **/
596 596
 function phraser_criteres($params, &$result) {
597 597
 
598
-	$err_ci = ''; // indiquera s'il y a eu une erreur
599
-	$args = [];
600
-	$type = $result->type_requete;
601
-	$doublons = [];
602
-	foreach ($params as $v) {
603
-		$var = $v[1][0];
604
-		$param = ($var->type != 'texte') ? '' : $var->texte;
605
-		if (((is_countable($v) ? count($v) : 0) > 2) && (!preg_match(',[^A-Za-z]IN[^A-Za-z],i', $param))) {
606
-			// plus d'un argument et pas le critere IN:
607
-			// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
608
-			if (
609
-				$var->type != 'texte'
610
-				or preg_match('/^(n|n-|(n-)?\d+)$/S', $param)
611
-			) {
612
-				$op = ',';
613
-				$not = false;
614
-				$cond = false;
615
-			} else {
616
-				// Le debut du premier argument est l'operateur
617
-				preg_match('/^([!]?)([a-zA-Z][a-zA-Z0-9_]*)[[:space:]]*(\??)[[:space:]]*(.*)$/ms', $param, $m);
618
-				$op = $m[2];
619
-				$not = (bool) $m[1];
620
-				$cond = $m[3];
621
-				// virer le premier argument,
622
-				// et mettre son reliquat eventuel
623
-				// Recopier pour ne pas alterer le texte source
624
-				// utile au debusqueur
625
-				if ($m[4]) {
626
-					// une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
627
-					if (preg_match(',^(["\'])(.*)\1$,', $m[4])) {
628
-						$c = null;
629
-						eval('$c = ' . $m[4] . ';');
630
-						if (isset($c)) {
631
-							$m[4] = $c;
632
-						}
633
-					}
634
-					$texte = new Texte();
635
-					$texte->texte = $m[4];
636
-					$v[1][0] = $texte;
637
-				} else {
638
-					array_shift($v[1]);
639
-				}
640
-			}
641
-			array_shift($v); // $v[O] est vide
642
-			$crit = new Critere();
643
-			$crit->op = $op;
644
-			$crit->not = $not;
645
-			$crit->cond = $cond;
646
-			$crit->exclus = '';
647
-			$crit->param = $v;
648
-			$args[] = $crit;
649
-		} else {
650
-			if ($var->type != 'texte') {
651
-				// cas 1 seul arg ne commencant pas par du texte brut:
652
-				// erreur ou critere infixe "/"
653
-				if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) != '/')) {
654
-					$err_ci = [
655
-						'zbug_critere_inconnu',
656
-						['critere' => $var->nom_champ]
657
-					];
658
-					erreur_squelette($err_ci, $result);
659
-				} else {
660
-					$crit = new Critere();
661
-					$crit->op = '/';
662
-					$crit->not = false;
663
-					$crit->exclus = '';
664
-					$crit->param = [[$v[1][0]], [$v[1][2]]];
665
-					$args[] = $crit;
666
-				}
667
-			} else {
668
-				// traiter qq lexemes particuliers pour faciliter la suite
669
-				// les separateurs
670
-				if ($var->apres) {
671
-					$result->separateur[] = $param;
672
-				} elseif (($param == 'tout') or ($param == 'tous')) {
673
-					$result->modificateur['tout'] = true;
674
-				} elseif ($param == 'plat') {
675
-					$result->modificateur['plat'] = true;
676
-				}
677
-
678
-				// Boucle hierarchie, analyser le critere id_rubrique
679
-				// et les autres critères {id_x} pour forcer {tout} sur
680
-				// ceux-ci pour avoir la rubrique mere...
681
-				// Les autres critères de la boucle hierarchie doivent Ăªtre
682
-				// traités normalement.
683
-				elseif (
684
-					strcasecmp($type, 'hierarchie') == 0
685
-					and !preg_match(",^id_rubrique\b,", $param)
686
-					and preg_match(',^id_\w+\s*$,', $param)
687
-				) {
688
-					$result->modificateur['tout'] = true;
689
-				} elseif (strcasecmp($type, 'hierarchie') == 0 and $param == 'id_rubrique') {
690
-					// rien a faire sur {id_rubrique} tout seul
691
-				} else {
692
-					// pas d'emplacement statique, faut un dynamique
693
-					// mais il y a 2 cas qui ont les 2 !
694
-					if (($param == 'unique') || (preg_match(',^!?doublons *,', $param))) {
695
-						// cette variable sera inseree dans le code
696
-						// et son nom sert d'indicateur des maintenant
697
-						$result->doublons = '$doublons_index';
698
-						if ($param == 'unique') {
699
-							$param = 'doublons';
700
-						}
701
-					} elseif ($param == 'recherche') {
702
-						// meme chose (a cause de #nom_de_boucle:URL_*)
703
-						$result->hash = ' ';
704
-					}
705
-
706
-					if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
707
-						$crit = phraser_critere_infixe($m[1], $m[3], $v, '/', '', '');
708
-					} elseif (
709
-						preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC .
710
-						')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)
711
-					) {
712
-						$a2 = trim($m[8]);
713
-						if ($a2 and ($a2[0] == "'" or $a2[0] == '"') and ($a2[0] == substr($a2, -1))) {
714
-							$a2 = substr($a2, 1, -1);
715
-						}
716
-						$crit = phraser_critere_infixe(
717
-							$m[2],
718
-							$a2,
719
-							$v,
720
-							(($m[2] == 'lang_select') ? $m[2] : $m[7]),
721
-							$m[6],
722
-							$m[5]
723
-						);
724
-						$crit->exclus = $m[1];
725
-					} elseif (
726
-						preg_match('/^([!]?)\s*(' .
727
-						CHAMP_SQL_PLUS_FONC .
728
-						')\s*(\??)(.*)$/is', $param, $m)
729
-					) {
730
-						// contient aussi les comparaisons implicites !
731
-						// Comme ci-dessus:
732
-						// le premier arg contient l'operateur
733
-						array_shift($v);
734
-						if ($m[6]) {
735
-							$v[0][0] = new Texte();
736
-							$v[0][0]->texte = $m[6];
737
-						} else {
738
-							array_shift($v[0]);
739
-							if (!$v[0]) {
740
-								array_shift($v);
741
-							}
742
-						}
743
-						$crit = new Critere();
744
-						$crit->op = $m[2];
745
-						$crit->param = $v;
746
-						$crit->not = (bool) $m[1];
747
-						$crit->cond = $m[5];
748
-					} else {
749
-						$err_ci = [
750
-							'zbug_critere_inconnu',
751
-							['critere' => $param]
752
-						];
753
-						erreur_squelette($err_ci, $result);
754
-					}
755
-
756
-					if ((!preg_match(',^!?doublons *,', $param)) || $crit->not) {
757
-						$args[] = $crit;
758
-					} else {
759
-						$doublons[] = $crit;
760
-					}
761
-				}
762
-			}
763
-		}
764
-	}
765
-
766
-	// les doublons non nies doivent etre le dernier critere
767
-	// pour que la variable $doublon_index ait la bonne valeur
768
-	// cf critere_doublon
769
-	if ($doublons) {
770
-		$args = [...$args, ...$doublons];
771
-	}
772
-
773
-	// Si erreur, laisser la chaine dans ce champ pour le HTTP 503
774
-	if (!$err_ci) {
775
-		$result->criteres = $args;
776
-	}
598
+    $err_ci = ''; // indiquera s'il y a eu une erreur
599
+    $args = [];
600
+    $type = $result->type_requete;
601
+    $doublons = [];
602
+    foreach ($params as $v) {
603
+        $var = $v[1][0];
604
+        $param = ($var->type != 'texte') ? '' : $var->texte;
605
+        if (((is_countable($v) ? count($v) : 0) > 2) && (!preg_match(',[^A-Za-z]IN[^A-Za-z],i', $param))) {
606
+            // plus d'un argument et pas le critere IN:
607
+            // detecter comme on peut si c'est le critere implicite LIMIT debut, fin
608
+            if (
609
+                $var->type != 'texte'
610
+                or preg_match('/^(n|n-|(n-)?\d+)$/S', $param)
611
+            ) {
612
+                $op = ',';
613
+                $not = false;
614
+                $cond = false;
615
+            } else {
616
+                // Le debut du premier argument est l'operateur
617
+                preg_match('/^([!]?)([a-zA-Z][a-zA-Z0-9_]*)[[:space:]]*(\??)[[:space:]]*(.*)$/ms', $param, $m);
618
+                $op = $m[2];
619
+                $not = (bool) $m[1];
620
+                $cond = $m[3];
621
+                // virer le premier argument,
622
+                // et mettre son reliquat eventuel
623
+                // Recopier pour ne pas alterer le texte source
624
+                // utile au debusqueur
625
+                if ($m[4]) {
626
+                    // une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
627
+                    if (preg_match(',^(["\'])(.*)\1$,', $m[4])) {
628
+                        $c = null;
629
+                        eval('$c = ' . $m[4] . ';');
630
+                        if (isset($c)) {
631
+                            $m[4] = $c;
632
+                        }
633
+                    }
634
+                    $texte = new Texte();
635
+                    $texte->texte = $m[4];
636
+                    $v[1][0] = $texte;
637
+                } else {
638
+                    array_shift($v[1]);
639
+                }
640
+            }
641
+            array_shift($v); // $v[O] est vide
642
+            $crit = new Critere();
643
+            $crit->op = $op;
644
+            $crit->not = $not;
645
+            $crit->cond = $cond;
646
+            $crit->exclus = '';
647
+            $crit->param = $v;
648
+            $args[] = $crit;
649
+        } else {
650
+            if ($var->type != 'texte') {
651
+                // cas 1 seul arg ne commencant pas par du texte brut:
652
+                // erreur ou critere infixe "/"
653
+                if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) != '/')) {
654
+                    $err_ci = [
655
+                        'zbug_critere_inconnu',
656
+                        ['critere' => $var->nom_champ]
657
+                    ];
658
+                    erreur_squelette($err_ci, $result);
659
+                } else {
660
+                    $crit = new Critere();
661
+                    $crit->op = '/';
662
+                    $crit->not = false;
663
+                    $crit->exclus = '';
664
+                    $crit->param = [[$v[1][0]], [$v[1][2]]];
665
+                    $args[] = $crit;
666
+                }
667
+            } else {
668
+                // traiter qq lexemes particuliers pour faciliter la suite
669
+                // les separateurs
670
+                if ($var->apres) {
671
+                    $result->separateur[] = $param;
672
+                } elseif (($param == 'tout') or ($param == 'tous')) {
673
+                    $result->modificateur['tout'] = true;
674
+                } elseif ($param == 'plat') {
675
+                    $result->modificateur['plat'] = true;
676
+                }
677
+
678
+                // Boucle hierarchie, analyser le critere id_rubrique
679
+                // et les autres critères {id_x} pour forcer {tout} sur
680
+                // ceux-ci pour avoir la rubrique mere...
681
+                // Les autres critères de la boucle hierarchie doivent Ăªtre
682
+                // traités normalement.
683
+                elseif (
684
+                    strcasecmp($type, 'hierarchie') == 0
685
+                    and !preg_match(",^id_rubrique\b,", $param)
686
+                    and preg_match(',^id_\w+\s*$,', $param)
687
+                ) {
688
+                    $result->modificateur['tout'] = true;
689
+                } elseif (strcasecmp($type, 'hierarchie') == 0 and $param == 'id_rubrique') {
690
+                    // rien a faire sur {id_rubrique} tout seul
691
+                } else {
692
+                    // pas d'emplacement statique, faut un dynamique
693
+                    // mais il y a 2 cas qui ont les 2 !
694
+                    if (($param == 'unique') || (preg_match(',^!?doublons *,', $param))) {
695
+                        // cette variable sera inseree dans le code
696
+                        // et son nom sert d'indicateur des maintenant
697
+                        $result->doublons = '$doublons_index';
698
+                        if ($param == 'unique') {
699
+                            $param = 'doublons';
700
+                        }
701
+                    } elseif ($param == 'recherche') {
702
+                        // meme chose (a cause de #nom_de_boucle:URL_*)
703
+                        $result->hash = ' ';
704
+                    }
705
+
706
+                    if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
707
+                        $crit = phraser_critere_infixe($m[1], $m[3], $v, '/', '', '');
708
+                    } elseif (
709
+                        preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC .
710
+                        ')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)
711
+                    ) {
712
+                        $a2 = trim($m[8]);
713
+                        if ($a2 and ($a2[0] == "'" or $a2[0] == '"') and ($a2[0] == substr($a2, -1))) {
714
+                            $a2 = substr($a2, 1, -1);
715
+                        }
716
+                        $crit = phraser_critere_infixe(
717
+                            $m[2],
718
+                            $a2,
719
+                            $v,
720
+                            (($m[2] == 'lang_select') ? $m[2] : $m[7]),
721
+                            $m[6],
722
+                            $m[5]
723
+                        );
724
+                        $crit->exclus = $m[1];
725
+                    } elseif (
726
+                        preg_match('/^([!]?)\s*(' .
727
+                        CHAMP_SQL_PLUS_FONC .
728
+                        ')\s*(\??)(.*)$/is', $param, $m)
729
+                    ) {
730
+                        // contient aussi les comparaisons implicites !
731
+                        // Comme ci-dessus:
732
+                        // le premier arg contient l'operateur
733
+                        array_shift($v);
734
+                        if ($m[6]) {
735
+                            $v[0][0] = new Texte();
736
+                            $v[0][0]->texte = $m[6];
737
+                        } else {
738
+                            array_shift($v[0]);
739
+                            if (!$v[0]) {
740
+                                array_shift($v);
741
+                            }
742
+                        }
743
+                        $crit = new Critere();
744
+                        $crit->op = $m[2];
745
+                        $crit->param = $v;
746
+                        $crit->not = (bool) $m[1];
747
+                        $crit->cond = $m[5];
748
+                    } else {
749
+                        $err_ci = [
750
+                            'zbug_critere_inconnu',
751
+                            ['critere' => $param]
752
+                        ];
753
+                        erreur_squelette($err_ci, $result);
754
+                    }
755
+
756
+                    if ((!preg_match(',^!?doublons *,', $param)) || $crit->not) {
757
+                        $args[] = $crit;
758
+                    } else {
759
+                        $doublons[] = $crit;
760
+                    }
761
+                }
762
+            }
763
+        }
764
+    }
765
+
766
+    // les doublons non nies doivent etre le dernier critere
767
+    // pour que la variable $doublon_index ait la bonne valeur
768
+    // cf critere_doublon
769
+    if ($doublons) {
770
+        $args = [...$args, ...$doublons];
771
+    }
772
+
773
+    // Si erreur, laisser la chaine dans ce champ pour le HTTP 503
774
+    if (!$err_ci) {
775
+        $result->criteres = $args;
776
+    }
777 777
 }
778 778
 
779 779
 function phraser_critere_infixe($arg1, $arg2, $args, $op, $not, $cond) {
780
-	$args[0] = new Texte();
781
-	$args[0]->texte = $arg1;
782
-	$args[0] = [$args[0]];
783
-	$args[1][0] = new Texte();
784
-	$args[1][0]->texte = $arg2;
785
-	$crit = new Critere();
786
-	$crit->op = $op;
787
-	$crit->not = $not;
788
-	$crit->cond = $cond;
789
-	$crit->param = $args;
790
-
791
-	return $crit;
780
+    $args[0] = new Texte();
781
+    $args[0]->texte = $arg1;
782
+    $args[0] = [$args[0]];
783
+    $args[1][0] = new Texte();
784
+    $args[1][0]->texte = $arg2;
785
+    $crit = new Critere();
786
+    $crit->op = $op;
787
+    $crit->not = $not;
788
+    $crit->cond = $cond;
789
+    $crit->param = $args;
790
+
791
+    return $crit;
792 792
 }
793 793
 
794 794
 /**
@@ -799,12 +799,12 @@  discard block
 block discarded – undo
799 799
  * @return int
800 800
  */
801 801
 function public_compte_ligne($texte, $debut = 0, $fin = null) {
802
-	if (is_null($fin)) {
803
-		return substr_count($texte, "\n", $debut);
804
-	}
805
-	else {
806
-		return substr_count($texte, "\n", $debut, $fin - $debut);
807
-	}
802
+    if (is_null($fin)) {
803
+        return substr_count($texte, "\n", $debut);
804
+    }
805
+    else {
806
+        return substr_count($texte, "\n", $debut, $fin - $debut);
807
+    }
808 808
 }
809 809
 
810 810
 
@@ -820,87 +820,87 @@  discard block
 block discarded – undo
820 820
  * @return array|null
821 821
  */
822 822
 function public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte = 0) {
823
-	$premiere_boucle = null;
824
-	$pos_derniere_boucle_anonyme = $pos_debut_texte;
825
-
826
-	$current_pos = $pos_debut_texte;
827
-	while (($pos_boucle = strpos($texte, BALISE_BOUCLE, $current_pos)) !== false) {
828
-		$current_pos = $pos_boucle + 1;
829
-		$pos_parent = strpos($texte, '(', $pos_boucle);
830
-
831
-		$id_boucle = '';
832
-		if ($pos_parent !== false) {
833
-			$id_boucle = trim(substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), $pos_parent - $pos_boucle - strlen(BALISE_BOUCLE)));
834
-		}
835
-		if (
836
-			$pos_parent === false
837
-			or (strlen($id_boucle) and !(is_numeric($id_boucle) or strpos($id_boucle, '_') === 0))
838
-		) {
839
-			$result = new Boucle();
840
-			$result->id_parent = $id_parent;
841
-			$result->descr = $descr;
842
-
843
-			// un id_boucle pour l'affichage de l'erreur
844
-			if (!strlen($id_boucle)) {
845
-				$id_boucle = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
846
-			}
847
-			$result->id_boucle = $id_boucle;
848
-			$err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
849
-			erreur_squelette($err_b, $result);
850
-
851
-			continue;
852
-		}
853
-		else {
854
-			$boucle = [
855
-				'id_boucle' => $id_boucle,
856
-				'id_boucle_err' => $id_boucle,
857
-				'debut_boucle' => $pos_boucle,
858
-				'pos_boucle' => $pos_boucle,
859
-				'pos_parent' => $pos_parent,
860
-				'pos_precond' => false,
861
-				'pos_precond_inside' => false,
862
-				'pos_preaff' => false,
863
-				'pos_preaff_inside' => false,
864
-			];
865
-
866
-			// un id_boucle pour l'affichage de l'erreur sur les boucle anonymes
867
-			if (!strlen($id_boucle)) {
868
-				$boucle['id_boucle_err'] = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
869
-			}
870
-
871
-			// trouver sa position de depart reelle : au <Bxx> ou au <BBxx>
872
-			$precond_boucle = BALISE_PRECOND_BOUCLE . $id_boucle . '>';
873
-			$pos_precond = strpos($texte, $precond_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
874
-			if (
875
-				$pos_precond !== false
876
-				and $pos_precond < $boucle['debut_boucle']
877
-			) {
878
-				$boucle['debut_boucle'] = $pos_precond;
879
-				$boucle['pos_precond'] = $pos_precond;
880
-				$boucle['pos_precond_inside'] = $pos_precond + strlen($precond_boucle);
881
-			}
882
-
883
-			$preaff_boucle = BALISE_PREAFF_BOUCLE . $id_boucle . '>';
884
-			$pos_preaff = strpos($texte, $preaff_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
885
-			if (
886
-				$pos_preaff !== false
887
-				and $pos_preaff < $boucle['debut_boucle']
888
-			) {
889
-				$boucle['debut_boucle'] = $pos_preaff;
890
-				$boucle['pos_preaff'] = $pos_preaff;
891
-				$boucle['pos_preaff_inside'] = $pos_preaff + strlen($preaff_boucle);
892
-			}
893
-			if (!strlen($id_boucle)) {
894
-				$pos_derniere_boucle_anonyme = $pos_boucle;
895
-			}
896
-
897
-			if (is_null($premiere_boucle) or $premiere_boucle['debut_boucle'] > $boucle['debut_boucle']) {
898
-				$premiere_boucle = $boucle;
899
-			}
900
-		}
901
-	}
902
-
903
-	return $premiere_boucle;
823
+    $premiere_boucle = null;
824
+    $pos_derniere_boucle_anonyme = $pos_debut_texte;
825
+
826
+    $current_pos = $pos_debut_texte;
827
+    while (($pos_boucle = strpos($texte, BALISE_BOUCLE, $current_pos)) !== false) {
828
+        $current_pos = $pos_boucle + 1;
829
+        $pos_parent = strpos($texte, '(', $pos_boucle);
830
+
831
+        $id_boucle = '';
832
+        if ($pos_parent !== false) {
833
+            $id_boucle = trim(substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), $pos_parent - $pos_boucle - strlen(BALISE_BOUCLE)));
834
+        }
835
+        if (
836
+            $pos_parent === false
837
+            or (strlen($id_boucle) and !(is_numeric($id_boucle) or strpos($id_boucle, '_') === 0))
838
+        ) {
839
+            $result = new Boucle();
840
+            $result->id_parent = $id_parent;
841
+            $result->descr = $descr;
842
+
843
+            // un id_boucle pour l'affichage de l'erreur
844
+            if (!strlen($id_boucle)) {
845
+                $id_boucle = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
846
+            }
847
+            $result->id_boucle = $id_boucle;
848
+            $err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
849
+            erreur_squelette($err_b, $result);
850
+
851
+            continue;
852
+        }
853
+        else {
854
+            $boucle = [
855
+                'id_boucle' => $id_boucle,
856
+                'id_boucle_err' => $id_boucle,
857
+                'debut_boucle' => $pos_boucle,
858
+                'pos_boucle' => $pos_boucle,
859
+                'pos_parent' => $pos_parent,
860
+                'pos_precond' => false,
861
+                'pos_precond_inside' => false,
862
+                'pos_preaff' => false,
863
+                'pos_preaff_inside' => false,
864
+            ];
865
+
866
+            // un id_boucle pour l'affichage de l'erreur sur les boucle anonymes
867
+            if (!strlen($id_boucle)) {
868
+                $boucle['id_boucle_err'] = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
869
+            }
870
+
871
+            // trouver sa position de depart reelle : au <Bxx> ou au <BBxx>
872
+            $precond_boucle = BALISE_PRECOND_BOUCLE . $id_boucle . '>';
873
+            $pos_precond = strpos($texte, $precond_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
874
+            if (
875
+                $pos_precond !== false
876
+                and $pos_precond < $boucle['debut_boucle']
877
+            ) {
878
+                $boucle['debut_boucle'] = $pos_precond;
879
+                $boucle['pos_precond'] = $pos_precond;
880
+                $boucle['pos_precond_inside'] = $pos_precond + strlen($precond_boucle);
881
+            }
882
+
883
+            $preaff_boucle = BALISE_PREAFF_BOUCLE . $id_boucle . '>';
884
+            $pos_preaff = strpos($texte, $preaff_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
885
+            if (
886
+                $pos_preaff !== false
887
+                and $pos_preaff < $boucle['debut_boucle']
888
+            ) {
889
+                $boucle['debut_boucle'] = $pos_preaff;
890
+                $boucle['pos_preaff'] = $pos_preaff;
891
+                $boucle['pos_preaff_inside'] = $pos_preaff + strlen($preaff_boucle);
892
+            }
893
+            if (!strlen($id_boucle)) {
894
+                $pos_derniere_boucle_anonyme = $pos_boucle;
895
+            }
896
+
897
+            if (is_null($premiere_boucle) or $premiere_boucle['debut_boucle'] > $boucle['debut_boucle']) {
898
+                $premiere_boucle = $boucle;
899
+            }
900
+        }
901
+    }
902
+
903
+    return $premiere_boucle;
904 904
 }
905 905
 
906 906
 /**
@@ -915,68 +915,68 @@  discard block
 block discarded – undo
915 915
  * @return mixed
916 916
  */
917 917
 function public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_debut_texte, $result) {
918
-	$id_boucle = $boucle['id_boucle'];
919
-	$pos_courante = $pos_debut_texte;
920
-
921
-	$boucle['pos_postcond'] = false;
922
-	$boucle['pos_postcond_inside'] = false;
923
-	$boucle['pos_altern'] = false;
924
-	$boucle['pos_altern_inside'] = false;
925
-	$boucle['pos_postaff'] = false;
926
-	$boucle['pos_postaff_inside'] = false;
927
-
928
-	$pos_anonyme_next = null;
929
-	// si c'est une boucle anonyme, chercher la position de la prochaine boucle anonyme
930
-	if (!strlen($id_boucle)) {
931
-		$pos_anonyme_next = strpos($texte, BALISE_BOUCLE . '(', $pos_courante);
932
-	}
933
-
934
-	//
935
-	// 1. Recuperer la partie conditionnelle apres
936
-	//
937
-	$apres_boucle = BALISE_POSTCOND_BOUCLE . $id_boucle . '>';
938
-	$pos_apres = strpos($texte, $apres_boucle, $pos_courante);
939
-	if (
940
-		$pos_apres !== false
941
-		and (!$pos_anonyme_next or $pos_apres < $pos_anonyme_next)
942
-	) {
943
-		$boucle['pos_postcond'] = $pos_apres;
944
-		$pos_apres += strlen($apres_boucle);
945
-		$boucle['pos_postcond_inside'] = $pos_apres;
946
-		$pos_courante = $pos_apres ;
947
-	}
948
-
949
-	//
950
-	// 2. Récuperer la partie alternative apres
951
-	//
952
-	$altern_boucle = BALISE_ALT_BOUCLE . $id_boucle . '>';
953
-	$pos_altern = strpos($texte, $altern_boucle, $pos_courante);
954
-	if (
955
-		$pos_altern !== false
956
-		and (!$pos_anonyme_next or $pos_altern < $pos_anonyme_next)
957
-	) {
958
-		$boucle['pos_altern'] = $pos_altern;
959
-		$pos_altern += strlen($altern_boucle);
960
-		$boucle['pos_altern_inside'] = $pos_altern;
961
-		$pos_courante = $pos_altern;
962
-	}
963
-
964
-	//
965
-	// 3. Recuperer la partie footer non alternative
966
-	//
967
-	$postaff_boucle = BALISE_POSTAFF_BOUCLE . $id_boucle . '>';
968
-	$pos_postaff = strpos($texte, $postaff_boucle, $pos_courante);
969
-	if (
970
-		$pos_postaff !== false
971
-		and (!$pos_anonyme_next or $pos_postaff < $pos_anonyme_next)
972
-	) {
973
-		$boucle['pos_postaff'] = $pos_postaff;
974
-		$pos_postaff += strlen($postaff_boucle);
975
-		$boucle['pos_postaff_inside'] = $pos_postaff;
976
-		$pos_courante = $pos_postaff ;
977
-	}
978
-
979
-	return $boucle;
918
+    $id_boucle = $boucle['id_boucle'];
919
+    $pos_courante = $pos_debut_texte;
920
+
921
+    $boucle['pos_postcond'] = false;
922
+    $boucle['pos_postcond_inside'] = false;
923
+    $boucle['pos_altern'] = false;
924
+    $boucle['pos_altern_inside'] = false;
925
+    $boucle['pos_postaff'] = false;
926
+    $boucle['pos_postaff_inside'] = false;
927
+
928
+    $pos_anonyme_next = null;
929
+    // si c'est une boucle anonyme, chercher la position de la prochaine boucle anonyme
930
+    if (!strlen($id_boucle)) {
931
+        $pos_anonyme_next = strpos($texte, BALISE_BOUCLE . '(', $pos_courante);
932
+    }
933
+
934
+    //
935
+    // 1. Recuperer la partie conditionnelle apres
936
+    //
937
+    $apres_boucle = BALISE_POSTCOND_BOUCLE . $id_boucle . '>';
938
+    $pos_apres = strpos($texte, $apres_boucle, $pos_courante);
939
+    if (
940
+        $pos_apres !== false
941
+        and (!$pos_anonyme_next or $pos_apres < $pos_anonyme_next)
942
+    ) {
943
+        $boucle['pos_postcond'] = $pos_apres;
944
+        $pos_apres += strlen($apres_boucle);
945
+        $boucle['pos_postcond_inside'] = $pos_apres;
946
+        $pos_courante = $pos_apres ;
947
+    }
948
+
949
+    //
950
+    // 2. Récuperer la partie alternative apres
951
+    //
952
+    $altern_boucle = BALISE_ALT_BOUCLE . $id_boucle . '>';
953
+    $pos_altern = strpos($texte, $altern_boucle, $pos_courante);
954
+    if (
955
+        $pos_altern !== false
956
+        and (!$pos_anonyme_next or $pos_altern < $pos_anonyme_next)
957
+    ) {
958
+        $boucle['pos_altern'] = $pos_altern;
959
+        $pos_altern += strlen($altern_boucle);
960
+        $boucle['pos_altern_inside'] = $pos_altern;
961
+        $pos_courante = $pos_altern;
962
+    }
963
+
964
+    //
965
+    // 3. Recuperer la partie footer non alternative
966
+    //
967
+    $postaff_boucle = BALISE_POSTAFF_BOUCLE . $id_boucle . '>';
968
+    $pos_postaff = strpos($texte, $postaff_boucle, $pos_courante);
969
+    if (
970
+        $pos_postaff !== false
971
+        and (!$pos_anonyme_next or $pos_postaff < $pos_anonyme_next)
972
+    ) {
973
+        $boucle['pos_postaff'] = $pos_postaff;
974
+        $pos_postaff += strlen($postaff_boucle);
975
+        $boucle['pos_postaff_inside'] = $pos_postaff;
976
+        $pos_courante = $pos_postaff ;
977
+    }
978
+
979
+    return $boucle;
980 980
 }
981 981
 
982 982
 
@@ -986,21 +986,21 @@  discard block
 block discarded – undo
986 986
  * @param null|object $boucle
987 987
  */
988 988
 function phraser_boucle_placeholder(&$champ, $boucle_placeholder = null, $boucle = null) {
989
-	static $boucles_connues = [];
990
-	// si c'est un appel pour memoriser une boucle, memorisons la
991
-	if (is_string($champ) and !empty($boucle_placeholder) and !empty($boucle)) {
992
-		$boucles_connues[$boucle_placeholder][$champ] = &$boucle;
993
-	}
994
-	else {
995
-		if (!empty($champ->nom_champ) and !empty($boucles_connues[$champ->nom_champ])) {
996
-			$placeholder = $champ->nom_champ;
997
-			$id = reset($champ->param[0][1]);
998
-			$id = $id->texte;
999
-			if (!empty($boucles_connues[$placeholder][$id])) {
1000
-				$champ = $boucles_connues[$placeholder][$id];
1001
-			}
1002
-		}
1003
-	}
989
+    static $boucles_connues = [];
990
+    // si c'est un appel pour memoriser une boucle, memorisons la
991
+    if (is_string($champ) and !empty($boucle_placeholder) and !empty($boucle)) {
992
+        $boucles_connues[$boucle_placeholder][$champ] = &$boucle;
993
+    }
994
+    else {
995
+        if (!empty($champ->nom_champ) and !empty($boucles_connues[$champ->nom_champ])) {
996
+            $placeholder = $champ->nom_champ;
997
+            $id = reset($champ->param[0][1]);
998
+            $id = $id->texte;
999
+            if (!empty($boucles_connues[$placeholder][$id])) {
1000
+                $champ = $boucles_connues[$placeholder][$id];
1001
+            }
1002
+        }
1003
+    }
1004 1004
 }
1005 1005
 
1006 1006
 
@@ -1013,274 +1013,274 @@  discard block
 block discarded – undo
1013 1013
  * @return string
1014 1014
  */
1015 1015
 function public_generer_boucle_placeholder($id_boucle, &$boucle, $boucle_placeholder, $nb_lignes) {
1016
-	$placeholder = "[(#{$boucle_placeholder}{" . $id_boucle . '})' . str_pad('', $nb_lignes, "\n") . ']';
1017
-	//memoriser la boucle a reinjecter
1018
-	$id_boucle = "$id_boucle";
1019
-	phraser_boucle_placeholder($id_boucle, $boucle_placeholder, $boucle);
1020
-	return $placeholder;
1016
+    $placeholder = "[(#{$boucle_placeholder}{" . $id_boucle . '})' . str_pad('', $nb_lignes, "\n") . ']';
1017
+    //memoriser la boucle a reinjecter
1018
+    $id_boucle = "$id_boucle";
1019
+    phraser_boucle_placeholder($id_boucle, $boucle_placeholder, $boucle);
1020
+    return $placeholder;
1021 1021
 }
1022 1022
 
1023 1023
 function public_phraser_html_dist($texte, $id_parent, &$boucles, $descr, $ligne_debut_texte = 1, $boucle_placeholder = null) {
1024 1024
 
1025
-	$all_res = [];
1026
-	// definir un placholder pour les boucles dont on est sur d'avoir aucune occurence dans le squelette
1027
-	if (is_null($boucle_placeholder)) {
1028
-		do {
1029
-			$boucle_placeholder = 'BOUCLE_PLACEHOLDER_' . strtoupper(md5(uniqid()));
1030
-		} while (strpos($texte, $boucle_placeholder) !== false);
1031
-	}
1032
-
1033
-	$ligne_debut_initial = $ligne_debut_texte;
1034
-	$pos_debut_texte = 0;
1035
-	while ($boucle = public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte)) {
1036
-		$err_b = ''; // indiquera s'il y a eu une erreur
1037
-		$result = new Boucle();
1038
-		$result->id_parent = $id_parent;
1039
-		$result->descr = $descr;
1040
-
1041
-		$pos_courante = $boucle['pos_boucle'];
1042
-		$pos_parent = $boucle['pos_parent'];
1043
-		$id_boucle_search = $id_boucle = $boucle['id_boucle'];
1044
-
1045
-		$ligne_preaff = $ligne_avant = $ligne_milieu = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_parent);
1046
-
1047
-		// boucle anonyme ?
1048
-		if (!strlen($id_boucle)) {
1049
-			$id_boucle = '_anon_L' . $ligne_milieu . '_' . substr(md5('anonyme:' . $id_parent . ':' . json_encode($boucle, JSON_THROW_ON_ERROR)), 0, 8);
1050
-		}
1051
-
1052
-		$pos_debut_boucle = $pos_courante;
1053
-
1054
-		$pos_milieu = $pos_parent;
1055
-
1056
-		// Regarder si on a une partie conditionnelle avant <B_xxx>
1057
-		if ($boucle['pos_precond'] !== false) {
1058
-			$pos_debut_boucle = $boucle['pos_precond'];
1059
-
1060
-			$pos_avant = $boucle['pos_precond_inside'];
1061
-			$result->avant = substr($texte, $pos_avant, $pos_courante - $pos_avant);
1062
-			$ligne_avant = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_avant);
1063
-		}
1064
-
1065
-		// Regarder si on a une partie inconditionnelle avant <BB_xxx>
1066
-		if ($boucle['pos_preaff'] !== false) {
1067
-			$end_preaff = $pos_debut_boucle;
1068
-
1069
-			$pos_preaff = $boucle['pos_preaff_inside'];
1070
-			$result->preaff = substr($texte, $pos_preaff, $end_preaff - $pos_preaff);
1071
-			$ligne_preaff = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_preaff);
1072
-		}
1073
-
1074
-		$result->id_boucle = $id_boucle;
1075
-
1076
-		if (
1077
-			!preg_match(SPEC_BOUCLE, $texte, $match, 0, $pos_milieu)
1078
-			or ($pos_match = strpos($texte, (string) $match[0], $pos_milieu)) === false
1079
-			or $pos_match > $pos_milieu
1080
-		) {
1081
-			$err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
1082
-			erreur_squelette($err_b, $result);
1083
-
1084
-			$ligne_debut_texte += public_compte_ligne($texte, $pos_debut_texte, $pos_courante + 1);
1085
-			$pos_debut_texte = $pos_courante + 1;
1086
-			continue;
1087
-		}
1088
-
1089
-		$result->type_requete = $match[0];
1090
-		$pos_milieu += strlen($match[0]);
1091
-		$pos_courante = $pos_milieu; // on s'en sert pour compter les lignes plus precisemment
1092
-
1093
-		$type = $match[1];
1094
-		$jointures = trim($match[2]);
1095
-		$table_optionnelle = ($match[3]);
1096
-		if ($jointures) {
1097
-			// on affecte pas ici les jointures explicites, mais dans la compilation
1098
-			// ou elles seront completees des jointures declarees
1099
-			$result->jointures_explicites = $jointures;
1100
-		}
1101
-
1102
-		if ($table_optionnelle) {
1103
-			$result->table_optionnelle = $type;
1104
-		}
1105
-
1106
-		// 1ere passe sur les criteres, vu comme des arguments sans fct
1107
-		// Resultat mis dans result->param
1108
-		$pos_fin_criteres = $pos_milieu;
1109
-		phraser_args($texte, '/>', '', $all_res, $result, $pos_fin_criteres);
1110
-
1111
-		// En 2e passe result->criteres contiendra un tableau
1112
-		// pour l'instant on met le source (chaine) :
1113
-		// si elle reste ici au final, c'est qu'elle contient une erreur
1114
-		$pos_courante = $pos_fin_criteres; // on s'en sert pour compter les lignes plus precisemment
1115
-		$result->criteres = substr($texte, $pos_milieu, $pos_fin_criteres - $pos_milieu);
1116
-		$pos_milieu = $pos_fin_criteres;
1117
-
1118
-		//
1119
-		// Recuperer la fin :
1120
-		//
1121
-		if ($texte[$pos_milieu] === '/') {
1122
-			// boucle autofermante : pas de partie conditionnelle apres
1123
-			$pos_courante += 2;
1124
-			$result->milieu = '';
1125
-		} else {
1126
-			$pos_milieu += 1;
1127
-
1128
-			$fin_boucle = BALISE_FIN_BOUCLE . $id_boucle_search . '>';
1129
-			$pos_fin = strpos($texte, $fin_boucle, $pos_milieu);
1130
-			if ($pos_fin === false) {
1131
-				$err_b = [
1132
-					'zbug_erreur_boucle_fermant',
1133
-					['id' => $id_boucle]
1134
-				];
1135
-				erreur_squelette($err_b, $result);
1136
-				$pos_courante += strlen($fin_boucle);
1137
-			}
1138
-			else {
1139
-				// verifier une eventuelle imbrication d'une boucle homonyme
1140
-				// (interdite, generera une erreur plus loin, mais permet de signaler la bonne erreur)
1141
-				$search_debut_boucle = BALISE_BOUCLE . $id_boucle_search . '(';
1142
-				$search_from = $pos_milieu;
1143
-				$nb_open = 1;
1144
-				$nb_close = 1;
1145
-				$maxiter = 0;
1146
-				do {
1147
-					while (
1148
-						$nb_close < $nb_open
1149
-						and $p = strpos($texte, $fin_boucle, $pos_fin + 1)
1150
-					) {
1151
-						$nb_close++;
1152
-						$pos_fin = $p;
1153
-					}
1154
-					// si on a pas trouve assez de boucles fermantes, sortir de la, on a fait de notre mieux
1155
-					if ($nb_close < $nb_open) {
1156
-						break;
1157
-					}
1158
-					while (
1159
-						$p = strpos($texte, $search_debut_boucle, $search_from)
1160
-						and $p < $pos_fin
1161
-					) {
1162
-						$nb_open++;
1163
-						$search_from = $p + 1;
1164
-					}
1165
-				} while ($nb_close < $nb_open and $maxiter++ < 5);
1166
-
1167
-				$pos_courante = $pos_fin + strlen($fin_boucle);
1168
-			}
1169
-			$result->milieu = substr($texte, $pos_milieu, $pos_fin - $pos_milieu);
1170
-		}
1171
-
1172
-		$ligne_suite = $ligne_apres = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_courante);
1173
-		$boucle = public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_courante, $result);
1174
-
1175
-		//
1176
-		// 1. Partie conditionnelle apres ?
1177
-		//
1178
-		if ($boucle['pos_postcond']) {
1179
-			$result->apres = substr($texte, $pos_courante, $boucle['pos_postcond'] - $pos_courante);
1180
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postcond_inside']);
1181
-			$pos_courante = $boucle['pos_postcond_inside'] ;
1182
-		}
1183
-
1184
-
1185
-		//
1186
-		// 2. Partie alternative apres ?
1187
-		//
1188
-		$ligne_altern = $ligne_suite;
1189
-		if ($boucle['pos_altern']) {
1190
-			$result->altern = substr($texte, $pos_courante, $boucle['pos_altern'] - $pos_courante);
1191
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_altern_inside']);
1192
-			$pos_courante = $boucle['pos_altern_inside'];
1193
-		}
1194
-
1195
-		//
1196
-		// 3. Partie footer non alternative ?
1197
-		//
1198
-		$ligne_postaff = $ligne_suite;
1199
-		if ($boucle['pos_postaff']) {
1200
-			$result->postaff = substr($texte, $pos_courante, $boucle['pos_postaff'] - $pos_courante);
1201
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postaff_inside']);
1202
-			$pos_courante = $boucle['pos_postaff_inside'];
1203
-		}
1204
-
1205
-		$result->ligne = $ligne_preaff;
1206
-
1207
-		if ($p = strpos($type, ':')) {
1208
-			$result->sql_serveur = substr($type, 0, $p);
1209
-			$type = substr($type, $p + 1);
1210
-		}
1211
-		$soustype = strtolower($type);
1212
-
1213
-		if (!isset($GLOBALS['table_des_tables'][$soustype])) {
1214
-			$soustype = $type;
1215
-		}
1216
-
1217
-		$result->type_requete = $soustype;
1218
-		// Lancer la 2e passe sur les criteres si la 1ere etait bonne
1219
-		if (!is_array($result->param)) {
1220
-			$err_b = true;
1221
-		} else {
1222
-			phraser_criteres($result->param, $result);
1223
-			if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
1224
-				$result->type_requete = TYPE_RECURSIF;
1225
-				$args = $result->param;
1226
-				array_unshift(
1227
-					$args,
1228
-					substr($type, strlen(TYPE_RECURSIF))
1229
-				);
1230
-				$result->param = $args;
1231
-			}
1232
-		}
1233
-
1234
-		$descr['id_mere_contexte'] = $id_boucle;
1235
-		$result->milieu = public_phraser_html_dist($result->milieu, $id_boucle, $boucles, $descr, $ligne_milieu, $boucle_placeholder);
1236
-		// reserver la place dans la pile des boucles pour compiler ensuite dans le bon ordre
1237
-		// ie les boucles qui apparaissent dans les partie conditionnelles doivent etre compilees apres cette boucle
1238
-		// si il y a deja une boucle de ce nom, cela declenchera une erreur ensuite
1239
-		if (empty($boucles[$id_boucle])) {
1240
-			$boucles[$id_boucle] = null;
1241
-		}
1242
-		$result->preaff = public_phraser_html_dist($result->preaff, $id_parent, $boucles, $descr, $ligne_preaff, $boucle_placeholder);
1243
-		$result->avant = public_phraser_html_dist($result->avant, $id_parent, $boucles, $descr, $ligne_avant, $boucle_placeholder);
1244
-		$result->apres = public_phraser_html_dist($result->apres, $id_parent, $boucles, $descr, $ligne_apres, $boucle_placeholder);
1245
-		$result->altern = public_phraser_html_dist($result->altern, $id_parent, $boucles, $descr, $ligne_altern, $boucle_placeholder);
1246
-		$result->postaff = public_phraser_html_dist($result->postaff, $id_parent, $boucles, $descr, $ligne_postaff, $boucle_placeholder);
1247
-
1248
-		// Prevenir le generateur de code que le squelette est faux
1249
-		if ($err_b) {
1250
-			$result->type_requete = false;
1251
-		}
1252
-
1253
-		// Verifier qu'il n'y a pas double definition
1254
-		// apres analyse des sous-parties (pas avant).
1255
-		if (!empty($boucles[$id_boucle])) {
1256
-			if ($boucles[$id_boucle]->type_requete !== false) {
1257
-				$err_b_d = [
1258
-					'zbug_erreur_boucle_double',
1259
-					['id' => $id_boucle]
1260
-				];
1261
-				erreur_squelette($err_b_d, $result);
1262
-				// Prevenir le generateur de code que le squelette est faux
1263
-				$boucles[$id_boucle]->type_requete = false;
1264
-			}
1265
-		} else {
1266
-			$boucles[$id_boucle] = $result;
1267
-		}
1268
-
1269
-		// remplacer la boucle par un placeholder qui compte le meme nombre de lignes
1270
-		$placeholder = public_generer_boucle_placeholder($id_boucle, $boucles[$id_boucle], $boucle_placeholder, $ligne_suite - $ligne_debut_texte);
1271
-		$longueur_boucle = $pos_courante - $boucle['debut_boucle'];
1272
-		$texte = substr_replace($texte, $placeholder, $boucle['debut_boucle'], $longueur_boucle);
1273
-		$pos_courante = $pos_courante - $longueur_boucle + strlen($placeholder);
1274
-
1275
-		// phraser la partie avant le debut de la boucle
1276
-		#$all_res = phraser_champs_etendus(substr($texte, $pos_debut_texte, $boucle['debut_boucle'] - $pos_debut_texte), $ligne_debut_texte, $all_res);
1277
-		#$all_res[] = &$boucles[$id_boucle];
1278
-
1279
-		$ligne_debut_texte = $ligne_suite;
1280
-		$pos_debut_texte = $pos_courante;
1281
-	}
1282
-
1283
-	$all_res = phraser_champs_etendus($texte, $ligne_debut_initial, $all_res);
1284
-
1285
-	return $all_res;
1025
+    $all_res = [];
1026
+    // definir un placholder pour les boucles dont on est sur d'avoir aucune occurence dans le squelette
1027
+    if (is_null($boucle_placeholder)) {
1028
+        do {
1029
+            $boucle_placeholder = 'BOUCLE_PLACEHOLDER_' . strtoupper(md5(uniqid()));
1030
+        } while (strpos($texte, $boucle_placeholder) !== false);
1031
+    }
1032
+
1033
+    $ligne_debut_initial = $ligne_debut_texte;
1034
+    $pos_debut_texte = 0;
1035
+    while ($boucle = public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte)) {
1036
+        $err_b = ''; // indiquera s'il y a eu une erreur
1037
+        $result = new Boucle();
1038
+        $result->id_parent = $id_parent;
1039
+        $result->descr = $descr;
1040
+
1041
+        $pos_courante = $boucle['pos_boucle'];
1042
+        $pos_parent = $boucle['pos_parent'];
1043
+        $id_boucle_search = $id_boucle = $boucle['id_boucle'];
1044
+
1045
+        $ligne_preaff = $ligne_avant = $ligne_milieu = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_parent);
1046
+
1047
+        // boucle anonyme ?
1048
+        if (!strlen($id_boucle)) {
1049
+            $id_boucle = '_anon_L' . $ligne_milieu . '_' . substr(md5('anonyme:' . $id_parent . ':' . json_encode($boucle, JSON_THROW_ON_ERROR)), 0, 8);
1050
+        }
1051
+
1052
+        $pos_debut_boucle = $pos_courante;
1053
+
1054
+        $pos_milieu = $pos_parent;
1055
+
1056
+        // Regarder si on a une partie conditionnelle avant <B_xxx>
1057
+        if ($boucle['pos_precond'] !== false) {
1058
+            $pos_debut_boucle = $boucle['pos_precond'];
1059
+
1060
+            $pos_avant = $boucle['pos_precond_inside'];
1061
+            $result->avant = substr($texte, $pos_avant, $pos_courante - $pos_avant);
1062
+            $ligne_avant = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_avant);
1063
+        }
1064
+
1065
+        // Regarder si on a une partie inconditionnelle avant <BB_xxx>
1066
+        if ($boucle['pos_preaff'] !== false) {
1067
+            $end_preaff = $pos_debut_boucle;
1068
+
1069
+            $pos_preaff = $boucle['pos_preaff_inside'];
1070
+            $result->preaff = substr($texte, $pos_preaff, $end_preaff - $pos_preaff);
1071
+            $ligne_preaff = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_preaff);
1072
+        }
1073
+
1074
+        $result->id_boucle = $id_boucle;
1075
+
1076
+        if (
1077
+            !preg_match(SPEC_BOUCLE, $texte, $match, 0, $pos_milieu)
1078
+            or ($pos_match = strpos($texte, (string) $match[0], $pos_milieu)) === false
1079
+            or $pos_match > $pos_milieu
1080
+        ) {
1081
+            $err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
1082
+            erreur_squelette($err_b, $result);
1083
+
1084
+            $ligne_debut_texte += public_compte_ligne($texte, $pos_debut_texte, $pos_courante + 1);
1085
+            $pos_debut_texte = $pos_courante + 1;
1086
+            continue;
1087
+        }
1088
+
1089
+        $result->type_requete = $match[0];
1090
+        $pos_milieu += strlen($match[0]);
1091
+        $pos_courante = $pos_milieu; // on s'en sert pour compter les lignes plus precisemment
1092
+
1093
+        $type = $match[1];
1094
+        $jointures = trim($match[2]);
1095
+        $table_optionnelle = ($match[3]);
1096
+        if ($jointures) {
1097
+            // on affecte pas ici les jointures explicites, mais dans la compilation
1098
+            // ou elles seront completees des jointures declarees
1099
+            $result->jointures_explicites = $jointures;
1100
+        }
1101
+
1102
+        if ($table_optionnelle) {
1103
+            $result->table_optionnelle = $type;
1104
+        }
1105
+
1106
+        // 1ere passe sur les criteres, vu comme des arguments sans fct
1107
+        // Resultat mis dans result->param
1108
+        $pos_fin_criteres = $pos_milieu;
1109
+        phraser_args($texte, '/>', '', $all_res, $result, $pos_fin_criteres);
1110
+
1111
+        // En 2e passe result->criteres contiendra un tableau
1112
+        // pour l'instant on met le source (chaine) :
1113
+        // si elle reste ici au final, c'est qu'elle contient une erreur
1114
+        $pos_courante = $pos_fin_criteres; // on s'en sert pour compter les lignes plus precisemment
1115
+        $result->criteres = substr($texte, $pos_milieu, $pos_fin_criteres - $pos_milieu);
1116
+        $pos_milieu = $pos_fin_criteres;
1117
+
1118
+        //
1119
+        // Recuperer la fin :
1120
+        //
1121
+        if ($texte[$pos_milieu] === '/') {
1122
+            // boucle autofermante : pas de partie conditionnelle apres
1123
+            $pos_courante += 2;
1124
+            $result->milieu = '';
1125
+        } else {
1126
+            $pos_milieu += 1;
1127
+
1128
+            $fin_boucle = BALISE_FIN_BOUCLE . $id_boucle_search . '>';
1129
+            $pos_fin = strpos($texte, $fin_boucle, $pos_milieu);
1130
+            if ($pos_fin === false) {
1131
+                $err_b = [
1132
+                    'zbug_erreur_boucle_fermant',
1133
+                    ['id' => $id_boucle]
1134
+                ];
1135
+                erreur_squelette($err_b, $result);
1136
+                $pos_courante += strlen($fin_boucle);
1137
+            }
1138
+            else {
1139
+                // verifier une eventuelle imbrication d'une boucle homonyme
1140
+                // (interdite, generera une erreur plus loin, mais permet de signaler la bonne erreur)
1141
+                $search_debut_boucle = BALISE_BOUCLE . $id_boucle_search . '(';
1142
+                $search_from = $pos_milieu;
1143
+                $nb_open = 1;
1144
+                $nb_close = 1;
1145
+                $maxiter = 0;
1146
+                do {
1147
+                    while (
1148
+                        $nb_close < $nb_open
1149
+                        and $p = strpos($texte, $fin_boucle, $pos_fin + 1)
1150
+                    ) {
1151
+                        $nb_close++;
1152
+                        $pos_fin = $p;
1153
+                    }
1154
+                    // si on a pas trouve assez de boucles fermantes, sortir de la, on a fait de notre mieux
1155
+                    if ($nb_close < $nb_open) {
1156
+                        break;
1157
+                    }
1158
+                    while (
1159
+                        $p = strpos($texte, $search_debut_boucle, $search_from)
1160
+                        and $p < $pos_fin
1161
+                    ) {
1162
+                        $nb_open++;
1163
+                        $search_from = $p + 1;
1164
+                    }
1165
+                } while ($nb_close < $nb_open and $maxiter++ < 5);
1166
+
1167
+                $pos_courante = $pos_fin + strlen($fin_boucle);
1168
+            }
1169
+            $result->milieu = substr($texte, $pos_milieu, $pos_fin - $pos_milieu);
1170
+        }
1171
+
1172
+        $ligne_suite = $ligne_apres = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_courante);
1173
+        $boucle = public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_courante, $result);
1174
+
1175
+        //
1176
+        // 1. Partie conditionnelle apres ?
1177
+        //
1178
+        if ($boucle['pos_postcond']) {
1179
+            $result->apres = substr($texte, $pos_courante, $boucle['pos_postcond'] - $pos_courante);
1180
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postcond_inside']);
1181
+            $pos_courante = $boucle['pos_postcond_inside'] ;
1182
+        }
1183
+
1184
+
1185
+        //
1186
+        // 2. Partie alternative apres ?
1187
+        //
1188
+        $ligne_altern = $ligne_suite;
1189
+        if ($boucle['pos_altern']) {
1190
+            $result->altern = substr($texte, $pos_courante, $boucle['pos_altern'] - $pos_courante);
1191
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_altern_inside']);
1192
+            $pos_courante = $boucle['pos_altern_inside'];
1193
+        }
1194
+
1195
+        //
1196
+        // 3. Partie footer non alternative ?
1197
+        //
1198
+        $ligne_postaff = $ligne_suite;
1199
+        if ($boucle['pos_postaff']) {
1200
+            $result->postaff = substr($texte, $pos_courante, $boucle['pos_postaff'] - $pos_courante);
1201
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postaff_inside']);
1202
+            $pos_courante = $boucle['pos_postaff_inside'];
1203
+        }
1204
+
1205
+        $result->ligne = $ligne_preaff;
1206
+
1207
+        if ($p = strpos($type, ':')) {
1208
+            $result->sql_serveur = substr($type, 0, $p);
1209
+            $type = substr($type, $p + 1);
1210
+        }
1211
+        $soustype = strtolower($type);
1212
+
1213
+        if (!isset($GLOBALS['table_des_tables'][$soustype])) {
1214
+            $soustype = $type;
1215
+        }
1216
+
1217
+        $result->type_requete = $soustype;
1218
+        // Lancer la 2e passe sur les criteres si la 1ere etait bonne
1219
+        if (!is_array($result->param)) {
1220
+            $err_b = true;
1221
+        } else {
1222
+            phraser_criteres($result->param, $result);
1223
+            if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
1224
+                $result->type_requete = TYPE_RECURSIF;
1225
+                $args = $result->param;
1226
+                array_unshift(
1227
+                    $args,
1228
+                    substr($type, strlen(TYPE_RECURSIF))
1229
+                );
1230
+                $result->param = $args;
1231
+            }
1232
+        }
1233
+
1234
+        $descr['id_mere_contexte'] = $id_boucle;
1235
+        $result->milieu = public_phraser_html_dist($result->milieu, $id_boucle, $boucles, $descr, $ligne_milieu, $boucle_placeholder);
1236
+        // reserver la place dans la pile des boucles pour compiler ensuite dans le bon ordre
1237
+        // ie les boucles qui apparaissent dans les partie conditionnelles doivent etre compilees apres cette boucle
1238
+        // si il y a deja une boucle de ce nom, cela declenchera une erreur ensuite
1239
+        if (empty($boucles[$id_boucle])) {
1240
+            $boucles[$id_boucle] = null;
1241
+        }
1242
+        $result->preaff = public_phraser_html_dist($result->preaff, $id_parent, $boucles, $descr, $ligne_preaff, $boucle_placeholder);
1243
+        $result->avant = public_phraser_html_dist($result->avant, $id_parent, $boucles, $descr, $ligne_avant, $boucle_placeholder);
1244
+        $result->apres = public_phraser_html_dist($result->apres, $id_parent, $boucles, $descr, $ligne_apres, $boucle_placeholder);
1245
+        $result->altern = public_phraser_html_dist($result->altern, $id_parent, $boucles, $descr, $ligne_altern, $boucle_placeholder);
1246
+        $result->postaff = public_phraser_html_dist($result->postaff, $id_parent, $boucles, $descr, $ligne_postaff, $boucle_placeholder);
1247
+
1248
+        // Prevenir le generateur de code que le squelette est faux
1249
+        if ($err_b) {
1250
+            $result->type_requete = false;
1251
+        }
1252
+
1253
+        // Verifier qu'il n'y a pas double definition
1254
+        // apres analyse des sous-parties (pas avant).
1255
+        if (!empty($boucles[$id_boucle])) {
1256
+            if ($boucles[$id_boucle]->type_requete !== false) {
1257
+                $err_b_d = [
1258
+                    'zbug_erreur_boucle_double',
1259
+                    ['id' => $id_boucle]
1260
+                ];
1261
+                erreur_squelette($err_b_d, $result);
1262
+                // Prevenir le generateur de code que le squelette est faux
1263
+                $boucles[$id_boucle]->type_requete = false;
1264
+            }
1265
+        } else {
1266
+            $boucles[$id_boucle] = $result;
1267
+        }
1268
+
1269
+        // remplacer la boucle par un placeholder qui compte le meme nombre de lignes
1270
+        $placeholder = public_generer_boucle_placeholder($id_boucle, $boucles[$id_boucle], $boucle_placeholder, $ligne_suite - $ligne_debut_texte);
1271
+        $longueur_boucle = $pos_courante - $boucle['debut_boucle'];
1272
+        $texte = substr_replace($texte, $placeholder, $boucle['debut_boucle'], $longueur_boucle);
1273
+        $pos_courante = $pos_courante - $longueur_boucle + strlen($placeholder);
1274
+
1275
+        // phraser la partie avant le debut de la boucle
1276
+        #$all_res = phraser_champs_etendus(substr($texte, $pos_debut_texte, $boucle['debut_boucle'] - $pos_debut_texte), $ligne_debut_texte, $all_res);
1277
+        #$all_res[] = &$boucles[$id_boucle];
1278
+
1279
+        $ligne_debut_texte = $ligne_suite;
1280
+        $pos_debut_texte = $pos_courante;
1281
+    }
1282
+
1283
+    $all_res = phraser_champs_etendus($texte, $ligne_debut_initial, $all_res);
1284
+
1285
+    return $all_res;
1286 1286
 }
Please login to merge, or discard this patch.
ecrire/inc_version.php 1 patch
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
  **/
20 20
 
21 21
 if (defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 /**
@@ -39,15 +39,15 @@  discard block
 block discarded – undo
39 39
 define('_PHP_MAX', '8.2.99');
40 40
 
41 41
 if (!defined('_DIR_RESTREINT_ABS')) {
42
-	/** le nom du repertoire ecrire/ */
43
-	define('_DIR_RESTREINT_ABS', 'ecrire/');
42
+    /** le nom du repertoire ecrire/ */
43
+    define('_DIR_RESTREINT_ABS', 'ecrire/');
44 44
 }
45 45
 
46 46
 /** Chemin relatif pour aller dans ecrire
47 47
  *  vide si on est dans ecrire, 'ecrire/' sinon */
48 48
 define(
49
-	'_DIR_RESTREINT',
50
-	(!is_dir(_DIR_RESTREINT_ABS) ? '' : _DIR_RESTREINT_ABS)
49
+    '_DIR_RESTREINT',
50
+    (!is_dir(_DIR_RESTREINT_ABS) ? '' : _DIR_RESTREINT_ABS)
51 51
 );
52 52
 
53 53
 /** Chemin relatif pour aller Ă  la racine */
@@ -62,8 +62,8 @@  discard block
 block discarded – undo
62 62
 
63 63
 // Icones
64 64
 if (!defined('_NOM_IMG_PACK')) {
65
-	/** Nom du dossier images */
66
-	define('_NOM_IMG_PACK', 'images/');
65
+    /** Nom du dossier images */
66
+    define('_NOM_IMG_PACK', 'images/');
67 67
 }
68 68
 /** le chemin http (relatif) vers les images standard */
69 69
 define('_DIR_IMG_PACK', (_DIR_RACINE . 'prive/' . _NOM_IMG_PACK));
@@ -72,8 +72,8 @@  discard block
 block discarded – undo
72 72
 define('_ROOT_IMG_PACK', dirname(__DIR__) . '/prive/' . _NOM_IMG_PACK);
73 73
 
74 74
 if (!defined('_JAVASCRIPT')) {
75
-	/** Nom du repertoire des  bibliotheques JavaScript */
76
-	define('_JAVASCRIPT', 'javascript/');
75
+    /** Nom du repertoire des  bibliotheques JavaScript */
76
+    define('_JAVASCRIPT', 'javascript/');
77 77
 } // utilisable avec #CHEMIN et find_in_path
78 78
 /** le nom du repertoire des  bibliotheques JavaScript du prive */
79 79
 define('_DIR_JAVASCRIPT', (_DIR_RACINE . 'prive/' . _JAVASCRIPT));
@@ -83,47 +83,47 @@  discard block
 block discarded – undo
83 83
 # mais on peut les mettre ailleurs et changer completement les noms
84 84
 
85 85
 if (!defined('_NOM_TEMPORAIRES_INACCESSIBLES')) {
86
-	/** Nom du repertoire des fichiers Temporaires Inaccessibles par http:// */
87
-	define('_NOM_TEMPORAIRES_INACCESSIBLES', 'tmp/');
86
+    /** Nom du repertoire des fichiers Temporaires Inaccessibles par http:// */
87
+    define('_NOM_TEMPORAIRES_INACCESSIBLES', 'tmp/');
88 88
 }
89 89
 if (!defined('_NOM_TEMPORAIRES_ACCESSIBLES')) {
90
-	/** Nom du repertoire des fichiers Temporaires Accessibles par http:// */
91
-	define('_NOM_TEMPORAIRES_ACCESSIBLES', 'local/');
90
+    /** Nom du repertoire des fichiers Temporaires Accessibles par http:// */
91
+    define('_NOM_TEMPORAIRES_ACCESSIBLES', 'local/');
92 92
 }
93 93
 if (!defined('_NOM_PERMANENTS_INACCESSIBLES')) {
94
-	/** Nom du repertoire des fichiers Permanents Inaccessibles par http:// */
95
-	define('_NOM_PERMANENTS_INACCESSIBLES', 'config/');
94
+    /** Nom du repertoire des fichiers Permanents Inaccessibles par http:// */
95
+    define('_NOM_PERMANENTS_INACCESSIBLES', 'config/');
96 96
 }
97 97
 if (!defined('_NOM_PERMANENTS_ACCESSIBLES')) {
98
-	/** Nom du repertoire des fichiers Permanents Accessibles par http:// */
99
-	define('_NOM_PERMANENTS_ACCESSIBLES', 'IMG/');
98
+    /** Nom du repertoire des fichiers Permanents Accessibles par http:// */
99
+    define('_NOM_PERMANENTS_ACCESSIBLES', 'IMG/');
100 100
 }
101 101
 
102 102
 
103 103
 /** Le nom du fichier de personnalisation */
104 104
 if (!defined('_NOM_CONFIG')) {
105
-	define('_NOM_CONFIG', 'mes_options');
105
+    define('_NOM_CONFIG', 'mes_options');
106 106
 }
107 107
 
108 108
 // Son emplacement absolu si on le trouve
109 109
 if (
110
-	@file_exists($f = _ROOT_RACINE . _NOM_PERMANENTS_INACCESSIBLES . _NOM_CONFIG . '.php')
111
-	or (@file_exists($f = _ROOT_RESTREINT . _NOM_CONFIG . '.php'))
110
+    @file_exists($f = _ROOT_RACINE . _NOM_PERMANENTS_INACCESSIBLES . _NOM_CONFIG . '.php')
111
+    or (@file_exists($f = _ROOT_RESTREINT . _NOM_CONFIG . '.php'))
112 112
 ) {
113
-	/** Emplacement absolu du fichier d'option */
114
-	define('_FILE_OPTIONS', $f);
113
+    /** Emplacement absolu du fichier d'option */
114
+    define('_FILE_OPTIONS', $f);
115 115
 } else {
116
-	define('_FILE_OPTIONS', '');
116
+    define('_FILE_OPTIONS', '');
117 117
 }
118 118
 
119 119
 if (!defined('MODULES_IDIOMES')) {
120
-	/**
121
-	 * Modules par défaut pour la traduction.
122
-	 *
123
-	 * Constante utilisée par le compilateur et le décompilateur
124
-	 * sa valeur etant traitée par inc_traduire_dist
125
-	 */
126
-	define('MODULES_IDIOMES', 'public|spip|ecrire');
120
+    /**
121
+     * Modules par défaut pour la traduction.
122
+     *
123
+     * Constante utilisée par le compilateur et le décompilateur
124
+     * sa valeur etant traitée par inc_traduire_dist
125
+     */
126
+    define('MODULES_IDIOMES', 'public|spip|ecrire');
127 127
 }
128 128
 
129 129
 // *** Fin des define *** //
@@ -131,10 +131,10 @@  discard block
 block discarded – undo
131 131
 
132 132
 // inclure l'ecran de securite
133 133
 if (
134
-	!defined('_ECRAN_SECURITE')
135
-	and @file_exists($f = _ROOT_RACINE . _NOM_PERMANENTS_INACCESSIBLES . 'ecran_securite.php')
134
+    !defined('_ECRAN_SECURITE')
135
+    and @file_exists($f = _ROOT_RACINE . _NOM_PERMANENTS_INACCESSIBLES . 'ecran_securite.php')
136 136
 ) {
137
-	include $f;
137
+    include $f;
138 138
 }
139 139
 
140 140
 
@@ -142,30 +142,30 @@  discard block
 block discarded – undo
142 142
  * Détecteur de robot d'indexation
143 143
  */
144 144
 if (!defined('_IS_BOT')) {
145
-	define(
146
-		'_IS_BOT',
147
-		isset($_SERVER['HTTP_USER_AGENT'])
148
-		and preg_match(
149
-			// mots generiques
150
-			',bot|slurp|crawler|spider|webvac|yandex|'
151
-			// MSIE 6.0 est un botnet 99,9% du temps, on traite donc ce USER_AGENT comme un bot
152
-			. 'MSIE 6\.0|'
153
-			// UA plus cibles
154
-			. '80legs|accoona|AltaVista|ASPSeek|Baidu|Charlotte|EC2LinkFinder|eStyle|facebook|flipboard|hootsuite|FunWebProducts|Google|Genieo|INA dlweb|InfegyAtlas|Java VM|LiteFinder|Lycos|MetaURI|Moreover|Rambler|Scooter|ScrubbyBloglines|Yahoo|Yeti'
155
-			. ',i',
156
-			(string)$_SERVER['HTTP_USER_AGENT']
157
-		)
158
-	);
145
+    define(
146
+        '_IS_BOT',
147
+        isset($_SERVER['HTTP_USER_AGENT'])
148
+        and preg_match(
149
+            // mots generiques
150
+            ',bot|slurp|crawler|spider|webvac|yandex|'
151
+            // MSIE 6.0 est un botnet 99,9% du temps, on traite donc ce USER_AGENT comme un bot
152
+            . 'MSIE 6\.0|'
153
+            // UA plus cibles
154
+            . '80legs|accoona|AltaVista|ASPSeek|Baidu|Charlotte|EC2LinkFinder|eStyle|facebook|flipboard|hootsuite|FunWebProducts|Google|Genieo|INA dlweb|InfegyAtlas|Java VM|LiteFinder|Lycos|MetaURI|Moreover|Rambler|Scooter|ScrubbyBloglines|Yahoo|Yeti'
155
+            . ',i',
156
+            (string)$_SERVER['HTTP_USER_AGENT']
157
+        )
158
+    );
159 159
 }
160 160
 
161 161
 if (!defined('_IS_CLI')) {
162
-	define(
163
-		'_IS_CLI',
164
-		!isset($_SERVER['HTTP_HOST'])
165
-		and !strlen($_SERVER['DOCUMENT_ROOT'])
166
-		and !empty($_SERVER['argv'])
167
-		and empty($_SERVER['REQUEST_METHOD'])
168
-	);
162
+    define(
163
+        '_IS_CLI',
164
+        !isset($_SERVER['HTTP_HOST'])
165
+        and !strlen($_SERVER['DOCUMENT_ROOT'])
166
+        and !empty($_SERVER['argv'])
167
+        and empty($_SERVER['REQUEST_METHOD'])
168
+    );
169 169
 }
170 170
 
171 171
 // *** Parametrage par defaut de SPIP ***
@@ -177,61 +177,61 @@  discard block
 block discarded – undo
177 177
 // Ne pas les rendre indefinies.
178 178
 
179 179
 global
180
-	$nombre_de_logs,
181
-	$taille_des_logs,
182
-	$table_prefix,
183
-	$cookie_prefix,
184
-	$dossier_squelettes,
185
-	$filtrer_javascript,
186
-	$type_urls,
187
-	$debut_date_publication,
188
-	$ip,
189
-	$mysql_rappel_connexion,
190
-	$mysql_rappel_nom_base,
191
-	$test_i18n,
192
-	$ignore_auth_http,
193
-	$ignore_remote_user,
194
-	$derniere_modif_invalide,
195
-	$home_server,
196
-	$help_server,
197
-	$url_glossaire_externe,
198
-	$tex_server,
199
-	$traiter_math,
200
-	$xhtml,
201
-	$xml_indent,
202
-	$source_vignettes,
203
-	$formats_logos,
204
-	$controler_dates_rss,
205
-	$spip_pipeline,
206
-	$spip_matrice,
207
-	$plugins,
208
-	$surcharges,
209
-	$exceptions_des_tables,
210
-	$tables_principales,
211
-	$table_des_tables,
212
-	$tables_auxiliaires,
213
-	$table_primary,
214
-	$table_date,
215
-	$table_titre,
216
-	$tables_jointures,
217
-	$liste_des_statuts,
218
-	$liste_des_etats,
219
-	$liste_des_authentifications,
220
-	$spip_version_branche,
221
-	$spip_version_code,
222
-	$spip_version_base,
223
-	$spip_sql_version,
224
-	$spip_version_affichee,
225
-	$visiteur_session,
226
-	$auteur_session,
227
-	$connect_statut,
228
-	$connect_toutes_rubriques,
229
-	$hash_recherche,
230
-	$hash_recherche_strict,
231
-	$ldap_present,
232
-	$meta,
233
-	$connect_id_rubrique,
234
-	$puce;
180
+    $nombre_de_logs,
181
+    $taille_des_logs,
182
+    $table_prefix,
183
+    $cookie_prefix,
184
+    $dossier_squelettes,
185
+    $filtrer_javascript,
186
+    $type_urls,
187
+    $debut_date_publication,
188
+    $ip,
189
+    $mysql_rappel_connexion,
190
+    $mysql_rappel_nom_base,
191
+    $test_i18n,
192
+    $ignore_auth_http,
193
+    $ignore_remote_user,
194
+    $derniere_modif_invalide,
195
+    $home_server,
196
+    $help_server,
197
+    $url_glossaire_externe,
198
+    $tex_server,
199
+    $traiter_math,
200
+    $xhtml,
201
+    $xml_indent,
202
+    $source_vignettes,
203
+    $formats_logos,
204
+    $controler_dates_rss,
205
+    $spip_pipeline,
206
+    $spip_matrice,
207
+    $plugins,
208
+    $surcharges,
209
+    $exceptions_des_tables,
210
+    $tables_principales,
211
+    $table_des_tables,
212
+    $tables_auxiliaires,
213
+    $table_primary,
214
+    $table_date,
215
+    $table_titre,
216
+    $tables_jointures,
217
+    $liste_des_statuts,
218
+    $liste_des_etats,
219
+    $liste_des_authentifications,
220
+    $spip_version_branche,
221
+    $spip_version_code,
222
+    $spip_version_base,
223
+    $spip_sql_version,
224
+    $spip_version_affichee,
225
+    $visiteur_session,
226
+    $auteur_session,
227
+    $connect_statut,
228
+    $connect_toutes_rubriques,
229
+    $hash_recherche,
230
+    $hash_recherche_strict,
231
+    $ldap_present,
232
+    $meta,
233
+    $connect_id_rubrique,
234
+    $puce;
235 235
 
236 236
 # comment on logge, defaut 4 tmp/spip.log de 100k, 0 ou 0 suppriment le log
237 237
 $nombre_de_logs = 4;
@@ -286,48 +286,48 @@  discard block
 block discarded – undo
286 286
 // Prendre en compte les entetes HTTP_X_FORWARDED_XX
287 287
 //
288 288
 if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
289
-	if (empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
290
-		$_SERVER['HTTP_X_FORWARDED_HOST'] = $_SERVER['HTTP_HOST'];
291
-	}
292
-	if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
293
-		$_SERVER['HTTP_X_FORWARDED_PORT'] = 443;
294
-	}
289
+    if (empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
290
+        $_SERVER['HTTP_X_FORWARDED_HOST'] = $_SERVER['HTTP_HOST'];
291
+    }
292
+    if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
293
+        $_SERVER['HTTP_X_FORWARDED_PORT'] = 443;
294
+    }
295 295
 }
296 296
 if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
297
-	if (isset($_SERVER['HTTP_X_FORWARDED_PORT']) and is_numeric($_SERVER['HTTP_X_FORWARDED_PORT'])) {
298
-		$_SERVER['SERVER_PORT'] = $_SERVER['HTTP_X_FORWARDED_PORT'];
299
-		if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
300
-			$_SERVER['HTTPS'] = 'on';
301
-			if (isset($_SERVER['REQUEST_SCHEME'])) {
302
-				$_SERVER['REQUEST_SCHEME'] = 'https';
303
-			}
304
-		}
305
-	}
306
-	$host = $_SERVER['HTTP_X_FORWARDED_HOST'];
307
-	if (strpos($host, ',') !== false) {
308
-		$h = explode(',', $host);
309
-		$host = trim(reset($h));
310
-	}
311
-	// securite sur le contenu de l'entete
312
-	$host = strtr($host, "<>?\"\{\}\$'` \r\n", '____________');
313
-	$_SERVER['HTTP_HOST'] = $host;
297
+    if (isset($_SERVER['HTTP_X_FORWARDED_PORT']) and is_numeric($_SERVER['HTTP_X_FORWARDED_PORT'])) {
298
+        $_SERVER['SERVER_PORT'] = $_SERVER['HTTP_X_FORWARDED_PORT'];
299
+        if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
300
+            $_SERVER['HTTPS'] = 'on';
301
+            if (isset($_SERVER['REQUEST_SCHEME'])) {
302
+                $_SERVER['REQUEST_SCHEME'] = 'https';
303
+            }
304
+        }
305
+    }
306
+    $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
307
+    if (strpos($host, ',') !== false) {
308
+        $h = explode(',', $host);
309
+        $host = trim(reset($h));
310
+    }
311
+    // securite sur le contenu de l'entete
312
+    $host = strtr($host, "<>?\"\{\}\$'` \r\n", '____________');
313
+    $_SERVER['HTTP_HOST'] = $host;
314 314
 }
315 315
 //
316 316
 // On note le numero IP du client dans la variable $ip
317 317
 //
318 318
 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
319
-	$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
320
-	if (strpos($ip, ',') !== false) {
321
-		$ip = explode(',', $ip);
322
-		$ip = reset($ip);
323
-	}
324
-	// ecraser $_SERVER['REMOTE_ADDR'] si elle est en localhost
325
-	if (isset($_SERVER['REMOTE_ADDR']) and $_SERVER['REMOTE_ADDR'] === '127.0.0.1') {
326
-		$_SERVER['REMOTE_ADDR'] = $ip;
327
-	}
319
+    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
320
+    if (strpos($ip, ',') !== false) {
321
+        $ip = explode(',', $ip);
322
+        $ip = reset($ip);
323
+    }
324
+    // ecraser $_SERVER['REMOTE_ADDR'] si elle est en localhost
325
+    if (isset($_SERVER['REMOTE_ADDR']) and $_SERVER['REMOTE_ADDR'] === '127.0.0.1') {
326
+        $_SERVER['REMOTE_ADDR'] = $ip;
327
+    }
328 328
 }
329 329
 if (isset($_SERVER['REMOTE_ADDR'])) {
330
-	$ip = $_SERVER['REMOTE_ADDR'];
330
+    $ip = $_SERVER['REMOTE_ADDR'];
331 331
 }
332 332
 
333 333
 // Pour renforcer la privacy, decommentez la ligne ci-dessous (ou recopiez-la
@@ -412,24 +412,24 @@  discard block
 block discarded – undo
412 412
 
413 413
 // Liste des statuts.
414 414
 $liste_des_statuts = [
415
-	'info_administrateurs' => '0minirezo',
416
-	'info_redacteurs' => '1comite',
417
-	'info_visiteurs' => '6forum',
418
-	'texte_statut_poubelle' => '5poubelle'
415
+    'info_administrateurs' => '0minirezo',
416
+    'info_redacteurs' => '1comite',
417
+    'info_visiteurs' => '6forum',
418
+    'texte_statut_poubelle' => '5poubelle'
419 419
 ];
420 420
 
421 421
 $liste_des_etats = [
422
-	'texte_statut_en_cours_redaction' => 'prepa',
423
-	'texte_statut_propose_evaluation' => 'prop',
424
-	'texte_statut_publie' => 'publie',
425
-	'texte_statut_poubelle' => 'poubelle',
426
-	'texte_statut_refuse' => 'refuse'
422
+    'texte_statut_en_cours_redaction' => 'prepa',
423
+    'texte_statut_propose_evaluation' => 'prop',
424
+    'texte_statut_publie' => 'publie',
425
+    'texte_statut_poubelle' => 'poubelle',
426
+    'texte_statut_refuse' => 'refuse'
427 427
 ];
428 428
 
429 429
 // liste des methodes d'authentifications
430 430
 $liste_des_authentifications = [
431
-	'spip' => 'spip',
432
-	'ldap' => 'ldap'
431
+    'spip' => 'spip',
432
+    'ldap' => 'ldap'
433 433
 ];
434 434
 
435 435
 // Experimental : pour supprimer systematiquement l'affichage des numeros
@@ -479,12 +479,12 @@  discard block
 block discarded – undo
479 479
 // Definition personnelles eventuelles
480 480
 
481 481
 if (_FILE_OPTIONS) {
482
-	include_once _FILE_OPTIONS;
482
+    include_once _FILE_OPTIONS;
483 483
 }
484 484
 
485 485
 if (!defined('SPIP_ERREUR_REPORT')) {
486
-	/** Masquer les warning */
487
-	define('SPIP_ERREUR_REPORT', E_ALL ^ E_NOTICE ^ E_DEPRECATED);
486
+    /** Masquer les warning */
487
+    define('SPIP_ERREUR_REPORT', E_ALL ^ E_NOTICE ^ E_DEPRECATED);
488 488
 }
489 489
 error_reporting(SPIP_ERREUR_REPORT);
490 490
 
@@ -497,10 +497,10 @@  discard block
 block discarded – undo
497 497
 // ===> on execute en neutralisant les messages d'erreur
498 498
 
499 499
 spip_initialisation_core(
500
-	(_DIR_RACINE . _NOM_PERMANENTS_INACCESSIBLES),
501
-	(_DIR_RACINE . _NOM_PERMANENTS_ACCESSIBLES),
502
-	(_DIR_RACINE . _NOM_TEMPORAIRES_INACCESSIBLES),
503
-	(_DIR_RACINE . _NOM_TEMPORAIRES_ACCESSIBLES)
500
+    (_DIR_RACINE . _NOM_PERMANENTS_INACCESSIBLES),
501
+    (_DIR_RACINE . _NOM_PERMANENTS_ACCESSIBLES),
502
+    (_DIR_RACINE . _NOM_TEMPORAIRES_INACCESSIBLES),
503
+    (_DIR_RACINE . _NOM_TEMPORAIRES_ACCESSIBLES)
504 504
 );
505 505
 
506 506
 
@@ -510,70 +510,70 @@  discard block
 block discarded – undo
510 510
 // donc il faut avoir tout fini ici avant de charger les plugins
511 511
 
512 512
 if (@is_readable(_CACHE_PLUGINS_OPT) and @is_readable(_CACHE_PLUGINS_PATH)) {
513
-	// chargement optimise precompile
514
-	include_once(_CACHE_PLUGINS_OPT);
513
+    // chargement optimise precompile
514
+    include_once(_CACHE_PLUGINS_OPT);
515 515
 } else {
516
-	spip_initialisation_suite();
517
-	include_spip('inc/plugin');
518
-	// generer les fichiers php precompiles
519
-	// de chargement des plugins et des pipelines
520
-	actualise_plugins_actifs();
516
+    spip_initialisation_suite();
517
+    include_spip('inc/plugin');
518
+    // generer les fichiers php precompiles
519
+    // de chargement des plugins et des pipelines
520
+    actualise_plugins_actifs();
521 521
 }
522 522
 
523 523
 // Initialisations non critiques surchargeables par les plugins
524 524
 spip_initialisation_suite();
525 525
 
526 526
 if (!defined('_LOG_FILTRE_GRAVITE')) {
527
-	/** niveau maxi d'enregistrement des logs */
528
-	define('_LOG_FILTRE_GRAVITE', _LOG_INFO_IMPORTANTE);
527
+    /** niveau maxi d'enregistrement des logs */
528
+    define('_LOG_FILTRE_GRAVITE', _LOG_INFO_IMPORTANTE);
529 529
 }
530 530
 
531 531
 if (!defined('_OUTILS_DEVELOPPEURS')) {
532
-	/** Activer des outils pour développeurs ? */
533
-	define('_OUTILS_DEVELOPPEURS', false);
532
+    /** Activer des outils pour développeurs ? */
533
+    define('_OUTILS_DEVELOPPEURS', false);
534 534
 }
535 535
 
536 536
 // charger systematiquement inc/autoriser dans l'espace restreint
537 537
 if (test_espace_prive()) {
538
-	include_spip('inc/autoriser');
538
+    include_spip('inc/autoriser');
539 539
 }
540 540
 //
541 541
 // Installer Spip si pas installe... sauf si justement on est en train
542 542
 //
543 543
 if (
544
-	!(_FILE_CONNECT
545
-	or autoriser_sans_cookie(_request('exec'))
546
-	or _request('action') == 'cookie'
547
-	or _request('action') == 'converser'
548
-	or _request('action') == 'test_dirs')
544
+    !(_FILE_CONNECT
545
+    or autoriser_sans_cookie(_request('exec'))
546
+    or _request('action') == 'cookie'
547
+    or _request('action') == 'converser'
548
+    or _request('action') == 'test_dirs')
549 549
 ) {
550
-	// Si on peut installer, on lance illico
551
-	if (test_espace_prive()) {
552
-		include_spip('inc/headers');
553
-		redirige_url_ecrire('install');
554
-	} else {
555
-		// Si on est dans le site public, dire que qq s'en occupe
556
-		include_spip('inc/minipres');
557
-		utiliser_langue_visiteur();
558
-		echo minipres(_T('info_travaux_titre'), "<p style='text-align: center;'>" . _T('info_travaux_texte') . '</p>', ['status' => 503]);
559
-		exit;
560
-	}
561
-	// autrement c'est une install ad hoc (spikini...), on sait pas faire
550
+    // Si on peut installer, on lance illico
551
+    if (test_espace_prive()) {
552
+        include_spip('inc/headers');
553
+        redirige_url_ecrire('install');
554
+    } else {
555
+        // Si on est dans le site public, dire que qq s'en occupe
556
+        include_spip('inc/minipres');
557
+        utiliser_langue_visiteur();
558
+        echo minipres(_T('info_travaux_titre'), "<p style='text-align: center;'>" . _T('info_travaux_texte') . '</p>', ['status' => 503]);
559
+        exit;
560
+    }
561
+    // autrement c'est une install ad hoc (spikini...), on sait pas faire
562 562
 }
563 563
 
564 564
 // memoriser un tri sessionne eventuel
565 565
 if (
566
-	isset($_REQUEST['var_memotri'])
567
-	and $t = $_REQUEST['var_memotri']
568
-	and (strncmp($t, 'trisession', 10) == 0 or strncmp($t, 'senssession', 11) == 0)
566
+    isset($_REQUEST['var_memotri'])
567
+    and $t = $_REQUEST['var_memotri']
568
+    and (strncmp($t, 'trisession', 10) == 0 or strncmp($t, 'senssession', 11) == 0)
569 569
 ) {
570
-	if (!function_exists('session_set')) {
571
-		include_spip('inc/session');
572
-	}
573
-	$t = preg_replace(',\W,', '_', $t);
574
-	if ($v = _request($t)) {
575
-		session_set($t, $v);
576
-	}
570
+    if (!function_exists('session_set')) {
571
+        include_spip('inc/session');
572
+    }
573
+    $t = preg_replace(',\W,', '_', $t);
574
+    if ($v = _request($t)) {
575
+        session_set($t, $v);
576
+    }
577 577
 }
578 578
 
579 579
 /**
@@ -583,22 +583,22 @@  discard block
 block discarded – undo
583 583
  * La globale $spip_header_silencieux permet de rendre le header minimal pour raisons de securite
584 584
  */
585 585
 if (!defined('_HEADER_COMPOSED_BY')) {
586
-	define('_HEADER_COMPOSED_BY', 'Composed-By: SPIP');
586
+    define('_HEADER_COMPOSED_BY', 'Composed-By: SPIP');
587 587
 }
588 588
 if (!headers_sent() and _HEADER_COMPOSED_BY) {
589
-	if (!defined('_HEADER_VARY')) {
590
-		define('_HEADER_VARY', 'Vary: Cookie, Accept-Encoding');
591
-	}
592
-	if (_HEADER_VARY) {
593
-		header(_HEADER_VARY);
594
-	}
595
-	if (!isset($GLOBALS['spip_header_silencieux']) or !$GLOBALS['spip_header_silencieux']) {
596
-		include_spip('inc/filtres_mini');
597
-		header(_HEADER_COMPOSED_BY . " $spip_version_affichee @ www.spip.net + " . url_absolue(_DIR_VAR . 'config.txt'));
598
-	} else {
599
-		// header minimal
600
-		header(_HEADER_COMPOSED_BY . ' @ www.spip.net');
601
-	}
589
+    if (!defined('_HEADER_VARY')) {
590
+        define('_HEADER_VARY', 'Vary: Cookie, Accept-Encoding');
591
+    }
592
+    if (_HEADER_VARY) {
593
+        header(_HEADER_VARY);
594
+    }
595
+    if (!isset($GLOBALS['spip_header_silencieux']) or !$GLOBALS['spip_header_silencieux']) {
596
+        include_spip('inc/filtres_mini');
597
+        header(_HEADER_COMPOSED_BY . " $spip_version_affichee @ www.spip.net + " . url_absolue(_DIR_VAR . 'config.txt'));
598
+    } else {
599
+        // header minimal
600
+        header(_HEADER_COMPOSED_BY . ' @ www.spip.net');
601
+    }
602 602
 }
603 603
 
604 604
 $methode = ($_SERVER['REQUEST_METHOD'] ?? ((php_sapi_name() == 'cli') ? 'cli' : ''));
Please login to merge, or discard this patch.