Completed
Push — master ( 039abd...2056af )
by cam
01:08
created
ecrire/balise/formulaire_.php 1 patch
Indentation   +269 added lines, -269 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Formulaires
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 include_spip('inc/filtres');
@@ -35,25 +35,25 @@  discard block
 block discarded – undo
35 35
  *     Saisie protégée
36 36
  **/
37 37
 function protege_champ($texte) {
38
-	if (is_array($texte)) {
39
-		$texte = array_map('protege_champ', $texte);
40
-	} else {
41
-		// ne pas corrompre une valeur serialize
42
-		if ((preg_match(',^[abis]:\d+[:;],', $texte) and @unserialize($texte) != false) or is_null($texte)) {
43
-			return $texte;
44
-		}
45
-		if (
46
-			is_string($texte)
47
-			and $texte
48
-			and strpbrk($texte, "&\"'<>") !== false
49
-		) {
50
-			$texte = spip_htmlspecialchars($texte, ENT_QUOTES);
51
-		} elseif (is_bool($texte)) {
52
-			$texte = ($texte ? '1' : '');
53
-		}
54
-	}
55
-
56
-	return $texte;
38
+    if (is_array($texte)) {
39
+        $texte = array_map('protege_champ', $texte);
40
+    } else {
41
+        // ne pas corrompre une valeur serialize
42
+        if ((preg_match(',^[abis]:\d+[:;],', $texte) and @unserialize($texte) != false) or is_null($texte)) {
43
+            return $texte;
44
+        }
45
+        if (
46
+            is_string($texte)
47
+            and $texte
48
+            and strpbrk($texte, "&\"'<>") !== false
49
+        ) {
50
+            $texte = spip_htmlspecialchars($texte, ENT_QUOTES);
51
+        } elseif (is_bool($texte)) {
52
+            $texte = ($texte ? '1' : '');
53
+        }
54
+    }
55
+
56
+    return $texte;
57 57
 }
58 58
 
59 59
 /**
@@ -67,17 +67,17 @@  discard block
 block discarded – undo
67 67
  *     - false : pas de squelette trouvé
68 68
  **/
69 69
 function existe_formulaire($form) {
70
-	if (substr($form, 0, 11) == 'FORMULAIRE_') {
71
-		$form = strtolower(substr($form, 11));
72
-	} else {
73
-		$form = strtolower($form);
74
-	}
70
+    if (substr($form, 0, 11) == 'FORMULAIRE_') {
71
+        $form = strtolower(substr($form, 11));
72
+    } else {
73
+        $form = strtolower($form);
74
+    }
75 75
 
76
-	if (!$form) {
77
-		return '';
78
-	} // on ne sait pas, le nom du formulaire n'est pas fourni ici
76
+    if (!$form) {
77
+        return '';
78
+    } // on ne sait pas, le nom du formulaire n'est pas fourni ici
79 79
 
80
-	return trouver_fond($form, 'formulaires/') ? $form : false;
80
+    return trouver_fond($form, 'formulaires/') ? $form : false;
81 81
 }
82 82
 
83 83
 /**
@@ -86,31 +86,31 @@  discard block
 block discarded – undo
86 86
  * @return false|array
87 87
  */
88 88
 function test_formulaire_inclus_par_modele() {
89
-	$trace = debug_backtrace(null, 20);
90
-	$trace_fonctions = array_column($trace, 'function');
91
-	$trace_fonctions = array_map('strtolower', $trace_fonctions);
92
-
93
-	// regarder si un flag a ete leve juste avant l'appel de balise_FORMULAIRE_dyn
94
-	if (
95
-		function_exists('arguments_balise_dyn_depuis_modele')
96
-		and $form = arguments_balise_dyn_depuis_modele(null, 'read')
97
-	) {
98
-		if (in_array('balise_formulaire__dyn', $trace_fonctions)) {
99
-			$k = array_search('balise_formulaire__dyn', $trace_fonctions);
100
-			if ($trace[$k]['args'][0] === $form) {
101
-				return $trace[$k]['args'];
102
-			}
103
-		}
104
-	}
105
-
106
-	// fallback qui ne repose pas sur le flag lie a l'analyse de contexte_compil,
107
-	// mais ne marche pas si executer_balise_dynamique est appelee via du php dans le squelette
108
-	if (in_array('eval', $trace_fonctions) and in_array('inclure_modele', $trace_fonctions)) {
109
-		$k = array_search('inclure_modele', $trace_fonctions);
110
-		// les arguments de recuperer_fond() passes par inclure_modele()
111
-		return $trace[$k - 1]['args'][1]['args'];
112
-	}
113
-	return false;
89
+    $trace = debug_backtrace(null, 20);
90
+    $trace_fonctions = array_column($trace, 'function');
91
+    $trace_fonctions = array_map('strtolower', $trace_fonctions);
92
+
93
+    // regarder si un flag a ete leve juste avant l'appel de balise_FORMULAIRE_dyn
94
+    if (
95
+        function_exists('arguments_balise_dyn_depuis_modele')
96
+        and $form = arguments_balise_dyn_depuis_modele(null, 'read')
97
+    ) {
98
+        if (in_array('balise_formulaire__dyn', $trace_fonctions)) {
99
+            $k = array_search('balise_formulaire__dyn', $trace_fonctions);
100
+            if ($trace[$k]['args'][0] === $form) {
101
+                return $trace[$k]['args'];
102
+            }
103
+        }
104
+    }
105
+
106
+    // fallback qui ne repose pas sur le flag lie a l'analyse de contexte_compil,
107
+    // mais ne marche pas si executer_balise_dynamique est appelee via du php dans le squelette
108
+    if (in_array('eval', $trace_fonctions) and in_array('inclure_modele', $trace_fonctions)) {
109
+        $k = array_search('inclure_modele', $trace_fonctions);
110
+        // les arguments de recuperer_fond() passes par inclure_modele()
111
+        return $trace[$k - 1]['args'][1]['args'];
112
+    }
113
+    return false;
114 114
 }
115 115
 
116 116
 /**
@@ -125,32 +125,32 @@  discard block
 block discarded – undo
125 125
  **/
126 126
 function balise_FORMULAIRE__dist($p) {
127 127
 
128
-	// Cas d'un #FORMULAIRE_TOTO inexistant : renvoyer la chaine vide.
129
-	// mais si #FORMULAIRE_{toto} on ne peut pas savoir a la compilation, continuer
130
-	if (existe_formulaire($p->nom_champ) === false) {
131
-		$p->code = "''";
132
-		$p->interdire_scripts = false;
133
-
134
-		return $p;
135
-	}
136
-
137
-	// sinon renvoyer un code php dynamique
138
-	$p = calculer_balise_dynamique($p, $p->nom_champ, []);
139
-
140
-	if (
141
-		!test_espace_prive()
142
-		and !empty($p->descr['sourcefile'])
143
-		and $f = $p->descr['sourcefile']
144
-		and basename(dirname($f)) === 'modeles'
145
-	) {
146
-		// un modele est toujours inséré en texte dans son contenant
147
-		// donc si on est dans le public avec un cache on va perdre le dynamisme
148
-		// et on risque de mettre en cache les valeurs pre-remplies du formulaire
149
-		// on injecte donc le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
150
-		$p->code = "'<'.'?php echo (" . texte_script($p->code) . "); ?'.'>'";
151
-		// dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave)
152
-	}
153
-	return $p;
128
+    // Cas d'un #FORMULAIRE_TOTO inexistant : renvoyer la chaine vide.
129
+    // mais si #FORMULAIRE_{toto} on ne peut pas savoir a la compilation, continuer
130
+    if (existe_formulaire($p->nom_champ) === false) {
131
+        $p->code = "''";
132
+        $p->interdire_scripts = false;
133
+
134
+        return $p;
135
+    }
136
+
137
+    // sinon renvoyer un code php dynamique
138
+    $p = calculer_balise_dynamique($p, $p->nom_champ, []);
139
+
140
+    if (
141
+        !test_espace_prive()
142
+        and !empty($p->descr['sourcefile'])
143
+        and $f = $p->descr['sourcefile']
144
+        and basename(dirname($f)) === 'modeles'
145
+    ) {
146
+        // un modele est toujours inséré en texte dans son contenant
147
+        // donc si on est dans le public avec un cache on va perdre le dynamisme
148
+        // et on risque de mettre en cache les valeurs pre-remplies du formulaire
149
+        // on injecte donc le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
150
+        $p->code = "'<'.'?php echo (" . texte_script($p->code) . "); ?'.'>'";
151
+        // dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave)
152
+    }
153
+    return $p;
154 154
 }
155 155
 
156 156
 /**
@@ -170,17 +170,17 @@  discard block
 block discarded – undo
170 170
  *     - string : texte à afficher directement
171 171
  */
172 172
 function balise_FORMULAIRE__dyn($form, ...$args) {
173
-	$form = existe_formulaire($form);
174
-	if (!$form) {
175
-		return '';
176
-	}
173
+    $form = existe_formulaire($form);
174
+    if (!$form) {
175
+        return '';
176
+    }
177 177
 
178
-	$contexte = balise_FORMULAIRE__contexte($form, $args);
179
-	if (!is_array($contexte)) {
180
-		return $contexte;
181
-	}
178
+    $contexte = balise_FORMULAIRE__contexte($form, $args);
179
+    if (!is_array($contexte)) {
180
+        return $contexte;
181
+    }
182 182
 
183
-	return ["formulaires/$form", 3600, $contexte];
183
+    return ["formulaires/$form", 3600, $contexte];
184 184
 }
185 185
 
186 186
 /**
@@ -194,84 +194,84 @@  discard block
 block discarded – undo
194 194
  *     Contexte d'environnement à envoyer au squelette
195 195
  **/
196 196
 function balise_FORMULAIRE__contexte($form, $args) {
197
-	// tester si ce formulaire vient d'etre poste (memes arguments)
198
-	// pour ne pas confondre 2 #FORMULAIRES_XX identiques sur une meme page
199
-	// si poste, on recupere les erreurs
200
-
201
-	$je_suis_poste = false;
202
-	if (
203
-		$post_form = _request('formulaire_action')
204
-		and $post_form == $form
205
-		and $p = _request('formulaire_action_args')
206
-		and is_array($p = decoder_contexte_ajax($p, $post_form))
207
-	) {
208
-		// enlever le faux attribut de langue masque
209
-		array_shift($p);
210
-		if (formulaire__identifier($form, $args, $p)) {
211
-			$je_suis_poste = true;
212
-		}
213
-	}
214
-
215
-	$editable = true;
216
-	$erreurs = $post = [];
217
-	if ($je_suis_poste) {
218
-		$post = traiter_formulaires_dynamiques(true);
219
-		$e = "erreurs_$form";
220
-		$erreurs = isset($post[$e]) ? $post[$e] : [];
221
-		$editable = "editable_$form";
222
-		$editable = (!isset($post[$e]))
223
-			|| count($erreurs)
224
-			|| (isset($post[$editable]) && $post[$editable]);
225
-	}
226
-
227
-	$valeurs = formulaire__charger($form, $args, $je_suis_poste);
228
-
229
-	// si $valeurs n'est pas un tableau, le formulaire n'est pas applicable
230
-	// C'est plus fort qu'editable qui est gere par le squelette
231
-	// Idealement $valeur doit etre alors un message explicatif.
232
-	if (!is_array($valeurs)) {
233
-		return is_string($valeurs) ? $valeurs : '';
234
-	}
235
-
236
-	// charger peut passer une action si le formulaire ne tourne pas sur self()
237
-	// ou une action vide si elle ne sert pas
238
-	$action = (isset($valeurs['action'])) ? $valeurs['action'] : self('&amp;', true);
239
-	// bug IEx : si action finit par /
240
-	// IE croit que le <form ... action=../ > est autoferme
241
-	if (substr($action, -1) == '/') {
242
-		// on ajoute une ancre pour feinter IE, au pire ca tue l'ancre qui finit par un /
243
-		$action .= '#';
244
-	}
245
-
246
-	// recuperer la saisie en cours si erreurs
247
-	// seulement si c'est ce formulaire qui est poste
248
-	// ou si on le demande explicitement par le parametre _forcer_request = true
249
-	$dispo = ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request']));
250
-	foreach (array_keys($valeurs) as $champ) {
251
-		if ($champ[0] !== '_' and !in_array($champ, ['message_ok', 'message_erreur', 'editable'])) {
252
-			if ($dispo and (($v = _request($champ)) !== null)) {
253
-				$valeurs[$champ] = $v;
254
-			}
255
-			// nettoyer l'url des champs qui vont etre saisis
256
-			if ($action) {
257
-				$action = parametre_url($action, $champ, '');
258
-			}
259
-			// proteger les ' et les " dans les champs que l'on va injecter
260
-			$valeurs[$champ] = protege_champ($valeurs[$champ]);
261
-		}
262
-	}
263
-
264
-	if ($action) {
265
-		// nettoyer l'url
266
-		$action = parametre_url($action, 'formulaire_action', '');
267
-		$action = parametre_url($action, 'formulaire_action_args', '');
268
-	}
269
-
270
-	/**
271
-	 * @deprecated
272
-	 * servait pour poster sur les actions de type editer_xxx() qui ne prenaient pas d'argument autrement que par _request('arg') et pour lesquelles il fallait donc passer un hash valide
273
-	 */
274
-	/*
197
+    // tester si ce formulaire vient d'etre poste (memes arguments)
198
+    // pour ne pas confondre 2 #FORMULAIRES_XX identiques sur une meme page
199
+    // si poste, on recupere les erreurs
200
+
201
+    $je_suis_poste = false;
202
+    if (
203
+        $post_form = _request('formulaire_action')
204
+        and $post_form == $form
205
+        and $p = _request('formulaire_action_args')
206
+        and is_array($p = decoder_contexte_ajax($p, $post_form))
207
+    ) {
208
+        // enlever le faux attribut de langue masque
209
+        array_shift($p);
210
+        if (formulaire__identifier($form, $args, $p)) {
211
+            $je_suis_poste = true;
212
+        }
213
+    }
214
+
215
+    $editable = true;
216
+    $erreurs = $post = [];
217
+    if ($je_suis_poste) {
218
+        $post = traiter_formulaires_dynamiques(true);
219
+        $e = "erreurs_$form";
220
+        $erreurs = isset($post[$e]) ? $post[$e] : [];
221
+        $editable = "editable_$form";
222
+        $editable = (!isset($post[$e]))
223
+            || count($erreurs)
224
+            || (isset($post[$editable]) && $post[$editable]);
225
+    }
226
+
227
+    $valeurs = formulaire__charger($form, $args, $je_suis_poste);
228
+
229
+    // si $valeurs n'est pas un tableau, le formulaire n'est pas applicable
230
+    // C'est plus fort qu'editable qui est gere par le squelette
231
+    // Idealement $valeur doit etre alors un message explicatif.
232
+    if (!is_array($valeurs)) {
233
+        return is_string($valeurs) ? $valeurs : '';
234
+    }
235
+
236
+    // charger peut passer une action si le formulaire ne tourne pas sur self()
237
+    // ou une action vide si elle ne sert pas
238
+    $action = (isset($valeurs['action'])) ? $valeurs['action'] : self('&amp;', true);
239
+    // bug IEx : si action finit par /
240
+    // IE croit que le <form ... action=../ > est autoferme
241
+    if (substr($action, -1) == '/') {
242
+        // on ajoute une ancre pour feinter IE, au pire ca tue l'ancre qui finit par un /
243
+        $action .= '#';
244
+    }
245
+
246
+    // recuperer la saisie en cours si erreurs
247
+    // seulement si c'est ce formulaire qui est poste
248
+    // ou si on le demande explicitement par le parametre _forcer_request = true
249
+    $dispo = ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request']));
250
+    foreach (array_keys($valeurs) as $champ) {
251
+        if ($champ[0] !== '_' and !in_array($champ, ['message_ok', 'message_erreur', 'editable'])) {
252
+            if ($dispo and (($v = _request($champ)) !== null)) {
253
+                $valeurs[$champ] = $v;
254
+            }
255
+            // nettoyer l'url des champs qui vont etre saisis
256
+            if ($action) {
257
+                $action = parametre_url($action, $champ, '');
258
+            }
259
+            // proteger les ' et les " dans les champs que l'on va injecter
260
+            $valeurs[$champ] = protege_champ($valeurs[$champ]);
261
+        }
262
+    }
263
+
264
+    if ($action) {
265
+        // nettoyer l'url
266
+        $action = parametre_url($action, 'formulaire_action', '');
267
+        $action = parametre_url($action, 'formulaire_action_args', '');
268
+    }
269
+
270
+    /**
271
+     * @deprecated
272
+     * servait pour poster sur les actions de type editer_xxx() qui ne prenaient pas d'argument autrement que par _request('arg') et pour lesquelles il fallait donc passer un hash valide
273
+     */
274
+    /*
275 275
 	if (isset($valeurs['_action'])) {
276 276
 		$securiser_action = charger_fonction('securiser_action', 'inc');
277 277
 		$secu = $securiser_action(reset($valeurs['_action']), end($valeurs['_action']), '', -1);
@@ -281,59 +281,59 @@  discard block
 block discarded – undo
281 281
 	}
282 282
 	*/
283 283
 
284
-	// empiler la lang en tant que premier argument implicite du CVT
285
-	// pour permettre de la restaurer au moment du Verifier et du Traiter
286
-	array_unshift($args, $GLOBALS['spip_lang']);
287
-
288
-	$valeurs['formulaire_args'] = encoder_contexte_ajax($args, $form);
289
-	$valeurs['erreurs'] = $erreurs;
290
-	$valeurs['action'] = $action;
291
-	$valeurs['form'] = $form;
292
-
293
-	$valeurs['formulaire_sign'] = '';
294
-	if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
295
-		$securiser_action = charger_fonction('securiser_action', 'inc');
296
-		$secu = $securiser_action($valeurs['form'], $valeurs['formulaire_args'], '', -1);
297
-		$valeurs['formulaire_sign'] = $secu['hash'];
298
-	}
299
-
300
-	if (!isset($valeurs['id'])) {
301
-		$valeurs['id'] = 'new';
302
-	}
303
-	// editable peut venir de charger() ou de traiter() sinon
304
-	if (!isset($valeurs['editable'])) {
305
-		$valeurs['editable'] = $editable;
306
-	}
307
-	// dans tous les cas, renvoyer un espace ou vide (et pas un booleen)
308
-	$valeurs['editable'] = ($valeurs['editable'] ? ' ' : '');
309
-
310
-	if ($je_suis_poste) {
311
-		$valeurs['message_erreur'] = '';
312
-		if (isset($erreurs['message_erreur'])) {
313
-			$valeurs['message_erreur'] = $erreurs['message_erreur'];
314
-		}
315
-
316
-		$valeurs['message_ok'] = '';
317
-		if (isset($post["message_ok_$form"])) {
318
-			$valeurs['message_ok'] = $post["message_ok_$form"];
319
-		} elseif (isset($erreurs['message_ok'])) {
320
-			$valeurs['message_ok'] = $erreurs['message_ok'];
321
-		}
322
-
323
-		// accessibilite : encapsuler toutes les erreurs dans un role='alert'
324
-		// uniquement si c'est une string et au premier niveau (on ne touche pas au tableaux)
325
-		// et si $k ne commence pas par un _ (c'est bien une vrai erreur sur un vrai champ)
326
-		if (html5_permis()) {
327
-			foreach ($erreurs as $k => $v) {
328
-				if (is_string($v) and strlen(trim($v)) and strpos($k, '_') !== 0) {
329
-					// on encapsule dans un span car ces messages sont en general simple, juste du texte, et deja dans un span dans le form
330
-					$valeurs['erreurs'][$k] = "<span role='alert'>" . $erreurs[$k] . '</span>';
331
-				}
332
-			}
333
-		}
334
-	}
335
-
336
-	return $valeurs;
284
+    // empiler la lang en tant que premier argument implicite du CVT
285
+    // pour permettre de la restaurer au moment du Verifier et du Traiter
286
+    array_unshift($args, $GLOBALS['spip_lang']);
287
+
288
+    $valeurs['formulaire_args'] = encoder_contexte_ajax($args, $form);
289
+    $valeurs['erreurs'] = $erreurs;
290
+    $valeurs['action'] = $action;
291
+    $valeurs['form'] = $form;
292
+
293
+    $valeurs['formulaire_sign'] = '';
294
+    if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
295
+        $securiser_action = charger_fonction('securiser_action', 'inc');
296
+        $secu = $securiser_action($valeurs['form'], $valeurs['formulaire_args'], '', -1);
297
+        $valeurs['formulaire_sign'] = $secu['hash'];
298
+    }
299
+
300
+    if (!isset($valeurs['id'])) {
301
+        $valeurs['id'] = 'new';
302
+    }
303
+    // editable peut venir de charger() ou de traiter() sinon
304
+    if (!isset($valeurs['editable'])) {
305
+        $valeurs['editable'] = $editable;
306
+    }
307
+    // dans tous les cas, renvoyer un espace ou vide (et pas un booleen)
308
+    $valeurs['editable'] = ($valeurs['editable'] ? ' ' : '');
309
+
310
+    if ($je_suis_poste) {
311
+        $valeurs['message_erreur'] = '';
312
+        if (isset($erreurs['message_erreur'])) {
313
+            $valeurs['message_erreur'] = $erreurs['message_erreur'];
314
+        }
315
+
316
+        $valeurs['message_ok'] = '';
317
+        if (isset($post["message_ok_$form"])) {
318
+            $valeurs['message_ok'] = $post["message_ok_$form"];
319
+        } elseif (isset($erreurs['message_ok'])) {
320
+            $valeurs['message_ok'] = $erreurs['message_ok'];
321
+        }
322
+
323
+        // accessibilite : encapsuler toutes les erreurs dans un role='alert'
324
+        // uniquement si c'est une string et au premier niveau (on ne touche pas au tableaux)
325
+        // et si $k ne commence pas par un _ (c'est bien une vrai erreur sur un vrai champ)
326
+        if (html5_permis()) {
327
+            foreach ($erreurs as $k => $v) {
328
+                if (is_string($v) and strlen(trim($v)) and strpos($k, '_') !== 0) {
329
+                    // on encapsule dans un span car ces messages sont en general simple, juste du texte, et deja dans un span dans le form
330
+                    $valeurs['erreurs'][$k] = "<span role='alert'>" . $erreurs[$k] . '</span>';
331
+                }
332
+            }
333
+        }
334
+    }
335
+
336
+    return $valeurs;
337 337
 }
338 338
 
339 339
 /**
@@ -345,51 +345,51 @@  discard block
 block discarded – undo
345 345
  * @return array
346 346
  */
347 347
 function formulaire__charger($form, $args, $poste) {
348
-	if ($charger_valeurs = charger_fonction('charger', "formulaires/$form", true)) {
349
-		$valeurs = call_user_func_array($charger_valeurs, $args);
350
-	} else {
351
-		$valeurs = [];
352
-	}
353
-
354
-	$valeurs = pipeline(
355
-		'formulaire_charger',
356
-		[
357
-			'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
358
-			'data' => $valeurs
359
-		]
360
-	);
361
-
362
-	// prise en charge CVT multi etape
363
-	if (is_array($valeurs) and isset($valeurs['_etapes'])) {
364
-		include_spip('inc/cvt_multietapes');
365
-		$valeurs = cvtmulti_formulaire_charger_etapes(
366
-			['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
367
-			$valeurs
368
-		);
369
-	}
370
-
371
-	// si $valeurs et false ou une chaine, pas de formulaire, donc pas de pipeline !
372
-	if (is_array($valeurs)) {
373
-		if (!isset($valeurs['_pipelines'])) {
374
-			$valeurs['_pipelines'] = [];
375
-		}
376
-		// l'ancien argument _pipeline devient maintenant _pipelines
377
-		// reinjectons le vieux _pipeline au debut de _pipelines
378
-		if (isset($valeurs['_pipeline'])) {
379
-			$pipe = is_array($valeurs['_pipeline']) ? reset($valeurs['_pipeline']) : $valeurs['_pipeline'];
380
-			$args = is_array($valeurs['_pipeline']) ? end($valeurs['_pipeline']) : [];
381
-
382
-			$pipelines = [$pipe => $args];
383
-			$valeurs['_pipelines'] = array_merge($pipelines, $valeurs['_pipelines']);
384
-		}
385
-
386
-		// et enfin, ajoutons systematiquement un pipeline sur le squelette du formulaire
387
-		// qui constitue le cas le plus courant d'utilisation du pipeline recuperer_fond
388
-		// (performance, cela evite de s'injecter dans recuperer_fond utilise pour *tous* les squelettes)
389
-		$valeurs['_pipelines']['formulaire_fond'] = ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste];
390
-	}
391
-
392
-	return $valeurs;
348
+    if ($charger_valeurs = charger_fonction('charger', "formulaires/$form", true)) {
349
+        $valeurs = call_user_func_array($charger_valeurs, $args);
350
+    } else {
351
+        $valeurs = [];
352
+    }
353
+
354
+    $valeurs = pipeline(
355
+        'formulaire_charger',
356
+        [
357
+            'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
358
+            'data' => $valeurs
359
+        ]
360
+    );
361
+
362
+    // prise en charge CVT multi etape
363
+    if (is_array($valeurs) and isset($valeurs['_etapes'])) {
364
+        include_spip('inc/cvt_multietapes');
365
+        $valeurs = cvtmulti_formulaire_charger_etapes(
366
+            ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
367
+            $valeurs
368
+        );
369
+    }
370
+
371
+    // si $valeurs et false ou une chaine, pas de formulaire, donc pas de pipeline !
372
+    if (is_array($valeurs)) {
373
+        if (!isset($valeurs['_pipelines'])) {
374
+            $valeurs['_pipelines'] = [];
375
+        }
376
+        // l'ancien argument _pipeline devient maintenant _pipelines
377
+        // reinjectons le vieux _pipeline au debut de _pipelines
378
+        if (isset($valeurs['_pipeline'])) {
379
+            $pipe = is_array($valeurs['_pipeline']) ? reset($valeurs['_pipeline']) : $valeurs['_pipeline'];
380
+            $args = is_array($valeurs['_pipeline']) ? end($valeurs['_pipeline']) : [];
381
+
382
+            $pipelines = [$pipe => $args];
383
+            $valeurs['_pipelines'] = array_merge($pipelines, $valeurs['_pipelines']);
384
+        }
385
+
386
+        // et enfin, ajoutons systematiquement un pipeline sur le squelette du formulaire
387
+        // qui constitue le cas le plus courant d'utilisation du pipeline recuperer_fond
388
+        // (performance, cela evite de s'injecter dans recuperer_fond utilise pour *tous* les squelettes)
389
+        $valeurs['_pipelines']['formulaire_fond'] = ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste];
390
+    }
391
+
392
+    return $valeurs;
393 393
 }
394 394
 
395 395
 /**
@@ -408,9 +408,9 @@  discard block
 block discarded – undo
408 408
  * @return bool
409 409
  */
410 410
 function formulaire__identifier($form, $args, $p) {
411
-	if ($identifier_args = charger_fonction('identifier', "formulaires/$form", true)) {
412
-		return call_user_func_array($identifier_args, $args) === call_user_func_array($identifier_args, $p);
413
-	}
411
+    if ($identifier_args = charger_fonction('identifier', "formulaires/$form", true)) {
412
+        return call_user_func_array($identifier_args, $args) === call_user_func_array($identifier_args, $p);
413
+    }
414 414
 
415
-	return $args === $p;
415
+    return $args === $p;
416 416
 }
Please login to merge, or discard this patch.
ecrire/base/trouver_table.php 1 patch
Indentation   +150 added lines, -150 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\SQL\Tables
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 include_spip('base/objets');
22 22
 
@@ -68,153 +68,153 @@  discard block
 block discarded – undo
68 68
  *
69 69
  **/
70 70
 function base_trouver_table_dist($nom, $serveur = '', $table_spip = true, array $options = []) {
71
-	static $nom_cache_desc_sql = [];
72
-
73
-	if (
74
-		!spip_connect($serveur)
75
-		or !preg_match('/^[a-zA-Z0-9._-]*/', $nom)
76
-	) {
77
-		return null;
78
-	}
79
-
80
-	$options = $options + [
81
-		// si false, baissera le niveau de log si une table demandée n’existe pas
82
-		'log_missing' => true,
83
-	];
84
-
85
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
86
-	$objets_sql = lister_tables_objets_sql('::md5');
87
-
88
-	// le nom du cache depend du serveur mais aussi du nom de la db et du prefixe
89
-	// ce qui permet une auto invalidation en cas de modif manuelle du fichier
90
-	// de connexion, et tout risque d'ambiguite
91
-	if (!isset($nom_cache_desc_sql[$serveur][$objets_sql])) {
92
-		$nom_cache_desc_sql[$serveur][$objets_sql] =
93
-			_DIR_CACHE . 'sql_desc_'
94
-			. ($serveur ? "{$serveur}_" : '')
95
-			. substr(md5($connexion['db'] . ':' . $connexion['prefixe'] . ":$objets_sql"), 0, 8)
96
-			. '.txt';
97
-		// nouveau nom de cache = nouvelle version en memoire
98
-		unset($connexion['tables']);
99
-	}
100
-
101
-	// un appel avec $nom vide est une demande explicite de vidange du cache des descriptions
102
-	if (!$nom) {
103
-		spip_unlink($nom_cache_desc_sql[$serveur][$objets_sql]);
104
-		$connexion['tables'] = [];
105
-
106
-		return null;
107
-	}
108
-
109
-	$nom_sql = $nom;
110
-	if (preg_match('/\.(.*)$/', $nom, $s)) {
111
-		$nom_sql = $s[1];
112
-	} else {
113
-		$nom_sql = $nom;
114
-	}
115
-
116
-	$fdesc = $desc = '';
117
-	$connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
118
-
119
-	// base sous SPIP: gerer les abreviations explicites des noms de table
120
-	if ($connexion['spip_connect_version']) {
121
-		if ($table_spip and isset($GLOBALS['table_des_tables'][$nom])) {
122
-			$nom = $GLOBALS['table_des_tables'][$nom];
123
-			$nom_sql = 'spip_' . $nom;
124
-		}
125
-	}
126
-
127
-	// si c'est la premiere table qu'on cherche
128
-	// et si on est pas explicitement en recalcul
129
-	// on essaye de recharger le cache des decriptions de ce serveur
130
-	// dans le fichier cache
131
-	if (
132
-		!isset($connexion['tables'][$nom_sql])
133
-		and defined('_VAR_MODE') and _VAR_MODE !== 'recalcul'
134
-		and (!isset($connexion['tables']) or !$connexion['tables'])
135
-	) {
136
-		if (
137
-			lire_fichier($nom_cache_desc_sql[$serveur][$objets_sql], $desc_cache)
138
-			and $desc_cache = unserialize($desc_cache)
139
-		) {
140
-			$connexion['tables'] = $desc_cache;
141
-		}
142
-	}
143
-	if ($table_spip and !isset($connexion['tables'][$nom_sql])) {
144
-		if (isset($GLOBALS['tables_principales'][$nom_sql])) {
145
-			$fdesc = $GLOBALS['tables_principales'][$nom_sql];
146
-		}
147
-		// meme si pas d'abreviation declaree, trouver la table spip_$nom
148
-		// si c'est une table principale,
149
-		// puisqu'on le fait aussi pour les tables auxiliaires
150
-		elseif ($nom_sql == $nom and isset($GLOBALS['tables_principales']['spip_' . $nom])) {
151
-			$nom_sql = 'spip_' . $nom;
152
-			$fdesc = &$GLOBALS['tables_principales'][$nom_sql];
153
-		} elseif (
154
-			isset($GLOBALS['tables_auxiliaires'][$n = $nom])
155
-			or isset($GLOBALS['tables_auxiliaires'][$n = 'spip_' . $nom])
156
-		) {
157
-			$nom_sql = $n;
158
-			$fdesc = &$GLOBALS['tables_auxiliaires'][$n];
159
-		}  # table locale a cote de SPIP, comme non SPIP:
160
-	}
161
-	if (!isset($connexion['tables'][$nom_sql])) {
162
-		// La *vraie* base a la priorite
163
-		$exists = sql_table_exists($nom_sql, $table_spip, $serveur);
164
-		if (
165
-			!$exists
166
-			or !$desc = sql_showtable($nom_sql, $table_spip, $serveur)
167
-			or !$desc['field']
168
-		) {
169
-			if (!$fdesc) {
170
-				$log_level = $options['log_missing'] ? _LOG_INFO_IMPORTANTE : _LOG_DEBUG;
171
-				spip_log("trouver_table: table inconnue '$serveur' '$nom'", 'base' . $log_level);
172
-
173
-				return null;
174
-			}
175
-			// on ne sait pas lire la structure de la table :
176
-			// on retombe sur la description donnee dans les fichiers spip
177
-			$desc = $fdesc;
178
-			$desc['exist'] = false;
179
-		} else {
180
-			$desc['exist'] = true;
181
-			// gerer le cas des cles vides (echec de l'analyse sur une vue par exemple)
182
-			// pour recuperer la declaration de lister_tables_objets_sql() si il y en a une
183
-			if (! $desc['key']) {
184
-				spip_log("trouver_table: table sans cle '$serveur' '$nom'", 'base');
185
-				unset($desc['key']);
186
-			}
187
-		}
188
-
189
-		$desc['table'] = $desc['table_sql'] = $nom_sql;
190
-		$desc['connexion'] = $serveur;
191
-
192
-		// charger les infos declarees pour cette table
193
-		// en lui passant les infos connues
194
-		// $desc est prioritaire pour la description de la table
195
-		$desc = array_merge(lister_tables_objets_sql($nom_sql, $desc), $desc);
196
-		// s'assurer qu'on a toujours un 'key'
197
-		if (!isset($desc['key']) && !empty($fdesc['key'])) {
198
-			$desc['key'] = $fdesc['key'];
199
-		}
200
-		if (! isset($desc['key'])) {
201
-			$desc['key'] = [];
202
-		}
203
-
204
-		// si tables_objets_sql est bien fini d'init, on peut cacher
205
-		$connexion['tables'][$nom_sql] = $desc;
206
-		$res = &$connexion['tables'][$nom_sql];
207
-		// une nouvelle table a ete decrite
208
-		// mettons donc a jour le cache des descriptions de ce serveur
209
-		if (is_writeable(_DIR_CACHE)) {
210
-			ecrire_fichier($nom_cache_desc_sql[$serveur][$objets_sql], serialize($connexion['tables']), true);
211
-		}
212
-	} else {
213
-		$res = &$connexion['tables'][$nom_sql];
214
-	}
215
-
216
-	// toujours retourner $nom dans id_table
217
-	$res['id_table'] = $nom;
218
-
219
-	return $res;
71
+    static $nom_cache_desc_sql = [];
72
+
73
+    if (
74
+        !spip_connect($serveur)
75
+        or !preg_match('/^[a-zA-Z0-9._-]*/', $nom)
76
+    ) {
77
+        return null;
78
+    }
79
+
80
+    $options = $options + [
81
+        // si false, baissera le niveau de log si une table demandée n’existe pas
82
+        'log_missing' => true,
83
+    ];
84
+
85
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
86
+    $objets_sql = lister_tables_objets_sql('::md5');
87
+
88
+    // le nom du cache depend du serveur mais aussi du nom de la db et du prefixe
89
+    // ce qui permet une auto invalidation en cas de modif manuelle du fichier
90
+    // de connexion, et tout risque d'ambiguite
91
+    if (!isset($nom_cache_desc_sql[$serveur][$objets_sql])) {
92
+        $nom_cache_desc_sql[$serveur][$objets_sql] =
93
+            _DIR_CACHE . 'sql_desc_'
94
+            . ($serveur ? "{$serveur}_" : '')
95
+            . substr(md5($connexion['db'] . ':' . $connexion['prefixe'] . ":$objets_sql"), 0, 8)
96
+            . '.txt';
97
+        // nouveau nom de cache = nouvelle version en memoire
98
+        unset($connexion['tables']);
99
+    }
100
+
101
+    // un appel avec $nom vide est une demande explicite de vidange du cache des descriptions
102
+    if (!$nom) {
103
+        spip_unlink($nom_cache_desc_sql[$serveur][$objets_sql]);
104
+        $connexion['tables'] = [];
105
+
106
+        return null;
107
+    }
108
+
109
+    $nom_sql = $nom;
110
+    if (preg_match('/\.(.*)$/', $nom, $s)) {
111
+        $nom_sql = $s[1];
112
+    } else {
113
+        $nom_sql = $nom;
114
+    }
115
+
116
+    $fdesc = $desc = '';
117
+    $connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];
118
+
119
+    // base sous SPIP: gerer les abreviations explicites des noms de table
120
+    if ($connexion['spip_connect_version']) {
121
+        if ($table_spip and isset($GLOBALS['table_des_tables'][$nom])) {
122
+            $nom = $GLOBALS['table_des_tables'][$nom];
123
+            $nom_sql = 'spip_' . $nom;
124
+        }
125
+    }
126
+
127
+    // si c'est la premiere table qu'on cherche
128
+    // et si on est pas explicitement en recalcul
129
+    // on essaye de recharger le cache des decriptions de ce serveur
130
+    // dans le fichier cache
131
+    if (
132
+        !isset($connexion['tables'][$nom_sql])
133
+        and defined('_VAR_MODE') and _VAR_MODE !== 'recalcul'
134
+        and (!isset($connexion['tables']) or !$connexion['tables'])
135
+    ) {
136
+        if (
137
+            lire_fichier($nom_cache_desc_sql[$serveur][$objets_sql], $desc_cache)
138
+            and $desc_cache = unserialize($desc_cache)
139
+        ) {
140
+            $connexion['tables'] = $desc_cache;
141
+        }
142
+    }
143
+    if ($table_spip and !isset($connexion['tables'][$nom_sql])) {
144
+        if (isset($GLOBALS['tables_principales'][$nom_sql])) {
145
+            $fdesc = $GLOBALS['tables_principales'][$nom_sql];
146
+        }
147
+        // meme si pas d'abreviation declaree, trouver la table spip_$nom
148
+        // si c'est une table principale,
149
+        // puisqu'on le fait aussi pour les tables auxiliaires
150
+        elseif ($nom_sql == $nom and isset($GLOBALS['tables_principales']['spip_' . $nom])) {
151
+            $nom_sql = 'spip_' . $nom;
152
+            $fdesc = &$GLOBALS['tables_principales'][$nom_sql];
153
+        } elseif (
154
+            isset($GLOBALS['tables_auxiliaires'][$n = $nom])
155
+            or isset($GLOBALS['tables_auxiliaires'][$n = 'spip_' . $nom])
156
+        ) {
157
+            $nom_sql = $n;
158
+            $fdesc = &$GLOBALS['tables_auxiliaires'][$n];
159
+        }  # table locale a cote de SPIP, comme non SPIP:
160
+    }
161
+    if (!isset($connexion['tables'][$nom_sql])) {
162
+        // La *vraie* base a la priorite
163
+        $exists = sql_table_exists($nom_sql, $table_spip, $serveur);
164
+        if (
165
+            !$exists
166
+            or !$desc = sql_showtable($nom_sql, $table_spip, $serveur)
167
+            or !$desc['field']
168
+        ) {
169
+            if (!$fdesc) {
170
+                $log_level = $options['log_missing'] ? _LOG_INFO_IMPORTANTE : _LOG_DEBUG;
171
+                spip_log("trouver_table: table inconnue '$serveur' '$nom'", 'base' . $log_level);
172
+
173
+                return null;
174
+            }
175
+            // on ne sait pas lire la structure de la table :
176
+            // on retombe sur la description donnee dans les fichiers spip
177
+            $desc = $fdesc;
178
+            $desc['exist'] = false;
179
+        } else {
180
+            $desc['exist'] = true;
181
+            // gerer le cas des cles vides (echec de l'analyse sur une vue par exemple)
182
+            // pour recuperer la declaration de lister_tables_objets_sql() si il y en a une
183
+            if (! $desc['key']) {
184
+                spip_log("trouver_table: table sans cle '$serveur' '$nom'", 'base');
185
+                unset($desc['key']);
186
+            }
187
+        }
188
+
189
+        $desc['table'] = $desc['table_sql'] = $nom_sql;
190
+        $desc['connexion'] = $serveur;
191
+
192
+        // charger les infos declarees pour cette table
193
+        // en lui passant les infos connues
194
+        // $desc est prioritaire pour la description de la table
195
+        $desc = array_merge(lister_tables_objets_sql($nom_sql, $desc), $desc);
196
+        // s'assurer qu'on a toujours un 'key'
197
+        if (!isset($desc['key']) && !empty($fdesc['key'])) {
198
+            $desc['key'] = $fdesc['key'];
199
+        }
200
+        if (! isset($desc['key'])) {
201
+            $desc['key'] = [];
202
+        }
203
+
204
+        // si tables_objets_sql est bien fini d'init, on peut cacher
205
+        $connexion['tables'][$nom_sql] = $desc;
206
+        $res = &$connexion['tables'][$nom_sql];
207
+        // une nouvelle table a ete decrite
208
+        // mettons donc a jour le cache des descriptions de ce serveur
209
+        if (is_writeable(_DIR_CACHE)) {
210
+            ecrire_fichier($nom_cache_desc_sql[$serveur][$objets_sql], serialize($connexion['tables']), true);
211
+        }
212
+    } else {
213
+        $res = &$connexion['tables'][$nom_sql];
214
+    }
215
+
216
+    // toujours retourner $nom dans id_table
217
+    $res['id_table'] = $nom;
218
+
219
+    return $res;
220 220
 }
Please login to merge, or discard this patch.
ecrire/public/jointures.php 1 patch
Indentation   +398 added lines, -398 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
 
@@ -33,11 +33,11 @@  discard block
 block discarded – undo
33 33
  *     Chaine sinon : le nom du champ (non décomposable donc)
34 34
  */
35 35
 function decompose_champ_id_objet($champ) {
36
-	if (($champ !== 'id_objet') and preg_match(',^id_([a-z_]+)$,', $champ, $regs)) {
37
-		return ['id_objet', 'objet', objet_type($champ)];
38
-	}
36
+    if (($champ !== 'id_objet') and preg_match(',^id_([a-z_]+)$,', $champ, $regs)) {
37
+        return ['id_objet', 'objet', objet_type($champ)];
38
+    }
39 39
 
40
-	return $champ;
40
+    return $champ;
41 41
 }
42 42
 
43 43
 /**
@@ -56,21 +56,21 @@  discard block
 block discarded – undo
56 56
  *     - array(id_objet, objet), si le champ n'existe pas mais qu'on peut décomposer
57 57
  */
58 58
 function trouver_champs_decomposes($champ, $desc) {
59
-	if (
60
-		!is_array($desc) // on ne se risque pas en conjectures si on ne connait pas la table
61
-		or array_key_exists($champ, $desc['field'])
62
-	) {
63
-		return [$champ];
64
-	}
65
-	// si le champ se décompose, tester que les colonnes décomposées sont présentes
66
-	if (is_array($decompose = decompose_champ_id_objet($champ))) {
67
-		array_pop($decompose);
68
-		if (count(array_intersect($decompose, array_keys($desc['field']))) == count($decompose)) {
69
-			return $decompose;
70
-		}
71
-	}
72
-
73
-	return [$champ];
59
+    if (
60
+        !is_array($desc) // on ne se risque pas en conjectures si on ne connait pas la table
61
+        or array_key_exists($champ, $desc['field'])
62
+    ) {
63
+        return [$champ];
64
+    }
65
+    // si le champ se décompose, tester que les colonnes décomposées sont présentes
66
+    if (is_array($decompose = decompose_champ_id_objet($champ))) {
67
+        array_pop($decompose);
68
+        if (count(array_intersect($decompose, array_keys($desc['field']))) == count($decompose)) {
69
+            return $decompose;
70
+        }
71
+    }
72
+
73
+    return [$champ];
74 74
 }
75 75
 
76 76
 
@@ -100,23 +100,23 @@  discard block
 block discarded – undo
100 100
  *     Alias de la table de jointure (Lx)
101 101
  */
102 102
 function calculer_jointure(&$boucle, $depart, $arrivee, $col = '', $cond = false, $max_liens = 5) {
103
-	// les jointures minimales sont optimales :
104
-	// on contraint le nombre d'etapes en l'augmentant
105
-	// jusqu'a ce qu'on trouve une jointure ou qu'on atteigne la limite maxi
106
-	$max = 1;
107
-	$res = false;
108
-	$milieu_exclus = ($col ? $col : []);
109
-	while ($max <= $max_liens and !$res) {
110
-		$res = calculer_chaine_jointures($boucle, $depart, $arrivee, [], $milieu_exclus, $max);
111
-		$max++;
112
-	}
113
-	if (!$res) {
114
-		return '';
115
-	}
116
-
117
-	list($nom, $desc) = $depart;
118
-
119
-	return fabrique_jointures($boucle, $res, $cond, $desc, $nom, $col);
103
+    // les jointures minimales sont optimales :
104
+    // on contraint le nombre d'etapes en l'augmentant
105
+    // jusqu'a ce qu'on trouve une jointure ou qu'on atteigne la limite maxi
106
+    $max = 1;
107
+    $res = false;
108
+    $milieu_exclus = ($col ? $col : []);
109
+    while ($max <= $max_liens and !$res) {
110
+        $res = calculer_chaine_jointures($boucle, $depart, $arrivee, [], $milieu_exclus, $max);
111
+        $max++;
112
+    }
113
+    if (!$res) {
114
+        return '';
115
+    }
116
+
117
+    list($nom, $desc) = $depart;
118
+
119
+    return fabrique_jointures($boucle, $res, $cond, $desc, $nom, $col);
120 120
 }
121 121
 
122 122
 /**
@@ -155,79 +155,79 @@  discard block
 block discarded – undo
155 155
  *     Alias de la table de jointure (Lx)
156 156
  */
157 157
 function fabrique_jointures(&$boucle, $res, $cond = false, $desc = [], $nom = '', $col = '', $echap = true) {
158
-	static $num = [];
159
-	$id_table = '';
160
-	$cpt = &$num[$boucle->descr['nom']][$boucle->descr['gram']][$boucle->id_boucle];
161
-	foreach ($res as $cle => $r) {
162
-		list($d, $a, $j) = $r;
163
-		if (!$id_table) {
164
-			$id_table = $d;
165
-		}
166
-		$n = ++$cpt;
167
-		if (is_array($j)) { // c'est un lien sur un champ du type id_objet,objet,'article'
168
-			list($j1, $j2, $obj, $type) = $j;
169
-			// trouver de quel cote est (id_objet,objet)
170
-			if ($j1 == "id_$obj") {
171
-				$obj = "$id_table.$obj";
172
-			} else {
173
-				$obj = "L$n.$obj";
174
-			}
175
-			// le where complementaire est envoye dans la jointure et dans le where
176
-			// on utilise une clé qui le relie a la jointure pour que l'optimiseur
177
-			// sache qu'il peut enlever ce where si il enleve la jointure
178
-			$boucle->where["JOIN-L$n"] =
179
-				$echap ?
180
-					["'='","'$obj'","sql_quote('$type')"]
181
-					:
182
-					['=',"$obj",sql_quote($type)];
183
-			$boucle->join["L$n"] =
184
-				$echap ?
185
-					["'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')"]
186
-					:
187
-					[$id_table, $j2, $j1, "$obj=" . sql_quote($type)];
188
-		} else {
189
-			$boucle->join["L$n"] = $echap ? ["'$id_table'", "'$j'"] : [$id_table, $j];
190
-		}
191
-		$boucle->from[$id_table = "L$n"] = $a[0];
192
-	}
193
-
194
-
195
-	// pas besoin de group by
196
-	// (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
197
-	// si une seule jointure et sur une table avec primary key formee
198
-	// de l'index principal et de l'index de jointure (non conditionnel! [6031])
199
-	// et operateur d'egalite (https://core.spip.net/issues/477)
200
-
201
-	if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
202
-		$pk = nogroupby_if($desc, $a[1], $col);
203
-	}
204
-
205
-	// pas de group by
206
-	// si une seule jointure
207
-	// et si l'index de jointure est une primary key a l'arrivee !
208
-	if (
209
-		!$pk
210
-		and (count($boucle->from) == 2)
211
-		and isset($a[1]['key']['PRIMARY KEY'])
212
-		and ($j == $a[1]['key']['PRIMARY KEY'])
213
-	) {
214
-		$pk = true;
215
-	}
216
-
217
-	// la clause Group by est en conflit avec ORDER BY, a completer
218
-	$groups = liste_champs_jointures($nom, $desc, true);
219
-	if (!$pk) {
220
-		foreach ($groups as $id_prim) {
221
-			$id_field = $nom . '.' . $id_prim;
222
-			if (!in_array($id_field, $boucle->group)) {
223
-				$boucle->group[] = $id_field;
224
-			}
225
-		}
226
-	}
227
-
228
-	$boucle->modificateur['lien'] = true;
229
-
230
-	return "L$n";
158
+    static $num = [];
159
+    $id_table = '';
160
+    $cpt = &$num[$boucle->descr['nom']][$boucle->descr['gram']][$boucle->id_boucle];
161
+    foreach ($res as $cle => $r) {
162
+        list($d, $a, $j) = $r;
163
+        if (!$id_table) {
164
+            $id_table = $d;
165
+        }
166
+        $n = ++$cpt;
167
+        if (is_array($j)) { // c'est un lien sur un champ du type id_objet,objet,'article'
168
+            list($j1, $j2, $obj, $type) = $j;
169
+            // trouver de quel cote est (id_objet,objet)
170
+            if ($j1 == "id_$obj") {
171
+                $obj = "$id_table.$obj";
172
+            } else {
173
+                $obj = "L$n.$obj";
174
+            }
175
+            // le where complementaire est envoye dans la jointure et dans le where
176
+            // on utilise une clé qui le relie a la jointure pour que l'optimiseur
177
+            // sache qu'il peut enlever ce where si il enleve la jointure
178
+            $boucle->where["JOIN-L$n"] =
179
+                $echap ?
180
+                    ["'='","'$obj'","sql_quote('$type')"]
181
+                    :
182
+                    ['=',"$obj",sql_quote($type)];
183
+            $boucle->join["L$n"] =
184
+                $echap ?
185
+                    ["'$id_table'", "'$j2'", "'$j1'", "'$obj='.sql_quote('$type')"]
186
+                    :
187
+                    [$id_table, $j2, $j1, "$obj=" . sql_quote($type)];
188
+        } else {
189
+            $boucle->join["L$n"] = $echap ? ["'$id_table'", "'$j'"] : [$id_table, $j];
190
+        }
191
+        $boucle->from[$id_table = "L$n"] = $a[0];
192
+    }
193
+
194
+
195
+    // pas besoin de group by
196
+    // (cf http://article.gmane.org/gmane.comp.web.spip.devel/30555)
197
+    // si une seule jointure et sur une table avec primary key formee
198
+    // de l'index principal et de l'index de jointure (non conditionnel! [6031])
199
+    // et operateur d'egalite (https://core.spip.net/issues/477)
200
+
201
+    if ($pk = (isset($a[1]) && (count($boucle->from) == 2) && !$cond)) {
202
+        $pk = nogroupby_if($desc, $a[1], $col);
203
+    }
204
+
205
+    // pas de group by
206
+    // si une seule jointure
207
+    // et si l'index de jointure est une primary key a l'arrivee !
208
+    if (
209
+        !$pk
210
+        and (count($boucle->from) == 2)
211
+        and isset($a[1]['key']['PRIMARY KEY'])
212
+        and ($j == $a[1]['key']['PRIMARY KEY'])
213
+    ) {
214
+        $pk = true;
215
+    }
216
+
217
+    // la clause Group by est en conflit avec ORDER BY, a completer
218
+    $groups = liste_champs_jointures($nom, $desc, true);
219
+    if (!$pk) {
220
+        foreach ($groups as $id_prim) {
221
+            $id_field = $nom . '.' . $id_prim;
222
+            if (!in_array($id_field, $boucle->group)) {
223
+                $boucle->group[] = $id_field;
224
+            }
225
+        }
226
+    }
227
+
228
+    $boucle->modificateur['lien'] = true;
229
+
230
+    return "L$n";
231 231
 }
232 232
 
233 233
 /**
@@ -242,19 +242,19 @@  discard block
 block discarded – undo
242 242
  * @return bool
243 243
  */
244 244
 function nogroupby_if($depart, $arrivee, $col) {
245
-	if (
246
-		empty($arrivee['key']['PRIMARY KEY'])
247
-		or !($pk = $arrivee['key']['PRIMARY KEY'])
248
-		or empty($depart['key']['PRIMARY KEY'])
249
-	) {
250
-		return false;
251
-	}
252
-	$id_primary = $depart['key']['PRIMARY KEY'];
253
-	if (is_array($col)) {
254
-		$col = implode(', *', $col);
255
-	} // cas id_objet, objet
256
-	return (preg_match("/^$id_primary, *$col$/", $pk) or
257
-		preg_match("/^$col, *$id_primary$/", $pk));
245
+    if (
246
+        empty($arrivee['key']['PRIMARY KEY'])
247
+        or !($pk = $arrivee['key']['PRIMARY KEY'])
248
+        or empty($depart['key']['PRIMARY KEY'])
249
+    ) {
250
+        return false;
251
+    }
252
+    $id_primary = $depart['key']['PRIMARY KEY'];
253
+    if (is_array($col)) {
254
+        $col = implode(', *', $col);
255
+    } // cas id_objet, objet
256
+    return (preg_match("/^$id_primary, *$col$/", $pk) or
257
+        preg_match("/^$col, *$id_primary$/", $pk));
258 258
 }
259 259
 
260 260
 /**
@@ -272,46 +272,46 @@  discard block
 block discarded – undo
272 272
  */
273 273
 function liste_champs_jointures($nom, $desc, $primary = false) {
274 274
 
275
-	static $nojoin = ['idx', 'maj', 'date', 'statut'];
275
+    static $nojoin = ['idx', 'maj', 'date', 'statut'];
276 276
 
277
-	// si cle primaire demandee, la privilegier
278
-	if ($primary && isset($desc['key']['PRIMARY KEY'])) {
279
-		return split_key($desc['key']['PRIMARY KEY']);
280
-	}
277
+    // si cle primaire demandee, la privilegier
278
+    if ($primary && isset($desc['key']['PRIMARY KEY'])) {
279
+        return split_key($desc['key']['PRIMARY KEY']);
280
+    }
281 281
 
282
-	// les champs declares explicitement pour les jointures
283
-	if (isset($desc['join'])) {
284
-		return $desc['join'];
285
-	}
286
-	/*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
282
+    // les champs declares explicitement pour les jointures
283
+    if (isset($desc['join'])) {
284
+        return $desc['join'];
285
+    }
286
+    /*elseif (isset($GLOBALS['tables_principales'][$nom]['join'])) return $GLOBALS['tables_principales'][$nom]['join'];
287 287
 	elseif (isset($GLOBALS['tables_auxiliaires'][$nom]['join'])) return $GLOBALS['tables_auxiliaires'][$nom]['join'];*/
288 288
 
289
-	// si pas de cle, c'est fichu
290
-	if (!isset($desc['key'])) {
291
-		return [];
292
-	}
293
-
294
-	// si cle primaire
295
-	if (isset($desc['key']['PRIMARY KEY'])) {
296
-		return split_key($desc['key']['PRIMARY KEY']);
297
-	}
298
-
299
-	// ici on se rabat sur les cles secondaires,
300
-	// en eliminant celles qui sont pas pertinentes (idx, maj)
301
-	// si jamais le resultat n'est pas pertinent pour une table donnee,
302
-	// il faut declarer explicitement le champ 'join' de sa description
303
-
304
-	$join = [];
305
-	foreach ($desc['key'] as $v) {
306
-		$join = split_key($v, $join);
307
-	}
308
-	foreach ($join as $k) {
309
-		if (in_array($k, $nojoin)) {
310
-			unset($join[$k]);
311
-		}
312
-	}
313
-
314
-	return $join;
289
+    // si pas de cle, c'est fichu
290
+    if (!isset($desc['key'])) {
291
+        return [];
292
+    }
293
+
294
+    // si cle primaire
295
+    if (isset($desc['key']['PRIMARY KEY'])) {
296
+        return split_key($desc['key']['PRIMARY KEY']);
297
+    }
298
+
299
+    // ici on se rabat sur les cles secondaires,
300
+    // en eliminant celles qui sont pas pertinentes (idx, maj)
301
+    // si jamais le resultat n'est pas pertinent pour une table donnee,
302
+    // il faut declarer explicitement le champ 'join' de sa description
303
+
304
+    $join = [];
305
+    foreach ($desc['key'] as $v) {
306
+        $join = split_key($v, $join);
307
+    }
308
+    foreach ($join as $k) {
309
+        if (in_array($k, $nojoin)) {
310
+            unset($join[$k]);
311
+        }
312
+    }
313
+
314
+    return $join;
315 315
 }
316 316
 
317 317
 /**
@@ -322,14 +322,14 @@  discard block
 block discarded – undo
322 322
  * @return array
323 323
  */
324 324
 function split_key($v, $join = []) {
325
-	foreach (preg_split('/,\s*/', $v) as $k) {
326
-		if (strpos($k, '(') !== false) {
327
-			$k = explode('(', $k);
328
-			$k = trim(reset($k));
329
-		}
330
-		$join[$k] = $k;
331
-	}
332
-	return $join;
325
+    foreach (preg_split('/,\s*/', $v) as $k) {
326
+        if (strpos($k, '(') !== false) {
327
+            $k = explode('(', $k);
328
+            $k = trim(reset($k));
329
+        }
330
+        $join[$k] = $k;
331
+    }
332
+    return $join;
333 333
 }
334 334
 
335 335
 /**
@@ -352,135 +352,135 @@  discard block
 block discarded – undo
352 352
  * @return array
353 353
  */
354 354
 function calculer_chaine_jointures(
355
-	&$boucle,
356
-	$depart,
357
-	$arrivee,
358
-	$vu = [],
359
-	$milieu_exclus = [],
360
-	$max_liens = 5
355
+    &$boucle,
356
+    $depart,
357
+    $arrivee,
358
+    $vu = [],
359
+    $milieu_exclus = [],
360
+    $max_liens = 5
361 361
 ) {
362
-	static $trouver_table;
363
-	if (!$trouver_table) {
364
-		$trouver_table = charger_fonction('trouver_table', 'base');
365
-	}
366
-
367
-	if (is_string($milieu_exclus)) {
368
-		$milieu_exclus = [$milieu_exclus];
369
-	}
370
-	// quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
371
-	// faire une jointure sur objet tout seul n'a pas de sens
372
-	if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
373
-		$milieu_exclus[] = 'objet';
374
-	}
375
-
376
-	list($dnom, $ddesc) = $depart;
377
-	list($anom, $adesc) = $arrivee;
378
-	if (!count($vu)) {
379
-		$vu[] = $dnom; // ne pas oublier la table de depart
380
-		$vu[] = $anom; // ne pas oublier la table d'arrivee
381
-	}
382
-
383
-	$akeys = [];
384
-	foreach ($adesc['key'] as $k) {
385
-		// respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
386
-		$akeys = array_merge($akeys, preg_split('/,\s*/', $k));
387
-	}
388
-
389
-	// enlever les cles d'arrivee exclues par l'appel
390
-	$akeys = array_diff($akeys, $milieu_exclus);
391
-
392
-	// cles candidates au depart
393
-	$keys = liste_champs_jointures($dnom, $ddesc);
394
-	// enlever les cles dde depart exclues par l'appel
395
-	$keys = array_diff($keys, $milieu_exclus);
396
-
397
-	$v = !$keys ? false : array_intersect(array_values($keys), $akeys);
398
-
399
-	if ($v) {
400
-		return [[$dnom, [$adesc['table'], $adesc], array_shift($v)]];
401
-	}
402
-
403
-	// regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
404
-	if (count(array_intersect(['id_objet', 'objet'], $keys)) == 2) {
405
-		// regarder si l'une des cles d'arrivee peut se decomposer en
406
-		// id_objet,objet
407
-		// si oui on la prend
408
-		foreach ($akeys as $key) {
409
-			$v = decompose_champ_id_objet($key);
410
-			if (is_array($v)) {
411
-				$objet = array_shift($v); // objet,'article'
412
-				array_unshift($v, $key); // id_article,objet,'article'
413
-				array_unshift($v, $objet); // id_objet,id_article,objet,'article'
414
-				return [[$dnom, [$adesc['table'], $adesc], $v]];
415
-			}
416
-		}
417
-	} else {
418
-		// regarder si l'une des cles de depart peut se decomposer en
419
-		// id_objet,objet a l'arrivee
420
-		// si oui on la prend
421
-		foreach ($keys as $key) {
422
-			if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
423
-				if (count($v) == count(array_intersect($v, $akeys))) {
424
-					$v = decompose_champ_id_objet($key); // id_objet,objet,'article'
425
-					array_unshift($v, $key); // id_article,id_objet,objet,'article'
426
-					return [[$dnom, [$adesc['table'], $adesc], $v]];
427
-				}
428
-			}
429
-		}
430
-	}
431
-	// si l'on voulait une jointure direct, c'est rate !
432
-	if ($max_liens <= 1) {
433
-		return [];
434
-	}
435
-
436
-	// sinon essayer de passer par une autre table
437
-	$new = $vu;
438
-	foreach ($boucle->jointures as $v) {
439
-		if (
440
-			$v
441
-			and !in_array($v, $vu)
442
-			and $def = $trouver_table($v, $boucle->sql_serveur)
443
-			and !in_array($def['table_sql'], $vu)
444
-		) {
445
-			// ne pas tester les cles qui sont exclues a l'appel
446
-			// ie la cle de la jointure precedente
447
-			$test_cles = $milieu_exclus;
448
-			$new[] = $v;
449
-			$max_iter = 50; // securite
450
-			while (
451
-				count($jointure_directe_possible = calculer_chaine_jointures(
452
-					$boucle,
453
-					$depart,
454
-					[$v, $def],
455
-					$vu,
456
-					$test_cles,
457
-					1
458
-				))
459
-				and $max_iter--
460
-			) {
461
-				$jointure_directe_possible = reset($jointure_directe_possible);
462
-				$milieu = end($jointure_directe_possible);
463
-				$exclure_fin = $milieu_exclus;
464
-				if (is_string($milieu)) {
465
-					$exclure_fin[] = $milieu;
466
-					$test_cles[] = $milieu;
467
-				} else {
468
-					$exclure_fin = array_merge($exclure_fin, $milieu);
469
-					$test_cles = array_merge($test_cles, $milieu);
470
-				}
471
-				// essayer de rejoindre l'arrivee a partir de cette etape intermediaire
472
-				// sans repasser par la meme cle milieu, ni une cle deja vue !
473
-				$r = calculer_chaine_jointures($boucle, [$v, $def], $arrivee, $new, $exclure_fin, $max_liens - 1);
474
-				if ($r) {
475
-					array_unshift($r, $jointure_directe_possible);
476
-
477
-					return $r;
478
-				}
479
-			}
480
-		}
481
-	}
482
-
483
-	return [];
362
+    static $trouver_table;
363
+    if (!$trouver_table) {
364
+        $trouver_table = charger_fonction('trouver_table', 'base');
365
+    }
366
+
367
+    if (is_string($milieu_exclus)) {
368
+        $milieu_exclus = [$milieu_exclus];
369
+    }
370
+    // quand on a exclus id_objet comme cle de jointure, il faut aussi exclure objet
371
+    // faire une jointure sur objet tout seul n'a pas de sens
372
+    if (in_array('id_objet', $milieu_exclus) and !in_array('objet', $milieu_exclus)) {
373
+        $milieu_exclus[] = 'objet';
374
+    }
375
+
376
+    list($dnom, $ddesc) = $depart;
377
+    list($anom, $adesc) = $arrivee;
378
+    if (!count($vu)) {
379
+        $vu[] = $dnom; // ne pas oublier la table de depart
380
+        $vu[] = $anom; // ne pas oublier la table d'arrivee
381
+    }
382
+
383
+    $akeys = [];
384
+    foreach ($adesc['key'] as $k) {
385
+        // respecter l'ordre de $adesc['key'] pour ne pas avoir id_trad en premier entre autres...
386
+        $akeys = array_merge($akeys, preg_split('/,\s*/', $k));
387
+    }
388
+
389
+    // enlever les cles d'arrivee exclues par l'appel
390
+    $akeys = array_diff($akeys, $milieu_exclus);
391
+
392
+    // cles candidates au depart
393
+    $keys = liste_champs_jointures($dnom, $ddesc);
394
+    // enlever les cles dde depart exclues par l'appel
395
+    $keys = array_diff($keys, $milieu_exclus);
396
+
397
+    $v = !$keys ? false : array_intersect(array_values($keys), $akeys);
398
+
399
+    if ($v) {
400
+        return [[$dnom, [$adesc['table'], $adesc], array_shift($v)]];
401
+    }
402
+
403
+    // regarder si l'on a (id_objet,objet) au depart et si on peut le mapper sur un id_xx
404
+    if (count(array_intersect(['id_objet', 'objet'], $keys)) == 2) {
405
+        // regarder si l'une des cles d'arrivee peut se decomposer en
406
+        // id_objet,objet
407
+        // si oui on la prend
408
+        foreach ($akeys as $key) {
409
+            $v = decompose_champ_id_objet($key);
410
+            if (is_array($v)) {
411
+                $objet = array_shift($v); // objet,'article'
412
+                array_unshift($v, $key); // id_article,objet,'article'
413
+                array_unshift($v, $objet); // id_objet,id_article,objet,'article'
414
+                return [[$dnom, [$adesc['table'], $adesc], $v]];
415
+            }
416
+        }
417
+    } else {
418
+        // regarder si l'une des cles de depart peut se decomposer en
419
+        // id_objet,objet a l'arrivee
420
+        // si oui on la prend
421
+        foreach ($keys as $key) {
422
+            if (count($v = trouver_champs_decomposes($key, $adesc)) > 1) {
423
+                if (count($v) == count(array_intersect($v, $akeys))) {
424
+                    $v = decompose_champ_id_objet($key); // id_objet,objet,'article'
425
+                    array_unshift($v, $key); // id_article,id_objet,objet,'article'
426
+                    return [[$dnom, [$adesc['table'], $adesc], $v]];
427
+                }
428
+            }
429
+        }
430
+    }
431
+    // si l'on voulait une jointure direct, c'est rate !
432
+    if ($max_liens <= 1) {
433
+        return [];
434
+    }
435
+
436
+    // sinon essayer de passer par une autre table
437
+    $new = $vu;
438
+    foreach ($boucle->jointures as $v) {
439
+        if (
440
+            $v
441
+            and !in_array($v, $vu)
442
+            and $def = $trouver_table($v, $boucle->sql_serveur)
443
+            and !in_array($def['table_sql'], $vu)
444
+        ) {
445
+            // ne pas tester les cles qui sont exclues a l'appel
446
+            // ie la cle de la jointure precedente
447
+            $test_cles = $milieu_exclus;
448
+            $new[] = $v;
449
+            $max_iter = 50; // securite
450
+            while (
451
+                count($jointure_directe_possible = calculer_chaine_jointures(
452
+                    $boucle,
453
+                    $depart,
454
+                    [$v, $def],
455
+                    $vu,
456
+                    $test_cles,
457
+                    1
458
+                ))
459
+                and $max_iter--
460
+            ) {
461
+                $jointure_directe_possible = reset($jointure_directe_possible);
462
+                $milieu = end($jointure_directe_possible);
463
+                $exclure_fin = $milieu_exclus;
464
+                if (is_string($milieu)) {
465
+                    $exclure_fin[] = $milieu;
466
+                    $test_cles[] = $milieu;
467
+                } else {
468
+                    $exclure_fin = array_merge($exclure_fin, $milieu);
469
+                    $test_cles = array_merge($test_cles, $milieu);
470
+                }
471
+                // essayer de rejoindre l'arrivee a partir de cette etape intermediaire
472
+                // sans repasser par la meme cle milieu, ni une cle deja vue !
473
+                $r = calculer_chaine_jointures($boucle, [$v, $def], $arrivee, $new, $exclure_fin, $max_liens - 1);
474
+                if ($r) {
475
+                    array_unshift($r, $jointure_directe_possible);
476
+
477
+                    return $r;
478
+                }
479
+            }
480
+        }
481
+    }
482
+
483
+    return [];
484 484
 }
485 485
 
486 486
 /**
@@ -491,18 +491,18 @@  discard block
 block discarded – undo
491 491
  * @return array
492 492
  */
493 493
 function trouver_cles_table($keys) {
494
-	$res = [];
495
-	foreach ($keys as $v) {
496
-		if (!strpos($v, ',')) {
497
-			$res[$v] = 1;
498
-		} else {
499
-			foreach (preg_split('/\s*,\s*/', $v) as $k) {
500
-				$res[$k] = 1;
501
-			}
502
-		}
503
-	}
504
-
505
-	return array_keys($res);
494
+    $res = [];
495
+    foreach ($keys as $v) {
496
+        if (!strpos($v, ',')) {
497
+            $res[$v] = 1;
498
+        } else {
499
+            foreach (preg_split('/\s*,\s*/', $v) as $k) {
500
+                $res[$k] = 1;
501
+            }
502
+        }
503
+    }
504
+
505
+    return array_keys($res);
506 506
 }
507 507
 
508 508
 
@@ -529,34 +529,34 @@  discard block
 block discarded – undo
529 529
  *     - 'alias' : alias utilisé pour la table (si pertinent. ie: avec `$boucle->from` transmis par exemple)
530 530
  */
531 531
 function chercher_champ_dans_tables($cle, $tables, $connect, $checkarrivee = false) {
532
-	static $trouver_table = '';
533
-	if (!$trouver_table) {
534
-		$trouver_table = charger_fonction('trouver_table', 'base');
535
-	}
536
-
537
-	if (!is_array($cle)) {
538
-		$cle = [$cle];
539
-	}
540
-
541
-	foreach ($tables as $k => $table) {
542
-		if ($table && $desc = $trouver_table($table, $connect)) {
543
-			if (
544
-				isset($desc['field'])
545
-				// verifier que toutes les cles cherchees sont la
546
-				and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
547
-				// si on sait ou on veut arriver, il faut que ca colle
548
-				and ($checkarrivee == false || $checkarrivee == $desc['table'])
549
-			) {
550
-				return [
551
-					'desc' => $desc,
552
-					'table' => $desc['table'],
553
-					'alias' => $k,
554
-				];
555
-			}
556
-		}
557
-	}
558
-
559
-	return false;
532
+    static $trouver_table = '';
533
+    if (!$trouver_table) {
534
+        $trouver_table = charger_fonction('trouver_table', 'base');
535
+    }
536
+
537
+    if (!is_array($cle)) {
538
+        $cle = [$cle];
539
+    }
540
+
541
+    foreach ($tables as $k => $table) {
542
+        if ($table && $desc = $trouver_table($table, $connect)) {
543
+            if (
544
+                isset($desc['field'])
545
+                // verifier que toutes les cles cherchees sont la
546
+                and (count(array_intersect($cle, array_keys($desc['field']))) == count($cle))
547
+                // si on sait ou on veut arriver, il faut que ca colle
548
+                and ($checkarrivee == false || $checkarrivee == $desc['table'])
549
+            ) {
550
+                return [
551
+                    'desc' => $desc,
552
+                    'table' => $desc['table'],
553
+                    'alias' => $k,
554
+                ];
555
+            }
556
+        }
557
+    }
558
+
559
+    return false;
560 560
 }
561 561
 
562 562
 /**
@@ -582,52 +582,52 @@  discard block
 block discarded – undo
582 582
  */
583 583
 function trouver_champ_exterieur($cle, $joints, &$boucle, $checkarrivee = false) {
584 584
 
585
-	// support de la recherche multi champ :
586
-	// si en seconde etape on a decompose le champ id_xx en id_objet,objet
587
-	// on reentre ici soit en cherchant une table les 2 champs id_objet,objet
588
-	// soit une table avec les 3 champs id_xx, id_objet, objet
589
-	if (!is_array($cle)) {
590
-		$cle = [$cle];
591
-	}
592
-
593
-	if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
594
-		return [$infos['table'], $infos['desc'], $cle];
595
-	}
596
-
597
-	// au premier coup, on essaye de decomposer, si possible
598
-	if (
599
-		count($cle) == 1
600
-		and $c = reset($cle)
601
-		and is_array($decompose = decompose_champ_id_objet($c))
602
-	) {
603
-		$desc = $boucle->show;
604
-
605
-		// cas 1 : la cle id_xx est dans la table de depart
606
-		// -> on cherche uniquement id_objet,objet a l'arrivee
607
-		if (isset($desc['field'][$c])) {
608
-			$cle = [];
609
-			$cle[] = array_shift($decompose); // id_objet
610
-			$cle[] = array_shift($decompose); // objet
611
-			return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
612
-		}
613
-		// cas 2 : la cle id_xx n'est pas dans la table de depart
614
-		// -> il faut trouver une cle de depart zzz telle que
615
-		// id_objet,objet,zzz soit a l'arrivee
616
-		else {
617
-			$depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
618
-			foreach ($depart as $d) {
619
-				$cle = [];
620
-				$cle[] = array_shift($decompose); // id_objet
621
-				$cle[] = array_shift($decompose); // objet
622
-				$cle[] = $d;
623
-				if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
624
-					return $ext;
625
-				}
626
-			}
627
-		}
628
-	}
629
-
630
-	return '';
585
+    // support de la recherche multi champ :
586
+    // si en seconde etape on a decompose le champ id_xx en id_objet,objet
587
+    // on reentre ici soit en cherchant une table les 2 champs id_objet,objet
588
+    // soit une table avec les 3 champs id_xx, id_objet, objet
589
+    if (!is_array($cle)) {
590
+        $cle = [$cle];
591
+    }
592
+
593
+    if ($infos = chercher_champ_dans_tables($cle, $joints, $boucle->sql_serveur, $checkarrivee)) {
594
+        return [$infos['table'], $infos['desc'], $cle];
595
+    }
596
+
597
+    // au premier coup, on essaye de decomposer, si possible
598
+    if (
599
+        count($cle) == 1
600
+        and $c = reset($cle)
601
+        and is_array($decompose = decompose_champ_id_objet($c))
602
+    ) {
603
+        $desc = $boucle->show;
604
+
605
+        // cas 1 : la cle id_xx est dans la table de depart
606
+        // -> on cherche uniquement id_objet,objet a l'arrivee
607
+        if (isset($desc['field'][$c])) {
608
+            $cle = [];
609
+            $cle[] = array_shift($decompose); // id_objet
610
+            $cle[] = array_shift($decompose); // objet
611
+            return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee);
612
+        }
613
+        // cas 2 : la cle id_xx n'est pas dans la table de depart
614
+        // -> il faut trouver une cle de depart zzz telle que
615
+        // id_objet,objet,zzz soit a l'arrivee
616
+        else {
617
+            $depart = liste_champs_jointures((isset($desc['table']) ? $desc['table'] : ''), $desc);
618
+            foreach ($depart as $d) {
619
+                $cle = [];
620
+                $cle[] = array_shift($decompose); // id_objet
621
+                $cle[] = array_shift($decompose); // objet
622
+                $cle[] = $d;
623
+                if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) {
624
+                    return $ext;
625
+                }
626
+            }
627
+        }
628
+    }
629
+
630
+    return '';
631 631
 }
632 632
 
633 633
 /**
@@ -659,21 +659,21 @@  discard block
 block discarded – undo
659 659
  * @return string
660 660
  */
661 661
 function trouver_jointure_champ($champ, &$boucle, $jointures = false, $cond = false, $checkarrivee = false) {
662
-	if ($jointures === false) {
663
-		$jointures = $boucle->jointures;
664
-	}
665
-	// TODO : aberration, on utilise $jointures pour trouver le champ
666
-	// mais pas poour construire la jointure ensuite
667
-	$arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
668
-	if ($arrivee) {
669
-		$desc = $boucle->show;
670
-		array_pop($arrivee); // enlever la cle en 3eme argument
671
-		$cle = calculer_jointure($boucle, [$desc['id_table'], $desc], $arrivee, '', $cond);
672
-		if ($cle) {
673
-			return $cle;
674
-		}
675
-	}
676
-	spip_log("trouver_jointure_champ: $champ inconnu");
677
-
678
-	return '';
662
+    if ($jointures === false) {
663
+        $jointures = $boucle->jointures;
664
+    }
665
+    // TODO : aberration, on utilise $jointures pour trouver le champ
666
+    // mais pas poour construire la jointure ensuite
667
+    $arrivee = trouver_champ_exterieur($champ, $jointures, $boucle, $checkarrivee);
668
+    if ($arrivee) {
669
+        $desc = $boucle->show;
670
+        array_pop($arrivee); // enlever la cle en 3eme argument
671
+        $cle = calculer_jointure($boucle, [$desc['id_table'], $desc], $arrivee, '', $cond);
672
+        if ($cle) {
673
+            return $cle;
674
+        }
675
+    }
676
+    spip_log("trouver_jointure_champ: $champ inconnu");
677
+
678
+    return '';
679 679
 }
Please login to merge, or discard this patch.
ecrire/public/interfaces.php 1 patch
Indentation   +916 added lines, -916 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
 
@@ -34,53 +34,53 @@  discard block
 block discarded – undo
34 34
  * @package SPIP\Core\Compilateur\AST
35 35
  */
36 36
 class Contexte {
37
-	/**
38
-	 * Description du squelette
39
-	 *
40
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
41
-	 *
42
-	 * Peut contenir les index :
43
-	 *
44
-	 * - nom : Nom du fichier de cache
45
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
46
-	 * - sourcefile : Chemin du squelette
47
-	 * - squelette : Code du squelette
48
-	 * - id_mere : Identifiant de la boucle parente
49
-	 * - documents : Pour embed et img dans les textes
50
-	 * - session : Pour un cache sessionné par auteur
51
-	 * - niv : Niveau de tabulation
52
-	 *
53
-	 * @var array
54
-	 */
55
-	public $descr = [];
56
-
57
-	/**
58
-	 * Identifiant de la boucle
59
-	 *
60
-	 * @var string
61
-	 */
62
-	public $id_boucle = '';
63
-
64
-	/**
65
-	 * Numéro de ligne dans le code source du squelette
66
-	 *
67
-	 * @var int
68
-	 */
69
-	public $ligne = 0;
70
-
71
-	/**
72
-	 * Langue d'exécution
73
-	 *
74
-	 * @var string
75
-	 */
76
-	public $lang = '';
77
-
78
-	/**
79
-	 * Résultat de la compilation: toujours une expression PHP
80
-	 *
81
-	 * @var string
82
-	 */
83
-	public $code = '';
37
+    /**
38
+     * Description du squelette
39
+     *
40
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
41
+     *
42
+     * Peut contenir les index :
43
+     *
44
+     * - nom : Nom du fichier de cache
45
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
46
+     * - sourcefile : Chemin du squelette
47
+     * - squelette : Code du squelette
48
+     * - id_mere : Identifiant de la boucle parente
49
+     * - documents : Pour embed et img dans les textes
50
+     * - session : Pour un cache sessionné par auteur
51
+     * - niv : Niveau de tabulation
52
+     *
53
+     * @var array
54
+     */
55
+    public $descr = [];
56
+
57
+    /**
58
+     * Identifiant de la boucle
59
+     *
60
+     * @var string
61
+     */
62
+    public $id_boucle = '';
63
+
64
+    /**
65
+     * Numéro de ligne dans le code source du squelette
66
+     *
67
+     * @var int
68
+     */
69
+    public $ligne = 0;
70
+
71
+    /**
72
+     * Langue d'exécution
73
+     *
74
+     * @var string
75
+     */
76
+    public $lang = '';
77
+
78
+    /**
79
+     * Résultat de la compilation: toujours une expression PHP
80
+     *
81
+     * @var string
82
+     */
83
+    public $code = '';
84 84
 }
85 85
 
86 86
 
@@ -90,44 +90,44 @@  discard block
 block discarded – undo
90 90
  * @package SPIP\Core\Compilateur\AST
91 91
  **/
92 92
 class Texte {
93
-	/**
94
-	 * Type de noeud
95
-	 *
96
-	 * @var string
97
-	 */
98
-	public $type = 'texte';
99
-
100
-	/**
101
-	 * Le texte
102
-	 *
103
-	 * @var string
104
-	 */
105
-	public $texte;
106
-
107
-	/**
108
-	 * Contenu avant le texte.
109
-	 *
110
-	 * Vide ou apostrophe simple ou double si le texte en était entouré
111
-	 *
112
-	 * @var string|array
113
-	 */
114
-	public $avant = '';
115
-
116
-	/**
117
-	 * Contenu après le texte.
118
-	 *
119
-	 * Vide ou apostrophe simple ou double si le texte en était entouré
120
-	 *
121
-	 * @var string|array
122
-	 */
123
-	public $apres = '';
124
-
125
-	/**
126
-	 * Numéro de ligne dans le code source du squelette
127
-	 *
128
-	 * @var int
129
-	 */
130
-	public $ligne = 0;
93
+    /**
94
+     * Type de noeud
95
+     *
96
+     * @var string
97
+     */
98
+    public $type = 'texte';
99
+
100
+    /**
101
+     * Le texte
102
+     *
103
+     * @var string
104
+     */
105
+    public $texte;
106
+
107
+    /**
108
+     * Contenu avant le texte.
109
+     *
110
+     * Vide ou apostrophe simple ou double si le texte en était entouré
111
+     *
112
+     * @var string|array
113
+     */
114
+    public $avant = '';
115
+
116
+    /**
117
+     * Contenu après le texte.
118
+     *
119
+     * Vide ou apostrophe simple ou double si le texte en était entouré
120
+     *
121
+     * @var string|array
122
+     */
123
+    public $apres = '';
124
+
125
+    /**
126
+     * Numéro de ligne dans le code source du squelette
127
+     *
128
+     * @var int
129
+     */
130
+    public $ligne = 0;
131 131
 }
132 132
 
133 133
 /**
@@ -136,50 +136,50 @@  discard block
 block discarded – undo
136 136
  * @package SPIP\Core\Compilateur\AST
137 137
  **/
138 138
 class Inclure {
139
-	/**
140
-	 * Type de noeud
141
-	 *
142
-	 * @var string
143
-	 */
144
-	public $type = 'include';
145
-
146
-	/**
147
-	 * Nom d'un fichier inclu
148
-	 *
149
-	 * - Objet Texte si inclusion d'un autre squelette
150
-	 * - chaîne si inclusion d'un fichier PHP directement
151
-	 *
152
-	 * @var string|Texte
153
-	 */
154
-	public $texte;
155
-
156
-	/**
157
-	 * Inutilisé, propriété générique de l'AST
158
-	 *
159
-	 * @var string|array
160
-	 */
161
-	public $avant = '';
162
-
163
-	/**
164
-	 * Inutilisé, propriété générique de l'AST
165
-	 *
166
-	 * @var string|array
167
-	 */
168
-	public $apres = '';
169
-
170
-	/**
171
-	 * Numéro de ligne dans le code source du squelette
172
-	 *
173
-	 * @var int
174
-	 */
175
-	public $ligne = 0;
176
-
177
-	/**
178
-	 * Valeurs des paramètres
179
-	 *
180
-	 * @var array
181
-	 */
182
-	public $param = [];
139
+    /**
140
+     * Type de noeud
141
+     *
142
+     * @var string
143
+     */
144
+    public $type = 'include';
145
+
146
+    /**
147
+     * Nom d'un fichier inclu
148
+     *
149
+     * - Objet Texte si inclusion d'un autre squelette
150
+     * - chaîne si inclusion d'un fichier PHP directement
151
+     *
152
+     * @var string|Texte
153
+     */
154
+    public $texte;
155
+
156
+    /**
157
+     * Inutilisé, propriété générique de l'AST
158
+     *
159
+     * @var string|array
160
+     */
161
+    public $avant = '';
162
+
163
+    /**
164
+     * Inutilisé, propriété générique de l'AST
165
+     *
166
+     * @var string|array
167
+     */
168
+    public $apres = '';
169
+
170
+    /**
171
+     * Numéro de ligne dans le code source du squelette
172
+     *
173
+     * @var int
174
+     */
175
+    public $ligne = 0;
176
+
177
+    /**
178
+     * Valeurs des paramètres
179
+     *
180
+     * @var array
181
+     */
182
+    public $param = [];
183 183
 }
184 184
 
185 185
 
@@ -189,386 +189,386 @@  discard block
 block discarded – undo
189 189
  * @package SPIP\Core\Compilateur\AST
190 190
  **/
191 191
 class Boucle {
192
-	/**
193
-	 * Type de noeud
194
-	 *
195
-	 * @var string
196
-	 */
197
-	public $type = 'boucle';
198
-
199
-	/**
200
-	 * Identifiant de la boucle
201
-	 *
202
-	 * @var string
203
-	 */
204
-	public $id_boucle;
205
-
206
-	/**
207
-	 * Identifiant de la boucle parente
208
-	 *
209
-	 * @var string
210
-	 */
211
-	public $id_parent = '';
212
-
213
-	/**
214
-	 * Partie avant toujours affichee
215
-	 *
216
-	 * @var string|array
217
-	 */
218
-	public $preaff = '';
219
-
220
-	/**
221
-	 * Partie optionnelle avant
222
-	 *
223
-	 * @var string|array
224
-	 */
225
-	public $avant = '';
226
-
227
-	/**
228
-	 * Pour chaque élément
229
-	 *
230
-	 * @var string|array
231
-	 */
232
-	public $milieu = '';
233
-
234
-	/**
235
-	 * Partie optionnelle après
236
-	 *
237
-	 * @var string|array
238
-	 */
239
-	public $apres = '';
240
-
241
-	/**
242
-	 * Partie alternative, si pas de résultat dans la boucle
243
-	 *
244
-	 * @var string|array
245
-	 */
246
-	public $altern = '';
247
-
248
-	/**
249
-	 * Partie apres toujours affichee
250
-	 *
251
-	 * @var string|array
252
-	 */
253
-	public $postaff = '';
254
-
255
-
256
-	/**
257
-	 * La boucle doit-elle sélectionner la langue ?
258
-	 *
259
-	 * @var string|null
260
-	 */
261
-	public $lang_select;
262
-
263
-	/**
264
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
265
-	 *
266
-	 * @var string|null
267
-	 */
268
-	public $type_requete;
269
-
270
-	/**
271
-	 * La table est elle optionnelle ?
272
-	 *
273
-	 * Si oui, aucune erreur ne sera générée si la table demandée n'est pas présente
274
-	 *
275
-	 * @var bool
276
-	 */
277
-	public $table_optionnelle = false;
278
-
279
-	/**
280
-	 * Nom du fichier de connexion
281
-	 *
282
-	 * @var string
283
-	 */
284
-	public $sql_serveur = '';
285
-
286
-	/**
287
-	 * Paramètres de la boucle
288
-	 *
289
-	 * Description des paramètres passés à la boucle, qui servent ensuite
290
-	 * au calcul des critères
291
-	 *
292
-	 * @var array
293
-	 */
294
-	public $param = [];
295
-
296
-	/**
297
-	 * Critères de la boucle
298
-	 *
299
-	 * @var Critere[]
300
-	 */
301
-	public $criteres = [];
302
-
303
-	/**
304
-	 * Textes insérés entre 2 éléments de boucle (critère inter)
305
-	 *
306
-	 * @var string[]
307
-	 */
308
-	public $separateur = [];
309
-
310
-	/**
311
-	 * Liste des jointures possibles avec cette table
312
-	 *
313
-	 * Les jointures par défaut de la table sont complétées en priorité
314
-	 * des jointures déclarées explicitement sur la boucle
315
-	 *
316
-	 * @see base_trouver_table_dist()
317
-	 * @var array
318
-	 */
319
-	public $jointures = [];
320
-
321
-	/**
322
-	 * Jointures explicites avec cette table
323
-	 *
324
-	 * Ces jointures sont utilisées en priorité par rapport aux jointures
325
-	 * normales possibles pour retrouver les colonnes demandées extérieures
326
-	 * à la boucle.
327
-	 *
328
-	 * @var string|bool
329
-	 */
330
-	public $jointures_explicites = false;
331
-
332
-	/**
333
-	 * Nom de la variable PHP stockant le noms de doublons utilisés "$doublons_index"
334
-	 *
335
-	 * @var string|null
336
-	 */
337
-	public $doublons;
338
-
339
-	/**
340
-	 * Code PHP ajouté au début de chaque itération de boucle.
341
-	 *
342
-	 * Utilisé entre autre par les critères {pagination}, {n-a,b}, {a/b}...
343
-	 *
344
-	 * @var string
345
-	 */
346
-	public $partie = '';
347
-
348
-	/**
349
-	 * Nombre de divisions de la boucle, d'éléments à afficher,
350
-	 * ou de soustractions d'éléments à faire
351
-	 *
352
-	 * Dans les critères limitant le nombre d'éléments affichés
353
-	 * {a,b}, {a,n-b}, {a/b}, {pagination b}, b est affecté à total_parties.
354
-	 *
355
-	 * @var string
356
-	 */
357
-	public $total_parties = '';
358
-
359
-	/**
360
-	 * Code PHP ajouté avant l'itération de boucle.
361
-	 *
362
-	 * Utilisé entre autre par les critères {pagination}, {a,b}, {a/b}
363
-	 * pour initialiser les variables de début et de fin d'itération.
364
-	 *
365
-	 * @var string
366
-	 */
367
-	public $mode_partie = '';
368
-
369
-	/**
370
-	 * Identifiant d'une boucle qui appelle celle-ci de manière récursive
371
-	 *
372
-	 * Si une boucle est appelée de manière récursive quelque part par
373
-	 * une autre boucle comme <BOUCLE_rec(boucle_identifiant) />, cette
374
-	 * boucle (identifiant) reçoit dans cette propriété l'identifiant
375
-	 * de l'appelant (rec)
376
-	 *
377
-	 * @var string
378
-	 */
379
-	public $externe = '';
380
-
381
-	// champs pour la construction de la requete SQL
382
-
383
-	/**
384
-	 * Liste des champs à récupérer par la boucle
385
-	 *
386
-	 * Expression 'table.nom_champ' ou calculée 'nom_champ AS x'
387
-	 *
388
-	 * @var string[]
389
-	 */
390
-	public $select = [];
391
-
392
-	/**
393
-	 * Liste des alias / tables SQL utilisées dans la boucle
394
-	 *
395
-	 * L'index est un identifiant (xx dans spip_xx assez souvent) qui servira
396
-	 * d'alias au nom de la table ; la valeur est le nom de la table SQL désirée.
397
-	 *
398
-	 * L'index 0 peut définir le type de sources de données de l'itérateur DATA
399
-	 *
400
-	 * @var string[]
401
-	 */
402
-	public $from = [];
403
-
404
-	/**
405
-	 * Liste des alias / type de jointures utilisées dans la boucle
406
-	 *
407
-	 * L'index est le nom d'alias (comme pour la propriété $from), et la valeur
408
-	 * un type de jointure parmi 'INNER', 'LEFT', 'RIGHT', 'OUTER'.
409
-	 *
410
-	 * Lorsque le type n'est pas déclaré pour un alias, c'est 'INNER'
411
-	 * qui sera utilisé par défaut (créant donc un INNER JOIN).
412
-	 *
413
-	 * @var string[]
414
-	 */
415
-	public $from_type = [];
416
-
417
-	/**
418
-	 * Liste des conditions WHERE de la boucle
419
-	 *
420
-	 * Permet de restreindre les éléments retournés par une boucle
421
-	 * en fonctions des conditions transmises dans ce tableau.
422
-	 *
423
-	 * Ce tableau peut avoir plusieurs niveaux de profondeur.
424
-	 *
425
-	 * Les éléments du premier niveau sont reliés par des AND, donc
426
-	 * chaque élément ajouté directement au where par
427
-	 * $boucle->where[] = array(...) ou $boucle->where[] = "'expression'"
428
-	 * est une condition AND en plus.
429
-	 *
430
-	 * Par contre, lorsqu'on indique un tableau, il peut décrire des relations
431
-	 * internes différentes. Soit $expr un tableau d'expressions quelconques de 3 valeurs :
432
-	 * $expr = array(operateur, val1, val2)
433
-	 *
434
-	 * Ces 3 valeurs sont des expressions PHP. L'index 0 désigne l'opérateur
435
-	 * à réaliser tel que :
436
-	 *
437
-	 * - "'='" , "'>='", "'<'", "'IN'", "'REGEXP'", "'LIKE'", ... :
438
-	 *    val1 et val2 sont des champs et valeurs à utiliser dans la comparaison
439
-	 *    suivant cet ordre : "val1 operateur val2".
440
-	 *    Exemple : $boucle->where[] = array("'='", "'articles.statut'", "'\"publie\"'");
441
-	 * - "'AND'", "'OR'", "'NOT'" :
442
-	 *    dans ce cas val1 et val2 sont également des expressions
443
-	 *    de comparaison complètes, et peuvent être eux-même des tableaux comme $expr
444
-	 *    Exemples :
445
-	 *    $boucle->where[] = array("'OR'", $expr1, $expr2);
446
-	 *    $boucle->where[] = array("'NOT'", $expr); // val2 n'existe pas avec NOT
447
-	 *
448
-	 * D'autres noms sont possibles pour l'opérateur (le nombre de valeurs diffère) :
449
-	 * - "'SELF'", "'SUBSELECT'" : indiquent des sous requêtes
450
-	 * - "'?'" : indique une condition à faire évaluer (val1 ? val2 : val3)
451
-	 *
452
-	 * @var array
453
-	 */
454
-	public $where = [];
455
-
456
-	public $join = [];
457
-	public $having = [];
458
-	public $limit;
459
-	public $group = [];
460
-	public $order = [];
461
-	public $default_order = [];
462
-	public $date = 'date';
463
-	public $hash = '';
464
-	public $in = '';
465
-	public $sous_requete = false;
466
-
467
-	/**
468
-	 * Code PHP qui sera ajouté en tout début de la fonction de boucle
469
-	 *
470
-	 * Il sert à insérer le code calculant une hierarchie
471
-	 *
472
-	 * @var string
473
-	 */
474
-	public $hierarchie = '';
475
-
476
-	// champs pour la construction du corps PHP
477
-
478
-	/**
479
-	 * Description des sources de données de la boucle
480
-	 *
481
-	 * Description des données de la boucle issu de trouver_table
482
-	 * dans le cadre de l'itérateur SQL et contenant au moins l'index 'field'.
483
-	 *
484
-	 * @see base_trouver_table_dist()
485
-	 * @var array
486
-	 */
487
-	public $show = [];
488
-
489
-	/**
490
-	 * Nom de la table SQL principale de la boucle, sans son préfixe
491
-	 *
492
-	 * @var string
493
-	 */
494
-	public $id_table;
495
-
496
-	/**
497
-	 * Nom de la clé primaire de la table SQL principale de la boucle
498
-	 *
499
-	 * @var string
500
-	 */
501
-	public $primary;
502
-
503
-	/**
504
-	 * Code PHP compilé de la boucle
505
-	 *
506
-	 * @var string
507
-	 */
508
-	public $return;
509
-
510
-	public $numrows = false;
511
-	public $cptrows = false;
512
-
513
-	/**
514
-	 * Description du squelette
515
-	 *
516
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
517
-	 *
518
-	 * Peut contenir les index :
519
-	 *
520
-	 * - nom : Nom du fichier de cache
521
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
522
-	 * - sourcefile : Chemin du squelette
523
-	 * - squelette : Code du squelette
524
-	 * - id_mere : Identifiant de la boucle parente
525
-	 * - documents : Pour embed et img dans les textes
526
-	 * - session : Pour un cache sessionné par auteur
527
-	 * - niv : Niveau de tabulation
528
-	 *
529
-	 * @var array
530
-	 */
531
-	public $descr = [];
532
-
533
-	/**
534
-	 * Numéro de ligne dans le code source du squelette
535
-	 *
536
-	 * @var int
537
-	 */
538
-	public $ligne = 0;
539
-
540
-
541
-	public $modificateur = []; // table pour stocker les modificateurs de boucle tels que tout, plat ..., utilisable par les plugins egalement
542
-
543
-	/**
544
-	 * Type d'itérateur utilisé pour cette boucle
545
-	 *
546
-	 * - 'SQL' dans le cadre d'une boucle sur une table SQL
547
-	 * - 'DATA' pour l'itérateur DATA, ...
548
-	 *
549
-	 * @var string
550
-	 */
551
-	public $iterateur = ''; // type d'iterateur
552
-
553
-	/**
554
-	 * @var array $debug Textes qui seront insérés dans l’entête de boucle du mode debug
555
-	 */
556
-	public $debug = [];
557
-
558
-	/**
559
-	 * Index de la boucle dont le champ présent dans cette boucle est originaire,
560
-	 * notamment si le champ a été trouve dans une boucle parente
561
-	 *
562
-	 * Tableau nom du champ => index de boucle
563
-	 *
564
-	 * @var array $index_champ
565
-	*/
566
-	public $index_champ = [];
567
-
568
-	// obsoletes, conserves provisoirement pour compatibilite
569
-	public $tout = false;
570
-	public $plat = false;
571
-	public $lien = false;
192
+    /**
193
+     * Type de noeud
194
+     *
195
+     * @var string
196
+     */
197
+    public $type = 'boucle';
198
+
199
+    /**
200
+     * Identifiant de la boucle
201
+     *
202
+     * @var string
203
+     */
204
+    public $id_boucle;
205
+
206
+    /**
207
+     * Identifiant de la boucle parente
208
+     *
209
+     * @var string
210
+     */
211
+    public $id_parent = '';
212
+
213
+    /**
214
+     * Partie avant toujours affichee
215
+     *
216
+     * @var string|array
217
+     */
218
+    public $preaff = '';
219
+
220
+    /**
221
+     * Partie optionnelle avant
222
+     *
223
+     * @var string|array
224
+     */
225
+    public $avant = '';
226
+
227
+    /**
228
+     * Pour chaque élément
229
+     *
230
+     * @var string|array
231
+     */
232
+    public $milieu = '';
233
+
234
+    /**
235
+     * Partie optionnelle après
236
+     *
237
+     * @var string|array
238
+     */
239
+    public $apres = '';
240
+
241
+    /**
242
+     * Partie alternative, si pas de résultat dans la boucle
243
+     *
244
+     * @var string|array
245
+     */
246
+    public $altern = '';
247
+
248
+    /**
249
+     * Partie apres toujours affichee
250
+     *
251
+     * @var string|array
252
+     */
253
+    public $postaff = '';
254
+
255
+
256
+    /**
257
+     * La boucle doit-elle sélectionner la langue ?
258
+     *
259
+     * @var string|null
260
+     */
261
+    public $lang_select;
262
+
263
+    /**
264
+     * Alias de table d'application de la requête ou nom complet de la table SQL
265
+     *
266
+     * @var string|null
267
+     */
268
+    public $type_requete;
269
+
270
+    /**
271
+     * La table est elle optionnelle ?
272
+     *
273
+     * Si oui, aucune erreur ne sera générée si la table demandée n'est pas présente
274
+     *
275
+     * @var bool
276
+     */
277
+    public $table_optionnelle = false;
278
+
279
+    /**
280
+     * Nom du fichier de connexion
281
+     *
282
+     * @var string
283
+     */
284
+    public $sql_serveur = '';
285
+
286
+    /**
287
+     * Paramètres de la boucle
288
+     *
289
+     * Description des paramètres passés à la boucle, qui servent ensuite
290
+     * au calcul des critères
291
+     *
292
+     * @var array
293
+     */
294
+    public $param = [];
295
+
296
+    /**
297
+     * Critères de la boucle
298
+     *
299
+     * @var Critere[]
300
+     */
301
+    public $criteres = [];
302
+
303
+    /**
304
+     * Textes insérés entre 2 éléments de boucle (critère inter)
305
+     *
306
+     * @var string[]
307
+     */
308
+    public $separateur = [];
309
+
310
+    /**
311
+     * Liste des jointures possibles avec cette table
312
+     *
313
+     * Les jointures par défaut de la table sont complétées en priorité
314
+     * des jointures déclarées explicitement sur la boucle
315
+     *
316
+     * @see base_trouver_table_dist()
317
+     * @var array
318
+     */
319
+    public $jointures = [];
320
+
321
+    /**
322
+     * Jointures explicites avec cette table
323
+     *
324
+     * Ces jointures sont utilisées en priorité par rapport aux jointures
325
+     * normales possibles pour retrouver les colonnes demandées extérieures
326
+     * à la boucle.
327
+     *
328
+     * @var string|bool
329
+     */
330
+    public $jointures_explicites = false;
331
+
332
+    /**
333
+     * Nom de la variable PHP stockant le noms de doublons utilisés "$doublons_index"
334
+     *
335
+     * @var string|null
336
+     */
337
+    public $doublons;
338
+
339
+    /**
340
+     * Code PHP ajouté au début de chaque itération de boucle.
341
+     *
342
+     * Utilisé entre autre par les critères {pagination}, {n-a,b}, {a/b}...
343
+     *
344
+     * @var string
345
+     */
346
+    public $partie = '';
347
+
348
+    /**
349
+     * Nombre de divisions de la boucle, d'éléments à afficher,
350
+     * ou de soustractions d'éléments à faire
351
+     *
352
+     * Dans les critères limitant le nombre d'éléments affichés
353
+     * {a,b}, {a,n-b}, {a/b}, {pagination b}, b est affecté à total_parties.
354
+     *
355
+     * @var string
356
+     */
357
+    public $total_parties = '';
358
+
359
+    /**
360
+     * Code PHP ajouté avant l'itération de boucle.
361
+     *
362
+     * Utilisé entre autre par les critères {pagination}, {a,b}, {a/b}
363
+     * pour initialiser les variables de début et de fin d'itération.
364
+     *
365
+     * @var string
366
+     */
367
+    public $mode_partie = '';
368
+
369
+    /**
370
+     * Identifiant d'une boucle qui appelle celle-ci de manière récursive
371
+     *
372
+     * Si une boucle est appelée de manière récursive quelque part par
373
+     * une autre boucle comme <BOUCLE_rec(boucle_identifiant) />, cette
374
+     * boucle (identifiant) reçoit dans cette propriété l'identifiant
375
+     * de l'appelant (rec)
376
+     *
377
+     * @var string
378
+     */
379
+    public $externe = '';
380
+
381
+    // champs pour la construction de la requete SQL
382
+
383
+    /**
384
+     * Liste des champs à récupérer par la boucle
385
+     *
386
+     * Expression 'table.nom_champ' ou calculée 'nom_champ AS x'
387
+     *
388
+     * @var string[]
389
+     */
390
+    public $select = [];
391
+
392
+    /**
393
+     * Liste des alias / tables SQL utilisées dans la boucle
394
+     *
395
+     * L'index est un identifiant (xx dans spip_xx assez souvent) qui servira
396
+     * d'alias au nom de la table ; la valeur est le nom de la table SQL désirée.
397
+     *
398
+     * L'index 0 peut définir le type de sources de données de l'itérateur DATA
399
+     *
400
+     * @var string[]
401
+     */
402
+    public $from = [];
403
+
404
+    /**
405
+     * Liste des alias / type de jointures utilisées dans la boucle
406
+     *
407
+     * L'index est le nom d'alias (comme pour la propriété $from), et la valeur
408
+     * un type de jointure parmi 'INNER', 'LEFT', 'RIGHT', 'OUTER'.
409
+     *
410
+     * Lorsque le type n'est pas déclaré pour un alias, c'est 'INNER'
411
+     * qui sera utilisé par défaut (créant donc un INNER JOIN).
412
+     *
413
+     * @var string[]
414
+     */
415
+    public $from_type = [];
416
+
417
+    /**
418
+     * Liste des conditions WHERE de la boucle
419
+     *
420
+     * Permet de restreindre les éléments retournés par une boucle
421
+     * en fonctions des conditions transmises dans ce tableau.
422
+     *
423
+     * Ce tableau peut avoir plusieurs niveaux de profondeur.
424
+     *
425
+     * Les éléments du premier niveau sont reliés par des AND, donc
426
+     * chaque élément ajouté directement au where par
427
+     * $boucle->where[] = array(...) ou $boucle->where[] = "'expression'"
428
+     * est une condition AND en plus.
429
+     *
430
+     * Par contre, lorsqu'on indique un tableau, il peut décrire des relations
431
+     * internes différentes. Soit $expr un tableau d'expressions quelconques de 3 valeurs :
432
+     * $expr = array(operateur, val1, val2)
433
+     *
434
+     * Ces 3 valeurs sont des expressions PHP. L'index 0 désigne l'opérateur
435
+     * à réaliser tel que :
436
+     *
437
+     * - "'='" , "'>='", "'<'", "'IN'", "'REGEXP'", "'LIKE'", ... :
438
+     *    val1 et val2 sont des champs et valeurs à utiliser dans la comparaison
439
+     *    suivant cet ordre : "val1 operateur val2".
440
+     *    Exemple : $boucle->where[] = array("'='", "'articles.statut'", "'\"publie\"'");
441
+     * - "'AND'", "'OR'", "'NOT'" :
442
+     *    dans ce cas val1 et val2 sont également des expressions
443
+     *    de comparaison complètes, et peuvent être eux-même des tableaux comme $expr
444
+     *    Exemples :
445
+     *    $boucle->where[] = array("'OR'", $expr1, $expr2);
446
+     *    $boucle->where[] = array("'NOT'", $expr); // val2 n'existe pas avec NOT
447
+     *
448
+     * D'autres noms sont possibles pour l'opérateur (le nombre de valeurs diffère) :
449
+     * - "'SELF'", "'SUBSELECT'" : indiquent des sous requêtes
450
+     * - "'?'" : indique une condition à faire évaluer (val1 ? val2 : val3)
451
+     *
452
+     * @var array
453
+     */
454
+    public $where = [];
455
+
456
+    public $join = [];
457
+    public $having = [];
458
+    public $limit;
459
+    public $group = [];
460
+    public $order = [];
461
+    public $default_order = [];
462
+    public $date = 'date';
463
+    public $hash = '';
464
+    public $in = '';
465
+    public $sous_requete = false;
466
+
467
+    /**
468
+     * Code PHP qui sera ajouté en tout début de la fonction de boucle
469
+     *
470
+     * Il sert à insérer le code calculant une hierarchie
471
+     *
472
+     * @var string
473
+     */
474
+    public $hierarchie = '';
475
+
476
+    // champs pour la construction du corps PHP
477
+
478
+    /**
479
+     * Description des sources de données de la boucle
480
+     *
481
+     * Description des données de la boucle issu de trouver_table
482
+     * dans le cadre de l'itérateur SQL et contenant au moins l'index 'field'.
483
+     *
484
+     * @see base_trouver_table_dist()
485
+     * @var array
486
+     */
487
+    public $show = [];
488
+
489
+    /**
490
+     * Nom de la table SQL principale de la boucle, sans son préfixe
491
+     *
492
+     * @var string
493
+     */
494
+    public $id_table;
495
+
496
+    /**
497
+     * Nom de la clé primaire de la table SQL principale de la boucle
498
+     *
499
+     * @var string
500
+     */
501
+    public $primary;
502
+
503
+    /**
504
+     * Code PHP compilé de la boucle
505
+     *
506
+     * @var string
507
+     */
508
+    public $return;
509
+
510
+    public $numrows = false;
511
+    public $cptrows = false;
512
+
513
+    /**
514
+     * Description du squelette
515
+     *
516
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
517
+     *
518
+     * Peut contenir les index :
519
+     *
520
+     * - nom : Nom du fichier de cache
521
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
522
+     * - sourcefile : Chemin du squelette
523
+     * - squelette : Code du squelette
524
+     * - id_mere : Identifiant de la boucle parente
525
+     * - documents : Pour embed et img dans les textes
526
+     * - session : Pour un cache sessionné par auteur
527
+     * - niv : Niveau de tabulation
528
+     *
529
+     * @var array
530
+     */
531
+    public $descr = [];
532
+
533
+    /**
534
+     * Numéro de ligne dans le code source du squelette
535
+     *
536
+     * @var int
537
+     */
538
+    public $ligne = 0;
539
+
540
+
541
+    public $modificateur = []; // table pour stocker les modificateurs de boucle tels que tout, plat ..., utilisable par les plugins egalement
542
+
543
+    /**
544
+     * Type d'itérateur utilisé pour cette boucle
545
+     *
546
+     * - 'SQL' dans le cadre d'une boucle sur une table SQL
547
+     * - 'DATA' pour l'itérateur DATA, ...
548
+     *
549
+     * @var string
550
+     */
551
+    public $iterateur = ''; // type d'iterateur
552
+
553
+    /**
554
+     * @var array $debug Textes qui seront insérés dans l’entête de boucle du mode debug
555
+     */
556
+    public $debug = [];
557
+
558
+    /**
559
+     * Index de la boucle dont le champ présent dans cette boucle est originaire,
560
+     * notamment si le champ a été trouve dans une boucle parente
561
+     *
562
+     * Tableau nom du champ => index de boucle
563
+     *
564
+     * @var array $index_champ
565
+     */
566
+    public $index_champ = [];
567
+
568
+    // obsoletes, conserves provisoirement pour compatibilite
569
+    public $tout = false;
570
+    public $plat = false;
571
+    public $lien = false;
572 572
 }
573 573
 
574 574
 /**
@@ -579,56 +579,56 @@  discard block
 block discarded – undo
579 579
  * @package SPIP\Core\Compilateur\AST
580 580
  **/
581 581
 class Critere {
582
-	/**
583
-	 * Type de noeud
584
-	 *
585
-	 * @var string
586
-	 */
587
-	public $type = 'critere';
588
-
589
-	/**
590
-	 * Opérateur (>, <, >=, IN, ...)
591
-	 *
592
-	 * @var null|string
593
-	 */
594
-	public $op;
595
-
596
-	/**
597
-	 * Présence d'une négation (truc !op valeur)
598
-	 *
599
-	 * @var null|string
600
-	 */
601
-	public $not;
602
-
603
-	/**
604
-	 * Présence d'une exclusion (!truc op valeur)
605
-	 *
606
-	 * @var null|string
607
-	 */
608
-	public $exclus;
609
-
610
-	/**
611
-	 * Présence d'une condition dans le critère (truc ?)
612
-	 *
613
-	 * @var bool
614
-	 */
615
-	public $cond = false;
616
-
617
-	/**
618
-	 * Paramètres du critère
619
-	 * - $param[0] : élément avant l'opérateur
620
-	 * - $param[1..n] : éléments après l'opérateur
621
-	 *
622
-	 * @var array
623
-	 */
624
-	public $param = [];
625
-
626
-	/**
627
-	 * Numéro de ligne dans le code source du squelette
628
-	 *
629
-	 * @var int
630
-	 */
631
-	public $ligne = 0;
582
+    /**
583
+     * Type de noeud
584
+     *
585
+     * @var string
586
+     */
587
+    public $type = 'critere';
588
+
589
+    /**
590
+     * Opérateur (>, <, >=, IN, ...)
591
+     *
592
+     * @var null|string
593
+     */
594
+    public $op;
595
+
596
+    /**
597
+     * Présence d'une négation (truc !op valeur)
598
+     *
599
+     * @var null|string
600
+     */
601
+    public $not;
602
+
603
+    /**
604
+     * Présence d'une exclusion (!truc op valeur)
605
+     *
606
+     * @var null|string
607
+     */
608
+    public $exclus;
609
+
610
+    /**
611
+     * Présence d'une condition dans le critère (truc ?)
612
+     *
613
+     * @var bool
614
+     */
615
+    public $cond = false;
616
+
617
+    /**
618
+     * Paramètres du critère
619
+     * - $param[0] : élément avant l'opérateur
620
+     * - $param[1..n] : éléments après l'opérateur
621
+     *
622
+     * @var array
623
+     */
624
+    public $param = [];
625
+
626
+    /**
627
+     * Numéro de ligne dans le code source du squelette
628
+     *
629
+     * @var int
630
+     */
631
+    public $ligne = 0;
632 632
 }
633 633
 
634 634
 /**
@@ -637,139 +637,139 @@  discard block
 block discarded – undo
637 637
  * @package SPIP\Core\Compilateur\AST
638 638
  **/
639 639
 class Champ {
640
-	/**
641
-	 * Type de noeud
642
-	 *
643
-	 * @var string
644
-	 */
645
-	public $type = 'champ';
646
-
647
-	/**
648
-	 * Nom du champ demandé. Exemple 'ID_ARTICLE'
649
-	 *
650
-	 * @var string|null
651
-	 */
652
-	public $nom_champ;
653
-
654
-	/**
655
-	 * Identifiant de la boucle parente si explicité
656
-	 *
657
-	 * @var string|null
658
-	 */
659
-	public $nom_boucle = '';
660
-
661
-	/**
662
-	 * Partie optionnelle avant
663
-	 *
664
-	 * @var null|string|array
665
-	 */
666
-	public $avant;
667
-
668
-	/**
669
-	 * Partie optionnelle après
670
-	 *
671
-	 * @var null|string|array
672
-	 */
673
-	public $apres;
674
-
675
-	/**
676
-	 * Étoiles : annuler des automatismes
677
-	 *
678
-	 * - '*' annule les filtres automatiques
679
-	 * - '**' annule en plus les protections de scripts
680
-	 *
681
-	 * @var null|string
682
-	 */
683
-	public $etoile;
684
-
685
-	/**
686
-	 * Arguments et filtres explicites sur la balise
687
-	 *
688
-	 * - $param[0] contient les arguments de la balise
689
-	 * - $param[1..n] contient les filtres à appliquer à la balise
690
-	 *
691
-	 * @var array
692
-	 */
693
-	public $param = [];
694
-
695
-	/**
696
-	 * Source des filtres  (compatibilité) (?)
697
-	 *
698
-	 * @var array|null
699
-	 */
700
-	public $fonctions = [];
701
-
702
-	/**
703
-	 * Identifiant de la boucle
704
-	 *
705
-	 * @var string
706
-	 */
707
-	public $id_boucle = '';
708
-
709
-	/**
710
-	 * AST du squelette, liste de toutes les boucles
711
-	 *
712
-	 * @var Boucles[]
713
-	 */
714
-	public $boucles;
715
-
716
-	/**
717
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
718
-	 *
719
-	 * @var string|null
720
-	 */
721
-	public $type_requete;
722
-
723
-	/**
724
-	 * Résultat de la compilation: toujours une expression PHP
725
-	 *
726
-	 * @var string
727
-	 */
728
-	public $code = '';
729
-
730
-	/**
731
-	 * Interdire les scripts
732
-	 *
733
-	 * false si on est sûr de cette balise
734
-	 *
735
-	 * @see interdire_scripts()
736
-	 * @var bool
737
-	 */
738
-	public $interdire_scripts = true;
739
-
740
-	/**
741
-	 * Description du squelette
742
-	 *
743
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
744
-	 *
745
-	 * Peut contenir les index :
746
-	 *
747
-	 * - nom : Nom du fichier de cache
748
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
749
-	 * - sourcefile : Chemin du squelette
750
-	 * - squelette : Code du squelette
751
-	 * - id_mere : Identifiant de la boucle parente
752
-	 * - documents : Pour embed et img dans les textes
753
-	 * - session : Pour un cache sessionné par auteur
754
-	 * - niv : Niveau de tabulation
755
-	 *
756
-	 * @var array
757
-	 */
758
-	public $descr = [];
759
-
760
-	/**
761
-	 * Numéro de ligne dans le code source du squelette
762
-	 *
763
-	 * @var int
764
-	 */
765
-	public $ligne = 0;
766
-
767
-	/**
768
-	 * Drapeau pour reperer les balises calculées par une fonction explicite
769
-	 *
770
-	 * @var bool
771
-	 */
772
-	public $balise_calculee = false;
640
+    /**
641
+     * Type de noeud
642
+     *
643
+     * @var string
644
+     */
645
+    public $type = 'champ';
646
+
647
+    /**
648
+     * Nom du champ demandé. Exemple 'ID_ARTICLE'
649
+     *
650
+     * @var string|null
651
+     */
652
+    public $nom_champ;
653
+
654
+    /**
655
+     * Identifiant de la boucle parente si explicité
656
+     *
657
+     * @var string|null
658
+     */
659
+    public $nom_boucle = '';
660
+
661
+    /**
662
+     * Partie optionnelle avant
663
+     *
664
+     * @var null|string|array
665
+     */
666
+    public $avant;
667
+
668
+    /**
669
+     * Partie optionnelle après
670
+     *
671
+     * @var null|string|array
672
+     */
673
+    public $apres;
674
+
675
+    /**
676
+     * Étoiles : annuler des automatismes
677
+     *
678
+     * - '*' annule les filtres automatiques
679
+     * - '**' annule en plus les protections de scripts
680
+     *
681
+     * @var null|string
682
+     */
683
+    public $etoile;
684
+
685
+    /**
686
+     * Arguments et filtres explicites sur la balise
687
+     *
688
+     * - $param[0] contient les arguments de la balise
689
+     * - $param[1..n] contient les filtres à appliquer à la balise
690
+     *
691
+     * @var array
692
+     */
693
+    public $param = [];
694
+
695
+    /**
696
+     * Source des filtres  (compatibilité) (?)
697
+     *
698
+     * @var array|null
699
+     */
700
+    public $fonctions = [];
701
+
702
+    /**
703
+     * Identifiant de la boucle
704
+     *
705
+     * @var string
706
+     */
707
+    public $id_boucle = '';
708
+
709
+    /**
710
+     * AST du squelette, liste de toutes les boucles
711
+     *
712
+     * @var Boucles[]
713
+     */
714
+    public $boucles;
715
+
716
+    /**
717
+     * Alias de table d'application de la requête ou nom complet de la table SQL
718
+     *
719
+     * @var string|null
720
+     */
721
+    public $type_requete;
722
+
723
+    /**
724
+     * Résultat de la compilation: toujours une expression PHP
725
+     *
726
+     * @var string
727
+     */
728
+    public $code = '';
729
+
730
+    /**
731
+     * Interdire les scripts
732
+     *
733
+     * false si on est sûr de cette balise
734
+     *
735
+     * @see interdire_scripts()
736
+     * @var bool
737
+     */
738
+    public $interdire_scripts = true;
739
+
740
+    /**
741
+     * Description du squelette
742
+     *
743
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
744
+     *
745
+     * Peut contenir les index :
746
+     *
747
+     * - nom : Nom du fichier de cache
748
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
749
+     * - sourcefile : Chemin du squelette
750
+     * - squelette : Code du squelette
751
+     * - id_mere : Identifiant de la boucle parente
752
+     * - documents : Pour embed et img dans les textes
753
+     * - session : Pour un cache sessionné par auteur
754
+     * - niv : Niveau de tabulation
755
+     *
756
+     * @var array
757
+     */
758
+    public $descr = [];
759
+
760
+    /**
761
+     * Numéro de ligne dans le code source du squelette
762
+     *
763
+     * @var int
764
+     */
765
+    public $ligne = 0;
766
+
767
+    /**
768
+     * Drapeau pour reperer les balises calculées par une fonction explicite
769
+     *
770
+     * @var bool
771
+     */
772
+    public $balise_calculee = false;
773 773
 }
774 774
 
775 775
 
@@ -777,123 +777,123 @@  discard block
 block discarded – undo
777 777
  * Description d'une chaîne de langue
778 778
  **/
779 779
 class Idiome {
780
-	/**
781
-	 * Type de noeud
782
-	 *
783
-	 * @var string
784
-	 */
785
-	public $type = 'idiome';
786
-
787
-	/**
788
-	 * Clé de traduction demandée. Exemple 'item_oui'
789
-	 *
790
-	 * @var string
791
-	 */
792
-	public $nom_champ = '';
793
-
794
-	/**
795
-	 * Module de langue où chercher la clé de traduction. Exemple 'medias'
796
-	 *
797
-	 * @var string
798
-	 */
799
-	public $module = '';
800
-
801
-	/**
802
-	 * Arguments à passer à la chaîne
803
-	 *
804
-	 * @var array
805
-	 */
806
-	public $arg = [];
807
-
808
-	/**
809
-	 * Filtres à appliquer au résultat
810
-	 *
811
-	 * @var array
812
-	 */
813
-	public $param = [];
814
-
815
-	/**
816
-	 * Source des filtres  (compatibilité) (?)
817
-	 *
818
-	 * @var array|null
819
-	 */
820
-	public $fonctions = [];
821
-
822
-	/**
823
-	 * Inutilisé, propriété générique de l'AST
824
-	 *
825
-	 * @var string|array
826
-	 */
827
-	public $avant = '';
828
-
829
-	/**
830
-	 * Inutilisé, propriété générique de l'AST
831
-	 *
832
-	 * @var string|array
833
-	 */
834
-	public $apres = '';
835
-
836
-	/**
837
-	 * Identifiant de la boucle
838
-	 *
839
-	 * @var string
840
-	 */
841
-	public $id_boucle = '';
842
-
843
-	/**
844
-	 * AST du squelette, liste de toutes les boucles
845
-	 *
846
-	 * @var Boucles[]
847
-	 */
848
-	public $boucles;
849
-
850
-	/**
851
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
852
-	 *
853
-	 * @var string|null
854
-	 */
855
-	public $type_requete;
856
-
857
-	/**
858
-	 * Résultat de la compilation: toujours une expression PHP
859
-	 *
860
-	 * @var string
861
-	 */
862
-	public $code = '';
863
-
864
-	/**
865
-	 * Interdire les scripts
866
-	 *
867
-	 * @see interdire_scripts()
868
-	 * @var bool
869
-	 */
870
-	public $interdire_scripts = false;
871
-
872
-	/**
873
-	 * Description du squelette
874
-	 *
875
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
876
-	 *
877
-	 * Peut contenir les index :
878
-	 * - nom : Nom du fichier de cache
879
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
880
-	 * - sourcefile : Chemin du squelette
881
-	 * - squelette : Code du squelette
882
-	 * - id_mere : Identifiant de la boucle parente
883
-	 * - documents : Pour embed et img dans les textes
884
-	 * - session : Pour un cache sessionné par auteur
885
-	 * - niv : Niveau de tabulation
886
-	 *
887
-	 * @var array
888
-	 */
889
-	public $descr = [];
890
-
891
-	/**
892
-	 * Numéro de ligne dans le code source du squelette
893
-	 *
894
-	 * @var int
895
-	 */
896
-	public $ligne = 0;
780
+    /**
781
+     * Type de noeud
782
+     *
783
+     * @var string
784
+     */
785
+    public $type = 'idiome';
786
+
787
+    /**
788
+     * Clé de traduction demandée. Exemple 'item_oui'
789
+     *
790
+     * @var string
791
+     */
792
+    public $nom_champ = '';
793
+
794
+    /**
795
+     * Module de langue où chercher la clé de traduction. Exemple 'medias'
796
+     *
797
+     * @var string
798
+     */
799
+    public $module = '';
800
+
801
+    /**
802
+     * Arguments à passer à la chaîne
803
+     *
804
+     * @var array
805
+     */
806
+    public $arg = [];
807
+
808
+    /**
809
+     * Filtres à appliquer au résultat
810
+     *
811
+     * @var array
812
+     */
813
+    public $param = [];
814
+
815
+    /**
816
+     * Source des filtres  (compatibilité) (?)
817
+     *
818
+     * @var array|null
819
+     */
820
+    public $fonctions = [];
821
+
822
+    /**
823
+     * Inutilisé, propriété générique de l'AST
824
+     *
825
+     * @var string|array
826
+     */
827
+    public $avant = '';
828
+
829
+    /**
830
+     * Inutilisé, propriété générique de l'AST
831
+     *
832
+     * @var string|array
833
+     */
834
+    public $apres = '';
835
+
836
+    /**
837
+     * Identifiant de la boucle
838
+     *
839
+     * @var string
840
+     */
841
+    public $id_boucle = '';
842
+
843
+    /**
844
+     * AST du squelette, liste de toutes les boucles
845
+     *
846
+     * @var Boucles[]
847
+     */
848
+    public $boucles;
849
+
850
+    /**
851
+     * Alias de table d'application de la requête ou nom complet de la table SQL
852
+     *
853
+     * @var string|null
854
+     */
855
+    public $type_requete;
856
+
857
+    /**
858
+     * Résultat de la compilation: toujours une expression PHP
859
+     *
860
+     * @var string
861
+     */
862
+    public $code = '';
863
+
864
+    /**
865
+     * Interdire les scripts
866
+     *
867
+     * @see interdire_scripts()
868
+     * @var bool
869
+     */
870
+    public $interdire_scripts = false;
871
+
872
+    /**
873
+     * Description du squelette
874
+     *
875
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
876
+     *
877
+     * Peut contenir les index :
878
+     * - nom : Nom du fichier de cache
879
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
880
+     * - sourcefile : Chemin du squelette
881
+     * - squelette : Code du squelette
882
+     * - id_mere : Identifiant de la boucle parente
883
+     * - documents : Pour embed et img dans les textes
884
+     * - session : Pour un cache sessionné par auteur
885
+     * - niv : Niveau de tabulation
886
+     *
887
+     * @var array
888
+     */
889
+    public $descr = [];
890
+
891
+    /**
892
+     * Numéro de ligne dans le code source du squelette
893
+     *
894
+     * @var int
895
+     */
896
+    public $ligne = 0;
897 897
 }
898 898
 
899 899
 /**
@@ -902,28 +902,28 @@  discard block
 block discarded – undo
902 902
  * @package SPIP\Core\Compilateur\AST
903 903
  **/
904 904
 class Polyglotte {
905
-	/**
906
-	 * Type de noeud
907
-	 *
908
-	 * @var string
909
-	 */
910
-	public $type = 'polyglotte';
911
-
912
-	/**
913
-	 * Tableau des traductions possibles classées par langue
914
-	 *
915
-	 * Tableau code de langue => texte
916
-	 *
917
-	 * @var array
918
-	 */
919
-	public $traductions = [];
920
-
921
-	/**
922
-	 * Numéro de ligne dans le code source du squelette
923
-	 *
924
-	 * @var int
925
-	 */
926
-	public $ligne = 0;
905
+    /**
906
+     * Type de noeud
907
+     *
908
+     * @var string
909
+     */
910
+    public $type = 'polyglotte';
911
+
912
+    /**
913
+     * Tableau des traductions possibles classées par langue
914
+     *
915
+     * Tableau code de langue => texte
916
+     *
917
+     * @var array
918
+     */
919
+    public $traductions = [];
920
+
921
+    /**
922
+     * Numéro de ligne dans le code source du squelette
923
+     *
924
+     * @var int
925
+     */
926
+    public $ligne = 0;
927 927
 }
928 928
 
929 929
 
@@ -948,90 +948,90 @@  discard block
 block discarded – undo
948 948
  */
949 949
 function declarer_interfaces() {
950 950
 
951
-	$GLOBALS['table_des_tables']['articles'] = 'articles';
952
-	$GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
953
-	$GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
954
-	$GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
955
-
956
-	// definition des statuts de publication
957
-	$GLOBALS['table_statut'] = [];
958
-
959
-	//
960
-	// tableau des tables de jointures
961
-	// Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
962
-	$GLOBALS['tables_jointures'] = [];
963
-	$GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
964
-
965
-	// $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
966
-	$GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
967
-
968
-
969
-	if (!defined('_TRAITEMENT_TYPO')) {
970
-		define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
971
-	}
972
-	if (!defined('_TRAITEMENT_RACCOURCIS')) {
973
-		define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
974
-	}
975
-	if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
976
-		define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
977
-	}
978
-	$GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
979
-	$GLOBALS['table_des_traitements']['NOM_SITE']['spip_auteurs'] = 'entites_html(%s)';
980
-	$GLOBALS['table_des_traitements']['NOM']['spip_auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
981
-	$GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
982
-	$GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
983
-	$GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
984
-	$GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
985
-	$GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
986
-	$GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
987
-	$GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
988
-	$GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
989
-	$GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
990
-	$GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
991
-	$GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
992
-	$GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
993
-	$GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
994
-	$GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
995
-	$GLOBALS['table_des_traitements']['TAGS'][] = '%s';
996
-	$GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
997
-	$GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
998
-	$GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
999
-	$GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
1000
-	$GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
1001
-	$GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
1002
-
1003
-	// valeur par defaut pour les balises non listees ci-dessus
1004
-	$GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
1005
-	// toujours securiser les DATA
1006
-	$GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
1007
-	// expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
1008
-	$GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
1009
-
1010
-
1011
-	// gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
1012
-	$interfaces = pipeline(
1013
-		'declarer_tables_interfaces',
1014
-		[
1015
-			'table_des_tables' => $GLOBALS['table_des_tables'],
1016
-			'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
1017
-			'table_date' => $GLOBALS['table_date'],
1018
-			'table_titre' => $GLOBALS['table_titre'],
1019
-			'tables_jointures' => $GLOBALS['tables_jointures'],
1020
-			'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
1021
-			'table_des_traitements' => $GLOBALS['table_des_traitements'],
1022
-			'table_statut' => $GLOBALS['table_statut'],
1023
-		]
1024
-	);
1025
-	if ($interfaces) {
1026
-		$GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
1027
-		$GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
1028
-		$GLOBALS['table_date'] = $interfaces['table_date'];
1029
-		$GLOBALS['table_titre'] = $interfaces['table_titre'];
1030
-		$GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
1031
-		$GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
1032
-		$GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
1033
-		$GLOBALS['table_statut'] = $interfaces['table_statut'];
1034
-	}
951
+    $GLOBALS['table_des_tables']['articles'] = 'articles';
952
+    $GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
953
+    $GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
954
+    $GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
955
+
956
+    // definition des statuts de publication
957
+    $GLOBALS['table_statut'] = [];
958
+
959
+    //
960
+    // tableau des tables de jointures
961
+    // Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
962
+    $GLOBALS['tables_jointures'] = [];
963
+    $GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
964
+
965
+    // $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
966
+    $GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
967
+
968
+
969
+    if (!defined('_TRAITEMENT_TYPO')) {
970
+        define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
971
+    }
972
+    if (!defined('_TRAITEMENT_RACCOURCIS')) {
973
+        define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
974
+    }
975
+    if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
976
+        define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
977
+    }
978
+    $GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
979
+    $GLOBALS['table_des_traitements']['NOM_SITE']['spip_auteurs'] = 'entites_html(%s)';
980
+    $GLOBALS['table_des_traitements']['NOM']['spip_auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
981
+    $GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
982
+    $GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
983
+    $GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
984
+    $GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
985
+    $GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
986
+    $GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
987
+    $GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
988
+    $GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
989
+    $GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
990
+    $GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
991
+    $GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
992
+    $GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
993
+    $GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
994
+    $GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
995
+    $GLOBALS['table_des_traitements']['TAGS'][] = '%s';
996
+    $GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
997
+    $GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
998
+    $GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
999
+    $GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
1000
+    $GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
1001
+    $GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
1002
+
1003
+    // valeur par defaut pour les balises non listees ci-dessus
1004
+    $GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
1005
+    // toujours securiser les DATA
1006
+    $GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
1007
+    // expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
1008
+    $GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
1009
+
1010
+
1011
+    // gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
1012
+    $interfaces = pipeline(
1013
+        'declarer_tables_interfaces',
1014
+        [
1015
+            'table_des_tables' => $GLOBALS['table_des_tables'],
1016
+            'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
1017
+            'table_date' => $GLOBALS['table_date'],
1018
+            'table_titre' => $GLOBALS['table_titre'],
1019
+            'tables_jointures' => $GLOBALS['tables_jointures'],
1020
+            'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
1021
+            'table_des_traitements' => $GLOBALS['table_des_traitements'],
1022
+            'table_statut' => $GLOBALS['table_statut'],
1023
+        ]
1024
+    );
1025
+    if ($interfaces) {
1026
+        $GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
1027
+        $GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
1028
+        $GLOBALS['table_date'] = $interfaces['table_date'];
1029
+        $GLOBALS['table_titre'] = $interfaces['table_titre'];
1030
+        $GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
1031
+        $GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
1032
+        $GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
1033
+        $GLOBALS['table_statut'] = $interfaces['table_statut'];
1034
+    }
1035 1035
 }
1036 1036
 
1037 1037
 declarer_interfaces();
Please login to merge, or discard this patch.
ecrire/public/criteres.php 1 patch
Indentation   +1723 added lines, -1723 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
 /**
@@ -43,14 +43,14 @@  discard block
 block discarded – undo
43 43
  **/
44 44
 function critere_racine_dist($idb, &$boucles, $crit) {
45 45
 
46
-	$not = $crit->not;
47
-	$boucle = &$boucles[$idb];
48
-	$id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
49
-		$GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
50
-		'id_parent';
46
+    $not = $crit->not;
47
+    $boucle = &$boucles[$idb];
48
+    $id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
49
+        $GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
50
+        'id_parent';
51 51
 
52
-	$c = ["'='", "'$boucle->id_table." . "$id_parent'", 0];
53
-	$boucle->where[] = ($crit->not ? ["'NOT'", $c] : $c);
52
+    $c = ["'='", "'$boucle->id_table." . "$id_parent'", 0];
53
+    $boucle->where[] = ($crit->not ? ["'NOT'", $c] : $c);
54 54
 }
55 55
 
56 56
 
@@ -67,15 +67,15 @@  discard block
 block discarded – undo
67 67
  * @return void
68 68
  **/
69 69
 function critere_exclus_dist($idb, &$boucles, $crit) {
70
-	$not = $crit->not;
71
-	$boucle = &$boucles[$idb];
72
-	$id = $boucle->primary;
73
-
74
-	if ($not or !$id) {
75
-		return (['zbug_critere_inconnu', ['critere' => $not . $crit->op]]);
76
-	}
77
-	$arg = kwote(calculer_argument_precedent($idb, $id, $boucles));
78
-	$boucle->where[] = ["'!='", "'$boucle->id_table." . "$id'", $arg];
70
+    $not = $crit->not;
71
+    $boucle = &$boucles[$idb];
72
+    $id = $boucle->primary;
73
+
74
+    if ($not or !$id) {
75
+        return (['zbug_critere_inconnu', ['critere' => $not . $crit->op]]);
76
+    }
77
+    $arg = kwote(calculer_argument_precedent($idb, $id, $boucles));
78
+    $boucle->where[] = ["'!='", "'$boucle->id_table." . "$id'", $arg];
79 79
 }
80 80
 
81 81
 
@@ -95,73 +95,73 @@  discard block
 block discarded – undo
95 95
  * @return void
96 96
  **/
97 97
 function critere_doublons_dist($idb, &$boucles, $crit) {
98
-	$boucle = &$boucles[$idb];
99
-	$primary = $boucle->primary;
100
-
101
-	// la table nécessite une clé primaire, non composée
102
-	if (!$primary or strpos($primary, ',')) {
103
-		return (['zbug_doublon_sur_table_sans_cle_primaire']);
104
-	}
105
-
106
-	$not = ($crit->not ? '' : 'NOT');
107
-
108
-	// le doublon s'applique sur un type de boucle (article)
109
-	$nom = "'" . $boucle->type_requete . "'";
110
-
111
-	// compléter le nom avec un nom précisé {doublons nom}
112
-	// on obtient $nom = "'article' . 'nom'"
113
-	if (isset($crit->param[0])) {
114
-		$nom .= '.' . calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
115
-	}
116
-
117
-	// code qui déclarera l'index du stockage de nos doublons (pour éviter une notice PHP)
118
-	$init_comment = "\n\n\t// Initialise le(s) critère(s) doublons\n";
119
-	$init_code = "\tif (!isset(\$doublons[\$d = $nom])) { \$doublons[\$d] = ''; }\n";
120
-
121
-	// on crée un sql_in avec la clé primaire de la table
122
-	// et la collection des doublons déjà emmagasinés dans le tableau
123
-	// $doublons et son index, ici $nom
124
-
125
-	// debut du code "sql_in('articles.id_article', "
126
-	$debut_in = "sql_in('" . $boucle->id_table . '.' . $primary . "', ";
127
-	// lecture des données du doublon "$doublons[$doublon_index[] = "
128
-	// Attention : boucle->doublons désigne une variable qu'on affecte
129
-	$debut_doub = '$doublons[' . (!$not ? '' : ($boucle->doublons . '[]= '));
130
-
131
-	// le debut complet du code des doublons
132
-	$debut_doub = $debut_in . $debut_doub;
133
-
134
-	// nom du doublon "('article' . 'nom')]"
135
-	$fin_doub = "($nom)]";
136
-
137
-	// si on trouve un autre critère doublon,
138
-	// on fusionne pour avoir un seul IN, et on s'en va !
139
-	foreach ($boucle->where as $k => $w) {
140
-		if (strpos($w[0], $debut_doub) === 0) {
141
-			// fusionner le sql_in (du where)
142
-			$boucle->where[$k][0] = $debut_doub . $fin_doub . ' . ' . substr($w[0], strlen($debut_in));
143
-			// fusionner l'initialisation (du hash) pour faire plus joli
144
-			$x = strpos($boucle->hash, $init_comment);
145
-			$len = strlen($init_comment);
146
-			$boucle->hash =
147
-				substr($boucle->hash, 0, $x + $len) . $init_code . substr($boucle->hash, $x + $len);
148
-
149
-			return;
150
-		}
151
-	}
152
-
153
-	// mettre l'ensemble dans un tableau pour que ce ne soit pas vu comme une constante
154
-	$boucle->where[] = [$debut_doub . $fin_doub . ", '" . $not . "')"];
155
-
156
-	// déclarer le doublon s'il n'existe pas encore
157
-	$boucle->hash .= $init_comment . $init_code;
158
-
159
-
160
-	# la ligne suivante avait l'intention d'eviter une collecte deja faite
161
-	# mais elle fait planter une boucle a 2 critere doublons:
162
-	# {!doublons A}{doublons B}
163
-	# (de http://article.gmane.org/gmane.comp.web.spip.devel/31034)
164
-	#	if ($crit->not) $boucle->doublons = "";
98
+    $boucle = &$boucles[$idb];
99
+    $primary = $boucle->primary;
100
+
101
+    // la table nécessite une clé primaire, non composée
102
+    if (!$primary or strpos($primary, ',')) {
103
+        return (['zbug_doublon_sur_table_sans_cle_primaire']);
104
+    }
105
+
106
+    $not = ($crit->not ? '' : 'NOT');
107
+
108
+    // le doublon s'applique sur un type de boucle (article)
109
+    $nom = "'" . $boucle->type_requete . "'";
110
+
111
+    // compléter le nom avec un nom précisé {doublons nom}
112
+    // on obtient $nom = "'article' . 'nom'"
113
+    if (isset($crit->param[0])) {
114
+        $nom .= '.' . calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
115
+    }
116
+
117
+    // code qui déclarera l'index du stockage de nos doublons (pour éviter une notice PHP)
118
+    $init_comment = "\n\n\t// Initialise le(s) critère(s) doublons\n";
119
+    $init_code = "\tif (!isset(\$doublons[\$d = $nom])) { \$doublons[\$d] = ''; }\n";
120
+
121
+    // on crée un sql_in avec la clé primaire de la table
122
+    // et la collection des doublons déjà emmagasinés dans le tableau
123
+    // $doublons et son index, ici $nom
124
+
125
+    // debut du code "sql_in('articles.id_article', "
126
+    $debut_in = "sql_in('" . $boucle->id_table . '.' . $primary . "', ";
127
+    // lecture des données du doublon "$doublons[$doublon_index[] = "
128
+    // Attention : boucle->doublons désigne une variable qu'on affecte
129
+    $debut_doub = '$doublons[' . (!$not ? '' : ($boucle->doublons . '[]= '));
130
+
131
+    // le debut complet du code des doublons
132
+    $debut_doub = $debut_in . $debut_doub;
133
+
134
+    // nom du doublon "('article' . 'nom')]"
135
+    $fin_doub = "($nom)]";
136
+
137
+    // si on trouve un autre critère doublon,
138
+    // on fusionne pour avoir un seul IN, et on s'en va !
139
+    foreach ($boucle->where as $k => $w) {
140
+        if (strpos($w[0], $debut_doub) === 0) {
141
+            // fusionner le sql_in (du where)
142
+            $boucle->where[$k][0] = $debut_doub . $fin_doub . ' . ' . substr($w[0], strlen($debut_in));
143
+            // fusionner l'initialisation (du hash) pour faire plus joli
144
+            $x = strpos($boucle->hash, $init_comment);
145
+            $len = strlen($init_comment);
146
+            $boucle->hash =
147
+                substr($boucle->hash, 0, $x + $len) . $init_code . substr($boucle->hash, $x + $len);
148
+
149
+            return;
150
+        }
151
+    }
152
+
153
+    // mettre l'ensemble dans un tableau pour que ce ne soit pas vu comme une constante
154
+    $boucle->where[] = [$debut_doub . $fin_doub . ", '" . $not . "')"];
155
+
156
+    // déclarer le doublon s'il n'existe pas encore
157
+    $boucle->hash .= $init_comment . $init_code;
158
+
159
+
160
+    # la ligne suivante avait l'intention d'eviter une collecte deja faite
161
+    # mais elle fait planter une boucle a 2 critere doublons:
162
+    # {!doublons A}{doublons B}
163
+    # (de http://article.gmane.org/gmane.comp.web.spip.devel/31034)
164
+    #	if ($crit->not) $boucle->doublons = "";
165 165
 }
166 166
 
167 167
 
@@ -182,14 +182,14 @@  discard block
 block discarded – undo
182 182
  * @return void
183 183
  **/
184 184
 function critere_lang_select_dist($idb, &$boucles, $crit) {
185
-	if (!isset($crit->param[1][0]) or !($param = $crit->param[1][0]->texte)) {
186
-		$param = 'oui';
187
-	}
188
-	if ($crit->not) {
189
-		$param = ($param == 'oui') ? 'non' : 'oui';
190
-	}
191
-	$boucle = &$boucles[$idb];
192
-	$boucle->lang_select = $param;
185
+    if (!isset($crit->param[1][0]) or !($param = $crit->param[1][0]->texte)) {
186
+        $param = 'oui';
187
+    }
188
+    if ($crit->not) {
189
+        $param = ($param == 'oui') ? 'non' : 'oui';
190
+    }
191
+    $boucle = &$boucles[$idb];
192
+    $boucle->lang_select = $param;
193 193
 }
194 194
 
195 195
 
@@ -211,18 +211,18 @@  discard block
 block discarded – undo
211 211
  * @return void
212 212
  **/
213 213
 function critere_debut_dist($idb, &$boucles, $crit) {
214
-	list($un, $deux) = $crit->param;
215
-	$un = $un[0]->texte;
216
-	$deux = $deux[0]->texte;
217
-	if ($deux) {
218
-		$boucles[$idb]->limit = 'intval($Pile[0]["debut' .
219
-			$un .
220
-			'"]) . ",' .
221
-			$deux .
222
-			'"';
223
-	} else {
224
-		calculer_critere_DEFAUT_dist($idb, $boucles, $crit);
225
-	}
214
+    list($un, $deux) = $crit->param;
215
+    $un = $un[0]->texte;
216
+    $deux = $deux[0]->texte;
217
+    if ($deux) {
218
+        $boucles[$idb]->limit = 'intval($Pile[0]["debut' .
219
+            $un .
220
+            '"]) . ",' .
221
+            $deux .
222
+            '"';
223
+    } else {
224
+        calculer_critere_DEFAUT_dist($idb, $boucles, $crit);
225
+    }
226 226
 }
227 227
 
228 228
 
@@ -256,58 +256,58 @@  discard block
 block discarded – undo
256 256
  **/
257 257
 function critere_pagination_dist($idb, &$boucles, $crit) {
258 258
 
259
-	$boucle = &$boucles[$idb];
260
-	// definition de la taille de la page
261
-	$pas = !isset($crit->param[0][0]) ? "''"
262
-		: calculer_liste([$crit->param[0][0]], $idb, $boucles, $boucle->id_parent);
263
-
264
-	if (!preg_match(_CODE_QUOTE, $pas, $r)) {
265
-		$pas = "((\$a = intval($pas)) ? \$a : 10)";
266
-	} else {
267
-		$r = intval($r[2]);
268
-		$pas = strval($r ? $r : 10);
269
-	}
270
-
271
-	// Calcul du nommage de la pagination si il existe.
272
-	// La nouvelle syntaxe {pagination 20, nom} est prise en compte et privilégiée mais on reste
273
-	// compatible avec l'ancienne car certains cas fonctionnent correctement
274
-	$type = "'$idb'";
275
-	// Calcul d'un nommage spécifique de la pagination si précisé.
276
-	// Syntaxe {pagination 20, nom}
277
-	if (isset($crit->param[0][1])) {
278
-		$type = calculer_liste([$crit->param[0][1]], $idb, $boucles, $boucle->id_parent);
279
-	} // Ancienne syntaxe {pagination 20 nom} pour compatibilité
280
-	elseif (isset($crit->param[1][0])) {
281
-		$type = calculer_liste([$crit->param[1][0]], $idb, $boucles, $boucle->id_parent);
282
-	}
283
-
284
-	$debut = ($type[0] !== "'") ? "'debut'.$type" : ("'debut" . substr($type, 1));
285
-	$boucle->modificateur['debut_nom'] = $type;
286
-	$partie =
287
-		// tester si le numero de page demande est de la forme '@yyy'
288
-		'isset($Pile[0][' . $debut . ']) ? $Pile[0][' . $debut . '] : _request(' . $debut . ");\n"
289
-		. "\tif(substr(\$debut_boucle,0,1)=='@'){\n"
290
-		. "\t\t" . '$debut_boucle = $Pile[0][' . $debut . '] = quete_debut_pagination(\'' . $boucle->primary . '\',$Pile[0][\'@' . $boucle->primary . '\'] = substr($debut_boucle,1),' . $pas . ',$iter);' . "\n"
291
-		. "\t\t" . '$iter->seek(0);' . "\n"
292
-		. "\t}\n"
293
-		. "\t" . '$debut_boucle = intval($debut_boucle)';
294
-
295
-	$boucle->hash .= '
259
+    $boucle = &$boucles[$idb];
260
+    // definition de la taille de la page
261
+    $pas = !isset($crit->param[0][0]) ? "''"
262
+        : calculer_liste([$crit->param[0][0]], $idb, $boucles, $boucle->id_parent);
263
+
264
+    if (!preg_match(_CODE_QUOTE, $pas, $r)) {
265
+        $pas = "((\$a = intval($pas)) ? \$a : 10)";
266
+    } else {
267
+        $r = intval($r[2]);
268
+        $pas = strval($r ? $r : 10);
269
+    }
270
+
271
+    // Calcul du nommage de la pagination si il existe.
272
+    // La nouvelle syntaxe {pagination 20, nom} est prise en compte et privilégiée mais on reste
273
+    // compatible avec l'ancienne car certains cas fonctionnent correctement
274
+    $type = "'$idb'";
275
+    // Calcul d'un nommage spécifique de la pagination si précisé.
276
+    // Syntaxe {pagination 20, nom}
277
+    if (isset($crit->param[0][1])) {
278
+        $type = calculer_liste([$crit->param[0][1]], $idb, $boucles, $boucle->id_parent);
279
+    } // Ancienne syntaxe {pagination 20 nom} pour compatibilité
280
+    elseif (isset($crit->param[1][0])) {
281
+        $type = calculer_liste([$crit->param[1][0]], $idb, $boucles, $boucle->id_parent);
282
+    }
283
+
284
+    $debut = ($type[0] !== "'") ? "'debut'.$type" : ("'debut" . substr($type, 1));
285
+    $boucle->modificateur['debut_nom'] = $type;
286
+    $partie =
287
+        // tester si le numero de page demande est de la forme '@yyy'
288
+        'isset($Pile[0][' . $debut . ']) ? $Pile[0][' . $debut . '] : _request(' . $debut . ");\n"
289
+        . "\tif(substr(\$debut_boucle,0,1)=='@'){\n"
290
+        . "\t\t" . '$debut_boucle = $Pile[0][' . $debut . '] = quete_debut_pagination(\'' . $boucle->primary . '\',$Pile[0][\'@' . $boucle->primary . '\'] = substr($debut_boucle,1),' . $pas . ',$iter);' . "\n"
291
+        . "\t\t" . '$iter->seek(0);' . "\n"
292
+        . "\t}\n"
293
+        . "\t" . '$debut_boucle = intval($debut_boucle)';
294
+
295
+    $boucle->hash .= '
296 296
 	$command[\'pagination\'] = array((isset($Pile[0][' . $debut . ']) ? $Pile[0][' . $debut . '] : null), ' . $pas . ');';
297 297
 
298
-	$boucle->total_parties = $pas;
299
-	calculer_parties($boucles, $idb, $partie, 'p+');
300
-	// ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id
301
-	// sauf si pas de primaire, ou si primaire composee
302
-	// dans ce cas, on ne sait pas gerer une pagination indirecte
303
-	$t = $boucle->id_table . '.' . $boucle->primary;
304
-	if (
305
-		$boucle->primary
306
-		and !preg_match('/[,\s]/', $boucle->primary)
307
-		and !in_array($t, $boucle->select)
308
-	) {
309
-		$boucle->select[] = $t;
310
-	}
298
+    $boucle->total_parties = $pas;
299
+    calculer_parties($boucles, $idb, $partie, 'p+');
300
+    // ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id
301
+    // sauf si pas de primaire, ou si primaire composee
302
+    // dans ce cas, on ne sait pas gerer une pagination indirecte
303
+    $t = $boucle->id_table . '.' . $boucle->primary;
304
+    if (
305
+        $boucle->primary
306
+        and !preg_match('/[,\s]/', $boucle->primary)
307
+        and !in_array($t, $boucle->select)
308
+    ) {
309
+        $boucle->select[] = $t;
310
+    }
311 311
 }
312 312
 
313 313
 
@@ -329,24 +329,24 @@  discard block
 block discarded – undo
329 329
  **/
330 330
 function critere_recherche_dist($idb, &$boucles, $crit) {
331 331
 
332
-	$boucle = &$boucles[$idb];
332
+    $boucle = &$boucles[$idb];
333 333
 
334
-	if (!$boucle->primary or strpos($boucle->primary, ',')) {
335
-		erreur_squelette(_T('zbug_critere_sur_table_sans_cle_primaire', ['critere' => 'recherche']), $boucle);
334
+    if (!$boucle->primary or strpos($boucle->primary, ',')) {
335
+        erreur_squelette(_T('zbug_critere_sur_table_sans_cle_primaire', ['critere' => 'recherche']), $boucle);
336 336
 
337
-		return;
338
-	}
337
+        return;
338
+    }
339 339
 
340
-	if (isset($crit->param[0])) {
341
-		$quoi = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
342
-	} else {
343
-		$quoi = '(isset($Pile[0]["recherche"])?$Pile[0]["recherche"]:(isset($GLOBALS["recherche"])?$GLOBALS["recherche"]:""))';
344
-	}
340
+    if (isset($crit->param[0])) {
341
+        $quoi = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
342
+    } else {
343
+        $quoi = '(isset($Pile[0]["recherche"])?$Pile[0]["recherche"]:(isset($GLOBALS["recherche"])?$GLOBALS["recherche"]:""))';
344
+    }
345 345
 
346
-	$_modificateur = var_export($boucle->modificateur, true);
347
-	$boucle->hash .= '
346
+    $_modificateur = var_export($boucle->modificateur, true);
347
+    $boucle->hash .= '
348 348
 	// RECHERCHE'
349
-		. ($crit->cond ? '
349
+        . ($crit->cond ? '
350 350
 	if (!strlen(' . $quoi . ')){
351 351
 		list($rech_select, $rech_where) = array("0 as points","");
352 352
 	} else' : '') . '
@@ -357,21 +357,21 @@  discard block
 block discarded – undo
357 357
 	';
358 358
 
359 359
 
360
-	$t = $boucle->id_table . '.' . $boucle->primary;
361
-	if (!in_array($t, $boucles[$idb]->select)) {
362
-		$boucle->select[] = $t;
363
-	} # pour postgres, neuneu ici
364
-	// jointure uniquement sur le serveur principal
365
-	// (on ne peut joindre une table d'un serveur distant avec la table des resultats du serveur principal)
366
-	if (!$boucle->sql_serveur) {
367
-		$boucle->join['resultats'] = ["'" . $boucle->id_table . "'", "'id'", "'" . $boucle->primary . "'"];
368
-		$boucle->from['resultats'] = 'spip_resultats';
369
-	}
370
-	$boucle->select[] = '$rech_select';
371
-	//$boucle->where[]= "\$rech_where?'resultats.id=".$boucle->id_table.".".$boucle->primary."':''";
372
-
373
-	// et la recherche trouve
374
-	$boucle->where[] = '$rech_where?$rech_where:\'\'';
360
+    $t = $boucle->id_table . '.' . $boucle->primary;
361
+    if (!in_array($t, $boucles[$idb]->select)) {
362
+        $boucle->select[] = $t;
363
+    } # pour postgres, neuneu ici
364
+    // jointure uniquement sur le serveur principal
365
+    // (on ne peut joindre une table d'un serveur distant avec la table des resultats du serveur principal)
366
+    if (!$boucle->sql_serveur) {
367
+        $boucle->join['resultats'] = ["'" . $boucle->id_table . "'", "'id'", "'" . $boucle->primary . "'"];
368
+        $boucle->from['resultats'] = 'spip_resultats';
369
+    }
370
+    $boucle->select[] = '$rech_select';
371
+    //$boucle->where[]= "\$rech_where?'resultats.id=".$boucle->id_table.".".$boucle->primary."':''";
372
+
373
+    // et la recherche trouve
374
+    $boucle->where[] = '$rech_where?$rech_where:\'\'';
375 375
 }
376 376
 
377 377
 /**
@@ -388,25 +388,25 @@  discard block
 block discarded – undo
388 388
  * @return void
389 389
  **/
390 390
 function critere_traduction_dist($idb, &$boucles, $crit) {
391
-	$boucle = &$boucles[$idb];
392
-	$prim = $boucle->primary;
393
-	$table = $boucle->id_table;
394
-	$arg = kwote(calculer_argument_precedent($idb, 'id_trad', $boucles));
395
-	$dprim = kwote(calculer_argument_precedent($idb, $prim, $boucles));
396
-	$boucle->where[] =
397
-		[
398
-			"'OR'",
399
-			[
400
-				"'AND'",
401
-				["'='", "'$table.id_trad'", 0],
402
-				["'='", "'$table.$prim'", $dprim]
403
-			],
404
-			[
405
-				"'AND'",
406
-				["'>'", "'$table.id_trad'", 0],
407
-				["'='", "'$table.id_trad'", $arg]
408
-			]
409
-		];
391
+    $boucle = &$boucles[$idb];
392
+    $prim = $boucle->primary;
393
+    $table = $boucle->id_table;
394
+    $arg = kwote(calculer_argument_precedent($idb, 'id_trad', $boucles));
395
+    $dprim = kwote(calculer_argument_precedent($idb, $prim, $boucles));
396
+    $boucle->where[] =
397
+        [
398
+            "'OR'",
399
+            [
400
+                "'AND'",
401
+                ["'='", "'$table.id_trad'", 0],
402
+                ["'='", "'$table.$prim'", $dprim]
403
+            ],
404
+            [
405
+                "'AND'",
406
+                ["'>'", "'$table.id_trad'", 0],
407
+                ["'='", "'$table.id_trad'", $arg]
408
+            ]
409
+        ];
410 410
 }
411 411
 
412 412
 
@@ -424,17 +424,17 @@  discard block
 block discarded – undo
424 424
  * @return void
425 425
  **/
426 426
 function critere_origine_traduction_dist($idb, &$boucles, $crit) {
427
-	$boucle = &$boucles[$idb];
428
-	$prim = $boucle->primary;
429
-	$table = $boucle->id_table;
430
-
431
-	$c =
432
-		[
433
-			"'OR'",
434
-			["'='", "'$table." . "id_trad'", "'$table.$prim'"],
435
-			["'='", "'$table.id_trad'", "'0'"]
436
-		];
437
-	$boucle->where[] = ($crit->not ? ["'NOT'", $c] : $c);
427
+    $boucle = &$boucles[$idb];
428
+    $prim = $boucle->primary;
429
+    $table = $boucle->id_table;
430
+
431
+    $c =
432
+        [
433
+            "'OR'",
434
+            ["'='", "'$table." . "id_trad'", "'$table.$prim'"],
435
+            ["'='", "'$table.id_trad'", "'0'"]
436
+        ];
437
+    $boucle->where[] = ($crit->not ? ["'NOT'", $c] : $c);
438 438
 }
439 439
 
440 440
 
@@ -451,19 +451,19 @@  discard block
 block discarded – undo
451 451
  **/
452 452
 function critere_meme_parent_dist($idb, &$boucles, $crit) {
453 453
 
454
-	$boucle = &$boucles[$idb];
455
-	$arg = kwote(calculer_argument_precedent($idb, 'id_parent', $boucles));
456
-	$id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
457
-		$GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
458
-		'id_parent';
459
-	$mparent = $boucle->id_table . '.' . $id_parent;
460
-
461
-	if ($boucle->type_requete == 'rubriques' or isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'])) {
462
-		$boucle->where[] = ["'='", "'$mparent'", $arg];
463
-	} // le cas FORUMS est gere dans le plugin forum, dans la fonction critere_FORUMS_meme_parent_dist()
464
-	else {
465
-		return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . $boucle->type_requete]]);
466
-	}
454
+    $boucle = &$boucles[$idb];
455
+    $arg = kwote(calculer_argument_precedent($idb, 'id_parent', $boucles));
456
+    $id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
457
+        $GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
458
+        'id_parent';
459
+    $mparent = $boucle->id_table . '.' . $id_parent;
460
+
461
+    if ($boucle->type_requete == 'rubriques' or isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'])) {
462
+        $boucle->where[] = ["'='", "'$mparent'", $arg];
463
+    } // le cas FORUMS est gere dans le plugin forum, dans la fonction critere_FORUMS_meme_parent_dist()
464
+    else {
465
+        return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . $boucle->type_requete]]);
466
+    }
467 467
 }
468 468
 
469 469
 
@@ -494,37 +494,37 @@  discard block
 block discarded – undo
494 494
  **/
495 495
 function critere_branche_dist($idb, &$boucles, $crit) {
496 496
 
497
-	$not = $crit->not;
498
-	$boucle = &$boucles[$idb];
499
-	// prendre en priorite un identifiant en parametre {branche XX}
500
-	if (isset($crit->param[0])) {
501
-		$arg = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
502
-		// sinon on le prend chez une boucle parente
503
-	} else {
504
-		$arg = kwote(calculer_argument_precedent($idb, 'id_rubrique', $boucles), $boucle->sql_serveur, 'int NOT NULL');
505
-	}
506
-
507
-	//Trouver une jointure
508
-	$champ = 'id_rubrique';
509
-	$desc = $boucle->show;
510
-	//Seulement si necessaire
511
-	if (!array_key_exists($champ, $desc['field'])) {
512
-		$cle = trouver_jointure_champ($champ, $boucle);
513
-		$trouver_table = charger_fonction('trouver_table', 'base');
514
-		$desc = $trouver_table($boucle->from[$cle]);
515
-		if (count(trouver_champs_decomposes($champ, $desc)) > 1) {
516
-			$decompose = decompose_champ_id_objet($champ);
517
-			$champ = array_shift($decompose);
518
-			$boucle->where[] = ["'='", _q($cle . '.' . reset($decompose)), '"' . sql_quote(end($decompose)) . '"'];
519
-		}
520
-	} else {
521
-		$cle = $boucle->id_table;
522
-	}
523
-
524
-	$c = "sql_in('$cle" . ".$champ', calcul_branche_in($arg)"
525
-		. ($not ? ", 'NOT'" : '') . ')';
526
-	$boucle->where[] = !$crit->cond ? $c :
527
-		("($arg ? $c : " . ($not ? "'0=1'" : "'1=1'") . ')');
497
+    $not = $crit->not;
498
+    $boucle = &$boucles[$idb];
499
+    // prendre en priorite un identifiant en parametre {branche XX}
500
+    if (isset($crit->param[0])) {
501
+        $arg = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
502
+        // sinon on le prend chez une boucle parente
503
+    } else {
504
+        $arg = kwote(calculer_argument_precedent($idb, 'id_rubrique', $boucles), $boucle->sql_serveur, 'int NOT NULL');
505
+    }
506
+
507
+    //Trouver une jointure
508
+    $champ = 'id_rubrique';
509
+    $desc = $boucle->show;
510
+    //Seulement si necessaire
511
+    if (!array_key_exists($champ, $desc['field'])) {
512
+        $cle = trouver_jointure_champ($champ, $boucle);
513
+        $trouver_table = charger_fonction('trouver_table', 'base');
514
+        $desc = $trouver_table($boucle->from[$cle]);
515
+        if (count(trouver_champs_decomposes($champ, $desc)) > 1) {
516
+            $decompose = decompose_champ_id_objet($champ);
517
+            $champ = array_shift($decompose);
518
+            $boucle->where[] = ["'='", _q($cle . '.' . reset($decompose)), '"' . sql_quote(end($decompose)) . '"'];
519
+        }
520
+    } else {
521
+        $cle = $boucle->id_table;
522
+    }
523
+
524
+    $c = "sql_in('$cle" . ".$champ', calcul_branche_in($arg)"
525
+        . ($not ? ", 'NOT'" : '') . ')';
526
+    $boucle->where[] = !$crit->cond ? $c :
527
+        ("($arg ? $c : " . ($not ? "'0=1'" : "'1=1'") . ')');
528 528
 }
529 529
 
530 530
 /**
@@ -540,15 +540,15 @@  discard block
 block discarded – undo
540 540
  **/
541 541
 function critere_logo_dist($idb, &$boucles, $crit) {
542 542
 
543
-	$boucle = &$boucles[$idb];
544
-	$not = ($crit->not ? 'NOT' : '');
545
-	$serveur = $boucle->sql_serveur;
543
+    $boucle = &$boucles[$idb];
544
+    $not = ($crit->not ? 'NOT' : '');
545
+    $serveur = $boucle->sql_serveur;
546 546
 
547
-	$c = "sql_in('" .
548
-		$boucle->id_table . '.' . $boucle->primary
549
-		. "', lister_objets_avec_logos('" . $boucle->primary . "'), '$not', '$serveur')";
547
+    $c = "sql_in('" .
548
+        $boucle->id_table . '.' . $boucle->primary
549
+        . "', lister_objets_avec_logos('" . $boucle->primary . "'), '$not', '$serveur')";
550 550
 
551
-	$boucle->where[] = $c;
551
+    $boucle->where[] = $c;
552 552
 }
553 553
 
554 554
 
@@ -570,31 +570,31 @@  discard block
 block discarded – undo
570 570
  * @return void
571 571
  **/
572 572
 function critere_fusion_dist($idb, &$boucles, $crit) {
573
-	if ($t = isset($crit->param[0])) {
574
-		$t = $crit->param[0];
575
-		if ($t[0]->type == 'texte') {
576
-			$t = $t[0]->texte;
577
-			if (preg_match('/^(.*)\.(.*)$/', $t, $r)) {
578
-				$t = table_objet_sql($r[1]);
579
-				$t = array_search($t, $boucles[$idb]->from);
580
-				if ($t) {
581
-					$t .= '.' . $r[2];
582
-				}
583
-			}
584
-		} else {
585
-			$t = '".'
586
-				. calculer_critere_arg_dynamique($idb, $boucles, $t)
587
-				. '."';
588
-		}
589
-	}
590
-	if ($t) {
591
-		$boucles[$idb]->group[] = $t;
592
-		if (!in_array($t, $boucles[$idb]->select)) {
593
-			$boucles[$idb]->select[] = $t;
594
-		}
595
-	} else {
596
-		return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']]);
597
-	}
573
+    if ($t = isset($crit->param[0])) {
574
+        $t = $crit->param[0];
575
+        if ($t[0]->type == 'texte') {
576
+            $t = $t[0]->texte;
577
+            if (preg_match('/^(.*)\.(.*)$/', $t, $r)) {
578
+                $t = table_objet_sql($r[1]);
579
+                $t = array_search($t, $boucles[$idb]->from);
580
+                if ($t) {
581
+                    $t .= '.' . $r[2];
582
+                }
583
+            }
584
+        } else {
585
+            $t = '".'
586
+                . calculer_critere_arg_dynamique($idb, $boucles, $t)
587
+                . '."';
588
+        }
589
+    }
590
+    if ($t) {
591
+        $boucles[$idb]->group[] = $t;
592
+        if (!in_array($t, $boucles[$idb]->select)) {
593
+            $boucles[$idb]->select[] = $t;
594
+        }
595
+    } else {
596
+        return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']]);
597
+    }
598 598
 }
599 599
 
600 600
 /**
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
  * @return void
615 615
  **/
616 616
 function critere_fusion_supprimer_dist($idb, &$boucles, $crit) {
617
-	$boucles[$idb]->group = [];
617
+    $boucles[$idb]->group = [];
618 618
 }
619 619
 
620 620
 /**
@@ -651,45 +651,45 @@  discard block
 block discarded – undo
651 651
  * @param Critere $crit Paramètres du critère dans cette boucle
652 652
  */
653 653
 function critere_collecte_dist($idb, &$boucles, $crit) {
654
-	if (isset($crit->param[0])) {
655
-		$_coll = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
656
-		$boucle = $boucles[$idb];
657
-		$boucle->modificateur['collate'] = "($_coll ?' COLLATE '.$_coll:'')";
658
-		$n = count($boucle->order);
659
-		if ($n && (strpos($boucle->order[$n - 1], 'COLLATE') === false)) {
660
-			// l'instruction COLLATE doit être placée avant ASC ou DESC
661
-			// notamment lors de l'utilisation `{!par xxx}{collate yyy}`
662
-			if (
663
-				(false !== $i = strpos($boucle->order[$n - 1], 'ASC'))
664
-				or (false !== $i = strpos($boucle->order[$n - 1], 'DESC'))
665
-			) {
666
-				$boucle->order[$n - 1] = substr_replace($boucle->order[$n - 1], "' . " . $boucle->modificateur['collate'] . " . ' ", $i, 0);
667
-			} else {
668
-				$boucle->order[$n - 1] .= ' . ' . $boucle->modificateur['collate'];
669
-			}
670
-		}
671
-	} else {
672
-		return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . count($boucles[$idb]->order)]]);
673
-	}
654
+    if (isset($crit->param[0])) {
655
+        $_coll = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
656
+        $boucle = $boucles[$idb];
657
+        $boucle->modificateur['collate'] = "($_coll ?' COLLATE '.$_coll:'')";
658
+        $n = count($boucle->order);
659
+        if ($n && (strpos($boucle->order[$n - 1], 'COLLATE') === false)) {
660
+            // l'instruction COLLATE doit être placée avant ASC ou DESC
661
+            // notamment lors de l'utilisation `{!par xxx}{collate yyy}`
662
+            if (
663
+                (false !== $i = strpos($boucle->order[$n - 1], 'ASC'))
664
+                or (false !== $i = strpos($boucle->order[$n - 1], 'DESC'))
665
+            ) {
666
+                $boucle->order[$n - 1] = substr_replace($boucle->order[$n - 1], "' . " . $boucle->modificateur['collate'] . " . ' ", $i, 0);
667
+            } else {
668
+                $boucle->order[$n - 1] .= ' . ' . $boucle->modificateur['collate'];
669
+            }
670
+        }
671
+    } else {
672
+        return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . count($boucles[$idb]->order)]]);
673
+    }
674 674
 }
675 675
 
676 676
 // https://code.spip.net/@calculer_critere_arg_dynamique
677 677
 function calculer_critere_arg_dynamique($idb, &$boucles, $crit, $suffix = '') {
678
-	$boucle = $boucles[$idb];
679
-	$alt = "('" . $boucle->id_table . '.\' . $x' . $suffix . ')';
680
-	$var = '$champs_' . $idb;
681
-	$desc = (strpos($boucle->in, "static $var =") !== false);
682
-	if (!$desc) {
683
-		$desc = $boucle->show['field'];
684
-		$desc = implode(',', array_map('_q', array_keys($desc)));
685
-		$boucles[$idb]->in .= "\n\tstatic $var = array(" . $desc . ');';
686
-	}
687
-	if ($desc) {
688
-		$alt = "(in_array(\$x, $var)  ? $alt :(\$x$suffix))";
689
-	}
690
-	$arg = calculer_liste($crit, $idb, $boucles, $boucle->id_parent);
691
-
692
-	return "((\$x = preg_replace(\"/\\W/\",'', $arg)) ? $alt : '')";
678
+    $boucle = $boucles[$idb];
679
+    $alt = "('" . $boucle->id_table . '.\' . $x' . $suffix . ')';
680
+    $var = '$champs_' . $idb;
681
+    $desc = (strpos($boucle->in, "static $var =") !== false);
682
+    if (!$desc) {
683
+        $desc = $boucle->show['field'];
684
+        $desc = implode(',', array_map('_q', array_keys($desc)));
685
+        $boucles[$idb]->in .= "\n\tstatic $var = array(" . $desc . ');';
686
+    }
687
+    if ($desc) {
688
+        $alt = "(in_array(\$x, $var)  ? $alt :(\$x$suffix))";
689
+    }
690
+    $arg = calculer_liste($crit, $idb, $boucles, $boucle->id_parent);
691
+
692
+    return "((\$x = preg_replace(\"/\\W/\",'', $arg)) ? $alt : '')";
693 693
 }
694 694
 
695 695
 /**
@@ -728,7 +728,7 @@  discard block
 block discarded – undo
728 728
  * @param Critere $crit Paramètres du critère dans cette boucle
729 729
  */
730 730
 function critere_par_dist($idb, &$boucles, $crit) {
731
-	return critere_parinverse($idb, $boucles, $crit);
731
+    return critere_parinverse($idb, $boucles, $crit);
732 732
 }
733 733
 
734 734
 /**
@@ -750,93 +750,93 @@  discard block
 block discarded – undo
750 750
  * @param Critere $crit Paramètres du critère dans cette boucle
751 751
  */
752 752
 function critere_parinverse($idb, &$boucles, $crit) {
753
-	$boucle = &$boucles[$idb];
754
-
755
-	$sens = $collecte = '';
756
-	if ($crit->not) {
757
-		$sens = " . ' DESC'";
758
-	}
759
-	if (isset($boucle->modificateur['collate'])) {
760
-		$collecte = ' . ' . $boucle->modificateur['collate'];
761
-	}
762
-
763
-	// Pour chaque paramètre du critère
764
-	foreach ($crit->param as $tri) {
765
-		$order = $fct = '';
766
-		// tris specifiés dynamiquement {par #ENV{tri}}
767
-		if ($tri[0]->type != 'texte') {
768
-			// calculer le order dynamique qui verifie les champs
769
-			$order = calculer_critere_arg_dynamique($idb, $boucles, $tri, $sens);
770
-			// ajouter 'hasard' comme possibilité de tri dynamique
771
-			calculer_critere_par_hasard($idb, $boucles, $crit);
772
-		}
773
-		// tris textuels {par titre}
774
-		else {
775
-			$par = array_shift($tri);
776
-			$par = $par->texte;
777
-
778
-			// tris de la forme {par expression champ} tel que {par num titre} ou {par multi titre}
779
-			if (preg_match(',^(\w+)[\s]+(.*)$,', $par, $m)) {
780
-				$expression = trim($m[1]);
781
-				$champ = trim($m[2]);
782
-				if (function_exists($f = 'calculer_critere_par_expression_' . $expression)) {
783
-					$order = $f($idb, $boucles, $crit, $tri, $champ);
784
-				} else {
785
-					return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
786
-				}
787
-
788
-			// tris de la forme {par champ} ou {par FONCTION(champ)}
789
-			} elseif (preg_match(',^' . CHAMP_SQL_PLUS_FONC . '$,is', $par, $match)) {
790
-				// {par FONCTION(champ)}
791
-				if (count($match) > 2) {
792
-					$par = substr($match[2], 1, -1);
793
-					$fct = $match[1];
794
-				}
795
-				// quelques cas spécifiques {par hasard}, {par date}
796
-				if ($par == 'hasard') {
797
-					$order = calculer_critere_par_hasard($idb, $boucles, $crit);
798
-				} elseif ($par == 'date' and !empty($boucle->show['date'])) {
799
-					$order = "'" . $boucle->id_table . '.' . $boucle->show['date'] . "'";
800
-				} else {
801
-					// cas général {par champ}, {par table.champ}, ...
802
-					$order = calculer_critere_par_champ($idb, $boucles, $crit, $par);
803
-				}
804
-			}
805
-
806
-			// on ne sait pas traiter…
807
-			else {
808
-				return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
809
-			}
810
-
811
-			// En cas d'erreur de squelette retournée par une fonction
812
-			if (is_array($order)) {
813
-				return $order;
814
-			}
815
-		}
816
-
817
-		if (preg_match('/^\'([^"]*)\'$/', $order, $m)) {
818
-			$t = $m[1];
819
-			if (strpos($t, '.') and !in_array($t, $boucle->select)) {
820
-				$boucle->select[] = $t;
821
-			}
822
-		} else {
823
-			$sens = '';
824
-		}
825
-
826
-		if ($fct) {
827
-			if (preg_match("/^\s*'(.*)'\s*$/", $order, $r)) {
828
-				$order = "'$fct(" . $r[1] . ")'";
829
-			} else {
830
-				$order = "'$fct(' . $order . ')'";
831
-			}
832
-		}
833
-		$t = $order . $collecte . $sens;
834
-		if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) {
835
-			$t = $r[1] . $r[2];
836
-		}
837
-
838
-		$boucle->order[] = $t;
839
-	}
753
+    $boucle = &$boucles[$idb];
754
+
755
+    $sens = $collecte = '';
756
+    if ($crit->not) {
757
+        $sens = " . ' DESC'";
758
+    }
759
+    if (isset($boucle->modificateur['collate'])) {
760
+        $collecte = ' . ' . $boucle->modificateur['collate'];
761
+    }
762
+
763
+    // Pour chaque paramètre du critère
764
+    foreach ($crit->param as $tri) {
765
+        $order = $fct = '';
766
+        // tris specifiés dynamiquement {par #ENV{tri}}
767
+        if ($tri[0]->type != 'texte') {
768
+            // calculer le order dynamique qui verifie les champs
769
+            $order = calculer_critere_arg_dynamique($idb, $boucles, $tri, $sens);
770
+            // ajouter 'hasard' comme possibilité de tri dynamique
771
+            calculer_critere_par_hasard($idb, $boucles, $crit);
772
+        }
773
+        // tris textuels {par titre}
774
+        else {
775
+            $par = array_shift($tri);
776
+            $par = $par->texte;
777
+
778
+            // tris de la forme {par expression champ} tel que {par num titre} ou {par multi titre}
779
+            if (preg_match(',^(\w+)[\s]+(.*)$,', $par, $m)) {
780
+                $expression = trim($m[1]);
781
+                $champ = trim($m[2]);
782
+                if (function_exists($f = 'calculer_critere_par_expression_' . $expression)) {
783
+                    $order = $f($idb, $boucles, $crit, $tri, $champ);
784
+                } else {
785
+                    return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
786
+                }
787
+
788
+            // tris de la forme {par champ} ou {par FONCTION(champ)}
789
+            } elseif (preg_match(',^' . CHAMP_SQL_PLUS_FONC . '$,is', $par, $match)) {
790
+                // {par FONCTION(champ)}
791
+                if (count($match) > 2) {
792
+                    $par = substr($match[2], 1, -1);
793
+                    $fct = $match[1];
794
+                }
795
+                // quelques cas spécifiques {par hasard}, {par date}
796
+                if ($par == 'hasard') {
797
+                    $order = calculer_critere_par_hasard($idb, $boucles, $crit);
798
+                } elseif ($par == 'date' and !empty($boucle->show['date'])) {
799
+                    $order = "'" . $boucle->id_table . '.' . $boucle->show['date'] . "'";
800
+                } else {
801
+                    // cas général {par champ}, {par table.champ}, ...
802
+                    $order = calculer_critere_par_champ($idb, $boucles, $crit, $par);
803
+                }
804
+            }
805
+
806
+            // on ne sait pas traiter…
807
+            else {
808
+                return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
809
+            }
810
+
811
+            // En cas d'erreur de squelette retournée par une fonction
812
+            if (is_array($order)) {
813
+                return $order;
814
+            }
815
+        }
816
+
817
+        if (preg_match('/^\'([^"]*)\'$/', $order, $m)) {
818
+            $t = $m[1];
819
+            if (strpos($t, '.') and !in_array($t, $boucle->select)) {
820
+                $boucle->select[] = $t;
821
+            }
822
+        } else {
823
+            $sens = '';
824
+        }
825
+
826
+        if ($fct) {
827
+            if (preg_match("/^\s*'(.*)'\s*$/", $order, $r)) {
828
+                $order = "'$fct(" . $r[1] . ")'";
829
+            } else {
830
+                $order = "'$fct(' . $order . ')'";
831
+            }
832
+        }
833
+        $t = $order . $collecte . $sens;
834
+        if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) {
835
+            $t = $r[1] . $r[2];
836
+        }
837
+
838
+        $boucle->order[] = $t;
839
+    }
840 840
 }
841 841
 
842 842
 /**
@@ -850,13 +850,13 @@  discard block
 block discarded – undo
850 850
  * @return string Clause pour le Order by
851 851
  */
852 852
 function calculer_critere_par_hasard($idb, &$boucles, $crit) {
853
-	$boucle = &$boucles[$idb];
854
-	// Si ce n'est fait, ajouter un champ 'hasard' dans le select
855
-	$parha = 'rand() AS hasard';
856
-	if (!in_array($parha, $boucle->select)) {
857
-		$boucle->select[] = $parha;
858
-	}
859
-	return "'hasard'";
853
+    $boucle = &$boucles[$idb];
854
+    // Si ce n'est fait, ajouter un champ 'hasard' dans le select
855
+    $parha = 'rand() AS hasard';
856
+    if (!in_array($parha, $boucle->select)) {
857
+        $boucle->select[] = $parha;
858
+    }
859
+    return "'hasard'";
860 860
 }
861 861
 
862 862
 /**
@@ -880,24 +880,24 @@  discard block
 block discarded – undo
880 880
  * @return string Clause pour le Order by
881 881
  */
882 882
 function calculer_critere_par_expression_num($idb, &$boucles, $crit, $tri, $champ) {
883
-	$_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
884
-	if (is_array($_champ)) {
885
-		return ['zbug_critere_inconnu', ['critere' => $crit->op . " num $champ"]];
886
-	}
887
-	$boucle = &$boucles[$idb];
888
-	$texte = '0+' . $_champ;
889
-	$suite = calculer_liste($tri, $idb, $boucles, $boucle->id_parent);
890
-	if ($suite !== "''") {
891
-		$texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')" . ' . "';
892
-	}
893
-	$asnum = 'num' . ($boucle->order ? count($boucle->order) : '');
894
-	$boucle->select[] = $texte . " AS $asnum";
895
-
896
-	$orderassinum = calculer_critere_par_expression_sinum($idb, $boucles, $crit, $tri, $champ);
897
-	$orderassinum = trim($orderassinum, "'");
898
-
899
-	$order = "'$orderassinum, $asnum'";
900
-	return $order;
883
+    $_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
884
+    if (is_array($_champ)) {
885
+        return ['zbug_critere_inconnu', ['critere' => $crit->op . " num $champ"]];
886
+    }
887
+    $boucle = &$boucles[$idb];
888
+    $texte = '0+' . $_champ;
889
+    $suite = calculer_liste($tri, $idb, $boucles, $boucle->id_parent);
890
+    if ($suite !== "''") {
891
+        $texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')" . ' . "';
892
+    }
893
+    $asnum = 'num' . ($boucle->order ? count($boucle->order) : '');
894
+    $boucle->select[] = $texte . " AS $asnum";
895
+
896
+    $orderassinum = calculer_critere_par_expression_sinum($idb, $boucles, $crit, $tri, $champ);
897
+    $orderassinum = trim($orderassinum, "'");
898
+
899
+    $order = "'$orderassinum, $asnum'";
900
+    return $order;
901 901
 }
902 902
 
903 903
 /**
@@ -918,35 +918,35 @@  discard block
 block discarded – undo
918 918
  * @return string Clause pour le Order by
919 919
  */
920 920
 function calculer_critere_par_expression_sinum($idb, &$boucles, $crit, $tri, $champ) {
921
-	$_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
922
-	if (is_array($_champ)) {
923
-		return ['zbug_critere_inconnu', ['critere' => $crit->op . " sinum $champ"]];
924
-	}
925
-	$boucle = &$boucles[$idb];
926
-	$texte = '0+' . $_champ;
927
-	$suite = calculer_liste($tri, $idb, $boucles, $boucle->id_parent);
928
-	if ($suite !== "''") {
929
-		$texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')" . ' . "';
930
-	}
931
-
932
-	$as = false;
933
-	$select = "CASE ( $texte ) WHEN 0 THEN 1 ELSE 0 END AS ";
934
-	foreach ($boucle->select as $s) {
935
-		if (strpos($s, $select) === 0) {
936
-			$as = trim(substr($s, strlen($select)));
937
-			if (!preg_match(',\W,', $as)) {
938
-				break;
939
-			}
940
-			$as = false;
941
-		}
942
-	}
943
-
944
-	if (!$as) {
945
-		$as = 'sinum' . ($boucle->order ? count($boucle->order) : '');
946
-		$boucle->select[] = $select . $as;
947
-	}
948
-	$order = "'$as'";
949
-	return $order;
921
+    $_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
922
+    if (is_array($_champ)) {
923
+        return ['zbug_critere_inconnu', ['critere' => $crit->op . " sinum $champ"]];
924
+    }
925
+    $boucle = &$boucles[$idb];
926
+    $texte = '0+' . $_champ;
927
+    $suite = calculer_liste($tri, $idb, $boucles, $boucle->id_parent);
928
+    if ($suite !== "''") {
929
+        $texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')" . ' . "';
930
+    }
931
+
932
+    $as = false;
933
+    $select = "CASE ( $texte ) WHEN 0 THEN 1 ELSE 0 END AS ";
934
+    foreach ($boucle->select as $s) {
935
+        if (strpos($s, $select) === 0) {
936
+            $as = trim(substr($s, strlen($select)));
937
+            if (!preg_match(',\W,', $as)) {
938
+                break;
939
+            }
940
+            $as = false;
941
+        }
942
+    }
943
+
944
+    if (!$as) {
945
+        $as = 'sinum' . ($boucle->order ? count($boucle->order) : '');
946
+        $boucle->select[] = $select . $as;
947
+    }
948
+    $order = "'$as'";
949
+    return $order;
950 950
 }
951 951
 
952 952
 
@@ -966,14 +966,14 @@  discard block
 block discarded – undo
966 966
  * @return string Clause pour le Order by
967 967
  */
968 968
 function calculer_critere_par_expression_multi($idb, &$boucles, $crit, $tri, $champ) {
969
-	$_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
970
-	if (is_array($_champ)) {
971
-		return ['zbug_critere_inconnu', ['critere' => $crit->op . " multi $champ"]];
972
-	}
973
-	$boucle = &$boucles[$idb];
974
-	$boucle->select[] = "\".sql_multi('" . $_champ . "', \$GLOBALS['spip_lang']).\"";
975
-	$order = "'multi'";
976
-	return $order;
969
+    $_champ = calculer_critere_par_champ($idb, $boucles, $crit, $champ, true);
970
+    if (is_array($_champ)) {
971
+        return ['zbug_critere_inconnu', ['critere' => $crit->op . " multi $champ"]];
972
+    }
973
+    $boucle = &$boucles[$idb];
974
+    $boucle->select[] = "\".sql_multi('" . $_champ . "', \$GLOBALS['spip_lang']).\"";
975
+    $order = "'multi'";
976
+    return $order;
977 977
 }
978 978
 
979 979
 /**
@@ -992,56 +992,56 @@  discard block
 block discarded – undo
992 992
  * @return array|string
993 993
  */
994 994
 function calculer_critere_par_champ($idb, &$boucles, $crit, $par, $raw = false) {
995
-	$boucle = &$boucles[$idb];
996
-	$desc = $boucle->show;
997
-
998
-	// le champ existe dans la table, pas de souci (le plus commun)
999
-	if (isset($desc['field'][$par])) {
1000
-		$par = $boucle->id_table . '.' . $par;
1001
-	}
1002
-	// le champ est peut être une jointure
1003
-	else {
1004
-		$table = $table_alias = false; // toutes les tables de jointure possibles
1005
-		$champ = $par;
1006
-
1007
-		// le champ demandé est une exception de jointure {par titre_mot}
1008
-		if (isset($GLOBALS['exceptions_des_jointures'][$par])) {
1009
-			list($table, $champ) = $GLOBALS['exceptions_des_jointures'][$par];
1010
-		} // la table de jointure est explicitement indiquée {par truc.muche}
1011
-		elseif (preg_match('/^([^,]*)\.(.*)$/', $par, $r)) {
1012
-			list(, $table, $champ) = $r;
1013
-			$table_alias = $table; // c'est peut-être un alias de table {par L1.titre}
1014
-			$table = table_objet_sql($table);
1015
-		}
1016
-
1017
-		// Si on connait la table d'arrivée, on la demande donc explicitement
1018
-		// Sinon on cherche le champ dans les tables possibles de jointures
1019
-		// Si la table est déjà dans le from, on la réutilise.
1020
-		if ($infos = chercher_champ_dans_tables($champ, $boucle->from, $boucle->sql_serveur, $table)) {
1021
-			$par = $infos['alias'] . '.' . $champ;
1022
-		} elseif (
1023
-			$boucle->jointures_explicites
1024
-			and $alias = trouver_jointure_champ($champ, $boucle, explode(' ', $boucle->jointures_explicites), false, $table)
1025
-		) {
1026
-			$par = $alias . '.' . $champ;
1027
-		} elseif ($alias = trouver_jointure_champ($champ, $boucle, $boucle->jointures, false, $table)) {
1028
-			$par = $alias . '.' . $champ;
1029
-		// en spécifiant directement l'alias {par L2.titre} (situation hasardeuse tout de même)
1030
-		} elseif (
1031
-			$table_alias
1032
-			and isset($boucle->from[$table_alias])
1033
-			and $infos = chercher_champ_dans_tables($champ, $boucle->from, $boucle->sql_serveur, $boucle->from[$table_alias])
1034
-		) {
1035
-			$par = $infos['alias'] . '.' . $champ;
1036
-		} elseif ($table) {
1037
-			// On avait table + champ, mais on ne les a pas trouvés
1038
-			return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
1039
-		} else {
1040
-			// Sinon tant pis, ca doit etre un champ synthetise (cf points)
1041
-		}
1042
-	}
1043
-
1044
-	return $raw ? $par : "'$par'";
995
+    $boucle = &$boucles[$idb];
996
+    $desc = $boucle->show;
997
+
998
+    // le champ existe dans la table, pas de souci (le plus commun)
999
+    if (isset($desc['field'][$par])) {
1000
+        $par = $boucle->id_table . '.' . $par;
1001
+    }
1002
+    // le champ est peut être une jointure
1003
+    else {
1004
+        $table = $table_alias = false; // toutes les tables de jointure possibles
1005
+        $champ = $par;
1006
+
1007
+        // le champ demandé est une exception de jointure {par titre_mot}
1008
+        if (isset($GLOBALS['exceptions_des_jointures'][$par])) {
1009
+            list($table, $champ) = $GLOBALS['exceptions_des_jointures'][$par];
1010
+        } // la table de jointure est explicitement indiquée {par truc.muche}
1011
+        elseif (preg_match('/^([^,]*)\.(.*)$/', $par, $r)) {
1012
+            list(, $table, $champ) = $r;
1013
+            $table_alias = $table; // c'est peut-être un alias de table {par L1.titre}
1014
+            $table = table_objet_sql($table);
1015
+        }
1016
+
1017
+        // Si on connait la table d'arrivée, on la demande donc explicitement
1018
+        // Sinon on cherche le champ dans les tables possibles de jointures
1019
+        // Si la table est déjà dans le from, on la réutilise.
1020
+        if ($infos = chercher_champ_dans_tables($champ, $boucle->from, $boucle->sql_serveur, $table)) {
1021
+            $par = $infos['alias'] . '.' . $champ;
1022
+        } elseif (
1023
+            $boucle->jointures_explicites
1024
+            and $alias = trouver_jointure_champ($champ, $boucle, explode(' ', $boucle->jointures_explicites), false, $table)
1025
+        ) {
1026
+            $par = $alias . '.' . $champ;
1027
+        } elseif ($alias = trouver_jointure_champ($champ, $boucle, $boucle->jointures, false, $table)) {
1028
+            $par = $alias . '.' . $champ;
1029
+        // en spécifiant directement l'alias {par L2.titre} (situation hasardeuse tout de même)
1030
+        } elseif (
1031
+            $table_alias
1032
+            and isset($boucle->from[$table_alias])
1033
+            and $infos = chercher_champ_dans_tables($champ, $boucle->from, $boucle->sql_serveur, $boucle->from[$table_alias])
1034
+        ) {
1035
+            $par = $infos['alias'] . '.' . $champ;
1036
+        } elseif ($table) {
1037
+            // On avait table + champ, mais on ne les a pas trouvés
1038
+            return ['zbug_critere_inconnu', ['critere' => $crit->op . " $par"]];
1039
+        } else {
1040
+            // Sinon tant pis, ca doit etre un champ synthetise (cf points)
1041
+        }
1042
+    }
1043
+
1044
+    return $raw ? $par : "'$par'";
1045 1045
 }
1046 1046
 
1047 1047
 /**
@@ -1055,11 +1055,11 @@  discard block
 block discarded – undo
1055 1055
  * @return string Champ pour le compilateur si trouvé, tel que "'alias.champ'", sinon vide.
1056 1056
  */
1057 1057
 function critere_par_joint($table, $champ, &$boucle) {
1058
-	$t = array_search($table, $boucle->from);
1059
-	if (!$t) {
1060
-		$t = trouver_jointure_champ($champ, $boucle);
1061
-	}
1062
-	return !$t ? '' : ("'" . $t . '.' . $champ . "'");
1058
+    $t = array_search($table, $boucle->from);
1059
+    if (!$t) {
1060
+        $t = trouver_jointure_champ($champ, $boucle);
1061
+    }
1062
+    return !$t ? '' : ("'" . $t . '.' . $champ . "'");
1063 1063
 }
1064 1064
 
1065 1065
 /**
@@ -1084,33 +1084,33 @@  discard block
 block discarded – undo
1084 1084
  */
1085 1085
 function critere_inverse_dist($idb, &$boucles, $crit) {
1086 1086
 
1087
-	$boucle = &$boucles[$idb];
1088
-	// Classement par ordre inverse
1089
-	if ($crit->not) {
1090
-		critere_parinverse($idb, $boucles, $crit);
1091
-	} else {
1092
-		$order = "' DESC'";
1093
-		// Classement par ordre inverse fonction eventuelle de #ENV{...}
1094
-		if (isset($crit->param[0])) {
1095
-			$critere = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
1096
-			$order = "(($critere)?' DESC':'')";
1097
-		}
1098
-
1099
-		$n = count($boucle->order);
1100
-		if (!$n) {
1101
-			if (isset($boucle->default_order[0])) {
1102
-				$boucle->default_order[0] .= ' . " DESC"';
1103
-			} else {
1104
-				$boucle->default_order[] = ' DESC';
1105
-			}
1106
-		} else {
1107
-			$t = $boucle->order[$n - 1] . " . $order";
1108
-			if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) {
1109
-				$t = $r[1] . $r[2];
1110
-			}
1111
-			$boucle->order[$n - 1] = $t;
1112
-		}
1113
-	}
1087
+    $boucle = &$boucles[$idb];
1088
+    // Classement par ordre inverse
1089
+    if ($crit->not) {
1090
+        critere_parinverse($idb, $boucles, $crit);
1091
+    } else {
1092
+        $order = "' DESC'";
1093
+        // Classement par ordre inverse fonction eventuelle de #ENV{...}
1094
+        if (isset($crit->param[0])) {
1095
+            $critere = calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent);
1096
+            $order = "(($critere)?' DESC':'')";
1097
+        }
1098
+
1099
+        $n = count($boucle->order);
1100
+        if (!$n) {
1101
+            if (isset($boucle->default_order[0])) {
1102
+                $boucle->default_order[0] .= ' . " DESC"';
1103
+            } else {
1104
+                $boucle->default_order[] = ' DESC';
1105
+            }
1106
+        } else {
1107
+            $t = $boucle->order[$n - 1] . " . $order";
1108
+            if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) {
1109
+                $t = $r[1] . $r[2];
1110
+            }
1111
+            $boucle->order[$n - 1] = $t;
1112
+        }
1113
+    }
1114 1114
 }
1115 1115
 
1116 1116
 /**
@@ -1121,138 +1121,138 @@  discard block
 block discarded – undo
1121 1121
  * @return array|string
1122 1122
  */
1123 1123
 function critere_par_ordre_liste_dist($idb, &$boucles, $crit) {
1124
-	$boucle = &$boucles[$idb];
1124
+    $boucle = &$boucles[$idb];
1125 1125
 
1126
-	$sens = $collecte = '';
1127
-	if ($crit->not) {
1128
-		$sens = " . ' DESC'";
1129
-	}
1126
+    $sens = $collecte = '';
1127
+    if ($crit->not) {
1128
+        $sens = " . ' DESC'";
1129
+    }
1130 1130
 
1131
-	$crit2 = clone $crit;
1132
-	$crit2->not = false;
1133
-	$crit2->param = [reset($crit->param)];
1134
-	$res = critere_parinverse($idb, $boucles, $crit2);
1131
+    $crit2 = clone $crit;
1132
+    $crit2->not = false;
1133
+    $crit2->param = [reset($crit->param)];
1134
+    $res = critere_parinverse($idb, $boucles, $crit2);
1135 1135
 
1136
-	// erreur ?
1137
-	if (is_array($res)) {
1138
-		return $res;
1139
-	}
1136
+    // erreur ?
1137
+    if (is_array($res)) {
1138
+        return $res;
1139
+    }
1140 1140
 
1141
-	$_order = array_pop($boucle->order);
1141
+    $_order = array_pop($boucle->order);
1142 1142
 
1143
-	$_liste = calculer_liste($crit->param[1], [], $boucles, $boucles[$idb]->id_parent);
1144
-	$boucle->order[] = "'FIELD(' . $_order . ',' . ((\$zl=formate_liste_critere_par_ordre_liste($_liste,'" . $boucle->sql_serveur . "')) ? \$zl : '0').')'$sens";
1143
+    $_liste = calculer_liste($crit->param[1], [], $boucles, $boucles[$idb]->id_parent);
1144
+    $boucle->order[] = "'FIELD(' . $_order . ',' . ((\$zl=formate_liste_critere_par_ordre_liste($_liste,'" . $boucle->sql_serveur . "')) ? \$zl : '0').')'$sens";
1145 1145
 }
1146 1146
 
1147 1147
 
1148 1148
 // https://code.spip.net/@critere_agenda_dist
1149 1149
 function critere_agenda_dist($idb, &$boucles, $crit) {
1150
-	$params = $crit->param;
1151
-
1152
-	if (count($params) < 1) {
1153
-		return ['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']];
1154
-	}
1155
-
1156
-	$boucle = &$boucles[$idb];
1157
-	$parent = $boucle->id_parent;
1158
-	$fields = $boucle->show['field'];
1159
-
1160
-	$date = array_shift($params);
1161
-	$type = array_shift($params);
1162
-
1163
-	// la valeur $type doit etre connue a la compilation
1164
-	// donc etre forcement reduite a un litteral unique dans le source
1165
-	$type = is_object($type[0]) ? $type[0]->texte : null;
1166
-
1167
-	// La valeur date doit designer un champ de la table SQL.
1168
-	// Si c'est un litteral unique dans le source, verifier a la compil,
1169
-	// sinon synthetiser le test de verif pour execution ulterieure
1170
-	// On prendra arbitrairement le premier champ si test negatif.
1171
-	if ((count($date) == 1) and ($date[0]->type == 'texte')) {
1172
-		$date = $date[0]->texte;
1173
-		if (!isset($fields[$date])) {
1174
-			return ['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . $date]];
1175
-		}
1176
-	} else {
1177
-		$a = calculer_liste($date, $idb, $boucles, $parent);
1178
-		$noms = array_keys($fields);
1179
-		$defaut = $noms[0];
1180
-		$noms = join(' ', $noms);
1181
-		# bien laisser 2 espaces avant $nom pour que strpos<>0
1182
-		$cond = "(\$a=strval($a))AND\nstrpos(\"  $noms \",\" \$a \")";
1183
-		$date = "'.(($cond)\n?\$a:\"$defaut\").'";
1184
-	}
1185
-	$annee = $params ? array_shift($params) : '';
1186
-	$annee = "\n" . 'sprintf("%04d", ($x = ' .
1187
-		calculer_liste($annee, $idb, $boucles, $parent) .
1188
-		') ? $x : date("Y"))';
1189
-
1190
-	$mois = $params ? array_shift($params) : '';
1191
-	$mois = "\n" . 'sprintf("%02d", ($x = ' .
1192
-		calculer_liste($mois, $idb, $boucles, $parent) .
1193
-		') ? $x : date("m"))';
1194
-
1195
-	$jour = $params ? array_shift($params) : '';
1196
-	$jour = "\n" . 'sprintf("%02d", ($x = ' .
1197
-		calculer_liste($jour, $idb, $boucles, $parent) .
1198
-		') ? $x : date("d"))';
1199
-
1200
-	$annee2 = $params ? array_shift($params) : '';
1201
-	$annee2 = "\n" . 'sprintf("%04d", ($x = ' .
1202
-		calculer_liste($annee2, $idb, $boucles, $parent) .
1203
-		') ? $x : date("Y"))';
1204
-
1205
-	$mois2 = $params ? array_shift($params) : '';
1206
-	$mois2 = "\n" . 'sprintf("%02d", ($x = ' .
1207
-		calculer_liste($mois2, $idb, $boucles, $parent) .
1208
-		') ? $x : date("m"))';
1209
-
1210
-	$jour2 = $params ? array_shift($params) : '';
1211
-	$jour2 = "\n" . 'sprintf("%02d", ($x = ' .
1212
-		calculer_liste($jour2, $idb, $boucles, $parent) .
1213
-		') ? $x : date("d"))';
1214
-
1215
-	$date = $boucle->id_table . ".$date";
1216
-
1217
-	$quote_end = ",'" . $boucle->sql_serveur . "','text'";
1218
-	if ($type == 'jour') {
1219
-		$boucle->where[] = [
1220
-			"'='",
1221
-			"'DATE_FORMAT($date, \'%Y%m%d\')'",
1222
-			("sql_quote($annee . $mois . $jour$quote_end)")
1223
-		];
1224
-	} elseif ($type == 'mois') {
1225
-		$boucle->where[] = [
1226
-			"'='",
1227
-			"'DATE_FORMAT($date, \'%Y%m\')'",
1228
-			("sql_quote($annee . $mois$quote_end)")
1229
-		];
1230
-	} elseif ($type == 'semaine') {
1231
-		$boucle->where[] = [
1232
-			"'AND'",
1233
-			[
1234
-				"'>='",
1235
-				"'DATE_FORMAT($date, \'%Y%m%d\')'",
1236
-				("date_debut_semaine($annee, $mois, $jour)")
1237
-			],
1238
-			[
1239
-				"'<='",
1240
-				"'DATE_FORMAT($date, \'%Y%m%d\')'",
1241
-				("date_fin_semaine($annee, $mois, $jour)")
1242
-			]
1243
-		];
1244
-	} elseif (count($crit->param) > 2) {
1245
-		$boucle->where[] = [
1246
-			"'AND'",
1247
-			[
1248
-				"'>='",
1249
-				"'DATE_FORMAT($date, \'%Y%m%d\')'",
1250
-				("sql_quote($annee . $mois . $jour$quote_end)")
1251
-			],
1252
-			["'<='", "'DATE_FORMAT($date, \'%Y%m%d\')'", ("sql_quote($annee2 . $mois2 . $jour2$quote_end)")]
1253
-		];
1254
-	}
1255
-	// sinon on prend tout
1150
+    $params = $crit->param;
1151
+
1152
+    if (count($params) < 1) {
1153
+        return ['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']];
1154
+    }
1155
+
1156
+    $boucle = &$boucles[$idb];
1157
+    $parent = $boucle->id_parent;
1158
+    $fields = $boucle->show['field'];
1159
+
1160
+    $date = array_shift($params);
1161
+    $type = array_shift($params);
1162
+
1163
+    // la valeur $type doit etre connue a la compilation
1164
+    // donc etre forcement reduite a un litteral unique dans le source
1165
+    $type = is_object($type[0]) ? $type[0]->texte : null;
1166
+
1167
+    // La valeur date doit designer un champ de la table SQL.
1168
+    // Si c'est un litteral unique dans le source, verifier a la compil,
1169
+    // sinon synthetiser le test de verif pour execution ulterieure
1170
+    // On prendra arbitrairement le premier champ si test negatif.
1171
+    if ((count($date) == 1) and ($date[0]->type == 'texte')) {
1172
+        $date = $date[0]->texte;
1173
+        if (!isset($fields[$date])) {
1174
+            return ['zbug_critere_inconnu', ['critere' => $crit->op . ' ' . $date]];
1175
+        }
1176
+    } else {
1177
+        $a = calculer_liste($date, $idb, $boucles, $parent);
1178
+        $noms = array_keys($fields);
1179
+        $defaut = $noms[0];
1180
+        $noms = join(' ', $noms);
1181
+        # bien laisser 2 espaces avant $nom pour que strpos<>0
1182
+        $cond = "(\$a=strval($a))AND\nstrpos(\"  $noms \",\" \$a \")";
1183
+        $date = "'.(($cond)\n?\$a:\"$defaut\").'";
1184
+    }
1185
+    $annee = $params ? array_shift($params) : '';
1186
+    $annee = "\n" . 'sprintf("%04d", ($x = ' .
1187
+        calculer_liste($annee, $idb, $boucles, $parent) .
1188
+        ') ? $x : date("Y"))';
1189
+
1190
+    $mois = $params ? array_shift($params) : '';
1191
+    $mois = "\n" . 'sprintf("%02d", ($x = ' .
1192
+        calculer_liste($mois, $idb, $boucles, $parent) .
1193
+        ') ? $x : date("m"))';
1194
+
1195
+    $jour = $params ? array_shift($params) : '';
1196
+    $jour = "\n" . 'sprintf("%02d", ($x = ' .
1197
+        calculer_liste($jour, $idb, $boucles, $parent) .
1198
+        ') ? $x : date("d"))';
1199
+
1200
+    $annee2 = $params ? array_shift($params) : '';
1201
+    $annee2 = "\n" . 'sprintf("%04d", ($x = ' .
1202
+        calculer_liste($annee2, $idb, $boucles, $parent) .
1203
+        ') ? $x : date("Y"))';
1204
+
1205
+    $mois2 = $params ? array_shift($params) : '';
1206
+    $mois2 = "\n" . 'sprintf("%02d", ($x = ' .
1207
+        calculer_liste($mois2, $idb, $boucles, $parent) .
1208
+        ') ? $x : date("m"))';
1209
+
1210
+    $jour2 = $params ? array_shift($params) : '';
1211
+    $jour2 = "\n" . 'sprintf("%02d", ($x = ' .
1212
+        calculer_liste($jour2, $idb, $boucles, $parent) .
1213
+        ') ? $x : date("d"))';
1214
+
1215
+    $date = $boucle->id_table . ".$date";
1216
+
1217
+    $quote_end = ",'" . $boucle->sql_serveur . "','text'";
1218
+    if ($type == 'jour') {
1219
+        $boucle->where[] = [
1220
+            "'='",
1221
+            "'DATE_FORMAT($date, \'%Y%m%d\')'",
1222
+            ("sql_quote($annee . $mois . $jour$quote_end)")
1223
+        ];
1224
+    } elseif ($type == 'mois') {
1225
+        $boucle->where[] = [
1226
+            "'='",
1227
+            "'DATE_FORMAT($date, \'%Y%m\')'",
1228
+            ("sql_quote($annee . $mois$quote_end)")
1229
+        ];
1230
+    } elseif ($type == 'semaine') {
1231
+        $boucle->where[] = [
1232
+            "'AND'",
1233
+            [
1234
+                "'>='",
1235
+                "'DATE_FORMAT($date, \'%Y%m%d\')'",
1236
+                ("date_debut_semaine($annee, $mois, $jour)")
1237
+            ],
1238
+            [
1239
+                "'<='",
1240
+                "'DATE_FORMAT($date, \'%Y%m%d\')'",
1241
+                ("date_fin_semaine($annee, $mois, $jour)")
1242
+            ]
1243
+        ];
1244
+    } elseif (count($crit->param) > 2) {
1245
+        $boucle->where[] = [
1246
+            "'AND'",
1247
+            [
1248
+                "'>='",
1249
+                "'DATE_FORMAT($date, \'%Y%m%d\')'",
1250
+                ("sql_quote($annee . $mois . $jour$quote_end)")
1251
+            ],
1252
+            ["'<='", "'DATE_FORMAT($date, \'%Y%m%d\')'", ("sql_quote($annee2 . $mois2 . $jour2$quote_end)")]
1253
+        ];
1254
+    }
1255
+    // sinon on prend tout
1256 1256
 }
1257 1257
 
1258 1258
 
@@ -1277,33 +1277,33 @@  discard block
 block discarded – undo
1277 1277
  * @return void
1278 1278
  **/
1279 1279
 function calculer_critere_parties($idb, &$boucles, $crit) {
1280
-	$boucle = &$boucles[$idb];
1281
-	$a1 = $crit->param[0];
1282
-	$a2 = $crit->param[1];
1283
-	$op = $crit->op;
1284
-
1285
-	list($a11, $a12) = calculer_critere_parties_aux($idb, $boucles, $a1);
1286
-	list($a21, $a22) = calculer_critere_parties_aux($idb, $boucles, $a2);
1287
-
1288
-	if (($op == ',') && (is_numeric($a11) && (is_numeric($a21)))) {
1289
-		$boucle->limit = $a11 . ',' . $a21;
1290
-	} else {
1291
-		// 3 dans {1/3}, {2,3} ou {1,n-3}
1292
-		$boucle->total_parties = ($a21 != 'n') ? $a21 : $a22;
1293
-		// 2 dans {2/3}, {2,5}, {n-2,1}
1294
-		$partie = ($a11 != 'n') ? $a11 : $a12;
1295
-		$mode = (($op == '/') ? '/' :
1296
-			(($a11 == 'n') ? '-' : '+') . (($a21 == 'n') ? '-' : '+'));
1297
-		// cas simple {0,#ENV{truc}} compilons le en LIMIT :
1298
-		if ($a11 !== 'n' and $a21 !== 'n' and $mode == '++' and $op == ',') {
1299
-			$boucle->limit =
1300
-				(is_numeric($a11) ? "'$a11'" : $a11)
1301
-				. ".','."
1302
-				. (is_numeric($a21) ? "'$a21'" : $a21);
1303
-		} else {
1304
-			calculer_parties($boucles, $idb, $partie, $mode);
1305
-		}
1306
-	}
1280
+    $boucle = &$boucles[$idb];
1281
+    $a1 = $crit->param[0];
1282
+    $a2 = $crit->param[1];
1283
+    $op = $crit->op;
1284
+
1285
+    list($a11, $a12) = calculer_critere_parties_aux($idb, $boucles, $a1);
1286
+    list($a21, $a22) = calculer_critere_parties_aux($idb, $boucles, $a2);
1287
+
1288
+    if (($op == ',') && (is_numeric($a11) && (is_numeric($a21)))) {
1289
+        $boucle->limit = $a11 . ',' . $a21;
1290
+    } else {
1291
+        // 3 dans {1/3}, {2,3} ou {1,n-3}
1292
+        $boucle->total_parties = ($a21 != 'n') ? $a21 : $a22;
1293
+        // 2 dans {2/3}, {2,5}, {n-2,1}
1294
+        $partie = ($a11 != 'n') ? $a11 : $a12;
1295
+        $mode = (($op == '/') ? '/' :
1296
+            (($a11 == 'n') ? '-' : '+') . (($a21 == 'n') ? '-' : '+'));
1297
+        // cas simple {0,#ENV{truc}} compilons le en LIMIT :
1298
+        if ($a11 !== 'n' and $a21 !== 'n' and $mode == '++' and $op == ',') {
1299
+            $boucle->limit =
1300
+                (is_numeric($a11) ? "'$a11'" : $a11)
1301
+                . ".','."
1302
+                . (is_numeric($a21) ? "'$a21'" : $a21);
1303
+        } else {
1304
+            calculer_parties($boucles, $idb, $partie, $mode);
1305
+        }
1306
+    }
1307 1307
 }
1308 1308
 
1309 1309
 /**
@@ -1331,63 +1331,63 @@  discard block
 block discarded – undo
1331 1331
  * @return void
1332 1332
  **/
1333 1333
 function calculer_parties(&$boucles, $id_boucle, $debut, $mode) {
1334
-	$total_parties = $boucles[$id_boucle]->total_parties;
1335
-
1336
-	preg_match(',([+-/p])([+-/])?,', $mode, $regs);
1337
-	list(, $op1, $op2) = array_pad($regs, 3, null);
1338
-	$nombre_boucle = "\$Numrows['$id_boucle']['total']";
1339
-	// {1/3}
1340
-	if ($op1 == '/') {
1341
-		$pmoins1 = is_numeric($debut) ? ($debut - 1) : "($debut-1)";
1342
-		$totpos = is_numeric($total_parties) ? ($total_parties) :
1343
-			"($total_parties ? $total_parties : 1)";
1344
-		$fin = "ceil(($nombre_boucle * $debut )/$totpos) - 1";
1345
-		$debut = !$pmoins1 ? 0 : "ceil(($nombre_boucle * $pmoins1)/$totpos);";
1346
-	} else {
1347
-		// cas {n-1,x}
1348
-		if ($op1 == '-') {
1349
-			$debut = "$nombre_boucle - $debut;";
1350
-		}
1351
-
1352
-		// cas {x,n-1}
1353
-		if ($op2 == '-') {
1354
-			$fin = '$debut_boucle + ' . $nombre_boucle . ' - '
1355
-				. (is_numeric($total_parties) ? ($total_parties + 1) :
1356
-					($total_parties . ' - 1'));
1357
-		} else {
1358
-			// {x,1} ou {pagination}
1359
-			$fin = '$debut_boucle'
1360
-				. (is_numeric($total_parties) ?
1361
-					(($total_parties == 1) ? '' : (' + ' . ($total_parties - 1))) :
1362
-					('+' . $total_parties . ' - 1'));
1363
-		}
1364
-
1365
-		// {pagination}, gerer le debut_xx=-1 pour tout voir
1366
-		if ($op1 == 'p') {
1367
-			$debut .= ";\n	\$debut_boucle = ((\$tout=(\$debut_boucle == -1))?0:(\$debut_boucle))";
1368
-			$debut .= ";\n	\$debut_boucle = max(0,min(\$debut_boucle,floor(($nombre_boucle-1)/($total_parties))*($total_parties)))";
1369
-			$fin = "(\$tout ? $nombre_boucle : $fin)";
1370
-		}
1371
-	}
1372
-
1373
-	// Notes :
1374
-	// $debut_boucle et $fin_boucle sont les indices SQL du premier
1375
-	// et du dernier demandes dans la boucle : 0 pour le premier,
1376
-	// n-1 pour le dernier ; donc total_boucle = 1 + debut - fin
1377
-	// Utiliser min pour rabattre $fin_boucle sur total_boucle.
1378
-
1379
-	$boucles[$id_boucle]->mode_partie = "\n\t"
1380
-		. '$debut_boucle = ' . $debut . ";\n	"
1381
-		. "\$debut_boucle = intval(\$debut_boucle);\n	"
1382
-		. '$fin_boucle = min(' . $fin . ", \$Numrows['$id_boucle']['total'] - 1);\n	"
1383
-		. '$Numrows[\'' . $id_boucle . "']['grand_total'] = \$Numrows['$id_boucle']['total'];\n	"
1384
-		. '$Numrows[\'' . $id_boucle . '\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);'
1385
-		. "\n\tif (\$debut_boucle>0"
1386
-		. " AND \$debut_boucle < \$Numrows['$id_boucle']['grand_total']"
1387
-		. " AND \$iter->seek(\$debut_boucle,'continue'))"
1388
-		. "\n\t\t\$Numrows['$id_boucle']['compteur_boucle'] = \$debut_boucle;\n\t";
1389
-
1390
-	$boucles[$id_boucle]->partie = "
1334
+    $total_parties = $boucles[$id_boucle]->total_parties;
1335
+
1336
+    preg_match(',([+-/p])([+-/])?,', $mode, $regs);
1337
+    list(, $op1, $op2) = array_pad($regs, 3, null);
1338
+    $nombre_boucle = "\$Numrows['$id_boucle']['total']";
1339
+    // {1/3}
1340
+    if ($op1 == '/') {
1341
+        $pmoins1 = is_numeric($debut) ? ($debut - 1) : "($debut-1)";
1342
+        $totpos = is_numeric($total_parties) ? ($total_parties) :
1343
+            "($total_parties ? $total_parties : 1)";
1344
+        $fin = "ceil(($nombre_boucle * $debut )/$totpos) - 1";
1345
+        $debut = !$pmoins1 ? 0 : "ceil(($nombre_boucle * $pmoins1)/$totpos);";
1346
+    } else {
1347
+        // cas {n-1,x}
1348
+        if ($op1 == '-') {
1349
+            $debut = "$nombre_boucle - $debut;";
1350
+        }
1351
+
1352
+        // cas {x,n-1}
1353
+        if ($op2 == '-') {
1354
+            $fin = '$debut_boucle + ' . $nombre_boucle . ' - '
1355
+                . (is_numeric($total_parties) ? ($total_parties + 1) :
1356
+                    ($total_parties . ' - 1'));
1357
+        } else {
1358
+            // {x,1} ou {pagination}
1359
+            $fin = '$debut_boucle'
1360
+                . (is_numeric($total_parties) ?
1361
+                    (($total_parties == 1) ? '' : (' + ' . ($total_parties - 1))) :
1362
+                    ('+' . $total_parties . ' - 1'));
1363
+        }
1364
+
1365
+        // {pagination}, gerer le debut_xx=-1 pour tout voir
1366
+        if ($op1 == 'p') {
1367
+            $debut .= ";\n	\$debut_boucle = ((\$tout=(\$debut_boucle == -1))?0:(\$debut_boucle))";
1368
+            $debut .= ";\n	\$debut_boucle = max(0,min(\$debut_boucle,floor(($nombre_boucle-1)/($total_parties))*($total_parties)))";
1369
+            $fin = "(\$tout ? $nombre_boucle : $fin)";
1370
+        }
1371
+    }
1372
+
1373
+    // Notes :
1374
+    // $debut_boucle et $fin_boucle sont les indices SQL du premier
1375
+    // et du dernier demandes dans la boucle : 0 pour le premier,
1376
+    // n-1 pour le dernier ; donc total_boucle = 1 + debut - fin
1377
+    // Utiliser min pour rabattre $fin_boucle sur total_boucle.
1378
+
1379
+    $boucles[$id_boucle]->mode_partie = "\n\t"
1380
+        . '$debut_boucle = ' . $debut . ";\n	"
1381
+        . "\$debut_boucle = intval(\$debut_boucle);\n	"
1382
+        . '$fin_boucle = min(' . $fin . ", \$Numrows['$id_boucle']['total'] - 1);\n	"
1383
+        . '$Numrows[\'' . $id_boucle . "']['grand_total'] = \$Numrows['$id_boucle']['total'];\n	"
1384
+        . '$Numrows[\'' . $id_boucle . '\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);'
1385
+        . "\n\tif (\$debut_boucle>0"
1386
+        . " AND \$debut_boucle < \$Numrows['$id_boucle']['grand_total']"
1387
+        . " AND \$iter->seek(\$debut_boucle,'continue'))"
1388
+        . "\n\t\t\$Numrows['$id_boucle']['compteur_boucle'] = \$debut_boucle;\n\t";
1389
+
1390
+    $boucles[$id_boucle]->partie = "
1391 1391
 		if (\$Numrows['$id_boucle']['compteur_boucle'] <= \$debut_boucle) continue;
1392 1392
 		if (\$Numrows['$id_boucle']['compteur_boucle']-1 > \$fin_boucle) break;";
1393 1393
 }
@@ -1404,26 +1404,26 @@  discard block
 block discarded – undo
1404 1404
  * @return array          Valeur de l'élément (peut être une expression PHP), Nombre soustrait
1405 1405
  **/
1406 1406
 function calculer_critere_parties_aux($idb, &$boucles, $param) {
1407
-	if ($param[0]->type != 'texte') {
1408
-		$a1 = calculer_liste([$param[0]], $idb, $boucles, $boucles[$idb]->id_parent);
1409
-		if (isset($param[1]->texte)) {
1410
-			preg_match(',^ *(-([0-9]+))? *$,', $param[1]->texte, $m);
1411
-
1412
-			return ["intval($a1)", ((isset($m[2]) and $m[2]) ? $m[2] : 0)];
1413
-		} else {
1414
-			return ["intval($a1)", 0];
1415
-		}
1416
-	} else {
1417
-		preg_match(',^ *(([0-9]+)|n) *(- *([0-9]+)? *)?$,', $param[0]->texte, $m);
1418
-		$a1 = $m[1];
1419
-		if (empty($m[3])) {
1420
-			return [$a1, 0];
1421
-		} elseif (!empty($m[4])) {
1422
-			return [$a1, $m[4]];
1423
-		} else {
1424
-			return [$a1, calculer_liste([$param[1]], $idb, $boucles, $boucles[$idb]->id_parent)];
1425
-		}
1426
-	}
1407
+    if ($param[0]->type != 'texte') {
1408
+        $a1 = calculer_liste([$param[0]], $idb, $boucles, $boucles[$idb]->id_parent);
1409
+        if (isset($param[1]->texte)) {
1410
+            preg_match(',^ *(-([0-9]+))? *$,', $param[1]->texte, $m);
1411
+
1412
+            return ["intval($a1)", ((isset($m[2]) and $m[2]) ? $m[2] : 0)];
1413
+        } else {
1414
+            return ["intval($a1)", 0];
1415
+        }
1416
+    } else {
1417
+        preg_match(',^ *(([0-9]+)|n) *(- *([0-9]+)? *)?$,', $param[0]->texte, $m);
1418
+        $a1 = $m[1];
1419
+        if (empty($m[3])) {
1420
+            return [$a1, 0];
1421
+        } elseif (!empty($m[4])) {
1422
+            return [$a1, $m[4]];
1423
+        } else {
1424
+            return [$a1, calculer_liste([$param[1]], $idb, $boucles, $boucles[$idb]->id_parent)];
1425
+        }
1426
+    }
1427 1427
 }
1428 1428
 
1429 1429
 
@@ -1450,47 +1450,47 @@  discard block
 block discarded – undo
1450 1450
  *     array : Erreur sur un des critères
1451 1451
  **/
1452 1452
 function calculer_criteres($idb, &$boucles) {
1453
-	$msg = '';
1454
-	$boucle = $boucles[$idb];
1455
-	$table = strtoupper($boucle->type_requete);
1456
-	$serveur = strtolower($boucle->sql_serveur);
1457
-
1458
-	$defaut = charger_fonction('DEFAUT', 'calculer_critere');
1459
-	// s'il y avait une erreur de syntaxe, propager cette info
1460
-	if (!is_array($boucle->criteres)) {
1461
-		return [];
1462
-	}
1463
-
1464
-	foreach ($boucle->criteres as $crit) {
1465
-		$critere = $crit->op;
1466
-		// critere personnalise ?
1467
-		if (
1468
-			(!$serveur or
1469
-				((!function_exists($f = 'critere_' . $serveur . '_' . $table . '_' . $critere))
1470
-					and (!function_exists($f = $f . '_dist'))
1471
-					and (!function_exists($f = 'critere_' . $serveur . '_' . $critere))
1472
-					and (!function_exists($f = $f . '_dist'))
1473
-				)
1474
-			)
1475
-			and (!function_exists($f = 'critere_' . $table . '_' . $critere))
1476
-			and (!function_exists($f = $f . '_dist'))
1477
-			and (!function_exists($f = 'critere_' . $critere))
1478
-			and (!function_exists($f = $f . '_dist'))
1479
-		) {
1480
-			// fonction critere standard
1481
-			$f = $defaut;
1482
-		}
1483
-		// compile le critere
1484
-		$res = $f($idb, $boucles, $crit);
1485
-
1486
-		// Gestion centralisee des erreurs pour pouvoir propager
1487
-		if (is_array($res)) {
1488
-			$msg = $res;
1489
-			erreur_squelette($msg, $boucle);
1490
-		}
1491
-	}
1492
-
1493
-	return $msg;
1453
+    $msg = '';
1454
+    $boucle = $boucles[$idb];
1455
+    $table = strtoupper($boucle->type_requete);
1456
+    $serveur = strtolower($boucle->sql_serveur);
1457
+
1458
+    $defaut = charger_fonction('DEFAUT', 'calculer_critere');
1459
+    // s'il y avait une erreur de syntaxe, propager cette info
1460
+    if (!is_array($boucle->criteres)) {
1461
+        return [];
1462
+    }
1463
+
1464
+    foreach ($boucle->criteres as $crit) {
1465
+        $critere = $crit->op;
1466
+        // critere personnalise ?
1467
+        if (
1468
+            (!$serveur or
1469
+                ((!function_exists($f = 'critere_' . $serveur . '_' . $table . '_' . $critere))
1470
+                    and (!function_exists($f = $f . '_dist'))
1471
+                    and (!function_exists($f = 'critere_' . $serveur . '_' . $critere))
1472
+                    and (!function_exists($f = $f . '_dist'))
1473
+                )
1474
+            )
1475
+            and (!function_exists($f = 'critere_' . $table . '_' . $critere))
1476
+            and (!function_exists($f = $f . '_dist'))
1477
+            and (!function_exists($f = 'critere_' . $critere))
1478
+            and (!function_exists($f = $f . '_dist'))
1479
+        ) {
1480
+            // fonction critere standard
1481
+            $f = $defaut;
1482
+        }
1483
+        // compile le critere
1484
+        $res = $f($idb, $boucles, $crit);
1485
+
1486
+        // Gestion centralisee des erreurs pour pouvoir propager
1487
+        if (is_array($res)) {
1488
+            $msg = $res;
1489
+            erreur_squelette($msg, $boucle);
1490
+        }
1491
+    }
1492
+
1493
+    return $msg;
1494 1494
 }
1495 1495
 
1496 1496
 /**
@@ -1507,11 +1507,11 @@  discard block
 block discarded – undo
1507 1507
  * @return string         Code compilé rééchappé
1508 1508
  */
1509 1509
 function kwote($lisp, $serveur = '', $type = '') {
1510
-	if (preg_match(_CODE_QUOTE, $lisp, $r)) {
1511
-		return $r[1] . '"' . sql_quote(str_replace(["\\'", '\\\\'], ["'", '\\'], $r[2]), $serveur, $type) . '"';
1512
-	} else {
1513
-		return "sql_quote($lisp, '$serveur', '" . str_replace("'", "\\'", $type) . "')";
1514
-	}
1510
+    if (preg_match(_CODE_QUOTE, $lisp, $r)) {
1511
+        return $r[1] . '"' . sql_quote(str_replace(["\\'", '\\\\'], ["'", '\\'], $r[2]), $serveur, $type) . '"';
1512
+    } else {
1513
+        return "sql_quote($lisp, '$serveur', '" . str_replace("'", "\\'", $type) . "')";
1514
+    }
1515 1515
 }
1516 1516
 
1517 1517
 
@@ -1530,82 +1530,82 @@  discard block
 block discarded – undo
1530 1530
  * @return void
1531 1531
  **/
1532 1532
 function critere_IN_dist($idb, &$boucles, $crit) {
1533
-	$r = calculer_critere_infixe($idb, $boucles, $crit);
1534
-	if (!$r) {
1535
-		return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']]);
1536
-	}
1537
-	list($arg, $op, $val, $col, $where_complement) = $r;
1538
-
1539
-	$in = critere_IN_cas($idb, $boucles, $crit->not ? 'NOT' : ($crit->exclus ? 'exclus' : ''), $arg, $op, $val, $col);
1540
-
1541
-	//	inserer la condition; exemple: {id_mot ?IN (66, 62, 64)}
1542
-	$where = $in;
1543
-	if ($crit->cond) {
1544
-		$pred = calculer_argument_precedent($idb, $col, $boucles);
1545
-		$where = ["'?'", $pred, $where, "''"];
1546
-		if ($where_complement) { // condition annexe du type "AND (objet='article')"
1547
-		$where_complement = ["'?'", $pred, $where_complement, "''"];
1548
-		}
1549
-	}
1550
-	if ($crit->exclus) {
1551
-		if (!preg_match(',^L[0-9]+[.],', $arg)) {
1552
-			$where = ["'NOT'", $where];
1553
-		} else // un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete
1554
-			// c'est une sous requete identique a la requete principale sous la forme (SELF,$select,$where) avec $select et $where qui surchargent
1555
-		{
1556
-			$where = [
1557
-				"'NOT'",
1558
-				[
1559
-					"'IN'",
1560
-					"'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'",
1561
-					["'SELF'", "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'", $where]
1562
-				]
1563
-			];
1564
-		}
1565
-	}
1566
-
1567
-	$boucles[$idb]->where[] = $where;
1568
-	if ($where_complement) { // condition annexe du type "AND (objet='article')"
1569
-	$boucles[$idb]->where[] = $where_complement;
1570
-	}
1533
+    $r = calculer_critere_infixe($idb, $boucles, $crit);
1534
+    if (!$r) {
1535
+        return (['zbug_critere_inconnu', ['critere' => $crit->op . ' ?']]);
1536
+    }
1537
+    list($arg, $op, $val, $col, $where_complement) = $r;
1538
+
1539
+    $in = critere_IN_cas($idb, $boucles, $crit->not ? 'NOT' : ($crit->exclus ? 'exclus' : ''), $arg, $op, $val, $col);
1540
+
1541
+    //	inserer la condition; exemple: {id_mot ?IN (66, 62, 64)}
1542
+    $where = $in;
1543
+    if ($crit->cond) {
1544
+        $pred = calculer_argument_precedent($idb, $col, $boucles);
1545
+        $where = ["'?'", $pred, $where, "''"];
1546
+        if ($where_complement) { // condition annexe du type "AND (objet='article')"
1547
+        $where_complement = ["'?'", $pred, $where_complement, "''"];
1548
+        }
1549
+    }
1550
+    if ($crit->exclus) {
1551
+        if (!preg_match(',^L[0-9]+[.],', $arg)) {
1552
+            $where = ["'NOT'", $where];
1553
+        } else // un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete
1554
+            // c'est une sous requete identique a la requete principale sous la forme (SELF,$select,$where) avec $select et $where qui surchargent
1555
+        {
1556
+            $where = [
1557
+                "'NOT'",
1558
+                [
1559
+                    "'IN'",
1560
+                    "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'",
1561
+                    ["'SELF'", "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'", $where]
1562
+                ]
1563
+            ];
1564
+        }
1565
+    }
1566
+
1567
+    $boucles[$idb]->where[] = $where;
1568
+    if ($where_complement) { // condition annexe du type "AND (objet='article')"
1569
+    $boucles[$idb]->where[] = $where_complement;
1570
+    }
1571 1571
 }
1572 1572
 
1573 1573
 // https://code.spip.net/@critere_IN_cas
1574 1574
 function critere_IN_cas($idb, &$boucles, $crit2, $arg, $op, $val, $col) {
1575
-	static $num = [];
1576
-	$descr = $boucles[$idb]->descr;
1577
-	$cpt = &$num[$descr['nom']][$descr['gram']][$idb];
1578
-
1579
-	$var = '$in' . $cpt++;
1580
-	$x = "\n\t$var = array();";
1581
-	foreach ($val as $k => $v) {
1582
-		if (preg_match(",^(\n//.*\n)?'(.*)'$,", $v, $r)) {
1583
-			// optimiser le traitement des constantes
1584
-			if (is_numeric($r[2])) {
1585
-				$x .= "\n\t$var" . "[]= $r[2];";
1586
-			} else {
1587
-				$x .= "\n\t$var" . '[]= ' . sql_quote($r[2]) . ';';
1588
-			}
1589
-		} else {
1590
-			// Pour permettre de passer des tableaux de valeurs
1591
-			// on repere l'utilisation brute de #ENV**{X},
1592
-			// c'est-a-dire sa  traduction en ($PILE[0][X]).
1593
-			// et on deballe mais en rajoutant l'anti XSS
1594
-			$x .= "\n\tif (!(is_array(\$a = ($v))))\n\t\t$var" . "[]= \$a;\n\telse $var = array_merge($var, \$a);";
1595
-		}
1596
-	}
1597
-
1598
-	$boucles[$idb]->in .= $x;
1599
-
1600
-	// inserer le tri par defaut selon les ordres du IN ...
1601
-	// avec une ecriture de type FIELD qui degrade les performances (du meme ordre qu'un regexp)
1602
-	// et que l'on limite donc strictement aux cas necessaires :
1603
-	// si ce n'est pas un !IN, et si il n'y a pas d'autre order dans la boucle
1604
-	if (!$crit2) {
1605
-		$boucles[$idb]->default_order[] = "((!\$zqv=sql_quote($var) OR \$zqv===\"''\") ? 0 : ('FIELD($arg,' . \$zqv . ')'))";
1606
-	}
1607
-
1608
-	return "sql_in('$arg', $var" . ($crit2 == 'NOT' ? ",'NOT'" : '') . ')';
1575
+    static $num = [];
1576
+    $descr = $boucles[$idb]->descr;
1577
+    $cpt = &$num[$descr['nom']][$descr['gram']][$idb];
1578
+
1579
+    $var = '$in' . $cpt++;
1580
+    $x = "\n\t$var = array();";
1581
+    foreach ($val as $k => $v) {
1582
+        if (preg_match(",^(\n//.*\n)?'(.*)'$,", $v, $r)) {
1583
+            // optimiser le traitement des constantes
1584
+            if (is_numeric($r[2])) {
1585
+                $x .= "\n\t$var" . "[]= $r[2];";
1586
+            } else {
1587
+                $x .= "\n\t$var" . '[]= ' . sql_quote($r[2]) . ';';
1588
+            }
1589
+        } else {
1590
+            // Pour permettre de passer des tableaux de valeurs
1591
+            // on repere l'utilisation brute de #ENV**{X},
1592
+            // c'est-a-dire sa  traduction en ($PILE[0][X]).
1593
+            // et on deballe mais en rajoutant l'anti XSS
1594
+            $x .= "\n\tif (!(is_array(\$a = ($v))))\n\t\t$var" . "[]= \$a;\n\telse $var = array_merge($var, \$a);";
1595
+        }
1596
+    }
1597
+
1598
+    $boucles[$idb]->in .= $x;
1599
+
1600
+    // inserer le tri par defaut selon les ordres du IN ...
1601
+    // avec une ecriture de type FIELD qui degrade les performances (du meme ordre qu'un regexp)
1602
+    // et que l'on limite donc strictement aux cas necessaires :
1603
+    // si ce n'est pas un !IN, et si il n'y a pas d'autre order dans la boucle
1604
+    if (!$crit2) {
1605
+        $boucles[$idb]->default_order[] = "((!\$zqv=sql_quote($var) OR \$zqv===\"''\") ? 0 : ('FIELD($arg,' . \$zqv . ')'))";
1606
+    }
1607
+
1608
+    return "sql_in('$arg', $var" . ($crit2 == 'NOT' ? ",'NOT'" : '') . ')';
1609 1609
 }
1610 1610
 
1611 1611
 /**
@@ -1621,22 +1621,22 @@  discard block
 block discarded – undo
1621 1621
  * @return void
1622 1622
  */
1623 1623
 function critere_where_dist($idb, &$boucles, $crit) {
1624
-	$boucle = &$boucles[$idb];
1625
-	if (isset($crit->param[0])) {
1626
-		$_where = calculer_liste($crit->param[0], $idb, $boucles, $boucle->id_parent);
1627
-	} else {
1628
-		$_where = 'spip_sanitize_from_request(@$Pile[0]["where"],"where","vide")';
1629
-	}
1630
-
1631
-	if ($crit->cond) {
1632
-		$_where = "((\$zzw = $_where) ? \$zzw : '')";
1633
-	}
1634
-
1635
-	if ($crit->not) {
1636
-		$_where = "array('NOT',$_where)";
1637
-	}
1638
-
1639
-	$boucle->where[] = $_where;
1624
+    $boucle = &$boucles[$idb];
1625
+    if (isset($crit->param[0])) {
1626
+        $_where = calculer_liste($crit->param[0], $idb, $boucles, $boucle->id_parent);
1627
+    } else {
1628
+        $_where = 'spip_sanitize_from_request(@$Pile[0]["where"],"where","vide")';
1629
+    }
1630
+
1631
+    if ($crit->cond) {
1632
+        $_where = "((\$zzw = $_where) ? \$zzw : '')";
1633
+    }
1634
+
1635
+    if ($crit->not) {
1636
+        $_where = "array('NOT',$_where)";
1637
+    }
1638
+
1639
+    $boucle->where[] = $_where;
1640 1640
 }
1641 1641
 
1642 1642
 /**
@@ -1664,31 +1664,31 @@  discard block
 block discarded – undo
1664 1664
  * @return void
1665 1665
  */
1666 1666
 function critere_id__dist($idb, &$boucles, $crit) {
1667
-	/** @var Boucle $boucle */
1668
-	$boucle = $boucles[$idb];
1669
-
1670
-	$champs = lister_champs_id_conditionnel(
1671
-		$boucle->show['table'],
1672
-		$boucle->show,
1673
-		$boucle->sql_serveur
1674
-	);
1675
-
1676
-	// ne pas tenir compte des critères identiques déjà présents.
1677
-	if (!empty($boucle->modificateur['criteres'])) {
1678
-		$champs = array_diff($champs, array_keys($boucle->modificateur['criteres']));
1679
-	}
1680
-	// nous aider en mode debug.
1681
-	$boucle->debug[] = 'id_ : ' . implode(', ', $champs);
1682
-	$boucle->modificateur['id_'] = $champs;
1683
-
1684
-	// créer un critère {id_xxx?} de chaque champ retenu
1685
-	foreach ($champs as $champ) {
1686
-		$critere_id_table = new Critere();
1687
-		$critere_id_table->op = $champ;
1688
-		$critere_id_table->cond = '?';
1689
-		$critere_id_table->ligne = $crit->ligne;
1690
-		calculer_critere_DEFAUT_dist($idb, $boucles, $critere_id_table);
1691
-	}
1667
+    /** @var Boucle $boucle */
1668
+    $boucle = $boucles[$idb];
1669
+
1670
+    $champs = lister_champs_id_conditionnel(
1671
+        $boucle->show['table'],
1672
+        $boucle->show,
1673
+        $boucle->sql_serveur
1674
+    );
1675
+
1676
+    // ne pas tenir compte des critères identiques déjà présents.
1677
+    if (!empty($boucle->modificateur['criteres'])) {
1678
+        $champs = array_diff($champs, array_keys($boucle->modificateur['criteres']));
1679
+    }
1680
+    // nous aider en mode debug.
1681
+    $boucle->debug[] = 'id_ : ' . implode(', ', $champs);
1682
+    $boucle->modificateur['id_'] = $champs;
1683
+
1684
+    // créer un critère {id_xxx?} de chaque champ retenu
1685
+    foreach ($champs as $champ) {
1686
+        $critere_id_table = new Critere();
1687
+        $critere_id_table->op = $champ;
1688
+        $critere_id_table->cond = '?';
1689
+        $critere_id_table->ligne = $crit->ligne;
1690
+        calculer_critere_DEFAUT_dist($idb, $boucles, $critere_id_table);
1691
+    }
1692 1692
 }
1693 1693
 
1694 1694
 /**
@@ -1708,79 +1708,79 @@  discard block
 block discarded – undo
1708 1708
  * @return array Liste de nom de champs (tel que id_article, id_mot, id_parent ...)
1709 1709
  */
1710 1710
 function lister_champs_id_conditionnel($table, $desc = null, $serveur = '') {
1711
-	// calculer la description de la table
1712
-	if (!is_array($desc)) {
1713
-		$desc = description_table($table, $serveur);
1714
-	}
1715
-	if (!$desc) {
1716
-		return [];
1717
-	}
1718
-
1719
-	// Les champs id_xx de la table demandée
1720
-	$champs = array_filter(
1721
-		array_keys($desc['field']),
1722
-		function ($champ) {
1723
-			return
1724
-				strpos($champ, 'id_') === 0
1725
-				or (in_array($champ, ['objet']));
1726
-		}
1727
-	);
1728
-
1729
-	// Si le champ id_rubrique appartient à la liste et si id_secteur n'est pas inclus on le rajoute.
1730
-	if (
1731
-		in_array('id_rubrique', $champs)
1732
-		and !in_array('id_secteur', $champs)
1733
-	) {
1734
-		$champs[] = 'id_secteur';
1735
-	}
1736
-
1737
-	// On ne fera pas mieux pour les tables d’un autre serveur
1738
-	if ($serveur) {
1739
-		return $champs;
1740
-	}
1741
-
1742
-	$primary = false;
1743
-	$associable = false;
1744
-	include_spip('action/editer_liens');
1745
-
1746
-	if (isset($desc['type'])) {
1747
-		$primary = id_table_objet($desc['type']);
1748
-		$associable = objet_associable($desc['type']);
1749
-	}
1750
-	if (isset($desc['field']['id_objet']) and isset($desc['field']['objet'])) {
1751
-		$associable = true;
1752
-	}
1753
-
1754
-	// liste de toutes les tables principales, sauf la notre
1755
-	$tables = lister_tables_objets_sql();
1756
-	unset($tables[$table]);
1757
-
1758
-	foreach ($tables as $_table => $_desc) {
1759
-		if (
1760
-			$associable
1761
-			or ($primary and in_array($primary, array_keys($_desc['field'])))
1762
-			or objet_associable($_desc['type'])
1763
-		) {
1764
-			$champs[] = id_table_objet($_table);
1765
-		}
1766
-	}
1767
-	$champs = array_values(array_unique($champs));
1768
-
1769
-	// Exclusions de certains id
1770
-	$exclusions = pipeline(
1771
-		'exclure_id_conditionnel',
1772
-		[
1773
-			'args' => [
1774
-				'table' => $table,
1775
-				'id_table_objet' => $primary,
1776
-				'associable' => $associable,
1777
-			],
1778
-			'data' => [],
1779
-		]
1780
-	);
1781
-	$champs = array_diff($champs, $exclusions);
1782
-
1783
-	return $champs;
1711
+    // calculer la description de la table
1712
+    if (!is_array($desc)) {
1713
+        $desc = description_table($table, $serveur);
1714
+    }
1715
+    if (!$desc) {
1716
+        return [];
1717
+    }
1718
+
1719
+    // Les champs id_xx de la table demandée
1720
+    $champs = array_filter(
1721
+        array_keys($desc['field']),
1722
+        function ($champ) {
1723
+            return
1724
+                strpos($champ, 'id_') === 0
1725
+                or (in_array($champ, ['objet']));
1726
+        }
1727
+    );
1728
+
1729
+    // Si le champ id_rubrique appartient à la liste et si id_secteur n'est pas inclus on le rajoute.
1730
+    if (
1731
+        in_array('id_rubrique', $champs)
1732
+        and !in_array('id_secteur', $champs)
1733
+    ) {
1734
+        $champs[] = 'id_secteur';
1735
+    }
1736
+
1737
+    // On ne fera pas mieux pour les tables d’un autre serveur
1738
+    if ($serveur) {
1739
+        return $champs;
1740
+    }
1741
+
1742
+    $primary = false;
1743
+    $associable = false;
1744
+    include_spip('action/editer_liens');
1745
+
1746
+    if (isset($desc['type'])) {
1747
+        $primary = id_table_objet($desc['type']);
1748
+        $associable = objet_associable($desc['type']);
1749
+    }
1750
+    if (isset($desc['field']['id_objet']) and isset($desc['field']['objet'])) {
1751
+        $associable = true;
1752
+    }
1753
+
1754
+    // liste de toutes les tables principales, sauf la notre
1755
+    $tables = lister_tables_objets_sql();
1756
+    unset($tables[$table]);
1757
+
1758
+    foreach ($tables as $_table => $_desc) {
1759
+        if (
1760
+            $associable
1761
+            or ($primary and in_array($primary, array_keys($_desc['field'])))
1762
+            or objet_associable($_desc['type'])
1763
+        ) {
1764
+            $champs[] = id_table_objet($_table);
1765
+        }
1766
+    }
1767
+    $champs = array_values(array_unique($champs));
1768
+
1769
+    // Exclusions de certains id
1770
+    $exclusions = pipeline(
1771
+        'exclure_id_conditionnel',
1772
+        [
1773
+            'args' => [
1774
+                'table' => $table,
1775
+                'id_table_objet' => $primary,
1776
+                'associable' => $associable,
1777
+            ],
1778
+            'data' => [],
1779
+        ]
1780
+    );
1781
+    $champs = array_diff($champs, $exclusions);
1782
+
1783
+    return $champs;
1784 1784
 }
1785 1785
 
1786 1786
 /**
@@ -1835,27 +1835,27 @@  discard block
 block discarded – undo
1835 1835
  * @return void
1836 1836
  */
1837 1837
 function critere_tri_dist($idb, &$boucles, $crit) {
1838
-	$boucle = &$boucles[$idb];
1839
-
1840
-	// definition du champ par defaut
1841
-	$_champ_defaut = !isset($crit->param[0][0]) ? "''"
1842
-		: calculer_liste([$crit->param[0][0]], $idb, $boucles, $boucle->id_parent);
1843
-	$_sens_defaut = !isset($crit->param[1][0]) ? '1'
1844
-		: calculer_liste([$crit->param[1][0]], $idb, $boucles, $boucle->id_parent);
1845
-	$_variable = !isset($crit->param[2][0]) ? "'$idb'"
1846
-		: calculer_liste([$crit->param[2][0]], $idb, $boucles, $boucle->id_parent);
1847
-
1848
-	$_tri = "((\$t=(isset(\$Pile[0]['tri'.$_variable]))?\$Pile[0]['tri'.$_variable]:((strncmp($_variable,'session',7)==0 AND session_get('tri'.$_variable))?session_get('tri'.$_variable):$_champ_defaut))?tri_protege_champ(\$t):'')";
1849
-
1850
-	$_sens_defaut = "(is_array(\$s=$_sens_defaut)?(isset(\$s[\$st=$_tri])?\$s[\$st]:reset(\$s)):\$s)";
1851
-	$_sens = "((intval(\$t=(isset(\$Pile[0]['sens'.$_variable]))?\$Pile[0]['sens'.$_variable]:((strncmp($_variable,'session',7)==0 AND session_get('sens'.$_variable))?session_get('sens'.$_variable):$_sens_defaut))==-1 OR \$t=='inverse')?-1:1)";
1852
-
1853
-	$boucle->modificateur['tri_champ'] = $_tri;
1854
-	$boucle->modificateur['tri_sens'] = $_sens;
1855
-	$boucle->modificateur['tri_nom'] = $_variable;
1856
-	// faut il inserer un test sur l'existence de $tri parmi les champs de la table ?
1857
-	// evite des erreurs sql, mais peut empecher des tri sur jointure ...
1858
-	$boucle->hash .= "
1838
+    $boucle = &$boucles[$idb];
1839
+
1840
+    // definition du champ par defaut
1841
+    $_champ_defaut = !isset($crit->param[0][0]) ? "''"
1842
+        : calculer_liste([$crit->param[0][0]], $idb, $boucles, $boucle->id_parent);
1843
+    $_sens_defaut = !isset($crit->param[1][0]) ? '1'
1844
+        : calculer_liste([$crit->param[1][0]], $idb, $boucles, $boucle->id_parent);
1845
+    $_variable = !isset($crit->param[2][0]) ? "'$idb'"
1846
+        : calculer_liste([$crit->param[2][0]], $idb, $boucles, $boucle->id_parent);
1847
+
1848
+    $_tri = "((\$t=(isset(\$Pile[0]['tri'.$_variable]))?\$Pile[0]['tri'.$_variable]:((strncmp($_variable,'session',7)==0 AND session_get('tri'.$_variable))?session_get('tri'.$_variable):$_champ_defaut))?tri_protege_champ(\$t):'')";
1849
+
1850
+    $_sens_defaut = "(is_array(\$s=$_sens_defaut)?(isset(\$s[\$st=$_tri])?\$s[\$st]:reset(\$s)):\$s)";
1851
+    $_sens = "((intval(\$t=(isset(\$Pile[0]['sens'.$_variable]))?\$Pile[0]['sens'.$_variable]:((strncmp($_variable,'session',7)==0 AND session_get('sens'.$_variable))?session_get('sens'.$_variable):$_sens_defaut))==-1 OR \$t=='inverse')?-1:1)";
1852
+
1853
+    $boucle->modificateur['tri_champ'] = $_tri;
1854
+    $boucle->modificateur['tri_sens'] = $_sens;
1855
+    $boucle->modificateur['tri_nom'] = $_variable;
1856
+    // faut il inserer un test sur l'existence de $tri parmi les champs de la table ?
1857
+    // evite des erreurs sql, mais peut empecher des tri sur jointure ...
1858
+    $boucle->hash .= "
1859 1859
 	\$senstri = '';
1860 1860
 	\$tri = $_tri;
1861 1861
 	if (\$tri){
@@ -1863,8 +1863,8 @@  discard block
 block discarded – undo
1863 1863
 		\$senstri = (\$senstri<0)?' DESC':'';
1864 1864
 	};
1865 1865
 	";
1866
-	$boucle->select[] = '".tri_champ_select($tri)."';
1867
-	$boucle->order[] = "tri_champ_order(\$tri,\$command['from'],\$senstri)";
1866
+    $boucle->select[] = '".tri_champ_select($tri)."';
1867
+    $boucle->order[] = "tri_champ_order(\$tri,\$command['from'],\$senstri)";
1868 1868
 }
1869 1869
 
1870 1870
 # Criteres de comparaison
@@ -1881,20 +1881,20 @@  discard block
 block discarded – undo
1881 1881
  * @return void
1882 1882
  **/
1883 1883
 function calculer_critere_DEFAUT_dist($idb, &$boucles, $crit) {
1884
-	// double cas particulier {0,1} et {1/2} repere a l'analyse lexicale
1885
-	if (($crit->op == ',') or ($crit->op == '/')) {
1886
-		return calculer_critere_parties($idb, $boucles, $crit);
1887
-	}
1888
-
1889
-	$r = calculer_critere_infixe($idb, $boucles, $crit);
1890
-	if (!$r) {
1891
-		#	// on produit une erreur seulement si le critere n'a pas de '?'
1892
-		#	if (!$crit->cond) {
1893
-		return (['zbug_critere_inconnu', ['critere' => $crit->op]]);
1894
-		#	}
1895
-	} else {
1896
-		calculer_critere_DEFAUT_args($idb, $boucles, $crit, $r);
1897
-	}
1884
+    // double cas particulier {0,1} et {1/2} repere a l'analyse lexicale
1885
+    if (($crit->op == ',') or ($crit->op == '/')) {
1886
+        return calculer_critere_parties($idb, $boucles, $crit);
1887
+    }
1888
+
1889
+    $r = calculer_critere_infixe($idb, $boucles, $crit);
1890
+    if (!$r) {
1891
+        #	// on produit une erreur seulement si le critere n'a pas de '?'
1892
+        #	if (!$crit->cond) {
1893
+        return (['zbug_critere_inconnu', ['critere' => $crit->op]]);
1894
+        #	}
1895
+    } else {
1896
+        calculer_critere_DEFAUT_args($idb, $boucles, $crit, $r);
1897
+    }
1898 1898
 }
1899 1899
 
1900 1900
 
@@ -1914,62 +1914,62 @@  discard block
 block discarded – undo
1914 1914
  * @return void
1915 1915
  **/
1916 1916
 function calculer_critere_DEFAUT_args($idb, &$boucles, $crit, $args) {
1917
-	list($arg, $op, $val, $col, $where_complement) = $args;
1918
-
1919
-	$where = ["'$op'", "'$arg'", $val[0]];
1920
-
1921
-	// inserer la negation (cf !...)
1922
-
1923
-	if ($crit->not) {
1924
-		$where = ["'NOT'", $where];
1925
-	}
1926
-	if ($crit->exclus) {
1927
-		if (!preg_match(',^L[0-9]+[.],', $arg)) {
1928
-			$where = ["'NOT'", $where];
1929
-		} else {
1930
-			// un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete
1931
-			// c'est une sous requete identique a la requete principale sous la forme (SELF,$select,$where) avec $select et $where qui surchargent
1932
-			$where = [
1933
-				"'NOT'",
1934
-				[
1935
-					"'IN'",
1936
-					"'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'",
1937
-					["'SELF'", "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'", $where]
1938
-				]
1939
-			];
1940
-		}
1941
-	}
1942
-
1943
-	// inserer la condition (cf {lang?})
1944
-	// traiter a part la date, elle est mise d'office par SPIP,
1945
-	if ($crit->cond) {
1946
-		$pred = calculer_argument_precedent($idb, $col, $boucles);
1947
-		if ($col == 'date' or $col == 'date_redac') {
1948
-			if ($pred == "\$Pile[0]['" . $col . "']") {
1949
-				$pred = "(\$Pile[0]['{$col}_default']?'':$pred)";
1950
-			}
1951
-		}
1952
-
1953
-		if ($op == '=' and !$crit->not) {
1954
-			$where = [
1955
-				"'?'",
1956
-				"(is_array($pred))",
1957
-				critere_IN_cas($idb, $boucles, 'COND', $arg, $op, [$pred], $col),
1958
-				$where
1959
-			];
1960
-		}
1961
-		$where = ["'?'", "!(is_array($pred)?count($pred):strlen($pred))", "''", $where];
1962
-		if ($where_complement) {
1963
-			// condition annexe du type "AND (objet='article')"
1964
-			$where_complement = ["'?'", "!(is_array($pred)?count($pred):strlen($pred))", "''", $where_complement];
1965
-		}
1966
-	}
1967
-
1968
-	$boucles[$idb]->where[] = $where;
1969
-	if ($where_complement) {
1970
-		// condition annexe du type "AND (objet='article')"
1971
-		$boucles[$idb]->where[] = $where_complement;
1972
-	}
1917
+    list($arg, $op, $val, $col, $where_complement) = $args;
1918
+
1919
+    $where = ["'$op'", "'$arg'", $val[0]];
1920
+
1921
+    // inserer la negation (cf !...)
1922
+
1923
+    if ($crit->not) {
1924
+        $where = ["'NOT'", $where];
1925
+    }
1926
+    if ($crit->exclus) {
1927
+        if (!preg_match(',^L[0-9]+[.],', $arg)) {
1928
+            $where = ["'NOT'", $where];
1929
+        } else {
1930
+            // un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete
1931
+            // c'est une sous requete identique a la requete principale sous la forme (SELF,$select,$where) avec $select et $where qui surchargent
1932
+            $where = [
1933
+                "'NOT'",
1934
+                [
1935
+                    "'IN'",
1936
+                    "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'",
1937
+                    ["'SELF'", "'" . $boucles[$idb]->id_table . '.' . $boucles[$idb]->primary . "'", $where]
1938
+                ]
1939
+            ];
1940
+        }
1941
+    }
1942
+
1943
+    // inserer la condition (cf {lang?})
1944
+    // traiter a part la date, elle est mise d'office par SPIP,
1945
+    if ($crit->cond) {
1946
+        $pred = calculer_argument_precedent($idb, $col, $boucles);
1947
+        if ($col == 'date' or $col == 'date_redac') {
1948
+            if ($pred == "\$Pile[0]['" . $col . "']") {
1949
+                $pred = "(\$Pile[0]['{$col}_default']?'':$pred)";
1950
+            }
1951
+        }
1952
+
1953
+        if ($op == '=' and !$crit->not) {
1954
+            $where = [
1955
+                "'?'",
1956
+                "(is_array($pred))",
1957
+                critere_IN_cas($idb, $boucles, 'COND', $arg, $op, [$pred], $col),
1958
+                $where
1959
+            ];
1960
+        }
1961
+        $where = ["'?'", "!(is_array($pred)?count($pred):strlen($pred))", "''", $where];
1962
+        if ($where_complement) {
1963
+            // condition annexe du type "AND (objet='article')"
1964
+            $where_complement = ["'?'", "!(is_array($pred)?count($pred):strlen($pred))", "''", $where_complement];
1965
+        }
1966
+    }
1967
+
1968
+    $boucles[$idb]->where[] = $where;
1969
+    if ($where_complement) {
1970
+        // condition annexe du type "AND (objet='article')"
1971
+        $boucles[$idb]->where[] = $where_complement;
1972
+    }
1973 1973
 }
1974 1974
 
1975 1975
 
@@ -2010,165 +2010,165 @@  discard block
 block discarded – undo
2010 2010
  **/
2011 2011
 function calculer_critere_infixe($idb, &$boucles, $crit) {
2012 2012
 
2013
-	$boucle = &$boucles[$idb];
2014
-	$type = $boucle->type_requete;
2015
-	$table = $boucle->id_table;
2016
-	$desc = $boucle->show;
2017
-	$col_vraie = null;
2018
-
2019
-	list($fct, $col, $op, $val, $args_sql) =
2020
-		calculer_critere_infixe_ops($idb, $boucles, $crit);
2021
-
2022
-	$col_alias = $col;
2023
-	$where_complement = false;
2024
-
2025
-	// Cas particulier : id_enfant => utiliser la colonne id_objet
2026
-	if ($col == 'id_enfant') {
2027
-		$col = $boucle->primary;
2028
-	}
2029
-
2030
-	// Cas particulier : id_parent => verifier les exceptions de tables
2031
-	if (
2032
-		(in_array($col, ['id_parent', 'id_secteur']) and isset($GLOBALS['exceptions_des_tables'][$table][$col]))
2033
-		or (isset($GLOBALS['exceptions_des_tables'][$table][$col]) and is_string($GLOBALS['exceptions_des_tables'][$table][$col]))
2034
-	) {
2035
-		$col = $GLOBALS['exceptions_des_tables'][$table][$col];
2036
-	} // et possibilite de gerer un critere secteur sur des tables de plugins (ie forums)
2037
-	else {
2038
-		if (($col == 'id_secteur') and ($critere_secteur = charger_fonction("critere_secteur_$type", 'public', true))) {
2039
-			$table = $critere_secteur($idb, $boucles, $val, $crit);
2040
-		}
2041
-
2042
-		// cas id_article=xx qui se mappe en id_objet=xx AND objet=article
2043
-		// sauf si exception declaree : sauter cette etape
2044
-		else {
2045
-			if (
2046
-				!isset($GLOBALS['exceptions_des_jointures'][table_objet_sql($table)][$col])
2047
-				and !isset($GLOBALS['exceptions_des_jointures'][$col])
2048
-				and count(trouver_champs_decomposes($col, $desc)) > 1
2049
-			) {
2050
-				$e = decompose_champ_id_objet($col);
2051
-				$col = array_shift($e);
2052
-				$where_complement = primary_doublee($e, $table);
2053
-			} // Cas particulier : expressions de date
2054
-			else {
2055
-				if ($c = calculer_critere_infixe_date($idb, $boucles, $col)) {
2056
-					list($col, $col_vraie) = $c;
2057
-					$table = '';
2058
-				} // table explicitée {mots.titre}
2059
-				else {
2060
-					if (preg_match('/^(.*)\.(.*)$/', $col, $r)) {
2061
-						list(, $table, $col) = $r;
2062
-						$col_alias = $col;
2063
-
2064
-						$trouver_table = charger_fonction('trouver_table', 'base');
2065
-						if (
2066
-							$desc = $trouver_table($table, $boucle->sql_serveur)
2067
-							and isset($desc['field'][$col])
2068
-							and $cle = array_search($desc['table'], $boucle->from)
2069
-						) {
2070
-							$table = $cle;
2071
-						} else {
2072
-							$table = trouver_jointure_champ($col, $boucle, [$table], ($crit->cond or $op != '='));
2073
-						}
2074
-						#$table = calculer_critere_externe_init($boucle, array($table), $col, $desc, ($crit->cond OR $op!='='), true);
2075
-						if (!$table) {
2076
-							return '';
2077
-						}
2078
-					}
2079
-					// si le champ n'est pas trouvé dans la table,
2080
-					// on cherche si une jointure peut l'obtenir
2081
-					elseif (@!array_key_exists($col, $desc['field'])) {
2082
-						// Champ joker * des iterateurs DATA qui accepte tout
2083
-						if (@array_key_exists('*', $desc['field'])) {
2084
-							$desc['field'][$col_vraie ? $col_vraie : $col] = ''; // on veut pas de cast INT par defaut car le type peut etre n'importe quoi dans les boucles DATA
2085
-						}
2086
-						else {
2087
-							$r = calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table);
2088
-							if (!$r) {
2089
-								return '';
2090
-							}
2091
-							list($col, $col_alias, $table, $where_complement, $desc) = $r;
2092
-						}
2093
-					}
2094
-				}
2095
-			}
2096
-		}
2097
-	}
2098
-
2099
-	$col_vraie = ($col_vraie ? $col_vraie : $col);
2100
-	// Dans tous les cas,
2101
-	// virer les guillemets eventuels autour d'un int (qui sont refuses par certains SQL)
2102
-	// et passer dans sql_quote avec le type si connu
2103
-	// et int sinon si la valeur est numerique
2104
-	// sinon introduire le vrai type du champ si connu dans le sql_quote (ou int NOT NULL sinon)
2105
-	// Ne pas utiliser intval, PHP tronquant les Bigint de SQL
2106
-	if ($op == '=' or in_array($op, $GLOBALS['table_criteres_infixes'])) {
2107
-		$type_cast_quote = (isset($desc['field'][$col_vraie]) ? $desc['field'][$col_vraie] : 'int NOT NULL');
2108
-		// defaire le quote des int et les passer dans sql_quote avec le bon type de champ si on le connait, int sinon
2109
-		// prendre en compte le debug ou la valeur arrive avec un commentaire PHP en debut
2110
-		if (preg_match(",^\\A(\s*//.*?$\s*)?\"'(-?\d+)'\"\\z,ms", $val[0], $r)) {
2111
-			$val[0] = $r[1] . '"' . sql_quote($r[2], $boucle->sql_serveur, $type_cast_quote) . '"';
2112
-		}
2113
-		// sinon expliciter les
2114
-		// sql_quote(truc) en sql_quote(truc,'',type)
2115
-		// sql_quote(truc,serveur) en sql_quote(truc,serveur,type)
2116
-		// sql_quote(truc,serveur,'') en sql_quote(truc,serveur,type)
2117
-		// sans toucher aux
2118
-		// sql_quote(truc,'','varchar(10) DEFAULT \'oui\' COLLATE NOCASE')
2119
-		// sql_quote(truc,'','varchar')
2120
-		elseif (
2121
-			preg_match('/\Asql_quote[(](.*?)(,[^)]*?)?(,[^)]*(?:\(\d+\)[^)]*)?)?[)]\s*\z/ms', $val[0], $r)
2122
-			// si pas deja un type
2123
-			and (!isset($r[3]) or !$r[3] or !trim($r[3], ", '"))
2124
-		) {
2125
-			$r = $r[1]
2126
-				. ((isset($r[2]) and $r[2]) ? $r[2] : ",''")
2127
-				. ",'" . addslashes($type_cast_quote) . "'";
2128
-			$val[0] = "sql_quote($r)";
2129
-		}
2130
-		elseif (
2131
-			strpos($val[0], '@@defaultcast@@') !== false
2132
-			and preg_match("/'@@defaultcast@@'\s*\)\s*\z/ms", $val[0], $r)
2133
-		) {
2134
-			$val[0] = substr($val[0], 0, -strlen($r[0])) . "'" . addslashes($type_cast_quote) . "')";
2135
-		}
2136
-	}
2137
-
2138
-	if (
2139
-		strpos($val[0], '@@defaultcast@@') !== false
2140
-		and preg_match("/'@@defaultcast@@'\s*\)\s*\z/ms", $val[0], $r)
2141
-	) {
2142
-		$val[0] = substr($val[0], 0, -strlen($r[0])) . "'char')";
2143
-	}
2144
-
2145
-	// Indicateur pour permettre aux fonctionx boucle_X de modifier
2146
-	// leurs requetes par defaut, notamment le champ statut
2147
-	// Ne pas confondre champs de la table principale et des jointures
2148
-	if ($table === $boucle->id_table) {
2149
-		$boucles[$idb]->modificateur['criteres'][$col_vraie] = true;
2150
-		if ($col_alias != $col_vraie) {
2151
-			$boucles[$idb]->modificateur['criteres'][$col_alias] = true;
2152
-		}
2153
-	}
2154
-
2155
-	// inserer le nom de la table SQL devant le nom du champ
2156
-	if ($table) {
2157
-		if ($col[0] == '`') {
2158
-			$arg = "$table." . substr($col, 1, -1);
2159
-		} else {
2160
-			$arg = "$table.$col";
2161
-		}
2162
-	} else {
2163
-		$arg = $col;
2164
-	}
2165
-
2166
-	// inserer la fonction SQL
2167
-	if ($fct) {
2168
-		$arg = "$fct($arg$args_sql)";
2169
-	}
2170
-
2171
-	return [$arg, $op, $val, $col_alias, $where_complement];
2013
+    $boucle = &$boucles[$idb];
2014
+    $type = $boucle->type_requete;
2015
+    $table = $boucle->id_table;
2016
+    $desc = $boucle->show;
2017
+    $col_vraie = null;
2018
+
2019
+    list($fct, $col, $op, $val, $args_sql) =
2020
+        calculer_critere_infixe_ops($idb, $boucles, $crit);
2021
+
2022
+    $col_alias = $col;
2023
+    $where_complement = false;
2024
+
2025
+    // Cas particulier : id_enfant => utiliser la colonne id_objet
2026
+    if ($col == 'id_enfant') {
2027
+        $col = $boucle->primary;
2028
+    }
2029
+
2030
+    // Cas particulier : id_parent => verifier les exceptions de tables
2031
+    if (
2032
+        (in_array($col, ['id_parent', 'id_secteur']) and isset($GLOBALS['exceptions_des_tables'][$table][$col]))
2033
+        or (isset($GLOBALS['exceptions_des_tables'][$table][$col]) and is_string($GLOBALS['exceptions_des_tables'][$table][$col]))
2034
+    ) {
2035
+        $col = $GLOBALS['exceptions_des_tables'][$table][$col];
2036
+    } // et possibilite de gerer un critere secteur sur des tables de plugins (ie forums)
2037
+    else {
2038
+        if (($col == 'id_secteur') and ($critere_secteur = charger_fonction("critere_secteur_$type", 'public', true))) {
2039
+            $table = $critere_secteur($idb, $boucles, $val, $crit);
2040
+        }
2041
+
2042
+        // cas id_article=xx qui se mappe en id_objet=xx AND objet=article
2043
+        // sauf si exception declaree : sauter cette etape
2044
+        else {
2045
+            if (
2046
+                !isset($GLOBALS['exceptions_des_jointures'][table_objet_sql($table)][$col])
2047
+                and !isset($GLOBALS['exceptions_des_jointures'][$col])
2048
+                and count(trouver_champs_decomposes($col, $desc)) > 1
2049
+            ) {
2050
+                $e = decompose_champ_id_objet($col);
2051
+                $col = array_shift($e);
2052
+                $where_complement = primary_doublee($e, $table);
2053
+            } // Cas particulier : expressions de date
2054
+            else {
2055
+                if ($c = calculer_critere_infixe_date($idb, $boucles, $col)) {
2056
+                    list($col, $col_vraie) = $c;
2057
+                    $table = '';
2058
+                } // table explicitée {mots.titre}
2059
+                else {
2060
+                    if (preg_match('/^(.*)\.(.*)$/', $col, $r)) {
2061
+                        list(, $table, $col) = $r;
2062
+                        $col_alias = $col;
2063
+
2064
+                        $trouver_table = charger_fonction('trouver_table', 'base');
2065
+                        if (
2066
+                            $desc = $trouver_table($table, $boucle->sql_serveur)
2067
+                            and isset($desc['field'][$col])
2068
+                            and $cle = array_search($desc['table'], $boucle->from)
2069
+                        ) {
2070
+                            $table = $cle;
2071
+                        } else {
2072
+                            $table = trouver_jointure_champ($col, $boucle, [$table], ($crit->cond or $op != '='));
2073
+                        }
2074
+                        #$table = calculer_critere_externe_init($boucle, array($table), $col, $desc, ($crit->cond OR $op!='='), true);
2075
+                        if (!$table) {
2076
+                            return '';
2077
+                        }
2078
+                    }
2079
+                    // si le champ n'est pas trouvé dans la table,
2080
+                    // on cherche si une jointure peut l'obtenir
2081
+                    elseif (@!array_key_exists($col, $desc['field'])) {
2082
+                        // Champ joker * des iterateurs DATA qui accepte tout
2083
+                        if (@array_key_exists('*', $desc['field'])) {
2084
+                            $desc['field'][$col_vraie ? $col_vraie : $col] = ''; // on veut pas de cast INT par defaut car le type peut etre n'importe quoi dans les boucles DATA
2085
+                        }
2086
+                        else {
2087
+                            $r = calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table);
2088
+                            if (!$r) {
2089
+                                return '';
2090
+                            }
2091
+                            list($col, $col_alias, $table, $where_complement, $desc) = $r;
2092
+                        }
2093
+                    }
2094
+                }
2095
+            }
2096
+        }
2097
+    }
2098
+
2099
+    $col_vraie = ($col_vraie ? $col_vraie : $col);
2100
+    // Dans tous les cas,
2101
+    // virer les guillemets eventuels autour d'un int (qui sont refuses par certains SQL)
2102
+    // et passer dans sql_quote avec le type si connu
2103
+    // et int sinon si la valeur est numerique
2104
+    // sinon introduire le vrai type du champ si connu dans le sql_quote (ou int NOT NULL sinon)
2105
+    // Ne pas utiliser intval, PHP tronquant les Bigint de SQL
2106
+    if ($op == '=' or in_array($op, $GLOBALS['table_criteres_infixes'])) {
2107
+        $type_cast_quote = (isset($desc['field'][$col_vraie]) ? $desc['field'][$col_vraie] : 'int NOT NULL');
2108
+        // defaire le quote des int et les passer dans sql_quote avec le bon type de champ si on le connait, int sinon
2109
+        // prendre en compte le debug ou la valeur arrive avec un commentaire PHP en debut
2110
+        if (preg_match(",^\\A(\s*//.*?$\s*)?\"'(-?\d+)'\"\\z,ms", $val[0], $r)) {
2111
+            $val[0] = $r[1] . '"' . sql_quote($r[2], $boucle->sql_serveur, $type_cast_quote) . '"';
2112
+        }
2113
+        // sinon expliciter les
2114
+        // sql_quote(truc) en sql_quote(truc,'',type)
2115
+        // sql_quote(truc,serveur) en sql_quote(truc,serveur,type)
2116
+        // sql_quote(truc,serveur,'') en sql_quote(truc,serveur,type)
2117
+        // sans toucher aux
2118
+        // sql_quote(truc,'','varchar(10) DEFAULT \'oui\' COLLATE NOCASE')
2119
+        // sql_quote(truc,'','varchar')
2120
+        elseif (
2121
+            preg_match('/\Asql_quote[(](.*?)(,[^)]*?)?(,[^)]*(?:\(\d+\)[^)]*)?)?[)]\s*\z/ms', $val[0], $r)
2122
+            // si pas deja un type
2123
+            and (!isset($r[3]) or !$r[3] or !trim($r[3], ", '"))
2124
+        ) {
2125
+            $r = $r[1]
2126
+                . ((isset($r[2]) and $r[2]) ? $r[2] : ",''")
2127
+                . ",'" . addslashes($type_cast_quote) . "'";
2128
+            $val[0] = "sql_quote($r)";
2129
+        }
2130
+        elseif (
2131
+            strpos($val[0], '@@defaultcast@@') !== false
2132
+            and preg_match("/'@@defaultcast@@'\s*\)\s*\z/ms", $val[0], $r)
2133
+        ) {
2134
+            $val[0] = substr($val[0], 0, -strlen($r[0])) . "'" . addslashes($type_cast_quote) . "')";
2135
+        }
2136
+    }
2137
+
2138
+    if (
2139
+        strpos($val[0], '@@defaultcast@@') !== false
2140
+        and preg_match("/'@@defaultcast@@'\s*\)\s*\z/ms", $val[0], $r)
2141
+    ) {
2142
+        $val[0] = substr($val[0], 0, -strlen($r[0])) . "'char')";
2143
+    }
2144
+
2145
+    // Indicateur pour permettre aux fonctionx boucle_X de modifier
2146
+    // leurs requetes par defaut, notamment le champ statut
2147
+    // Ne pas confondre champs de la table principale et des jointures
2148
+    if ($table === $boucle->id_table) {
2149
+        $boucles[$idb]->modificateur['criteres'][$col_vraie] = true;
2150
+        if ($col_alias != $col_vraie) {
2151
+            $boucles[$idb]->modificateur['criteres'][$col_alias] = true;
2152
+        }
2153
+    }
2154
+
2155
+    // inserer le nom de la table SQL devant le nom du champ
2156
+    if ($table) {
2157
+        if ($col[0] == '`') {
2158
+            $arg = "$table." . substr($col, 1, -1);
2159
+        } else {
2160
+            $arg = "$table.$col";
2161
+        }
2162
+    } else {
2163
+        $arg = $col;
2164
+    }
2165
+
2166
+    // inserer la fonction SQL
2167
+    if ($fct) {
2168
+        $arg = "$fct($arg$args_sql)";
2169
+    }
2170
+
2171
+    return [$arg, $op, $val, $col_alias, $where_complement];
2172 2172
 }
2173 2173
 
2174 2174
 
@@ -2197,78 +2197,78 @@  discard block
 block discarded – undo
2197 2197
  **/
2198 2198
 function calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table) {
2199 2199
 
2200
-	$where = '';
2201
-
2202
-	$calculer_critere_externe = 'calculer_critere_externe_init';
2203
-	// gestion par les plugins des jointures tordues
2204
-	// pas automatiques mais necessaires
2205
-	$table_sql = table_objet_sql($table);
2206
-	if (
2207
-		isset($GLOBALS['exceptions_des_jointures'][$table_sql])
2208
-		and is_array($GLOBALS['exceptions_des_jointures'][$table_sql])
2209
-		and
2210
-		(
2211
-			isset($GLOBALS['exceptions_des_jointures'][$table_sql][$col])
2212
-			or
2213
-			isset($GLOBALS['exceptions_des_jointures'][$table_sql][''])
2214
-		)
2215
-	) {
2216
-		$t = $GLOBALS['exceptions_des_jointures'][$table_sql];
2217
-		$index = isset($t[$col])
2218
-			? $t[$col] : (isset($t['']) ? $t[''] : []);
2219
-
2220
-		if (count($index) == 3) {
2221
-			list($t, $col, $calculer_critere_externe) = $index;
2222
-		} elseif (count($index) == 2) {
2223
-			list($t, $col) = $t[$col];
2224
-		} elseif (count($index) == 1) {
2225
-			list($calculer_critere_externe) = $index;
2226
-			$t = $table;
2227
-		} else {
2228
-			$t = '';
2229
-		} // jointure non declaree. La trouver.
2230
-	} elseif (isset($GLOBALS['exceptions_des_jointures'][$col])) {
2231
-		list($t, $col) = $GLOBALS['exceptions_des_jointures'][$col];
2232
-	} else {
2233
-		$t = '';
2234
-	} // jointure non declaree. La trouver.
2235
-
2236
-	// ici on construit le from pour fournir $col en piochant dans les jointures
2237
-
2238
-	// si des jointures explicites sont fournies, on cherche d'abord dans celles ci
2239
-	// permet de forcer une table de lien quand il y a ambiguite
2240
-	// <BOUCLE_(DOCUMENTS documents_liens){id_mot}>
2241
-	// alors que <BOUCLE_(DOCUMENTS){id_mot}> produit la meme chose que <BOUCLE_(DOCUMENTS mots_liens){id_mot}>
2242
-	$table = '';
2243
-	if ($boucle->jointures_explicites) {
2244
-		$jointures_explicites = explode(' ', $boucle->jointures_explicites);
2245
-		$table = $calculer_critere_externe($boucle, $jointures_explicites, $col, $desc, ($crit->cond or $op != '='), $t);
2246
-	}
2247
-
2248
-	// et sinon on cherche parmi toutes les jointures declarees
2249
-	if (!$table) {
2250
-		$table = $calculer_critere_externe($boucle, $boucle->jointures, $col, $desc, ($crit->cond or $op != '='), $t);
2251
-	}
2252
-
2253
-	if (!$table) {
2254
-		return '';
2255
-	}
2256
-
2257
-	// il ne reste plus qu'a trouver le champ dans les from
2258
-	list($nom, $desc, $cle) = trouver_champ_exterieur($col, $boucle->from, $boucle);
2259
-
2260
-	if (count($cle) > 1 or reset($cle) !== $col) {
2261
-		$col_alias = $col; // id_article devient juste le nom d'origine
2262
-		if (count($cle) > 1 and reset($cle) == 'id_objet') {
2263
-			$e = decompose_champ_id_objet($col);
2264
-			$col = array_shift($e);
2265
-			$where = primary_doublee($e, $table);
2266
-		} else {
2267
-			$col = reset($cle);
2268
-		}
2269
-	}
2270
-
2271
-	return [$col, $col_alias, $table, $where, $desc];
2200
+    $where = '';
2201
+
2202
+    $calculer_critere_externe = 'calculer_critere_externe_init';
2203
+    // gestion par les plugins des jointures tordues
2204
+    // pas automatiques mais necessaires
2205
+    $table_sql = table_objet_sql($table);
2206
+    if (
2207
+        isset($GLOBALS['exceptions_des_jointures'][$table_sql])
2208
+        and is_array($GLOBALS['exceptions_des_jointures'][$table_sql])
2209
+        and
2210
+        (
2211
+            isset($GLOBALS['exceptions_des_jointures'][$table_sql][$col])
2212
+            or
2213
+            isset($GLOBALS['exceptions_des_jointures'][$table_sql][''])
2214
+        )
2215
+    ) {
2216
+        $t = $GLOBALS['exceptions_des_jointures'][$table_sql];
2217
+        $index = isset($t[$col])
2218
+            ? $t[$col] : (isset($t['']) ? $t[''] : []);
2219
+
2220
+        if (count($index) == 3) {
2221
+            list($t, $col, $calculer_critere_externe) = $index;
2222
+        } elseif (count($index) == 2) {
2223
+            list($t, $col) = $t[$col];
2224
+        } elseif (count($index) == 1) {
2225
+            list($calculer_critere_externe) = $index;
2226
+            $t = $table;
2227
+        } else {
2228
+            $t = '';
2229
+        } // jointure non declaree. La trouver.
2230
+    } elseif (isset($GLOBALS['exceptions_des_jointures'][$col])) {
2231
+        list($t, $col) = $GLOBALS['exceptions_des_jointures'][$col];
2232
+    } else {
2233
+        $t = '';
2234
+    } // jointure non declaree. La trouver.
2235
+
2236
+    // ici on construit le from pour fournir $col en piochant dans les jointures
2237
+
2238
+    // si des jointures explicites sont fournies, on cherche d'abord dans celles ci
2239
+    // permet de forcer une table de lien quand il y a ambiguite
2240
+    // <BOUCLE_(DOCUMENTS documents_liens){id_mot}>
2241
+    // alors que <BOUCLE_(DOCUMENTS){id_mot}> produit la meme chose que <BOUCLE_(DOCUMENTS mots_liens){id_mot}>
2242
+    $table = '';
2243
+    if ($boucle->jointures_explicites) {
2244
+        $jointures_explicites = explode(' ', $boucle->jointures_explicites);
2245
+        $table = $calculer_critere_externe($boucle, $jointures_explicites, $col, $desc, ($crit->cond or $op != '='), $t);
2246
+    }
2247
+
2248
+    // et sinon on cherche parmi toutes les jointures declarees
2249
+    if (!$table) {
2250
+        $table = $calculer_critere_externe($boucle, $boucle->jointures, $col, $desc, ($crit->cond or $op != '='), $t);
2251
+    }
2252
+
2253
+    if (!$table) {
2254
+        return '';
2255
+    }
2256
+
2257
+    // il ne reste plus qu'a trouver le champ dans les from
2258
+    list($nom, $desc, $cle) = trouver_champ_exterieur($col, $boucle->from, $boucle);
2259
+
2260
+    if (count($cle) > 1 or reset($cle) !== $col) {
2261
+        $col_alias = $col; // id_article devient juste le nom d'origine
2262
+        if (count($cle) > 1 and reset($cle) == 'id_objet') {
2263
+            $e = decompose_champ_id_objet($col);
2264
+            $col = array_shift($e);
2265
+            $where = primary_doublee($e, $table);
2266
+        } else {
2267
+            $col = reset($cle);
2268
+        }
2269
+    }
2270
+
2271
+    return [$col, $col_alias, $table, $where, $desc];
2272 2272
 }
2273 2273
 
2274 2274
 
@@ -2289,10 +2289,10 @@  discard block
 block discarded – undo
2289 2289
  *     - valeur
2290 2290
  **/
2291 2291
 function primary_doublee($decompose, $table) {
2292
-	$e1 = reset($decompose);
2293
-	$e2 = "sql_quote('" . end($decompose) . "')";
2292
+    $e1 = reset($decompose);
2293
+    $e2 = "sql_quote('" . end($decompose) . "')";
2294 2294
 
2295
-	return ["'='", "'$table." . $e1 . "'", $e2];
2295
+    return ["'='", "'$table." . $e1 . "'", $e2];
2296 2296
 }
2297 2297
 
2298 2298
 /**
@@ -2323,57 +2323,57 @@  discard block
 block discarded – undo
2323 2323
  *     Vide sinon.
2324 2324
  */
2325 2325
 function calculer_critere_externe_init(&$boucle, $joints, $col, $desc, $cond, $checkarrivee = false) {
2326
-	// si on demande un truc du genre spip_mots
2327
-	// avec aussi spip_mots_liens dans les jointures dispo
2328
-	// et qu'on est la
2329
-	// il faut privilegier la jointure directe en 2 etapes spip_mots_liens, spip_mots
2330
-	if (
2331
-		$checkarrivee
2332
-		and is_string($checkarrivee)
2333
-		and $a = table_objet($checkarrivee)
2334
-		and in_array($a . '_liens', $joints)
2335
-	) {
2336
-		if ($res = calculer_lien_externe_init($boucle, $joints, $col, $desc, $cond, $checkarrivee)) {
2337
-			return $res;
2338
-		}
2339
-	}
2340
-	foreach ($joints as $joint) {
2341
-		if ($arrivee = trouver_champ_exterieur($col, [$joint], $boucle, $checkarrivee)) {
2342
-			// alias de table dans le from
2343
-			$t = array_search($arrivee[0], $boucle->from);
2344
-			// recuperer la cle id_xx eventuellement decomposee en (id_objet,objet)
2345
-			$cols = $arrivee[2];
2346
-			// mais on ignore la 3eme cle si presente qui correspond alors au point de depart
2347
-			if (count($cols) > 2) {
2348
-				array_pop($cols);
2349
-			}
2350
-			if ($t) {
2351
-				// la table est déjà dans le FROM, on vérifie si le champ est utilisé.
2352
-				$joindre = false;
2353
-				foreach ($cols as $col) {
2354
-					$c = '/\b' . $t . ".$col" . '\b/';
2355
-					if (trouver_champ($c, $boucle->where)) {
2356
-						$joindre = true;
2357
-					} else {
2358
-						// mais ca peut etre dans le FIELD pour le Having
2359
-						$c = "/FIELD.$t" . ".$col,/";
2360
-						if (trouver_champ($c, $boucle->select)) {
2361
-							$joindre = true;
2362
-						}
2363
-					}
2364
-				}
2365
-				if (!$joindre) {
2366
-					return $t;
2367
-				}
2368
-			}
2369
-			array_pop($arrivee);
2370
-			if ($res = calculer_jointure($boucle, [$boucle->id_table, $desc], $arrivee, $cols, $cond, 1)) {
2371
-				return $res;
2372
-			}
2373
-		}
2374
-	}
2375
-
2376
-	return '';
2326
+    // si on demande un truc du genre spip_mots
2327
+    // avec aussi spip_mots_liens dans les jointures dispo
2328
+    // et qu'on est la
2329
+    // il faut privilegier la jointure directe en 2 etapes spip_mots_liens, spip_mots
2330
+    if (
2331
+        $checkarrivee
2332
+        and is_string($checkarrivee)
2333
+        and $a = table_objet($checkarrivee)
2334
+        and in_array($a . '_liens', $joints)
2335
+    ) {
2336
+        if ($res = calculer_lien_externe_init($boucle, $joints, $col, $desc, $cond, $checkarrivee)) {
2337
+            return $res;
2338
+        }
2339
+    }
2340
+    foreach ($joints as $joint) {
2341
+        if ($arrivee = trouver_champ_exterieur($col, [$joint], $boucle, $checkarrivee)) {
2342
+            // alias de table dans le from
2343
+            $t = array_search($arrivee[0], $boucle->from);
2344
+            // recuperer la cle id_xx eventuellement decomposee en (id_objet,objet)
2345
+            $cols = $arrivee[2];
2346
+            // mais on ignore la 3eme cle si presente qui correspond alors au point de depart
2347
+            if (count($cols) > 2) {
2348
+                array_pop($cols);
2349
+            }
2350
+            if ($t) {
2351
+                // la table est déjà dans le FROM, on vérifie si le champ est utilisé.
2352
+                $joindre = false;
2353
+                foreach ($cols as $col) {
2354
+                    $c = '/\b' . $t . ".$col" . '\b/';
2355
+                    if (trouver_champ($c, $boucle->where)) {
2356
+                        $joindre = true;
2357
+                    } else {
2358
+                        // mais ca peut etre dans le FIELD pour le Having
2359
+                        $c = "/FIELD.$t" . ".$col,/";
2360
+                        if (trouver_champ($c, $boucle->select)) {
2361
+                            $joindre = true;
2362
+                        }
2363
+                    }
2364
+                }
2365
+                if (!$joindre) {
2366
+                    return $t;
2367
+                }
2368
+            }
2369
+            array_pop($arrivee);
2370
+            if ($res = calculer_jointure($boucle, [$boucle->id_table, $desc], $arrivee, $cols, $cond, 1)) {
2371
+                return $res;
2372
+            }
2373
+        }
2374
+    }
2375
+
2376
+    return '';
2377 2377
 }
2378 2378
 
2379 2379
 /**
@@ -2399,35 +2399,35 @@  discard block
 block discarded – undo
2399 2399
  *     Alias de la table de jointure (Lx)
2400 2400
  */
2401 2401
 function calculer_lien_externe_init(&$boucle, $joints, $col, $desc, $cond, $checkarrivee = false) {
2402
-	$primary_arrivee = id_table_objet($checkarrivee);
2403
-
2404
-	// [FIXME] $checkarrivee peut-il arriver avec false ????
2405
-	$intermediaire = trouver_champ_exterieur($primary_arrivee, $joints, $boucle, $checkarrivee . '_liens');
2406
-	$arrivee = trouver_champ_exterieur($col, $joints, $boucle, $checkarrivee);
2407
-
2408
-	if (!$intermediaire or !$arrivee) {
2409
-		return '';
2410
-	}
2411
-	array_pop($intermediaire); // enlever la cle en 3eme argument
2412
-	array_pop($arrivee); // enlever la cle en 3eme argument
2413
-
2414
-	$res = fabrique_jointures(
2415
-		$boucle,
2416
-		[
2417
-			[
2418
-				$boucle->id_table,
2419
-				$intermediaire,
2420
-				[id_table_objet($desc['table_objet']), 'id_objet', 'objet', $desc['type']]
2421
-			],
2422
-			[reset($intermediaire), $arrivee, $primary_arrivee]
2423
-		],
2424
-		$cond,
2425
-		$desc,
2426
-		$boucle->id_table,
2427
-		[$col]
2428
-	);
2429
-
2430
-	return $res;
2402
+    $primary_arrivee = id_table_objet($checkarrivee);
2403
+
2404
+    // [FIXME] $checkarrivee peut-il arriver avec false ????
2405
+    $intermediaire = trouver_champ_exterieur($primary_arrivee, $joints, $boucle, $checkarrivee . '_liens');
2406
+    $arrivee = trouver_champ_exterieur($col, $joints, $boucle, $checkarrivee);
2407
+
2408
+    if (!$intermediaire or !$arrivee) {
2409
+        return '';
2410
+    }
2411
+    array_pop($intermediaire); // enlever la cle en 3eme argument
2412
+    array_pop($arrivee); // enlever la cle en 3eme argument
2413
+
2414
+    $res = fabrique_jointures(
2415
+        $boucle,
2416
+        [
2417
+            [
2418
+                $boucle->id_table,
2419
+                $intermediaire,
2420
+                [id_table_objet($desc['table_objet']), 'id_objet', 'objet', $desc['type']]
2421
+            ],
2422
+            [reset($intermediaire), $arrivee, $primary_arrivee]
2423
+        ],
2424
+        $cond,
2425
+        $desc,
2426
+        $boucle->id_table,
2427
+        [$col]
2428
+    );
2429
+
2430
+    return $res;
2431 2431
 }
2432 2432
 
2433 2433
 
@@ -2444,17 +2444,17 @@  discard block
 block discarded – undo
2444 2444
  *     false sinon.
2445 2445
  **/
2446 2446
 function trouver_champ($champ, $where) {
2447
-	if (!is_array($where)) {
2448
-		return preg_match($champ, $where);
2449
-	} else {
2450
-		foreach ($where as $clause) {
2451
-			if (trouver_champ($champ, $clause)) {
2452
-				return true;
2453
-			}
2454
-		}
2455
-
2456
-		return false;
2457
-	}
2447
+    if (!is_array($where)) {
2448
+        return preg_match($champ, $where);
2449
+    } else {
2450
+        foreach ($where as $clause) {
2451
+            if (trouver_champ($champ, $clause)) {
2452
+                return true;
2453
+            }
2454
+        }
2455
+
2456
+        return false;
2457
+    }
2458 2458
 }
2459 2459
 
2460 2460
 
@@ -2480,130 +2480,130 @@  discard block
 block discarded – undo
2480 2480
  *     - string $args_sql  Suite des arguments du critère. ?
2481 2481
  **/
2482 2482
 function calculer_critere_infixe_ops($idb, &$boucles, $crit) {
2483
-	// cas d'une valeur comparee a elle-meme ou son referent
2484
-	if (count($crit->param) == 0) {
2485
-		$op = '=';
2486
-		$col = $val = $crit->op;
2487
-		if (preg_match('/^(.*)\.(.*)$/', $col, $r)) {
2488
-			$val = $r[2];
2489
-		}
2490
-		// Cas special {lang} : aller chercher $GLOBALS['spip_lang']
2491
-		if ($val == 'lang') {
2492
-			$val = [kwote('$GLOBALS[\'spip_lang\']')];
2493
-		} else {
2494
-			$defaut = null;
2495
-			if ($val == 'id_parent') {
2496
-				// Si id_parent, comparer l'id_parent avec l'id_objet
2497
-				// de la boucle superieure.... faudrait verifier qu'il existe
2498
-				// pour eviter l'erreur SQL
2499
-				$val = $boucles[$idb]->primary;
2500
-				// mais si pas de boucle superieure, prendre id_parent dans l'env
2501
-				$defaut = "(\$Pile[0]['id_parent'] ?? null)";
2502
-			} elseif ($val == 'id_enfant') {
2503
-				// Si id_enfant, comparer l'id_objet avec l'id_parent
2504
-				// de la boucle superieure
2505
-				$val = 'id_parent';
2506
-			} elseif ($crit->cond and ($col == 'date' or $col == 'date_redac')) {
2507
-				// un critere conditionnel sur date est traite a part
2508
-				// car la date est mise d'office par SPIP,
2509
-				$defaut = "(\$Pile[0]['{$col}_default']?'':\$Pile[0]['" . $col . "'])";
2510
-			}
2511
-
2512
-			$val = calculer_argument_precedent($idb, $val, $boucles, $defaut);
2513
-			$val = [kwote($val)];
2514
-		}
2515
-	} else {
2516
-		// comparaison explicite
2517
-		// le phraseur impose que le premier param soit du texte
2518
-		$params = $crit->param;
2519
-		$op = $crit->op;
2520
-		if ($op == '==') {
2521
-			$op = 'REGEXP';
2522
-		}
2523
-		$col = array_shift($params);
2524
-		$col = $col[0]->texte;
2525
-
2526
-		$val = [];
2527
-		$parent = $boucles[$idb]->id_parent;
2528
-
2529
-		// Dans le cas {x=='#DATE'} etc, defaire le travail du phraseur,
2530
-		// celui ne sachant pas ce qu'est un critere infixe
2531
-		// et a fortiori son 2e operande qu'entoure " ou '
2532
-		if (
2533
-			count($params) == 1
2534
-			and count($params[0]) == 3
2535
-			and $params[0][0]->type == 'texte'
2536
-			and $params[0][2]->type == 'texte'
2537
-			and ($p = $params[0][0]->texte) == $params[0][2]->texte
2538
-			and (($p == "'") or ($p == '"'))
2539
-			and $params[0][1]->type == 'champ'
2540
-		) {
2541
-			$val[] = "$p\\$p#" . $params[0][1]->nom_champ . "\\$p$p";
2542
-		} else {
2543
-			foreach ((($op != 'IN') ? $params : calculer_vieux_in($params)) as $p) {
2544
-				$a = calculer_liste($p, $idb, $boucles, $parent);
2545
-				if (strcasecmp($op, 'IN') == 0) {
2546
-					$val[] = $a;
2547
-				} else {
2548
-					$val[] = kwote($a, $boucles[$idb]->sql_serveur, '@@defaultcast@@');
2549
-				} // toujours quoter en char ici
2550
-			}
2551
-		}
2552
-	}
2553
-
2554
-	$fct = $args_sql = '';
2555
-	// fonction SQL ?
2556
-	// chercher FONCTION(champ) tel que CONCAT(titre,descriptif)
2557
-	if (preg_match('/^(.*)' . SQL_ARGS . '$/', $col, $m)) {
2558
-		$fct = $m[1];
2559
-		preg_match('/^\(([^,]*)(.*)\)$/', $m[2], $a);
2560
-		$col = $a[1];
2561
-		if (preg_match('/^(\S*)(\s+AS\s+.*)$/i', $col, $m)) {
2562
-			$col = $m[1];
2563
-			$args_sql = $m[2];
2564
-		}
2565
-		$args_sql .= $a[2];
2566
-	}
2567
-
2568
-	return [$fct, $col, $op, $val, $args_sql];
2483
+    // cas d'une valeur comparee a elle-meme ou son referent
2484
+    if (count($crit->param) == 0) {
2485
+        $op = '=';
2486
+        $col = $val = $crit->op;
2487
+        if (preg_match('/^(.*)\.(.*)$/', $col, $r)) {
2488
+            $val = $r[2];
2489
+        }
2490
+        // Cas special {lang} : aller chercher $GLOBALS['spip_lang']
2491
+        if ($val == 'lang') {
2492
+            $val = [kwote('$GLOBALS[\'spip_lang\']')];
2493
+        } else {
2494
+            $defaut = null;
2495
+            if ($val == 'id_parent') {
2496
+                // Si id_parent, comparer l'id_parent avec l'id_objet
2497
+                // de la boucle superieure.... faudrait verifier qu'il existe
2498
+                // pour eviter l'erreur SQL
2499
+                $val = $boucles[$idb]->primary;
2500
+                // mais si pas de boucle superieure, prendre id_parent dans l'env
2501
+                $defaut = "(\$Pile[0]['id_parent'] ?? null)";
2502
+            } elseif ($val == 'id_enfant') {
2503
+                // Si id_enfant, comparer l'id_objet avec l'id_parent
2504
+                // de la boucle superieure
2505
+                $val = 'id_parent';
2506
+            } elseif ($crit->cond and ($col == 'date' or $col == 'date_redac')) {
2507
+                // un critere conditionnel sur date est traite a part
2508
+                // car la date est mise d'office par SPIP,
2509
+                $defaut = "(\$Pile[0]['{$col}_default']?'':\$Pile[0]['" . $col . "'])";
2510
+            }
2511
+
2512
+            $val = calculer_argument_precedent($idb, $val, $boucles, $defaut);
2513
+            $val = [kwote($val)];
2514
+        }
2515
+    } else {
2516
+        // comparaison explicite
2517
+        // le phraseur impose que le premier param soit du texte
2518
+        $params = $crit->param;
2519
+        $op = $crit->op;
2520
+        if ($op == '==') {
2521
+            $op = 'REGEXP';
2522
+        }
2523
+        $col = array_shift($params);
2524
+        $col = $col[0]->texte;
2525
+
2526
+        $val = [];
2527
+        $parent = $boucles[$idb]->id_parent;
2528
+
2529
+        // Dans le cas {x=='#DATE'} etc, defaire le travail du phraseur,
2530
+        // celui ne sachant pas ce qu'est un critere infixe
2531
+        // et a fortiori son 2e operande qu'entoure " ou '
2532
+        if (
2533
+            count($params) == 1
2534
+            and count($params[0]) == 3
2535
+            and $params[0][0]->type == 'texte'
2536
+            and $params[0][2]->type == 'texte'
2537
+            and ($p = $params[0][0]->texte) == $params[0][2]->texte
2538
+            and (($p == "'") or ($p == '"'))
2539
+            and $params[0][1]->type == 'champ'
2540
+        ) {
2541
+            $val[] = "$p\\$p#" . $params[0][1]->nom_champ . "\\$p$p";
2542
+        } else {
2543
+            foreach ((($op != 'IN') ? $params : calculer_vieux_in($params)) as $p) {
2544
+                $a = calculer_liste($p, $idb, $boucles, $parent);
2545
+                if (strcasecmp($op, 'IN') == 0) {
2546
+                    $val[] = $a;
2547
+                } else {
2548
+                    $val[] = kwote($a, $boucles[$idb]->sql_serveur, '@@defaultcast@@');
2549
+                } // toujours quoter en char ici
2550
+            }
2551
+        }
2552
+    }
2553
+
2554
+    $fct = $args_sql = '';
2555
+    // fonction SQL ?
2556
+    // chercher FONCTION(champ) tel que CONCAT(titre,descriptif)
2557
+    if (preg_match('/^(.*)' . SQL_ARGS . '$/', $col, $m)) {
2558
+        $fct = $m[1];
2559
+        preg_match('/^\(([^,]*)(.*)\)$/', $m[2], $a);
2560
+        $col = $a[1];
2561
+        if (preg_match('/^(\S*)(\s+AS\s+.*)$/i', $col, $m)) {
2562
+            $col = $m[1];
2563
+            $args_sql = $m[2];
2564
+        }
2565
+        $args_sql .= $a[2];
2566
+    }
2567
+
2568
+    return [$fct, $col, $op, $val, $args_sql];
2569 2569
 }
2570 2570
 
2571 2571
 // compatibilite ancienne version
2572 2572
 
2573 2573
 // https://code.spip.net/@calculer_vieux_in
2574 2574
 function calculer_vieux_in($params) {
2575
-	$deb = $params[0][0];
2576
-	$k = count($params) - 1;
2577
-	$last = $params[$k];
2578
-	$j = count($last) - 1;
2579
-	$last = $last[$j];
2580
-	$n = isset($last->texte) ? strlen($last->texte) : 0;
2581
-
2582
-	if (
2583
-		!((isset($deb->texte[0]) and $deb->texte[0] == '(')
2584
-		&& (isset($last->texte[$n - 1]) and $last->texte[$n - 1] == ')'))
2585
-	) {
2586
-		return $params;
2587
-	}
2588
-	$params[0][0]->texte = substr($deb->texte, 1);
2589
-	// attention, on peut avoir k=0,j=0 ==> recalculer
2590
-	$last = $params[$k][$j];
2591
-	$n = strlen($last->texte);
2592
-	$params[$k][$j]->texte = substr($last->texte, 0, $n - 1);
2593
-	$newp = [];
2594
-	foreach ($params as $v) {
2595
-		if ($v[0]->type != 'texte') {
2596
-			$newp[] = $v;
2597
-		} else {
2598
-			foreach (explode(',', $v[0]->texte) as $x) {
2599
-				$t = new Texte();
2600
-				$t->texte = $x;
2601
-				$newp[] = [$t];
2602
-			}
2603
-		}
2604
-	}
2605
-
2606
-	return $newp;
2575
+    $deb = $params[0][0];
2576
+    $k = count($params) - 1;
2577
+    $last = $params[$k];
2578
+    $j = count($last) - 1;
2579
+    $last = $last[$j];
2580
+    $n = isset($last->texte) ? strlen($last->texte) : 0;
2581
+
2582
+    if (
2583
+        !((isset($deb->texte[0]) and $deb->texte[0] == '(')
2584
+        && (isset($last->texte[$n - 1]) and $last->texte[$n - 1] == ')'))
2585
+    ) {
2586
+        return $params;
2587
+    }
2588
+    $params[0][0]->texte = substr($deb->texte, 1);
2589
+    // attention, on peut avoir k=0,j=0 ==> recalculer
2590
+    $last = $params[$k][$j];
2591
+    $n = strlen($last->texte);
2592
+    $params[$k][$j]->texte = substr($last->texte, 0, $n - 1);
2593
+    $newp = [];
2594
+    foreach ($params as $v) {
2595
+        if ($v[0]->type != 'texte') {
2596
+            $newp[] = $v;
2597
+        } else {
2598
+            foreach (explode(',', $v[0]->texte) as $x) {
2599
+                $t = new Texte();
2600
+                $t->texte = $x;
2601
+                $newp[] = [$t];
2602
+            }
2603
+        }
2604
+    }
2605
+
2606
+    return $newp;
2607 2607
 }
2608 2608
 
2609 2609
 /**
@@ -2622,89 +2622,89 @@  discard block
 block discarded – undo
2622 2622
  *     - nom de la colonne de date (si le calcul n'est pas relatif)
2623 2623
  **/
2624 2624
 function calculer_critere_infixe_date($idb, &$boucles, $col) {
2625
-	if (!preg_match(',^((age|jour|mois|annee)_relatif|date|mois|annee|jour|heure|age)(_[a-z_]+)?$,', $col, $regs)) {
2626
-		return '';
2627
-	}
2628
-
2629
-	$boucle = $boucles[$idb];
2630
-	$table = $boucle->show;
2631
-
2632
-	// si c'est une colonne de la table, ne rien faire
2633
-	if (isset($table['field'][$col])) {
2634
-		return '';
2635
-	}
2636
-
2637
-	if (!$table['date'] && !isset($GLOBALS['table_date'][$table['id_table']])) {
2638
-		return '';
2639
-	}
2640
-	$pred = $date_orig = isset($GLOBALS['table_date'][$table['id_table']]) ? $GLOBALS['table_date'][$table['id_table']] : $table['date'];
2641
-
2642
-	$col = $regs[1];
2643
-	if (isset($regs[3]) and $suite = $regs[3]) {
2644
-		# Recherche de l'existence du champ date_xxxx,
2645
-		# si oui choisir ce champ, sinon choisir xxxx
2646
-
2647
-		if (isset($table['field']["date$suite"])) {
2648
-			$date_orig = 'date' . $suite;
2649
-		} else {
2650
-			$date_orig = substr($suite, 1);
2651
-		}
2652
-		$pred = $date_orig;
2653
-	} else {
2654
-		if (isset($regs[2]) and $rel = $regs[2]) {
2655
-			$pred = 'date';
2656
-		}
2657
-	}
2658
-
2659
-	$date_compare = "\"' . normaliser_date(" .
2660
-		calculer_argument_precedent($idb, $pred, $boucles) .
2661
-		") . '\"";
2662
-
2663
-	$col_vraie = $date_orig;
2664
-	$date_orig = $boucle->id_table . '.' . $date_orig;
2665
-
2666
-	switch ($col) {
2667
-		case 'date':
2668
-			$col = $date_orig;
2669
-			break;
2670
-		case 'jour':
2671
-			$col = "DAYOFMONTH($date_orig)";
2672
-			break;
2673
-		case 'mois':
2674
-			$col = "MONTH($date_orig)";
2675
-			break;
2676
-		case 'annee':
2677
-			$col = "YEAR($date_orig)";
2678
-			break;
2679
-		case 'heure':
2680
-			$col = "DATE_FORMAT($date_orig, \\'%H:%i\\')";
2681
-			break;
2682
-		case 'age':
2683
-			$col = calculer_param_date("\'' . date('Y-m-d H:i:00') . '\'", $date_orig);
2684
-			$col_vraie = '';// comparer a un int (par defaut)
2685
-			break;
2686
-		case 'age_relatif':
2687
-			$col = calculer_param_date($date_compare, $date_orig);
2688
-			$col_vraie = '';// comparer a un int (par defaut)
2689
-			break;
2690
-		case 'jour_relatif':
2691
-			$col = '(TO_DAYS(' . $date_compare . ')-TO_DAYS(' . $date_orig . '))';
2692
-			$col_vraie = '';// comparer a un int (par defaut)
2693
-			break;
2694
-		case 'mois_relatif':
2695
-			$col = 'MONTH(' . $date_compare . ')-MONTH(' .
2696
-				$date_orig . ')+12*(YEAR(' . $date_compare .
2697
-				')-YEAR(' . $date_orig . '))';
2698
-			$col_vraie = '';// comparer a un int (par defaut)
2699
-			break;
2700
-		case 'annee_relatif':
2701
-			$col = 'YEAR(' . $date_compare . ')-YEAR(' .
2702
-				$date_orig . ')';
2703
-			$col_vraie = '';// comparer a un int (par defaut)
2704
-			break;
2705
-	}
2706
-
2707
-	return [$col, $col_vraie];
2625
+    if (!preg_match(',^((age|jour|mois|annee)_relatif|date|mois|annee|jour|heure|age)(_[a-z_]+)?$,', $col, $regs)) {
2626
+        return '';
2627
+    }
2628
+
2629
+    $boucle = $boucles[$idb];
2630
+    $table = $boucle->show;
2631
+
2632
+    // si c'est une colonne de la table, ne rien faire
2633
+    if (isset($table['field'][$col])) {
2634
+        return '';
2635
+    }
2636
+
2637
+    if (!$table['date'] && !isset($GLOBALS['table_date'][$table['id_table']])) {
2638
+        return '';
2639
+    }
2640
+    $pred = $date_orig = isset($GLOBALS['table_date'][$table['id_table']]) ? $GLOBALS['table_date'][$table['id_table']] : $table['date'];
2641
+
2642
+    $col = $regs[1];
2643
+    if (isset($regs[3]) and $suite = $regs[3]) {
2644
+        # Recherche de l'existence du champ date_xxxx,
2645
+        # si oui choisir ce champ, sinon choisir xxxx
2646
+
2647
+        if (isset($table['field']["date$suite"])) {
2648
+            $date_orig = 'date' . $suite;
2649
+        } else {
2650
+            $date_orig = substr($suite, 1);
2651
+        }
2652
+        $pred = $date_orig;
2653
+    } else {
2654
+        if (isset($regs[2]) and $rel = $regs[2]) {
2655
+            $pred = 'date';
2656
+        }
2657
+    }
2658
+
2659
+    $date_compare = "\"' . normaliser_date(" .
2660
+        calculer_argument_precedent($idb, $pred, $boucles) .
2661
+        ") . '\"";
2662
+
2663
+    $col_vraie = $date_orig;
2664
+    $date_orig = $boucle->id_table . '.' . $date_orig;
2665
+
2666
+    switch ($col) {
2667
+        case 'date':
2668
+            $col = $date_orig;
2669
+            break;
2670
+        case 'jour':
2671
+            $col = "DAYOFMONTH($date_orig)";
2672
+            break;
2673
+        case 'mois':
2674
+            $col = "MONTH($date_orig)";
2675
+            break;
2676
+        case 'annee':
2677
+            $col = "YEAR($date_orig)";
2678
+            break;
2679
+        case 'heure':
2680
+            $col = "DATE_FORMAT($date_orig, \\'%H:%i\\')";
2681
+            break;
2682
+        case 'age':
2683
+            $col = calculer_param_date("\'' . date('Y-m-d H:i:00') . '\'", $date_orig);
2684
+            $col_vraie = '';// comparer a un int (par defaut)
2685
+            break;
2686
+        case 'age_relatif':
2687
+            $col = calculer_param_date($date_compare, $date_orig);
2688
+            $col_vraie = '';// comparer a un int (par defaut)
2689
+            break;
2690
+        case 'jour_relatif':
2691
+            $col = '(TO_DAYS(' . $date_compare . ')-TO_DAYS(' . $date_orig . '))';
2692
+            $col_vraie = '';// comparer a un int (par defaut)
2693
+            break;
2694
+        case 'mois_relatif':
2695
+            $col = 'MONTH(' . $date_compare . ')-MONTH(' .
2696
+                $date_orig . ')+12*(YEAR(' . $date_compare .
2697
+                ')-YEAR(' . $date_orig . '))';
2698
+            $col_vraie = '';// comparer a un int (par defaut)
2699
+            break;
2700
+        case 'annee_relatif':
2701
+            $col = 'YEAR(' . $date_compare . ')-YEAR(' .
2702
+                $date_orig . ')';
2703
+            $col_vraie = '';// comparer a un int (par defaut)
2704
+            break;
2705
+    }
2706
+
2707
+    return [$col, $col_vraie];
2708 2708
 }
2709 2709
 
2710 2710
 /**
@@ -2723,16 +2723,16 @@  discard block
 block discarded – undo
2723 2723
  *     de colonne SQL et une date.
2724 2724
  **/
2725 2725
 function calculer_param_date($date_compare, $date_orig) {
2726
-	if (preg_match(",'\" *\.(.*)\. *\"',", $date_compare, $r)) {
2727
-		$init = "'\" . (\$x = $r[1]) . \"'";
2728
-		$date_compare = '\'$x\'';
2729
-	} else {
2730
-		$init = $date_compare;
2731
-	}
2732
-
2733
-	return
2734
-		// optimisation : mais prevoir le support SQLite avant
2735
-		"TIMESTAMPDIFF(HOUR,$date_orig,$init)/24";
2726
+    if (preg_match(",'\" *\.(.*)\. *\"',", $date_compare, $r)) {
2727
+        $init = "'\" . (\$x = $r[1]) . \"'";
2728
+        $date_compare = '\'$x\'';
2729
+    } else {
2730
+        $init = $date_compare;
2731
+    }
2732
+
2733
+    return
2734
+        // optimisation : mais prevoir le support SQLite avant
2735
+        "TIMESTAMPDIFF(HOUR,$date_orig,$init)/24";
2736 2736
 }
2737 2737
 
2738 2738
 /**
@@ -2750,20 +2750,20 @@  discard block
 block discarded – undo
2750 2750
  * @param Critere $crit Paramètres du critère dans cette boucle
2751 2751
  */
2752 2752
 function critere_DATA_source_dist($idb, &$boucles, $crit) {
2753
-	$boucle = &$boucles[$idb];
2754
-
2755
-	$args = [];
2756
-	foreach ($crit->param as &$param) {
2757
-		array_push(
2758
-			$args,
2759
-			calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent)
2760
-		);
2761
-	}
2753
+    $boucle = &$boucles[$idb];
2762 2754
 
2763
-	$boucle->hash .= '
2755
+    $args = [];
2756
+    foreach ($crit->param as &$param) {
2757
+        array_push(
2758
+            $args,
2759
+            calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent)
2760
+        );
2761
+    }
2762
+
2763
+    $boucle->hash .= '
2764 2764
 	$command[\'sourcemode\'] = ' . array_shift($args) . ";\n";
2765 2765
 
2766
-	$boucle->hash .= '
2766
+    $boucle->hash .= '
2767 2767
 	$command[\'source\'] = array(' . join(', ', $args) . ");\n";
2768 2768
 }
2769 2769
 
@@ -2781,8 +2781,8 @@  discard block
 block discarded – undo
2781 2781
  * @param Critere $crit Paramètres du critère dans cette boucle
2782 2782
  */
2783 2783
 function critere_DATA_datacache_dist($idb, &$boucles, $crit) {
2784
-	$boucle = &$boucles[$idb];
2785
-	$boucle->hash .= '
2784
+    $boucle = &$boucles[$idb];
2785
+    $boucle->hash .= '
2786 2786
 	$command[\'datacache\'] = ' . calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent) . ';';
2787 2787
 }
2788 2788
 
@@ -2798,12 +2798,12 @@  discard block
 block discarded – undo
2798 2798
  * @param Critere $crit Paramètres du critère dans cette boucle
2799 2799
  */
2800 2800
 function critere_php_args_dist($idb, &$boucles, $crit) {
2801
-	$boucle = &$boucles[$idb];
2802
-	$boucle->hash .= '$command[\'args\']=array();';
2803
-	foreach ($crit->param as $param) {
2804
-		$boucle->hash .= '
2801
+    $boucle = &$boucles[$idb];
2802
+    $boucle->hash .= '$command[\'args\']=array();';
2803
+    foreach ($crit->param as $param) {
2804
+        $boucle->hash .= '
2805 2805
 			$command[\'args\'][] = ' . calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent) . ';';
2806
-	}
2806
+    }
2807 2807
 }
2808 2808
 
2809 2809
 /**
@@ -2820,16 +2820,16 @@  discard block
 block discarded – undo
2820 2820
  * @param Critere $crit Paramètres du critère dans cette boucle
2821 2821
  */
2822 2822
 function critere_DATA_liste_dist($idb, &$boucles, $crit) {
2823
-	$boucle = &$boucles[$idb];
2824
-	$boucle->hash .= "\n\t" . '$command[\'liste\'] = array();' . "\n";
2825
-	foreach ($crit->param as $param) {
2826
-		$boucle->hash .= "\t" . '$command[\'liste\'][] = ' . calculer_liste(
2827
-			$param,
2828
-			$idb,
2829
-			$boucles,
2830
-			$boucles[$idb]->id_parent
2831
-		) . ";\n";
2832
-	}
2823
+    $boucle = &$boucles[$idb];
2824
+    $boucle->hash .= "\n\t" . '$command[\'liste\'] = array();' . "\n";
2825
+    foreach ($crit->param as $param) {
2826
+        $boucle->hash .= "\t" . '$command[\'liste\'][] = ' . calculer_liste(
2827
+            $param,
2828
+            $idb,
2829
+            $boucles,
2830
+            $boucles[$idb]->id_parent
2831
+        ) . ";\n";
2832
+    }
2833 2833
 }
2834 2834
 
2835 2835
 /**
@@ -2854,16 +2854,16 @@  discard block
 block discarded – undo
2854 2854
  * @param Critere $crit Paramètres du critère dans cette boucle
2855 2855
  */
2856 2856
 function critere_DATA_enum_dist($idb, &$boucles, $crit) {
2857
-	$boucle = &$boucles[$idb];
2858
-	$boucle->hash .= "\n\t" . '$command[\'enum\'] = array();' . "\n";
2859
-	foreach ($crit->param as $param) {
2860
-		$boucle->hash .= "\t" . '$command[\'enum\'][] = ' . calculer_liste(
2861
-			$param,
2862
-			$idb,
2863
-			$boucles,
2864
-			$boucles[$idb]->id_parent
2865
-		) . ";\n";
2866
-	}
2857
+    $boucle = &$boucles[$idb];
2858
+    $boucle->hash .= "\n\t" . '$command[\'enum\'] = array();' . "\n";
2859
+    foreach ($crit->param as $param) {
2860
+        $boucle->hash .= "\t" . '$command[\'enum\'][] = ' . calculer_liste(
2861
+            $param,
2862
+            $idb,
2863
+            $boucles,
2864
+            $boucles[$idb]->id_parent
2865
+        ) . ";\n";
2866
+    }
2867 2867
 }
2868 2868
 
2869 2869
 /**
@@ -2878,11 +2878,11 @@  discard block
 block discarded – undo
2878 2878
  * @param Critere $crit Paramètres du critère dans cette boucle
2879 2879
  */
2880 2880
 function critere_DATA_datapath_dist($idb, &$boucles, $crit) {
2881
-	$boucle = &$boucles[$idb];
2882
-	foreach ($crit->param as $param) {
2883
-		$boucle->hash .= '
2881
+    $boucle = &$boucles[$idb];
2882
+    foreach ($crit->param as $param) {
2883
+        $boucle->hash .= '
2884 2884
 			$command[\'datapath\'][] = ' . calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent) . ';';
2885
-	}
2885
+    }
2886 2886
 }
2887 2887
 
2888 2888
 
@@ -2914,20 +2914,20 @@  discard block
 block discarded – undo
2914 2914
  * @param Critere $crit Paramètres du critère dans cette boucle
2915 2915
  */
2916 2916
 function critere_si_dist($idb, &$boucles, $crit) {
2917
-	$boucle = &$boucles[$idb];
2918
-	// il faut initialiser 1 fois le tableau a chaque appel de la boucle
2919
-	// (par exemple lorsque notre boucle est appelee dans une autre boucle)
2920
-	// mais ne pas l'initialiser n fois si il y a n criteres {si } dans la boucle !
2921
-	$boucle->hash .= "\n\tif (!isset(\$si_init)) { \$command['si'] = array(); \$si_init = true; }\n";
2922
-	if ($crit->param) {
2923
-		foreach ($crit->param as $param) {
2924
-			$boucle->hash .= "\t\$command['si'][] = "
2925
-				. calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent) . ";\n";
2926
-		}
2927
-		// interdire {si 0} aussi !
2928
-	} else {
2929
-		$boucle->hash .= '$command[\'si\'][] = 0;';
2930
-	}
2917
+    $boucle = &$boucles[$idb];
2918
+    // il faut initialiser 1 fois le tableau a chaque appel de la boucle
2919
+    // (par exemple lorsque notre boucle est appelee dans une autre boucle)
2920
+    // mais ne pas l'initialiser n fois si il y a n criteres {si } dans la boucle !
2921
+    $boucle->hash .= "\n\tif (!isset(\$si_init)) { \$command['si'] = array(); \$si_init = true; }\n";
2922
+    if ($crit->param) {
2923
+        foreach ($crit->param as $param) {
2924
+            $boucle->hash .= "\t\$command['si'][] = "
2925
+                . calculer_liste($param, $idb, $boucles, $boucles[$idb]->id_parent) . ";\n";
2926
+        }
2927
+        // interdire {si 0} aussi !
2928
+    } else {
2929
+        $boucle->hash .= '$command[\'si\'][] = 0;';
2930
+    }
2931 2931
 }
2932 2932
 
2933 2933
 /**
@@ -2944,8 +2944,8 @@  discard block
 block discarded – undo
2944 2944
  * @param Critere $crit Paramètres du critère dans cette boucle
2945 2945
  */
2946 2946
 function critere_POUR_tableau_dist($idb, &$boucles, $crit) {
2947
-	$boucle = &$boucles[$idb];
2948
-	$boucle->hash .= '
2947
+    $boucle = &$boucles[$idb];
2948
+    $boucle->hash .= '
2949 2949
 	$command[\'source\'] = array(' . calculer_liste($crit->param[0], $idb, $boucles, $boucles[$idb]->id_parent) . ');
2950 2950
 	$command[\'sourcemode\'] = \'table\';';
2951 2951
 }
@@ -2966,29 +2966,29 @@  discard block
 block discarded – undo
2966 2966
  */
2967 2967
 function critere_noeud_dist($idb, &$boucles, $crit) {
2968 2968
 
2969
-	$not = $crit->not;
2970
-	$boucle = &$boucles[$idb];
2971
-	$primary = $boucle->primary;
2969
+    $not = $crit->not;
2970
+    $boucle = &$boucles[$idb];
2971
+    $primary = $boucle->primary;
2972 2972
 
2973
-	if (!$primary or strpos($primary, ',')) {
2974
-		erreur_squelette(_T('zbug_doublon_sur_table_sans_cle_primaire'), $boucle);
2973
+    if (!$primary or strpos($primary, ',')) {
2974
+        erreur_squelette(_T('zbug_doublon_sur_table_sans_cle_primaire'), $boucle);
2975 2975
 
2976
-		return;
2977
-	}
2978
-	$table = $boucle->type_requete;
2979
-	$table_sql = table_objet_sql(objet_type($table));
2976
+        return;
2977
+    }
2978
+    $table = $boucle->type_requete;
2979
+    $table_sql = table_objet_sql(objet_type($table));
2980 2980
 
2981
-	$id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
2982
-		$GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
2983
-		'id_parent';
2981
+    $id_parent = isset($GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent']) ?
2982
+        $GLOBALS['exceptions_des_tables'][$boucle->id_table]['id_parent'] :
2983
+        'id_parent';
2984 2984
 
2985
-	$in = 'IN';
2986
-	$where = ["'IN'", "'$boucle->id_table." . "$primary'", "'('.sql_get_select('$id_parent', '$table_sql').')'"];
2987
-	if ($not) {
2988
-		$where = ["'NOT'", $where];
2989
-	}
2985
+    $in = 'IN';
2986
+    $where = ["'IN'", "'$boucle->id_table." . "$primary'", "'('.sql_get_select('$id_parent', '$table_sql').')'"];
2987
+    if ($not) {
2988
+        $where = ["'NOT'", $where];
2989
+    }
2990 2990
 
2991
-	$boucle->where[] = $where;
2991
+    $boucle->where[] = $where;
2992 2992
 }
2993 2993
 
2994 2994
 /**
@@ -3004,8 +3004,8 @@  discard block
 block discarded – undo
3004 3004
  * @param Critere $crit Paramètres du critère dans cette boucle
3005 3005
  */
3006 3006
 function critere_feuille_dist($idb, &$boucles, $crit) {
3007
-	$not = $crit->not;
3008
-	$crit->not = $not ? false : true;
3009
-	critere_noeud_dist($idb, $boucles, $crit);
3010
-	$crit->not = $not;
3007
+    $not = $crit->not;
3008
+    $crit->not = $not ? false : true;
3009
+    critere_noeud_dist($idb, $boucles, $crit);
3010
+    $crit->not = $not;
3011 3011
 }
Please login to merge, or discard this patch.
ecrire/public/iterateur.php 1 patch
Indentation   +655 added lines, -655 removed lines patch added patch discarded remove patch
@@ -11,7 +11,7 @@  discard block
 block discarded – undo
11 11
 \***************************************************************************/
12 12
 
13 13
 if (!defined('_ECRIRE_INC_VERSION')) {
14
-	return;
14
+    return;
15 15
 }
16 16
 
17 17
 /**
@@ -21,668 +21,668 @@  discard block
 block discarded – undo
21 21
  *
22 22
  */
23 23
 class IterFactory {
24
-	public static function create($iterateur, $command, $info = null) {
25
-
26
-		// cas des SI {si expression} analises tres tot
27
-		// pour eviter le chargement de tout iterateur
28
-		if (isset($command['si'])) {
29
-			foreach ($command['si'] as $si) {
30
-				if (!$si) {
31
-					// $command pour boucle SQL peut generer des erreurs de compilation
32
-					// s'il est transmis alors qu'on est dans un iterateur vide
33
-					return new IterDecorator(new EmptyIterator(), [], $info);
34
-				}
35
-			}
36
-		}
37
-
38
-		// chercher un iterateur PHP existant (par exemple dans SPL)
39
-		// (il faudrait passer l'argument ->sql_serveur
40
-		// pour etre certain qu'on est sur un "php:")
41
-		if (class_exists($iterateur)) {
42
-			$a = isset($command['args']) ? $command['args'] : [];
43
-
44
-			// permettre de passer un Iterateur directement {args #ITERATEUR} :
45
-			// si on recoit deja un iterateur en argument, on l'utilise
46
-			if (count($a) == 1 and is_object($a[0]) and is_subclass_of($a[0], 'Iterator')) {
47
-				$iter = $a[0];
48
-
49
-				// sinon, on cree un iterateur du type donne
50
-			} else {
51
-				// arguments de creation de l'iterateur...
52
-				// (pas glop)
53
-				try {
54
-					switch (count($a)) {
55
-						case 0:
56
-							$iter = new $iterateur();
57
-							break;
58
-						case 1:
59
-							$iter = new $iterateur($a[0]);
60
-							break;
61
-						case 2:
62
-							$iter = new $iterateur($a[0], $a[1]);
63
-							break;
64
-						case 3:
65
-							$iter = new $iterateur($a[0], $a[1], $a[2]);
66
-							break;
67
-						case 4:
68
-							$iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
69
-							break;
70
-					}
71
-				} catch (Exception $e) {
72
-					spip_log("Erreur de chargement de l'iterateur $iterateur");
73
-					spip_log($e->getMessage());
74
-					$iter = new EmptyIterator();
75
-				}
76
-			}
77
-		} else {
78
-			// chercher la classe d'iterateur
79
-			// IterateurXXX
80
-			// definie dans le fichier iterateurs/xxx.php
81
-			$class = 'Iterateur' . $iterateur;
82
-			if (!class_exists($class)) {
83
-				if (
84
-					!include_spip('iterateur/' . strtolower($iterateur))
85
-					or !class_exists($class)
86
-				) {
87
-					die("Iterateur $iterateur non trouv&#233;");
88
-					// si l'iterateur n'existe pas, on se rabat sur le generique
89
-					# $iter = new EmptyIterator();
90
-				}
91
-			}
92
-			$iter = new $class($command, $info);
93
-		}
94
-
95
-		return new IterDecorator($iter, $command, $info);
96
-	}
24
+    public static function create($iterateur, $command, $info = null) {
25
+
26
+        // cas des SI {si expression} analises tres tot
27
+        // pour eviter le chargement de tout iterateur
28
+        if (isset($command['si'])) {
29
+            foreach ($command['si'] as $si) {
30
+                if (!$si) {
31
+                    // $command pour boucle SQL peut generer des erreurs de compilation
32
+                    // s'il est transmis alors qu'on est dans un iterateur vide
33
+                    return new IterDecorator(new EmptyIterator(), [], $info);
34
+                }
35
+            }
36
+        }
37
+
38
+        // chercher un iterateur PHP existant (par exemple dans SPL)
39
+        // (il faudrait passer l'argument ->sql_serveur
40
+        // pour etre certain qu'on est sur un "php:")
41
+        if (class_exists($iterateur)) {
42
+            $a = isset($command['args']) ? $command['args'] : [];
43
+
44
+            // permettre de passer un Iterateur directement {args #ITERATEUR} :
45
+            // si on recoit deja un iterateur en argument, on l'utilise
46
+            if (count($a) == 1 and is_object($a[0]) and is_subclass_of($a[0], 'Iterator')) {
47
+                $iter = $a[0];
48
+
49
+                // sinon, on cree un iterateur du type donne
50
+            } else {
51
+                // arguments de creation de l'iterateur...
52
+                // (pas glop)
53
+                try {
54
+                    switch (count($a)) {
55
+                        case 0:
56
+                            $iter = new $iterateur();
57
+                            break;
58
+                        case 1:
59
+                            $iter = new $iterateur($a[0]);
60
+                            break;
61
+                        case 2:
62
+                            $iter = new $iterateur($a[0], $a[1]);
63
+                            break;
64
+                        case 3:
65
+                            $iter = new $iterateur($a[0], $a[1], $a[2]);
66
+                            break;
67
+                        case 4:
68
+                            $iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
69
+                            break;
70
+                    }
71
+                } catch (Exception $e) {
72
+                    spip_log("Erreur de chargement de l'iterateur $iterateur");
73
+                    spip_log($e->getMessage());
74
+                    $iter = new EmptyIterator();
75
+                }
76
+            }
77
+        } else {
78
+            // chercher la classe d'iterateur
79
+            // IterateurXXX
80
+            // definie dans le fichier iterateurs/xxx.php
81
+            $class = 'Iterateur' . $iterateur;
82
+            if (!class_exists($class)) {
83
+                if (
84
+                    !include_spip('iterateur/' . strtolower($iterateur))
85
+                    or !class_exists($class)
86
+                ) {
87
+                    die("Iterateur $iterateur non trouv&#233;");
88
+                    // si l'iterateur n'existe pas, on se rabat sur le generique
89
+                    # $iter = new EmptyIterator();
90
+                }
91
+            }
92
+            $iter = new $class($command, $info);
93
+        }
94
+
95
+        return new IterDecorator($iter, $command, $info);
96
+    }
97 97
 }
98 98
 
99 99
 
100 100
 class IterDecorator extends FilterIterator {
101
-	private $iter;
102
-
103
-	/**
104
-	 * Conditions de filtrage
105
-	 * ie criteres de selection
106
-	 *
107
-	 * @var array
108
-	 */
109
-	protected $filtre = [];
110
-
111
-	/**
112
-	 * Fonction de filtrage compilee a partir des criteres de filtre
113
-	 *
114
-	 * @var string
115
-	 */
116
-	protected $func_filtre = null;
117
-
118
-	/**
119
-	 * Critere {offset, limit}
120
-	 *
121
-	 * @var int
122
-	 * @var int
123
-	 */
124
-	protected $offset = null;
125
-	protected $limit = null;
126
-
127
-	/**
128
-	 * nombre d'elements recuperes depuis la position 0,
129
-	 * en tenant compte des filtres
130
-	 *
131
-	 * @var int
132
-	 */
133
-	protected $fetched = 0;
134
-
135
-	/**
136
-	 * Y a t'il une erreur ?
137
-	 *
138
-	 * @var bool
139
-	 **/
140
-	protected $err = false;
141
-
142
-	/**
143
-	 * Drapeau a activer en cas d'echec
144
-	 * (select SQL errone, non chargement des DATA, etc)
145
-	 */
146
-	public function err() {
147
-		if (method_exists($this->iter, 'err')) {
148
-			return $this->iter->err();
149
-		}
150
-		if (property_exists($this->iter, 'err')) {
151
-			return $this->iter->err;
152
-		}
153
-
154
-		return false;
155
-	}
156
-
157
-	public function __construct(Iterator $iter, $command, $info) {
158
-		parent::__construct($iter);
159
-		parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
160
-
161
-		// recuperer l'iterateur transmis
162
-		$this->iter = $this->getInnerIterator();
163
-		$this->command = $command;
164
-		$this->info = $info;
165
-		$this->pos = 0;
166
-		$this->fetched = 0;
167
-
168
-		// chercher la liste des champs a retourner par
169
-		// fetch si l'objet ne les calcule pas tout seul
170
-		if (!method_exists($this->iter, 'fetch')) {
171
-			$this->calculer_select();
172
-			$this->calculer_filtres();
173
-		}
174
-
175
-		// emptyIterator critere {si} faux n'a pas d'erreur !
176
-		if (isset($this->iter->err)) {
177
-			$this->err = $this->iter->err;
178
-		}
179
-
180
-		// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
181
-		//$this->total = $this->count();
182
-	}
183
-
184
-
185
-	// calcule les elements a retournes par fetch()
186
-	// enleve les elements inutiles du select()
187
-	//
188
-	private function calculer_select() {
189
-		if ($select = &$this->command['select']) {
190
-			foreach ($select as $s) {
191
-				// /!\ $s = '.nom'
192
-				if ($s[0] == '.') {
193
-					$s = substr($s, 1);
194
-				}
195
-				$this->select[] = $s;
196
-			}
197
-		}
198
-	}
199
-
200
-	// recuperer la valeur d'une balise #X
201
-	// en fonction des methodes
202
-	// et proprietes disponibles
203
-	public function get_select($nom) {
204
-		if (
205
-			is_object($this->iter)
206
-			and method_exists($this->iter, $nom)
207
-		) {
208
-			try {
209
-				return $this->iter->$nom();
210
-			} catch (Exception $e) {
211
-				// #GETCHILDREN sur un fichier de DirectoryIterator ...
212
-				spip_log("Methode $nom en echec sur " . get_class($this->iter));
213
-				spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
214
-
215
-				return '';
216
-			}
217
-		}
218
-		/*
101
+    private $iter;
102
+
103
+    /**
104
+     * Conditions de filtrage
105
+     * ie criteres de selection
106
+     *
107
+     * @var array
108
+     */
109
+    protected $filtre = [];
110
+
111
+    /**
112
+     * Fonction de filtrage compilee a partir des criteres de filtre
113
+     *
114
+     * @var string
115
+     */
116
+    protected $func_filtre = null;
117
+
118
+    /**
119
+     * Critere {offset, limit}
120
+     *
121
+     * @var int
122
+     * @var int
123
+     */
124
+    protected $offset = null;
125
+    protected $limit = null;
126
+
127
+    /**
128
+     * nombre d'elements recuperes depuis la position 0,
129
+     * en tenant compte des filtres
130
+     *
131
+     * @var int
132
+     */
133
+    protected $fetched = 0;
134
+
135
+    /**
136
+     * Y a t'il une erreur ?
137
+     *
138
+     * @var bool
139
+     **/
140
+    protected $err = false;
141
+
142
+    /**
143
+     * Drapeau a activer en cas d'echec
144
+     * (select SQL errone, non chargement des DATA, etc)
145
+     */
146
+    public function err() {
147
+        if (method_exists($this->iter, 'err')) {
148
+            return $this->iter->err();
149
+        }
150
+        if (property_exists($this->iter, 'err')) {
151
+            return $this->iter->err;
152
+        }
153
+
154
+        return false;
155
+    }
156
+
157
+    public function __construct(Iterator $iter, $command, $info) {
158
+        parent::__construct($iter);
159
+        parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
160
+
161
+        // recuperer l'iterateur transmis
162
+        $this->iter = $this->getInnerIterator();
163
+        $this->command = $command;
164
+        $this->info = $info;
165
+        $this->pos = 0;
166
+        $this->fetched = 0;
167
+
168
+        // chercher la liste des champs a retourner par
169
+        // fetch si l'objet ne les calcule pas tout seul
170
+        if (!method_exists($this->iter, 'fetch')) {
171
+            $this->calculer_select();
172
+            $this->calculer_filtres();
173
+        }
174
+
175
+        // emptyIterator critere {si} faux n'a pas d'erreur !
176
+        if (isset($this->iter->err)) {
177
+            $this->err = $this->iter->err;
178
+        }
179
+
180
+        // pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
181
+        //$this->total = $this->count();
182
+    }
183
+
184
+
185
+    // calcule les elements a retournes par fetch()
186
+    // enleve les elements inutiles du select()
187
+    //
188
+    private function calculer_select() {
189
+        if ($select = &$this->command['select']) {
190
+            foreach ($select as $s) {
191
+                // /!\ $s = '.nom'
192
+                if ($s[0] == '.') {
193
+                    $s = substr($s, 1);
194
+                }
195
+                $this->select[] = $s;
196
+            }
197
+        }
198
+    }
199
+
200
+    // recuperer la valeur d'une balise #X
201
+    // en fonction des methodes
202
+    // et proprietes disponibles
203
+    public function get_select($nom) {
204
+        if (
205
+            is_object($this->iter)
206
+            and method_exists($this->iter, $nom)
207
+        ) {
208
+            try {
209
+                return $this->iter->$nom();
210
+            } catch (Exception $e) {
211
+                // #GETCHILDREN sur un fichier de DirectoryIterator ...
212
+                spip_log("Methode $nom en echec sur " . get_class($this->iter));
213
+                spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
214
+
215
+                return '';
216
+            }
217
+        }
218
+        /*
219 219
 		if (property_exists($this->iter, $nom)) {
220 220
 			return $this->iter->$nom;
221 221
 		}*/
222
-		// cle et valeur par defaut
223
-		// ICI PLANTAGE SI ON NE CONTROLE PAS $nom
224
-		if (
225
-			in_array($nom, ['cle', 'valeur'])
226
-			and method_exists($this, $nom)
227
-		) {
228
-			return $this->$nom();
229
-		}
230
-
231
-		// Par defaut chercher en xpath dans la valeur()
232
-		return table_valeur($this->valeur(), $nom, null);
233
-	}
234
-
235
-
236
-	private function calculer_filtres() {
237
-
238
-		// Issu de calculer_select() de public/composer L.519
239
-		// TODO: externaliser...
240
-		//
241
-		// retirer les criteres vides:
242
-		// {X ?} avec X absent de l'URL
243
-		// {par #ENV{X}} avec X absent de l'URL
244
-		// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
245
-		if ($where = &$this->command['where']) {
246
-			foreach ($where as $k => $v) {
247
-				$this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
248
-			}
249
-		}
250
-
251
-		// critere {2,7}
252
-		if (isset($this->command['limit']) and $this->command['limit']) {
253
-			$limit = explode(',', $this->command['limit']);
254
-			$this->offset = $limit[0];
255
-			$this->limit = $limit[1];
256
-		}
257
-
258
-		// Creer la fonction de filtrage sur $this
259
-		if ($this->filtre) {
260
-			if ($filtres = $this->assembler_filtres($this->filtre)) {
261
-				$filtres = 'return ' . $filtres . ';';
262
-				$this->func_filtre = function () use ($filtres) {
263
-					return eval($filtres);
264
-				};
265
-			}
266
-			else {
267
-				$this->func_filtre = null;
268
-			}
269
-		}
270
-	}
271
-
272
-	/**
273
-	 * Assembler le tableau de filtres traduits depuis les conditions SQL
274
-	 * les filtres vides ou null sont ignores
275
-	 * @param $filtres
276
-	 * @param string $operateur
277
-	 * @return string|null
278
-	 */
279
-	protected function assembler_filtres($filtres, $operateur = 'AND') {
280
-
281
-		$filtres_string = [];
282
-		foreach ($filtres as $k => $v) {
283
-			// si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
284
-			if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
285
-				$op = array_shift($v);
286
-				$v = $this->assembler_filtres($v, $op);
287
-			}
288
-			if (is_null($v) or !is_string($v) or empty($v)) {
289
-				continue;
290
-			}
291
-			$filtres_string[] = $v;
292
-		}
293
-
294
-		if (!count($filtres_string)) {
295
-			return null;
296
-		}
297
-
298
-		return '(' . implode(") $operateur (", $filtres_string) . ')';
299
-	}
300
-
301
-	/**
302
-	 * Traduire un element du tableau where SQL en un filtre
303
-	 * @param $v
304
-	 * @return string|array|null
305
-	 */
306
-	protected function traduire_condition_sql_en_filtre($v) {
307
-		if (is_array($v)) {
308
-			if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
309
-				return 'true';
310
-			} elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
311
-				return 'true';
312
-			} else {
313
-				$op = $v[0] ?: $v;
314
-			}
315
-		} else {
316
-			$op = $v;
317
-		}
318
-		if ((!$op) or ($op == 1) or ($op == '0=0')) {
319
-			return 'true';
320
-		}
321
-		if ($op === '0=1') {
322
-			return 'false';
323
-		}
324
-		// traiter {cle IN a,b} ou {valeur !IN a,b}
325
-		if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
326
-			return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
327
-		}
328
-
329
-		// 3 possibilites : count($v) =
330
-		// * 1 : {x y} ; on recoit $v[0] = y
331
-		// * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
332
-		// * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
333
-
334
-		// 1 : forcement traite par un critere, on passe
335
-		if (!$v or !is_array($v) or count($v) == 1) {
336
-			return null; // sera ignore
337
-		}
338
-		if (count($v) == 2 and is_array($v[1])) {
339
-			return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
340
-		}
341
-		if (count($v) == 3) {
342
-			// traiter le OR/AND suivi de 2 valeurs
343
-			if (in_array($op, ['OR', 'AND'])) {
344
-				array_shift($v);
345
-				foreach (array_keys($v) as $k) {
346
-					$v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
347
-					if ($v[$k] === null) {
348
-						unset($v[$k]);
349
-					}
350
-					elseif ($v[$k] === 'true') {
351
-						if ($op === 'OR') {
352
-							return 'true';
353
-						}
354
-						if ($op === 'AND') {
355
-							unset($v[$k]);
356
-						}
357
-					}
358
-					elseif ($v[$k] === 'false') {
359
-						if ($op === 'OR') {
360
-							unset($v[$k]);
361
-						}
362
-						if ($op === 'AND') {
363
-							return 'false';
364
-						}
365
-					}
366
-				}
367
-				if (!count($v)) {
368
-					return null;
369
-				}
370
-				if (count($v) === 1) {
371
-					return reset($v);
372
-				}
373
-				array_unshift($v, $op);
374
-				return $v;
375
-			}
376
-			return $this->composer_filtre($v[1], $v[0], $v[2]);
377
-		}
378
-
379
-		return null;  // sera ignore
380
-	}
381
-
382
-	/**
383
-	 * Calculer un filtre sur un champ du tableau
384
-	 * @param $cle
385
-	 * @param $op
386
-	 * @param $valeur
387
-	 * @param false $not
388
-	 * @return string|null
389
-	 */
390
-	protected function composer_filtre($cle, $op, $valeur, $not = false) {
391
-		if (method_exists($this->iter, 'exception_des_criteres')) {
392
-			if (in_array($cle, $this->iter->exception_des_criteres())) {
393
-				return null;
394
-			}
395
-		}
396
-		// TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
397
-		# mais c'est normalement deja opere par calculer_critere_infixe()
398
-		# qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
399
-		# ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
400
-		# il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
401
-
402
-		# if (!in_array($cle, array('cle', 'valeur')))
403
-		#	return;
404
-
405
-		$a = '$this->get_select(\'' . $cle . '\')';
406
-
407
-		$filtre = '';
408
-
409
-		if ($op == 'REGEXP') {
410
-			$filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
411
-			$op = '';
412
-		} else {
413
-			if ($op == 'LIKE') {
414
-				$valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
415
-				$filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
416
-				$op = '';
417
-			} else {
418
-				if ($op == '=') {
419
-					$op = '==';
420
-				} else {
421
-					if ($op == 'IN') {
422
-						$filtre = 'in_array(' . $a . ', array' . $valeur . ')';
423
-						$op = '';
424
-					} else {
425
-						if (!in_array($op, ['<', '<=', '>', '>='])) {
426
-							spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
427
-							$op = '';
428
-						}
429
-					}
430
-				}
431
-			}
432
-		}
433
-
434
-		if ($op) {
435
-			$filtre = $a . $op . str_replace('\"', '"', $valeur);
436
-		}
437
-
438
-		if ($not) {
439
-			$filtre = "!($filtre)";
440
-		}
441
-
442
-		return $filtre;
443
-	}
444
-
445
-
446
-	public function next() {
447
-		$this->pos++;
448
-		parent::next();
449
-	}
450
-
451
-	/**
452
-	 * revient au depart
453
-	 *
454
-	 * @return void
455
-	 */
456
-	public function rewind() {
457
-		$this->pos = 0;
458
-		$this->fetched = 0;
459
-		parent::rewind();
460
-	}
461
-
462
-
463
-	# Extension SPIP des iterateurs PHP
464
-	/**
465
-	 * type de l'iterateur
466
-	 *
467
-	 * @var string
468
-	 */
469
-	protected $type;
470
-
471
-	/**
472
-	 * parametres de l'iterateur
473
-	 *
474
-	 * @var array
475
-	 */
476
-	protected $command;
477
-
478
-	/**
479
-	 * infos de compilateur
480
-	 *
481
-	 * @var array
482
-	 */
483
-	protected $info;
484
-
485
-	/**
486
-	 * position courante de l'iterateur
487
-	 *
488
-	 * @var int
489
-	 */
490
-	protected $pos = null;
491
-
492
-	/**
493
-	 * nombre total resultats dans l'iterateur
494
-	 *
495
-	 * @var int
496
-	 */
497
-	protected $total = null;
498
-
499
-	/**
500
-	 * nombre maximal de recherche pour $total
501
-	 * si l'iterateur n'implemente pas de fonction specifique
502
-	 */
503
-	protected $max = 100000;
504
-
505
-
506
-	/**
507
-	 * Liste des champs a inserer dans les $row
508
-	 * retournes par ->fetch()
509
-	 */
510
-	protected $select = [];
511
-
512
-
513
-	/**
514
-	 * aller a la position absolue n,
515
-	 * comptee depuis le debut
516
-	 *
517
-	 * @param int $n
518
-	 *   absolute pos
519
-	 * @param string $continue
520
-	 *   param for sql_ api
521
-	 * @return bool
522
-	 *   success or fail if not implemented
523
-	 */
524
-	public function seek($n = 0, $continue = null) {
525
-		if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
526
-			$this->seek_loop($n);
527
-		}
528
-		$this->pos = $n;
529
-		$this->fetched = $n;
530
-
531
-		return true;
532
-	}
533
-
534
-	/*
222
+        // cle et valeur par defaut
223
+        // ICI PLANTAGE SI ON NE CONTROLE PAS $nom
224
+        if (
225
+            in_array($nom, ['cle', 'valeur'])
226
+            and method_exists($this, $nom)
227
+        ) {
228
+            return $this->$nom();
229
+        }
230
+
231
+        // Par defaut chercher en xpath dans la valeur()
232
+        return table_valeur($this->valeur(), $nom, null);
233
+    }
234
+
235
+
236
+    private function calculer_filtres() {
237
+
238
+        // Issu de calculer_select() de public/composer L.519
239
+        // TODO: externaliser...
240
+        //
241
+        // retirer les criteres vides:
242
+        // {X ?} avec X absent de l'URL
243
+        // {par #ENV{X}} avec X absent de l'URL
244
+        // IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
245
+        if ($where = &$this->command['where']) {
246
+            foreach ($where as $k => $v) {
247
+                $this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
248
+            }
249
+        }
250
+
251
+        // critere {2,7}
252
+        if (isset($this->command['limit']) and $this->command['limit']) {
253
+            $limit = explode(',', $this->command['limit']);
254
+            $this->offset = $limit[0];
255
+            $this->limit = $limit[1];
256
+        }
257
+
258
+        // Creer la fonction de filtrage sur $this
259
+        if ($this->filtre) {
260
+            if ($filtres = $this->assembler_filtres($this->filtre)) {
261
+                $filtres = 'return ' . $filtres . ';';
262
+                $this->func_filtre = function () use ($filtres) {
263
+                    return eval($filtres);
264
+                };
265
+            }
266
+            else {
267
+                $this->func_filtre = null;
268
+            }
269
+        }
270
+    }
271
+
272
+    /**
273
+     * Assembler le tableau de filtres traduits depuis les conditions SQL
274
+     * les filtres vides ou null sont ignores
275
+     * @param $filtres
276
+     * @param string $operateur
277
+     * @return string|null
278
+     */
279
+    protected function assembler_filtres($filtres, $operateur = 'AND') {
280
+
281
+        $filtres_string = [];
282
+        foreach ($filtres as $k => $v) {
283
+            // si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
284
+            if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
285
+                $op = array_shift($v);
286
+                $v = $this->assembler_filtres($v, $op);
287
+            }
288
+            if (is_null($v) or !is_string($v) or empty($v)) {
289
+                continue;
290
+            }
291
+            $filtres_string[] = $v;
292
+        }
293
+
294
+        if (!count($filtres_string)) {
295
+            return null;
296
+        }
297
+
298
+        return '(' . implode(") $operateur (", $filtres_string) . ')';
299
+    }
300
+
301
+    /**
302
+     * Traduire un element du tableau where SQL en un filtre
303
+     * @param $v
304
+     * @return string|array|null
305
+     */
306
+    protected function traduire_condition_sql_en_filtre($v) {
307
+        if (is_array($v)) {
308
+            if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
309
+                return 'true';
310
+            } elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
311
+                return 'true';
312
+            } else {
313
+                $op = $v[0] ?: $v;
314
+            }
315
+        } else {
316
+            $op = $v;
317
+        }
318
+        if ((!$op) or ($op == 1) or ($op == '0=0')) {
319
+            return 'true';
320
+        }
321
+        if ($op === '0=1') {
322
+            return 'false';
323
+        }
324
+        // traiter {cle IN a,b} ou {valeur !IN a,b}
325
+        if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
326
+            return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
327
+        }
328
+
329
+        // 3 possibilites : count($v) =
330
+        // * 1 : {x y} ; on recoit $v[0] = y
331
+        // * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
332
+        // * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
333
+
334
+        // 1 : forcement traite par un critere, on passe
335
+        if (!$v or !is_array($v) or count($v) == 1) {
336
+            return null; // sera ignore
337
+        }
338
+        if (count($v) == 2 and is_array($v[1])) {
339
+            return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
340
+        }
341
+        if (count($v) == 3) {
342
+            // traiter le OR/AND suivi de 2 valeurs
343
+            if (in_array($op, ['OR', 'AND'])) {
344
+                array_shift($v);
345
+                foreach (array_keys($v) as $k) {
346
+                    $v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
347
+                    if ($v[$k] === null) {
348
+                        unset($v[$k]);
349
+                    }
350
+                    elseif ($v[$k] === 'true') {
351
+                        if ($op === 'OR') {
352
+                            return 'true';
353
+                        }
354
+                        if ($op === 'AND') {
355
+                            unset($v[$k]);
356
+                        }
357
+                    }
358
+                    elseif ($v[$k] === 'false') {
359
+                        if ($op === 'OR') {
360
+                            unset($v[$k]);
361
+                        }
362
+                        if ($op === 'AND') {
363
+                            return 'false';
364
+                        }
365
+                    }
366
+                }
367
+                if (!count($v)) {
368
+                    return null;
369
+                }
370
+                if (count($v) === 1) {
371
+                    return reset($v);
372
+                }
373
+                array_unshift($v, $op);
374
+                return $v;
375
+            }
376
+            return $this->composer_filtre($v[1], $v[0], $v[2]);
377
+        }
378
+
379
+        return null;  // sera ignore
380
+    }
381
+
382
+    /**
383
+     * Calculer un filtre sur un champ du tableau
384
+     * @param $cle
385
+     * @param $op
386
+     * @param $valeur
387
+     * @param false $not
388
+     * @return string|null
389
+     */
390
+    protected function composer_filtre($cle, $op, $valeur, $not = false) {
391
+        if (method_exists($this->iter, 'exception_des_criteres')) {
392
+            if (in_array($cle, $this->iter->exception_des_criteres())) {
393
+                return null;
394
+            }
395
+        }
396
+        // TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
397
+        # mais c'est normalement deja opere par calculer_critere_infixe()
398
+        # qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
399
+        # ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
400
+        # il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
401
+
402
+        # if (!in_array($cle, array('cle', 'valeur')))
403
+        #	return;
404
+
405
+        $a = '$this->get_select(\'' . $cle . '\')';
406
+
407
+        $filtre = '';
408
+
409
+        if ($op == 'REGEXP') {
410
+            $filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
411
+            $op = '';
412
+        } else {
413
+            if ($op == 'LIKE') {
414
+                $valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
415
+                $filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
416
+                $op = '';
417
+            } else {
418
+                if ($op == '=') {
419
+                    $op = '==';
420
+                } else {
421
+                    if ($op == 'IN') {
422
+                        $filtre = 'in_array(' . $a . ', array' . $valeur . ')';
423
+                        $op = '';
424
+                    } else {
425
+                        if (!in_array($op, ['<', '<=', '>', '>='])) {
426
+                            spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
427
+                            $op = '';
428
+                        }
429
+                    }
430
+                }
431
+            }
432
+        }
433
+
434
+        if ($op) {
435
+            $filtre = $a . $op . str_replace('\"', '"', $valeur);
436
+        }
437
+
438
+        if ($not) {
439
+            $filtre = "!($filtre)";
440
+        }
441
+
442
+        return $filtre;
443
+    }
444
+
445
+
446
+    public function next() {
447
+        $this->pos++;
448
+        parent::next();
449
+    }
450
+
451
+    /**
452
+     * revient au depart
453
+     *
454
+     * @return void
455
+     */
456
+    public function rewind() {
457
+        $this->pos = 0;
458
+        $this->fetched = 0;
459
+        parent::rewind();
460
+    }
461
+
462
+
463
+    # Extension SPIP des iterateurs PHP
464
+    /**
465
+     * type de l'iterateur
466
+     *
467
+     * @var string
468
+     */
469
+    protected $type;
470
+
471
+    /**
472
+     * parametres de l'iterateur
473
+     *
474
+     * @var array
475
+     */
476
+    protected $command;
477
+
478
+    /**
479
+     * infos de compilateur
480
+     *
481
+     * @var array
482
+     */
483
+    protected $info;
484
+
485
+    /**
486
+     * position courante de l'iterateur
487
+     *
488
+     * @var int
489
+     */
490
+    protected $pos = null;
491
+
492
+    /**
493
+     * nombre total resultats dans l'iterateur
494
+     *
495
+     * @var int
496
+     */
497
+    protected $total = null;
498
+
499
+    /**
500
+     * nombre maximal de recherche pour $total
501
+     * si l'iterateur n'implemente pas de fonction specifique
502
+     */
503
+    protected $max = 100000;
504
+
505
+
506
+    /**
507
+     * Liste des champs a inserer dans les $row
508
+     * retournes par ->fetch()
509
+     */
510
+    protected $select = [];
511
+
512
+
513
+    /**
514
+     * aller a la position absolue n,
515
+     * comptee depuis le debut
516
+     *
517
+     * @param int $n
518
+     *   absolute pos
519
+     * @param string $continue
520
+     *   param for sql_ api
521
+     * @return bool
522
+     *   success or fail if not implemented
523
+     */
524
+    public function seek($n = 0, $continue = null) {
525
+        if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
526
+            $this->seek_loop($n);
527
+        }
528
+        $this->pos = $n;
529
+        $this->fetched = $n;
530
+
531
+        return true;
532
+    }
533
+
534
+    /*
535 535
 	 * aller a la position $n en parcourant
536 536
 	 * un par un tous les elements
537 537
 	 */
538
-	private function seek_loop($n) {
539
-		if ($this->pos > $n) {
540
-			$this->rewind();
541
-		}
542
-
543
-		while ($this->pos < $n and $this->valid()) {
544
-			$this->next();
545
-		}
546
-
547
-		return true;
548
-	}
549
-
550
-	/**
551
-	 * Avancer de $saut pas
552
-	 *
553
-	 * @param  $saut
554
-	 * @param  $max
555
-	 * @return int
556
-	 */
557
-	public function skip($saut, $max = null) {
558
-		// pas de saut en arriere autorise pour cette fonction
559
-		if (($saut = intval($saut)) <= 0) {
560
-			return $this->pos;
561
-		}
562
-		$seek = $this->pos + $saut;
563
-		// si le saut fait depasser le maxi, on libere la resource
564
-		// et on sort
565
-		if (is_null($max)) {
566
-			$max = $this->count();
567
-		}
568
-
569
-		if ($seek >= $max or $seek >= $this->count()) {
570
-			// sortie plus rapide que de faire next() jusqu'a la fin !
571
-			$this->free();
572
-
573
-			return $max;
574
-		}
575
-
576
-		$this->seek($seek);
577
-
578
-		return $this->pos;
579
-	}
580
-
581
-	/**
582
-	 * Renvoyer un tableau des donnees correspondantes
583
-	 * a la position courante de l'iterateur
584
-	 * en controlant si on respecte le filtre
585
-	 * Appliquer aussi le critere {offset,limit}
586
-	 *
587
-	 * @return array|bool
588
-	 */
589
-	public function fetch() {
590
-		if (method_exists($this->iter, 'fetch')) {
591
-			return $this->iter->fetch();
592
-		} else {
593
-			while (
594
-				$this->valid()
595
-				and (
596
-					!$this->accept()
597
-					or (isset($this->offset) and $this->fetched++ < $this->offset)
598
-				)
599
-			) {
600
-				$this->next();
601
-			}
602
-
603
-			if (!$this->valid()) {
604
-				return false;
605
-			}
606
-
607
-			if (
608
-				isset($this->limit)
609
-				and $this->fetched > $this->offset + $this->limit
610
-			) {
611
-				return false;
612
-			}
613
-
614
-			$r = [];
615
-			foreach ($this->select as $nom) {
616
-				$r[$nom] = $this->get_select($nom);
617
-			}
618
-			$this->next();
619
-
620
-			return $r;
621
-		}
622
-	}
623
-
624
-	// retourner la cle pour #CLE
625
-	public function cle() {
626
-		return $this->key();
627
-	}
628
-
629
-	// retourner la valeur pour #VALEUR
630
-	public function valeur() {
631
-		return $this->current();
632
-	}
633
-
634
-	/**
635
-	 * Accepte-t-on l'entree courante lue ?
636
-	 * On execute les filtres pour le savoir.
637
-	 **/
638
-	public function accept() {
639
-		if ($f = $this->func_filtre) {
640
-			return $f();
641
-		}
642
-
643
-		return true;
644
-	}
645
-
646
-	/**
647
-	 * liberer la ressource
648
-	 *
649
-	 * @return bool
650
-	 */
651
-	public function free() {
652
-		if (method_exists($this->iter, 'free')) {
653
-			$this->iter->free();
654
-		}
655
-		$this->pos = $this->total = 0;
656
-
657
-		return true;
658
-	}
659
-
660
-	/**
661
-	 * Compter le nombre total de resultats
662
-	 * pour #TOTAL_BOUCLE
663
-	 *
664
-	 * @return int
665
-	 */
666
-	public function count() {
667
-		if (is_null($this->total)) {
668
-			if (
669
-				method_exists($this->iter, 'count')
670
-				and !$this->func_filtre
671
-			) {
672
-				return $this->total = $this->iter->count();
673
-			} else {
674
-				// compter les lignes et rembobiner
675
-				$total = 0;
676
-				$pos = $this->pos; // sauver la position
677
-				$this->rewind();
678
-				while ($this->fetch() and $total < $this->max) {
679
-					$total++;
680
-				}
681
-				$this->seek($pos);
682
-				$this->total = $total;
683
-			}
684
-		}
685
-
686
-		return $this->total;
687
-	}
538
+    private function seek_loop($n) {
539
+        if ($this->pos > $n) {
540
+            $this->rewind();
541
+        }
542
+
543
+        while ($this->pos < $n and $this->valid()) {
544
+            $this->next();
545
+        }
546
+
547
+        return true;
548
+    }
549
+
550
+    /**
551
+     * Avancer de $saut pas
552
+     *
553
+     * @param  $saut
554
+     * @param  $max
555
+     * @return int
556
+     */
557
+    public function skip($saut, $max = null) {
558
+        // pas de saut en arriere autorise pour cette fonction
559
+        if (($saut = intval($saut)) <= 0) {
560
+            return $this->pos;
561
+        }
562
+        $seek = $this->pos + $saut;
563
+        // si le saut fait depasser le maxi, on libere la resource
564
+        // et on sort
565
+        if (is_null($max)) {
566
+            $max = $this->count();
567
+        }
568
+
569
+        if ($seek >= $max or $seek >= $this->count()) {
570
+            // sortie plus rapide que de faire next() jusqu'a la fin !
571
+            $this->free();
572
+
573
+            return $max;
574
+        }
575
+
576
+        $this->seek($seek);
577
+
578
+        return $this->pos;
579
+    }
580
+
581
+    /**
582
+     * Renvoyer un tableau des donnees correspondantes
583
+     * a la position courante de l'iterateur
584
+     * en controlant si on respecte le filtre
585
+     * Appliquer aussi le critere {offset,limit}
586
+     *
587
+     * @return array|bool
588
+     */
589
+    public function fetch() {
590
+        if (method_exists($this->iter, 'fetch')) {
591
+            return $this->iter->fetch();
592
+        } else {
593
+            while (
594
+                $this->valid()
595
+                and (
596
+                    !$this->accept()
597
+                    or (isset($this->offset) and $this->fetched++ < $this->offset)
598
+                )
599
+            ) {
600
+                $this->next();
601
+            }
602
+
603
+            if (!$this->valid()) {
604
+                return false;
605
+            }
606
+
607
+            if (
608
+                isset($this->limit)
609
+                and $this->fetched > $this->offset + $this->limit
610
+            ) {
611
+                return false;
612
+            }
613
+
614
+            $r = [];
615
+            foreach ($this->select as $nom) {
616
+                $r[$nom] = $this->get_select($nom);
617
+            }
618
+            $this->next();
619
+
620
+            return $r;
621
+        }
622
+    }
623
+
624
+    // retourner la cle pour #CLE
625
+    public function cle() {
626
+        return $this->key();
627
+    }
628
+
629
+    // retourner la valeur pour #VALEUR
630
+    public function valeur() {
631
+        return $this->current();
632
+    }
633
+
634
+    /**
635
+     * Accepte-t-on l'entree courante lue ?
636
+     * On execute les filtres pour le savoir.
637
+     **/
638
+    public function accept() {
639
+        if ($f = $this->func_filtre) {
640
+            return $f();
641
+        }
642
+
643
+        return true;
644
+    }
645
+
646
+    /**
647
+     * liberer la ressource
648
+     *
649
+     * @return bool
650
+     */
651
+    public function free() {
652
+        if (method_exists($this->iter, 'free')) {
653
+            $this->iter->free();
654
+        }
655
+        $this->pos = $this->total = 0;
656
+
657
+        return true;
658
+    }
659
+
660
+    /**
661
+     * Compter le nombre total de resultats
662
+     * pour #TOTAL_BOUCLE
663
+     *
664
+     * @return int
665
+     */
666
+    public function count() {
667
+        if (is_null($this->total)) {
668
+            if (
669
+                method_exists($this->iter, 'count')
670
+                and !$this->func_filtre
671
+            ) {
672
+                return $this->total = $this->iter->count();
673
+            } else {
674
+                // compter les lignes et rembobiner
675
+                $total = 0;
676
+                $pos = $this->pos; // sauver la position
677
+                $this->rewind();
678
+                while ($this->fetch() and $total < $this->max) {
679
+                    $total++;
680
+                }
681
+                $this->seek($pos);
682
+                $this->total = $total;
683
+            }
684
+        }
685
+
686
+        return $this->total;
687
+    }
688 688
 }
Please login to merge, or discard this patch.
ecrire/inc/invalideur.php 1 patch
Indentation   +138 added lines, -138 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
 include_spip('base/serial');
@@ -27,7 +27,7 @@  discard block
 block discarded – undo
27 27
  * en droit de l'éliminer
28 28
  */
29 29
 if (!defined('_AGE_CACHE_ATIME')) {
30
-	define('_AGE_CACHE_ATIME', 3600);
30
+    define('_AGE_CACHE_ATIME', 3600);
31 31
 }
32 32
 
33 33
 
@@ -40,31 +40,31 @@  discard block
 block discarded – undo
40 40
  * @return int Taille approximative en octets
41 41
  **/
42 42
 function taille_du_cache() {
43
-	# check dirs until we reach > 500 files
44
-	$t = 0;
45
-	$n = 0;
46
-	$time = isset($GLOBALS['meta']['cache_mark']) ? $GLOBALS['meta']['cache_mark'] : 0;
47
-	for ($i = 0; $i < 256; $i++) {
48
-		$dir = _DIR_CACHE . sprintf('%02s', dechex($i));
49
-		if (@is_dir($dir) and is_readable($dir) and $d = opendir($dir)) {
50
-			while (($f = readdir($d)) !== false) {
51
-				if (preg_match(',^[[0-9a-f]+\.cache$,S', $f) and $a = stat("$dir/$f")) {
52
-					$n++;
53
-					if ($a['mtime'] >= $time) {
54
-						if ($a['blocks'] > 0) {
55
-							$t += 512 * $a['blocks'];
56
-						} else {
57
-							$t += $a['size'];
58
-						}
59
-					}
60
-				}
61
-			}
62
-		}
63
-		if ($n > 500) {
64
-			return intval(256 * $t / (1 + $i));
65
-		}
66
-	}
67
-	return $t;
43
+    # check dirs until we reach > 500 files
44
+    $t = 0;
45
+    $n = 0;
46
+    $time = isset($GLOBALS['meta']['cache_mark']) ? $GLOBALS['meta']['cache_mark'] : 0;
47
+    for ($i = 0; $i < 256; $i++) {
48
+        $dir = _DIR_CACHE . sprintf('%02s', dechex($i));
49
+        if (@is_dir($dir) and is_readable($dir) and $d = opendir($dir)) {
50
+            while (($f = readdir($d)) !== false) {
51
+                if (preg_match(',^[[0-9a-f]+\.cache$,S', $f) and $a = stat("$dir/$f")) {
52
+                    $n++;
53
+                    if ($a['mtime'] >= $time) {
54
+                        if ($a['blocks'] > 0) {
55
+                            $t += 512 * $a['blocks'];
56
+                        } else {
57
+                            $t += $a['size'];
58
+                        }
59
+                    }
60
+                }
61
+            }
62
+        }
63
+        if ($n > 500) {
64
+            return intval(256 * $t / (1 + $i));
65
+        }
66
+    }
67
+    return $t;
68 68
 }
69 69
 
70 70
 
@@ -91,30 +91,30 @@  discard block
 block discarded – undo
91 91
  *     Inutilisé
92 92
  **/
93 93
 function inc_suivre_invalideur_dist($cond, $modif = true) {
94
-	if (!$modif) {
95
-		return;
96
-	}
97
-
98
-	// determiner l'objet modifie : forum, article, etc
99
-	if (preg_match(',["\']([a-z_]+)[/"\'],', $cond, $r)) {
100
-		$objet = objet_type($r[1]);
101
-	}
102
-
103
-	// stocker la date_modif_$objet (ne sert a rien pour le moment)
104
-	if (isset($objet)) {
105
-		ecrire_meta('derniere_modif_' . $objet, time());
106
-	}
107
-
108
-	// si $derniere_modif_invalide est un array('article', 'rubrique')
109
-	// n'affecter la meta que si un de ces objets est modifie
110
-	if (is_array($GLOBALS['derniere_modif_invalide'])) {
111
-		if (in_array($objet, $GLOBALS['derniere_modif_invalide'])) {
112
-			ecrire_meta('derniere_modif', time());
113
-		}
114
-	} // sinon, cas standard, toujours affecter la meta
115
-	else {
116
-		ecrire_meta('derniere_modif', time());
117
-	}
94
+    if (!$modif) {
95
+        return;
96
+    }
97
+
98
+    // determiner l'objet modifie : forum, article, etc
99
+    if (preg_match(',["\']([a-z_]+)[/"\'],', $cond, $r)) {
100
+        $objet = objet_type($r[1]);
101
+    }
102
+
103
+    // stocker la date_modif_$objet (ne sert a rien pour le moment)
104
+    if (isset($objet)) {
105
+        ecrire_meta('derniere_modif_' . $objet, time());
106
+    }
107
+
108
+    // si $derniere_modif_invalide est un array('article', 'rubrique')
109
+    // n'affecter la meta que si un de ces objets est modifie
110
+    if (is_array($GLOBALS['derniere_modif_invalide'])) {
111
+        if (in_array($objet, $GLOBALS['derniere_modif_invalide'])) {
112
+            ecrire_meta('derniere_modif', time());
113
+        }
114
+    } // sinon, cas standard, toujours affecter la meta
115
+    else {
116
+        ecrire_meta('derniere_modif', time());
117
+    }
118 118
 }
119 119
 
120 120
 
@@ -139,57 +139,57 @@  discard block
 block discarded – undo
139 139
  *     Nombre de fichiers supprimés
140 140
  **/
141 141
 function purger_repertoire($dir, $options = []) {
142
-	if (!is_dir($dir) or !is_readable($dir)) {
143
-		return 0;
144
-	}
145
-
146
-	// sur certains sites on veut absolument garder certains caches référencés dans un CDN
147
-	// on peut donc inhiber la purge de ces répertoires pour eviter tout probleme
148
-	if (file_exists(rtrim($dir, '/') . '/inhib_purger_repertoire.txt')) {
149
-		return 0;
150
-	}
151
-
152
-	$handle = opendir($dir);
153
-	if (!$handle) {
154
-		return 0;
155
-	}
156
-
157
-	$total = 0;
158
-
159
-	while (($fichier = @readdir($handle)) !== false) {
160
-		// Eviter ".", "..", ".htaccess", ".svn" etc & CACHEDIR.TAG
161
-		if ($fichier[0] == '.' or $fichier == 'CACHEDIR.TAG') {
162
-			continue;
163
-		}
164
-		$chemin = "$dir/$fichier";
165
-		if (is_file($chemin)) {
166
-			if (
167
-				(!isset($options['atime']) or (@fileatime($chemin) < $options['atime']))
168
-				and (!isset($options['mtime']) or (@filemtime($chemin) < $options['mtime']))
169
-			) {
170
-				supprimer_fichier($chemin);
171
-				$total++;
172
-			}
173
-		} else {
174
-			if (is_dir($chemin)) {
175
-				$opts = $options;
176
-				if (isset($options['limit'])) {
177
-					$opts['limit'] = $options['limit'] - $total;
178
-				}
179
-				$total += purger_repertoire($chemin, $opts);
180
-				if (isset($options['subdir']) && $options['subdir']) {
181
-					spip_unlink($chemin);
182
-				}
183
-			}
184
-		}
185
-
186
-		if (isset($options['limit']) and $total >= $options['limit']) {
187
-			break;
188
-		}
189
-	}
190
-	closedir($handle);
191
-
192
-	return $total;
142
+    if (!is_dir($dir) or !is_readable($dir)) {
143
+        return 0;
144
+    }
145
+
146
+    // sur certains sites on veut absolument garder certains caches référencés dans un CDN
147
+    // on peut donc inhiber la purge de ces répertoires pour eviter tout probleme
148
+    if (file_exists(rtrim($dir, '/') . '/inhib_purger_repertoire.txt')) {
149
+        return 0;
150
+    }
151
+
152
+    $handle = opendir($dir);
153
+    if (!$handle) {
154
+        return 0;
155
+    }
156
+
157
+    $total = 0;
158
+
159
+    while (($fichier = @readdir($handle)) !== false) {
160
+        // Eviter ".", "..", ".htaccess", ".svn" etc & CACHEDIR.TAG
161
+        if ($fichier[0] == '.' or $fichier == 'CACHEDIR.TAG') {
162
+            continue;
163
+        }
164
+        $chemin = "$dir/$fichier";
165
+        if (is_file($chemin)) {
166
+            if (
167
+                (!isset($options['atime']) or (@fileatime($chemin) < $options['atime']))
168
+                and (!isset($options['mtime']) or (@filemtime($chemin) < $options['mtime']))
169
+            ) {
170
+                supprimer_fichier($chemin);
171
+                $total++;
172
+            }
173
+        } else {
174
+            if (is_dir($chemin)) {
175
+                $opts = $options;
176
+                if (isset($options['limit'])) {
177
+                    $opts['limit'] = $options['limit'] - $total;
178
+                }
179
+                $total += purger_repertoire($chemin, $opts);
180
+                if (isset($options['subdir']) && $options['subdir']) {
181
+                    spip_unlink($chemin);
182
+                }
183
+            }
184
+        }
185
+
186
+        if (isset($options['limit']) and $total >= $options['limit']) {
187
+            break;
188
+        }
189
+    }
190
+    closedir($handle);
191
+
192
+    return $total;
193 193
 }
194 194
 
195 195
 
@@ -201,17 +201,17 @@  discard block
 block discarded – undo
201 201
 // https://code.spip.net/@retire_cache
202 202
 function retire_cache($cache) {
203 203
 
204
-	if (
205
-		preg_match(
206
-			',^([0-9a-f]/)?([0-9]+/)?[0-9a-f]+\.cache(\.gz)?$,i',
207
-			$cache
208
-		)
209
-	) {
210
-		// supprimer le fichier (de facon propre)
211
-		supprimer_fichier(_DIR_CACHE . $cache);
212
-	} else {
213
-		spip_log("Nom de fichier cache incorrect : $cache");
214
-	}
204
+    if (
205
+        preg_match(
206
+            ',^([0-9a-f]/)?([0-9]+/)?[0-9a-f]+\.cache(\.gz)?$,i',
207
+            $cache
208
+        )
209
+    ) {
210
+        // supprimer le fichier (de facon propre)
211
+        supprimer_fichier(_DIR_CACHE . $cache);
212
+    } else {
213
+        spip_log("Nom de fichier cache incorrect : $cache");
214
+    }
215 215
 }
216 216
 
217 217
 // Supprimer les caches marques "x"
@@ -219,9 +219,9 @@  discard block
 block discarded – undo
219 219
 // la meta est toujours false ; mais evitons un bug si elle est appellee
220 220
 // https://code.spip.net/@retire_caches
221 221
 function inc_retire_caches_dist($chemin = '') {
222
-	if (isset($GLOBALS['meta']['invalider_caches'])) {
223
-		effacer_meta('invalider_caches');
224
-	} # concurrence
222
+    if (isset($GLOBALS['meta']['invalider_caches'])) {
223
+        effacer_meta('invalider_caches');
224
+    } # concurrence
225 225
 }
226 226
 
227 227
 #######################################################################
@@ -232,9 +232,9 @@  discard block
 block discarded – undo
232 232
 ##
233 233
 
234 234
 function retire_caches($chemin = '') {
235
-	if ($retire_caches = charger_fonction('retire_caches', 'inc', true)) {
236
-		return $retire_caches($chemin);
237
-	}
235
+    if ($retire_caches = charger_fonction('retire_caches', 'inc', true)) {
236
+        return $retire_caches($chemin);
237
+    }
238 238
 }
239 239
 
240 240
 
@@ -243,10 +243,10 @@  discard block
 block discarded – undo
243 243
 
244 244
 // https://code.spip.net/@calcul_invalideurs
245 245
 function calcul_invalideurs($corps, $primary, &$boucles, $id_boucle) {
246
-	if ($calcul_invalideurs = charger_fonction('calcul_invalideurs', 'inc', true)) {
247
-		return $calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
248
-	}
249
-	return $corps;
246
+    if ($calcul_invalideurs = charger_fonction('calcul_invalideurs', 'inc', true)) {
247
+        return $calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
248
+    }
249
+    return $corps;
250 250
 }
251 251
 
252 252
 
@@ -256,27 +256,27 @@  discard block
 block discarded – undo
256 256
 //
257 257
 // https://code.spip.net/@supprime_invalideurs
258 258
 function supprime_invalideurs() {
259
-	if ($supprime_invalideurs = charger_fonction('supprime_invalideurs', 'inc', true)) {
260
-		return $supprime_invalideurs();
261
-	}
259
+    if ($supprime_invalideurs = charger_fonction('supprime_invalideurs', 'inc', true)) {
260
+        return $supprime_invalideurs();
261
+    }
262 262
 }
263 263
 
264 264
 
265 265
 // Calcul des pages : noter dans la base les liens d'invalidation
266 266
 // https://code.spip.net/@maj_invalideurs
267 267
 function maj_invalideurs($fichier, &$page) {
268
-	if ($maj_invalideurs = charger_fonction('maj_invalideurs', 'inc', true)) {
269
-		return $maj_invalideurs($fichier, $page);
270
-	}
268
+    if ($maj_invalideurs = charger_fonction('maj_invalideurs', 'inc', true)) {
269
+        return $maj_invalideurs($fichier, $page);
270
+    }
271 271
 }
272 272
 
273 273
 
274 274
 // les invalideurs sont de la forme "objet/id_objet"
275 275
 // https://code.spip.net/@insere_invalideur
276 276
 function insere_invalideur($inval, $fichier) {
277
-	if ($insere_invalideur = charger_fonction('insere_invalideur', 'inc', true)) {
278
-		return $insere_invalideur($inval, $fichier);
279
-	}
277
+    if ($insere_invalideur = charger_fonction('insere_invalideur', 'inc', true)) {
278
+        return $insere_invalideur($inval, $fichier);
279
+    }
280 280
 }
281 281
 
282 282
 //
@@ -284,16 +284,16 @@  discard block
 block discarded – undo
284 284
 //
285 285
 // https://code.spip.net/@applique_invalideur
286 286
 function applique_invalideur($depart) {
287
-	if ($applique_invalideur = charger_fonction('applique_invalideur', 'inc', true)) {
288
-		return $applique_invalideur($depart);
289
-	}
287
+    if ($applique_invalideur = charger_fonction('applique_invalideur', 'inc', true)) {
288
+        return $applique_invalideur($depart);
289
+    }
290 290
 }
291 291
 
292 292
 //
293 293
 // Invalider les caches liés à telle condition
294 294
 //
295 295
 function suivre_invalideur($cond, $modif = true) {
296
-	if ($suivre_invalideur = charger_fonction('suivre_invalideur', 'inc', true)) {
297
-		return $suivre_invalideur($cond, $modif);
298
-	}
296
+    if ($suivre_invalideur = charger_fonction('suivre_invalideur', 'inc', true)) {
297
+        return $suivre_invalideur($cond, $modif);
298
+    }
299 299
 }
Please login to merge, or discard this patch.
ecrire/inc/documents.php 1 patch
Indentation   +224 added lines, -224 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
 /**
@@ -30,11 +30,11 @@  discard block
 block discarded – undo
30 30
  * @return string
31 31
  */
32 32
 function set_spip_doc($fichier) {
33
-	if (strpos($fichier, _DIR_IMG) === 0) {
34
-		return substr($fichier, strlen(_DIR_IMG));
35
-	} else {
36
-		return $fichier;
37
-	} // ex: fichier distant
33
+    if (strpos($fichier, _DIR_IMG) === 0) {
34
+        return substr($fichier, strlen(_DIR_IMG));
35
+    } else {
36
+        return $fichier;
37
+    } // ex: fichier distant
38 38
 }
39 39
 
40 40
 /**
@@ -46,24 +46,24 @@  discard block
 block discarded – undo
46 46
  * @return bool|string
47 47
  */
48 48
 function get_spip_doc($fichier) {
49
-	// fichier distant
50
-	if (tester_url_absolue($fichier)) {
51
-		return $fichier;
52
-	}
53
-
54
-	// gestion d'erreurs, fichier=''
55
-	if (!strlen($fichier)) {
56
-		return false;
57
-	}
58
-
59
-	$fichier = (
60
-		strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) != 0
61
-	)
62
-		? _DIR_IMG . $fichier
63
-		: $fichier;
64
-
65
-	// fichier normal
66
-	return $fichier;
49
+    // fichier distant
50
+    if (tester_url_absolue($fichier)) {
51
+        return $fichier;
52
+    }
53
+
54
+    // gestion d'erreurs, fichier=''
55
+    if (!strlen($fichier)) {
56
+        return false;
57
+    }
58
+
59
+    $fichier = (
60
+        strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) != 0
61
+    )
62
+        ? _DIR_IMG . $fichier
63
+        : $fichier;
64
+
65
+    // fichier normal
66
+    return $fichier;
67 67
 }
68 68
 
69 69
 /**
@@ -77,26 +77,26 @@  discard block
 block discarded – undo
77 77
  * @return string
78 78
  */
79 79
 function creer_repertoire_documents($ext) {
80
-	$rep = sous_repertoire(_DIR_IMG, $ext);
81
-
82
-	if (!$ext or !$rep) {
83
-		spip_log("creer_repertoire_documents '$rep' interdit");
84
-		exit;
85
-	}
86
-
87
-	// Cette variable de configuration peut etre posee par un plugin
88
-	// par exemple acces_restreint
89
-	// sauf pour logo/ utilise pour stocker les logoon et logooff
90
-	if (
91
-		isset($GLOBALS['meta']['creer_htaccess'])
92
-		and $GLOBALS['meta']['creer_htaccess'] == 'oui'
93
-		and $ext !== 'logo'
94
-	) {
95
-		include_spip('inc/acces');
96
-		verifier_htaccess($rep);
97
-	}
98
-
99
-	return $rep;
80
+    $rep = sous_repertoire(_DIR_IMG, $ext);
81
+
82
+    if (!$ext or !$rep) {
83
+        spip_log("creer_repertoire_documents '$rep' interdit");
84
+        exit;
85
+    }
86
+
87
+    // Cette variable de configuration peut etre posee par un plugin
88
+    // par exemple acces_restreint
89
+    // sauf pour logo/ utilise pour stocker les logoon et logooff
90
+    if (
91
+        isset($GLOBALS['meta']['creer_htaccess'])
92
+        and $GLOBALS['meta']['creer_htaccess'] == 'oui'
93
+        and $ext !== 'logo'
94
+    ) {
95
+        include_spip('inc/acces');
96
+        verifier_htaccess($rep);
97
+    }
98
+
99
+    return $rep;
100 100
 }
101 101
 
102 102
 /**
@@ -105,22 +105,22 @@  discard block
 block discarded – undo
105 105
  * @param string $nom
106 106
  */
107 107
 function effacer_repertoire_temporaire($nom) {
108
-	if ($d = opendir($nom)) {
109
-		while (($f = readdir($d)) !== false) {
110
-			if (is_file("$nom/$f")) {
111
-				spip_unlink("$nom/$f");
112
-			} else {
113
-				if (
114
-					$f <> '.' and $f <> '..'
115
-					and is_dir("$nom/$f")
116
-				) {
117
-					effacer_repertoire_temporaire("$nom/$f");
118
-				}
119
-			}
120
-		}
121
-	}
122
-	closedir($d);
123
-	@rmdir($nom);
108
+    if ($d = opendir($nom)) {
109
+        while (($f = readdir($d)) !== false) {
110
+            if (is_file("$nom/$f")) {
111
+                spip_unlink("$nom/$f");
112
+            } else {
113
+                if (
114
+                    $f <> '.' and $f <> '..'
115
+                    and is_dir("$nom/$f")
116
+                ) {
117
+                    effacer_repertoire_temporaire("$nom/$f");
118
+                }
119
+            }
120
+        }
121
+    }
122
+    closedir($d);
123
+    @rmdir($nom);
124 124
 }
125 125
 
126 126
 //
@@ -137,45 +137,45 @@  discard block
 block discarded – undo
137 137
  */
138 138
 function copier_document($ext, $orig, $source, $subdir = null) {
139 139
 
140
-	$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
141
-	$dir = creer_repertoire_documents($subdir ? $subdir : $ext);
142
-
143
-	$dest = preg_replace('/<[^>]*>/', '', basename($orig));
144
-	$dest = preg_replace('/\.([^.]+)$/', '', $dest);
145
-	$dest = translitteration($dest);
146
-	$dest = preg_replace('/[^.=\w-]+/', '_', $dest);
147
-
148
-	// ne pas accepter de noms de la forme -r90.jpg qui sont reserves
149
-	// pour les images transformees par rotation (action/documenter)
150
-	$dest = preg_replace(',-r(90|180|270)$,', '', $dest);
151
-
152
-	while (preg_match(',\.(\w+)$,', $dest, $m)) {
153
-		if (
154
-			!function_exists('verifier_upload_autorise')
155
-			or !$r = verifier_upload_autorise($dest)
156
-			or $r['autozip']
157
-		) {
158
-			$dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
159
-			break;
160
-		}
161
-		else {
162
-			$dest = substr($dest, 0, -strlen($m[0]));
163
-			$ext = $m[1] . '.' . $ext;
164
-		}
165
-	}
166
-
167
-	// Si le document "source" est deja au bon endroit, ne rien faire
168
-	if ($source == ($dir . $dest . '.' . $ext)) {
169
-		return $source;
170
-	}
171
-
172
-	// sinon tourner jusqu'a trouver un numero correct
173
-	$n = 0;
174
-	while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
175
-		;
176
-	}
177
-
178
-	return deplacer_fichier_upload($source, $newFile);
140
+    $orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
141
+    $dir = creer_repertoire_documents($subdir ? $subdir : $ext);
142
+
143
+    $dest = preg_replace('/<[^>]*>/', '', basename($orig));
144
+    $dest = preg_replace('/\.([^.]+)$/', '', $dest);
145
+    $dest = translitteration($dest);
146
+    $dest = preg_replace('/[^.=\w-]+/', '_', $dest);
147
+
148
+    // ne pas accepter de noms de la forme -r90.jpg qui sont reserves
149
+    // pour les images transformees par rotation (action/documenter)
150
+    $dest = preg_replace(',-r(90|180|270)$,', '', $dest);
151
+
152
+    while (preg_match(',\.(\w+)$,', $dest, $m)) {
153
+        if (
154
+            !function_exists('verifier_upload_autorise')
155
+            or !$r = verifier_upload_autorise($dest)
156
+            or $r['autozip']
157
+        ) {
158
+            $dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
159
+            break;
160
+        }
161
+        else {
162
+            $dest = substr($dest, 0, -strlen($m[0]));
163
+            $ext = $m[1] . '.' . $ext;
164
+        }
165
+    }
166
+
167
+    // Si le document "source" est deja au bon endroit, ne rien faire
168
+    if ($source == ($dir . $dest . '.' . $ext)) {
169
+        return $source;
170
+    }
171
+
172
+    // sinon tourner jusqu'a trouver un numero correct
173
+    $n = 0;
174
+    while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
175
+        ;
176
+    }
177
+
178
+    return deplacer_fichier_upload($source, $newFile);
179 179
 }
180 180
 
181 181
 /**
@@ -190,28 +190,28 @@  discard block
 block discarded – undo
190 190
  * @return bool|string
191 191
  */
192 192
 function determine_upload($type = '') {
193
-	if (!function_exists('autoriser')) {
194
-		include_spip('inc/autoriser');
195
-	}
196
-
197
-	if (
198
-		!autoriser('chargerftp')
199
-		or $type == 'logos'
200
-	) { # on ne le permet pas pour les logos
201
-	return false;
202
-	}
203
-
204
-	$repertoire = _DIR_TRANSFERT;
205
-	if (!@is_dir($repertoire)) {
206
-		$repertoire = str_replace(_DIR_TMP, '', $repertoire);
207
-		$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
208
-	}
209
-
210
-	if (!$GLOBALS['visiteur_session']['restreint']) {
211
-		return $repertoire;
212
-	} else {
213
-		return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
214
-	}
193
+    if (!function_exists('autoriser')) {
194
+        include_spip('inc/autoriser');
195
+    }
196
+
197
+    if (
198
+        !autoriser('chargerftp')
199
+        or $type == 'logos'
200
+    ) { # on ne le permet pas pour les logos
201
+    return false;
202
+    }
203
+
204
+    $repertoire = _DIR_TRANSFERT;
205
+    if (!@is_dir($repertoire)) {
206
+        $repertoire = str_replace(_DIR_TMP, '', $repertoire);
207
+        $repertoire = sous_repertoire(_DIR_TMP, $repertoire);
208
+    }
209
+
210
+    if (!$GLOBALS['visiteur_session']['restreint']) {
211
+        return $repertoire;
212
+    } else {
213
+        return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
214
+    }
215 215
 }
216 216
 
217 217
 /**
@@ -230,35 +230,35 @@  discard block
 block discarded – undo
230 230
  * @return bool|mixed|string
231 231
  */
232 232
 function deplacer_fichier_upload($source, $dest, $move = false) {
233
-	// Securite
234
-	if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
235
-		$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
236
-	} else {
237
-		$dest = preg_replace(',\.\.+,', '.', $dest);
238
-	}
239
-
240
-	if ($move) {
241
-		$ok = @rename($source, $dest);
242
-	} else {
243
-		$ok = @copy($source, $dest);
244
-	}
245
-	if (!$ok) {
246
-		$ok = @move_uploaded_file($source, $dest);
247
-	}
248
-	if ($ok) {
249
-		@chmod($dest, _SPIP_CHMOD & ~0111);
250
-	} else {
251
-		$f = @fopen($dest, 'w');
252
-		if ($f) {
253
-			fclose($f);
254
-		} else {
255
-			include_spip('inc/flock');
256
-			raler_fichier($dest);
257
-		}
258
-		spip_unlink($dest);
259
-	}
260
-
261
-	return $ok ? $dest : false;
233
+    // Securite
234
+    if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
235
+        $dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
236
+    } else {
237
+        $dest = preg_replace(',\.\.+,', '.', $dest);
238
+    }
239
+
240
+    if ($move) {
241
+        $ok = @rename($source, $dest);
242
+    } else {
243
+        $ok = @copy($source, $dest);
244
+    }
245
+    if (!$ok) {
246
+        $ok = @move_uploaded_file($source, $dest);
247
+    }
248
+    if ($ok) {
249
+        @chmod($dest, _SPIP_CHMOD & ~0111);
250
+    } else {
251
+        $f = @fopen($dest, 'w');
252
+        if ($f) {
253
+            fclose($f);
254
+        } else {
255
+            include_spip('inc/flock');
256
+            raler_fichier($dest);
257
+        }
258
+        spip_unlink($dest);
259
+    }
260
+
261
+    return $ok ? $dest : false;
262 262
 }
263 263
 
264 264
 
@@ -282,60 +282,60 @@  discard block
 block discarded – undo
282 282
  */
283 283
 function check_upload_error($error, $msg = '', $return = false) {
284 284
 
285
-	if (!$error) {
286
-		return false;
287
-	}
288
-
289
-	spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
290
-
291
-	switch ($error) {
292
-		case 4: /* UPLOAD_ERR_NO_FILE */
293
-			return true;
294
-
295
-		# on peut affiner les differents messages d'erreur
296
-		case 1: /* UPLOAD_ERR_INI_SIZE */
297
-			$msg = _T(
298
-				'upload_limit',
299
-				['max' => ini_get('upload_max_filesize')]
300
-			);
301
-			break;
302
-		case 2: /* UPLOAD_ERR_FORM_SIZE */
303
-			$msg = _T(
304
-				'upload_limit',
305
-				['max' => ini_get('upload_max_filesize')]
306
-			);
307
-			break;
308
-		case 3: /* UPLOAD_ERR_PARTIAL  */
309
-			$msg = _T(
310
-				'upload_limit',
311
-				['max' => ini_get('upload_max_filesize')]
312
-			);
313
-			break;
314
-
315
-		default: /* autre */
316
-			if (!$msg) {
317
-				$msg = _T('pass_erreur') . ' ' . $error
318
-					. '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
319
-			}
320
-			break;
321
-	}
322
-
323
-	spip_log("erreur upload $error");
324
-	if ($return) {
325
-		return $msg;
326
-	}
327
-
328
-	if (_request('iframe') == 'iframe') {
329
-		echo "<div class='upload_answer upload_error'>$msg</div>";
330
-		exit;
331
-	}
332
-
333
-	include_spip('inc/minipres');
334
-	echo minipres(
335
-		$msg,
336
-		"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
337
-	);
338
-	exit;
285
+    if (!$error) {
286
+        return false;
287
+    }
288
+
289
+    spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
290
+
291
+    switch ($error) {
292
+        case 4: /* UPLOAD_ERR_NO_FILE */
293
+            return true;
294
+
295
+        # on peut affiner les differents messages d'erreur
296
+        case 1: /* UPLOAD_ERR_INI_SIZE */
297
+            $msg = _T(
298
+                'upload_limit',
299
+                ['max' => ini_get('upload_max_filesize')]
300
+            );
301
+            break;
302
+        case 2: /* UPLOAD_ERR_FORM_SIZE */
303
+            $msg = _T(
304
+                'upload_limit',
305
+                ['max' => ini_get('upload_max_filesize')]
306
+            );
307
+            break;
308
+        case 3: /* UPLOAD_ERR_PARTIAL  */
309
+            $msg = _T(
310
+                'upload_limit',
311
+                ['max' => ini_get('upload_max_filesize')]
312
+            );
313
+            break;
314
+
315
+        default: /* autre */
316
+            if (!$msg) {
317
+                $msg = _T('pass_erreur') . ' ' . $error
318
+                    . '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
319
+            }
320
+            break;
321
+    }
322
+
323
+    spip_log("erreur upload $error");
324
+    if ($return) {
325
+        return $msg;
326
+    }
327
+
328
+    if (_request('iframe') == 'iframe') {
329
+        echo "<div class='upload_answer upload_error'>$msg</div>";
330
+        exit;
331
+    }
332
+
333
+    include_spip('inc/minipres');
334
+    echo minipres(
335
+        $msg,
336
+        "<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
337
+    );
338
+    exit;
339 339
 }
340 340
 
341 341
 /**
@@ -352,24 +352,24 @@  discard block
 block discarded – undo
352 352
  * @return string
353 353
  */
354 354
 function corriger_extension($ext) {
355
-	$ext = preg_replace(',[^a-z0-9],i', '', $ext);
356
-	switch ($ext) {
357
-		case 'htm':
358
-			$ext = 'html';
359
-			break;
360
-		case 'jpeg':
361
-			$ext = 'jpg';
362
-			break;
363
-		case 'tiff':
364
-			$ext = 'tif';
365
-			break;
366
-		case 'aif':
367
-			$ext = 'aiff';
368
-			break;
369
-		case 'mpeg':
370
-			$ext = 'mpg';
371
-			break;
372
-	}
373
-
374
-	return $ext;
355
+    $ext = preg_replace(',[^a-z0-9],i', '', $ext);
356
+    switch ($ext) {
357
+        case 'htm':
358
+            $ext = 'html';
359
+            break;
360
+        case 'jpeg':
361
+            $ext = 'jpg';
362
+            break;
363
+        case 'tiff':
364
+            $ext = 'tif';
365
+            break;
366
+        case 'aif':
367
+            $ext = 'aiff';
368
+            break;
369
+        case 'mpeg':
370
+            $ext = 'mpg';
371
+            break;
372
+    }
373
+
374
+    return $ext;
375 375
 }
Please login to merge, or discard this patch.
ecrire/inc/distant.php 1 patch
Indentation   +1046 added lines, -1046 removed lines patch added patch discarded remove patch
@@ -16,32 +16,32 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Distant
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 if (!defined('_INC_DISTANT_VERSION_HTTP')) {
23
-	define('_INC_DISTANT_VERSION_HTTP', 'HTTP/1.0');
23
+    define('_INC_DISTANT_VERSION_HTTP', 'HTTP/1.0');
24 24
 }
25 25
 if (!defined('_INC_DISTANT_CONTENT_ENCODING')) {
26
-	define('_INC_DISTANT_CONTENT_ENCODING', 'gzip');
26
+    define('_INC_DISTANT_CONTENT_ENCODING', 'gzip');
27 27
 }
28 28
 if (!defined('_INC_DISTANT_USER_AGENT')) {
29
-	define('_INC_DISTANT_USER_AGENT', 'SPIP-' . $GLOBALS['spip_version_affichee'] . ' (' . $GLOBALS['home_server'] . ')');
29
+    define('_INC_DISTANT_USER_AGENT', 'SPIP-' . $GLOBALS['spip_version_affichee'] . ' (' . $GLOBALS['home_server'] . ')');
30 30
 }
31 31
 if (!defined('_INC_DISTANT_MAX_SIZE')) {
32
-	define('_INC_DISTANT_MAX_SIZE', 2097152);
32
+    define('_INC_DISTANT_MAX_SIZE', 2097152);
33 33
 }
34 34
 if (!defined('_INC_DISTANT_CONNECT_TIMEOUT')) {
35
-	define('_INC_DISTANT_CONNECT_TIMEOUT', 10);
35
+    define('_INC_DISTANT_CONNECT_TIMEOUT', 10);
36 36
 }
37 37
 
38 38
 define('_REGEXP_COPIE_LOCALE', ',' 	.
39
-	preg_replace(
40
-		'@^https?:@',
41
-		'https?:',
42
-		(isset($GLOBALS['meta']['adresse_site']) ? $GLOBALS['meta']['adresse_site'] : '')
43
-	)
44
-	. '/?spip.php[?]action=acceder_document.*file=(.*)$,');
39
+    preg_replace(
40
+        '@^https?:@',
41
+        'https?:',
42
+        (isset($GLOBALS['meta']['adresse_site']) ? $GLOBALS['meta']['adresse_site'] : '')
43
+    )
44
+    . '/?spip.php[?]action=acceder_document.*file=(.*)$,');
45 45
 
46 46
 //@define('_COPIE_LOCALE_MAX_SIZE',2097152); // poids (inc/utils l'a fait)
47 47
 
@@ -68,89 +68,89 @@  discard block
 block discarded – undo
68 68
  */
69 69
 function copie_locale($source, $mode = 'auto', $local = null, $taille_max = null) {
70 70
 
71
-	// si c'est la protection de soi-meme, retourner le path
72
-	if ($mode !== 'force' and preg_match(_REGEXP_COPIE_LOCALE, $source, $match)) {
73
-		$source = substr(_DIR_IMG, strlen(_DIR_RACINE)) . urldecode($match[1]);
74
-
75
-		return @file_exists($source) ? $source : false;
76
-	}
77
-
78
-	if (is_null($local)) {
79
-		$local = fichier_copie_locale($source);
80
-	} else {
81
-		if (_DIR_RACINE and strncmp(_DIR_RACINE, $local, strlen(_DIR_RACINE)) == 0) {
82
-			$local = substr($local, strlen(_DIR_RACINE));
83
-		}
84
-	}
85
-
86
-	// si $local = '' c'est un fichier refuse par fichier_copie_locale(),
87
-	// par exemple un fichier qui ne figure pas dans nos documents ;
88
-	// dans ce cas on n'essaie pas de le telecharger pour ensuite echouer
89
-	if (!$local) {
90
-		return false;
91
-	}
92
-
93
-	$localrac = _DIR_RACINE . $local;
94
-	$t = ($mode === 'force') ? false : @file_exists($localrac);
95
-
96
-	// test d'existence du fichier
97
-	if ($mode === 'test') {
98
-		return $t ? $local : '';
99
-	}
100
-
101
-	// sinon voir si on doit/peut le telecharger
102
-	if ($local === $source or !tester_url_absolue($source)) {
103
-		return $local;
104
-	}
105
-
106
-	if ($mode === 'modif' or !$t) {
107
-		// passer par un fichier temporaire unique pour gerer les echecs en cours de recuperation
108
-		// et des eventuelles recuperations concurantes
109
-		include_spip('inc/acces');
110
-		if (!$taille_max) {
111
-			$taille_max = _COPIE_LOCALE_MAX_SIZE;
112
-		}
113
-		$res = recuperer_url(
114
-			$source,
115
-			['file' => $localrac, 'taille_max' => $taille_max, 'if_modified_since' => $t ? filemtime($localrac) : '']
116
-		);
117
-		if (!$res or (!$res['length'] and $res['status'] != 304)) {
118
-			spip_log("copie_locale : Echec recuperation $source sur $localrac status : " . ($res ? $res['status'] : '-'), 'distant' . _LOG_INFO_IMPORTANTE);
119
-		}
120
-		else {
121
-			spip_log("copie_locale : recuperation $source sur $localrac OK | taille " . $res['length'] . ' status ' . $res['status'], 'distant');
122
-		}
123
-		if (!$res or !$res['length']) {
124
-			// si $t c'est sans doute juste un not-modified-since
125
-			return $t ? $local : false;
126
-		}
127
-
128
-		// si on retrouve l'extension
129
-		if (
130
-			!empty($res['headers'])
131
-			and $extension = distant_trouver_extension_selon_headers($source, $res['headers'])
132
-		) {
133
-			if ($sanitizer = charger_fonction($extension, 'sanitizer', true)) {
134
-				$sanitizer($localrac);
135
-			}
136
-		}
137
-
138
-		// pour une eventuelle indexation
139
-		pipeline(
140
-			'post_edition',
141
-			[
142
-				'args' => [
143
-					'operation' => 'copie_locale',
144
-					'source' => $source,
145
-					'fichier' => $local,
146
-					'http_res' => $res['length'],
147
-				],
148
-				'data' => null
149
-			]
150
-		);
151
-	}
152
-
153
-	return $local;
71
+    // si c'est la protection de soi-meme, retourner le path
72
+    if ($mode !== 'force' and preg_match(_REGEXP_COPIE_LOCALE, $source, $match)) {
73
+        $source = substr(_DIR_IMG, strlen(_DIR_RACINE)) . urldecode($match[1]);
74
+
75
+        return @file_exists($source) ? $source : false;
76
+    }
77
+
78
+    if (is_null($local)) {
79
+        $local = fichier_copie_locale($source);
80
+    } else {
81
+        if (_DIR_RACINE and strncmp(_DIR_RACINE, $local, strlen(_DIR_RACINE)) == 0) {
82
+            $local = substr($local, strlen(_DIR_RACINE));
83
+        }
84
+    }
85
+
86
+    // si $local = '' c'est un fichier refuse par fichier_copie_locale(),
87
+    // par exemple un fichier qui ne figure pas dans nos documents ;
88
+    // dans ce cas on n'essaie pas de le telecharger pour ensuite echouer
89
+    if (!$local) {
90
+        return false;
91
+    }
92
+
93
+    $localrac = _DIR_RACINE . $local;
94
+    $t = ($mode === 'force') ? false : @file_exists($localrac);
95
+
96
+    // test d'existence du fichier
97
+    if ($mode === 'test') {
98
+        return $t ? $local : '';
99
+    }
100
+
101
+    // sinon voir si on doit/peut le telecharger
102
+    if ($local === $source or !tester_url_absolue($source)) {
103
+        return $local;
104
+    }
105
+
106
+    if ($mode === 'modif' or !$t) {
107
+        // passer par un fichier temporaire unique pour gerer les echecs en cours de recuperation
108
+        // et des eventuelles recuperations concurantes
109
+        include_spip('inc/acces');
110
+        if (!$taille_max) {
111
+            $taille_max = _COPIE_LOCALE_MAX_SIZE;
112
+        }
113
+        $res = recuperer_url(
114
+            $source,
115
+            ['file' => $localrac, 'taille_max' => $taille_max, 'if_modified_since' => $t ? filemtime($localrac) : '']
116
+        );
117
+        if (!$res or (!$res['length'] and $res['status'] != 304)) {
118
+            spip_log("copie_locale : Echec recuperation $source sur $localrac status : " . ($res ? $res['status'] : '-'), 'distant' . _LOG_INFO_IMPORTANTE);
119
+        }
120
+        else {
121
+            spip_log("copie_locale : recuperation $source sur $localrac OK | taille " . $res['length'] . ' status ' . $res['status'], 'distant');
122
+        }
123
+        if (!$res or !$res['length']) {
124
+            // si $t c'est sans doute juste un not-modified-since
125
+            return $t ? $local : false;
126
+        }
127
+
128
+        // si on retrouve l'extension
129
+        if (
130
+            !empty($res['headers'])
131
+            and $extension = distant_trouver_extension_selon_headers($source, $res['headers'])
132
+        ) {
133
+            if ($sanitizer = charger_fonction($extension, 'sanitizer', true)) {
134
+                $sanitizer($localrac);
135
+            }
136
+        }
137
+
138
+        // pour une eventuelle indexation
139
+        pipeline(
140
+            'post_edition',
141
+            [
142
+                'args' => [
143
+                    'operation' => 'copie_locale',
144
+                    'source' => $source,
145
+                    'fichier' => $local,
146
+                    'http_res' => $res['length'],
147
+                ],
148
+                'data' => null
149
+            ]
150
+        );
151
+    }
152
+
153
+    return $local;
154 154
 }
155 155
 
156 156
 /**
@@ -165,99 +165,99 @@  discard block
 block discarded – undo
165 165
  *   url ou false en cas d'echec
166 166
  */
167 167
 function valider_url_distante($url, $known_hosts = []) {
168
-	if (!function_exists('protocole_verifier')) {
169
-		include_spip('inc/filtres_mini');
170
-	}
171
-
172
-	if (!protocole_verifier($url, ['http', 'https'])) {
173
-		return false;
174
-	}
175
-
176
-	$parsed_url = parse_url($url);
177
-	if (!$parsed_url or empty($parsed_url['host'])) {
178
-		return false;
179
-	}
180
-
181
-	if (isset($parsed_url['user']) or isset($parsed_url['pass'])) {
182
-		return false;
183
-	}
184
-
185
-	if (false !== strpbrk($parsed_url['host'], ':#?[]')) {
186
-		return false;
187
-	}
188
-
189
-	if (!is_array($known_hosts)) {
190
-		$known_hosts = [$known_hosts];
191
-	}
192
-	$known_hosts[] = $GLOBALS['meta']['adresse_site'];
193
-	$known_hosts[] = url_de_base();
194
-	$known_hosts = pipeline('declarer_hosts_distants', $known_hosts);
195
-
196
-	$is_known_host = false;
197
-	foreach ($known_hosts as $known_host) {
198
-		$parse_known = parse_url($known_host);
199
-		if (
200
-			$parse_known
201
-			and strtolower($parse_known['host']) === strtolower($parsed_url['host'])
202
-		) {
203
-			$is_known_host = true;
204
-			break;
205
-		}
206
-	}
207
-
208
-	if (!$is_known_host) {
209
-		$host = trim($parsed_url['host'], '.');
210
-		if (! $ip = filter_var($host, FILTER_VALIDATE_IP)) {
211
-			$ip = gethostbyname($host);
212
-			if ($ip === $host) {
213
-				// Error condition for gethostbyname()
214
-				$ip = false;
215
-			}
216
-			if ($records = dns_get_record($host)) {
217
-				foreach ($records as $record) {
218
-					// il faut que le TTL soit suffisant afin d'etre certain que le copie_locale eventuel qui suit
219
-					// se fasse sur la meme IP
220
-					if ($record['ttl'] < 10) {
221
-						$ip = false;
222
-						break;
223
-					}
224
-				}
225
-			}
226
-			else {
227
-				$ip = false;
228
-			}
229
-		}
230
-		if ($ip) {
231
-			if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
232
-				return false;
233
-			}
234
-		}
235
-	}
236
-
237
-	if (empty($parsed_url['port'])) {
238
-		return $url;
239
-	}
240
-
241
-	$port = $parsed_url['port'];
242
-	if ($port === 80  or $port === 443  or $port === 8080) {
243
-		return $url;
244
-	}
245
-
246
-	if ($is_known_host) {
247
-		foreach ($known_hosts as $known_host) {
248
-			$parse_known = parse_url($known_host);
249
-			if (
250
-				$parse_known
251
-				and !empty($parse_known['port'])
252
-				and strtolower($parse_known['host']) === strtolower($parsed_url['host'])
253
-				and $parse_known['port'] == $port
254
-			) {
255
-				return $url;
256
-			}
257
-		}
258
-	}
259
-
260
-	return false;
168
+    if (!function_exists('protocole_verifier')) {
169
+        include_spip('inc/filtres_mini');
170
+    }
171
+
172
+    if (!protocole_verifier($url, ['http', 'https'])) {
173
+        return false;
174
+    }
175
+
176
+    $parsed_url = parse_url($url);
177
+    if (!$parsed_url or empty($parsed_url['host'])) {
178
+        return false;
179
+    }
180
+
181
+    if (isset($parsed_url['user']) or isset($parsed_url['pass'])) {
182
+        return false;
183
+    }
184
+
185
+    if (false !== strpbrk($parsed_url['host'], ':#?[]')) {
186
+        return false;
187
+    }
188
+
189
+    if (!is_array($known_hosts)) {
190
+        $known_hosts = [$known_hosts];
191
+    }
192
+    $known_hosts[] = $GLOBALS['meta']['adresse_site'];
193
+    $known_hosts[] = url_de_base();
194
+    $known_hosts = pipeline('declarer_hosts_distants', $known_hosts);
195
+
196
+    $is_known_host = false;
197
+    foreach ($known_hosts as $known_host) {
198
+        $parse_known = parse_url($known_host);
199
+        if (
200
+            $parse_known
201
+            and strtolower($parse_known['host']) === strtolower($parsed_url['host'])
202
+        ) {
203
+            $is_known_host = true;
204
+            break;
205
+        }
206
+    }
207
+
208
+    if (!$is_known_host) {
209
+        $host = trim($parsed_url['host'], '.');
210
+        if (! $ip = filter_var($host, FILTER_VALIDATE_IP)) {
211
+            $ip = gethostbyname($host);
212
+            if ($ip === $host) {
213
+                // Error condition for gethostbyname()
214
+                $ip = false;
215
+            }
216
+            if ($records = dns_get_record($host)) {
217
+                foreach ($records as $record) {
218
+                    // il faut que le TTL soit suffisant afin d'etre certain que le copie_locale eventuel qui suit
219
+                    // se fasse sur la meme IP
220
+                    if ($record['ttl'] < 10) {
221
+                        $ip = false;
222
+                        break;
223
+                    }
224
+                }
225
+            }
226
+            else {
227
+                $ip = false;
228
+            }
229
+        }
230
+        if ($ip) {
231
+            if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
232
+                return false;
233
+            }
234
+        }
235
+    }
236
+
237
+    if (empty($parsed_url['port'])) {
238
+        return $url;
239
+    }
240
+
241
+    $port = $parsed_url['port'];
242
+    if ($port === 80  or $port === 443  or $port === 8080) {
243
+        return $url;
244
+    }
245
+
246
+    if ($is_known_host) {
247
+        foreach ($known_hosts as $known_host) {
248
+            $parse_known = parse_url($known_host);
249
+            if (
250
+                $parse_known
251
+                and !empty($parse_known['port'])
252
+                and strtolower($parse_known['host']) === strtolower($parsed_url['host'])
253
+                and $parse_known['port'] == $port
254
+            ) {
255
+                return $url;
256
+            }
257
+        }
258
+    }
259
+
260
+    return false;
261 261
 }
262 262
 
263 263
 /**
@@ -277,86 +277,86 @@  discard block
 block discarded – undo
277 277
  */
278 278
 function prepare_donnees_post($donnees, $boundary = '') {
279 279
 
280
-	// permettre a la fonction qui a demande le post de formater elle meme ses donnees
281
-	// pour un appel soap par exemple
282
-	// l'entete est separe des donnees par un double retour a la ligne
283
-	// on s'occupe ici de passer tous les retours lignes (\r\n, \r ou \n) en \r\n
284
-	if (is_string($donnees) && strlen($donnees)) {
285
-		$entete = '';
286
-		// on repasse tous les \r\n et \r en simples \n
287
-		$donnees = str_replace("\r\n", "\n", $donnees);
288
-		$donnees = str_replace("\r", "\n", $donnees);
289
-		// un double retour a la ligne signifie la fin de l'entete et le debut des donnees
290
-		$p = strpos($donnees, "\n\n");
291
-		if ($p !== false) {
292
-			$entete = str_replace("\n", "\r\n", substr($donnees, 0, $p + 1));
293
-			$donnees = substr($donnees, $p + 2);
294
-		}
295
-		$chaine = str_replace("\n", "\r\n", $donnees);
296
-	} else {
297
-		/* boundary automatique */
298
-		// Si on a plus de 500 octects de donnees, on "boundarise"
299
-		if ($boundary === '') {
300
-			$taille = 0;
301
-			foreach ($donnees as $cle => $valeur) {
302
-				if (is_array($valeur)) {
303
-					foreach ($valeur as $val2) {
304
-						$taille += strlen($val2);
305
-					}
306
-				} else {
307
-					// faut-il utiliser spip_strlen() dans inc/charsets ?
308
-					$taille += strlen($valeur);
309
-				}
310
-			}
311
-			if ($taille > 500) {
312
-				$boundary = substr(md5(rand() . 'spip'), 0, 8);
313
-			}
314
-		}
315
-
316
-		if (is_string($boundary) and strlen($boundary)) {
317
-			// fabrique une chaine HTTP pour un POST avec boundary
318
-			$entete = "Content-Type: multipart/form-data; boundary=$boundary\r\n";
319
-			$chaine = '';
320
-			if (is_array($donnees)) {
321
-				foreach ($donnees as $cle => $valeur) {
322
-					if (is_array($valeur)) {
323
-						foreach ($valeur as $val2) {
324
-							$chaine .= "\r\n--$boundary\r\n";
325
-							$chaine .= "Content-Disposition: form-data; name=\"{$cle}[]\"\r\n";
326
-							$chaine .= "\r\n";
327
-							$chaine .= $val2;
328
-						}
329
-					} else {
330
-						$chaine .= "\r\n--$boundary\r\n";
331
-						$chaine .= "Content-Disposition: form-data; name=\"$cle\"\r\n";
332
-						$chaine .= "\r\n";
333
-						$chaine .= $valeur;
334
-					}
335
-				}
336
-				$chaine .= "\r\n--$boundary\r\n";
337
-			}
338
-		} else {
339
-			// fabrique une chaine HTTP simple pour un POST
340
-			$entete = 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
341
-			$chaine = [];
342
-			if (is_array($donnees)) {
343
-				foreach ($donnees as $cle => $valeur) {
344
-					if (is_array($valeur)) {
345
-						foreach ($valeur as $val2) {
346
-							$chaine[] = rawurlencode($cle) . '[]=' . rawurlencode($val2);
347
-						}
348
-					} else {
349
-						$chaine[] = rawurlencode($cle) . '=' . rawurlencode($valeur);
350
-					}
351
-				}
352
-				$chaine = implode('&', $chaine);
353
-			} else {
354
-				$chaine = $donnees;
355
-			}
356
-		}
357
-	}
358
-
359
-	return [$entete, $chaine];
280
+    // permettre a la fonction qui a demande le post de formater elle meme ses donnees
281
+    // pour un appel soap par exemple
282
+    // l'entete est separe des donnees par un double retour a la ligne
283
+    // on s'occupe ici de passer tous les retours lignes (\r\n, \r ou \n) en \r\n
284
+    if (is_string($donnees) && strlen($donnees)) {
285
+        $entete = '';
286
+        // on repasse tous les \r\n et \r en simples \n
287
+        $donnees = str_replace("\r\n", "\n", $donnees);
288
+        $donnees = str_replace("\r", "\n", $donnees);
289
+        // un double retour a la ligne signifie la fin de l'entete et le debut des donnees
290
+        $p = strpos($donnees, "\n\n");
291
+        if ($p !== false) {
292
+            $entete = str_replace("\n", "\r\n", substr($donnees, 0, $p + 1));
293
+            $donnees = substr($donnees, $p + 2);
294
+        }
295
+        $chaine = str_replace("\n", "\r\n", $donnees);
296
+    } else {
297
+        /* boundary automatique */
298
+        // Si on a plus de 500 octects de donnees, on "boundarise"
299
+        if ($boundary === '') {
300
+            $taille = 0;
301
+            foreach ($donnees as $cle => $valeur) {
302
+                if (is_array($valeur)) {
303
+                    foreach ($valeur as $val2) {
304
+                        $taille += strlen($val2);
305
+                    }
306
+                } else {
307
+                    // faut-il utiliser spip_strlen() dans inc/charsets ?
308
+                    $taille += strlen($valeur);
309
+                }
310
+            }
311
+            if ($taille > 500) {
312
+                $boundary = substr(md5(rand() . 'spip'), 0, 8);
313
+            }
314
+        }
315
+
316
+        if (is_string($boundary) and strlen($boundary)) {
317
+            // fabrique une chaine HTTP pour un POST avec boundary
318
+            $entete = "Content-Type: multipart/form-data; boundary=$boundary\r\n";
319
+            $chaine = '';
320
+            if (is_array($donnees)) {
321
+                foreach ($donnees as $cle => $valeur) {
322
+                    if (is_array($valeur)) {
323
+                        foreach ($valeur as $val2) {
324
+                            $chaine .= "\r\n--$boundary\r\n";
325
+                            $chaine .= "Content-Disposition: form-data; name=\"{$cle}[]\"\r\n";
326
+                            $chaine .= "\r\n";
327
+                            $chaine .= $val2;
328
+                        }
329
+                    } else {
330
+                        $chaine .= "\r\n--$boundary\r\n";
331
+                        $chaine .= "Content-Disposition: form-data; name=\"$cle\"\r\n";
332
+                        $chaine .= "\r\n";
333
+                        $chaine .= $valeur;
334
+                    }
335
+                }
336
+                $chaine .= "\r\n--$boundary\r\n";
337
+            }
338
+        } else {
339
+            // fabrique une chaine HTTP simple pour un POST
340
+            $entete = 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
341
+            $chaine = [];
342
+            if (is_array($donnees)) {
343
+                foreach ($donnees as $cle => $valeur) {
344
+                    if (is_array($valeur)) {
345
+                        foreach ($valeur as $val2) {
346
+                            $chaine[] = rawurlencode($cle) . '[]=' . rawurlencode($val2);
347
+                        }
348
+                    } else {
349
+                        $chaine[] = rawurlencode($cle) . '=' . rawurlencode($valeur);
350
+                    }
351
+                }
352
+                $chaine = implode('&', $chaine);
353
+            } else {
354
+                $chaine = $donnees;
355
+            }
356
+        }
357
+    }
358
+
359
+    return [$entete, $chaine];
360 360
 }
361 361
 
362 362
 /**
@@ -370,22 +370,22 @@  discard block
 block discarded – undo
370 370
  */
371 371
 function url_to_ascii($url_idn) {
372 372
 
373
-	if ($parts = parse_url($url_idn)) {
374
-		$host = $parts['host'];
375
-		if (!preg_match(',^[a-z0-9_\.\-]+$,i', $host)) {
376
-			include_spip('inc/idna_convert.class');
377
-			$IDN = new idna_convert();
378
-			$host_ascii = $IDN->encode($host);
379
-			$url_idn = explode($host, $url_idn, 2);
380
-			$url_idn = implode($host_ascii, $url_idn);
381
-		}
382
-		// et on urlencode les char utf si besoin dans le path
383
-		$url_idn = preg_replace_callback('/[^\x20-\x7f]/', function ($match) {
384
- return urlencode($match[0]);
385
-		}, $url_idn);
386
-	}
387
-
388
-	return $url_idn;
373
+    if ($parts = parse_url($url_idn)) {
374
+        $host = $parts['host'];
375
+        if (!preg_match(',^[a-z0-9_\.\-]+$,i', $host)) {
376
+            include_spip('inc/idna_convert.class');
377
+            $IDN = new idna_convert();
378
+            $host_ascii = $IDN->encode($host);
379
+            $url_idn = explode($host, $url_idn, 2);
380
+            $url_idn = implode($host_ascii, $url_idn);
381
+        }
382
+        // et on urlencode les char utf si besoin dans le path
383
+        $url_idn = preg_replace_callback('/[^\x20-\x7f]/', function ($match) {
384
+    return urlencode($match[0]);
385
+        }, $url_idn);
386
+    }
387
+
388
+    return $url_idn;
389 389
 }
390 390
 
391 391
 /**
@@ -426,197 +426,197 @@  discard block
 block discarded – undo
426 426
  *     string file : nom du fichier si enregistre dans un fichier
427 427
  */
428 428
 function recuperer_url($url, $options = []) {
429
-	// Conserve la mémoire de la méthode fournit éventuellement
430
-	$methode_demandee = $options['methode'] ?? '';
431
-	$default = [
432
-		'transcoder' => false,
433
-		'methode' => 'GET',
434
-		'taille_max' => null,
435
-		'headers' => [],
436
-		'datas' => '',
437
-		'boundary' => '',
438
-		'refuser_gz' => false,
439
-		'if_modified_since' => '',
440
-		'uri_referer' => '',
441
-		'file' => '',
442
-		'follow_location' => 10,
443
-		'version_http' => _INC_DISTANT_VERSION_HTTP,
444
-	];
445
-	$options = array_merge($default, $options);
446
-	// copier directement dans un fichier ?
447
-	$copy = $options['file'];
448
-
449
-	if ($options['methode'] == 'HEAD') {
450
-		$options['taille_max'] = 0;
451
-	}
452
-	if (is_null($options['taille_max'])) {
453
-		$options['taille_max'] = $copy ? _COPIE_LOCALE_MAX_SIZE : _INC_DISTANT_MAX_SIZE;
454
-	}
455
-
456
-
457
-	// Ajout des en-têtes spécifiques si besoin
458
-	$head_add = '';
459
-	if (!empty($options['headers'])) {
460
-		foreach ($options['headers'] as $champ => $valeur) {
461
-			$head_add .= $champ . ': ' . $valeur . "\r\n";
462
-		}
463
-		// ne pas le repasser a recuperer_url si on follow un location, car ils seront dans datas
464
-		unset($options['headers']);
465
-	}
466
-
467
-	if (!empty($options['datas'])) {
468
-		list($head, $postdata) = prepare_donnees_post($options['datas'], $options['boundary']);
469
-		$head .= $head_add;
470
-		if (stripos($head, 'Content-Length:') === false) {
471
-			$head .= 'Content-Length: ' . strlen($postdata) . "\r\n";
472
-		}
473
-		$options['datas'] = $head . "\r\n" . $postdata;
474
-		if (
475
-			strlen($postdata)
476
-			and !$methode_demandee
477
-		) {
478
-			$options['methode'] = 'POST';
479
-		}
480
-	} elseif ($head_add) {
481
-		$options['datas'] = $head_add . "\r\n";
482
-	}
483
-
484
-	// Accepter les URLs au format feed:// ou qui ont oublie le http:// ou les urls relatives au protocole
485
-	$url = preg_replace(',^feed://,i', 'http://', $url);
486
-	if (!tester_url_absolue($url)) {
487
-		$url = 'http://' . $url;
488
-	} elseif (strncmp($url, '//', 2) == 0) {
489
-		$url = 'http:' . $url;
490
-	}
491
-
492
-	$url = url_to_ascii($url);
493
-
494
-	$result = [
495
-		'status' => 0,
496
-		'headers' => '',
497
-		'page' => '',
498
-		'length' => 0,
499
-		'last_modified' => '',
500
-		'location' => '',
501
-		'url' => $url
502
-	];
503
-
504
-	// si on ecrit directement dans un fichier, pour ne pas manipuler en memoire refuser gz
505
-	$refuser_gz = (($options['refuser_gz'] or $copy) ? true : false);
506
-
507
-	// ouvrir la connexion et envoyer la requete et ses en-tetes
508
-	list($handle, $fopen) = init_http(
509
-		$options['methode'],
510
-		$url,
511
-		$refuser_gz,
512
-		$options['uri_referer'],
513
-		$options['datas'],
514
-		$options['version_http'],
515
-		$options['if_modified_since']
516
-	);
517
-	if (!$handle) {
518
-		spip_log("ECHEC init_http $url", 'distant' . _LOG_ERREUR);
519
-
520
-		return false;
521
-	}
522
-
523
-	// Sauf en fopen, envoyer le flux d'entree
524
-	// et recuperer les en-tetes de reponses
525
-	if (!$fopen) {
526
-		$res = recuperer_entetes_complets($handle, $options['if_modified_since']);
527
-		if (!$res) {
528
-			fclose($handle);
529
-			$t = @parse_url($url);
530
-			$host = $t['host'];
531
-			// Chinoisierie inexplicable pour contrer
532
-			// les actions liberticides de l'empire du milieu
533
-			if (
534
-				!need_proxy($host)
535
-				and $res = @file_get_contents($url)
536
-			) {
537
-				$result['length'] = strlen($res);
538
-				if ($copy) {
539
-					ecrire_fichier($copy, $res);
540
-					$result['file'] = $copy;
541
-				} else {
542
-					$result['page'] = $res;
543
-				}
544
-				$res = [
545
-					'status' => 200,
546
-				];
547
-			} else {
548
-				spip_log("ECHEC chinoiserie $url", 'distant' . _LOG_ERREUR);
549
-				return false;
550
-			}
551
-		} elseif ($res['location'] and $options['follow_location']) {
552
-			$options['follow_location']--;
553
-			fclose($handle);
554
-			include_spip('inc/filtres');
555
-			$url = suivre_lien($url, $res['location']);
556
-			spip_log("recuperer_url recommence sur $url", 'distant');
557
-
558
-			return recuperer_url($url, $options);
559
-		} elseif ($res['status'] !== 200) {
560
-			spip_log('HTTP status ' . $res['status'] . " pour $url", 'distant');
561
-		}
562
-		$result['status'] = $res['status'];
563
-		if (isset($res['headers'])) {
564
-			$result['headers'] = $res['headers'];
565
-		}
566
-		if (isset($res['last_modified'])) {
567
-			$result['last_modified'] = $res['last_modified'];
568
-		}
569
-		if (isset($res['location'])) {
570
-			$result['location'] = $res['location'];
571
-		}
572
-	}
573
-
574
-	// on ne veut que les entetes
575
-	if (!$options['taille_max'] or $options['methode'] == 'HEAD' or $result['status'] == '304') {
576
-		return $result;
577
-	}
578
-
579
-
580
-	// s'il faut deballer, le faire via un fichier temporaire
581
-	// sinon la memoire explose pour les gros flux
582
-
583
-	$gz = false;
584
-	if (preg_match(",\bContent-Encoding: .*gzip,is", $result['headers'])) {
585
-		$gz = (_DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz');
586
-	}
587
-
588
-	// si on a pas deja recuperer le contenu par une methode detournee
589
-	if (!$result['length']) {
590
-		$res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy);
591
-		fclose($handle);
592
-		if ($copy) {
593
-			$result['length'] = $res;
594
-			$result['file'] = $copy;
595
-		} elseif ($res) {
596
-			$result['page'] = &$res;
597
-			$result['length'] = strlen($result['page']);
598
-		}
599
-		if (!$result['status']) {
600
-			$result['status'] = 200; // on a reussi, donc !
601
-		}
602
-	}
603
-	if (!$result['page']) {
604
-		return $result;
605
-	}
606
-
607
-	// Decompresser au besoin
608
-	if ($gz) {
609
-		$result['page'] = implode('', gzfile($gz));
610
-		supprimer_fichier($gz);
611
-	}
612
-
613
-	// Faut-il l'importer dans notre charset local ?
614
-	if ($options['transcoder']) {
615
-		include_spip('inc/charsets');
616
-		$result['page'] = transcoder_page($result['page'], $result['headers']);
617
-	}
618
-
619
-	return $result;
429
+    // Conserve la mémoire de la méthode fournit éventuellement
430
+    $methode_demandee = $options['methode'] ?? '';
431
+    $default = [
432
+        'transcoder' => false,
433
+        'methode' => 'GET',
434
+        'taille_max' => null,
435
+        'headers' => [],
436
+        'datas' => '',
437
+        'boundary' => '',
438
+        'refuser_gz' => false,
439
+        'if_modified_since' => '',
440
+        'uri_referer' => '',
441
+        'file' => '',
442
+        'follow_location' => 10,
443
+        'version_http' => _INC_DISTANT_VERSION_HTTP,
444
+    ];
445
+    $options = array_merge($default, $options);
446
+    // copier directement dans un fichier ?
447
+    $copy = $options['file'];
448
+
449
+    if ($options['methode'] == 'HEAD') {
450
+        $options['taille_max'] = 0;
451
+    }
452
+    if (is_null($options['taille_max'])) {
453
+        $options['taille_max'] = $copy ? _COPIE_LOCALE_MAX_SIZE : _INC_DISTANT_MAX_SIZE;
454
+    }
455
+
456
+
457
+    // Ajout des en-têtes spécifiques si besoin
458
+    $head_add = '';
459
+    if (!empty($options['headers'])) {
460
+        foreach ($options['headers'] as $champ => $valeur) {
461
+            $head_add .= $champ . ': ' . $valeur . "\r\n";
462
+        }
463
+        // ne pas le repasser a recuperer_url si on follow un location, car ils seront dans datas
464
+        unset($options['headers']);
465
+    }
466
+
467
+    if (!empty($options['datas'])) {
468
+        list($head, $postdata) = prepare_donnees_post($options['datas'], $options['boundary']);
469
+        $head .= $head_add;
470
+        if (stripos($head, 'Content-Length:') === false) {
471
+            $head .= 'Content-Length: ' . strlen($postdata) . "\r\n";
472
+        }
473
+        $options['datas'] = $head . "\r\n" . $postdata;
474
+        if (
475
+            strlen($postdata)
476
+            and !$methode_demandee
477
+        ) {
478
+            $options['methode'] = 'POST';
479
+        }
480
+    } elseif ($head_add) {
481
+        $options['datas'] = $head_add . "\r\n";
482
+    }
483
+
484
+    // Accepter les URLs au format feed:// ou qui ont oublie le http:// ou les urls relatives au protocole
485
+    $url = preg_replace(',^feed://,i', 'http://', $url);
486
+    if (!tester_url_absolue($url)) {
487
+        $url = 'http://' . $url;
488
+    } elseif (strncmp($url, '//', 2) == 0) {
489
+        $url = 'http:' . $url;
490
+    }
491
+
492
+    $url = url_to_ascii($url);
493
+
494
+    $result = [
495
+        'status' => 0,
496
+        'headers' => '',
497
+        'page' => '',
498
+        'length' => 0,
499
+        'last_modified' => '',
500
+        'location' => '',
501
+        'url' => $url
502
+    ];
503
+
504
+    // si on ecrit directement dans un fichier, pour ne pas manipuler en memoire refuser gz
505
+    $refuser_gz = (($options['refuser_gz'] or $copy) ? true : false);
506
+
507
+    // ouvrir la connexion et envoyer la requete et ses en-tetes
508
+    list($handle, $fopen) = init_http(
509
+        $options['methode'],
510
+        $url,
511
+        $refuser_gz,
512
+        $options['uri_referer'],
513
+        $options['datas'],
514
+        $options['version_http'],
515
+        $options['if_modified_since']
516
+    );
517
+    if (!$handle) {
518
+        spip_log("ECHEC init_http $url", 'distant' . _LOG_ERREUR);
519
+
520
+        return false;
521
+    }
522
+
523
+    // Sauf en fopen, envoyer le flux d'entree
524
+    // et recuperer les en-tetes de reponses
525
+    if (!$fopen) {
526
+        $res = recuperer_entetes_complets($handle, $options['if_modified_since']);
527
+        if (!$res) {
528
+            fclose($handle);
529
+            $t = @parse_url($url);
530
+            $host = $t['host'];
531
+            // Chinoisierie inexplicable pour contrer
532
+            // les actions liberticides de l'empire du milieu
533
+            if (
534
+                !need_proxy($host)
535
+                and $res = @file_get_contents($url)
536
+            ) {
537
+                $result['length'] = strlen($res);
538
+                if ($copy) {
539
+                    ecrire_fichier($copy, $res);
540
+                    $result['file'] = $copy;
541
+                } else {
542
+                    $result['page'] = $res;
543
+                }
544
+                $res = [
545
+                    'status' => 200,
546
+                ];
547
+            } else {
548
+                spip_log("ECHEC chinoiserie $url", 'distant' . _LOG_ERREUR);
549
+                return false;
550
+            }
551
+        } elseif ($res['location'] and $options['follow_location']) {
552
+            $options['follow_location']--;
553
+            fclose($handle);
554
+            include_spip('inc/filtres');
555
+            $url = suivre_lien($url, $res['location']);
556
+            spip_log("recuperer_url recommence sur $url", 'distant');
557
+
558
+            return recuperer_url($url, $options);
559
+        } elseif ($res['status'] !== 200) {
560
+            spip_log('HTTP status ' . $res['status'] . " pour $url", 'distant');
561
+        }
562
+        $result['status'] = $res['status'];
563
+        if (isset($res['headers'])) {
564
+            $result['headers'] = $res['headers'];
565
+        }
566
+        if (isset($res['last_modified'])) {
567
+            $result['last_modified'] = $res['last_modified'];
568
+        }
569
+        if (isset($res['location'])) {
570
+            $result['location'] = $res['location'];
571
+        }
572
+    }
573
+
574
+    // on ne veut que les entetes
575
+    if (!$options['taille_max'] or $options['methode'] == 'HEAD' or $result['status'] == '304') {
576
+        return $result;
577
+    }
578
+
579
+
580
+    // s'il faut deballer, le faire via un fichier temporaire
581
+    // sinon la memoire explose pour les gros flux
582
+
583
+    $gz = false;
584
+    if (preg_match(",\bContent-Encoding: .*gzip,is", $result['headers'])) {
585
+        $gz = (_DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz');
586
+    }
587
+
588
+    // si on a pas deja recuperer le contenu par une methode detournee
589
+    if (!$result['length']) {
590
+        $res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy);
591
+        fclose($handle);
592
+        if ($copy) {
593
+            $result['length'] = $res;
594
+            $result['file'] = $copy;
595
+        } elseif ($res) {
596
+            $result['page'] = &$res;
597
+            $result['length'] = strlen($result['page']);
598
+        }
599
+        if (!$result['status']) {
600
+            $result['status'] = 200; // on a reussi, donc !
601
+        }
602
+    }
603
+    if (!$result['page']) {
604
+        return $result;
605
+    }
606
+
607
+    // Decompresser au besoin
608
+    if ($gz) {
609
+        $result['page'] = implode('', gzfile($gz));
610
+        supprimer_fichier($gz);
611
+    }
612
+
613
+    // Faut-il l'importer dans notre charset local ?
614
+    if ($options['transcoder']) {
615
+        include_spip('inc/charsets');
616
+        $result['page'] = transcoder_page($result['page'], $result['headers']);
617
+    }
618
+
619
+    return $result;
620 620
 }
621 621
 
622 622
 /**
@@ -632,73 +632,73 @@  discard block
 block discarded – undo
632 632
  * @return array|bool|mixed
633 633
  */
634 634
 function recuperer_url_cache($url, $options = []) {
635
-	if (!defined('_DELAI_RECUPERER_URL_CACHE')) {
636
-		define('_DELAI_RECUPERER_URL_CACHE', 3600);
637
-	}
638
-	$default = [
639
-		'transcoder' => false,
640
-		'methode' => 'GET',
641
-		'taille_max' => null,
642
-		'datas' => '',
643
-		'boundary' => '',
644
-		'refuser_gz' => false,
645
-		'if_modified_since' => '',
646
-		'uri_referer' => '',
647
-		'file' => '',
648
-		'follow_location' => 10,
649
-		'version_http' => _INC_DISTANT_VERSION_HTTP,
650
-		'delai_cache' => in_array(_VAR_MODE, ['preview', 'recalcul']) ? 0 : _DELAI_RECUPERER_URL_CACHE,
651
-	];
652
-	$options = array_merge($default, $options);
653
-
654
-	// cas ou il n'est pas possible de cacher
655
-	if (!empty($options['data']) or $options['methode'] == 'POST') {
656
-		return recuperer_url($url, $options);
657
-	}
658
-
659
-	// ne pas tenter plusieurs fois la meme url en erreur (non cachee donc)
660
-	static $errors = [];
661
-	if (isset($errors[$url])) {
662
-		return $errors[$url];
663
-	}
664
-
665
-	$sig = $options;
666
-	unset($sig['if_modified_since']);
667
-	unset($sig['delai_cache']);
668
-	$sig['url'] = $url;
669
-
670
-	$dir = sous_repertoire(_DIR_CACHE, 'curl');
671
-	$cache = md5(serialize($sig)) . '-' . substr(preg_replace(',\W+,', '_', $url), 0, 80);
672
-	$sub = sous_repertoire($dir, substr($cache, 0, 2));
673
-	$cache = "$sub$cache";
674
-
675
-	$res = false;
676
-	$is_cached = file_exists($cache);
677
-	if (
678
-		$is_cached
679
-		and (filemtime($cache) > $_SERVER['REQUEST_TIME'] - $options['delai_cache'])
680
-	) {
681
-		lire_fichier($cache, $res);
682
-		if ($res = unserialize($res)) {
683
-			// mettre le last_modified et le status=304 ?
684
-		}
685
-	}
686
-	if (!$res) {
687
-		$res = recuperer_url($url, $options);
688
-		// ne pas recharger cette url non cachee dans le meme hit puisque non disponible
689
-		if (!$res) {
690
-			if ($is_cached) {
691
-				// on a pas reussi a recuperer mais on avait un cache : l'utiliser
692
-				lire_fichier($cache, $res);
693
-				$res = unserialize($res);
694
-			}
695
-
696
-			return $errors[$url] = $res;
697
-		}
698
-		ecrire_fichier($cache, serialize($res));
699
-	}
700
-
701
-	return $res;
635
+    if (!defined('_DELAI_RECUPERER_URL_CACHE')) {
636
+        define('_DELAI_RECUPERER_URL_CACHE', 3600);
637
+    }
638
+    $default = [
639
+        'transcoder' => false,
640
+        'methode' => 'GET',
641
+        'taille_max' => null,
642
+        'datas' => '',
643
+        'boundary' => '',
644
+        'refuser_gz' => false,
645
+        'if_modified_since' => '',
646
+        'uri_referer' => '',
647
+        'file' => '',
648
+        'follow_location' => 10,
649
+        'version_http' => _INC_DISTANT_VERSION_HTTP,
650
+        'delai_cache' => in_array(_VAR_MODE, ['preview', 'recalcul']) ? 0 : _DELAI_RECUPERER_URL_CACHE,
651
+    ];
652
+    $options = array_merge($default, $options);
653
+
654
+    // cas ou il n'est pas possible de cacher
655
+    if (!empty($options['data']) or $options['methode'] == 'POST') {
656
+        return recuperer_url($url, $options);
657
+    }
658
+
659
+    // ne pas tenter plusieurs fois la meme url en erreur (non cachee donc)
660
+    static $errors = [];
661
+    if (isset($errors[$url])) {
662
+        return $errors[$url];
663
+    }
664
+
665
+    $sig = $options;
666
+    unset($sig['if_modified_since']);
667
+    unset($sig['delai_cache']);
668
+    $sig['url'] = $url;
669
+
670
+    $dir = sous_repertoire(_DIR_CACHE, 'curl');
671
+    $cache = md5(serialize($sig)) . '-' . substr(preg_replace(',\W+,', '_', $url), 0, 80);
672
+    $sub = sous_repertoire($dir, substr($cache, 0, 2));
673
+    $cache = "$sub$cache";
674
+
675
+    $res = false;
676
+    $is_cached = file_exists($cache);
677
+    if (
678
+        $is_cached
679
+        and (filemtime($cache) > $_SERVER['REQUEST_TIME'] - $options['delai_cache'])
680
+    ) {
681
+        lire_fichier($cache, $res);
682
+        if ($res = unserialize($res)) {
683
+            // mettre le last_modified et le status=304 ?
684
+        }
685
+    }
686
+    if (!$res) {
687
+        $res = recuperer_url($url, $options);
688
+        // ne pas recharger cette url non cachee dans le meme hit puisque non disponible
689
+        if (!$res) {
690
+            if ($is_cached) {
691
+                // on a pas reussi a recuperer mais on avait un cache : l'utiliser
692
+                lire_fichier($cache, $res);
693
+                $res = unserialize($res);
694
+            }
695
+
696
+            return $errors[$url] = $res;
697
+        }
698
+        ecrire_fichier($cache, serialize($res));
699
+    }
700
+
701
+    return $res;
702 702
 }
703 703
 
704 704
 /**
@@ -716,41 +716,41 @@  discard block
 block discarded – undo
716 716
  *   string contenu de la resource
717 717
  */
718 718
 function recuperer_body($handle, $taille_max = _INC_DISTANT_MAX_SIZE, $fichier = '') {
719
-	$taille = 0;
720
-	$result = '';
721
-	$fp = false;
722
-	if ($fichier) {
723
-		include_spip('inc/acces');
724
-		$tmpfile = "$fichier." . creer_uniqid() . '.tmp';
725
-		$fp = spip_fopen_lock($tmpfile, 'w', LOCK_EX);
726
-		if (!$fp and file_exists($fichier)) {
727
-			return filesize($fichier);
728
-		}
729
-		if (!$fp) {
730
-			return false;
731
-		}
732
-		$result = 0; // on renvoie la taille du fichier
733
-	}
734
-	while (!feof($handle) and $taille < $taille_max) {
735
-		$res = fread($handle, 16384);
736
-		$taille += strlen($res);
737
-		if ($fp) {
738
-			fwrite($fp, $res);
739
-			$result = $taille;
740
-		} else {
741
-			$result .= $res;
742
-		}
743
-	}
744
-	if ($fp) {
745
-		spip_fclose_unlock($fp);
746
-		spip_unlink($fichier);
747
-		@rename($tmpfile, $fichier);
748
-		if (!file_exists($fichier)) {
749
-			return false;
750
-		}
751
-	}
752
-
753
-	return $result;
719
+    $taille = 0;
720
+    $result = '';
721
+    $fp = false;
722
+    if ($fichier) {
723
+        include_spip('inc/acces');
724
+        $tmpfile = "$fichier." . creer_uniqid() . '.tmp';
725
+        $fp = spip_fopen_lock($tmpfile, 'w', LOCK_EX);
726
+        if (!$fp and file_exists($fichier)) {
727
+            return filesize($fichier);
728
+        }
729
+        if (!$fp) {
730
+            return false;
731
+        }
732
+        $result = 0; // on renvoie la taille du fichier
733
+    }
734
+    while (!feof($handle) and $taille < $taille_max) {
735
+        $res = fread($handle, 16384);
736
+        $taille += strlen($res);
737
+        if ($fp) {
738
+            fwrite($fp, $res);
739
+            $result = $taille;
740
+        } else {
741
+            $result .= $res;
742
+        }
743
+    }
744
+    if ($fp) {
745
+        spip_fclose_unlock($fp);
746
+        spip_unlink($fichier);
747
+        @rename($tmpfile, $fichier);
748
+        if (!file_exists($fichier)) {
749
+            return false;
750
+        }
751
+    }
752
+
753
+    return $result;
754 754
 }
755 755
 
756 756
 /**
@@ -772,35 +772,35 @@  discard block
 block discarded – undo
772 772
  *   string location
773 773
  */
774 774
 function recuperer_entetes_complets($handle, $if_modified_since = false) {
775
-	$result = ['status' => 0, 'headers' => [], 'last_modified' => 0, 'location' => ''];
776
-
777
-	$s = @trim(fgets($handle, 16384));
778
-	if (!preg_match(',^HTTP/[0-9]+\.[0-9]+ ([0-9]+),', $s, $r)) {
779
-		return false;
780
-	}
781
-	$result['status'] = intval($r[1]);
782
-	while ($s = trim(fgets($handle, 16384))) {
783
-		$result['headers'][] = $s . "\n";
784
-		preg_match(',^([^:]*): *(.*)$,i', $s, $r);
785
-		list(, $d, $v) = $r;
786
-		if (strtolower(trim($d)) == 'location' and $result['status'] >= 300 and $result['status'] < 400) {
787
-			$result['location'] = $v;
788
-		} elseif ($d == 'Last-Modified') {
789
-			$result['last_modified'] = strtotime($v);
790
-		}
791
-	}
792
-	if (
793
-		$if_modified_since
794
-		and $result['last_modified']
795
-		and $if_modified_since > $result['last_modified']
796
-		and $result['status'] == 200
797
-	) {
798
-		$result['status'] = 304;
799
-	}
800
-
801
-	$result['headers'] = implode('', $result['headers']);
802
-
803
-	return $result;
775
+    $result = ['status' => 0, 'headers' => [], 'last_modified' => 0, 'location' => ''];
776
+
777
+    $s = @trim(fgets($handle, 16384));
778
+    if (!preg_match(',^HTTP/[0-9]+\.[0-9]+ ([0-9]+),', $s, $r)) {
779
+        return false;
780
+    }
781
+    $result['status'] = intval($r[1]);
782
+    while ($s = trim(fgets($handle, 16384))) {
783
+        $result['headers'][] = $s . "\n";
784
+        preg_match(',^([^:]*): *(.*)$,i', $s, $r);
785
+        list(, $d, $v) = $r;
786
+        if (strtolower(trim($d)) == 'location' and $result['status'] >= 300 and $result['status'] < 400) {
787
+            $result['location'] = $v;
788
+        } elseif ($d == 'Last-Modified') {
789
+            $result['last_modified'] = strtotime($v);
790
+        }
791
+    }
792
+    if (
793
+        $if_modified_since
794
+        and $result['last_modified']
795
+        and $if_modified_since > $result['last_modified']
796
+        and $result['status'] == 200
797
+    ) {
798
+        $result['status'] = 304;
799
+    }
800
+
801
+    $result['headers'] = implode('', $result['headers']);
802
+
803
+    return $result;
804 804
 }
805 805
 
806 806
 /**
@@ -822,22 +822,22 @@  discard block
 block discarded – undo
822 822
  *     Nom du fichier pour copie locale
823 823
  **/
824 824
 function nom_fichier_copie_locale($source, $extension) {
825
-	include_spip('inc/documents');
825
+    include_spip('inc/documents');
826 826
 
827
-	$d = creer_repertoire_documents('distant'); # IMG/distant/
828
-	$d = sous_repertoire($d, $extension); # IMG/distant/pdf/
827
+    $d = creer_repertoire_documents('distant'); # IMG/distant/
828
+    $d = sous_repertoire($d, $extension); # IMG/distant/pdf/
829 829
 
830
-	// on se place tout le temps comme si on etait a la racine
831
-	if (_DIR_RACINE) {
832
-		$d = preg_replace(',^' . preg_quote(_DIR_RACINE) . ',', '', $d);
833
-	}
830
+    // on se place tout le temps comme si on etait a la racine
831
+    if (_DIR_RACINE) {
832
+        $d = preg_replace(',^' . preg_quote(_DIR_RACINE) . ',', '', $d);
833
+    }
834 834
 
835
-	$m = md5($source);
835
+    $m = md5($source);
836 836
 
837
-	return $d
838
-	. substr(preg_replace(',[^\w-],', '', basename($source)) . '-' . $m, 0, 12)
839
-	. substr($m, 0, 4)
840
-	. ".$extension";
837
+    return $d
838
+    . substr(preg_replace(',[^\w-],', '', basename($source)) . '-' . $m, 0, 12)
839
+    . substr($m, 0, 4)
840
+    . ".$extension";
841 841
 }
842 842
 
843 843
 /**
@@ -855,70 +855,70 @@  discard block
 block discarded – undo
855 855
  *      Nom du fichier calculé
856 856
  **/
857 857
 function fichier_copie_locale($source) {
858
-	// Si c'est deja local pas de souci
859
-	if (!tester_url_absolue($source)) {
860
-		if (_DIR_RACINE) {
861
-			$source = preg_replace(',^' . preg_quote(_DIR_RACINE) . ',', '', $source);
862
-		}
863
-
864
-		return $source;
865
-	}
866
-
867
-	// optimisation : on regarde si on peut deviner l'extension dans l'url et si le fichier
868
-	// a deja ete copie en local avec cette extension
869
-	// dans ce cas elle est fiable, pas la peine de requeter en base
870
-	$path_parts = pathinfo($source);
871
-	if (!isset($path_parts['extension'])) {
872
-		$path_parts['extension'] = '';
873
-	}
874
-	$ext = $path_parts ? $path_parts['extension'] : '';
875
-	if (
876
-		$ext
877
-		and preg_match(',^\w+$,', $ext) // pas de php?truc=1&...
878
-		and $f = nom_fichier_copie_locale($source, $ext)
879
-		and file_exists(_DIR_RACINE . $f)
880
-	) {
881
-		return $f;
882
-	}
883
-
884
-
885
-	// Si c'est deja dans la table des documents,
886
-	// ramener le nom de sa copie potentielle
887
-	$ext = sql_getfetsel('extension', 'spip_documents', 'fichier=' . sql_quote($source) . " AND distant='oui' AND extension <> ''");
888
-
889
-	if ($ext) {
890
-		return nom_fichier_copie_locale($source, $ext);
891
-	}
892
-
893
-	// voir si l'extension indiquee dans le nom du fichier est ok
894
-	// et si il n'aurait pas deja ete rapatrie
895
-
896
-	$ext = $path_parts ? $path_parts['extension'] : '';
897
-
898
-	if ($ext and sql_getfetsel('extension', 'spip_types_documents', 'extension=' . sql_quote($ext))) {
899
-		$f = nom_fichier_copie_locale($source, $ext);
900
-		if (file_exists(_DIR_RACINE . $f)) {
901
-			return $f;
902
-		}
903
-	}
904
-
905
-	// Ping  pour voir si son extension est connue et autorisee
906
-	// avec mise en cache du resultat du ping
907
-
908
-	$cache = sous_repertoire(_DIR_CACHE, 'rid') . md5($source);
909
-	if (
910
-		!@file_exists($cache)
911
-		or !$path_parts = @unserialize(spip_file_get_contents($cache))
912
-		or _request('var_mode') === 'recalcul'
913
-	) {
914
-		$path_parts = recuperer_infos_distantes($source, 0, false);
915
-		ecrire_fichier($cache, serialize($path_parts));
916
-	}
917
-	$ext = !empty($path_parts['extension']) ? $path_parts['extension'] : '';
918
-	if ($ext and sql_getfetsel('extension', 'spip_types_documents', 'extension=' . sql_quote($ext))) {
919
-		return nom_fichier_copie_locale($source, $ext);
920
-	}
921
-	spip_log("pas de copie locale pour $source", 'distant' . _LOG_ERREUR);
858
+    // Si c'est deja local pas de souci
859
+    if (!tester_url_absolue($source)) {
860
+        if (_DIR_RACINE) {
861
+            $source = preg_replace(',^' . preg_quote(_DIR_RACINE) . ',', '', $source);
862
+        }
863
+
864
+        return $source;
865
+    }
866
+
867
+    // optimisation : on regarde si on peut deviner l'extension dans l'url et si le fichier
868
+    // a deja ete copie en local avec cette extension
869
+    // dans ce cas elle est fiable, pas la peine de requeter en base
870
+    $path_parts = pathinfo($source);
871
+    if (!isset($path_parts['extension'])) {
872
+        $path_parts['extension'] = '';
873
+    }
874
+    $ext = $path_parts ? $path_parts['extension'] : '';
875
+    if (
876
+        $ext
877
+        and preg_match(',^\w+$,', $ext) // pas de php?truc=1&...
878
+        and $f = nom_fichier_copie_locale($source, $ext)
879
+        and file_exists(_DIR_RACINE . $f)
880
+    ) {
881
+        return $f;
882
+    }
883
+
884
+
885
+    // Si c'est deja dans la table des documents,
886
+    // ramener le nom de sa copie potentielle
887
+    $ext = sql_getfetsel('extension', 'spip_documents', 'fichier=' . sql_quote($source) . " AND distant='oui' AND extension <> ''");
888
+
889
+    if ($ext) {
890
+        return nom_fichier_copie_locale($source, $ext);
891
+    }
892
+
893
+    // voir si l'extension indiquee dans le nom du fichier est ok
894
+    // et si il n'aurait pas deja ete rapatrie
895
+
896
+    $ext = $path_parts ? $path_parts['extension'] : '';
897
+
898
+    if ($ext and sql_getfetsel('extension', 'spip_types_documents', 'extension=' . sql_quote($ext))) {
899
+        $f = nom_fichier_copie_locale($source, $ext);
900
+        if (file_exists(_DIR_RACINE . $f)) {
901
+            return $f;
902
+        }
903
+    }
904
+
905
+    // Ping  pour voir si son extension est connue et autorisee
906
+    // avec mise en cache du resultat du ping
907
+
908
+    $cache = sous_repertoire(_DIR_CACHE, 'rid') . md5($source);
909
+    if (
910
+        !@file_exists($cache)
911
+        or !$path_parts = @unserialize(spip_file_get_contents($cache))
912
+        or _request('var_mode') === 'recalcul'
913
+    ) {
914
+        $path_parts = recuperer_infos_distantes($source, 0, false);
915
+        ecrire_fichier($cache, serialize($path_parts));
916
+    }
917
+    $ext = !empty($path_parts['extension']) ? $path_parts['extension'] : '';
918
+    if ($ext and sql_getfetsel('extension', 'spip_types_documents', 'extension=' . sql_quote($ext))) {
919
+        return nom_fichier_copie_locale($source, $ext);
920
+    }
921
+    spip_log("pas de copie locale pour $source", 'distant' . _LOG_ERREUR);
922 922
 }
923 923
 
924 924
 
@@ -946,97 +946,97 @@  discard block
 block discarded – undo
946 946
  **/
947 947
 function recuperer_infos_distantes($source, $max = 0, $charger_si_petite_image = true) {
948 948
 
949
-	// pas la peine de perdre son temps
950
-	if (!tester_url_absolue($source)) {
951
-		return false;
952
-	}
953
-
954
-	# charger les alias des types mime
955
-	include_spip('base/typedoc');
956
-
957
-	$a = [];
958
-	$mime_type = '';
959
-	// On va directement charger le debut des images et des fichiers html,
960
-	// de maniere a attrapper le maximum d'infos (titre, taille, etc). Si
961
-	// ca echoue l'utilisateur devra les entrer...
962
-	$reponse = recuperer_url($source, ['taille_max' => $max, 'refuser_gz' => true]);
963
-	$headers = $reponse['headers'] ?? '';
964
-	$a['body'] = $reponse['page'] ?? '';
965
-	if ($headers) {
966
-		if (!$extension = distant_trouver_extension_selon_headers($source, $headers)) {
967
-			return false;
968
-		}
969
-
970
-		$a['extension'] = $extension;
971
-
972
-		if (preg_match(",\nContent-Length: *([^[:space:]]*),i", "\n$headers", $regs)) {
973
-			$a['taille'] = intval($regs[1]);
974
-		}
975
-	}
976
-
977
-	// Echec avec HEAD, on tente avec GET
978
-	if (!$a and !$max) {
979
-		spip_log("tenter GET $source", 'distant');
980
-		$a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE);
981
-	}
982
-
983
-	// si on a rien trouve pas la peine d'insister
984
-	if (!$a) {
985
-		return false;
986
-	}
987
-
988
-	// S'il s'agit d'une image pas trop grosse ou d'un fichier html, on va aller
989
-	// recharger le document en GET et recuperer des donnees supplementaires...
990
-	include_spip('inc/filtres_images_lib_mini');
991
-	if (
992
-		strpos($mime_type, 'image/') === 0
993
-		and $extension = _image_trouver_extension_depuis_mime($mime_type)
994
-	) {
995
-		if (
996
-			$max == 0
997
-			and (empty($a['taille']) or $a['taille'] < _INC_DISTANT_MAX_SIZE)
998
-			and in_array($extension, formats_image_acceptables())
999
-			and $charger_si_petite_image
1000
-		) {
1001
-			$a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE);
1002
-		} else {
1003
-			if ($a['body']) {
1004
-				$a['extension'] = $extension;
1005
-				$a['fichier'] = _DIR_RACINE . nom_fichier_copie_locale($source, $extension);
1006
-				ecrire_fichier($a['fichier'], $a['body']);
1007
-				$size_image = @spip_getimagesize($a['fichier']);
1008
-				$a['largeur'] = intval($size_image[0]);
1009
-				$a['hauteur'] = intval($size_image[1]);
1010
-				$a['type_image'] = true;
1011
-			}
1012
-		}
1013
-	}
1014
-
1015
-	// Fichier swf, si on n'a pas la taille, on va mettre 425x350 par defaut
1016
-	// ce sera mieux que 0x0
1017
-	// Flash is dead!
1018
-	if (
1019
-		$a and isset($a['extension']) and $a['extension'] == 'swf'
1020
-		and empty($a['largeur'])
1021
-	) {
1022
-		$a['largeur'] = 425;
1023
-		$a['hauteur'] = 350;
1024
-	}
1025
-
1026
-	if ($mime_type == 'text/html') {
1027
-		include_spip('inc/filtres');
1028
-		$page = recuperer_url($source, ['transcoder' => true, 'taille_max' => _INC_DISTANT_MAX_SIZE]);
1029
-		$page = $page['page'] ?? '';
1030
-		if (preg_match(',<title>(.*?)</title>,ims', $page, $regs)) {
1031
-			$a['titre'] = corriger_caracteres(trim($regs[1]));
1032
-		}
1033
-		if (!isset($a['taille']) or !$a['taille']) {
1034
-			$a['taille'] = strlen($page); # a peu pres
1035
-		}
1036
-	}
1037
-	$a['mime_type'] = $mime_type;
1038
-
1039
-	return $a;
949
+    // pas la peine de perdre son temps
950
+    if (!tester_url_absolue($source)) {
951
+        return false;
952
+    }
953
+
954
+    # charger les alias des types mime
955
+    include_spip('base/typedoc');
956
+
957
+    $a = [];
958
+    $mime_type = '';
959
+    // On va directement charger le debut des images et des fichiers html,
960
+    // de maniere a attrapper le maximum d'infos (titre, taille, etc). Si
961
+    // ca echoue l'utilisateur devra les entrer...
962
+    $reponse = recuperer_url($source, ['taille_max' => $max, 'refuser_gz' => true]);
963
+    $headers = $reponse['headers'] ?? '';
964
+    $a['body'] = $reponse['page'] ?? '';
965
+    if ($headers) {
966
+        if (!$extension = distant_trouver_extension_selon_headers($source, $headers)) {
967
+            return false;
968
+        }
969
+
970
+        $a['extension'] = $extension;
971
+
972
+        if (preg_match(",\nContent-Length: *([^[:space:]]*),i", "\n$headers", $regs)) {
973
+            $a['taille'] = intval($regs[1]);
974
+        }
975
+    }
976
+
977
+    // Echec avec HEAD, on tente avec GET
978
+    if (!$a and !$max) {
979
+        spip_log("tenter GET $source", 'distant');
980
+        $a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE);
981
+    }
982
+
983
+    // si on a rien trouve pas la peine d'insister
984
+    if (!$a) {
985
+        return false;
986
+    }
987
+
988
+    // S'il s'agit d'une image pas trop grosse ou d'un fichier html, on va aller
989
+    // recharger le document en GET et recuperer des donnees supplementaires...
990
+    include_spip('inc/filtres_images_lib_mini');
991
+    if (
992
+        strpos($mime_type, 'image/') === 0
993
+        and $extension = _image_trouver_extension_depuis_mime($mime_type)
994
+    ) {
995
+        if (
996
+            $max == 0
997
+            and (empty($a['taille']) or $a['taille'] < _INC_DISTANT_MAX_SIZE)
998
+            and in_array($extension, formats_image_acceptables())
999
+            and $charger_si_petite_image
1000
+        ) {
1001
+            $a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE);
1002
+        } else {
1003
+            if ($a['body']) {
1004
+                $a['extension'] = $extension;
1005
+                $a['fichier'] = _DIR_RACINE . nom_fichier_copie_locale($source, $extension);
1006
+                ecrire_fichier($a['fichier'], $a['body']);
1007
+                $size_image = @spip_getimagesize($a['fichier']);
1008
+                $a['largeur'] = intval($size_image[0]);
1009
+                $a['hauteur'] = intval($size_image[1]);
1010
+                $a['type_image'] = true;
1011
+            }
1012
+        }
1013
+    }
1014
+
1015
+    // Fichier swf, si on n'a pas la taille, on va mettre 425x350 par defaut
1016
+    // ce sera mieux que 0x0
1017
+    // Flash is dead!
1018
+    if (
1019
+        $a and isset($a['extension']) and $a['extension'] == 'swf'
1020
+        and empty($a['largeur'])
1021
+    ) {
1022
+        $a['largeur'] = 425;
1023
+        $a['hauteur'] = 350;
1024
+    }
1025
+
1026
+    if ($mime_type == 'text/html') {
1027
+        include_spip('inc/filtres');
1028
+        $page = recuperer_url($source, ['transcoder' => true, 'taille_max' => _INC_DISTANT_MAX_SIZE]);
1029
+        $page = $page['page'] ?? '';
1030
+        if (preg_match(',<title>(.*?)</title>,ims', $page, $regs)) {
1031
+            $a['titre'] = corriger_caracteres(trim($regs[1]));
1032
+        }
1033
+        if (!isset($a['taille']) or !$a['taille']) {
1034
+            $a['taille'] = strlen($page); # a peu pres
1035
+        }
1036
+    }
1037
+    $a['mime_type'] = $mime_type;
1038
+
1039
+    return $a;
1040 1040
 }
1041 1041
 
1042 1042
 /**
@@ -1045,70 +1045,70 @@  discard block
 block discarded – undo
1045 1045
  * @return false|mixed
1046 1046
  */
1047 1047
 function distant_trouver_extension_selon_headers($source, $headers) {
1048
-	if (preg_match(",\nContent-Type: *([^[:space:];]*),i", "\n$headers", $regs)) {
1049
-		$mime_type = (trim($regs[1]));
1050
-	} else {
1051
-		$mime_type = '';
1052
-	} // inconnu
1053
-
1054
-	// Appliquer les alias
1055
-	while (isset($GLOBALS['mime_alias'][$mime_type])) {
1056
-		$mime_type = $GLOBALS['mime_alias'][$mime_type];
1057
-	}
1058
-
1059
-	// pour corriger_extension()
1060
-	include_spip('inc/documents');
1061
-
1062
-	// Si on a un mime-type insignifiant
1063
-	// text/plain,application/octet-stream ou vide
1064
-	// c'est peut-etre que le serveur ne sait pas
1065
-	// ce qu'il sert ; on va tenter de detecter via l'extension de l'url
1066
-	// ou le Content-Disposition: attachment; filename=...
1067
-	$t = null;
1068
-	if (in_array($mime_type, ['text/plain', '', 'application/octet-stream'])) {
1069
-		if (
1070
-			!$t
1071
-			and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $source, $rext)
1072
-		) {
1073
-			$t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1074
-		}
1075
-		if (
1076
-			!$t
1077
-			and preg_match(',^Content-Disposition:\s*attachment;\s*filename=(.*)$,Uims', $headers, $m)
1078
-			and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $m[1], $rext)
1079
-		) {
1080
-			$t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1081
-		}
1082
-	}
1083
-
1084
-	// Autre mime/type (ou text/plain avec fichier d'extension inconnue)
1085
-	if (!$t) {
1086
-		$t = sql_fetsel('extension', 'spip_types_documents', 'mime_type=' . sql_quote($mime_type));
1087
-	}
1088
-
1089
-	// Toujours rien ? (ex: audio/x-ogg au lieu de application/ogg)
1090
-	// On essaie de nouveau avec l'extension
1091
-	if (
1092
-		!$t
1093
-		and $mime_type != 'text/plain'
1094
-		and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $source, $rext)
1095
-	) {
1096
-		# eviter xxx.3 => 3gp (> SPIP 3)
1097
-		$t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1098
-	}
1099
-
1100
-	if ($t) {
1101
-		spip_log("mime-type $mime_type ok, extension " . $t['extension'], 'distant');
1102
-		return $t['extension'];
1103
-	} else {
1104
-		# par defaut on retombe sur '.bin' si c'est autorise
1105
-		spip_log("mime-type $mime_type inconnu", 'distant');
1106
-		$t = sql_fetsel('extension', 'spip_types_documents', "extension='bin'");
1107
-		if (!$t) {
1108
-			return false;
1109
-		}
1110
-		return $t['extension'];
1111
-	}
1048
+    if (preg_match(",\nContent-Type: *([^[:space:];]*),i", "\n$headers", $regs)) {
1049
+        $mime_type = (trim($regs[1]));
1050
+    } else {
1051
+        $mime_type = '';
1052
+    } // inconnu
1053
+
1054
+    // Appliquer les alias
1055
+    while (isset($GLOBALS['mime_alias'][$mime_type])) {
1056
+        $mime_type = $GLOBALS['mime_alias'][$mime_type];
1057
+    }
1058
+
1059
+    // pour corriger_extension()
1060
+    include_spip('inc/documents');
1061
+
1062
+    // Si on a un mime-type insignifiant
1063
+    // text/plain,application/octet-stream ou vide
1064
+    // c'est peut-etre que le serveur ne sait pas
1065
+    // ce qu'il sert ; on va tenter de detecter via l'extension de l'url
1066
+    // ou le Content-Disposition: attachment; filename=...
1067
+    $t = null;
1068
+    if (in_array($mime_type, ['text/plain', '', 'application/octet-stream'])) {
1069
+        if (
1070
+            !$t
1071
+            and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $source, $rext)
1072
+        ) {
1073
+            $t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1074
+        }
1075
+        if (
1076
+            !$t
1077
+            and preg_match(',^Content-Disposition:\s*attachment;\s*filename=(.*)$,Uims', $headers, $m)
1078
+            and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $m[1], $rext)
1079
+        ) {
1080
+            $t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1081
+        }
1082
+    }
1083
+
1084
+    // Autre mime/type (ou text/plain avec fichier d'extension inconnue)
1085
+    if (!$t) {
1086
+        $t = sql_fetsel('extension', 'spip_types_documents', 'mime_type=' . sql_quote($mime_type));
1087
+    }
1088
+
1089
+    // Toujours rien ? (ex: audio/x-ogg au lieu de application/ogg)
1090
+    // On essaie de nouveau avec l'extension
1091
+    if (
1092
+        !$t
1093
+        and $mime_type != 'text/plain'
1094
+        and preg_match(',\.([a-z0-9]+)(\?.*)?$,i', $source, $rext)
1095
+    ) {
1096
+        # eviter xxx.3 => 3gp (> SPIP 3)
1097
+        $t = sql_fetsel('extension', 'spip_types_documents', 'extension=' . sql_quote(corriger_extension($rext[1]), '', 'text'));
1098
+    }
1099
+
1100
+    if ($t) {
1101
+        spip_log("mime-type $mime_type ok, extension " . $t['extension'], 'distant');
1102
+        return $t['extension'];
1103
+    } else {
1104
+        # par defaut on retombe sur '.bin' si c'est autorise
1105
+        spip_log("mime-type $mime_type inconnu", 'distant');
1106
+        $t = sql_fetsel('extension', 'spip_types_documents', "extension='bin'");
1107
+        if (!$t) {
1108
+            return false;
1109
+        }
1110
+        return $t['extension'];
1111
+    }
1112 1112
 }
1113 1113
 
1114 1114
 /**
@@ -1123,46 +1123,46 @@  discard block
 block discarded – undo
1123 1123
  * @return string
1124 1124
  */
1125 1125
 function need_proxy($host, $http_proxy = null, $http_noproxy = null) {
1126
-	if (is_null($http_proxy)) {
1127
-		$http_proxy = isset($GLOBALS['meta']['http_proxy']) ? $GLOBALS['meta']['http_proxy'] : null;
1128
-	}
1129
-	// rien a faire si pas de proxy :)
1130
-	if (is_null($http_proxy) or !$http_proxy = trim($http_proxy)) {
1131
-		return '';
1132
-	}
1133
-
1134
-	if (is_null($http_noproxy)) {
1135
-		$http_noproxy = isset($GLOBALS['meta']['http_noproxy']) ? $GLOBALS['meta']['http_noproxy'] : null;
1136
-	}
1137
-	// si pas d'exception, on retourne le proxy
1138
-	if (is_null($http_noproxy) or !$http_noproxy = trim($http_noproxy)) {
1139
-		return $http_proxy;
1140
-	}
1141
-
1142
-	// si le host ou l'un des domaines parents est dans $http_noproxy on fait exception
1143
-	// $http_noproxy peut contenir plusieurs domaines separes par des espaces ou retour ligne
1144
-	$http_noproxy = str_replace("\n", ' ', $http_noproxy);
1145
-	$http_noproxy = str_replace("\r", ' ', $http_noproxy);
1146
-	$http_noproxy = " $http_noproxy ";
1147
-	$domain = $host;
1148
-	// si le domaine exact www.example.org est dans les exceptions
1149
-	if (strpos($http_noproxy, " $domain ") !== false) {
1150
-		return '';
1151
-	}
1152
-
1153
-	while (strpos($domain, '.') !== false) {
1154
-		$domain = explode('.', $domain);
1155
-		array_shift($domain);
1156
-		$domain = implode('.', $domain);
1157
-
1158
-		// ou si un domaine parent commencant par un . est dans les exceptions (indiquant qu'il couvre tous les sous-domaines)
1159
-		if (strpos($http_noproxy, " .$domain ") !== false) {
1160
-			return '';
1161
-		}
1162
-	}
1163
-
1164
-	// ok c'est pas une exception
1165
-	return $http_proxy;
1126
+    if (is_null($http_proxy)) {
1127
+        $http_proxy = isset($GLOBALS['meta']['http_proxy']) ? $GLOBALS['meta']['http_proxy'] : null;
1128
+    }
1129
+    // rien a faire si pas de proxy :)
1130
+    if (is_null($http_proxy) or !$http_proxy = trim($http_proxy)) {
1131
+        return '';
1132
+    }
1133
+
1134
+    if (is_null($http_noproxy)) {
1135
+        $http_noproxy = isset($GLOBALS['meta']['http_noproxy']) ? $GLOBALS['meta']['http_noproxy'] : null;
1136
+    }
1137
+    // si pas d'exception, on retourne le proxy
1138
+    if (is_null($http_noproxy) or !$http_noproxy = trim($http_noproxy)) {
1139
+        return $http_proxy;
1140
+    }
1141
+
1142
+    // si le host ou l'un des domaines parents est dans $http_noproxy on fait exception
1143
+    // $http_noproxy peut contenir plusieurs domaines separes par des espaces ou retour ligne
1144
+    $http_noproxy = str_replace("\n", ' ', $http_noproxy);
1145
+    $http_noproxy = str_replace("\r", ' ', $http_noproxy);
1146
+    $http_noproxy = " $http_noproxy ";
1147
+    $domain = $host;
1148
+    // si le domaine exact www.example.org est dans les exceptions
1149
+    if (strpos($http_noproxy, " $domain ") !== false) {
1150
+        return '';
1151
+    }
1152
+
1153
+    while (strpos($domain, '.') !== false) {
1154
+        $domain = explode('.', $domain);
1155
+        array_shift($domain);
1156
+        $domain = implode('.', $domain);
1157
+
1158
+        // ou si un domaine parent commencant par un . est dans les exceptions (indiquant qu'il couvre tous les sous-domaines)
1159
+        if (strpos($http_noproxy, " .$domain ") !== false) {
1160
+            return '';
1161
+        }
1162
+    }
1163
+
1164
+    // ok c'est pas une exception
1165
+    return $http_proxy;
1166 1166
 }
1167 1167
 
1168 1168
 
@@ -1185,59 +1185,59 @@  discard block
 block discarded – undo
1185 1185
  * @return array
1186 1186
  */
1187 1187
 function init_http($method, $url, $refuse_gz = false, $referer = '', $datas = '', $vers = 'HTTP/1.0', $date = '') {
1188
-	$user = $via_proxy = $proxy_user = '';
1189
-	$fopen = false;
1190
-
1191
-	$t = @parse_url($url);
1192
-	$host = $t['host'];
1193
-	if ($t['scheme'] == 'http') {
1194
-		$scheme = 'http';
1195
-		$noproxy = '';
1196
-	} elseif ($t['scheme'] == 'https') {
1197
-		$scheme = 'ssl';
1198
-		$noproxy = 'ssl://';
1199
-		if (!isset($t['port']) || !($port = $t['port'])) {
1200
-			$t['port'] = 443;
1201
-		}
1202
-	} else {
1203
-		$scheme = $t['scheme'];
1204
-		$noproxy = $scheme . '://';
1205
-	}
1206
-	if (isset($t['user'])) {
1207
-		$user = [$t['user'], $t['pass']];
1208
-	}
1209
-
1210
-	if (!isset($t['port']) || !($port = $t['port'])) {
1211
-		$port = 80;
1212
-	}
1213
-	if (!isset($t['path']) || !($path = $t['path'])) {
1214
-		$path = '/';
1215
-	}
1216
-
1217
-	if (!empty($t['query'])) {
1218
-		$path .= '?' . $t['query'];
1219
-	}
1220
-
1221
-	$f = lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $refuse_gz, $referer, $datas, $vers, $date);
1222
-	if (!$f or !is_resource($f)) {
1223
-		// fallback : fopen si on a pas fait timeout dans lance_requete
1224
-		// ce qui correspond a $f===110
1225
-		if (
1226
-			$f !== 110
1227
-			and !need_proxy($host)
1228
-			and !_request('tester_proxy')
1229
-			and (!isset($GLOBALS['inc_distant_allow_fopen']) or $GLOBALS['inc_distant_allow_fopen'])
1230
-		) {
1231
-			$f = @fopen($url, 'rb');
1232
-			spip_log("connexion vers $url par simple fopen", 'distant');
1233
-			$fopen = true;
1234
-		} else {
1235
-			// echec total
1236
-			$f = false;
1237
-		}
1238
-	}
1239
-
1240
-	return [$f, $fopen];
1188
+    $user = $via_proxy = $proxy_user = '';
1189
+    $fopen = false;
1190
+
1191
+    $t = @parse_url($url);
1192
+    $host = $t['host'];
1193
+    if ($t['scheme'] == 'http') {
1194
+        $scheme = 'http';
1195
+        $noproxy = '';
1196
+    } elseif ($t['scheme'] == 'https') {
1197
+        $scheme = 'ssl';
1198
+        $noproxy = 'ssl://';
1199
+        if (!isset($t['port']) || !($port = $t['port'])) {
1200
+            $t['port'] = 443;
1201
+        }
1202
+    } else {
1203
+        $scheme = $t['scheme'];
1204
+        $noproxy = $scheme . '://';
1205
+    }
1206
+    if (isset($t['user'])) {
1207
+        $user = [$t['user'], $t['pass']];
1208
+    }
1209
+
1210
+    if (!isset($t['port']) || !($port = $t['port'])) {
1211
+        $port = 80;
1212
+    }
1213
+    if (!isset($t['path']) || !($path = $t['path'])) {
1214
+        $path = '/';
1215
+    }
1216
+
1217
+    if (!empty($t['query'])) {
1218
+        $path .= '?' . $t['query'];
1219
+    }
1220
+
1221
+    $f = lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $refuse_gz, $referer, $datas, $vers, $date);
1222
+    if (!$f or !is_resource($f)) {
1223
+        // fallback : fopen si on a pas fait timeout dans lance_requete
1224
+        // ce qui correspond a $f===110
1225
+        if (
1226
+            $f !== 110
1227
+            and !need_proxy($host)
1228
+            and !_request('tester_proxy')
1229
+            and (!isset($GLOBALS['inc_distant_allow_fopen']) or $GLOBALS['inc_distant_allow_fopen'])
1230
+        ) {
1231
+            $f = @fopen($url, 'rb');
1232
+            spip_log("connexion vers $url par simple fopen", 'distant');
1233
+            $fopen = true;
1234
+        } else {
1235
+            // echec total
1236
+            $f = false;
1237
+        }
1238
+    }
1239
+
1240
+    return [$f, $fopen];
1241 1241
 }
1242 1242
 
1243 1243
 /**
@@ -1272,125 +1272,125 @@  discard block
 block discarded – undo
1272 1272
  *   resource socket vers l'url demandee
1273 1273
  */
1274 1274
 function lance_requete(
1275
-	$method,
1276
-	$scheme,
1277
-	$user,
1278
-	$host,
1279
-	$path,
1280
-	$port,
1281
-	$noproxy,
1282
-	$refuse_gz = false,
1283
-	$referer = '',
1284
-	$datas = '',
1285
-	$vers = 'HTTP/1.0',
1286
-	$date = ''
1275
+    $method,
1276
+    $scheme,
1277
+    $user,
1278
+    $host,
1279
+    $path,
1280
+    $port,
1281
+    $noproxy,
1282
+    $refuse_gz = false,
1283
+    $referer = '',
1284
+    $datas = '',
1285
+    $vers = 'HTTP/1.0',
1286
+    $date = ''
1287 1287
 ) {
1288 1288
 
1289
-	$proxy_user = '';
1290
-	$http_proxy = need_proxy($host);
1291
-	if ($user) {
1292
-		$user = urlencode($user[0]) . ':' . urlencode($user[1]);
1293
-	}
1294
-
1295
-	$connect = '';
1296
-	if ($http_proxy) {
1297
-		if (!defined('_PROXY_HTTPS_NOT_VIA_CONNECT') and in_array($scheme, ['tls','ssl'])) {
1298
-			$path_host = (!$user ? '' : "$user@") . $host . (($port != 80) ? ":$port" : '');
1299
-			$connect = 'CONNECT ' . $path_host . " $vers\r\n"
1300
-				. "Host: $path_host\r\n"
1301
-				. "Proxy-Connection: Keep-Alive\r\n";
1302
-		} else {
1303
-			$path = (in_array($scheme, ['tls','ssl']) ? 'https://' : "$scheme://")
1304
-				. (!$user ? '' : "$user@")
1305
-				. "$host" . (($port != 80) ? ":$port" : '') . $path;
1306
-		}
1307
-		$t2 = @parse_url($http_proxy);
1308
-		$first_host = $t2['host'];
1309
-		if (!($port = $t2['port'])) {
1310
-			$port = 80;
1311
-		}
1312
-		if ($t2['user']) {
1313
-			$proxy_user = base64_encode($t2['user'] . ':' . $t2['pass']);
1314
-		}
1315
-	} else {
1316
-		$first_host = $noproxy . $host;
1317
-	}
1318
-
1319
-	if ($connect) {
1320
-		$streamContext = stream_context_create([
1321
-			'ssl' => [
1322
-				'verify_peer' => false,
1323
-				'allow_self_signed' => true,
1324
-				'SNI_enabled' => true,
1325
-				'peer_name' => $host,
1326
-			]
1327
-		]);
1328
-		$f = @stream_socket_client(
1329
-			"tcp://$first_host:$port",
1330
-			$errno,
1331
-			$errstr,
1332
-			_INC_DISTANT_CONNECT_TIMEOUT,
1333
-			STREAM_CLIENT_CONNECT,
1334
-			$streamContext
1335
-		);
1336
-		spip_log("Recuperer $path sur $first_host:$port par $f (via CONNECT)", 'connect');
1337
-		if (!$f) {
1338
-			spip_log("Erreur connexion $errno $errstr", 'distant' . _LOG_ERREUR);
1339
-			return $errno;
1340
-		}
1341
-		stream_set_timeout($f, _INC_DISTANT_CONNECT_TIMEOUT);
1342
-
1343
-		fputs($f, $connect);
1344
-		fputs($f, "\r\n");
1345
-		$res = fread($f, 1024);
1346
-		if (
1347
-			!$res
1348
-			or !count($res = explode(' ', $res))
1349
-			or $res[1] !== '200'
1350
-		) {
1351
-			spip_log("Echec CONNECT sur $first_host:$port", 'connect' . _LOG_INFO_IMPORTANTE);
1352
-			fclose($f);
1353
-
1354
-			return false;
1355
-		}
1356
-		// important, car sinon on lit trop vite et les donnees ne sont pas encore dispo
1357
-		stream_set_blocking($f, true);
1358
-		// envoyer le handshake
1359
-		stream_socket_enable_crypto($f, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
1360
-		spip_log("OK CONNECT sur $first_host:$port", 'connect');
1361
-	} else {
1362
-		$ntry = 3;
1363
-		do {
1364
-			$f = @fsockopen($first_host, $port, $errno, $errstr, _INC_DISTANT_CONNECT_TIMEOUT);
1365
-		} while (!$f and $ntry-- and $errno !== 110 and sleep(1));
1366
-		spip_log("Recuperer $path sur $first_host:$port par $f");
1367
-		if (!$f) {
1368
-			spip_log("Erreur connexion $errno $errstr", 'distant' . _LOG_ERREUR);
1369
-
1370
-			return $errno;
1371
-		}
1372
-		stream_set_timeout($f, _INC_DISTANT_CONNECT_TIMEOUT);
1373
-	}
1374
-
1375
-	$site = isset($GLOBALS['meta']['adresse_site']) ? $GLOBALS['meta']['adresse_site'] : '';
1376
-
1377
-	$host_port = $host;
1378
-	if ($port != (in_array($scheme, ['tls','ssl']) ? 443 : 80)) {
1379
-		$host_port .= ":$port";
1380
-	}
1381
-	$req = "$method $path $vers\r\n"
1382
-		. "Host: $host_port\r\n"
1383
-		. 'User-Agent: ' . _INC_DISTANT_USER_AGENT . "\r\n"
1384
-		. ($refuse_gz ? '' : ('Accept-Encoding: ' . _INC_DISTANT_CONTENT_ENCODING . "\r\n"))
1385
-		. (!$site ? '' : "Referer: $site/$referer\r\n")
1386
-		. (!$date ? '' : 'If-Modified-Since: ' . (gmdate('D, d M Y H:i:s', $date) . " GMT\r\n"))
1387
-		. (!$user ? '' : ('Authorization: Basic ' . base64_encode($user) . "\r\n"))
1388
-		. (!$proxy_user ? '' : "Proxy-Authorization: Basic $proxy_user\r\n")
1389
-		. (!strpos($vers, '1.1') ? '' : "Keep-Alive: 300\r\nConnection: keep-alive\r\n");
1289
+    $proxy_user = '';
1290
+    $http_proxy = need_proxy($host);
1291
+    if ($user) {
1292
+        $user = urlencode($user[0]) . ':' . urlencode($user[1]);
1293
+    }
1294
+
1295
+    $connect = '';
1296
+    if ($http_proxy) {
1297
+        if (!defined('_PROXY_HTTPS_NOT_VIA_CONNECT') and in_array($scheme, ['tls','ssl'])) {
1298
+            $path_host = (!$user ? '' : "$user@") . $host . (($port != 80) ? ":$port" : '');
1299
+            $connect = 'CONNECT ' . $path_host . " $vers\r\n"
1300
+                . "Host: $path_host\r\n"
1301
+                . "Proxy-Connection: Keep-Alive\r\n";
1302
+        } else {
1303
+            $path = (in_array($scheme, ['tls','ssl']) ? 'https://' : "$scheme://")
1304
+                . (!$user ? '' : "$user@")
1305
+                . "$host" . (($port != 80) ? ":$port" : '') . $path;
1306
+        }
1307
+        $t2 = @parse_url($http_proxy);
1308
+        $first_host = $t2['host'];
1309
+        if (!($port = $t2['port'])) {
1310
+            $port = 80;
1311
+        }
1312
+        if ($t2['user']) {
1313
+            $proxy_user = base64_encode($t2['user'] . ':' . $t2['pass']);
1314
+        }
1315
+    } else {
1316
+        $first_host = $noproxy . $host;
1317
+    }
1318
+
1319
+    if ($connect) {
1320
+        $streamContext = stream_context_create([
1321
+            'ssl' => [
1322
+                'verify_peer' => false,
1323
+                'allow_self_signed' => true,
1324
+                'SNI_enabled' => true,
1325
+                'peer_name' => $host,
1326
+            ]
1327
+        ]);
1328
+        $f = @stream_socket_client(
1329
+            "tcp://$first_host:$port",
1330
+            $errno,
1331
+            $errstr,
1332
+            _INC_DISTANT_CONNECT_TIMEOUT,
1333
+            STREAM_CLIENT_CONNECT,
1334
+            $streamContext
1335
+        );
1336
+        spip_log("Recuperer $path sur $first_host:$port par $f (via CONNECT)", 'connect');
1337
+        if (!$f) {
1338
+            spip_log("Erreur connexion $errno $errstr", 'distant' . _LOG_ERREUR);
1339
+            return $errno;
1340
+        }
1341
+        stream_set_timeout($f, _INC_DISTANT_CONNECT_TIMEOUT);
1342
+
1343
+        fputs($f, $connect);
1344
+        fputs($f, "\r\n");
1345
+        $res = fread($f, 1024);
1346
+        if (
1347
+            !$res
1348
+            or !count($res = explode(' ', $res))
1349
+            or $res[1] !== '200'
1350
+        ) {
1351
+            spip_log("Echec CONNECT sur $first_host:$port", 'connect' . _LOG_INFO_IMPORTANTE);
1352
+            fclose($f);
1353
+
1354
+            return false;
1355
+        }
1356
+        // important, car sinon on lit trop vite et les donnees ne sont pas encore dispo
1357
+        stream_set_blocking($f, true);
1358
+        // envoyer le handshake
1359
+        stream_socket_enable_crypto($f, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
1360
+        spip_log("OK CONNECT sur $first_host:$port", 'connect');
1361
+    } else {
1362
+        $ntry = 3;
1363
+        do {
1364
+            $f = @fsockopen($first_host, $port, $errno, $errstr, _INC_DISTANT_CONNECT_TIMEOUT);
1365
+        } while (!$f and $ntry-- and $errno !== 110 and sleep(1));
1366
+        spip_log("Recuperer $path sur $first_host:$port par $f");
1367
+        if (!$f) {
1368
+            spip_log("Erreur connexion $errno $errstr", 'distant' . _LOG_ERREUR);
1369
+
1370
+            return $errno;
1371
+        }
1372
+        stream_set_timeout($f, _INC_DISTANT_CONNECT_TIMEOUT);
1373
+    }
1374
+
1375
+    $site = isset($GLOBALS['meta']['adresse_site']) ? $GLOBALS['meta']['adresse_site'] : '';
1376
+
1377
+    $host_port = $host;
1378
+    if ($port != (in_array($scheme, ['tls','ssl']) ? 443 : 80)) {
1379
+        $host_port .= ":$port";
1380
+    }
1381
+    $req = "$method $path $vers\r\n"
1382
+        . "Host: $host_port\r\n"
1383
+        . 'User-Agent: ' . _INC_DISTANT_USER_AGENT . "\r\n"
1384
+        . ($refuse_gz ? '' : ('Accept-Encoding: ' . _INC_DISTANT_CONTENT_ENCODING . "\r\n"))
1385
+        . (!$site ? '' : "Referer: $site/$referer\r\n")
1386
+        . (!$date ? '' : 'If-Modified-Since: ' . (gmdate('D, d M Y H:i:s', $date) . " GMT\r\n"))
1387
+        . (!$user ? '' : ('Authorization: Basic ' . base64_encode($user) . "\r\n"))
1388
+        . (!$proxy_user ? '' : "Proxy-Authorization: Basic $proxy_user\r\n")
1389
+        . (!strpos($vers, '1.1') ? '' : "Keep-Alive: 300\r\nConnection: keep-alive\r\n");
1390 1390
 
1391 1391
 #	spip_log("Requete\n$req", 'distant');
1392
-	fputs($f, $req);
1393
-	fputs($f, $datas ? $datas : "\r\n");
1392
+    fputs($f, $req);
1393
+    fputs($f, $datas ? $datas : "\r\n");
1394 1394
 
1395
-	return $f;
1395
+    return $f;
1396 1396
 }
Please login to merge, or discard this patch.