Completed
Push — master ( bcd628...6b340f )
by cam
08:24 queued 07:20
created
ecrire/iterateur/sql.php 1 patch
Indentation   +209 added lines, -209 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
 
@@ -27,215 +27,215 @@  discard block
 block discarded – undo
27 27
  * Permet d'itérer sur des données en base de données
28 28
  */
29 29
 class IterateurSQL implements Iterator {
30
-	/**
31
-	 * Ressource sql
32
-	 *
33
-	 * @var Object|bool
34
-	 */
35
-	protected $sqlresult = false;
36
-
37
-	/**
38
-	 * row sql courante
39
-	 *
40
-	 * @var array|null
41
-	 */
42
-	protected $row = null;
43
-
44
-	protected bool $firstseek = false;
45
-
46
-	protected int $pos = -1;
47
-
48
-	protected string $type = 'SQL';
49
-
50
-	protected array $command = [];
51
-
52
-	protected array $info = [];
53
-
54
-
55
-	/** Erreur presente ? **/
56
-	public bool $err = false;
57
-
58
-	/**
59
-	 * Calcul du total des elements
60
-	 *
61
-	 * @var int|null
62
-	 **/
63
-	public $total = null;
64
-
65
-	/**
66
-	 * selectionner les donnees, ie faire la requete SQL
67
-	 *
68
-	 * @return void
69
-	 */
70
-	protected function select() {
71
-		$this->row = null;
72
-		$v = &$this->command;
73
-		$this->sqlresult = calculer_select(
74
-			$v['select'],
75
-			$v['from'],
76
-			$v['type'],
77
-			$v['where'],
78
-			$v['join'],
79
-			$v['groupby'],
80
-			$v['orderby'],
81
-			$v['limit'],
82
-			$v['having'],
83
-			$v['table'],
84
-			$v['id'],
85
-			$v['connect'],
86
-			$this->info
87
-		);
88
-		$this->err = !$this->sqlresult;
89
-		$this->firstseek = false;
90
-		$this->pos = -1;
91
-
92
-		// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
93
-		//$this->total = $this->count();
94
-	}
95
-
96
-	/*
30
+    /**
31
+     * Ressource sql
32
+     *
33
+     * @var Object|bool
34
+     */
35
+    protected $sqlresult = false;
36
+
37
+    /**
38
+     * row sql courante
39
+     *
40
+     * @var array|null
41
+     */
42
+    protected $row = null;
43
+
44
+    protected bool $firstseek = false;
45
+
46
+    protected int $pos = -1;
47
+
48
+    protected string $type = 'SQL';
49
+
50
+    protected array $command = [];
51
+
52
+    protected array $info = [];
53
+
54
+
55
+    /** Erreur presente ? **/
56
+    public bool $err = false;
57
+
58
+    /**
59
+     * Calcul du total des elements
60
+     *
61
+     * @var int|null
62
+     **/
63
+    public $total = null;
64
+
65
+    /**
66
+     * selectionner les donnees, ie faire la requete SQL
67
+     *
68
+     * @return void
69
+     */
70
+    protected function select() {
71
+        $this->row = null;
72
+        $v = &$this->command;
73
+        $this->sqlresult = calculer_select(
74
+            $v['select'],
75
+            $v['from'],
76
+            $v['type'],
77
+            $v['where'],
78
+            $v['join'],
79
+            $v['groupby'],
80
+            $v['orderby'],
81
+            $v['limit'],
82
+            $v['having'],
83
+            $v['table'],
84
+            $v['id'],
85
+            $v['connect'],
86
+            $this->info
87
+        );
88
+        $this->err = !$this->sqlresult;
89
+        $this->firstseek = false;
90
+        $this->pos = -1;
91
+
92
+        // pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
93
+        //$this->total = $this->count();
94
+    }
95
+
96
+    /*
97 97
 	 * array command: les commandes d'initialisation
98 98
 	 * array info: les infos sur le squelette
99 99
 	 */
100
-	public function __construct($command, $info = []) {
101
-		$this->type = 'SQL';
102
-		$this->command = $command;
103
-		$this->info = $info;
104
-		$this->select();
105
-	}
106
-
107
-	/**
108
-	 * Rembobiner
109
-	 *
110
-	 * @return bool
111
-	 */
112
-	public function rewind(): void {
113
-		if ($this->pos > 0) {
114
-			$this->seek(0);
115
-		}
116
-	}
117
-
118
-	/**
119
-	 * Verifier l'etat de l'iterateur
120
-	 *
121
-	 * @return bool
122
-	 */
123
-	public function valid(): bool {
124
-		if ($this->err) {
125
-			return false;
126
-		}
127
-		if (!$this->firstseek) {
128
-			$this->next();
129
-		}
130
-
131
-		return is_array($this->row);
132
-	}
133
-
134
-	/**
135
-	 * Valeurs sur la position courante
136
-	 *
137
-	 * @return array
138
-	 */
139
-	#[\ReturnTypeWillChange]
140
-	public function current() {
141
-		return $this->row;
142
-	}
143
-
144
-	#[\ReturnTypeWillChange]
145
-	public function key() {
146
-		return $this->pos;
147
-	}
148
-
149
-	/**
150
-	 * Sauter a une position absolue
151
-	 *
152
-	 * @param int $n
153
-	 * @param null|string $continue
154
-	 * @return bool
155
-	 */
156
-	public function seek($n = 0, $continue = null) {
157
-		if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
158
-			// SQLite ne sait pas seek(), il faut relancer la query
159
-			// si la position courante est apres la position visee
160
-			// il faut relancer la requete
161
-			if ($this->pos > $n) {
162
-				$this->free();
163
-				$this->select();
164
-				$this->valid();
165
-			}
166
-			// et utiliser la methode par defaut pour se deplacer au bon endroit
167
-			// (sera fait en cas d'echec de cette fonction)
168
-			return false;
169
-		}
170
-		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
171
-		$this->pos = min($n, $this->count());
172
-
173
-		return true;
174
-	}
175
-
176
-	/**
177
-	 * Avancer d'un cran
178
-	 *
179
-	 * @return void
180
-	 */
181
-	public function next(): void {
182
-		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
183
-		$this->pos++;
184
-		$this->firstseek |= true;
185
-	}
186
-
187
-	/**
188
-	 * Avancer et retourner les donnees pour le nouvel element
189
-	 *
190
-	 * @return array|bool|null
191
-	 */
192
-	public function fetch() {
193
-		if ($this->valid()) {
194
-			$r = $this->current();
195
-			$this->next();
196
-		} else {
197
-			$r = false;
198
-		}
199
-
200
-		return $r;
201
-	}
202
-
203
-	/**
204
-	 * liberer les ressources
205
-	 *
206
-	 * @return bool
207
-	 */
208
-	public function free() {
209
-		if (!$this->sqlresult) {
210
-			return true;
211
-		}
212
-		$a = sql_free($this->sqlresult, $this->command['connect']);
213
-		$this->sqlresult = null;
214
-
215
-		return $a;
216
-	}
217
-
218
-	/**
219
-	 * Compter le nombre de resultats
220
-	 *
221
-	 * @return int
222
-	 */
223
-	public function count() {
224
-		if (is_null($this->total)) {
225
-			if (!$this->sqlresult) {
226
-				$this->total = 0;
227
-			} else {
228
-				# cas count(*)
229
-				if (in_array('count(*)', $this->command['select'])) {
230
-					$this->valid();
231
-					$s = $this->current();
232
-					$this->total = $s['count(*)'];
233
-				} else {
234
-					$this->total = sql_count($this->sqlresult, $this->command['connect']);
235
-				}
236
-			}
237
-		}
238
-
239
-		return $this->total;
240
-	}
100
+    public function __construct($command, $info = []) {
101
+        $this->type = 'SQL';
102
+        $this->command = $command;
103
+        $this->info = $info;
104
+        $this->select();
105
+    }
106
+
107
+    /**
108
+     * Rembobiner
109
+     *
110
+     * @return bool
111
+     */
112
+    public function rewind(): void {
113
+        if ($this->pos > 0) {
114
+            $this->seek(0);
115
+        }
116
+    }
117
+
118
+    /**
119
+     * Verifier l'etat de l'iterateur
120
+     *
121
+     * @return bool
122
+     */
123
+    public function valid(): bool {
124
+        if ($this->err) {
125
+            return false;
126
+        }
127
+        if (!$this->firstseek) {
128
+            $this->next();
129
+        }
130
+
131
+        return is_array($this->row);
132
+    }
133
+
134
+    /**
135
+     * Valeurs sur la position courante
136
+     *
137
+     * @return array
138
+     */
139
+    #[\ReturnTypeWillChange]
140
+    public function current() {
141
+        return $this->row;
142
+    }
143
+
144
+    #[\ReturnTypeWillChange]
145
+    public function key() {
146
+        return $this->pos;
147
+    }
148
+
149
+    /**
150
+     * Sauter a une position absolue
151
+     *
152
+     * @param int $n
153
+     * @param null|string $continue
154
+     * @return bool
155
+     */
156
+    public function seek($n = 0, $continue = null) {
157
+        if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
158
+            // SQLite ne sait pas seek(), il faut relancer la query
159
+            // si la position courante est apres la position visee
160
+            // il faut relancer la requete
161
+            if ($this->pos > $n) {
162
+                $this->free();
163
+                $this->select();
164
+                $this->valid();
165
+            }
166
+            // et utiliser la methode par defaut pour se deplacer au bon endroit
167
+            // (sera fait en cas d'echec de cette fonction)
168
+            return false;
169
+        }
170
+        $this->row = sql_fetch($this->sqlresult, $this->command['connect']);
171
+        $this->pos = min($n, $this->count());
172
+
173
+        return true;
174
+    }
175
+
176
+    /**
177
+     * Avancer d'un cran
178
+     *
179
+     * @return void
180
+     */
181
+    public function next(): void {
182
+        $this->row = sql_fetch($this->sqlresult, $this->command['connect']);
183
+        $this->pos++;
184
+        $this->firstseek |= true;
185
+    }
186
+
187
+    /**
188
+     * Avancer et retourner les donnees pour le nouvel element
189
+     *
190
+     * @return array|bool|null
191
+     */
192
+    public function fetch() {
193
+        if ($this->valid()) {
194
+            $r = $this->current();
195
+            $this->next();
196
+        } else {
197
+            $r = false;
198
+        }
199
+
200
+        return $r;
201
+    }
202
+
203
+    /**
204
+     * liberer les ressources
205
+     *
206
+     * @return bool
207
+     */
208
+    public function free() {
209
+        if (!$this->sqlresult) {
210
+            return true;
211
+        }
212
+        $a = sql_free($this->sqlresult, $this->command['connect']);
213
+        $this->sqlresult = null;
214
+
215
+        return $a;
216
+    }
217
+
218
+    /**
219
+     * Compter le nombre de resultats
220
+     *
221
+     * @return int
222
+     */
223
+    public function count() {
224
+        if (is_null($this->total)) {
225
+            if (!$this->sqlresult) {
226
+                $this->total = 0;
227
+            } else {
228
+                # cas count(*)
229
+                if (in_array('count(*)', $this->command['select'])) {
230
+                    $this->valid();
231
+                    $s = $this->current();
232
+                    $this->total = $s['count(*)'];
233
+                } else {
234
+                    $this->total = sql_count($this->sqlresult, $this->command['connect']);
235
+                }
236
+            }
237
+        }
238
+
239
+        return $this->total;
240
+    }
241 241
 }
Please login to merge, or discard this patch.
ecrire/public/balises.php 1 patch
Indentation   +941 added lines, -941 removed lines patch added patch discarded remove patch
@@ -26,7 +26,7 @@  discard block
 block discarded – undo
26 26
  **/
27 27
 
28 28
 if (!defined('_ECRIRE_INC_VERSION')) {
29
-	return;
29
+    return;
30 30
 }
31 31
 
32 32
 /**
@@ -48,16 +48,16 @@  discard block
 block discarded – undo
48 48
  *     Code PHP si cet argument est présent, sinon null
49 49
  **/
50 50
 function interprete_argument_balise(int $n, Champ $p): ?string {
51
-	if (($p->param) && (!$p->param[0][0]) && ((is_countable($p->param[0]) ? count($p->param[0]) : 0) > $n)) {
52
-		return calculer_liste(
53
-			$p->param[0][$n],
54
-			$p->descr,
55
-			$p->boucles,
56
-			$p->id_boucle
57
-		);
58
-	} else {
59
-		return null;
60
-	}
51
+    if (($p->param) && (!$p->param[0][0]) && ((is_countable($p->param[0]) ? count($p->param[0]) : 0) > $n)) {
52
+        return calculer_liste(
53
+            $p->param[0][$n],
54
+            $p->descr,
55
+            $p->boucles,
56
+            $p->id_boucle
57
+        );
58
+    } else {
59
+        return null;
60
+    }
61 61
 }
62 62
 
63 63
 
@@ -77,10 +77,10 @@  discard block
 block discarded – undo
77 77
  *     Pile complétée par le code à générer
78 78
  **/
79 79
 function balise_NOM_SITE_SPIP_dist($p) {
80
-	$p->code = "\$GLOBALS['meta']['nom_site']";
80
+    $p->code = "\$GLOBALS['meta']['nom_site']";
81 81
 
82
-	#$p->interdire_scripts = true;
83
-	return $p;
82
+    #$p->interdire_scripts = true;
83
+    return $p;
84 84
 }
85 85
 
86 86
 /**
@@ -96,10 +96,10 @@  discard block
 block discarded – undo
96 96
  *     Pile complétée par le code à générer
97 97
  **/
98 98
 function balise_EMAIL_WEBMASTER_dist($p) {
99
-	$p->code = "\$GLOBALS['meta']['email_webmaster']";
99
+    $p->code = "\$GLOBALS['meta']['email_webmaster']";
100 100
 
101
-	#$p->interdire_scripts = true;
102
-	return $p;
101
+    #$p->interdire_scripts = true;
102
+    return $p;
103 103
 }
104 104
 
105 105
 /**
@@ -115,10 +115,10 @@  discard block
 block discarded – undo
115 115
  *     Pile complétée par le code à générer
116 116
  **/
117 117
 function balise_DESCRIPTIF_SITE_SPIP_dist($p) {
118
-	$p->code = "\$GLOBALS['meta']['descriptif_site']";
118
+    $p->code = "\$GLOBALS['meta']['descriptif_site']";
119 119
 
120
-	#$p->interdire_scripts = true;
121
-	return $p;
120
+    #$p->interdire_scripts = true;
121
+    return $p;
122 122
 }
123 123
 
124 124
 
@@ -139,10 +139,10 @@  discard block
 block discarded – undo
139 139
  *     Pile complétée par le code à générer
140 140
  **/
141 141
 function balise_CHARSET_dist($p) {
142
-	$p->code = "\$GLOBALS['meta']['charset']";
142
+    $p->code = "\$GLOBALS['meta']['charset']";
143 143
 
144
-	#$p->interdire_scripts = true;
145
-	return $p;
144
+    #$p->interdire_scripts = true;
145
+    return $p;
146 146
 }
147 147
 
148 148
 /**
@@ -167,11 +167,11 @@  discard block
 block discarded – undo
167 167
  *     Pile complétée par le code à générer
168 168
  **/
169 169
 function balise_LANG_LEFT_dist($p) {
170
-	$_lang = champ_sql('lang', $p);
171
-	$p->code = "lang_dir($_lang, 'left','right')";
172
-	$p->interdire_scripts = false;
170
+    $_lang = champ_sql('lang', $p);
171
+    $p->code = "lang_dir($_lang, 'left','right')";
172
+    $p->interdire_scripts = false;
173 173
 
174
-	return $p;
174
+    return $p;
175 175
 }
176 176
 
177 177
 /**
@@ -191,11 +191,11 @@  discard block
 block discarded – undo
191 191
  *     Pile complétée par le code à générer
192 192
  **/
193 193
 function balise_LANG_RIGHT_dist($p) {
194
-	$_lang = champ_sql('lang', $p);
195
-	$p->code = "lang_dir($_lang, 'right','left')";
196
-	$p->interdire_scripts = false;
194
+    $_lang = champ_sql('lang', $p);
195
+    $p->code = "lang_dir($_lang, 'right','left')";
196
+    $p->interdire_scripts = false;
197 197
 
198
-	return $p;
198
+    return $p;
199 199
 }
200 200
 
201 201
 /**
@@ -220,11 +220,11 @@  discard block
 block discarded – undo
220 220
  *     Pile complétée par le code à générer
221 221
  **/
222 222
 function balise_LANG_DIR_dist($p) {
223
-	$_lang = champ_sql('lang', $p);
224
-	$p->code = "lang_dir($_lang, 'ltr','rtl')";
225
-	$p->interdire_scripts = false;
223
+    $_lang = champ_sql('lang', $p);
224
+    $p->code = "lang_dir($_lang, 'ltr','rtl')";
225
+    $p->interdire_scripts = false;
226 226
 
227
-	return $p;
227
+    return $p;
228 228
 }
229 229
 
230 230
 
@@ -241,10 +241,10 @@  discard block
 block discarded – undo
241 241
  *     Pile complétée par le code à générer
242 242
  **/
243 243
 function balise_PUCE_dist($p) {
244
-	$p->code = 'definir_puce()';
245
-	$p->interdire_scripts = false;
244
+    $p->code = 'definir_puce()';
245
+    $p->interdire_scripts = false;
246 246
 
247
-	return $p;
247
+    return $p;
248 248
 }
249 249
 
250 250
 
@@ -268,9 +268,9 @@  discard block
 block discarded – undo
268 268
  *     Pile completée du code PHP d'exécution de la balise
269 269
  */
270 270
 function balise_DATE_dist($p) {
271
-	$p->code = champ_sql('date', $p);
271
+    $p->code = champ_sql('date', $p);
272 272
 
273
-	return $p;
273
+    return $p;
274 274
 }
275 275
 
276 276
 
@@ -290,10 +290,10 @@  discard block
 block discarded – undo
290 290
  *     Pile completée du code PHP d'exécution de la balise
291 291
  */
292 292
 function balise_DATE_REDAC_dist($p) {
293
-	$p->code = champ_sql('date_redac', $p);
294
-	$p->interdire_scripts = false;
293
+    $p->code = champ_sql('date_redac', $p);
294
+    $p->interdire_scripts = false;
295 295
 
296
-	return $p;
296
+    return $p;
297 297
 }
298 298
 
299 299
 /**
@@ -312,10 +312,10 @@  discard block
 block discarded – undo
312 312
  *     Pile completée du code PHP d'exécution de la balise
313 313
  */
314 314
 function balise_DATE_MODIF_dist($p) {
315
-	$p->code = champ_sql('date_modif', $p);
316
-	$p->interdire_scripts = false;
315
+    $p->code = champ_sql('date_modif', $p);
316
+    $p->interdire_scripts = false;
317 317
 
318
-	return $p;
318
+    return $p;
319 319
 }
320 320
 
321 321
 /**
@@ -333,13 +333,13 @@  discard block
 block discarded – undo
333 333
  *     Pile completée du code PHP d'exécution de la balise
334 334
  */
335 335
 function balise_DATE_NOUVEAUTES_dist($p) {
336
-	$p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui'
336
+    $p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui'
337 337
 	AND isset(\$GLOBALS['meta']['dernier_envoi_neuf'])) ?
338 338
 	\$GLOBALS['meta']['dernier_envoi_neuf'] :
339 339
 	\"'0000-00-00'\")";
340
-	$p->interdire_scripts = false;
340
+    $p->interdire_scripts = false;
341 341
 
342
-	return $p;
342
+    return $p;
343 343
 }
344 344
 
345 345
 
@@ -357,11 +357,11 @@  discard block
 block discarded – undo
357 357
  *     Pile completée du code PHP d'exécution de la balise
358 358
  */
359 359
 function balise_DOSSIER_SQUELETTE_dist($p) {
360
-	$code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE));
361
-	$p->code = "_DIR_RACINE . '$code'" .
362
-		$p->interdire_scripts = false;
360
+    $code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE));
361
+    $p->code = "_DIR_RACINE . '$code'" .
362
+        $p->interdire_scripts = false;
363 363
 
364
-	return $p;
364
+    return $p;
365 365
 }
366 366
 
367 367
 /**
@@ -376,11 +376,11 @@  discard block
 block discarded – undo
376 376
  *     Pile completée du code PHP d'exécution de la balise
377 377
  */
378 378
 function balise_SQUELETTE_dist($p) {
379
-	$code = addslashes($p->descr['sourcefile']);
380
-	$p->code = "'$code'" .
381
-		$p->interdire_scripts = false;
379
+    $code = addslashes($p->descr['sourcefile']);
380
+    $p->code = "'$code'" .
381
+        $p->interdire_scripts = false;
382 382
 
383
-	return $p;
383
+    return $p;
384 384
 }
385 385
 
386 386
 /**
@@ -399,10 +399,10 @@  discard block
 block discarded – undo
399 399
  *     Pile completée du code PHP d'exécution de la balise
400 400
  */
401 401
 function balise_SPIP_VERSION_dist($p) {
402
-	$p->code = 'spip_version()';
403
-	$p->interdire_scripts = false;
402
+    $p->code = 'spip_version()';
403
+    $p->interdire_scripts = false;
404 404
 
405
-	return $p;
405
+    return $p;
406 406
 }
407 407
 
408 408
 
@@ -428,18 +428,18 @@  discard block
 block discarded – undo
428 428
  *     Pile complétée par le code à générer
429 429
  **/
430 430
 function balise_NOM_SITE_dist($p) {
431
-	if (!$p->etoile) {
432
-		$p->code = 'supprimer_numero(calculer_url(' .
433
-			champ_sql('url_site', $p) . ',' .
434
-			champ_sql('nom_site', $p) .
435
-			", 'titre', \$connect, false))";
436
-	} else {
437
-		$p->code = champ_sql('nom_site', $p);
438
-	}
431
+    if (!$p->etoile) {
432
+        $p->code = 'supprimer_numero(calculer_url(' .
433
+            champ_sql('url_site', $p) . ',' .
434
+            champ_sql('nom_site', $p) .
435
+            ", 'titre', \$connect, false))";
436
+    } else {
437
+        $p->code = champ_sql('nom_site', $p);
438
+    }
439 439
 
440
-	$p->interdire_scripts = true;
440
+    $p->interdire_scripts = true;
441 441
 
442
-	return $p;
442
+    return $p;
443 443
 }
444 444
 
445 445
 
@@ -456,11 +456,11 @@  discard block
 block discarded – undo
456 456
  *     Pile complétée par le code à générer
457 457
  **/
458 458
 function balise_NOTES_dist($p) {
459
-	// Recuperer les notes
460
-	$p->code = 'calculer_notes()';
459
+    // Recuperer les notes
460
+    $p->code = 'calculer_notes()';
461 461
 
462
-	#$p->interdire_scripts = true;
463
-	return $p;
462
+    #$p->interdire_scripts = true;
463
+    return $p;
464 464
 }
465 465
 
466 466
 
@@ -482,10 +482,10 @@  discard block
 block discarded – undo
482 482
  *     Pile complétée par le code à générer
483 483
  **/
484 484
 function balise_RECHERCHE_dist($p) {
485
-	$p->code = 'entites_html(_request("recherche"))';
486
-	$p->interdire_scripts = false;
485
+    $p->code = 'entites_html(_request("recherche"))';
486
+    $p->interdire_scripts = false;
487 487
 
488
-	return $p;
488
+    return $p;
489 489
 }
490 490
 
491 491
 
@@ -503,17 +503,17 @@  discard block
 block discarded – undo
503 503
  *     Pile complétée par le code à générer
504 504
  **/
505 505
 function balise_COMPTEUR_BOUCLE_dist($p) {
506
-	$b = index_boucle_mere($p);
507
-	if ($b === '') {
508
-		$msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
509
-		erreur_squelette($msg, $p);
510
-	} else {
511
-		$p->code = "(\$Numrows['$b']['compteur_boucle'] ?? 0)";
512
-		$p->boucles[$b]->cptrows = true;
513
-		$p->interdire_scripts = false;
506
+    $b = index_boucle_mere($p);
507
+    if ($b === '') {
508
+        $msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
509
+        erreur_squelette($msg, $p);
510
+    } else {
511
+        $p->code = "(\$Numrows['$b']['compteur_boucle'] ?? 0)";
512
+        $p->boucles[$b]->cptrows = true;
513
+        $p->interdire_scripts = false;
514 514
 
515
-		return $p;
516
-	}
515
+        return $p;
516
+    }
517 517
 }
518 518
 
519 519
 /**
@@ -531,17 +531,17 @@  discard block
 block discarded – undo
531 531
  *     Pile complétée par le code à générer
532 532
  **/
533 533
 function balise_TOTAL_BOUCLE_dist($p) {
534
-	$b = index_boucle_mere($p);
535
-	if ($b === '') {
536
-		$msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
537
-		erreur_squelette($msg, $p);
538
-	} else {
539
-		$p->code = "(\$Numrows['$b']['total'] ?? 0)";
540
-		$p->boucles[$b]->numrows = true;
541
-		$p->interdire_scripts = false;
542
-	}
534
+    $b = index_boucle_mere($p);
535
+    if ($b === '') {
536
+        $msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
537
+        erreur_squelette($msg, $p);
538
+    } else {
539
+        $p->code = "(\$Numrows['$b']['total'] ?? 0)";
540
+        $p->boucles[$b]->numrows = true;
541
+        $p->interdire_scripts = false;
542
+    }
543 543
 
544
-	return $p;
544
+    return $p;
545 545
 }
546 546
 
547 547
 
@@ -561,7 +561,7 @@  discard block
 block discarded – undo
561 561
  *     Pile complétée par le code à générer
562 562
  **/
563 563
 function balise_POINTS_dist($p) {
564
-	return rindex_pile($p, 'points', 'recherche');
564
+    return rindex_pile($p, 'points', 'recherche');
565 565
 }
566 566
 
567 567
 
@@ -582,12 +582,12 @@  discard block
 block discarded – undo
582 582
  *     Pile complétée par le code à générer
583 583
  **/
584 584
 function balise_POPULARITE_ABSOLUE_dist($p) {
585
-	$p->code = 'ceil(' .
586
-		champ_sql('popularite', $p) .
587
-		')';
588
-	$p->interdire_scripts = false;
585
+    $p->code = 'ceil(' .
586
+        champ_sql('popularite', $p) .
587
+        ')';
588
+    $p->interdire_scripts = false;
589 589
 
590
-	return $p;
590
+    return $p;
591 591
 }
592 592
 
593 593
 /**
@@ -607,10 +607,10 @@  discard block
 block discarded – undo
607 607
  *     Pile complétée par le code à générer
608 608
  **/
609 609
 function balise_POPULARITE_SITE_dist($p) {
610
-	$p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])';
611
-	$p->interdire_scripts = false;
610
+    $p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])';
611
+    $p->interdire_scripts = false;
612 612
 
613
-	return $p;
613
+    return $p;
614 614
 }
615 615
 
616 616
 /**
@@ -631,10 +631,10 @@  discard block
 block discarded – undo
631 631
  *     Pile complétée par le code à générer
632 632
  **/
633 633
 function balise_POPULARITE_MAX_dist($p) {
634
-	$p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])';
635
-	$p->interdire_scripts = false;
634
+    $p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])';
635
+    $p->interdire_scripts = false;
636 636
 
637
-	return $p;
637
+    return $p;
638 638
 }
639 639
 
640 640
 
@@ -660,15 +660,15 @@  discard block
 block discarded – undo
660 660
  *     Pile complétée par le code à générer
661 661
  **/
662 662
 function balise_VALEUR_dist($p) {
663
-	$b = $p->nom_boucle ?: $p->id_boucle;
664
-	$p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);
663
+    $b = $p->nom_boucle ?: $p->id_boucle;
664
+    $p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);
665 665
 ;
666
-	if (($v = interprete_argument_balise(1, $p)) !== null) {
667
-		$p->code = 'table_valeur(' . $p->code . ', ' . $v . ')';
668
-	}
669
-	$p->interdire_scripts = true;
666
+    if (($v = interprete_argument_balise(1, $p)) !== null) {
667
+        $p->code = 'table_valeur(' . $p->code . ', ' . $v . ')';
668
+    }
669
+    $p->interdire_scripts = true;
670 670
 
671
-	return $p;
671
+    return $p;
672 672
 }
673 673
 
674 674
 /**
@@ -697,16 +697,16 @@  discard block
 block discarded – undo
697 697
  *     Pile complétée par le code à générer
698 698
  **/
699 699
 function balise_EXPOSE_dist($p) {
700
-	$on = "'on'";
701
-	$off = "''";
702
-	if (($v = interprete_argument_balise(1, $p)) !== null) {
703
-		$on = $v;
704
-		if (($v = interprete_argument_balise(2, $p)) !== null) {
705
-			$off = $v;
706
-		}
707
-	}
700
+    $on = "'on'";
701
+    $off = "''";
702
+    if (($v = interprete_argument_balise(1, $p)) !== null) {
703
+        $on = $v;
704
+        if (($v = interprete_argument_balise(2, $p)) !== null) {
705
+            $off = $v;
706
+        }
707
+    }
708 708
 
709
-	return calculer_balise_expose($p, $on, $off);
709
+    return calculer_balise_expose($p, $on, $off);
710 710
 }
711 711
 
712 712
 /**
@@ -724,35 +724,35 @@  discard block
 block discarded – undo
724 724
  *     Pile complétée par le code à générer
725 725
  **/
726 726
 function calculer_balise_expose($p, $on, $off) {
727
-	$b = index_boucle($p);
728
-	if (empty($p->boucles[$b]->primary)) {
729
-		$msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
730
-		erreur_squelette($msg, $p);
731
-	} else {
732
-		$key = $p->boucles[$b]->primary;
733
-		$type = $p->boucles[$p->id_boucle]->primary;
734
-		$desc = $p->boucles[$b]->show;
735
-		$connect = sql_quote($p->boucles[$b]->sql_serveur);
727
+    $b = index_boucle($p);
728
+    if (empty($p->boucles[$b]->primary)) {
729
+        $msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
730
+        erreur_squelette($msg, $p);
731
+    } else {
732
+        $key = $p->boucles[$b]->primary;
733
+        $type = $p->boucles[$p->id_boucle]->primary;
734
+        $desc = $p->boucles[$b]->show;
735
+        $connect = sql_quote($p->boucles[$b]->sql_serveur);
736 736
 
737
-		// Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
738
-		$c = index_pile($p->id_boucle, $type, $p->boucles);
737
+        // Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
738
+        $c = index_pile($p->id_boucle, $type, $p->boucles);
739 739
 
740
-		if (isset($desc['field']['id_parent'])) {
741
-			$parent = 0; // pour if (!$parent) dans calculer_expose
742
-		} elseif (isset($desc['field']['id_rubrique'])) {
743
-			$parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
744
-		} elseif (isset($desc['field']['id_groupe'])) {
745
-			$parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
746
-		} else {
747
-			$parent = "''";
748
-		}
740
+        if (isset($desc['field']['id_parent'])) {
741
+            $parent = 0; // pour if (!$parent) dans calculer_expose
742
+        } elseif (isset($desc['field']['id_rubrique'])) {
743
+            $parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
744
+        } elseif (isset($desc['field']['id_groupe'])) {
745
+            $parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
746
+        } else {
747
+            $parent = "''";
748
+        }
749 749
 
750
-		$p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";
751
-	}
750
+        $p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";
751
+    }
752 752
 
753
-	$p->interdire_scripts = false;
753
+    $p->interdire_scripts = false;
754 754
 
755
-	return $p;
755
+    return $p;
756 756
 }
757 757
 
758 758
 
@@ -793,46 +793,46 @@  discard block
 block discarded – undo
793 793
  **/
794 794
 function balise_INTRODUCTION_dist($p) {
795 795
 
796
-	$type_objet = $p->type_requete;
797
-	$cle_objet = id_table_objet($type_objet);
798
-	$_id_objet = champ_sql($cle_objet, $p);
799
-
800
-	// Récupérer les valeurs sql nécessaires : descriptif, texte et chapo
801
-	// ainsi que le longueur d'introduction donnée dans la description de l'objet.
802
-	$_introduction_longueur = 'null';
803
-	$_ligne = 'array(';
804
-	$trouver_table = charger_fonction('trouver_table', 'base');
805
-	if ($desc = $trouver_table(table_objet_sql($type_objet))) {
806
-		if (isset($desc['field']['descriptif'])) {
807
-			$_ligne .= "'descriptif' => " . champ_sql('descriptif', $p) . ',';
808
-		}
809
-		if (isset($desc['field']['texte'])) {
810
-			$_ligne .= "'texte' => " . champ_sql('texte', $p) . ',';
811
-		}
812
-		if (isset($desc['field']['chapo'])) {
813
-			$_ligne .= "'chapo' => " . champ_sql('chapo', $p) . ',';
814
-		}
815
-		if (isset($desc['introduction_longueur'])) {
816
-			$_introduction_longueur = "'" . $desc['introduction_longueur'] . "'";
817
-		}
818
-	}
819
-	$_ligne .= ')';
820
-
821
-	// Récupérer la longueur et la suite passés en paramètres
822
-	$_longueur_ou_suite = 'null';
823
-	if (($v1 = interprete_argument_balise(1, $p)) !== null) {
824
-		$_longueur_ou_suite = $v1;
825
-	}
826
-	$_suite = 'null';
827
-	if (($v2 = interprete_argument_balise(2, $p)) !== null) {
828
-		$_suite = $v2;
829
-	}
830
-
831
-	$p->code = "generer_objet_introduction($_id_objet, '$type_objet', $_ligne, $_introduction_longueur, $_longueur_ou_suite, $_suite, \$connect)";
832
-
833
-	#$p->interdire_scripts = true;
834
-	$p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
835
-	return $p;
796
+    $type_objet = $p->type_requete;
797
+    $cle_objet = id_table_objet($type_objet);
798
+    $_id_objet = champ_sql($cle_objet, $p);
799
+
800
+    // Récupérer les valeurs sql nécessaires : descriptif, texte et chapo
801
+    // ainsi que le longueur d'introduction donnée dans la description de l'objet.
802
+    $_introduction_longueur = 'null';
803
+    $_ligne = 'array(';
804
+    $trouver_table = charger_fonction('trouver_table', 'base');
805
+    if ($desc = $trouver_table(table_objet_sql($type_objet))) {
806
+        if (isset($desc['field']['descriptif'])) {
807
+            $_ligne .= "'descriptif' => " . champ_sql('descriptif', $p) . ',';
808
+        }
809
+        if (isset($desc['field']['texte'])) {
810
+            $_ligne .= "'texte' => " . champ_sql('texte', $p) . ',';
811
+        }
812
+        if (isset($desc['field']['chapo'])) {
813
+            $_ligne .= "'chapo' => " . champ_sql('chapo', $p) . ',';
814
+        }
815
+        if (isset($desc['introduction_longueur'])) {
816
+            $_introduction_longueur = "'" . $desc['introduction_longueur'] . "'";
817
+        }
818
+    }
819
+    $_ligne .= ')';
820
+
821
+    // Récupérer la longueur et la suite passés en paramètres
822
+    $_longueur_ou_suite = 'null';
823
+    if (($v1 = interprete_argument_balise(1, $p)) !== null) {
824
+        $_longueur_ou_suite = $v1;
825
+    }
826
+    $_suite = 'null';
827
+    if (($v2 = interprete_argument_balise(2, $p)) !== null) {
828
+        $_suite = $v2;
829
+    }
830
+
831
+    $p->code = "generer_objet_introduction($_id_objet, '$type_objet', $_ligne, $_introduction_longueur, $_longueur_ou_suite, $_suite, \$connect)";
832
+
833
+    #$p->interdire_scripts = true;
834
+    $p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
835
+    return $p;
836 836
 }
837 837
 
838 838
 
@@ -852,15 +852,15 @@  discard block
 block discarded – undo
852 852
  *     Pile complétée par le code à générer
853 853
  **/
854 854
 function balise_LANG_dist($p) {
855
-	$_lang = champ_sql('lang', $p);
856
-	if (!$p->etoile) {
857
-		$p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
858
-	} else {
859
-		$p->code = "spip_htmlentities($_lang)";
860
-	}
861
-	$p->interdire_scripts = false;
855
+    $_lang = champ_sql('lang', $p);
856
+    if (!$p->etoile) {
857
+        $p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
858
+    } else {
859
+        $p->code = "spip_htmlentities($_lang)";
860
+    }
861
+    $p->interdire_scripts = false;
862 862
 
863
-	return $p;
863
+    return $p;
864 864
 }
865 865
 
866 866
 /**
@@ -882,45 +882,45 @@  discard block
 block discarded – undo
882 882
  *     Pile complétée par le code à générer
883 883
  */
884 884
 function balise_LESAUTEURS_dist($p) {
885
-	// Cherche le champ 'lesauteurs' dans la pile
886
-	$_lesauteurs = champ_sql('lesauteurs', $p, '');
887
-
888
-	// Si le champ n'existe pas (cas de spip_articles), on applique
889
-	// le modele lesauteurs.html en passant id_article dans le contexte;
890
-	// dans le cas contraire on prend le champ 'lesauteurs'
891
-	// (cf extension sites/)
892
-	if ($_lesauteurs) {
893
-		$p->code = "safehtml($_lesauteurs)";
894
-		// $p->interdire_scripts = true;
895
-	} else {
896
-		if (!$p->id_boucle) {
897
-			$connect = '';
898
-			$objet = 'article';
899
-			$id_table_objet = 'id_article';
900
-		} else {
901
-			$b = $p->nom_boucle ?: $p->id_boucle;
902
-			$connect = $p->boucles[$b]->sql_serveur;
903
-			$type_boucle = $p->boucles[$b]->type_requete;
904
-			$objet = objet_type($type_boucle);
905
-			$id_table_objet = id_table_objet($type_boucle);
906
-		}
907
-		$c = memoriser_contexte_compil($p);
908
-
909
-		$p->code = sprintf(
910
-			CODE_RECUPERER_FOND,
911
-			"'modeles/lesauteurs'",
912
-			"array('objet'=>'" . $objet .
913
-			"','id_objet' => " . champ_sql($id_table_objet, $p) .
914
-			",'$id_table_objet' => " . champ_sql($id_table_objet, $p) .
915
-			($objet == 'article' ? '' : ",'id_article' => " . champ_sql('id_article', $p)) .
916
-			')',
917
-			"'trim'=>true, 'compil'=>array($c)",
918
-			_q($connect)
919
-		);
920
-		$p->interdire_scripts = false; // securite apposee par recuperer_fond()
921
-	}
922
-
923
-	return $p;
885
+    // Cherche le champ 'lesauteurs' dans la pile
886
+    $_lesauteurs = champ_sql('lesauteurs', $p, '');
887
+
888
+    // Si le champ n'existe pas (cas de spip_articles), on applique
889
+    // le modele lesauteurs.html en passant id_article dans le contexte;
890
+    // dans le cas contraire on prend le champ 'lesauteurs'
891
+    // (cf extension sites/)
892
+    if ($_lesauteurs) {
893
+        $p->code = "safehtml($_lesauteurs)";
894
+        // $p->interdire_scripts = true;
895
+    } else {
896
+        if (!$p->id_boucle) {
897
+            $connect = '';
898
+            $objet = 'article';
899
+            $id_table_objet = 'id_article';
900
+        } else {
901
+            $b = $p->nom_boucle ?: $p->id_boucle;
902
+            $connect = $p->boucles[$b]->sql_serveur;
903
+            $type_boucle = $p->boucles[$b]->type_requete;
904
+            $objet = objet_type($type_boucle);
905
+            $id_table_objet = id_table_objet($type_boucle);
906
+        }
907
+        $c = memoriser_contexte_compil($p);
908
+
909
+        $p->code = sprintf(
910
+            CODE_RECUPERER_FOND,
911
+            "'modeles/lesauteurs'",
912
+            "array('objet'=>'" . $objet .
913
+            "','id_objet' => " . champ_sql($id_table_objet, $p) .
914
+            ",'$id_table_objet' => " . champ_sql($id_table_objet, $p) .
915
+            ($objet == 'article' ? '' : ",'id_article' => " . champ_sql('id_article', $p)) .
916
+            ')',
917
+            "'trim'=>true, 'compil'=>array($c)",
918
+            _q($connect)
919
+        );
920
+        $p->interdire_scripts = false; // securite apposee par recuperer_fond()
921
+    }
922
+
923
+    return $p;
924 924
 }
925 925
 
926 926
 
@@ -947,76 +947,76 @@  discard block
 block discarded – undo
947 947
  *     Pile complétée par le code à générer
948 948
  */
949 949
 function balise_RANG_dist($p) {
950
-	$b = index_boucle($p);
951
-	if ($b === '') {
952
-		$msg = [
953
-			'zbug_champ_hors_boucle',
954
-			['champ' => '#RANG']
955
-		];
956
-		erreur_squelette($msg, $p);
957
-	} else {
958
-		// chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql)
959
-		// dans la boucle immediatement englobante uniquement
960
-		// sinon on compose le champ calcule
961
-		$_rang = champ_sql('rang', $p, '', false);
962
-
963
-		// si pas trouve de champ sql rang :
964
-		if (!$_rang or $_rang == "''") {
965
-			$boucle = &$p->boucles[$b];
966
-
967
-			// on gere le cas ou #RANG est une extraction du numero dans le titre
968
-			$trouver_table = charger_fonction('trouver_table', 'base');
969
-			$desc = $trouver_table($boucle->id_table);
970
-			$_titre = ''; # où extraire le numero ?
971
-
972
-			if (isset($desc['titre'])) {
973
-				$t = $desc['titre'];
974
-				if (
975
-					// Soit on trouve avec la déclaration de la lang AVANT
976
-					preg_match(';(?:lang\s*,)\s*(.*?titre)\s*(,|$);', $t, $m)
977
-					// Soit on prend depuis le début
978
-					or preg_match(';^(.*?titre)\s*(,|$);', $t, $m)
979
-				) {
980
-					$m = preg_replace(',as\s+titre$,i', '', $m[1]);
981
-					$m = trim($m);
982
-					if ($m != "''") {
983
-						if (!preg_match(',\W,', $m)) {
984
-							$m = $boucle->id_table . ".$m";
985
-						}
986
-
987
-						$m .= ' AS titre_rang';
988
-
989
-						$boucle->select[] = $m;
990
-						$_titre = '$Pile[$SP][\'titre_rang\']';
991
-					}
992
-				}
993
-			}
994
-
995
-			// si on n'a rien trouvé, on utilise le champ titre classique
996
-			if (!$_titre) {
997
-				$_titre = champ_sql('titre', $p);
998
-			}
999
-
1000
-			// et on recupere aussi les infos de liaison si on est en train d'editer les liens justement
1001
-			// cas des formulaires xxx_lies utilises par #FORMULAIRE_EDITER_LIENS
1002
-			$type_boucle = $boucle->type_requete;
1003
-			$objet = objet_type($type_boucle);
1004
-			$id_table_objet = id_table_objet($type_boucle);
1005
-			$_primary = champ_sql($id_table_objet, $p, '', false);
1006
-			$_env = '$Pile[0]';
1007
-
1008
-			if (!$_titre) {$_titre = "''";
1009
-			}
1010
-			if (!$_primary) {$_primary = "''";
1011
-			}
1012
-			$_rang = "calculer_rang_smart($_titre, '$objet', $_primary, $_env)";
1013
-		}
1014
-
1015
-		$p->code = $_rang;
1016
-		$p->interdire_scripts = false;
1017
-	}
1018
-
1019
-	return $p;
950
+    $b = index_boucle($p);
951
+    if ($b === '') {
952
+        $msg = [
953
+            'zbug_champ_hors_boucle',
954
+            ['champ' => '#RANG']
955
+        ];
956
+        erreur_squelette($msg, $p);
957
+    } else {
958
+        // chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql)
959
+        // dans la boucle immediatement englobante uniquement
960
+        // sinon on compose le champ calcule
961
+        $_rang = champ_sql('rang', $p, '', false);
962
+
963
+        // si pas trouve de champ sql rang :
964
+        if (!$_rang or $_rang == "''") {
965
+            $boucle = &$p->boucles[$b];
966
+
967
+            // on gere le cas ou #RANG est une extraction du numero dans le titre
968
+            $trouver_table = charger_fonction('trouver_table', 'base');
969
+            $desc = $trouver_table($boucle->id_table);
970
+            $_titre = ''; # où extraire le numero ?
971
+
972
+            if (isset($desc['titre'])) {
973
+                $t = $desc['titre'];
974
+                if (
975
+                    // Soit on trouve avec la déclaration de la lang AVANT
976
+                    preg_match(';(?:lang\s*,)\s*(.*?titre)\s*(,|$);', $t, $m)
977
+                    // Soit on prend depuis le début
978
+                    or preg_match(';^(.*?titre)\s*(,|$);', $t, $m)
979
+                ) {
980
+                    $m = preg_replace(',as\s+titre$,i', '', $m[1]);
981
+                    $m = trim($m);
982
+                    if ($m != "''") {
983
+                        if (!preg_match(',\W,', $m)) {
984
+                            $m = $boucle->id_table . ".$m";
985
+                        }
986
+
987
+                        $m .= ' AS titre_rang';
988
+
989
+                        $boucle->select[] = $m;
990
+                        $_titre = '$Pile[$SP][\'titre_rang\']';
991
+                    }
992
+                }
993
+            }
994
+
995
+            // si on n'a rien trouvé, on utilise le champ titre classique
996
+            if (!$_titre) {
997
+                $_titre = champ_sql('titre', $p);
998
+            }
999
+
1000
+            // et on recupere aussi les infos de liaison si on est en train d'editer les liens justement
1001
+            // cas des formulaires xxx_lies utilises par #FORMULAIRE_EDITER_LIENS
1002
+            $type_boucle = $boucle->type_requete;
1003
+            $objet = objet_type($type_boucle);
1004
+            $id_table_objet = id_table_objet($type_boucle);
1005
+            $_primary = champ_sql($id_table_objet, $p, '', false);
1006
+            $_env = '$Pile[0]';
1007
+
1008
+            if (!$_titre) {$_titre = "''";
1009
+            }
1010
+            if (!$_primary) {$_primary = "''";
1011
+            }
1012
+            $_rang = "calculer_rang_smart($_titre, '$objet', $_primary, $_env)";
1013
+        }
1014
+
1015
+        $p->code = $_rang;
1016
+        $p->interdire_scripts = false;
1017
+    }
1018
+
1019
+    return $p;
1020 1020
 }
1021 1021
 
1022 1022
 
@@ -1038,12 +1038,12 @@  discard block
 block discarded – undo
1038 1038
  *     Pile complétée par le code à générer
1039 1039
  **/
1040 1040
 function balise_POPULARITE_dist($p) {
1041
-	$_popularite = champ_sql('popularite', $p);
1042
-	$p->code = "(ceil(min(100, 100 * $_popularite
1041
+    $_popularite = champ_sql('popularite', $p);
1042
+    $p->code = "(ceil(min(100, 100 * $_popularite
1043 1043
 	/ max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))";
1044
-	$p->interdire_scripts = false;
1044
+    $p->interdire_scripts = false;
1045 1045
 
1046
-	return $p;
1046
+    return $p;
1047 1047
 }
1048 1048
 
1049 1049
 /**
@@ -1054,8 +1054,8 @@  discard block
 block discarded – undo
1054 1054
  * l'absence peut-être due à une faute de frappe dans le contexte inclus.
1055 1055
  */
1056 1056
 define(
1057
-	'CODE_PAGINATION',
1058
-	'%s($Numrows["%s"]["grand_total"],
1057
+    'CODE_PAGINATION',
1058
+    '%s($Numrows["%s"]["grand_total"],
1059 1059
  		%s,
1060 1060
 		isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)),
1061 1061
 		%5$s, %6$s, %7$s, %8$s, array(%9$s))'
@@ -1092,75 +1092,75 @@  discard block
 block discarded – undo
1092 1092
  *     Pile complétée par le code à générer
1093 1093
  */
1094 1094
 function balise_PAGINATION_dist($p, $liste = 'true') {
1095
-	$b = index_boucle_mere($p);
1096
-
1097
-	// s'il n'y a pas de nom de boucle, on ne peut pas paginer
1098
-	if ($b === '') {
1099
-		$msg = [
1100
-			'zbug_champ_hors_boucle',
1101
-			['champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION']
1102
-		];
1103
-		erreur_squelette($msg, $p);
1104
-
1105
-		return $p;
1106
-	}
1107
-
1108
-	// s'il n'y a pas de mode_partie, c'est qu'on se trouve
1109
-	// dans un boucle recursive ou qu'on a oublie le critere {pagination}
1110
-	if (!$p->boucles[$b]->mode_partie) {
1111
-		if (!$p->boucles[$b]->table_optionnelle) {
1112
-			$msg = [
1113
-				'zbug_pagination_sans_critere',
1114
-				['champ' => '#PAGINATION']
1115
-			];
1116
-			erreur_squelette($msg, $p);
1117
-		}
1118
-
1119
-		return $p;
1120
-	}
1121
-
1122
-	// a priori true
1123
-	// si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
1124
-	// si true, les arguments simples (sans truc=chose) vont degager
1125
-	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
1126
-	if (is_countable($_contexte) ? count($_contexte) : 0) {
1127
-		$key = key($_contexte);
1128
-		if (is_numeric($key)) {
1129
-			array_shift($_contexte);
1130
-			$__modele = interprete_argument_balise(1, $p);
1131
-		}
1132
-	}
1133
-
1134
-	if (is_countable($_contexte) ? count($_contexte) : 0) {
1135
-		$code_contexte = implode(',', $_contexte);
1136
-	} else {
1137
-		$code_contexte = '';
1138
-	}
1139
-
1140
-	$connect = $p->boucles[$b]->sql_serveur;
1141
-	$pas = $p->boucles[$b]->total_parties;
1142
-	$f_pagination = chercher_filtre('pagination');
1143
-	$type = $p->boucles[$b]->modificateur['debut_nom'];
1144
-	$modif = ($type[0] !== "'") ? "'debut'.$type"
1145
-		: ("'debut" . substr($type, 1));
1146
-
1147
-	$p->code = sprintf(
1148
-		CODE_PAGINATION,
1149
-		$f_pagination,
1150
-		$b,
1151
-		$type,
1152
-		$modif,
1153
-		$pas,
1154
-		$liste,
1155
-		((isset($__modele) and $__modele) ? $__modele : "''"),
1156
-		_q($connect),
1157
-		$code_contexte
1158
-	);
1159
-
1160
-	$p->boucles[$b]->numrows = true;
1161
-	$p->interdire_scripts = false;
1162
-
1163
-	return $p;
1095
+    $b = index_boucle_mere($p);
1096
+
1097
+    // s'il n'y a pas de nom de boucle, on ne peut pas paginer
1098
+    if ($b === '') {
1099
+        $msg = [
1100
+            'zbug_champ_hors_boucle',
1101
+            ['champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION']
1102
+        ];
1103
+        erreur_squelette($msg, $p);
1104
+
1105
+        return $p;
1106
+    }
1107
+
1108
+    // s'il n'y a pas de mode_partie, c'est qu'on se trouve
1109
+    // dans un boucle recursive ou qu'on a oublie le critere {pagination}
1110
+    if (!$p->boucles[$b]->mode_partie) {
1111
+        if (!$p->boucles[$b]->table_optionnelle) {
1112
+            $msg = [
1113
+                'zbug_pagination_sans_critere',
1114
+                ['champ' => '#PAGINATION']
1115
+            ];
1116
+            erreur_squelette($msg, $p);
1117
+        }
1118
+
1119
+        return $p;
1120
+    }
1121
+
1122
+    // a priori true
1123
+    // si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
1124
+    // si true, les arguments simples (sans truc=chose) vont degager
1125
+    $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
1126
+    if (is_countable($_contexte) ? count($_contexte) : 0) {
1127
+        $key = key($_contexte);
1128
+        if (is_numeric($key)) {
1129
+            array_shift($_contexte);
1130
+            $__modele = interprete_argument_balise(1, $p);
1131
+        }
1132
+    }
1133
+
1134
+    if (is_countable($_contexte) ? count($_contexte) : 0) {
1135
+        $code_contexte = implode(',', $_contexte);
1136
+    } else {
1137
+        $code_contexte = '';
1138
+    }
1139
+
1140
+    $connect = $p->boucles[$b]->sql_serveur;
1141
+    $pas = $p->boucles[$b]->total_parties;
1142
+    $f_pagination = chercher_filtre('pagination');
1143
+    $type = $p->boucles[$b]->modificateur['debut_nom'];
1144
+    $modif = ($type[0] !== "'") ? "'debut'.$type"
1145
+        : ("'debut" . substr($type, 1));
1146
+
1147
+    $p->code = sprintf(
1148
+        CODE_PAGINATION,
1149
+        $f_pagination,
1150
+        $b,
1151
+        $type,
1152
+        $modif,
1153
+        $pas,
1154
+        $liste,
1155
+        ((isset($__modele) and $__modele) ? $__modele : "''"),
1156
+        _q($connect),
1157
+        $code_contexte
1158
+    );
1159
+
1160
+    $p->boucles[$b]->numrows = true;
1161
+    $p->interdire_scripts = false;
1162
+
1163
+    return $p;
1164 1164
 }
1165 1165
 
1166 1166
 
@@ -1187,11 +1187,11 @@  discard block
 block discarded – undo
1187 1187
  *     Pile complétée par le code à générer
1188 1188
  **/
1189 1189
 function balise_ANCRE_PAGINATION_dist($p) {
1190
-	if ($f = charger_fonction('PAGINATION', 'balise', true)) {
1191
-		return $f($p, $liste = 'false');
1192
-	} else {
1193
-		return null;
1194
-	} // ou une erreur ?
1190
+    if ($f = charger_fonction('PAGINATION', 'balise', true)) {
1191
+        return $f($p, $liste = 'false');
1192
+    } else {
1193
+        return null;
1194
+    } // ou une erreur ?
1195 1195
 }
1196 1196
 
1197 1197
 
@@ -1212,17 +1212,17 @@  discard block
 block discarded – undo
1212 1212
  *     Pile complétée par le code à générer
1213 1213
  **/
1214 1214
 function balise_GRAND_TOTAL_dist($p) {
1215
-	$b = index_boucle_mere($p);
1216
-	if ($b === '') {
1217
-		$msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
1218
-		erreur_squelette($msg, $p);
1219
-	} else {
1220
-		$p->code = "(\$Numrows['$b']['grand_total'] ?? \$Numrows['$b']['total'] ?? 0)";
1221
-		$p->boucles[$b]->numrows = true;
1222
-		$p->interdire_scripts = false;
1223
-	}
1215
+    $b = index_boucle_mere($p);
1216
+    if ($b === '') {
1217
+        $msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
1218
+        erreur_squelette($msg, $p);
1219
+    } else {
1220
+        $p->code = "(\$Numrows['$b']['grand_total'] ?? \$Numrows['$b']['total'] ?? 0)";
1221
+        $p->boucles[$b]->numrows = true;
1222
+        $p->interdire_scripts = false;
1223
+    }
1224 1224
 
1225
-	return $p;
1225
+    return $p;
1226 1226
 }
1227 1227
 
1228 1228
 
@@ -1250,10 +1250,10 @@  discard block
 block discarded – undo
1250 1250
  *     Pile complétée par le code à générer
1251 1251
  **/
1252 1252
 function balise_SELF_dist($p) {
1253
-	$p->code = 'self()';
1254
-	$p->interdire_scripts = false;
1253
+    $p->code = 'self()';
1254
+    $p->interdire_scripts = false;
1255 1255
 
1256
-	return $p;
1256
+    return $p;
1257 1257
 }
1258 1258
 
1259 1259
 
@@ -1280,17 +1280,17 @@  discard block
 block discarded – undo
1280 1280
  *     Pile complétée par le code à générer
1281 1281
  **/
1282 1282
 function balise_CHEMIN_dist($p) {
1283
-	$arg = interprete_argument_balise(1, $p);
1284
-	if (!$arg) {
1285
-		$msg = ['zbug_balise_sans_argument', ['balise' => ' CHEMIN']];
1286
-		erreur_squelette($msg, $p);
1287
-	} else {
1288
-		$p->code = 'find_in_path((string)' . $arg . ')';
1289
-	}
1283
+    $arg = interprete_argument_balise(1, $p);
1284
+    if (!$arg) {
1285
+        $msg = ['zbug_balise_sans_argument', ['balise' => ' CHEMIN']];
1286
+        erreur_squelette($msg, $p);
1287
+    } else {
1288
+        $p->code = 'find_in_path((string)' . $arg . ')';
1289
+    }
1290 1290
 
1291
-	$p->interdire_scripts = false;
1291
+    $p->interdire_scripts = false;
1292 1292
 
1293
-	return $p;
1293
+    return $p;
1294 1294
 }
1295 1295
 
1296 1296
 /**
@@ -1315,16 +1315,16 @@  discard block
 block discarded – undo
1315 1315
  *     Pile complétée par le code à générer
1316 1316
  **/
1317 1317
 function balise_CHEMIN_IMAGE_dist($p) {
1318
-	$arg = interprete_argument_balise(1, $p);
1319
-	if (!$arg) {
1320
-		$msg = ['zbug_balise_sans_argument', ['balise' => ' CHEMIN_IMAGE']];
1321
-		erreur_squelette($msg, $p);
1322
-	} else {
1323
-		$p->code = 'chemin_image((string)' . $arg . ')';
1324
-	}
1318
+    $arg = interprete_argument_balise(1, $p);
1319
+    if (!$arg) {
1320
+        $msg = ['zbug_balise_sans_argument', ['balise' => ' CHEMIN_IMAGE']];
1321
+        erreur_squelette($msg, $p);
1322
+    } else {
1323
+        $p->code = 'chemin_image((string)' . $arg . ')';
1324
+    }
1325 1325
 
1326
-	$p->interdire_scripts = false;
1327
-	return $p;
1326
+    $p->interdire_scripts = false;
1327
+    return $p;
1328 1328
 }
1329 1329
 
1330 1330
 
@@ -1362,36 +1362,36 @@  discard block
 block discarded – undo
1362 1362
  **/
1363 1363
 function balise_ENV_dist($p, $src = null) {
1364 1364
 
1365
-	// cle du tableau desiree
1366
-	$_nom = interprete_argument_balise(1, $p);
1367
-	// valeur par defaut
1368
-	$_sinon = interprete_argument_balise(2, $p);
1365
+    // cle du tableau desiree
1366
+    $_nom = interprete_argument_balise(1, $p);
1367
+    // valeur par defaut
1368
+    $_sinon = interprete_argument_balise(2, $p);
1369 1369
 
1370
-	// $src est un tableau de donnees sources eventuellement transmis
1371
-	// en absence, on utilise l'environnement du squelette $Pile[0]
1370
+    // $src est un tableau de donnees sources eventuellement transmis
1371
+    // en absence, on utilise l'environnement du squelette $Pile[0]
1372 1372
 
1373
-	if (!$_nom) {
1374
-		// cas de #ENV sans argument : on retourne le serialize() du tableau
1375
-		// une belle fonction [(#ENV|affiche_env)] serait pratique
1376
-		if ($src) {
1377
-			$p->code = '(is_array($a = (' . $src . ')) ? serialize($a) : "")';
1378
-		} else {
1379
-			$p->code = 'serialize($Pile[0]??[])';
1380
-		}
1381
-	} else {
1382
-		if (!$src) {
1383
-			$src = '$Pile[0]??[]';
1384
-		}
1385
-		if ($_sinon) {
1386
-			$p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)";
1387
-		} else {
1388
-			$p->code = "table_valeur($src, (string)$_nom, null)";
1389
-		}
1390
-	}
1373
+    if (!$_nom) {
1374
+        // cas de #ENV sans argument : on retourne le serialize() du tableau
1375
+        // une belle fonction [(#ENV|affiche_env)] serait pratique
1376
+        if ($src) {
1377
+            $p->code = '(is_array($a = (' . $src . ')) ? serialize($a) : "")';
1378
+        } else {
1379
+            $p->code = 'serialize($Pile[0]??[])';
1380
+        }
1381
+    } else {
1382
+        if (!$src) {
1383
+            $src = '$Pile[0]??[]';
1384
+        }
1385
+        if ($_sinon) {
1386
+            $p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)";
1387
+        } else {
1388
+            $p->code = "table_valeur($src, (string)$_nom, null)";
1389
+        }
1390
+    }
1391 1391
 
1392
-	#$p->interdire_scripts = true;
1392
+    #$p->interdire_scripts = true;
1393 1393
 
1394
-	return $p;
1394
+    return $p;
1395 1395
 }
1396 1396
 
1397 1397
 /**
@@ -1421,16 +1421,16 @@  discard block
 block discarded – undo
1421 1421
  *     Pile completée du code PHP d'exécution de la balise
1422 1422
  */
1423 1423
 function balise_CONFIG_dist($p) {
1424
-	if (!$arg = interprete_argument_balise(1, $p)) {
1425
-		$arg = "''";
1426
-	}
1427
-	$_sinon = interprete_argument_balise(2, $p);
1428
-	$_unserialize = sinon(interprete_argument_balise(3, $p), 'false');
1424
+    if (!$arg = interprete_argument_balise(1, $p)) {
1425
+        $arg = "''";
1426
+    }
1427
+    $_sinon = interprete_argument_balise(2, $p);
1428
+    $_unserialize = sinon(interprete_argument_balise(3, $p), 'false');
1429 1429
 
1430
-	$p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' .
1431
-		($_sinon && $_sinon != "''" ? $_sinon : 'null') . ',' . $_unserialize . "):'')";
1430
+    $p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' .
1431
+        ($_sinon && $_sinon != "''" ? $_sinon : 'null') . ',' . $_unserialize . "):'')";
1432 1432
 
1433
-	return $p;
1433
+    return $p;
1434 1434
 }
1435 1435
 
1436 1436
 
@@ -1453,10 +1453,10 @@  discard block
 block discarded – undo
1453 1453
  *     Pile completée du code PHP d'exécution de la balise
1454 1454
  */
1455 1455
 function balise_CONNECT_dist($p) {
1456
-	$p->code = '($connect ? $connect : NULL)';
1457
-	$p->interdire_scripts = false;
1456
+    $p->code = '($connect ? $connect : NULL)';
1457
+    $p->interdire_scripts = false;
1458 1458
 
1459
-	return $p;
1459
+    return $p;
1460 1460
 }
1461 1461
 
1462 1462
 
@@ -1484,15 +1484,15 @@  discard block
 block discarded – undo
1484 1484
  *     Pile completée du code PHP d'exécution de la balise
1485 1485
  **/
1486 1486
 function balise_SESSION_dist($p) {
1487
-	$p->descr['session'] = true;
1487
+    $p->descr['session'] = true;
1488 1488
 
1489
-	$f = function_exists('balise_ENV')
1490
-		? 'balise_ENV'
1491
-		: 'balise_ENV_dist';
1489
+    $f = function_exists('balise_ENV')
1490
+        ? 'balise_ENV'
1491
+        : 'balise_ENV_dist';
1492 1492
 
1493
-	$p = $f($p, '$GLOBALS["visiteur_session"]??[]');
1493
+    $p = $f($p, '$GLOBALS["visiteur_session"]??[]');
1494 1494
 
1495
-	return $p;
1495
+    return $p;
1496 1496
 }
1497 1497
 
1498 1498
 
@@ -1515,18 +1515,18 @@  discard block
 block discarded – undo
1515 1515
  *     Pile completée du code PHP d'exécution de la balise
1516 1516
  **/
1517 1517
 function balise_SESSION_SET_dist($p) {
1518
-	$_nom = interprete_argument_balise(1, $p);
1519
-	$_val = interprete_argument_balise(2, $p);
1520
-	if (!$_nom or !$_val) {
1521
-		$err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'SESSION_SET']];
1522
-		erreur_squelette($err_b_s_a, $p);
1523
-	} else {
1524
-		$p->code = '(include_spip("inc/session") AND session_set(' . $_nom . ',' . $_val . '))';
1525
-	}
1518
+    $_nom = interprete_argument_balise(1, $p);
1519
+    $_val = interprete_argument_balise(2, $p);
1520
+    if (!$_nom or !$_val) {
1521
+        $err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'SESSION_SET']];
1522
+        erreur_squelette($err_b_s_a, $p);
1523
+    } else {
1524
+        $p->code = '(include_spip("inc/session") AND session_set(' . $_nom . ',' . $_val . '))';
1525
+    }
1526 1526
 
1527
-	$p->interdire_scripts = false;
1527
+    $p->interdire_scripts = false;
1528 1528
 
1529
-	return $p;
1529
+    return $p;
1530 1530
 }
1531 1531
 
1532 1532
 
@@ -1557,30 +1557,30 @@  discard block
 block discarded – undo
1557 1557
  *     Pile completée du code PHP d'exécution de la balise
1558 1558
  **/
1559 1559
 function balise_EVAL_dist($p) {
1560
-	$php = interprete_argument_balise(1, $p);
1561
-	if ($php) {
1562
-		# optimisation sur les #EVAL{une expression sans #BALISE}
1563
-		# attention au commentaire "// x signes" qui precede
1564
-		if (
1565
-			preg_match(
1566
-				",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms",
1567
-				$php,
1568
-				$r
1569
-			)
1570
-		) {
1571
-			$p->code = /* $r[1]. */
1572
-				'(' . $r[2] . ')';
1573
-		} else {
1574
-			$p->code = "eval('return '.$php.';')";
1575
-		}
1576
-	} else {
1577
-		$msg = ['zbug_balise_sans_argument', ['balise' => ' EVAL']];
1578
-		erreur_squelette($msg, $p);
1579
-	}
1580
-
1581
-	#$p->interdire_scripts = true;
1582
-
1583
-	return $p;
1560
+    $php = interprete_argument_balise(1, $p);
1561
+    if ($php) {
1562
+        # optimisation sur les #EVAL{une expression sans #BALISE}
1563
+        # attention au commentaire "// x signes" qui precede
1564
+        if (
1565
+            preg_match(
1566
+                ",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms",
1567
+                $php,
1568
+                $r
1569
+            )
1570
+        ) {
1571
+            $p->code = /* $r[1]. */
1572
+                '(' . $r[2] . ')';
1573
+        } else {
1574
+            $p->code = "eval('return '.$php.';')";
1575
+        }
1576
+    } else {
1577
+        $msg = ['zbug_balise_sans_argument', ['balise' => ' EVAL']];
1578
+        erreur_squelette($msg, $p);
1579
+    }
1580
+
1581
+    #$p->interdire_scripts = true;
1582
+
1583
+    return $p;
1584 1584
 }
1585 1585
 
1586 1586
 
@@ -1610,19 +1610,19 @@  discard block
 block discarded – undo
1610 1610
  **/
1611 1611
 function balise_CHAMP_SQL_dist($p) {
1612 1612
 
1613
-	if (
1614
-		$p->param
1615
-		and isset($p->param[0][1][0])
1616
-		and $champ = ($p->param[0][1][0]->texte)
1617
-	) {
1618
-		$p->code = champ_sql($champ, $p);
1619
-	} else {
1620
-		$err_b_s_a = ['zbug_balise_sans_argument', ['balise' => ' CHAMP_SQL']];
1621
-		erreur_squelette($err_b_s_a, $p);
1622
-	}
1613
+    if (
1614
+        $p->param
1615
+        and isset($p->param[0][1][0])
1616
+        and $champ = ($p->param[0][1][0]->texte)
1617
+    ) {
1618
+        $p->code = champ_sql($champ, $p);
1619
+    } else {
1620
+        $err_b_s_a = ['zbug_balise_sans_argument', ['balise' => ' CHAMP_SQL']];
1621
+        erreur_squelette($err_b_s_a, $p);
1622
+    }
1623 1623
 
1624
-	#$p->interdire_scripts = true;
1625
-	return $p;
1624
+    #$p->interdire_scripts = true;
1625
+    return $p;
1626 1626
 }
1627 1627
 
1628 1628
 /**
@@ -1648,13 +1648,13 @@  discard block
 block discarded – undo
1648 1648
  *     Pile complétée par le code à générer
1649 1649
  **/
1650 1650
 function balise_VAL_dist($p) {
1651
-	$p->code = interprete_argument_balise(1, $p) ?? '';
1652
-	if (!strlen($p->code)) {
1653
-		$p->code = "''";
1654
-	}
1655
-	$p->interdire_scripts = false;
1651
+    $p->code = interprete_argument_balise(1, $p) ?? '';
1652
+    if (!strlen($p->code)) {
1653
+        $p->code = "''";
1654
+    }
1655
+    $p->interdire_scripts = false;
1656 1656
 
1657
-	return $p;
1657
+    return $p;
1658 1658
 }
1659 1659
 
1660 1660
 /**
@@ -1683,10 +1683,10 @@  discard block
 block discarded – undo
1683 1683
  *     Pile complétée par le code à générer
1684 1684
  **/
1685 1685
 function balise_REM_dist($p) {
1686
-	$p->code = "''";
1687
-	$p->interdire_scripts = false;
1686
+    $p->code = "''";
1687
+    $p->interdire_scripts = false;
1688 1688
 
1689
-	return $p;
1689
+    return $p;
1690 1690
 }
1691 1691
 
1692 1692
 /**
@@ -1696,10 +1696,10 @@  discard block
 block discarded – undo
1696 1696
  * @return mixed
1697 1697
  */
1698 1698
 function balise_NULL_dist($p) {
1699
-	$p->code = 'null';
1700
-	$p->interdire_scripts = false;
1699
+    $p->code = 'null';
1700
+    $p->interdire_scripts = false;
1701 1701
 
1702
-	return $p;
1702
+    return $p;
1703 1703
 }
1704 1704
 
1705 1705
 
@@ -1723,18 +1723,18 @@  discard block
 block discarded – undo
1723 1723
  **/
1724 1724
 function balise_HTTP_HEADER_dist($p) {
1725 1725
 
1726
-	$header = interprete_argument_balise(1, $p);
1727
-	if (!$header) {
1728
-		$err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'HTTP_HEADER']];
1729
-		erreur_squelette($err_b_s_a, $p);
1730
-	} else {
1731
-		$p->code = "'<'.'?php header(' . _q("
1732
-			. $header
1733
-			. ") . '); ?'.'>'";
1734
-	}
1735
-	$p->interdire_scripts = false;
1726
+    $header = interprete_argument_balise(1, $p);
1727
+    if (!$header) {
1728
+        $err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'HTTP_HEADER']];
1729
+        erreur_squelette($err_b_s_a, $p);
1730
+    } else {
1731
+        $p->code = "'<'.'?php header(' . _q("
1732
+            . $header
1733
+            . ") . '); ?'.'>'";
1734
+    }
1735
+    $p->interdire_scripts = false;
1736 1736
 
1737
-	return $p;
1737
+    return $p;
1738 1738
 }
1739 1739
 
1740 1740
 
@@ -1759,20 +1759,20 @@  discard block
 block discarded – undo
1759 1759
  *     Pile complétée par le code à générer
1760 1760
  **/
1761 1761
 function balise_FILTRE_dist($p) {
1762
-	if ($p->param) {
1763
-		$args = [];
1764
-		foreach ($p->param as $i => $ignore) {
1765
-			$args[] = interprete_argument_balise($i + 1, $p);
1766
-		}
1767
-		$p->code = "'<' . '"
1768
-			. '?php header("X-Spip-Filtre: \'.'
1769
-			. join('.\'|\'.', $args)
1770
-			. " . '\"); ?'.'>'";
1762
+    if ($p->param) {
1763
+        $args = [];
1764
+        foreach ($p->param as $i => $ignore) {
1765
+            $args[] = interprete_argument_balise($i + 1, $p);
1766
+        }
1767
+        $p->code = "'<' . '"
1768
+            . '?php header("X-Spip-Filtre: \'.'
1769
+            . join('.\'|\'.', $args)
1770
+            . " . '\"); ?'.'>'";
1771 1771
 
1772
-		$p->interdire_scripts = false;
1772
+        $p->interdire_scripts = false;
1773 1773
 
1774
-		return $p;
1775
-	}
1774
+        return $p;
1775
+    }
1776 1776
 }
1777 1777
 
1778 1778
 
@@ -1808,55 +1808,55 @@  discard block
 block discarded – undo
1808 1808
  **/
1809 1809
 function balise_CACHE_dist($p) {
1810 1810
 
1811
-	if ($p->param) {
1812
-		$duree = valeur_numerique($p->param[0][1][0]->texte);
1813
-
1814
-		// noter la duree du cache dans un entete proprietaire
1815
-
1816
-		$code = "'<'.'" . '?php header("X-Spip-Cache: '
1817
-			. $duree
1818
-			. '"); ?' . "'.'>'";
1819
-
1820
-		// Remplir le header Cache-Control
1821
-		// cas #CACHE{0}
1822
-		if ($duree == 0) {
1823
-			$code .= ".'<'.'"
1824
-				. '?php header("Cache-Control: no-cache, must-revalidate"); ?'
1825
-				. "'.'><'.'"
1826
-				. '?php header("Pragma: no-cache"); ?'
1827
-				. "'.'>'";
1828
-		}
1829
-
1830
-		// recuperer les parametres suivants
1831
-		$i = 1;
1832
-		while (isset($p->param[0][++$i])) {
1833
-			$pa = ($p->param[0][$i][0]->texte);
1834
-
1835
-			if (
1836
-				$pa == 'cache-client'
1837
-				and $duree > 0
1838
-			) {
1839
-				$code .= ".'<'.'" . '?php header("Cache-Control: max-age='
1840
-					. $duree
1841
-					. '"); ?' . "'.'>'";
1842
-				// il semble logique, si on cache-client, de ne pas invalider
1843
-				$pa = 'statique';
1844
-			}
1845
-
1846
-			if (
1847
-				$pa == 'statique'
1848
-				and $duree > 0
1849
-			) {
1850
-				$code .= ".'<'.'" . '?php header("X-Spip-Statique: oui"); ?' . "'.'>'";
1851
-			}
1852
-		}
1853
-	} else {
1854
-		$code = "''";
1855
-	}
1856
-	$p->code = $code;
1857
-	$p->interdire_scripts = false;
1858
-
1859
-	return $p;
1811
+    if ($p->param) {
1812
+        $duree = valeur_numerique($p->param[0][1][0]->texte);
1813
+
1814
+        // noter la duree du cache dans un entete proprietaire
1815
+
1816
+        $code = "'<'.'" . '?php header("X-Spip-Cache: '
1817
+            . $duree
1818
+            . '"); ?' . "'.'>'";
1819
+
1820
+        // Remplir le header Cache-Control
1821
+        // cas #CACHE{0}
1822
+        if ($duree == 0) {
1823
+            $code .= ".'<'.'"
1824
+                . '?php header("Cache-Control: no-cache, must-revalidate"); ?'
1825
+                . "'.'><'.'"
1826
+                . '?php header("Pragma: no-cache"); ?'
1827
+                . "'.'>'";
1828
+        }
1829
+
1830
+        // recuperer les parametres suivants
1831
+        $i = 1;
1832
+        while (isset($p->param[0][++$i])) {
1833
+            $pa = ($p->param[0][$i][0]->texte);
1834
+
1835
+            if (
1836
+                $pa == 'cache-client'
1837
+                and $duree > 0
1838
+            ) {
1839
+                $code .= ".'<'.'" . '?php header("Cache-Control: max-age='
1840
+                    . $duree
1841
+                    . '"); ?' . "'.'>'";
1842
+                // il semble logique, si on cache-client, de ne pas invalider
1843
+                $pa = 'statique';
1844
+            }
1845
+
1846
+            if (
1847
+                $pa == 'statique'
1848
+                and $duree > 0
1849
+            ) {
1850
+                $code .= ".'<'.'" . '?php header("X-Spip-Statique: oui"); ?' . "'.'>'";
1851
+            }
1852
+        }
1853
+    } else {
1854
+        $code = "''";
1855
+    }
1856
+    $p->code = $code;
1857
+    $p->interdire_scripts = false;
1858
+
1859
+    return $p;
1860 1860
 }
1861 1861
 
1862 1862
 
@@ -1888,13 +1888,13 @@  discard block
 block discarded – undo
1888 1888
  *     Pile complétée par le code à générer
1889 1889
  */
1890 1890
 function balise_INSERT_HEAD_dist($p) {
1891
-	$p->code = "'<'.'"
1892
-		. '?php header("X-Spip-Filtre: insert_head_css_conditionnel"); ?'
1893
-		. "'.'>'";
1894
-	$p->code .= ". pipeline('insert_head','<!-- insert_head -->')";
1895
-	$p->interdire_scripts = false;
1891
+    $p->code = "'<'.'"
1892
+        . '?php header("X-Spip-Filtre: insert_head_css_conditionnel"); ?'
1893
+        . "'.'>'";
1894
+    $p->code .= ". pipeline('insert_head','<!-- insert_head -->')";
1895
+    $p->interdire_scripts = false;
1896 1896
 
1897
-	return $p;
1897
+    return $p;
1898 1898
 }
1899 1899
 
1900 1900
 /**
@@ -1912,10 +1912,10 @@  discard block
 block discarded – undo
1912 1912
  *     Pile complétée par le code à générer
1913 1913
  */
1914 1914
 function balise_INSERT_HEAD_CSS_dist($p) {
1915
-	$p->code = "pipeline('insert_head_css','<!-- insert_head_css -->')";
1916
-	$p->interdire_scripts = false;
1915
+    $p->code = "pipeline('insert_head_css','<!-- insert_head_css -->')";
1916
+    $p->interdire_scripts = false;
1917 1917
 
1918
-	return $p;
1918
+    return $p;
1919 1919
 }
1920 1920
 
1921 1921
 /**
@@ -1930,11 +1930,11 @@  discard block
 block discarded – undo
1930 1930
  *     Pile complétée par le code à générer
1931 1931
  **/
1932 1932
 function balise_INCLUDE_dist($p) {
1933
-	if (function_exists('balise_INCLURE')) {
1934
-		return balise_INCLURE($p);
1935
-	} else {
1936
-		return balise_INCLURE_dist($p);
1937
-	}
1933
+    if (function_exists('balise_INCLURE')) {
1934
+        return balise_INCLURE($p);
1935
+    } else {
1936
+        return balise_INCLURE_dist($p);
1937
+    }
1938 1938
 }
1939 1939
 
1940 1940
 /**
@@ -1968,66 +1968,66 @@  discard block
 block discarded – undo
1968 1968
  *     Pile complétée par le code à générer
1969 1969
  **/
1970 1970
 function balise_INCLURE_dist($p) {
1971
-	$id_boucle = $p->id_boucle;
1972
-	// la lang n'est pas passe de facon automatique par argumenter
1973
-	// mais le sera pas recuperer_fond, sauf si etoile=>true est passe
1974
-	// en option
1975
-
1976
-	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
1977
-
1978
-	// erreur de syntaxe = fond absent
1979
-	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
1980
-	if (!$_contexte) {
1981
-		$contexte = [];
1982
-	}
1983
-
1984
-	if (isset($_contexte['fond'])) {
1985
-		$f = $_contexte['fond'];
1986
-		// toujours vrai :
1987
-		if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
1988
-			$f = $r[1];
1989
-			unset($_contexte['fond']);
1990
-		} else {
1991
-			spip_log('compilation de #INCLURE a revoir');
1992
-		}
1993
-
1994
-		// #INCLURE{doublons}
1995
-		if (isset($_contexte['doublons'])) {
1996
-			$_contexte['doublons'] = "'doublons' => \$doublons";
1997
-		}
1998
-
1999
-		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
2000
-		$flag_env = false;
2001
-		if (isset($_contexte['env']) or isset($_contexte['self'])) {
2002
-			$flag_env = true;
2003
-			unset($_contexte['env']);
2004
-		}
2005
-
2006
-		$_options = [];
2007
-		if (isset($_contexte['ajax'])) {
2008
-			$_options[] = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2009
-			unset($_contexte['ajax']);
2010
-		}
2011
-		if ($p->etoile) {
2012
-			$_options[] = "'etoile'=>true";
2013
-		}
2014
-		$_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) . ')';
2015
-
2016
-		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
2017
-		if ($flag_env) {
2018
-			$_l = "array_merge(\$Pile[0],$_l)";
2019
-		}
2020
-
2021
-		$p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',', $_options), "_request('connect') ?? ''");
2022
-	} elseif (!isset($_contexte[1])) {
2023
-		$msg = ['zbug_balise_sans_argument', ['balise' => ' INCLURE']];
2024
-		erreur_squelette($msg, $p);
2025
-	} else {
2026
-		$p->code = 'charge_scripts(' . $_contexte[1] . ',false)';
2027
-	}
2028
-
2029
-	$p->interdire_scripts = false; // la securite est assuree par recuperer_fond
2030
-	return $p;
1971
+    $id_boucle = $p->id_boucle;
1972
+    // la lang n'est pas passe de facon automatique par argumenter
1973
+    // mais le sera pas recuperer_fond, sauf si etoile=>true est passe
1974
+    // en option
1975
+
1976
+    $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
1977
+
1978
+    // erreur de syntaxe = fond absent
1979
+    // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
1980
+    if (!$_contexte) {
1981
+        $contexte = [];
1982
+    }
1983
+
1984
+    if (isset($_contexte['fond'])) {
1985
+        $f = $_contexte['fond'];
1986
+        // toujours vrai :
1987
+        if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
1988
+            $f = $r[1];
1989
+            unset($_contexte['fond']);
1990
+        } else {
1991
+            spip_log('compilation de #INCLURE a revoir');
1992
+        }
1993
+
1994
+        // #INCLURE{doublons}
1995
+        if (isset($_contexte['doublons'])) {
1996
+            $_contexte['doublons'] = "'doublons' => \$doublons";
1997
+        }
1998
+
1999
+        // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
2000
+        $flag_env = false;
2001
+        if (isset($_contexte['env']) or isset($_contexte['self'])) {
2002
+            $flag_env = true;
2003
+            unset($_contexte['env']);
2004
+        }
2005
+
2006
+        $_options = [];
2007
+        if (isset($_contexte['ajax'])) {
2008
+            $_options[] = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2009
+            unset($_contexte['ajax']);
2010
+        }
2011
+        if ($p->etoile) {
2012
+            $_options[] = "'etoile'=>true";
2013
+        }
2014
+        $_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) . ')';
2015
+
2016
+        $_l = 'array(' . join(",\n\t", $_contexte) . ')';
2017
+        if ($flag_env) {
2018
+            $_l = "array_merge(\$Pile[0],$_l)";
2019
+        }
2020
+
2021
+        $p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',', $_options), "_request('connect') ?? ''");
2022
+    } elseif (!isset($_contexte[1])) {
2023
+        $msg = ['zbug_balise_sans_argument', ['balise' => ' INCLURE']];
2024
+        erreur_squelette($msg, $p);
2025
+    } else {
2026
+        $p->code = 'charge_scripts(' . $_contexte[1] . ',false)';
2027
+    }
2028
+
2029
+    $p->interdire_scripts = false; // la securite est assuree par recuperer_fond
2030
+    return $p;
2031 2031
 }
2032 2032
 
2033 2033
 
@@ -2055,69 +2055,69 @@  discard block
 block discarded – undo
2055 2055
  **/
2056 2056
 function balise_MODELE_dist($p) {
2057 2057
 
2058
-	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
2059
-
2060
-	// erreur de syntaxe = fond absent
2061
-	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
2062
-	if (!$_contexte) {
2063
-		$_contexte = [];
2064
-	}
2065
-
2066
-	if (!isset($_contexte[1])) {
2067
-		$msg = ['zbug_balise_sans_argument', ['balise' => ' MODELE']];
2068
-		erreur_squelette($msg, $p);
2069
-	} else {
2070
-		$nom = $_contexte[1];
2071
-		unset($_contexte[1]);
2072
-
2073
-		if (preg_match("/^\s*'[^']*'/s", $nom)) {
2074
-			$nom = "'modeles/" . substr($nom, 1);
2075
-		} else {
2076
-			$nom = "'modeles/' . $nom";
2077
-		}
2078
-
2079
-		$flag_env = false;
2080
-		if (isset($_contexte['env'])) {
2081
-			$flag_env = true;
2082
-			unset($_contexte['env']);
2083
-		}
2084
-
2085
-		// Incoherence dans la syntaxe du contexte. A revoir.
2086
-		// Reserver la cle primaire de la boucle courante si elle existe
2087
-		if (isset($p->boucles[$p->id_boucle]->primary)) {
2088
-			$primary = $p->boucles[$p->id_boucle]->primary;
2089
-			if (!strpos($primary, ',')) {
2090
-				$id = champ_sql($primary, $p);
2091
-				$_contexte[] = "'$primary'=>" . $id;
2092
-				$_contexte[] = "'id'=>" . $id;
2093
-			}
2094
-		}
2095
-		$_contexte[] = "'recurs'=>(++\$recurs)";
2096
-		$connect = '';
2097
-		if (isset($p->boucles[$p->id_boucle])) {
2098
-			$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2099
-		}
2100
-
2101
-		$_options = memoriser_contexte_compil($p);
2102
-		$_options = "'compil'=>array($_options), 'trim'=>true";
2103
-		if (isset($_contexte['ajax'])) {
2104
-			$_options .= ', ' . preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2105
-			unset($_contexte['ajax']);
2106
-		}
2107
-
2108
-		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
2109
-		if ($flag_env) {
2110
-			$_l = "array_merge(\$Pile[0],$_l)";
2111
-		}
2112
-
2113
-		$page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect));
2114
-
2115
-		$p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
2116
-
2117
-		$p->interdire_scripts = false; // securite assuree par le squelette
2118
-	}
2119
-
2120
-	return $p;
2058
+    $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
2059
+
2060
+    // erreur de syntaxe = fond absent
2061
+    // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
2062
+    if (!$_contexte) {
2063
+        $_contexte = [];
2064
+    }
2065
+
2066
+    if (!isset($_contexte[1])) {
2067
+        $msg = ['zbug_balise_sans_argument', ['balise' => ' MODELE']];
2068
+        erreur_squelette($msg, $p);
2069
+    } else {
2070
+        $nom = $_contexte[1];
2071
+        unset($_contexte[1]);
2072
+
2073
+        if (preg_match("/^\s*'[^']*'/s", $nom)) {
2074
+            $nom = "'modeles/" . substr($nom, 1);
2075
+        } else {
2076
+            $nom = "'modeles/' . $nom";
2077
+        }
2078
+
2079
+        $flag_env = false;
2080
+        if (isset($_contexte['env'])) {
2081
+            $flag_env = true;
2082
+            unset($_contexte['env']);
2083
+        }
2084
+
2085
+        // Incoherence dans la syntaxe du contexte. A revoir.
2086
+        // Reserver la cle primaire de la boucle courante si elle existe
2087
+        if (isset($p->boucles[$p->id_boucle]->primary)) {
2088
+            $primary = $p->boucles[$p->id_boucle]->primary;
2089
+            if (!strpos($primary, ',')) {
2090
+                $id = champ_sql($primary, $p);
2091
+                $_contexte[] = "'$primary'=>" . $id;
2092
+                $_contexte[] = "'id'=>" . $id;
2093
+            }
2094
+        }
2095
+        $_contexte[] = "'recurs'=>(++\$recurs)";
2096
+        $connect = '';
2097
+        if (isset($p->boucles[$p->id_boucle])) {
2098
+            $connect = $p->boucles[$p->id_boucle]->sql_serveur;
2099
+        }
2100
+
2101
+        $_options = memoriser_contexte_compil($p);
2102
+        $_options = "'compil'=>array($_options), 'trim'=>true";
2103
+        if (isset($_contexte['ajax'])) {
2104
+            $_options .= ', ' . preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2105
+            unset($_contexte['ajax']);
2106
+        }
2107
+
2108
+        $_l = 'array(' . join(",\n\t", $_contexte) . ')';
2109
+        if ($flag_env) {
2110
+            $_l = "array_merge(\$Pile[0],$_l)";
2111
+        }
2112
+
2113
+        $page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect));
2114
+
2115
+        $p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
2116
+
2117
+        $p->interdire_scripts = false; // securite assuree par le squelette
2118
+    }
2119
+
2120
+    return $p;
2121 2121
 }
2122 2122
 
2123 2123
 
@@ -2141,21 +2141,21 @@  discard block
 block discarded – undo
2141 2141
  *     Pile complétée par le code à générer
2142 2142
  **/
2143 2143
 function balise_SET_dist($p) {
2144
-	$_nom = interprete_argument_balise(1, $p);
2145
-	$_val = interprete_argument_balise(2, $p);
2144
+    $_nom = interprete_argument_balise(1, $p);
2145
+    $_val = interprete_argument_balise(2, $p);
2146 2146
 
2147
-	if (!$_nom or !$_val) {
2148
-		$err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'SET']];
2149
-		erreur_squelette($err_b_s_a, $p);
2150
-	}
2151
-	// affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4
2152
-	// cf https://bugs.php.net/bug.php?id=65845
2153
-	else {
2154
-		$p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)";
2155
-	}
2147
+    if (!$_nom or !$_val) {
2148
+        $err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'SET']];
2149
+        erreur_squelette($err_b_s_a, $p);
2150
+    }
2151
+    // affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4
2152
+    // cf https://bugs.php.net/bug.php?id=65845
2153
+    else {
2154
+        $p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)";
2155
+    }
2156 2156
 
2157
-	$p->interdire_scripts = false; // la balise ne renvoie rien
2158
-	return $p;
2157
+    $p->interdire_scripts = false; // la balise ne renvoie rien
2158
+    return $p;
2159 2159
 }
2160 2160
 
2161 2161
 
@@ -2185,12 +2185,12 @@  discard block
 block discarded – undo
2185 2185
  *     Pile complétée par le code à générer
2186 2186
  **/
2187 2187
 function balise_GET_dist($p) {
2188
-	$p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
2189
-	if (function_exists('balise_ENV')) {
2190
-		return balise_ENV($p, '$Pile["vars"]??[]');
2191
-	} else {
2192
-		return balise_ENV_dist($p, '$Pile["vars"]??[]');
2193
-	}
2188
+    $p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
2189
+    if (function_exists('balise_ENV')) {
2190
+        return balise_ENV($p, '$Pile["vars"]??[]');
2191
+    } else {
2192
+        return balise_ENV_dist($p, '$Pile["vars"]??[]');
2193
+    }
2194 2194
 }
2195 2195
 
2196 2196
 
@@ -2213,22 +2213,22 @@  discard block
 block discarded – undo
2213 2213
  *     Pile complétée par le code à générer
2214 2214
  **/
2215 2215
 function balise_DOUBLONS_dist($p) {
2216
-	if ($type = interprete_argument_balise(1, $p)) {
2217
-		if ($famille = interprete_argument_balise(2, $p)) {
2218
-			$type .= '.' . $famille;
2219
-		}
2220
-		$p->code = '(isset($doublons[' . $type . ']) ? $doublons[' . $type . '] : "")';
2221
-		if (!$p->etoile) {
2222
-			$p->code = 'array_filter(array_map("intval",explode(",",'
2223
-				. $p->code . ')))';
2224
-		}
2225
-	} else {
2226
-		$p->code = '$doublons';
2227
-	}
2216
+    if ($type = interprete_argument_balise(1, $p)) {
2217
+        if ($famille = interprete_argument_balise(2, $p)) {
2218
+            $type .= '.' . $famille;
2219
+        }
2220
+        $p->code = '(isset($doublons[' . $type . ']) ? $doublons[' . $type . '] : "")';
2221
+        if (!$p->etoile) {
2222
+            $p->code = 'array_filter(array_map("intval",explode(",",'
2223
+                . $p->code . ')))';
2224
+        }
2225
+    } else {
2226
+        $p->code = '$doublons';
2227
+    }
2228 2228
 
2229
-	$p->interdire_scripts = false;
2229
+    $p->interdire_scripts = false;
2230 2230
 
2231
-	return $p;
2231
+    return $p;
2232 2232
 }
2233 2233
 
2234 2234
 
@@ -2251,18 +2251,18 @@  discard block
 block discarded – undo
2251 2251
  *     Pile complétée par le code à générer
2252 2252
  **/
2253 2253
 function balise_PIPELINE_dist($p) {
2254
-	$_pipe = interprete_argument_balise(1, $p);
2255
-	if (!$_pipe) {
2256
-		$err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'PIPELINE']];
2257
-		erreur_squelette($err_b_s_a, $p);
2258
-	} else {
2259
-		$_flux = interprete_argument_balise(2, $p);
2260
-		$_flux = $_flux ?: "''";
2261
-		$p->code = "pipeline( $_pipe , $_flux )";
2262
-		$p->interdire_scripts = false;
2263
-	}
2254
+    $_pipe = interprete_argument_balise(1, $p);
2255
+    if (!$_pipe) {
2256
+        $err_b_s_a = ['zbug_balise_sans_argument', ['balise' => 'PIPELINE']];
2257
+        erreur_squelette($err_b_s_a, $p);
2258
+    } else {
2259
+        $_flux = interprete_argument_balise(2, $p);
2260
+        $_flux = $_flux ?: "''";
2261
+        $p->code = "pipeline( $_pipe , $_flux )";
2262
+        $p->interdire_scripts = false;
2263
+    }
2264 2264
 
2265
-	return $p;
2265
+    return $p;
2266 2266
 }
2267 2267
 
2268 2268
 
@@ -2287,10 +2287,10 @@  discard block
 block discarded – undo
2287 2287
  *     Pile complétée par le code à générer
2288 2288
  **/
2289 2289
 function balise_EDIT_dist($p) {
2290
-	$p->code = "''";
2291
-	$p->interdire_scripts = false;
2290
+    $p->code = "''";
2291
+    $p->interdire_scripts = false;
2292 2292
 
2293
-	return $p;
2293
+    return $p;
2294 2294
 }
2295 2295
 
2296 2296
 
@@ -2313,11 +2313,11 @@  discard block
 block discarded – undo
2313 2313
  *     Pile complétée par le code à générer
2314 2314
  **/
2315 2315
 function balise_TOTAL_UNIQUE_dist($p) {
2316
-	$_famille = interprete_argument_balise(1, $p);
2317
-	$_famille = $_famille ?: "''";
2318
-	$p->code = "unique('', $_famille, true)";
2316
+    $_famille = interprete_argument_balise(1, $p);
2317
+    $_famille = $_famille ?: "''";
2318
+    $p->code = "unique('', $_famille, true)";
2319 2319
 
2320
-	return $p;
2320
+    return $p;
2321 2321
 }
2322 2322
 
2323 2323
 /**
@@ -2340,19 +2340,19 @@  discard block
 block discarded – undo
2340 2340
  *     Pile complétée par le code à générer
2341 2341
  **/
2342 2342
 function balise_ARRAY_dist($p) {
2343
-	$_code = [];
2344
-	$n = 1;
2345
-	do {
2346
-		$_key = interprete_argument_balise($n++, $p);
2347
-		$_val = interprete_argument_balise($n++, $p);
2348
-		if ($_key and $_val) {
2349
-			$_code[] = "$_key => $_val";
2350
-		}
2351
-	} while ($_key && $_val);
2352
-	$p->code = 'array(' . join(', ', $_code) . ')';
2353
-	$p->interdire_scripts = false;
2343
+    $_code = [];
2344
+    $n = 1;
2345
+    do {
2346
+        $_key = interprete_argument_balise($n++, $p);
2347
+        $_val = interprete_argument_balise($n++, $p);
2348
+        if ($_key and $_val) {
2349
+            $_code[] = "$_key => $_val";
2350
+        }
2351
+    } while ($_key && $_val);
2352
+    $p->code = 'array(' . join(', ', $_code) . ')';
2353
+    $p->interdire_scripts = false;
2354 2354
 
2355
-	return $p;
2355
+    return $p;
2356 2356
 }
2357 2357
 
2358 2358
 /**
@@ -2371,15 +2371,15 @@  discard block
 block discarded – undo
2371 2371
  *     Pile complétée par le code à générer
2372 2372
  */
2373 2373
 function balise_LISTE_dist($p) {
2374
-	$_code = [];
2375
-	$n = 1;
2376
-	while ($_val = interprete_argument_balise($n++, $p)) {
2377
-		$_code[] = $_val;
2378
-	}
2379
-	$p->code = 'array(' . join(', ', $_code) . ')';
2380
-	$p->interdire_scripts = false;
2374
+    $_code = [];
2375
+    $n = 1;
2376
+    while ($_val = interprete_argument_balise($n++, $p)) {
2377
+        $_code[] = $_val;
2378
+    }
2379
+    $p->code = 'array(' . join(', ', $_code) . ')';
2380
+    $p->interdire_scripts = false;
2381 2381
 
2382
-	return $p;
2382
+    return $p;
2383 2383
 }
2384 2384
 
2385 2385
 
@@ -2413,21 +2413,21 @@  discard block
 block discarded – undo
2413 2413
  *     Pile complétée par le code à générer
2414 2414
  **/
2415 2415
 function balise_AUTORISER_dist($p) {
2416
-	$_code = [];
2417
-	$p->descr['session'] = true; // faire un cache par session
2416
+    $_code = [];
2417
+    $p->descr['session'] = true; // faire un cache par session
2418 2418
 
2419
-	$n = 1;
2420
-	while ($_v = interprete_argument_balise($n++, $p)) {
2421
-		$_code[] = $_v;
2422
-	}
2419
+    $n = 1;
2420
+    while ($_v = interprete_argument_balise($n++, $p)) {
2421
+        $_code[] = $_v;
2422
+    }
2423 2423
 
2424
-	$p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(
2425
-		', ',
2426
-		$_code
2427
-	) . ')?" ":"")';
2428
-	$p->interdire_scripts = false;
2424
+    $p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(
2425
+        ', ',
2426
+        $_code
2427
+    ) . ')?" ":"")';
2428
+    $p->interdire_scripts = false;
2429 2429
 
2430
-	return $p;
2430
+    return $p;
2431 2431
 }
2432 2432
 
2433 2433
 
@@ -2451,15 +2451,15 @@  discard block
 block discarded – undo
2451 2451
  *     Pile complétée par le code à générer
2452 2452
  **/
2453 2453
 function balise_PLUGIN_dist($p) {
2454
-	$plugin = interprete_argument_balise(1, $p);
2455
-	$plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
2456
-	$type_info = interprete_argument_balise(2, $p);
2457
-	$type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
2454
+    $plugin = interprete_argument_balise(1, $p);
2455
+    $plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
2456
+    $type_info = interprete_argument_balise(2, $p);
2457
+    $type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
2458 2458
 
2459
-	$f = chercher_filtre('info_plugin');
2460
-	$p->code = $f . '(' . $plugin . ', ' . $type_info . ')';
2459
+    $f = chercher_filtre('info_plugin');
2460
+    $p->code = $f . '(' . $plugin . ', ' . $type_info . ')';
2461 2461
 
2462
-	return $p;
2462
+    return $p;
2463 2463
 }
2464 2464
 
2465 2465
 /**
@@ -2480,9 +2480,9 @@  discard block
 block discarded – undo
2480 2480
  *     Pile complétée par le code à générer
2481 2481
  **/
2482 2482
 function balise_AIDER_dist($p) {
2483
-	$_motif = interprete_argument_balise(1, $p);
2484
-	$p->code = "((\$aider=charger_fonction('aide','inc',true))?\$aider($_motif):'')";
2485
-	return $p;
2483
+    $_motif = interprete_argument_balise(1, $p);
2484
+    $p->code = "((\$aider=charger_fonction('aide','inc',true))?\$aider($_motif):'')";
2485
+    return $p;
2486 2486
 }
2487 2487
 
2488 2488
 /**
@@ -2508,16 +2508,16 @@  discard block
 block discarded – undo
2508 2508
  *     Pile complétée par le code à générer
2509 2509
  **/
2510 2510
 function balise_ACTION_FORMULAIRE($p) {
2511
-	if (!$_url = interprete_argument_balise(1, $p)) {
2512
-		$_url = "(\$Pile[0]['action'] ?? '')";
2513
-	}
2514
-	if (!$_form = interprete_argument_balise(2, $p)) {
2515
-		$_form = "(\$Pile[0]['form'] ?? '')";
2516
-	}
2517
-
2518
-	// envoyer le nom du formulaire que l'on traite
2519
-	// transmettre les eventuels args de la balise formulaire
2520
-	$p->code = "	'<span class=\"form-hidden\">' .
2511
+    if (!$_url = interprete_argument_balise(1, $p)) {
2512
+        $_url = "(\$Pile[0]['action'] ?? '')";
2513
+    }
2514
+    if (!$_form = interprete_argument_balise(2, $p)) {
2515
+        $_form = "(\$Pile[0]['form'] ?? '')";
2516
+    }
2517
+
2518
+    // envoyer le nom du formulaire que l'on traite
2519
+    // transmettre les eventuels args de la balise formulaire
2520
+    $p->code = "	'<span class=\"form-hidden\">' .
2521 2521
 	form_hidden($_url) .
2522 2522
 	'<input name=\'formulaire_action\' type=\'hidden\'
2523 2523
 		value=\'' . $_form . '\' />' .
@@ -2528,9 +2528,9 @@  discard block
 block discarded – undo
2528 2528
 	(\$Pile[0]['_hidden'] ?? '') .
2529 2529
 	'</span>'";
2530 2530
 
2531
-	$p->interdire_scripts = false;
2531
+    $p->interdire_scripts = false;
2532 2532
 
2533
-	return $p;
2533
+    return $p;
2534 2534
 }
2535 2535
 
2536 2536
 
@@ -2571,25 +2571,25 @@  discard block
 block discarded – undo
2571 2571
  */
2572 2572
 function balise_BOUTON_ACTION_dist($p) {
2573 2573
 
2574
-	$args = [];
2575
-	for ($k = 1; $k <= 6; $k++) {
2576
-		$_a = interprete_argument_balise($k, $p);
2577
-		if (!$_a) {
2578
-			$_a = "''";
2579
-		}
2580
-		$args[] = $_a;
2581
-	}
2582
-	// supprimer les args vides
2583
-	while (end($args) == "''" and count($args) > 2) {
2584
-		array_pop($args);
2585
-	}
2586
-	$args = implode(',', $args);
2574
+    $args = [];
2575
+    for ($k = 1; $k <= 6; $k++) {
2576
+        $_a = interprete_argument_balise($k, $p);
2577
+        if (!$_a) {
2578
+            $_a = "''";
2579
+        }
2580
+        $args[] = $_a;
2581
+    }
2582
+    // supprimer les args vides
2583
+    while (end($args) == "''" and count($args) > 2) {
2584
+        array_pop($args);
2585
+    }
2586
+    $args = implode(',', $args);
2587 2587
 
2588
-	$bouton_action = chercher_filtre('bouton_action');
2589
-	$p->code = "$bouton_action($args)";
2590
-	$p->interdire_scripts = false;
2588
+    $bouton_action = chercher_filtre('bouton_action');
2589
+    $p->code = "$bouton_action($args)";
2590
+    $p->interdire_scripts = false;
2591 2591
 
2592
-	return $p;
2592
+    return $p;
2593 2593
 }
2594 2594
 
2595 2595
 
@@ -2608,10 +2608,10 @@  discard block
 block discarded – undo
2608 2608
  *     Pile complétée par le code à générer
2609 2609
  */
2610 2610
 function balise_SLOGAN_SITE_SPIP_dist($p) {
2611
-	$p->code = "\$GLOBALS['meta']['slogan_site']";
2611
+    $p->code = "\$GLOBALS['meta']['slogan_site']";
2612 2612
 
2613
-	#$p->interdire_scripts = true;
2614
-	return $p;
2613
+    #$p->interdire_scripts = true;
2614
+    return $p;
2615 2615
 }
2616 2616
 
2617 2617
 
@@ -2635,10 +2635,10 @@  discard block
 block discarded – undo
2635 2635
  *     Pile complétée par le code à générer
2636 2636
  */
2637 2637
 function balise_HTML5_dist($p) {
2638
-	$p->code = html5_permis() ? "' '" : "''";
2639
-	$p->interdire_scripts = false;
2638
+    $p->code = html5_permis() ? "' '" : "''";
2639
+    $p->interdire_scripts = false;
2640 2640
 
2641
-	return $p;
2641
+    return $p;
2642 2642
 }
2643 2643
 
2644 2644
 
@@ -2664,58 +2664,58 @@  discard block
 block discarded – undo
2664 2664
  *     Pile complétée par le code à générer
2665 2665
  */
2666 2666
 function balise_TRI_dist($p, $liste = 'true') {
2667
-	$b = index_boucle_mere($p);
2668
-	// s'il n'y a pas de nom de boucle, on ne peut pas trier
2669
-	if ($b === '') {
2670
-		$msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
2671
-		erreur_squelette($msg, $p);
2672
-		$p->code = "''";
2667
+    $b = index_boucle_mere($p);
2668
+    // s'il n'y a pas de nom de boucle, on ne peut pas trier
2669
+    if ($b === '') {
2670
+        $msg = ['zbug_champ_hors_boucle', ['champ' => zbug_presenter_champ($p)]];
2671
+        erreur_squelette($msg, $p);
2672
+        $p->code = "''";
2673 2673
 
2674
-		return $p;
2675
-	}
2676
-	$boucle = $p->boucles[$b];
2674
+        return $p;
2675
+    }
2676
+    $boucle = $p->boucles[$b];
2677 2677
 
2678
-	// s'il n'y a pas de tri_champ, c'est qu'on se trouve
2679
-	// dans un boucle recursive ou qu'on a oublie le critere {tri}
2680
-	if (!isset($boucle->modificateur['tri_champ'])) {
2681
-		$msg = ['zbug_champ_hors_critere', [
2682
-			'champ' => zbug_presenter_champ($p),
2683
-			'critere' => 'tri'
2684
-		]];
2685
-		erreur_squelette($msg, $p);
2686
-		$p->code = "''";
2678
+    // s'il n'y a pas de tri_champ, c'est qu'on se trouve
2679
+    // dans un boucle recursive ou qu'on a oublie le critere {tri}
2680
+    if (!isset($boucle->modificateur['tri_champ'])) {
2681
+        $msg = ['zbug_champ_hors_critere', [
2682
+            'champ' => zbug_presenter_champ($p),
2683
+            'critere' => 'tri'
2684
+        ]];
2685
+        erreur_squelette($msg, $p);
2686
+        $p->code = "''";
2687 2687
 
2688
-		return $p;
2689
-	}
2688
+        return $p;
2689
+    }
2690 2690
 
2691
-	// Différentes infos relatives au tri présentes dans les modificateurs
2692
-	$_tri_nom = $boucle->modificateur['tri_nom'] ; // nom du paramètre définissant le tri
2693
-	$_tri_champ = $boucle->modificateur['tri_champ']; // champ actuel utilisé le tri
2694
-	$_tri_sens = $boucle->modificateur['tri_sens']; // sens de tri actuel
2695
-	$_tri_liste_sens_defaut = $boucle->modificateur['tri_liste_sens_defaut']; // sens par défaut pour chaque champ
2691
+    // Différentes infos relatives au tri présentes dans les modificateurs
2692
+    $_tri_nom = $boucle->modificateur['tri_nom'] ; // nom du paramètre définissant le tri
2693
+    $_tri_champ = $boucle->modificateur['tri_champ']; // champ actuel utilisé le tri
2694
+    $_tri_sens = $boucle->modificateur['tri_sens']; // sens de tri actuel
2695
+    $_tri_liste_sens_defaut = $boucle->modificateur['tri_liste_sens_defaut']; // sens par défaut pour chaque champ
2696 2696
 
2697
-	$_champ_ou_sens = interprete_argument_balise(1, $p);
2698
-	// si pas de champ, renvoyer le critère de tri actuel
2699
-	if (!$_champ_ou_sens) {
2700
-		$p->code = $_tri_champ;
2697
+    $_champ_ou_sens = interprete_argument_balise(1, $p);
2698
+    // si pas de champ, renvoyer le critère de tri actuel
2699
+    if (!$_champ_ou_sens) {
2700
+        $p->code = $_tri_champ;
2701 2701
 
2702
-		return $p;
2703
-	}
2704
-	// forcer la jointure si besoin, et si le champ est statique
2705
-	if (preg_match(",^'([\w.]+)'$,i", $_champ_ou_sens, $m)) {
2706
-		index_pile($b, $m[1], $p->boucles, '', null, true, false);
2707
-	}
2702
+        return $p;
2703
+    }
2704
+    // forcer la jointure si besoin, et si le champ est statique
2705
+    if (preg_match(",^'([\w.]+)'$,i", $_champ_ou_sens, $m)) {
2706
+        index_pile($b, $m[1], $p->boucles, '', null, true, false);
2707
+    }
2708 2708
 
2709
-	$_libelle = interprete_argument_balise(2, $p);
2710
-	$_libelle = $_libelle ?: $_champ_ou_sens;
2709
+    $_libelle = interprete_argument_balise(2, $p);
2710
+    $_libelle = $_libelle ?: $_champ_ou_sens;
2711 2711
 
2712
-	$_class = interprete_argument_balise(3, $p) ?? "''";
2712
+    $_class = interprete_argument_balise(3, $p) ?? "''";
2713 2713
 
2714
-	$p->code = "calculer_balise_tri($_champ_ou_sens, $_libelle, $_class, $_tri_nom, $_tri_champ, $_tri_sens, $_tri_liste_sens_defaut)";
2714
+    $p->code = "calculer_balise_tri($_champ_ou_sens, $_libelle, $_class, $_tri_nom, $_tri_champ, $_tri_sens, $_tri_liste_sens_defaut)";
2715 2715
 
2716
-	$p->interdire_scripts = false;
2716
+    $p->interdire_scripts = false;
2717 2717
 
2718
-	return $p;
2718
+    return $p;
2719 2719
 }
2720 2720
 
2721 2721
 
@@ -2736,21 +2736,21 @@  discard block
 block discarded – undo
2736 2736
  *     Pile complétée par le code à générer
2737 2737
  */
2738 2738
 function balise_SAUTER_dist($p) {
2739
-	$id_boucle = $p->id_boucle;
2739
+    $id_boucle = $p->id_boucle;
2740 2740
 
2741
-	if (empty($p->boucles[$id_boucle])) {
2742
-		$msg = ['zbug_champ_hors_boucle', ['champ' => '#SAUTER']];
2743
-		erreur_squelette($msg, $p);
2744
-	} else {
2745
-		$_saut = interprete_argument_balise(1, $p);
2746
-		$_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
2747
-		$_total = "(\$Numrows['$id_boucle']['total'] ?? null)";
2741
+    if (empty($p->boucles[$id_boucle])) {
2742
+        $msg = ['zbug_champ_hors_boucle', ['champ' => '#SAUTER']];
2743
+        erreur_squelette($msg, $p);
2744
+    } else {
2745
+        $_saut = interprete_argument_balise(1, $p);
2746
+        $_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
2747
+        $_total = "(\$Numrows['$id_boucle']['total'] ?? null)";
2748 2748
 
2749
-		$p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
2750
-	}
2751
-	$p->interdire_scripts = false;
2749
+        $p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
2750
+    }
2751
+    $p->interdire_scripts = false;
2752 2752
 
2753
-	return $p;
2753
+    return $p;
2754 2754
 }
2755 2755
 
2756 2756
 
@@ -2772,22 +2772,22 @@  discard block
 block discarded – undo
2772 2772
  *     Pile complétée par le code à générer
2773 2773
  */
2774 2774
 function balise_PUBLIE_dist($p) {
2775
-	if (!$_type = interprete_argument_balise(1, $p)) {
2776
-		$_type = _q($p->type_requete);
2777
-		$_id = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
2778
-	} else {
2779
-		$_id = interprete_argument_balise(2, $p);
2780
-	}
2775
+    if (!$_type = interprete_argument_balise(1, $p)) {
2776
+        $_type = _q($p->type_requete);
2777
+        $_id = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
2778
+    } else {
2779
+        $_id = interprete_argument_balise(2, $p);
2780
+    }
2781 2781
 
2782
-	$connect = '';
2783
-	if (isset($p->boucles[$p->id_boucle])) {
2784
-		$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2785
-	}
2782
+    $connect = '';
2783
+    if (isset($p->boucles[$p->id_boucle])) {
2784
+        $connect = $p->boucles[$p->id_boucle]->sql_serveur;
2785
+    }
2786 2786
 
2787
-	$p->code = '(objet_test_si_publie(' . $_type . ',intval(' . $_id . '),' . _q($connect) . ")?' ':'')";
2788
-	$p->interdire_scripts = false;
2787
+    $p->code = '(objet_test_si_publie(' . $_type . ',intval(' . $_id . '),' . _q($connect) . ")?' ':'')";
2788
+    $p->interdire_scripts = false;
2789 2789
 
2790
-	return $p;
2790
+    return $p;
2791 2791
 }
2792 2792
 
2793 2793
 /**
@@ -2816,12 +2816,12 @@  discard block
 block discarded – undo
2816 2816
  *     Pile complétée par le code à générer
2817 2817
  */
2818 2818
 function balise_PRODUIRE_dist($p) {
2819
-	$balise_inclure = charger_fonction('INCLURE', 'balise');
2820
-	$p = $balise_inclure($p);
2819
+    $balise_inclure = charger_fonction('INCLURE', 'balise');
2820
+    $p = $balise_inclure($p);
2821 2821
 
2822
-	$p->code = str_replace('recuperer_fond(', 'produire_fond_statique(', $p->code);
2822
+    $p->code = str_replace('recuperer_fond(', 'produire_fond_statique(', $p->code);
2823 2823
 
2824
-	return $p;
2824
+    return $p;
2825 2825
 }
2826 2826
 
2827 2827
 /**
@@ -2840,13 +2840,13 @@  discard block
 block discarded – undo
2840 2840
  *     Pile complétée par le code à générer
2841 2841
  */
2842 2842
 function balise_LARGEUR_ECRAN_dist($p) {
2843
-	$_class = interprete_argument_balise(1, $p);
2844
-	if (!$_class) {
2845
-		$_class = 'null';
2846
-	}
2847
-	$p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))";
2843
+    $_class = interprete_argument_balise(1, $p);
2844
+    if (!$_class) {
2845
+        $_class = 'null';
2846
+    }
2847
+    $p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))";
2848 2848
 
2849
-	return $p;
2849
+    return $p;
2850 2850
 }
2851 2851
 
2852 2852
 
@@ -2862,14 +2862,14 @@  discard block
 block discarded – undo
2862 2862
  *     Pile complétée par le code à générer
2863 2863
  **/
2864 2864
 function balise_CONST_dist($p) {
2865
-	$_const = interprete_argument_balise(1, $p);
2866
-	if (!strlen($_const ?? '')) {
2867
-		$p->code = "''";
2868
-	}
2869
-	else {
2870
-		$p->code = "(defined($_const)?constant($_const):'')";
2871
-	}
2872
-	$p->interdire_scripts = false;
2873
-
2874
-	return $p;
2865
+    $_const = interprete_argument_balise(1, $p);
2866
+    if (!strlen($_const ?? '')) {
2867
+        $p->code = "''";
2868
+    }
2869
+    else {
2870
+        $p->code = "(defined($_const)?constant($_const):'')";
2871
+    }
2872
+    $p->interdire_scripts = false;
2873
+
2874
+    return $p;
2875 2875
 }
Please login to merge, or discard this patch.
ecrire/public/compiler.php 1 patch
Indentation   +1209 added lines, -1209 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
 /** Repérer un code ne calculant rien, meme avec commentaire */
@@ -58,92 +58,92 @@  discard block
 block discarded – undo
58 58
 
59 59
 
60 60
 function argumenter_inclure(
61
-	$params,
62
-	$rejet_filtres,
63
-	$p,
64
-	&$boucles,
65
-	$id_boucle,
66
-	$echap = true,
67
-	$lang = '',
68
-	$fond1 = false
61
+    $params,
62
+    $rejet_filtres,
63
+    $p,
64
+    &$boucles,
65
+    $id_boucle,
66
+    $echap = true,
67
+    $lang = '',
68
+    $fond1 = false
69 69
 ) {
70
-	$l = [];
71
-	$erreur_p_i_i = '';
72
-	if (!is_array($params)) {
73
-		return $l;
74
-	}
75
-	foreach ($params as $k => $couple) {
76
-		// la liste d'arguments d'inclusion peut se terminer par un filtre
77
-		$filtre = array_shift($couple);
78
-		if ($filtre) {
79
-			break;
80
-		}
81
-		foreach ($couple as $n => $val) {
82
-			$var = $val[0];
83
-			if ($var->type != 'texte') {
84
-				if ($n or $k or $fond1) {
85
-					$erreur_p_i_i = [
86
-						'zbug_parametres_inclus_incorrects',
87
-						['param' => $var->nom_champ]
88
-					];
89
-					erreur_squelette($erreur_p_i_i, $p);
90
-					break;
91
-				} else {
92
-					$l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
93
-				}
94
-			} else {
95
-				preg_match(',^([^=]*)(=?)(.*)$,m', $var->texte, $m);
96
-				$m = array_pad($m, 3, null);
97
-				$var = $m[1];
98
-				$auto = false;
70
+    $l = [];
71
+    $erreur_p_i_i = '';
72
+    if (!is_array($params)) {
73
+        return $l;
74
+    }
75
+    foreach ($params as $k => $couple) {
76
+        // la liste d'arguments d'inclusion peut se terminer par un filtre
77
+        $filtre = array_shift($couple);
78
+        if ($filtre) {
79
+            break;
80
+        }
81
+        foreach ($couple as $n => $val) {
82
+            $var = $val[0];
83
+            if ($var->type != 'texte') {
84
+                if ($n or $k or $fond1) {
85
+                    $erreur_p_i_i = [
86
+                        'zbug_parametres_inclus_incorrects',
87
+                        ['param' => $var->nom_champ]
88
+                    ];
89
+                    erreur_squelette($erreur_p_i_i, $p);
90
+                    break;
91
+                } else {
92
+                    $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
93
+                }
94
+            } else {
95
+                preg_match(',^([^=]*)(=?)(.*)$,m', $var->texte, $m);
96
+                $m = array_pad($m, 3, null);
97
+                $var = $m[1];
98
+                $auto = false;
99 99
 ;
100
-				if ($m[2]) {
101
-					$v = $m[3];
102
-					if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
103
-						$v = $m[1];
104
-					}
105
-					$val[0] = new Texte();
106
-					$val[0]->texte = $v;
107
-				} elseif ($k or $n or $fond1) {
108
-					$auto = true;
109
-				} else {
110
-					$var = 1;
111
-				}
112
-
113
-				if ($var == 'lang') {
114
-					$lang = !$auto
115
-						? calculer_liste($val, $p->descr, $boucles, $id_boucle)
116
-						: '$GLOBALS["spip_lang"]';
117
-				} else {
118
-					$val = $auto
119
-						? index_pile($id_boucle, $var, $boucles)
120
-						: calculer_liste($val, $p->descr, $boucles, $id_boucle);
121
-					if ($var !== 1) {
122
-						$val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
123
-							. $val . ($echap ? ") . '" : ' ');
124
-					} else {
125
-						$val = $echap ? "'.$val.'" : $val;
126
-					}
127
-					$l[$var] = $val;
128
-				}
129
-			}
130
-		}
131
-	}
132
-	if ($erreur_p_i_i) {
133
-		return false;
134
-	}
135
-	// Cas particulier de la langue : si {lang=xx} est definie, on
136
-	// la passe, sinon on passe la langue courante au moment du calcul
137
-	// sauf si on n'en veut pas
138
-	if ($lang === false) {
139
-		return $l;
140
-	}
141
-	if (!$lang) {
142
-		$lang = '$GLOBALS["spip_lang"]';
143
-	}
144
-	$l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : ' ');
145
-
146
-	return $l;
100
+                if ($m[2]) {
101
+                    $v = $m[3];
102
+                    if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) {
103
+                        $v = $m[1];
104
+                    }
105
+                    $val[0] = new Texte();
106
+                    $val[0]->texte = $v;
107
+                } elseif ($k or $n or $fond1) {
108
+                    $auto = true;
109
+                } else {
110
+                    $var = 1;
111
+                }
112
+
113
+                if ($var == 'lang') {
114
+                    $lang = !$auto
115
+                        ? calculer_liste($val, $p->descr, $boucles, $id_boucle)
116
+                        : '$GLOBALS["spip_lang"]';
117
+                } else {
118
+                    $val = $auto
119
+                        ? index_pile($id_boucle, $var, $boucles)
120
+                        : calculer_liste($val, $p->descr, $boucles, $id_boucle);
121
+                    if ($var !== 1) {
122
+                        $val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ")
123
+                            . $val . ($echap ? ") . '" : ' ');
124
+                    } else {
125
+                        $val = $echap ? "'.$val.'" : $val;
126
+                    }
127
+                    $l[$var] = $val;
128
+                }
129
+            }
130
+        }
131
+    }
132
+    if ($erreur_p_i_i) {
133
+        return false;
134
+    }
135
+    // Cas particulier de la langue : si {lang=xx} est definie, on
136
+    // la passe, sinon on passe la langue courante au moment du calcul
137
+    // sauf si on n'en veut pas
138
+    if ($lang === false) {
139
+        return $l;
140
+    }
141
+    if (!$lang) {
142
+        $lang = '$GLOBALS["spip_lang"]';
143
+    }
144
+    $l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : ' ');
145
+
146
+    return $l;
147 147
 }
148 148
 
149 149
 /**
@@ -167,84 +167,84 @@  discard block
 block discarded – undo
167 167
  **/
168 168
 function calculer_inclure($p, &$boucles, $id_boucle) {
169 169
 
170
-	$_options = [];
171
-	$_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
172
-	if (is_string($p->texte)) {
173
-		$fichier = $p->texte;
174
-		$code = '"' . str_replace('"', '\"', $fichier) . '"';
175
-	} else {
176
-		$code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
177
-		if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
178
-			$fichier = $r[1];
179
-		} else {
180
-			$fichier = '';
181
-		}
182
-	}
183
-	if (!$code or $code === '""' or $code === "''") {
184
-		$trace = $p->fonctions;
185
-		while (
186
-			is_array($trace)
187
-			and $trace = array_filter($trace)
188
-			and count($trace) == 1
189
-		) {
190
-			$trace = reset($trace);
191
-		}
192
-		$erreur_p_i_i = [
193
-			'zbug_parametres_inclus_incorrects',
194
-			['param' => print_r($trace, true)]
195
-		];
196
-		erreur_squelette($erreur_p_i_i, $p);
197
-
198
-		return "''";
199
-	}
200
-	$compil = texte_script(memoriser_contexte_compil($p));
201
-
202
-	if (is_array($_contexte)) {
203
-		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
204
-		if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
205
-			unset($_contexte['env']);
206
-		}
207
-
208
-		// noter les doublons dans l'appel a public.php
209
-		if (isset($_contexte['doublons'])) {
210
-			$_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
211
-		}
212
-
213
-		if ($ajax = isset($_contexte['ajax'])) {
214
-			$ajax = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
215
-			unset($_contexte['ajax']);
216
-		}
217
-
218
-		$_contexte = join(",\n\t", $_contexte);
219
-	} else {
220
-		return false;
221
-	} // j'aurais voulu toucher le fond ...
222
-
223
-	$contexte = 'array(' . $_contexte . ')';
224
-
225
-	if ($env) {
226
-		$contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
227
-	}
228
-
229
-	// s'il y a une extension .php, ce n'est pas un squelette
230
-	if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
231
-		$code = sandbox_composer_inclure_php($fichier, $p, $contexte);
232
-	} else {
233
-		$_options[] = "\"compil\"=>array($compil)";
234
-		if ($ajax) {
235
-			$_options[] = $ajax;
236
-		}
237
-		$code = " ' . argumenter_squelette($code) . '";
238
-		$code = 'echo ' . sprintf(
239
-			CODE_RECUPERER_FOND,
240
-			$code,
241
-			$contexte,
242
-			implode(',', $_options),
243
-			"_request(\\'connect\\') ?? \\'\\'"
244
-		) . ';';
245
-	}
246
-
247
-	return "\n'<'.'" . '?php ' . $code . "\n?'." . "'>'";
170
+    $_options = [];
171
+    $_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
172
+    if (is_string($p->texte)) {
173
+        $fichier = $p->texte;
174
+        $code = '"' . str_replace('"', '\"', $fichier) . '"';
175
+    } else {
176
+        $code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
177
+        if ($code and preg_match("/^'([^']*)'/s", $code, $r)) {
178
+            $fichier = $r[1];
179
+        } else {
180
+            $fichier = '';
181
+        }
182
+    }
183
+    if (!$code or $code === '""' or $code === "''") {
184
+        $trace = $p->fonctions;
185
+        while (
186
+            is_array($trace)
187
+            and $trace = array_filter($trace)
188
+            and count($trace) == 1
189
+        ) {
190
+            $trace = reset($trace);
191
+        }
192
+        $erreur_p_i_i = [
193
+            'zbug_parametres_inclus_incorrects',
194
+            ['param' => print_r($trace, true)]
195
+        ];
196
+        erreur_squelette($erreur_p_i_i, $p);
197
+
198
+        return "''";
199
+    }
200
+    $compil = texte_script(memoriser_contexte_compil($p));
201
+
202
+    if (is_array($_contexte)) {
203
+        // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
204
+        if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) {
205
+            unset($_contexte['env']);
206
+        }
207
+
208
+        // noter les doublons dans l'appel a public.php
209
+        if (isset($_contexte['doublons'])) {
210
+            $_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
211
+        }
212
+
213
+        if ($ajax = isset($_contexte['ajax'])) {
214
+            $ajax = preg_replace(',=>(.*)$,ims', '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
215
+            unset($_contexte['ajax']);
216
+        }
217
+
218
+        $_contexte = join(",\n\t", $_contexte);
219
+    } else {
220
+        return false;
221
+    } // j'aurais voulu toucher le fond ...
222
+
223
+    $contexte = 'array(' . $_contexte . ')';
224
+
225
+    if ($env) {
226
+        $contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
227
+    }
228
+
229
+    // s'il y a une extension .php, ce n'est pas un squelette
230
+    if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) {
231
+        $code = sandbox_composer_inclure_php($fichier, $p, $contexte);
232
+    } else {
233
+        $_options[] = "\"compil\"=>array($compil)";
234
+        if ($ajax) {
235
+            $_options[] = $ajax;
236
+        }
237
+        $code = " ' . argumenter_squelette($code) . '";
238
+        $code = 'echo ' . sprintf(
239
+            CODE_RECUPERER_FOND,
240
+            $code,
241
+            $contexte,
242
+            implode(',', $_options),
243
+            "_request(\\'connect\\') ?? \\'\\'"
244
+        ) . ';';
245
+    }
246
+
247
+    return "\n'<'.'" . '?php ' . $code . "\n?'." . "'>'";
248 248
 }
249 249
 
250 250
 
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
  *     true pour ne tester que le cas publie et ignorer l'eventuel var_mode=preview de la page
263 263
  */
264 264
 function instituer_boucle(&$boucle, $echapper = true, $ignore_previsu = false) {
265
-	/*
265
+    /*
266 266
 	$show['statut'][] = array(
267 267
 		'champ'=>'statut',  // champ de la table sur lequel porte le filtrage par le statut
268 268
 		'publie'=>'publie', // valeur ou liste de valeurs, qui definissent l'objet comme publie.
@@ -286,74 +286,74 @@  discard block
 block discarded – undo
286 286
 	champstatut est alors le champ statut sur la tablen
287 287
 	dans les jointures, clen peut etre un tableau pour une jointure complexe : array('id_objet','id_article','objet','article')
288 288
 */
289
-	$id_table = $boucle->id_table;
290
-	$show = $boucle->show;
291
-	if (isset($show['statut']) and $show['statut']) {
292
-		foreach ($show['statut'] as $k => $s) {
293
-			// Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
294
-			$filtrer = true;
295
-			if (isset($s['exception'])) {
296
-				foreach (is_array($s['exception']) ? $s['exception'] : [$s['exception']] as $m) {
297
-					if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
298
-						$filtrer = false;
299
-						break;
300
-					}
301
-				}
302
-			}
303
-
304
-			if ($filtrer) {
305
-				if (is_array($s['champ'])) {
306
-					$statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
307
-					$jointures = [];
308
-					// indiquer la description de chaque table dans le tableau de jointures,
309
-					// ce qui permet d'eviter certains GROUP BY inutiles.
310
-					$trouver_table = charger_fonction('trouver_table', 'base');
311
-					foreach ($s['champ'] as $j) {
312
-						$id = reset($j);
313
-						$def = $trouver_table($id);
314
-						$jointures[] = ['', [$id, $def], end($j)];
315
-					}
316
-					$jointures[0][0] = $id_table;
317
-					if (!array_search($id, $boucle->from)) {
318
-						include_spip('public/jointures');
319
-						fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
320
-					}
321
-					// trouver l'alias de la table d'arrivee qui porte le statut
322
-					$id = array_search($id, $boucle->from);
323
-				} else {
324
-					$id = $id_table;
325
-					$statut = preg_replace(',\W,', '', $s['champ']); // securite
326
-				}
327
-				$mstatut = $id . '.' . $statut;
328
-
329
-				$arg_ignore_previsu = ($ignore_previsu ? ',true' : '');
330
-				include_spip('public/quete');
331
-				if (
332
-					isset($s['post_date']) and $s['post_date']
333
-					and $GLOBALS['meta']['post_dates'] == 'non'
334
-				) {
335
-					$date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
336
-					array_unshift(
337
-						$boucle->where,
338
-						$echapper ?
339
-							"\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
340
-							:
341
-							quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
342
-					);
343
-				}
344
-				array_unshift(
345
-					$boucle->where,
346
-					$echapper ?
347
-						"\nquete_condition_statut('$mstatut',"
348
-						. _q($s['previsu']) . ','
349
-						. _q($s['publie']) . ','
350
-						. _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
351
-						:
352
-						quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
353
-				);
354
-			}
355
-		}
356
-	}
289
+    $id_table = $boucle->id_table;
290
+    $show = $boucle->show;
291
+    if (isset($show['statut']) and $show['statut']) {
292
+        foreach ($show['statut'] as $k => $s) {
293
+            // Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
294
+            $filtrer = true;
295
+            if (isset($s['exception'])) {
296
+                foreach (is_array($s['exception']) ? $s['exception'] : [$s['exception']] as $m) {
297
+                    if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) {
298
+                        $filtrer = false;
299
+                        break;
300
+                    }
301
+                }
302
+            }
303
+
304
+            if ($filtrer) {
305
+                if (is_array($s['champ'])) {
306
+                    $statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite
307
+                    $jointures = [];
308
+                    // indiquer la description de chaque table dans le tableau de jointures,
309
+                    // ce qui permet d'eviter certains GROUP BY inutiles.
310
+                    $trouver_table = charger_fonction('trouver_table', 'base');
311
+                    foreach ($s['champ'] as $j) {
312
+                        $id = reset($j);
313
+                        $def = $trouver_table($id);
314
+                        $jointures[] = ['', [$id, $def], end($j)];
315
+                    }
316
+                    $jointures[0][0] = $id_table;
317
+                    if (!array_search($id, $boucle->from)) {
318
+                        include_spip('public/jointures');
319
+                        fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
320
+                    }
321
+                    // trouver l'alias de la table d'arrivee qui porte le statut
322
+                    $id = array_search($id, $boucle->from);
323
+                } else {
324
+                    $id = $id_table;
325
+                    $statut = preg_replace(',\W,', '', $s['champ']); // securite
326
+                }
327
+                $mstatut = $id . '.' . $statut;
328
+
329
+                $arg_ignore_previsu = ($ignore_previsu ? ',true' : '');
330
+                include_spip('public/quete');
331
+                if (
332
+                    isset($s['post_date']) and $s['post_date']
333
+                    and $GLOBALS['meta']['post_dates'] == 'non'
334
+                ) {
335
+                    $date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite
336
+                    array_unshift(
337
+                        $boucle->where,
338
+                        $echapper ?
339
+                            "\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
340
+                            :
341
+                            quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu)
342
+                    );
343
+                }
344
+                array_unshift(
345
+                    $boucle->where,
346
+                    $echapper ?
347
+                        "\nquete_condition_statut('$mstatut',"
348
+                        . _q($s['previsu']) . ','
349
+                        . _q($s['publie']) . ','
350
+                        . _q($boucle->sql_serveur) . "$arg_ignore_previsu)"
351
+                        :
352
+                        quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu)
353
+                );
354
+            }
355
+        }
356
+    }
357 357
 }
358 358
 
359 359
 /**
@@ -372,29 +372,29 @@  discard block
 block discarded – undo
372 372
  */
373 373
 function calculer_boucle($id_boucle, &$boucles) {
374 374
 
375
-	$boucle = &$boucles[$id_boucle];
376
-	instituer_boucle($boucle);
377
-	$boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
378
-
379
-	// en mode debug memoriser les premiers passages dans la boucle,
380
-	// mais pas tous, sinon ca pete.
381
-	if (_request('var_mode_affiche') != 'resultat') {
382
-		$trace = '';
383
-	} else {
384
-		$_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
385
-		$_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
386
-		$trace = "
375
+    $boucle = &$boucles[$id_boucle];
376
+    instituer_boucle($boucle);
377
+    $boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
378
+
379
+    // en mode debug memoriser les premiers passages dans la boucle,
380
+    // mais pas tous, sinon ca pete.
381
+    if (_request('var_mode_affiche') != 'resultat') {
382
+        $trace = '';
383
+    } else {
384
+        $_trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
385
+        $_trace = "\$GLOBALS['debug_objets']['resultat']['$_trace']";
386
+        $trace = "
387 387
 		if (empty($_trace)) {
388 388
 			$_trace = [];
389 389
 		}
390 390
 		if (count($_trace) < 3) {
391 391
 			$_trace" . '[] = $t0;
392 392
 		}';
393
-	}
393
+    }
394 394
 
395
-	return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
396
-		? calculer_boucle_rec($id_boucle, $boucles, $trace)
397
-		: calculer_boucle_nonrec($id_boucle, $boucles, $trace);
395
+    return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
396
+        ? calculer_boucle_rec($id_boucle, $boucles, $trace)
397
+        : calculer_boucle_nonrec($id_boucle, $boucles, $trace);
398 398
 }
399 399
 
400 400
 
@@ -417,15 +417,15 @@  discard block
 block discarded – undo
417 417
  *    Code PHP compilé de la boucle récursive
418 418
  **/
419 419
 function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
420
-	$nom = $boucles[$id_boucle]->param[0];
421
-
422
-	return
423
-		// Numrows[$nom] peut ne pas être encore defini
424
-		"\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
425
-		. "\n\t\$t0 = " . $boucles[$id_boucle]->return . ';'
426
-		. "\n\t\$Numrows['$nom'] = (\$save_numrows);"
427
-		. $trace
428
-		. "\n\treturn \$t0;";
420
+    $nom = $boucles[$id_boucle]->param[0];
421
+
422
+    return
423
+        // Numrows[$nom] peut ne pas être encore defini
424
+        "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
425
+        . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ';'
426
+        . "\n\t\$Numrows['$nom'] = (\$save_numrows);"
427
+        . $trace
428
+        . "\n\treturn \$t0;";
429 429
 }
430 430
 
431 431
 /**
@@ -478,174 +478,174 @@  discard block
 block discarded – undo
478 478
  **/
479 479
 function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
480 480
 
481
-	$code_sep = null;
482
-	$boucle = &$boucles[$id_boucle];
483
-	$return = $boucle->return;
484
-	$type_boucle = $boucle->type_requete;
485
-	$primary = $boucle->primary;
486
-	$constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
487
-	$flag_cpt = $boucle->mode_partie || $boucle->cptrows;
488
-	$corps = '';
489
-
490
-	// faudrait expanser le foreach a la compil, car y en a souvent qu'un
491
-	// et puis faire un [] plutot qu'un "','."
492
-	if ($boucle->doublons) {
493
-		$corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
494
-			index_pile($id_boucle, $primary, $boucles)
495
-			. "; // doublons\n";
496
-	}
497
-
498
-	// La boucle doit-elle selectionner la langue ?
499
-	// - par defaut, les boucles suivantes le font
500
-	//    (sauf si forcer_lang==true ou si le titre contient <multi>).
501
-	// - a moins d'une demande explicite via {!lang_select}
502
-	if (
503
-		!$constant && $boucle->lang_select != 'non' &&
504
-		(($boucle->lang_select == 'oui') ||
505
-			in_array($type_boucle, [
506
-				'articles',
507
-				'rubriques',
508
-				'hierarchie',
509
-				'breves'
510
-			]))
511
-	) {
512
-		// Memoriser la langue avant la boucle et la restituer apres
513
-		// afin que le corps de boucle affecte la globale directement
514
-		$init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
515
-		$fin_lang = "lang_select();\n\t";
516
-		$fin_lang_select_public = "\n\t\tlang_select();";
517
-
518
-		$corps .=
519
-			"\n\t\tlang_select_public("
520
-			. index_pile($id_boucle, 'lang', $boucles)
521
-			. ", '" . $boucle->lang_select . "'"
522
-			. (in_array($type_boucle, [
523
-				'articles',
524
-				'rubriques',
525
-				'hierarchie',
526
-				'breves'
527
-			]) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
528
-			. ');';
529
-	} else {
530
-		$init_lang = '';
531
-		$fin_lang = '';
532
-		$fin_lang_select_public = '';
533
-		// sortir les appels au traducteur (invariants de boucle)
534
-		if (
535
-			strpos($return, '?php') === false
536
-			and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
537
-		) {
538
-			$i = 1;
539
-			foreach ($r[1] as $t) {
540
-				$init_lang .= "\n\t\$l$i = $t;";
541
-				$return = str_replace($t, "\$l$i", $return);
542
-				$i++;
543
-			}
544
-		}
545
-	}
546
-
547
-	// gestion optimale des separateurs et des boucles constantes
548
-	if (is_countable($boucle->separateur) ? count($boucle->separateur) : 0) {
549
-		$code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
550
-	}
551
-
552
-	$corps .=
553
-		((!$boucle->separateur) ?
554
-			(($constant && !$corps && !$flag_cpt) ? $return :
555
-				(($return === "''") ? '' :
556
-					("\n\t\t" . '$t0 .= ' . $return . ';'))) :
557
-			("\n\t\t\$t1 " .
558
-				((strpos($return, '$t1.') === 0) ?
559
-					('.=' . substr($return, 4)) :
560
-					('= ' . $return)) .
561
-				";\n\t\t" .
562
-				'$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
563
-
564
-	// Calculer les invalideurs si c'est une boucle non constante et si on
565
-	// souhaite invalider ces elements
566
-	if (!$constant and $primary) {
567
-		include_spip('inc/invalideur');
568
-		$corps = calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
569
-	}
570
-
571
-	// gerer le compteur de boucle
572
-	// avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
573
-
574
-	if ($boucle->partie or $boucle->cptrows) {
575
-		$corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
576
-			. $boucle->partie
577
-			. $corps;
578
-	}
579
-
580
-	// depiler la lang de la boucle si besoin
581
-	$corps .= $fin_lang_select_public;
582
-
583
-	// si le corps est une constante, ne pas appeler le serveur N fois!
584
-
585
-	if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
586
-		if (!isset($r[2]) or (!$r[2])) {
587
-			if (!$boucle->numrows) {
588
-				return "\n\t\$t0 = '';";
589
-			} else {
590
-				$corps = '';
591
-			}
592
-		} else {
593
-			$boucle->numrows = true;
594
-			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
595
-		}
596
-	} else {
597
-		$corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
598
-	}
599
-
600
-	$count = '';
601
-	if (!$boucle->select) {
602
-		if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
603
-			$count = '1';
604
-		} else {
605
-			$count = 'count(*)';
606
-		}
607
-		$boucles[$id_boucle]->select[] = $count;
608
-	}
609
-
610
-	if ($flag_cpt) {
611
-		$nums = "\n\t// COMPTEUR\n\t"
612
-			. "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
613
-	} else {
614
-		$nums = '';
615
-	}
616
-
617
-	if ($boucle->numrows or $boucle->mode_partie) {
618
-		$nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
619
-			. "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
620
-			. $boucle->mode_partie
621
-			. "\n\t";
622
-	}
623
-
624
-	// Ne calculer la requete que maintenant
625
-	// car ce qui precede appelle index_pile qui influe dessus
626
-
627
-	$init = (($init = $boucles[$id_boucle]->doublons)
628
-			? ("\n\t$init = array();") : '')
629
-		. calculer_requete_sql($boucles[$id_boucle]);
630
-
631
-	$contexte = memoriser_contexte_compil($boucle);
632
-
633
-	$a = sprintf(
634
-		CODE_CORPS_BOUCLE,
635
-		$init,
636
-		$boucle->iterateur,
637
-		'$command',
638
-		$contexte,
639
-		$nums,
640
-		$init_lang,
641
-		$corps,
642
-		$fin_lang,
643
-		$trace,
644
-		'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
645
-	);
481
+    $code_sep = null;
482
+    $boucle = &$boucles[$id_boucle];
483
+    $return = $boucle->return;
484
+    $type_boucle = $boucle->type_requete;
485
+    $primary = $boucle->primary;
486
+    $constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return));
487
+    $flag_cpt = $boucle->mode_partie || $boucle->cptrows;
488
+    $corps = '';
489
+
490
+    // faudrait expanser le foreach a la compil, car y en a souvent qu'un
491
+    // et puis faire un [] plutot qu'un "','."
492
+    if ($boucle->doublons) {
493
+        $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
494
+            index_pile($id_boucle, $primary, $boucles)
495
+            . "; // doublons\n";
496
+    }
497
+
498
+    // La boucle doit-elle selectionner la langue ?
499
+    // - par defaut, les boucles suivantes le font
500
+    //    (sauf si forcer_lang==true ou si le titre contient <multi>).
501
+    // - a moins d'une demande explicite via {!lang_select}
502
+    if (
503
+        !$constant && $boucle->lang_select != 'non' &&
504
+        (($boucle->lang_select == 'oui') ||
505
+            in_array($type_boucle, [
506
+                'articles',
507
+                'rubriques',
508
+                'hierarchie',
509
+                'breves'
510
+            ]))
511
+    ) {
512
+        // Memoriser la langue avant la boucle et la restituer apres
513
+        // afin que le corps de boucle affecte la globale directement
514
+        $init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
515
+        $fin_lang = "lang_select();\n\t";
516
+        $fin_lang_select_public = "\n\t\tlang_select();";
517
+
518
+        $corps .=
519
+            "\n\t\tlang_select_public("
520
+            . index_pile($id_boucle, 'lang', $boucles)
521
+            . ", '" . $boucle->lang_select . "'"
522
+            . (in_array($type_boucle, [
523
+                'articles',
524
+                'rubriques',
525
+                'hierarchie',
526
+                'breves'
527
+            ]) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '')
528
+            . ');';
529
+    } else {
530
+        $init_lang = '';
531
+        $fin_lang = '';
532
+        $fin_lang_select_public = '';
533
+        // sortir les appels au traducteur (invariants de boucle)
534
+        if (
535
+            strpos($return, '?php') === false
536
+            and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)
537
+        ) {
538
+            $i = 1;
539
+            foreach ($r[1] as $t) {
540
+                $init_lang .= "\n\t\$l$i = $t;";
541
+                $return = str_replace($t, "\$l$i", $return);
542
+                $i++;
543
+            }
544
+        }
545
+    }
546
+
547
+    // gestion optimale des separateurs et des boucles constantes
548
+    if (is_countable($boucle->separateur) ? count($boucle->separateur) : 0) {
549
+        $code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'");
550
+    }
551
+
552
+    $corps .=
553
+        ((!$boucle->separateur) ?
554
+            (($constant && !$corps && !$flag_cpt) ? $return :
555
+                (($return === "''") ? '' :
556
+                    ("\n\t\t" . '$t0 .= ' . $return . ';'))) :
557
+            ("\n\t\t\$t1 " .
558
+                ((strpos($return, '$t1.') === 0) ?
559
+                    ('.=' . substr($return, 4)) :
560
+                    ('= ' . $return)) .
561
+                ";\n\t\t" .
562
+                '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
563
+
564
+    // Calculer les invalideurs si c'est une boucle non constante et si on
565
+    // souhaite invalider ces elements
566
+    if (!$constant and $primary) {
567
+        include_spip('inc/invalideur');
568
+        $corps = calcul_invalideurs($corps, $primary, $boucles, $id_boucle);
569
+    }
570
+
571
+    // gerer le compteur de boucle
572
+    // avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
573
+
574
+    if ($boucle->partie or $boucle->cptrows) {
575
+        $corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
576
+            . $boucle->partie
577
+            . $corps;
578
+    }
579
+
580
+    // depiler la lang de la boucle si besoin
581
+    $corps .= $fin_lang_select_public;
582
+
583
+    // si le corps est une constante, ne pas appeler le serveur N fois!
584
+
585
+    if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) {
586
+        if (!isset($r[2]) or (!$r[2])) {
587
+            if (!$boucle->numrows) {
588
+                return "\n\t\$t0 = '';";
589
+            } else {
590
+                $corps = '';
591
+            }
592
+        } else {
593
+            $boucle->numrows = true;
594
+            $corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
595
+        }
596
+    } else {
597
+        $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}";
598
+    }
599
+
600
+    $count = '';
601
+    if (!$boucle->select) {
602
+        if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) {
603
+            $count = '1';
604
+        } else {
605
+            $count = 'count(*)';
606
+        }
607
+        $boucles[$id_boucle]->select[] = $count;
608
+    }
609
+
610
+    if ($flag_cpt) {
611
+        $nums = "\n\t// COMPTEUR\n\t"
612
+            . "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
613
+    } else {
614
+        $nums = '';
615
+    }
616
+
617
+    if ($boucle->numrows or $boucle->mode_partie) {
618
+        $nums .= "\$Numrows['$id_boucle']['command'] = \$command;\n\t"
619
+            . "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
620
+            . $boucle->mode_partie
621
+            . "\n\t";
622
+    }
623
+
624
+    // Ne calculer la requete que maintenant
625
+    // car ce qui precede appelle index_pile qui influe dessus
626
+
627
+    $init = (($init = $boucles[$id_boucle]->doublons)
628
+            ? ("\n\t$init = array();") : '')
629
+        . calculer_requete_sql($boucles[$id_boucle]);
630
+
631
+    $contexte = memoriser_contexte_compil($boucle);
632
+
633
+    $a = sprintf(
634
+        CODE_CORPS_BOUCLE,
635
+        $init,
636
+        $boucle->iterateur,
637
+        '$command',
638
+        $contexte,
639
+        $nums,
640
+        $init_lang,
641
+        $corps,
642
+        $fin_lang,
643
+        $trace,
644
+        'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile'])
645
+    );
646 646
 
647 647
 #	var_dump($a);exit;
648
-	return $a;
648
+    return $a;
649 649
 }
650 650
 
651 651
 
@@ -661,48 +661,48 @@  discard block
 block discarded – undo
661 661
  *     Code PHP compilé définissant les informations de requête
662 662
  **/
663 663
 function calculer_requete_sql($boucle) {
664
-	$init = [];
665
-	$init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
666
-	$init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
667
-	# En absence de champ c'est un decompte :
668
-	$init[] = calculer_dec('from', calculer_from($boucle));
669
-	$init[] = calculer_dec('type', calculer_from_type($boucle));
670
-	$init[] = calculer_dec(
671
-		'groupby',
672
-		'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ')'
673
-	);
674
-	$init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . '")');
675
-	$init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ')');
676
-	$init[] = calculer_dec('where', calculer_dump_array($boucle->where));
677
-	$init[] = calculer_dec('join', calculer_dump_join($boucle->join));
678
-	$init[] = calculer_dec(
679
-		'limit',
680
-		(
681
-			strpos($boucle->limit, 'intval') === false ?
682
-			"'" . ($boucle->limit) . "'" :
683
-			$boucle->limit
684
-		)
685
-	);
686
-	$init[] = calculer_dec('having', calculer_dump_array($boucle->having));
687
-	$s = $d = '';
688
-	// l'index 0 de $i indique si l'affectation est statique (contenu)
689
-	// ou recalculée à chaque passage (vide)
690
-	foreach ($init as $i) {
691
-		if (reset($i)) {
692
-			$s .= "\n\t\t" . end($i);
693
-		} # statique
694
-		else {
695
-			$d .= "\n\t" . end($i);
696
-		} # dynamique
697
-	}
698
-
699
-	return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
700
-	. $boucle->in
701
-	. $boucle->hash
702
-	. "\n\t" . 'if (!isset($command[\'table\'])) {'
703
-	. $s
704
-	. "\n\t}"
705
-	. $d;
664
+    $init = [];
665
+    $init[] = calculer_dec('table', "'" . $boucle->id_table . "'");
666
+    $init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'");
667
+    # En absence de champ c'est un decompte :
668
+    $init[] = calculer_dec('from', calculer_from($boucle));
669
+    $init[] = calculer_dec('type', calculer_from_type($boucle));
670
+    $init[] = calculer_dec(
671
+        'groupby',
672
+        'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ')'
673
+    );
674
+    $init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . '")');
675
+    $init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ')');
676
+    $init[] = calculer_dec('where', calculer_dump_array($boucle->where));
677
+    $init[] = calculer_dec('join', calculer_dump_join($boucle->join));
678
+    $init[] = calculer_dec(
679
+        'limit',
680
+        (
681
+            strpos($boucle->limit, 'intval') === false ?
682
+            "'" . ($boucle->limit) . "'" :
683
+            $boucle->limit
684
+        )
685
+    );
686
+    $init[] = calculer_dec('having', calculer_dump_array($boucle->having));
687
+    $s = $d = '';
688
+    // l'index 0 de $i indique si l'affectation est statique (contenu)
689
+    // ou recalculée à chaque passage (vide)
690
+    foreach ($init as $i) {
691
+        if (reset($i)) {
692
+            $s .= "\n\t\t" . end($i);
693
+        } # statique
694
+        else {
695
+            $d .= "\n\t" . end($i);
696
+        } # dynamique
697
+    }
698
+
699
+    return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
700
+    . $boucle->in
701
+    . $boucle->hash
702
+    . "\n\t" . 'if (!isset($command[\'table\'])) {'
703
+    . $s
704
+    . "\n\t}"
705
+    . $d;
706 706
 }
707 707
 
708 708
 /**
@@ -720,13 +720,13 @@  discard block
 block discarded – undo
720 720
  *     qui peut être utilisé pour la production d'un tableau array()
721 721
  **/
722 722
 function memoriser_contexte_compil($p) {
723
-	return join(',', [
724
-		_q($p->descr['sourcefile'] ?? ''),
725
-		_q($p->descr['nom'] ?? ''),
726
-		_q($p->id_boucle ?? ''),
727
-		intval($p->ligne),
728
-		'$GLOBALS[\'spip_lang\']'
729
-	]);
723
+    return join(',', [
724
+        _q($p->descr['sourcefile'] ?? ''),
725
+        _q($p->descr['nom'] ?? ''),
726
+        _q($p->id_boucle ?? ''),
727
+        intval($p->ligne),
728
+        '$GLOBALS[\'spip_lang\']'
729
+    ]);
730 730
 }
731 731
 
732 732
 /**
@@ -744,20 +744,20 @@  discard block
 block discarded – undo
744 744
  *     Objet Contexte
745 745
  **/
746 746
 function reconstruire_contexte_compil($context_compil) {
747
-	if (!is_array($context_compil)) {
748
-		return $context_compil;
749
-	}
750
-	$p = new Contexte();
751
-	$p->descr = [
752
-		'sourcefile' => $context_compil[0] ?? '',
753
-		'nom' => $context_compil[1] ?? '',
754
-	];
755
-
756
-	$p->id_boucle = $context_compil[2] ?? '';
757
-	$p->ligne = (int)($context_compil[3] ?? 0);
758
-	$p->lang = $context_compil[4] ?? '';
759
-
760
-	return $p;
747
+    if (!is_array($context_compil)) {
748
+        return $context_compil;
749
+    }
750
+    $p = new Contexte();
751
+    $p->descr = [
752
+        'sourcefile' => $context_compil[0] ?? '',
753
+        'nom' => $context_compil[1] ?? '',
754
+    ];
755
+
756
+    $p->id_boucle = $context_compil[2] ?? '';
757
+    $p->ligne = (int)($context_compil[3] ?? 0);
758
+    $p->lang = $context_compil[4] ?? '';
759
+
760
+    return $p;
761 761
 }
762 762
 
763 763
 /**
@@ -783,12 +783,12 @@  discard block
 block discarded – undo
783 783
  *    - index 1 : Code de l'affectation
784 784
  **/
785 785
 function calculer_dec($nom, $val) {
786
-	$static = 'if (!isset($command[\'' . $nom . '\'])) ';
787
-	// si une variable apparait dans le calcul de la clause
788
-	// il faut la re-evaluer a chaque passage
789
-	if (
790
-		strpos($val, '$') !== false
791
-		/*
786
+    $static = 'if (!isset($command[\'' . $nom . '\'])) ';
787
+    // si une variable apparait dans le calcul de la clause
788
+    // il faut la re-evaluer a chaque passage
789
+    if (
790
+        strpos($val, '$') !== false
791
+        /*
792 792
 		OR strpos($val, 'sql_') !== false
793 793
 		OR (
794 794
 			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
@@ -796,11 +796,11 @@  discard block
 block discarded – undo
796 796
 			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
797 797
 			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
798 798
 		)*/
799
-	) {
800
-		$static = '';
801
-	}
799
+    ) {
800
+        $static = '';
801
+    }
802 802
 
803
-	return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
803
+    return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
804 804
 }
805 805
 
806 806
 /**
@@ -820,32 +820,32 @@  discard block
 block discarded – undo
820 820
  *     Expression PHP décrivant un texte ou un tableau
821 821
  **/
822 822
 function calculer_dump_array($a) {
823
-	if (!is_array($a)) {
824
-		return $a;
825
-	}
826
-	$res = '';
827
-	if ($a and $a[0] == "'?'") {
828
-		return ('(' . calculer_dump_array($a[1]) .
829
-			' ? ' . calculer_dump_array($a[2]) .
830
-			' : ' . calculer_dump_array($a[3]) .
831
-			')');
832
-	} else {
833
-		foreach ($a as $k => $v) {
834
-			$showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
835
-			$res .= ', ' . $showk . calculer_dump_array($v);
836
-		}
837
-
838
-		return "\n\t\t\tarray(" . substr($res, 2) . ')';
839
-	}
823
+    if (!is_array($a)) {
824
+        return $a;
825
+    }
826
+    $res = '';
827
+    if ($a and $a[0] == "'?'") {
828
+        return ('(' . calculer_dump_array($a[1]) .
829
+            ' ? ' . calculer_dump_array($a[2]) .
830
+            ' : ' . calculer_dump_array($a[3]) .
831
+            ')');
832
+    } else {
833
+        foreach ($a as $k => $v) {
834
+            $showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
835
+            $res .= ', ' . $showk . calculer_dump_array($v);
836
+        }
837
+
838
+        return "\n\t\t\tarray(" . substr($res, 2) . ')';
839
+    }
840 840
 }
841 841
 
842 842
 function calculer_dump_join($a) {
843
-	$res = '';
844
-	foreach ($a as $k => $v) {
845
-		$res .= ", '$k' => array(" . implode(',', $v) . ')';
846
-	}
843
+    $res = '';
844
+    foreach ($a as $k => $v) {
845
+        $res .= ", '$k' => array(" . implode(',', $v) . ')';
846
+    }
847 847
 
848
-	return 'array(' . substr($res, 2) . ')';
848
+    return 'array(' . substr($res, 2) . ')';
849 849
 }
850 850
 
851 851
 /**
@@ -857,12 +857,12 @@  discard block
 block discarded – undo
857 857
  *     Code PHP construisant un tableau des alias et noms des tables du FROM
858 858
  **/
859 859
 function calculer_from(&$boucle) {
860
-	$res = '';
861
-	foreach ($boucle->from as $k => $v) {
862
-		$res .= ",'$k' => '$v'";
863
-	}
860
+    $res = '';
861
+    foreach ($boucle->from as $k => $v) {
862
+        $res .= ",'$k' => '$v'";
863
+    }
864 864
 
865
-	return 'array(' . substr($res, 1) . ')';
865
+    return 'array(' . substr($res, 1) . ')';
866 866
 }
867 867
 
868 868
 /**
@@ -875,30 +875,30 @@  discard block
 block discarded – undo
875 875
  *     Code PHP construisant un tableau des alias et type de jointure du FROM
876 876
  **/
877 877
 function calculer_from_type(&$boucle) {
878
-	$res = '';
879
-	foreach ($boucle->from_type as $k => $v) {
880
-		$res .= ",'$k' => '$v'";
881
-	}
878
+    $res = '';
879
+    foreach ($boucle->from_type as $k => $v) {
880
+        $res .= ",'$k' => '$v'";
881
+    }
882 882
 
883
-	return 'array(' . substr($res, 1) . ')';
883
+    return 'array(' . substr($res, 1) . ')';
884 884
 }
885 885
 
886 886
 function calculer_order(&$boucle) {
887
-	if (
888
-		!$order = $boucle->order
889
-		and !$order = $boucle->default_order
890
-	) {
891
-		$order = [];
892
-	}
893
-
894
-	/*if (isset($boucle->modificateur['collate'])){
887
+    if (
888
+        !$order = $boucle->order
889
+        and !$order = $boucle->default_order
890
+    ) {
891
+        $order = [];
892
+    }
893
+
894
+    /*if (isset($boucle->modificateur['collate'])){
895 895
 		$col = "." . $boucle->modificateur['collate'];
896 896
 		foreach($order as $k=>$o)
897 897
 			if (strpos($order[$k],'COLLATE')===false)
898 898
 				$order[$k].= $col;
899 899
 	}*/
900 900
 
901
-	return join(', ', $order);
901
+    return join(', ', $order);
902 902
 }
903 903
 
904 904
 // Production du code PHP a partir de la sequence livree par le phraseur
@@ -907,62 +907,62 @@  discard block
 block discarded – undo
907 907
 // (qui sera argument d'un Return ou la partie droite d'une affectation).
908 908
 
909 909
 function calculer_liste($tableau, $descr, &$boucles, $id_boucle = '') {
910
-	if (!$tableau) {
911
-		return "''";
912
-	}
913
-	if (is_string($descr)) {
914
-		if (isset($boucles[$descr])) {
915
-			$idb = $descr;
916
-			$descr = [];
917
-			if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
918
-				$descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
919
-			}
920
-			if (isset($boucles[$idb]->descr['sourcefile'])) {
921
-				$descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
922
-			}
923
-		}
924
-		else {
925
-			$descr = [];
926
-		}
927
-	}
928
-	if (!isset($descr['niv'])) {
929
-		$descr['niv'] = 0;
930
-	}
931
-	$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
932
-	if ($codes === false) {
933
-		return false;
934
-	}
935
-	$n = is_countable($codes) ? count($codes) : 0;
936
-	if (!$n) {
937
-		return "''";
938
-	}
939
-	$tab = str_repeat("\t", $descr['niv']);
940
-	if (_request('var_mode_affiche') != 'validation') {
941
-		if ($n == 1) {
942
-			return $codes[0];
943
-		} else {
944
-			$res = '';
945
-			foreach ($codes as $code) {
946
-				if (
947
-					!preg_match("/^'[^']*'$/", $code)
948
-					or substr($res, -1, 1) !== "'"
949
-				) {
950
-					$res .= " .\n$tab$code";
951
-				} else {
952
-					$res = substr($res, 0, -1) . substr($code, 1);
953
-				}
954
-			}
955
-
956
-			return '(' . substr($res, 2 + $descr['niv']) . ')';
957
-		}
958
-	} else {
959
-		$nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
960
-
961
-		return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
962
-			" ,\n$tab",
963
-			$codes
964
-		) . ')))';
965
-	}
910
+    if (!$tableau) {
911
+        return "''";
912
+    }
913
+    if (is_string($descr)) {
914
+        if (isset($boucles[$descr])) {
915
+            $idb = $descr;
916
+            $descr = [];
917
+            if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
918
+                $descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
919
+            }
920
+            if (isset($boucles[$idb]->descr['sourcefile'])) {
921
+                $descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
922
+            }
923
+        }
924
+        else {
925
+            $descr = [];
926
+        }
927
+    }
928
+    if (!isset($descr['niv'])) {
929
+        $descr['niv'] = 0;
930
+    }
931
+    $codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
932
+    if ($codes === false) {
933
+        return false;
934
+    }
935
+    $n = is_countable($codes) ? count($codes) : 0;
936
+    if (!$n) {
937
+        return "''";
938
+    }
939
+    $tab = str_repeat("\t", $descr['niv']);
940
+    if (_request('var_mode_affiche') != 'validation') {
941
+        if ($n == 1) {
942
+            return $codes[0];
943
+        } else {
944
+            $res = '';
945
+            foreach ($codes as $code) {
946
+                if (
947
+                    !preg_match("/^'[^']*'$/", $code)
948
+                    or substr($res, -1, 1) !== "'"
949
+                ) {
950
+                    $res .= " .\n$tab$code";
951
+                } else {
952
+                    $res = substr($res, 0, -1) . substr($code, 1);
953
+                }
954
+            }
955
+
956
+            return '(' . substr($res, 2 + $descr['niv']) . ')';
957
+        }
958
+    } else {
959
+        $nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
960
+
961
+        return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
962
+            " ,\n$tab",
963
+            $codes
964
+        ) . ')))';
965
+    }
966 966
 }
967 967
 
968 968
 
@@ -972,213 +972,213 @@  discard block
 block discarded – undo
972 972
 
973 973
 function compile_cas($tableau, $descr, &$boucles, $id_boucle) {
974 974
 
975
-	$codes = [];
976
-	// cas de la boucle recursive
977
-	if (is_array($id_boucle)) {
978
-		$id_boucle = $id_boucle[0];
979
-	}
980
-	$type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
981
-	$tab = str_repeat("\t", ++$descr['niv']);
982
-	$mode = _request('var_mode_affiche');
983
-	$err_e_c = '';
984
-	// chaque commentaire introduit dans le code doit commencer
985
-	// par un caractere distinguant le cas, pour exploitation par debug.
986
-	foreach ($tableau as $p) {
987
-		switch ($p->type) {
988
-			// texte seul
989
-			case 'texte':
990
-				$code = sandbox_composer_texte($p->texte, $p);
991
-				$commentaire = strlen($p->texte) . ' signes';
992
-				$avant = '';
993
-				$apres = '';
994
-				$altern = "''";
995
-				break;
996
-
997
-			case 'polyglotte':
998
-				$code = '';
999
-				foreach ($p->traductions as $k => $v) {
1000
-					$code .= ",'" .
1001
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1002
-						"' => '" .
1003
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1004
-						"'";
1005
-				}
1006
-				$code = 'choisir_traduction(array(' .
1007
-					substr($code, 1) .
1008
-					'))';
1009
-				$commentaire = '&';
1010
-				$avant = '';
1011
-				$apres = '';
1012
-				$altern = "''";
1013
-				break;
1014
-
1015
-			// inclure
1016
-			case 'include':
1017
-				$p->descr = $descr;
1018
-				$code = calculer_inclure($p, $boucles, $id_boucle);
1019
-				if ($code === false) {
1020
-					$err_e_c = true;
1021
-					$code = "''";
1022
-				} else {
1023
-					$commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1024
-					$avant = '';
1025
-					$apres = '';
1026
-					$altern = "''";
1027
-				}
1028
-				break;
1029
-
1030
-			// boucle
1031
-			case TYPE_RECURSIF:
1032
-				$nom = $p->id_boucle;
1033
-				$newdescr = $descr;
1034
-				$newdescr['id_mere'] = $nom;
1035
-				$newdescr['niv']++;
1036
-				$preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1037
-				$avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1038
-				$apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1039
-				$postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1040
-				$newdescr['niv']--;
1041
-				$altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1042
-				if (
1043
-					$preaff === false
1044
-					or $avant === false
1045
-					or $apres === false
1046
-					or $altern === false
1047
-					or $postaff === false
1048
-				) {
1049
-					$err_e_c = true;
1050
-					$code = "''";
1051
-				} else {
1052
-					$code = 'BOUCLE' .
1053
-						str_replace('-', '_', $nom) . $descr['nom'] .
1054
-						'($Cache, $Pile, $doublons, $Numrows, $SP)';
1055
-					$commentaire = "?$nom";
1056
-					if (
1057
-						!$boucles[$nom]->milieu
1058
-						and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1059
-					) {
1060
-						if ($preaff != "''") {
1061
-							$code .= "\n. $preaff";
1062
-						}
1063
-						if ($altern != "''") {
1064
-							$code .= "\n. $altern";
1065
-						}
1066
-						if ($postaff != "''") {
1067
-							$code .= "\n. $postaff";
1068
-						}
1069
-						if ($avant <> "''" or $apres <> "''") {
1070
-							spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1071
-						}
1072
-						$avant = $apres = $altern = "''";
1073
-					} else {
1074
-						if ($preaff != "''") {
1075
-							$avant = compile_concatene_parties_codes($preaff, $avant);
1076
-							$altern = compile_concatene_parties_codes($preaff, $altern);
1077
-						}
1078
-						if ($postaff != "''") {
1079
-							$apres = compile_concatene_parties_codes($apres, $postaff);
1080
-							$altern = compile_concatene_parties_codes($altern, $postaff);
1081
-						}
1082
-						if ($altern != "''") {
1083
-							$altern = "($altern)";
1084
-						}
1085
-					}
1086
-				}
1087
-				break;
1088
-
1089
-			case 'idiome':
1090
-				$l = [];
1091
-				$code = '';
1092
-				foreach ($p->arg as $k => $v) {
1093
-					$_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1094
-					if ($k) {
1095
-						$l[] = _q($k) . ' => ' . $_v;
1096
-					} else {
1097
-						$code = $_v;
1098
-					}
1099
-				}
1100
-				// Si le module n'est pas fourni, l'expliciter sauf si calculé
1101
-				if ($p->module) {
1102
-					$m = $p->module . ':' . $p->nom_champ;
1103
-				} elseif ($p->nom_champ) {
1104
-					$m = MODULES_IDIOMES . ':' . $p->nom_champ;
1105
-				} else {
1106
-					$m = '';
1107
-				}
1108
-
1109
-				$code = (!$code ? "'$m'" :
1110
-						($m ? "'$m' . $code" :
1111
-							("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1112
-					. (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1113
-				$code = "_T($code)";
1114
-				if ($p->param) {
1115
-					$p->id_boucle = $id_boucle;
1116
-					$p->boucles = &$boucles;
1117
-					$code = compose_filtres($p, $code);
1118
-				}
1119
-				$commentaire = ':';
1120
-				$avant = '';
1121
-				$apres = '';
1122
-				$altern = "''";
1123
-				break;
1124
-
1125
-			case 'champ':
1126
-				// cette structure pourrait etre completee des le phrase' (a faire)
1127
-				$p->id_boucle = $id_boucle;
1128
-				$p->boucles = &$boucles;
1129
-				$p->descr = $descr;
1130
-				#$p->interdire_scripts = true;
1131
-				$p->type_requete = $type;
1132
-
1133
-				$code = calculer_champ($p);
1134
-				$commentaire = '#' . $p->nom_champ . $p->etoile;
1135
-				$avant = calculer_liste(
1136
-					$p->avant,
1137
-					$descr,
1138
-					$boucles,
1139
-					$id_boucle
1140
-				);
1141
-				$apres = calculer_liste(
1142
-					$p->apres,
1143
-					$descr,
1144
-					$boucles,
1145
-					$id_boucle
1146
-				);
1147
-				$altern = "''";
1148
-				// Si la valeur est destinee a une comparaison a ''
1149
-				// forcer la conversion en une chaine par strval
1150
-				// si ca peut etre autre chose qu'une chaine
1151
-				if (
1152
-					($avant != "''" or $apres != "''")
1153
-					and $code[0] != "'"
975
+    $codes = [];
976
+    // cas de la boucle recursive
977
+    if (is_array($id_boucle)) {
978
+        $id_boucle = $id_boucle[0];
979
+    }
980
+    $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
981
+    $tab = str_repeat("\t", ++$descr['niv']);
982
+    $mode = _request('var_mode_affiche');
983
+    $err_e_c = '';
984
+    // chaque commentaire introduit dans le code doit commencer
985
+    // par un caractere distinguant le cas, pour exploitation par debug.
986
+    foreach ($tableau as $p) {
987
+        switch ($p->type) {
988
+            // texte seul
989
+            case 'texte':
990
+                $code = sandbox_composer_texte($p->texte, $p);
991
+                $commentaire = strlen($p->texte) . ' signes';
992
+                $avant = '';
993
+                $apres = '';
994
+                $altern = "''";
995
+                break;
996
+
997
+            case 'polyglotte':
998
+                $code = '';
999
+                foreach ($p->traductions as $k => $v) {
1000
+                    $code .= ",'" .
1001
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1002
+                        "' => '" .
1003
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1004
+                        "'";
1005
+                }
1006
+                $code = 'choisir_traduction(array(' .
1007
+                    substr($code, 1) .
1008
+                    '))';
1009
+                $commentaire = '&';
1010
+                $avant = '';
1011
+                $apres = '';
1012
+                $altern = "''";
1013
+                break;
1014
+
1015
+            // inclure
1016
+            case 'include':
1017
+                $p->descr = $descr;
1018
+                $code = calculer_inclure($p, $boucles, $id_boucle);
1019
+                if ($code === false) {
1020
+                    $err_e_c = true;
1021
+                    $code = "''";
1022
+                } else {
1023
+                    $commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1024
+                    $avant = '';
1025
+                    $apres = '';
1026
+                    $altern = "''";
1027
+                }
1028
+                break;
1029
+
1030
+            // boucle
1031
+            case TYPE_RECURSIF:
1032
+                $nom = $p->id_boucle;
1033
+                $newdescr = $descr;
1034
+                $newdescr['id_mere'] = $nom;
1035
+                $newdescr['niv']++;
1036
+                $preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1037
+                $avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1038
+                $apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1039
+                $postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1040
+                $newdescr['niv']--;
1041
+                $altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1042
+                if (
1043
+                    $preaff === false
1044
+                    or $avant === false
1045
+                    or $apres === false
1046
+                    or $altern === false
1047
+                    or $postaff === false
1048
+                ) {
1049
+                    $err_e_c = true;
1050
+                    $code = "''";
1051
+                } else {
1052
+                    $code = 'BOUCLE' .
1053
+                        str_replace('-', '_', $nom) . $descr['nom'] .
1054
+                        '($Cache, $Pile, $doublons, $Numrows, $SP)';
1055
+                    $commentaire = "?$nom";
1056
+                    if (
1057
+                        !$boucles[$nom]->milieu
1058
+                        and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1059
+                    ) {
1060
+                        if ($preaff != "''") {
1061
+                            $code .= "\n. $preaff";
1062
+                        }
1063
+                        if ($altern != "''") {
1064
+                            $code .= "\n. $altern";
1065
+                        }
1066
+                        if ($postaff != "''") {
1067
+                            $code .= "\n. $postaff";
1068
+                        }
1069
+                        if ($avant <> "''" or $apres <> "''") {
1070
+                            spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1071
+                        }
1072
+                        $avant = $apres = $altern = "''";
1073
+                    } else {
1074
+                        if ($preaff != "''") {
1075
+                            $avant = compile_concatene_parties_codes($preaff, $avant);
1076
+                            $altern = compile_concatene_parties_codes($preaff, $altern);
1077
+                        }
1078
+                        if ($postaff != "''") {
1079
+                            $apres = compile_concatene_parties_codes($apres, $postaff);
1080
+                            $altern = compile_concatene_parties_codes($altern, $postaff);
1081
+                        }
1082
+                        if ($altern != "''") {
1083
+                            $altern = "($altern)";
1084
+                        }
1085
+                    }
1086
+                }
1087
+                break;
1088
+
1089
+            case 'idiome':
1090
+                $l = [];
1091
+                $code = '';
1092
+                foreach ($p->arg as $k => $v) {
1093
+                    $_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1094
+                    if ($k) {
1095
+                        $l[] = _q($k) . ' => ' . $_v;
1096
+                    } else {
1097
+                        $code = $_v;
1098
+                    }
1099
+                }
1100
+                // Si le module n'est pas fourni, l'expliciter sauf si calculé
1101
+                if ($p->module) {
1102
+                    $m = $p->module . ':' . $p->nom_champ;
1103
+                } elseif ($p->nom_champ) {
1104
+                    $m = MODULES_IDIOMES . ':' . $p->nom_champ;
1105
+                } else {
1106
+                    $m = '';
1107
+                }
1108
+
1109
+                $code = (!$code ? "'$m'" :
1110
+                        ($m ? "'$m' . $code" :
1111
+                            ("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1112
+                    . (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1113
+                $code = "_T($code)";
1114
+                if ($p->param) {
1115
+                    $p->id_boucle = $id_boucle;
1116
+                    $p->boucles = &$boucles;
1117
+                    $code = compose_filtres($p, $code);
1118
+                }
1119
+                $commentaire = ':';
1120
+                $avant = '';
1121
+                $apres = '';
1122
+                $altern = "''";
1123
+                break;
1124
+
1125
+            case 'champ':
1126
+                // cette structure pourrait etre completee des le phrase' (a faire)
1127
+                $p->id_boucle = $id_boucle;
1128
+                $p->boucles = &$boucles;
1129
+                $p->descr = $descr;
1130
+                #$p->interdire_scripts = true;
1131
+                $p->type_requete = $type;
1132
+
1133
+                $code = calculer_champ($p);
1134
+                $commentaire = '#' . $p->nom_champ . $p->etoile;
1135
+                $avant = calculer_liste(
1136
+                    $p->avant,
1137
+                    $descr,
1138
+                    $boucles,
1139
+                    $id_boucle
1140
+                );
1141
+                $apres = calculer_liste(
1142
+                    $p->apres,
1143
+                    $descr,
1144
+                    $boucles,
1145
+                    $id_boucle
1146
+                );
1147
+                $altern = "''";
1148
+                // Si la valeur est destinee a une comparaison a ''
1149
+                // forcer la conversion en une chaine par strval
1150
+                // si ca peut etre autre chose qu'une chaine
1151
+                if (
1152
+                    ($avant != "''" or $apres != "''")
1153
+                    and $code[0] != "'"
1154 1154
 #			AND (strpos($code,'interdire_scripts') !== 0)
1155
-					and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1156
-					and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1157
-					and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1158
-				) {
1159
-					$code = "strval($code)";
1160
-				}
1161
-				break;
1162
-
1163
-			default:
1164
-				// Erreur de construction de l'arbre de syntaxe abstraite
1165
-				$code = "''";
1166
-				$p->descr = $descr;
1167
-				$err_e_c = _T('zbug_erreur_compilation');
1168
-				erreur_squelette($err_e_c, $p);
1169
-		} // switch
1170
-
1171
-		if ($code != "''") {
1172
-			$code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1173
-			$codes[] = (($mode == 'validation') ?
1174
-				"array($code, '$commentaire', " . $p->ligne . ')'
1175
-				: (($mode == 'code') ?
1176
-					"\n// $commentaire\n$code" :
1177
-					$code));
1178
-		}
1179
-	} // foreach
1180
-
1181
-	return $err_e_c ? false : $codes;
1155
+                    and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1156
+                    and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1157
+                    and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1158
+                ) {
1159
+                    $code = "strval($code)";
1160
+                }
1161
+                break;
1162
+
1163
+            default:
1164
+                // Erreur de construction de l'arbre de syntaxe abstraite
1165
+                $code = "''";
1166
+                $p->descr = $descr;
1167
+                $err_e_c = _T('zbug_erreur_compilation');
1168
+                erreur_squelette($err_e_c, $p);
1169
+        } // switch
1170
+
1171
+        if ($code != "''") {
1172
+            $code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1173
+            $codes[] = (($mode == 'validation') ?
1174
+                "array($code, '$commentaire', " . $p->ligne . ')'
1175
+                : (($mode == 'code') ?
1176
+                    "\n// $commentaire\n$code" :
1177
+                    $code));
1178
+        }
1179
+    } // foreach
1180
+
1181
+    return $err_e_c ? false : $codes;
1182 1182
 }
1183 1183
 
1184 1184
 /**
@@ -1188,13 +1188,13 @@  discard block
 block discarded – undo
1188 1188
  * @return string
1189 1189
  */
1190 1190
 function compile_concatene_parties_codes($partie1, $partie2) {
1191
-	if ($partie1 === "''") {
1192
-		return $partie2;
1193
-	}
1194
-	if ($partie2 === "''") {
1195
-		return $partie1;
1196
-	}
1197
-	return "$partie1\n. $partie2";
1191
+    if ($partie1 === "''") {
1192
+        return $partie2;
1193
+    }
1194
+    if ($partie2 === "''") {
1195
+        return $partie1;
1196
+    }
1197
+    return "$partie1\n. $partie2";
1198 1198
 }
1199 1199
 
1200 1200
 
@@ -1218,56 +1218,56 @@  discard block
 block discarded – undo
1218 1218
  * @return mixed|string
1219 1219
  */
1220 1220
 function compile_retour($code, $avant, $apres, $altern, $tab, $n) {
1221
-	if ($avant === "''") {
1222
-		$avant = '';
1223
-	}
1224
-	if ($apres === "''") {
1225
-		$apres = '';
1226
-	}
1227
-	if ($avant or $apres or ($altern !== "''")) {
1228
-		if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1229
-			$t = $code;
1230
-			$cond = '';
1231
-		} elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1232
-			$t = $r[2];
1233
-			$cond = '!' . $r[1];
1234
-		} else {
1235
-			if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1236
-				$t = $r[2];
1237
-				$cond = $r[1];
1238
-			} else {
1239
-				$t = '$t' . $n;
1240
-				$cond = "($t = $code)!==''";
1241
-			}
1242
-		}
1243
-
1244
-		$res = (!$avant ? '' : "$avant . ") .
1245
-			$t .
1246
-			(!$apres ? '' : " . $apres");
1247
-
1248
-		if ($res !== $t) {
1249
-			$res = "($res)";
1250
-		}
1251
-
1252
-		$code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1253
-	}
1254
-
1255
-	return $code;
1221
+    if ($avant === "''") {
1222
+        $avant = '';
1223
+    }
1224
+    if ($apres === "''") {
1225
+        $apres = '';
1226
+    }
1227
+    if ($avant or $apres or ($altern !== "''")) {
1228
+        if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1229
+            $t = $code;
1230
+            $cond = '';
1231
+        } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1232
+            $t = $r[2];
1233
+            $cond = '!' . $r[1];
1234
+        } else {
1235
+            if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1236
+                $t = $r[2];
1237
+                $cond = $r[1];
1238
+            } else {
1239
+                $t = '$t' . $n;
1240
+                $cond = "($t = $code)!==''";
1241
+            }
1242
+        }
1243
+
1244
+        $res = (!$avant ? '' : "$avant . ") .
1245
+            $t .
1246
+            (!$apres ? '' : " . $apres");
1247
+
1248
+        if ($res !== $t) {
1249
+            $res = "($res)";
1250
+        }
1251
+
1252
+        $code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1253
+    }
1254
+
1255
+    return $code;
1256 1256
 }
1257 1257
 
1258 1258
 
1259 1259
 function compile_inclure_doublons($lexemes) {
1260
-	foreach ($lexemes as $v) {
1261
-		if ($v->type === 'include' and $v->param) {
1262
-			foreach ($v->param as $r) {
1263
-				if (trim($r[0]) === 'doublons') {
1264
-					return true;
1265
-				}
1266
-			}
1267
-		}
1268
-	}
1269
-
1270
-	return false;
1260
+    foreach ($lexemes as $v) {
1261
+        if ($v->type === 'include' and $v->param) {
1262
+            foreach ($v->param as $r) {
1263
+                if (trim($r[0]) === 'doublons') {
1264
+                    return true;
1265
+                }
1266
+            }
1267
+        }
1268
+    }
1269
+
1270
+    return false;
1271 1271
 }
1272 1272
 
1273 1273
 // Prend en argument le texte d'un squelette, le nom de son fichier d'origine,
@@ -1286,354 +1286,354 @@  discard block
 block discarded – undo
1286 1286
 // En cas d'erreur, elle retournera un tableau des 2 premiers elements seulement
1287 1287
 
1288 1288
 function public_compiler_dist($squelette, $nom, $gram, $sourcefile, string $connect = '') {
1289
-	// Pre-traitement : reperer le charset du squelette, et le convertir
1290
-	// Bonus : supprime le BOM
1291
-	include_spip('inc/charsets');
1292
-	$squelette = transcoder_page($squelette);
1293
-
1294
-	// rendre inertes les echappements de #[](){}<>
1295
-	$i = 0;
1296
-	while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1297
-		$i++;
1298
-	}
1299
-	$squelette = preg_replace_callback(
1300
-		',\\\\([#[()\]{}<>]),',
1301
-		fn($a) => "$inerte-" . ord($a[1]) . '-',
1302
-		$squelette,
1303
-		-1,
1304
-		$esc
1305
-	);
1306
-
1307
-	$descr = [
1308
-		'nom' => $nom,
1309
-		'gram' => $gram,
1310
-		'sourcefile' => $sourcefile,
1311
-		'squelette' => $squelette
1312
-	];
1313
-
1314
-	// Phraser le squelette, selon sa grammaire
1315
-
1316
-	$boucles = [];
1317
-	$f = charger_fonction('phraser_' . $gram, 'public');
1318
-
1319
-	$squelette = $f($squelette, '', $boucles, $descr);
1320
-
1321
-	$boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1322
-
1323
-	// restituer les echappements
1324
-	if ($esc) {
1325
-		foreach ($boucles as $i => $boucle) {
1326
-			$boucles[$i]->return = preg_replace_callback(
1327
-				",$inerte-(\d+)-,",
1328
-				fn($a) => chr($a[1]),
1329
-				$boucle->return
1330
-			);
1331
-			$boucles[$i]->descr['squelette'] = preg_replace_callback(
1332
-				",$inerte-(\d+)-,",
1333
-				fn($a) => '\\\\' . chr($a[1]),
1334
-				$boucle->descr['squelette']
1335
-			);
1336
-		}
1337
-	}
1338
-
1339
-	$debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1340
-	if ($debug) {
1341
-		include_spip('public/decompiler');
1342
-		foreach ($boucles as $id => $boucle) {
1343
-			if ($id) {
1344
-				$decomp = "\n/* BOUCLE " .
1345
-					$boucle->type_requete .
1346
-					' ' .
1347
-					str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1348
-					($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1349
-					" */\n";
1350
-			} else {
1351
-				$decomp = ("\n/*\n" .
1352
-					str_replace('*/', '* /', public_decompiler($squelette, $gram))
1353
-					. "\n*/");
1354
-			}
1355
-			$boucles[$id]->return = $decomp . $boucle->return;
1356
-			$GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1357
-		}
1358
-	}
1359
-
1360
-	return $boucles;
1289
+    // Pre-traitement : reperer le charset du squelette, et le convertir
1290
+    // Bonus : supprime le BOM
1291
+    include_spip('inc/charsets');
1292
+    $squelette = transcoder_page($squelette);
1293
+
1294
+    // rendre inertes les echappements de #[](){}<>
1295
+    $i = 0;
1296
+    while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1297
+        $i++;
1298
+    }
1299
+    $squelette = preg_replace_callback(
1300
+        ',\\\\([#[()\]{}<>]),',
1301
+        fn($a) => "$inerte-" . ord($a[1]) . '-',
1302
+        $squelette,
1303
+        -1,
1304
+        $esc
1305
+    );
1306
+
1307
+    $descr = [
1308
+        'nom' => $nom,
1309
+        'gram' => $gram,
1310
+        'sourcefile' => $sourcefile,
1311
+        'squelette' => $squelette
1312
+    ];
1313
+
1314
+    // Phraser le squelette, selon sa grammaire
1315
+
1316
+    $boucles = [];
1317
+    $f = charger_fonction('phraser_' . $gram, 'public');
1318
+
1319
+    $squelette = $f($squelette, '', $boucles, $descr);
1320
+
1321
+    $boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1322
+
1323
+    // restituer les echappements
1324
+    if ($esc) {
1325
+        foreach ($boucles as $i => $boucle) {
1326
+            $boucles[$i]->return = preg_replace_callback(
1327
+                ",$inerte-(\d+)-,",
1328
+                fn($a) => chr($a[1]),
1329
+                $boucle->return
1330
+            );
1331
+            $boucles[$i]->descr['squelette'] = preg_replace_callback(
1332
+                ",$inerte-(\d+)-,",
1333
+                fn($a) => '\\\\' . chr($a[1]),
1334
+                $boucle->descr['squelette']
1335
+            );
1336
+        }
1337
+    }
1338
+
1339
+    $debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1340
+    if ($debug) {
1341
+        include_spip('public/decompiler');
1342
+        foreach ($boucles as $id => $boucle) {
1343
+            if ($id) {
1344
+                $decomp = "\n/* BOUCLE " .
1345
+                    $boucle->type_requete .
1346
+                    ' ' .
1347
+                    str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1348
+                    ($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1349
+                    " */\n";
1350
+            } else {
1351
+                $decomp = ("\n/*\n" .
1352
+                    str_replace('*/', '* /', public_decompiler($squelette, $gram))
1353
+                    . "\n*/");
1354
+            }
1355
+            $boucles[$id]->return = $decomp . $boucle->return;
1356
+            $GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1357
+        }
1358
+    }
1359
+
1360
+    return $boucles;
1361 1361
 }
1362 1362
 
1363 1363
 // Point d'entree pour arbre de syntaxe abstraite fourni en premier argument
1364 1364
 // Autres specifications comme ci-dessus
1365 1365
 
1366 1366
 function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, string $connect = '') {
1367
-	static $trouver_table;
1368
-	spip_timer('calcul_skel');
1369
-
1370
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1371
-		$GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1372
-		$GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1373
-
1374
-		if (!isset($GLOBALS['debug_objets']['principal'])) {
1375
-			$GLOBALS['debug_objets']['principal'] = $nom;
1376
-		}
1377
-	}
1378
-	foreach ($boucles as $id => $boucle) {
1379
-		$GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1380
-	}
1381
-	$descr['documents'] = compile_inclure_doublons($squelette);
1382
-
1383
-	// Demander la description des tables une fois pour toutes
1384
-	if (!$trouver_table) {
1385
-		$trouver_table = charger_fonction('trouver_table', 'base');
1386
-	}
1387
-
1388
-	// reperer si les doublons sont demandes
1389
-	// pour un inclure ou une boucle document
1390
-	// c'est utile a la fonction champs_traitements
1391
-	foreach ($boucles as $id => $boucle) {
1392
-		if (!($type = $boucle->type_requete)) {
1393
-			continue;
1394
-		}
1395
-		if (
1396
-			!$descr['documents'] and (
1397
-				(($type == 'documents') and $boucle->doublons) or
1398
-				compile_inclure_doublons($boucle->avant) or
1399
-				compile_inclure_doublons($boucle->apres) or
1400
-				compile_inclure_doublons($boucle->milieu) or
1401
-				compile_inclure_doublons($boucle->altern))
1402
-		) {
1403
-			$descr['documents'] = true;
1404
-		}
1405
-		if ($type != TYPE_RECURSIF) {
1406
-			if (!$boucles[$id]->sql_serveur and $connect) {
1407
-				$boucles[$id]->sql_serveur = $connect;
1408
-			}
1409
-
1410
-			// chercher dans les iterateurs du repertoire iterateur/
1411
-			if (
1412
-				$g = charger_fonction(
1413
-					preg_replace('/\W/', '_', $boucle->type_requete),
1414
-					'iterateur',
1415
-					true
1416
-				)
1417
-			) {
1418
-				$boucles[$id] = $g($boucle);
1419
-
1420
-				// sinon, en cas de requeteur d'un type predefini,
1421
-				// utiliser les informations donnees par le requeteur
1422
-				// cas "php:xx" et "data:xx".
1423
-			} else {
1424
-				if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1425
-					$requeteur($boucles, $boucle, $id);
1426
-
1427
-					// utiliser la description des champs transmis
1428
-				} else {
1429
-					$show = $trouver_table($type, $boucles[$id]->sql_serveur);
1430
-					// si la table n'existe pas avec le connecteur par defaut,
1431
-					// c'est peut etre une table qui necessite son connecteur dedie fourni
1432
-					// permet une ecriture allegee (GEO) -> (geo:GEO)
1433
-					if (
1434
-						!$show
1435
-						and $show = $trouver_table($type, strtolower($type))
1436
-					) {
1437
-						$boucles[$id]->sql_serveur = strtolower($type);
1438
-					}
1439
-					if ($show) {
1440
-						$boucles[$id]->show = $show;
1441
-						// recopie les infos les plus importantes
1442
-						$boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1443
-						$boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1444
-						$boucles[$id]->from[$x] = $nom_table = $show['table'];
1445
-						$boucles[$id]->iterateur = 'SQL';
1446
-
1447
-						if (empty($boucles[$id]->descr)) {
1448
-							$boucles[$id]->descr = &$descr;
1449
-						}
1450
-						if (
1451
-							(!$boucles[$id]->jointures)
1452
-							and is_array($show['tables_jointures'])
1453
-							and count($x = $show['tables_jointures'])
1454
-						) {
1455
-							$boucles[$id]->jointures = $x;
1456
-						}
1457
-						if ($boucles[$id]->jointures_explicites) {
1458
-							$jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1459
-							while ($j = array_pop($jointures)) {
1460
-								array_unshift($boucles[$id]->jointures, $j);
1461
-							}
1462
-						}
1463
-					} else {
1464
-						// Pas une erreur si la table est optionnelle
1465
-						if ($boucles[$id]->table_optionnelle) {
1466
-							$boucles[$id]->type_requete = '';
1467
-						} else {
1468
-							$boucles[$id]->type_requete = false;
1469
-							$boucle = $boucles[$id];
1470
-							$x = (!$boucle->sql_serveur ? '' :
1471
-									($boucle->sql_serveur . ':')) .
1472
-								$type;
1473
-							$msg = [
1474
-								'zbug_table_inconnue',
1475
-								['table' => $x]
1476
-							];
1477
-							erreur_squelette($msg, $boucle);
1478
-						}
1479
-					}
1480
-				}
1481
-			}
1482
-		}
1483
-	}
1484
-
1485
-	// Commencer par reperer les boucles appelees explicitement
1486
-	// car elles indexent les arguments de maniere derogatoire
1487
-	foreach ($boucles as $id => $boucle) {
1488
-		if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1489
-			$boucles[$id]->descr = &$descr;
1490
-			$rec = &$boucles[$boucle->param[0]];
1491
-			if (!$rec) {
1492
-				$msg = [
1493
-					'zbug_boucle_recursive_undef',
1494
-					['nom' => $boucle->param[0]]
1495
-				];
1496
-				erreur_squelette($msg, $boucle);
1497
-				$boucles[$id]->type_requete = false;
1498
-			} else {
1499
-				$rec->externe = $id;
1500
-				$descr['id_mere'] = $id;
1501
-				$boucles[$id]->return =
1502
-					calculer_liste(
1503
-						[$rec],
1504
-						$descr,
1505
-						$boucles,
1506
-						$boucle->param
1507
-					);
1508
-			}
1509
-		}
1510
-	}
1511
-	foreach ($boucles as $id => $boucle) {
1512
-		$id = strval($id); // attention au type dans index_pile
1513
-		$type = $boucle->type_requete;
1514
-		if ($type and $type != TYPE_RECURSIF) {
1515
-			$res = '';
1516
-			if ($boucle->param) {
1517
-				// retourne un tableau en cas d'erreur
1518
-				$res = calculer_criteres($id, $boucles);
1519
-			}
1520
-			$descr['id_mere'] = $id;
1521
-			$boucles[$id]->return =
1522
-				calculer_liste(
1523
-					$boucle->milieu,
1524
-					$descr,
1525
-					$boucles,
1526
-					$id
1527
-				);
1528
-			// Si les criteres se sont mal compiles
1529
-			// ne pas tenter d'assembler le code final
1530
-			// (mais compiler le corps pour detection d'erreurs)
1531
-			if (is_array($res)) {
1532
-				$boucles[$id]->type_requete = false;
1533
-			}
1534
-		}
1535
-	}
1536
-
1537
-	// idem pour la racine
1538
-	$descr['id_mere'] = '';
1539
-	$corps = calculer_liste($squelette, $descr, $boucles);
1540
-
1541
-
1542
-	// Calcul du corps de toutes les fonctions PHP,
1543
-	// en particulier les requetes SQL et TOTAL_BOUCLE
1544
-	// de'terminables seulement maintenant
1545
-
1546
-	foreach ($boucles as $id => $boucle) {
1547
-		$boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1548
-		if ($boucle->return === false) {
1549
-			$corps = false;
1550
-			continue;
1551
-		}
1552
-		// appeler la fonction de definition de la boucle
1553
-
1554
-		if ($req = $boucle->type_requete) {
1555
-			// boucle personnalisée ?
1556
-			$table = strtoupper($boucle->type_requete);
1557
-			$serveur = strtolower($boucle->sql_serveur);
1558
-			if (
1559
-				// fonction de boucle avec serveur & table
1560
-				(!$serveur or
1561
-					((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1562
-						and (!function_exists($f = $f . '_dist'))
1563
-					)
1564
-				)
1565
-				// fonction de boucle avec table
1566
-				and (!function_exists($f = 'boucle_' . $table))
1567
-				and (!function_exists($f = $f . '_dist'))
1568
-			) {
1569
-				// fonction de boucle standard
1570
-				if (!function_exists($f = 'boucle_DEFAUT')) {
1571
-					$f = 'boucle_DEFAUT_dist';
1572
-				}
1573
-			}
1574
-
1575
-			$req = "\n\n\tstatic \$command = array();\n\t" .
1576
-				"static \$connect;\n\t" .
1577
-				"\$command['connect'] = \$connect = " .
1578
-				_q($boucle->sql_serveur) .
1579
-				';' .
1580
-				$f($id, $boucles);
1581
-		} else {
1582
-			$req = ("\n\treturn '';");
1583
-		}
1584
-
1585
-		$boucles[$id]->return =
1586
-			"\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1587
-			'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1588
-			$req .
1589
-			"\n}\n";
1590
-	}
1591
-
1592
-	// Au final, si le corps ou un critere au moins s'est mal compile
1593
-	// retourner False, sinon inserer leur decompilation
1594
-	if (is_bool($corps)) {
1595
-		return false;
1596
-	}
1597
-
1598
-	$principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1367
+    static $trouver_table;
1368
+    spip_timer('calcul_skel');
1369
+
1370
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1371
+        $GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1372
+        $GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1373
+
1374
+        if (!isset($GLOBALS['debug_objets']['principal'])) {
1375
+            $GLOBALS['debug_objets']['principal'] = $nom;
1376
+        }
1377
+    }
1378
+    foreach ($boucles as $id => $boucle) {
1379
+        $GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1380
+    }
1381
+    $descr['documents'] = compile_inclure_doublons($squelette);
1382
+
1383
+    // Demander la description des tables une fois pour toutes
1384
+    if (!$trouver_table) {
1385
+        $trouver_table = charger_fonction('trouver_table', 'base');
1386
+    }
1387
+
1388
+    // reperer si les doublons sont demandes
1389
+    // pour un inclure ou une boucle document
1390
+    // c'est utile a la fonction champs_traitements
1391
+    foreach ($boucles as $id => $boucle) {
1392
+        if (!($type = $boucle->type_requete)) {
1393
+            continue;
1394
+        }
1395
+        if (
1396
+            !$descr['documents'] and (
1397
+                (($type == 'documents') and $boucle->doublons) or
1398
+                compile_inclure_doublons($boucle->avant) or
1399
+                compile_inclure_doublons($boucle->apres) or
1400
+                compile_inclure_doublons($boucle->milieu) or
1401
+                compile_inclure_doublons($boucle->altern))
1402
+        ) {
1403
+            $descr['documents'] = true;
1404
+        }
1405
+        if ($type != TYPE_RECURSIF) {
1406
+            if (!$boucles[$id]->sql_serveur and $connect) {
1407
+                $boucles[$id]->sql_serveur = $connect;
1408
+            }
1409
+
1410
+            // chercher dans les iterateurs du repertoire iterateur/
1411
+            if (
1412
+                $g = charger_fonction(
1413
+                    preg_replace('/\W/', '_', $boucle->type_requete),
1414
+                    'iterateur',
1415
+                    true
1416
+                )
1417
+            ) {
1418
+                $boucles[$id] = $g($boucle);
1419
+
1420
+                // sinon, en cas de requeteur d'un type predefini,
1421
+                // utiliser les informations donnees par le requeteur
1422
+                // cas "php:xx" et "data:xx".
1423
+            } else {
1424
+                if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1425
+                    $requeteur($boucles, $boucle, $id);
1426
+
1427
+                    // utiliser la description des champs transmis
1428
+                } else {
1429
+                    $show = $trouver_table($type, $boucles[$id]->sql_serveur);
1430
+                    // si la table n'existe pas avec le connecteur par defaut,
1431
+                    // c'est peut etre une table qui necessite son connecteur dedie fourni
1432
+                    // permet une ecriture allegee (GEO) -> (geo:GEO)
1433
+                    if (
1434
+                        !$show
1435
+                        and $show = $trouver_table($type, strtolower($type))
1436
+                    ) {
1437
+                        $boucles[$id]->sql_serveur = strtolower($type);
1438
+                    }
1439
+                    if ($show) {
1440
+                        $boucles[$id]->show = $show;
1441
+                        // recopie les infos les plus importantes
1442
+                        $boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1443
+                        $boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1444
+                        $boucles[$id]->from[$x] = $nom_table = $show['table'];
1445
+                        $boucles[$id]->iterateur = 'SQL';
1446
+
1447
+                        if (empty($boucles[$id]->descr)) {
1448
+                            $boucles[$id]->descr = &$descr;
1449
+                        }
1450
+                        if (
1451
+                            (!$boucles[$id]->jointures)
1452
+                            and is_array($show['tables_jointures'])
1453
+                            and count($x = $show['tables_jointures'])
1454
+                        ) {
1455
+                            $boucles[$id]->jointures = $x;
1456
+                        }
1457
+                        if ($boucles[$id]->jointures_explicites) {
1458
+                            $jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1459
+                            while ($j = array_pop($jointures)) {
1460
+                                array_unshift($boucles[$id]->jointures, $j);
1461
+                            }
1462
+                        }
1463
+                    } else {
1464
+                        // Pas une erreur si la table est optionnelle
1465
+                        if ($boucles[$id]->table_optionnelle) {
1466
+                            $boucles[$id]->type_requete = '';
1467
+                        } else {
1468
+                            $boucles[$id]->type_requete = false;
1469
+                            $boucle = $boucles[$id];
1470
+                            $x = (!$boucle->sql_serveur ? '' :
1471
+                                    ($boucle->sql_serveur . ':')) .
1472
+                                $type;
1473
+                            $msg = [
1474
+                                'zbug_table_inconnue',
1475
+                                ['table' => $x]
1476
+                            ];
1477
+                            erreur_squelette($msg, $boucle);
1478
+                        }
1479
+                    }
1480
+                }
1481
+            }
1482
+        }
1483
+    }
1484
+
1485
+    // Commencer par reperer les boucles appelees explicitement
1486
+    // car elles indexent les arguments de maniere derogatoire
1487
+    foreach ($boucles as $id => $boucle) {
1488
+        if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1489
+            $boucles[$id]->descr = &$descr;
1490
+            $rec = &$boucles[$boucle->param[0]];
1491
+            if (!$rec) {
1492
+                $msg = [
1493
+                    'zbug_boucle_recursive_undef',
1494
+                    ['nom' => $boucle->param[0]]
1495
+                ];
1496
+                erreur_squelette($msg, $boucle);
1497
+                $boucles[$id]->type_requete = false;
1498
+            } else {
1499
+                $rec->externe = $id;
1500
+                $descr['id_mere'] = $id;
1501
+                $boucles[$id]->return =
1502
+                    calculer_liste(
1503
+                        [$rec],
1504
+                        $descr,
1505
+                        $boucles,
1506
+                        $boucle->param
1507
+                    );
1508
+            }
1509
+        }
1510
+    }
1511
+    foreach ($boucles as $id => $boucle) {
1512
+        $id = strval($id); // attention au type dans index_pile
1513
+        $type = $boucle->type_requete;
1514
+        if ($type and $type != TYPE_RECURSIF) {
1515
+            $res = '';
1516
+            if ($boucle->param) {
1517
+                // retourne un tableau en cas d'erreur
1518
+                $res = calculer_criteres($id, $boucles);
1519
+            }
1520
+            $descr['id_mere'] = $id;
1521
+            $boucles[$id]->return =
1522
+                calculer_liste(
1523
+                    $boucle->milieu,
1524
+                    $descr,
1525
+                    $boucles,
1526
+                    $id
1527
+                );
1528
+            // Si les criteres se sont mal compiles
1529
+            // ne pas tenter d'assembler le code final
1530
+            // (mais compiler le corps pour detection d'erreurs)
1531
+            if (is_array($res)) {
1532
+                $boucles[$id]->type_requete = false;
1533
+            }
1534
+        }
1535
+    }
1536
+
1537
+    // idem pour la racine
1538
+    $descr['id_mere'] = '';
1539
+    $corps = calculer_liste($squelette, $descr, $boucles);
1540
+
1541
+
1542
+    // Calcul du corps de toutes les fonctions PHP,
1543
+    // en particulier les requetes SQL et TOTAL_BOUCLE
1544
+    // de'terminables seulement maintenant
1545
+
1546
+    foreach ($boucles as $id => $boucle) {
1547
+        $boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1548
+        if ($boucle->return === false) {
1549
+            $corps = false;
1550
+            continue;
1551
+        }
1552
+        // appeler la fonction de definition de la boucle
1553
+
1554
+        if ($req = $boucle->type_requete) {
1555
+            // boucle personnalisée ?
1556
+            $table = strtoupper($boucle->type_requete);
1557
+            $serveur = strtolower($boucle->sql_serveur);
1558
+            if (
1559
+                // fonction de boucle avec serveur & table
1560
+                (!$serveur or
1561
+                    ((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1562
+                        and (!function_exists($f = $f . '_dist'))
1563
+                    )
1564
+                )
1565
+                // fonction de boucle avec table
1566
+                and (!function_exists($f = 'boucle_' . $table))
1567
+                and (!function_exists($f = $f . '_dist'))
1568
+            ) {
1569
+                // fonction de boucle standard
1570
+                if (!function_exists($f = 'boucle_DEFAUT')) {
1571
+                    $f = 'boucle_DEFAUT_dist';
1572
+                }
1573
+            }
1574
+
1575
+            $req = "\n\n\tstatic \$command = array();\n\t" .
1576
+                "static \$connect;\n\t" .
1577
+                "\$command['connect'] = \$connect = " .
1578
+                _q($boucle->sql_serveur) .
1579
+                ';' .
1580
+                $f($id, $boucles);
1581
+        } else {
1582
+            $req = ("\n\treturn '';");
1583
+        }
1584
+
1585
+        $boucles[$id]->return =
1586
+            "\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1587
+            '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1588
+            $req .
1589
+            "\n}\n";
1590
+    }
1591
+
1592
+    // Au final, si le corps ou un critere au moins s'est mal compile
1593
+    // retourner False, sinon inserer leur decompilation
1594
+    if (is_bool($corps)) {
1595
+        return false;
1596
+    }
1597
+
1598
+    $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1599 1599
 '
1600
-		// reporter de maniere securisee les doublons inclus
1601
-		. '
1600
+        // reporter de maniere securisee les doublons inclus
1601
+        . '
1602 1602
 	if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"]))
1603 1603
 		$doublons = nettoyer_env_doublons($Pile[0]["doublons"]);
1604 1604
 
1605 1605
 	$connect = ' .
1606
-		_q($connect) . ';
1606
+        _q($connect) . ';
1607 1607
 	$page = ' .
1608
-		// ATTENTION, le calcul de l'expression $corps affectera $Cache
1609
-		// c'est pourquoi on l'affecte a la variable auxiliaire $page.
1610
-		// avant de referencer $Cache
1611
-		$corps . ';
1608
+        // ATTENTION, le calcul de l'expression $corps affectera $Cache
1609
+        // c'est pourquoi on l'affecte a la variable auxiliaire $page.
1610
+        // avant de referencer $Cache
1611
+        $corps . ';
1612 1612
 
1613 1613
 	return analyse_resultat_skel(' . var_export($nom, true)
1614
-		. ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1614
+        . ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1615 1615
 }';
1616 1616
 
1617
-	$secondes = spip_timer('calcul_skel');
1618
-	spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1619
-	// $connect n'est pas sûr : on nettoie
1620
-	$connect = preg_replace(',[^\w],', '', $connect);
1617
+    $secondes = spip_timer('calcul_skel');
1618
+    spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1619
+    // $connect n'est pas sûr : on nettoie
1620
+    $connect = preg_replace(',[^\w],', '', $connect);
1621 1621
 
1622
-	// Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1623
-	$code = new Boucle();
1624
-	$code->descr = $descr;
1625
-	$code->return = '
1622
+    // Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1623
+    $code = new Boucle();
1624
+    $code->descr = $descr;
1625
+    $code->return = '
1626 1626
 //
1627 1627
 // Fonction principale du squelette ' .
1628
-		$sourcefile .
1629
-		($connect ? " pour $connect" : '') .
1630
-		(!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1631
-		"\n//\n" .
1632
-		$principal;
1628
+        $sourcefile .
1629
+        ($connect ? " pour $connect" : '') .
1630
+        (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1631
+        "\n//\n" .
1632
+        $principal;
1633 1633
 
1634
-	$boucles[''] = $code;
1634
+    $boucles[''] = $code;
1635 1635
 
1636
-	return $boucles;
1636
+    return $boucles;
1637 1637
 }
1638 1638
 
1639 1639
 
@@ -1650,18 +1650,18 @@  discard block
 block discarded – undo
1650 1650
  *
1651 1651
  **/
1652 1652
 function requeteur_php_dist(&$boucles, &$boucle, &$id) {
1653
-	if (class_exists($boucle->type_requete)) {
1654
-		$g = charger_fonction('php', 'iterateur');
1655
-		$boucles[$id] = $g($boucle, $boucle->type_requete);
1656
-	} else {
1657
-		$x = $boucle->type_requete;
1658
-		$boucle->type_requete = false;
1659
-		$msg = [
1660
-			'zbug_iterateur_inconnu',
1661
-			['iterateur' => $x]
1662
-		];
1663
-		erreur_squelette($msg, $boucle);
1664
-	}
1653
+    if (class_exists($boucle->type_requete)) {
1654
+        $g = charger_fonction('php', 'iterateur');
1655
+        $boucles[$id] = $g($boucle, $boucle->type_requete);
1656
+    } else {
1657
+        $x = $boucle->type_requete;
1658
+        $boucle->type_requete = false;
1659
+        $msg = [
1660
+            'zbug_iterateur_inconnu',
1661
+            ['iterateur' => $x]
1662
+        ];
1663
+        erreur_squelette($msg, $boucle);
1664
+    }
1665 1665
 }
1666 1666
 
1667 1667
 
@@ -1679,22 +1679,22 @@  discard block
 block discarded – undo
1679 1679
  *
1680 1680
  **/
1681 1681
 function requeteur_data_dist(&$boucles, &$boucle, &$id) {
1682
-	include_spip('iterateur/data');
1683
-	if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1684
-		$g = charger_fonction('data', 'iterateur');
1685
-		$boucles[$id] = $g($boucle);
1686
-		// from[0] stocke le type de data (rss, yql, ...)
1687
-		$boucles[$id]->from[] = $boucle->type_requete;
1688
-	} else {
1689
-		$x = $boucle->type_requete;
1690
-		$boucle->type_requete = false;
1691
-		$msg = [
1692
-			'zbug_requeteur_inconnu',
1693
-			[
1694
-				'requeteur' => 'data',
1695
-				'type' => $x
1696
-			]
1697
-		];
1698
-		erreur_squelette($msg, $boucle);
1699
-	}
1682
+    include_spip('iterateur/data');
1683
+    if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1684
+        $g = charger_fonction('data', 'iterateur');
1685
+        $boucles[$id] = $g($boucle);
1686
+        // from[0] stocke le type de data (rss, yql, ...)
1687
+        $boucles[$id]->from[] = $boucle->type_requete;
1688
+    } else {
1689
+        $x = $boucle->type_requete;
1690
+        $boucle->type_requete = false;
1691
+        $msg = [
1692
+            'zbug_requeteur_inconnu',
1693
+            [
1694
+                'requeteur' => 'data',
1695
+                'type' => $x
1696
+            ]
1697
+        ];
1698
+        erreur_squelette($msg, $boucle);
1699
+    }
1700 1700
 }
Please login to merge, or discard this patch.
ecrire/public/phraser_html.php 1 patch
Indentation   +1032 added lines, -1032 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
  **/
21 21
 
22 22
 if (!defined('_ECRIRE_INC_VERSION')) {
23
-	return;
23
+    return;
24 24
 }
25 25
 
26 26
 /** Début de la partie principale d'une boucle */
@@ -64,82 +64,82 @@  discard block
 block discarded – undo
64 64
 
65 65
 function phraser_inclure($texte, $ligne, $result) {
66 66
 
67
-	while (preg_match(BALISE_INCLURE, $texte, $match)) {
68
-		$match = array_pad($match, 3, null);
69
-		$p = strpos($texte, (string) $match[0]);
70
-		$debut = substr($texte, 0, $p);
71
-		if ($p) {
72
-			$result = phraser_idiomes($debut, $ligne, $result);
73
-		}
74
-		$ligne += substr_count($debut, "\n");
75
-		$champ = new Inclure();
76
-		$champ->ligne = $ligne;
77
-		$ligne += substr_count($match[0], "\n");
78
-		$fichier = $match[2];
79
-		# assurer ici la migration .php3 => .php
80
-		# et de l'ancienne syntaxe INCLURE(page.php3) devenue surperflue
81
-		if ($fichier and preg_match(',^(.*[.]php)3$,', $fichier, $r)) {
82
-			$fichier = $r[1];
83
-		}
84
-		$champ->texte = ($fichier !== 'page.php') ? $fichier : '';
85
-		$texte = substr($texte, $p + strlen($match[0]));
86
-		// on assimile {var=val} a une liste de un argument sans fonction
87
-		$pos_apres = 0;
88
-		phraser_args($texte, '/>', '', $result, $champ, $pos_apres);
89
-		if (!$champ->texte or (is_countable($champ->param) ? count($champ->param) : 0) > 1) {
90
-			if (!function_exists('normaliser_inclure')) {
91
-				include_spip('public/normaliser');
92
-			}
93
-			normaliser_inclure($champ);
94
-		}
95
-		$texte = substr($texte, strpos($texte, '>', $pos_apres) + 1);
96
-		$texte = preg_replace(',^</INCLU[DR]E>,', '', $texte);
97
-		$result[] = $champ;
98
-	}
99
-
100
-	return (($texte === '') ? $result : phraser_idiomes($texte, $ligne, $result));
67
+    while (preg_match(BALISE_INCLURE, $texte, $match)) {
68
+        $match = array_pad($match, 3, null);
69
+        $p = strpos($texte, (string) $match[0]);
70
+        $debut = substr($texte, 0, $p);
71
+        if ($p) {
72
+            $result = phraser_idiomes($debut, $ligne, $result);
73
+        }
74
+        $ligne += substr_count($debut, "\n");
75
+        $champ = new Inclure();
76
+        $champ->ligne = $ligne;
77
+        $ligne += substr_count($match[0], "\n");
78
+        $fichier = $match[2];
79
+        # assurer ici la migration .php3 => .php
80
+        # et de l'ancienne syntaxe INCLURE(page.php3) devenue surperflue
81
+        if ($fichier and preg_match(',^(.*[.]php)3$,', $fichier, $r)) {
82
+            $fichier = $r[1];
83
+        }
84
+        $champ->texte = ($fichier !== 'page.php') ? $fichier : '';
85
+        $texte = substr($texte, $p + strlen($match[0]));
86
+        // on assimile {var=val} a une liste de un argument sans fonction
87
+        $pos_apres = 0;
88
+        phraser_args($texte, '/>', '', $result, $champ, $pos_apres);
89
+        if (!$champ->texte or (is_countable($champ->param) ? count($champ->param) : 0) > 1) {
90
+            if (!function_exists('normaliser_inclure')) {
91
+                include_spip('public/normaliser');
92
+            }
93
+            normaliser_inclure($champ);
94
+        }
95
+        $texte = substr($texte, strpos($texte, '>', $pos_apres) + 1);
96
+        $texte = preg_replace(',^</INCLU[DR]E>,', '', $texte);
97
+        $result[] = $champ;
98
+    }
99
+
100
+    return (($texte === '') ? $result : phraser_idiomes($texte, $ligne, $result));
101 101
 }
102 102
 
103 103
 function phraser_polyglotte($texte, $ligne, $result) {
104 104
 
105
-	if (preg_match_all(BALISE_POLYGLOTTE, $texte, $m, PREG_SET_ORDER)) {
106
-		foreach ($m as $match) {
107
-			$p = strpos($texte, (string) $match[0]);
108
-			$debut = substr($texte, 0, $p);
109
-			if ($p) {
110
-				$champ = new Texte();
111
-				$champ->texte = $debut;
112
-				$champ->ligne = $ligne;
113
-				$result[] = $champ;
114
-				$ligne += substr_count($champ->texte, "\n");
115
-			}
116
-
117
-			$champ = new Polyglotte();
118
-			$champ->ligne = $ligne;
119
-			$ligne += substr_count($match[0], "\n");
120
-			$lang = '';
121
-			$bloc = $match[1];
122
-			$texte = substr($texte, $p + strlen($match[0]));
123
-			while (preg_match('/^[[:space:]]*([^[{]*)[[:space:]]*[[{]([a-z_]+)[]}](.*)$/si', $bloc, $regs)) {
124
-				$trad = $regs[1];
125
-				if ($trad or $lang) {
126
-					$champ->traductions[$lang] = $trad;
127
-				}
128
-				$lang = $regs[2];
129
-				$bloc = $regs[3];
130
-			}
131
-			$champ->traductions[$lang] = $bloc;
132
-			$result[] = $champ;
133
-		}
134
-	}
135
-	if ($texte !== '') {
136
-		$champ = new Texte();
137
-		$champ->texte = $texte;
138
-		$champ->ligne = $ligne;
139
-		$result[] = $champ;
140
-	}
141
-
142
-	return $result;
105
+    if (preg_match_all(BALISE_POLYGLOTTE, $texte, $m, PREG_SET_ORDER)) {
106
+        foreach ($m as $match) {
107
+            $p = strpos($texte, (string) $match[0]);
108
+            $debut = substr($texte, 0, $p);
109
+            if ($p) {
110
+                $champ = new Texte();
111
+                $champ->texte = $debut;
112
+                $champ->ligne = $ligne;
113
+                $result[] = $champ;
114
+                $ligne += substr_count($champ->texte, "\n");
115
+            }
116
+
117
+            $champ = new Polyglotte();
118
+            $champ->ligne = $ligne;
119
+            $ligne += substr_count($match[0], "\n");
120
+            $lang = '';
121
+            $bloc = $match[1];
122
+            $texte = substr($texte, $p + strlen($match[0]));
123
+            while (preg_match('/^[[:space:]]*([^[{]*)[[:space:]]*[[{]([a-z_]+)[]}](.*)$/si', $bloc, $regs)) {
124
+                $trad = $regs[1];
125
+                if ($trad or $lang) {
126
+                    $champ->traductions[$lang] = $trad;
127
+                }
128
+                $lang = $regs[2];
129
+                $bloc = $regs[3];
130
+            }
131
+            $champ->traductions[$lang] = $bloc;
132
+            $result[] = $champ;
133
+        }
134
+    }
135
+    if ($texte !== '') {
136
+        $champ = new Texte();
137
+        $champ->texte = $texte;
138
+        $champ->ligne = $ligne;
139
+        $result[] = $champ;
140
+    }
141
+
142
+    return $result;
143 143
 }
144 144
 
145 145
 
@@ -161,43 +161,43 @@  discard block
 block discarded – undo
161 161
  * @return array
162 162
  **/
163 163
 function phraser_idiomes($texte, $ligne, $result) {
164
-	while (preg_match(BALISE_IDIOMES, $texte, $match)) {
165
-		$match = array_pad($match, 8, null);
166
-		$p = strpos($texte, (string) $match[0]);
167
-		$ko = (!$match[3] && ($match[5][0] !== '='));
168
-		$debut = substr($texte, 0, $p + ($ko ? strlen($match[0]) : 0));
169
-		if ($debut) {
170
-			$result = phraser_champs($debut, $ligne, $result);
171
-		}
172
-		$texte = substr($texte, $p + strlen($match[0]));
173
-		$ligne += substr_count($debut, "\n");
174
-		if ($ko) {
175
-			continue;
176
-		} // faux idiome
177
-		$champ = new Idiome();
178
-		$champ->ligne = $ligne;
179
-		$ligne += substr_count($match[0], "\n");
180
-		// Stocker les arguments de la balise de traduction
181
-		$args = [];
182
-		$largs = $match[5];
183
-		while (preg_match(BALISE_IDIOMES_ARGS, $largs, $r)) {
184
-			$args[$r[1]] = phraser_champs($r[2], 0, []);
185
-			$largs = substr($largs, strlen($r[0]));
186
-		}
187
-		$champ->arg = $args;
188
-		$champ->nom_champ = strtolower($match[3]);
189
-		$champ->module = $match[2];
190
-		// pas d'imbrication pour les filtres sur langue
191
-		$pos_apres = 0;
192
-		phraser_args($match[7] ?? '', ':', '', [], $champ, $pos_apres);
193
-		$champ->apres = substr($match[7] ?? '', $pos_apres);
194
-		$result[] = $champ;
195
-	}
196
-	if ($texte !== '') {
197
-		$result = phraser_champs($texte, $ligne, $result);
198
-	}
199
-
200
-	return $result;
164
+    while (preg_match(BALISE_IDIOMES, $texte, $match)) {
165
+        $match = array_pad($match, 8, null);
166
+        $p = strpos($texte, (string) $match[0]);
167
+        $ko = (!$match[3] && ($match[5][0] !== '='));
168
+        $debut = substr($texte, 0, $p + ($ko ? strlen($match[0]) : 0));
169
+        if ($debut) {
170
+            $result = phraser_champs($debut, $ligne, $result);
171
+        }
172
+        $texte = substr($texte, $p + strlen($match[0]));
173
+        $ligne += substr_count($debut, "\n");
174
+        if ($ko) {
175
+            continue;
176
+        } // faux idiome
177
+        $champ = new Idiome();
178
+        $champ->ligne = $ligne;
179
+        $ligne += substr_count($match[0], "\n");
180
+        // Stocker les arguments de la balise de traduction
181
+        $args = [];
182
+        $largs = $match[5];
183
+        while (preg_match(BALISE_IDIOMES_ARGS, $largs, $r)) {
184
+            $args[$r[1]] = phraser_champs($r[2], 0, []);
185
+            $largs = substr($largs, strlen($r[0]));
186
+        }
187
+        $champ->arg = $args;
188
+        $champ->nom_champ = strtolower($match[3]);
189
+        $champ->module = $match[2];
190
+        // pas d'imbrication pour les filtres sur langue
191
+        $pos_apres = 0;
192
+        phraser_args($match[7] ?? '', ':', '', [], $champ, $pos_apres);
193
+        $champ->apres = substr($match[7] ?? '', $pos_apres);
194
+        $result[] = $champ;
195
+    }
196
+    if ($texte !== '') {
197
+        $result = phraser_champs($texte, $ligne, $result);
198
+    }
199
+
200
+    return $result;
201 201
 }
202 202
 
203 203
 /**
@@ -215,47 +215,47 @@  discard block
 block discarded – undo
215 215
  * @return array
216 216
  **/
217 217
 function phraser_champs($texte, $ligne, $result) {
218
-	while (preg_match('/' . NOM_DE_CHAMP . '/S', $texte, $match)) {
219
-		$p = strpos($texte, (string) $match[0]);
220
-		// texte après la balise
221
-		$suite = substr($texte, $p + strlen($match[0]));
222
-
223
-		$debut = substr($texte, 0, $p);
224
-		if ($p) {
225
-			$result = phraser_polyglotte($debut, $ligne, $result);
226
-		}
227
-		$ligne += substr_count($debut, "\n");
228
-		$champ = new Champ();
229
-		$champ->ligne = $ligne;
230
-		$ligne += substr_count($match[0], "\n");
231
-		$champ->nom_boucle = $match[2];
232
-		$champ->nom_champ = $match[3];
233
-		$champ->etoile = $match[5];
234
-
235
-		if ($suite and $suite[0] == '{') {
236
-			phraser_arg($suite, '', [], $champ);
237
-			// ce ltrim est une ereur de conception
238
-			// mais on le conserve par souci de compatibilite
239
-			$texte = ltrim($suite);
240
-			// Il faudrait le normaliser dans l'arbre de syntaxe abstraite
241
-			// pour faire sauter ce cas particulier a la decompilation.
242
-			/* Ce qui suit est malheureusement incomplet pour cela:
218
+    while (preg_match('/' . NOM_DE_CHAMP . '/S', $texte, $match)) {
219
+        $p = strpos($texte, (string) $match[0]);
220
+        // texte après la balise
221
+        $suite = substr($texte, $p + strlen($match[0]));
222
+
223
+        $debut = substr($texte, 0, $p);
224
+        if ($p) {
225
+            $result = phraser_polyglotte($debut, $ligne, $result);
226
+        }
227
+        $ligne += substr_count($debut, "\n");
228
+        $champ = new Champ();
229
+        $champ->ligne = $ligne;
230
+        $ligne += substr_count($match[0], "\n");
231
+        $champ->nom_boucle = $match[2];
232
+        $champ->nom_champ = $match[3];
233
+        $champ->etoile = $match[5];
234
+
235
+        if ($suite and $suite[0] == '{') {
236
+            phraser_arg($suite, '', [], $champ);
237
+            // ce ltrim est une ereur de conception
238
+            // mais on le conserve par souci de compatibilite
239
+            $texte = ltrim($suite);
240
+            // Il faudrait le normaliser dans l'arbre de syntaxe abstraite
241
+            // pour faire sauter ce cas particulier a la decompilation.
242
+            /* Ce qui suit est malheureusement incomplet pour cela:
243 243
 			if ($n = (strlen($suite) - strlen($texte))) {
244 244
 				$champ->apres = array(new Texte);
245 245
 				$champ->apres[0]->texte = substr($suite,0,$n);
246 246
 			}
247 247
 			*/
248
-		} else {
249
-			$texte = $suite;
250
-		}
251
-		phraser_vieux($champ);
252
-		$result[] = $champ;
253
-	}
254
-	if ($texte !== '') {
255
-		$result = phraser_polyglotte($texte, $ligne, $result);
256
-	}
257
-
258
-	return $result;
248
+        } else {
249
+            $texte = $suite;
250
+        }
251
+        phraser_vieux($champ);
252
+        $result[] = $champ;
253
+    }
254
+    if ($texte !== '') {
255
+        $result = phraser_polyglotte($texte, $ligne, $result);
256
+    }
257
+
258
+    return $result;
259 259
 }
260 260
 
261 261
 // Gestion des imbrications:
@@ -264,15 +264,15 @@  discard block
 block discarded – undo
264 264
 // on recommence tant qu'il y a des [...] en substituant a l'appel suivant
265 265
 
266 266
 function phraser_champs_etendus($texte, $ligne, $result) {
267
-	if ($texte === '') {
268
-		return $result;
269
-	}
270
-	$sep = '##';
271
-	while (strpos($texte, (string) $sep) !== false) {
272
-		$sep .= '#';
273
-	}
274
-
275
-	return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, []));
267
+    if ($texte === '') {
268
+        return $result;
269
+    }
270
+    $sep = '##';
271
+    while (strpos($texte, (string) $sep) !== false) {
272
+        $sep .= '#';
273
+    }
274
+
275
+    return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, []));
276 276
 }
277 277
 
278 278
 /**
@@ -291,275 +291,275 @@  discard block
 block discarded – undo
291 291
  * @return array
292 292
  */
293 293
 function phraser_args(string $texte, $fin, $sep, $result, &$pointeur_champ, &$pos_debut) {
294
-	$length = strlen($texte);
295
-	while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
296
-		$pos_debut++;
297
-	}
298
-	while (($pos_debut < $length) && strpos($fin, $texte[$pos_debut]) === false) {
299
-		// phraser_arg modifie directement le $texte, on fait donc avec ici en passant par une sous chaine
300
-		$st = substr($texte, $pos_debut);
301
-		$result = phraser_arg($st, $sep, $result, $pointeur_champ);
302
-		$pos_debut = $length - strlen($st);
303
-		while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
304
-			$pos_debut++;
305
-		}
306
-	}
307
-
308
-	return $result;
294
+    $length = strlen($texte);
295
+    while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
296
+        $pos_debut++;
297
+    }
298
+    while (($pos_debut < $length) && strpos($fin, $texte[$pos_debut]) === false) {
299
+        // phraser_arg modifie directement le $texte, on fait donc avec ici en passant par une sous chaine
300
+        $st = substr($texte, $pos_debut);
301
+        $result = phraser_arg($st, $sep, $result, $pointeur_champ);
302
+        $pos_debut = $length - strlen($st);
303
+        while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
304
+            $pos_debut++;
305
+        }
306
+    }
307
+
308
+    return $result;
309 309
 }
310 310
 
311 311
 function phraser_arg(&$texte, $sep, $result, &$pointeur_champ) {
312
-	preg_match(',^(\|?[^}{)|]*)(.*)$,ms', $texte, $match);
313
-	$suite = ltrim($match[2]);
314
-	$fonc = trim($match[1]);
315
-	if ($fonc && $fonc[0] == '|') {
316
-		$fonc = ltrim(substr($fonc, 1));
317
-	}
318
-	$res = [$fonc];
319
-	$err_f = '';
320
-	// cas du filtre sans argument ou du critere /
321
-	if (($suite && ($suite[0] != '{')) || ($fonc && $fonc[0] == '/')) {
322
-		// si pas d'argument, alors il faut une fonction ou un double |
323
-		if (!$match[1]) {
324
-			$err_f = ['zbug_erreur_filtre', ['filtre' => $texte]];
325
-			erreur_squelette($err_f, $pointeur_champ);
326
-			$texte = '';
327
-		} else {
328
-			$texte = $suite;
329
-		}
330
-		if ($err_f) {
331
-			$pointeur_champ->param = false;
332
-		} elseif ($fonc !== '') {
333
-			$pointeur_champ->param[] = $res;
334
-		}
335
-		// pour les balises avec faux filtres qui boudent ce dur larbeur
336
-		$pointeur_champ->fonctions[] = [$fonc, ''];
337
-
338
-		return $result;
339
-	}
340
-	$args = ltrim(substr($suite, 1)); // virer le '(' initial
341
-	$collecte = [];
342
-	while ($args && $args[0] != '}') {
343
-		if ($args[0] == '"') {
344
-			preg_match('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
345
-		} elseif ($args[0] == "'") {
346
-			preg_match("/^(')([^']*)(')(.*)$/ms", $args, $regs);
347
-		} else {
348
-			preg_match('/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^,}]*)([,}].*)$/ms', $args, $regs);
349
-			if (!isset($regs[2]) or !strlen($regs[2])) {
350
-				$err_f = ['zbug_erreur_filtre', ['filtre' => $args]];
351
-				erreur_squelette($err_f, $pointeur_champ);
352
-				$champ = new Texte();
353
-				$champ->apres = $champ->avant = $args = '';
354
-				break;
355
-			}
356
-		}
357
-		$arg = $regs[2];
358
-		if (trim($regs[1])) {
359
-			$champ = new Texte();
360
-			$champ->texte = $arg;
361
-			$champ->apres = $champ->avant = $regs[1];
362
-			$result[] = $champ;
363
-			$collecte[] = $champ;
364
-			$args = ltrim($regs[count($regs) - 1]);
365
-		} else {
366
-			if (!preg_match('/' . NOM_DE_CHAMP . '([{|])/', $arg, $r)) {
367
-				// 0 est un aveu d'impuissance. A completer
368
-				$arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
369
-
370
-				$args = ltrim($regs[count($regs) - 1]);
371
-				$collecte = array_merge($collecte, $arg);
372
-				$result = array_merge($result, $arg);
373
-			} else {
374
-				$n = strpos($args, (string) $r[0]);
375
-				$pred = substr($args, 0, $n);
376
-				$par = ',}';
377
-				if (preg_match('/^(.*)\($/', $pred, $m)) {
378
-					$pred = $m[1];
379
-					$par = ')';
380
-				}
381
-				if ($pred) {
382
-					$champ = new Texte();
383
-					$champ->texte = $pred;
384
-					$champ->apres = $champ->avant = '';
385
-					$result[] = $champ;
386
-					$collecte[] = $champ;
387
-				}
388
-				$rec = substr($args, $n + strlen($r[0]) - 1);
389
-				$champ = new Champ();
390
-				$champ->nom_boucle = $r[2];
391
-				$champ->nom_champ = $r[3];
392
-				$champ->etoile = $r[5];
393
-				$next = $r[6];
394
-				while ($next == '{') {
395
-					phraser_arg($rec, $sep, [], $champ);
396
-					$args = ltrim($rec);
397
-					$next = $args[0] ?? '';
398
-				}
399
-				while ($next == '|') {
400
-					$pos_apres = 0;
401
-					phraser_args($rec, $par, $sep, [], $champ, $pos_apres);
402
-					$args = substr($rec, $pos_apres);
403
-					$next = $args[0] ?? '';
404
-				}
405
-				// Si erreur de syntaxe dans un sous-argument, propager.
406
-				if ($champ->param === false) {
407
-					$err_f = true;
408
-				} else {
409
-					phraser_vieux($champ);
410
-				}
411
-				if ($par == ')') {
412
-					$args = substr($args, 1);
413
-				}
414
-				$collecte[] = $champ;
415
-				$result[] = $champ;
416
-			}
417
-		}
418
-		if (isset($args[0]) and $args[0] == ',') {
419
-			$args = ltrim(substr($args, 1));
420
-			if ($collecte) {
421
-				$res[] = $collecte;
422
-				$collecte = [];
423
-			}
424
-		}
425
-	}
426
-	if ($collecte) {
427
-		$res[] = $collecte;
428
-		$collecte = [];
429
-	}
430
-	$texte = substr($args, 1);
431
-	$source = substr($suite, 0, strlen($suite) - strlen($texte));
432
-	// propager les erreurs, et ignorer les param vides
433
-	if ($pointeur_champ->param !== false) {
434
-		if ($err_f) {
435
-			$pointeur_champ->param = false;
436
-		} elseif ($fonc !== '' || count($res) > 1) {
437
-			$pointeur_champ->param[] = $res;
438
-		}
439
-	}
440
-	// pour les balises avec faux filtres qui boudent ce dur larbeur
441
-	$pointeur_champ->fonctions[] = [$fonc, $source];
442
-
443
-	return $result;
312
+    preg_match(',^(\|?[^}{)|]*)(.*)$,ms', $texte, $match);
313
+    $suite = ltrim($match[2]);
314
+    $fonc = trim($match[1]);
315
+    if ($fonc && $fonc[0] == '|') {
316
+        $fonc = ltrim(substr($fonc, 1));
317
+    }
318
+    $res = [$fonc];
319
+    $err_f = '';
320
+    // cas du filtre sans argument ou du critere /
321
+    if (($suite && ($suite[0] != '{')) || ($fonc && $fonc[0] == '/')) {
322
+        // si pas d'argument, alors il faut une fonction ou un double |
323
+        if (!$match[1]) {
324
+            $err_f = ['zbug_erreur_filtre', ['filtre' => $texte]];
325
+            erreur_squelette($err_f, $pointeur_champ);
326
+            $texte = '';
327
+        } else {
328
+            $texte = $suite;
329
+        }
330
+        if ($err_f) {
331
+            $pointeur_champ->param = false;
332
+        } elseif ($fonc !== '') {
333
+            $pointeur_champ->param[] = $res;
334
+        }
335
+        // pour les balises avec faux filtres qui boudent ce dur larbeur
336
+        $pointeur_champ->fonctions[] = [$fonc, ''];
337
+
338
+        return $result;
339
+    }
340
+    $args = ltrim(substr($suite, 1)); // virer le '(' initial
341
+    $collecte = [];
342
+    while ($args && $args[0] != '}') {
343
+        if ($args[0] == '"') {
344
+            preg_match('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
345
+        } elseif ($args[0] == "'") {
346
+            preg_match("/^(')([^']*)(')(.*)$/ms", $args, $regs);
347
+        } else {
348
+            preg_match('/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^,}]*)([,}].*)$/ms', $args, $regs);
349
+            if (!isset($regs[2]) or !strlen($regs[2])) {
350
+                $err_f = ['zbug_erreur_filtre', ['filtre' => $args]];
351
+                erreur_squelette($err_f, $pointeur_champ);
352
+                $champ = new Texte();
353
+                $champ->apres = $champ->avant = $args = '';
354
+                break;
355
+            }
356
+        }
357
+        $arg = $regs[2];
358
+        if (trim($regs[1])) {
359
+            $champ = new Texte();
360
+            $champ->texte = $arg;
361
+            $champ->apres = $champ->avant = $regs[1];
362
+            $result[] = $champ;
363
+            $collecte[] = $champ;
364
+            $args = ltrim($regs[count($regs) - 1]);
365
+        } else {
366
+            if (!preg_match('/' . NOM_DE_CHAMP . '([{|])/', $arg, $r)) {
367
+                // 0 est un aveu d'impuissance. A completer
368
+                $arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
369
+
370
+                $args = ltrim($regs[count($regs) - 1]);
371
+                $collecte = array_merge($collecte, $arg);
372
+                $result = array_merge($result, $arg);
373
+            } else {
374
+                $n = strpos($args, (string) $r[0]);
375
+                $pred = substr($args, 0, $n);
376
+                $par = ',}';
377
+                if (preg_match('/^(.*)\($/', $pred, $m)) {
378
+                    $pred = $m[1];
379
+                    $par = ')';
380
+                }
381
+                if ($pred) {
382
+                    $champ = new Texte();
383
+                    $champ->texte = $pred;
384
+                    $champ->apres = $champ->avant = '';
385
+                    $result[] = $champ;
386
+                    $collecte[] = $champ;
387
+                }
388
+                $rec = substr($args, $n + strlen($r[0]) - 1);
389
+                $champ = new Champ();
390
+                $champ->nom_boucle = $r[2];
391
+                $champ->nom_champ = $r[3];
392
+                $champ->etoile = $r[5];
393
+                $next = $r[6];
394
+                while ($next == '{') {
395
+                    phraser_arg($rec, $sep, [], $champ);
396
+                    $args = ltrim($rec);
397
+                    $next = $args[0] ?? '';
398
+                }
399
+                while ($next == '|') {
400
+                    $pos_apres = 0;
401
+                    phraser_args($rec, $par, $sep, [], $champ, $pos_apres);
402
+                    $args = substr($rec, $pos_apres);
403
+                    $next = $args[0] ?? '';
404
+                }
405
+                // Si erreur de syntaxe dans un sous-argument, propager.
406
+                if ($champ->param === false) {
407
+                    $err_f = true;
408
+                } else {
409
+                    phraser_vieux($champ);
410
+                }
411
+                if ($par == ')') {
412
+                    $args = substr($args, 1);
413
+                }
414
+                $collecte[] = $champ;
415
+                $result[] = $champ;
416
+            }
417
+        }
418
+        if (isset($args[0]) and $args[0] == ',') {
419
+            $args = ltrim(substr($args, 1));
420
+            if ($collecte) {
421
+                $res[] = $collecte;
422
+                $collecte = [];
423
+            }
424
+        }
425
+    }
426
+    if ($collecte) {
427
+        $res[] = $collecte;
428
+        $collecte = [];
429
+    }
430
+    $texte = substr($args, 1);
431
+    $source = substr($suite, 0, strlen($suite) - strlen($texte));
432
+    // propager les erreurs, et ignorer les param vides
433
+    if ($pointeur_champ->param !== false) {
434
+        if ($err_f) {
435
+            $pointeur_champ->param = false;
436
+        } elseif ($fonc !== '' || count($res) > 1) {
437
+            $pointeur_champ->param[] = $res;
438
+        }
439
+    }
440
+    // pour les balises avec faux filtres qui boudent ce dur larbeur
441
+    $pointeur_champ->fonctions[] = [$fonc, $source];
442
+
443
+    return $result;
444 444
 }
445 445
 
446 446
 
447 447
 function phraser_champs_exterieurs($texte, $ligne, $sep, $nested) {
448
-	$res = [];
449
-	while (($p = strpos($texte, (string) "%$sep")) !== false) {
450
-		if (!preg_match(',^%' . preg_quote($sep) . '([0-9]+)@,', substr($texte, $p), $m)) {
451
-			break;
452
-		}
453
-		$debut = substr($texte, 0, $p);
454
-		$texte = substr($texte, $p + strlen($m[0]));
455
-		if ($p) {
456
-			$res = phraser_inclure($debut, $ligne, $res);
457
-		}
458
-		$ligne += substr_count($debut, "\n");
459
-		$res[] = $nested[$m[1]];
460
-	}
461
-
462
-	return (($texte === '') ? $res : phraser_inclure($texte, $ligne, $res));
448
+    $res = [];
449
+    while (($p = strpos($texte, (string) "%$sep")) !== false) {
450
+        if (!preg_match(',^%' . preg_quote($sep) . '([0-9]+)@,', substr($texte, $p), $m)) {
451
+            break;
452
+        }
453
+        $debut = substr($texte, 0, $p);
454
+        $texte = substr($texte, $p + strlen($m[0]));
455
+        if ($p) {
456
+            $res = phraser_inclure($debut, $ligne, $res);
457
+        }
458
+        $ligne += substr_count($debut, "\n");
459
+        $res[] = $nested[$m[1]];
460
+    }
461
+
462
+    return (($texte === '') ? $res : phraser_inclure($texte, $ligne, $res));
463 463
 }
464 464
 
465 465
 function phraser_champs_interieurs($texte, $ligne, $sep, $result) {
466
-	$i = 0; // en fait count($result)
467
-	$x = '';
468
-
469
-	while (true) {
470
-		$j = $i;
471
-		$n = $ligne;
472
-		while (preg_match(CHAMP_ETENDU, $texte, $match)) {
473
-			$p = strpos($texte, (string) $match[0]);
474
-			$debut = substr($texte, 0, $p);
475
-			if ($p) {
476
-				$result[$i] = $debut;
477
-				$i++;
478
-			}
479
-			$nom = $match[4];
480
-			$champ = new Champ();
481
-			// ca ne marche pas encore en cas de champ imbrique
482
-			$champ->ligne = $x ? 0 : ($n + substr_count($debut, "\n"));
483
-			$champ->nom_boucle = $match[3];
484
-			$champ->nom_champ = $nom;
485
-			$champ->etoile = $match[6];
486
-			// phraser_args indiquera ou commence apres
487
-			$pos_apres = 0;
488
-			$result = phraser_args($match[7], ')', $sep, $result, $champ, $pos_apres);
489
-			phraser_vieux($champ);
490
-			$champ->avant =	phraser_champs_exterieurs($match[1], $n, $sep, $result);
491
-			$debut = substr($match[7], $pos_apres + 1);
492
-			if (!empty($debut)) {
493
-				$n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
494
-			}
495
-			$champ->apres = phraser_champs_exterieurs($debut, $n, $sep, $result);
496
-
497
-			// reinjecter la boucle si c'en est une
498
-			phraser_boucle_placeholder($champ);
499
-
500
-			$result[$i] = $champ;
501
-			$i++;
502
-			$texte = substr($texte, $p + strlen($match[0]));
503
-		}
504
-		if ($texte !== '') {
505
-			$result[$i] = $texte;
506
-			$i++;
507
-		}
508
-		$x = '';
509
-
510
-		while ($j < $i) {
511
-			$z = $result[$j];
512
-			// j'aurais besoin de connaitre le nombre de lignes...
513
-			if (is_object($z)) {
514
-				$x .= "%$sep$j@";
515
-			} else {
516
-				$x .= $z;
517
-			}
518
-			$j++;
519
-		}
520
-		if (preg_match(CHAMP_ETENDU, $x)) {
521
-			$texte = $x;
522
-		} else {
523
-			return phraser_champs_exterieurs($x, $ligne, $sep, $result);
524
-		}
525
-	}
466
+    $i = 0; // en fait count($result)
467
+    $x = '';
468
+
469
+    while (true) {
470
+        $j = $i;
471
+        $n = $ligne;
472
+        while (preg_match(CHAMP_ETENDU, $texte, $match)) {
473
+            $p = strpos($texte, (string) $match[0]);
474
+            $debut = substr($texte, 0, $p);
475
+            if ($p) {
476
+                $result[$i] = $debut;
477
+                $i++;
478
+            }
479
+            $nom = $match[4];
480
+            $champ = new Champ();
481
+            // ca ne marche pas encore en cas de champ imbrique
482
+            $champ->ligne = $x ? 0 : ($n + substr_count($debut, "\n"));
483
+            $champ->nom_boucle = $match[3];
484
+            $champ->nom_champ = $nom;
485
+            $champ->etoile = $match[6];
486
+            // phraser_args indiquera ou commence apres
487
+            $pos_apres = 0;
488
+            $result = phraser_args($match[7], ')', $sep, $result, $champ, $pos_apres);
489
+            phraser_vieux($champ);
490
+            $champ->avant =	phraser_champs_exterieurs($match[1], $n, $sep, $result);
491
+            $debut = substr($match[7], $pos_apres + 1);
492
+            if (!empty($debut)) {
493
+                $n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
494
+            }
495
+            $champ->apres = phraser_champs_exterieurs($debut, $n, $sep, $result);
496
+
497
+            // reinjecter la boucle si c'en est une
498
+            phraser_boucle_placeholder($champ);
499
+
500
+            $result[$i] = $champ;
501
+            $i++;
502
+            $texte = substr($texte, $p + strlen($match[0]));
503
+        }
504
+        if ($texte !== '') {
505
+            $result[$i] = $texte;
506
+            $i++;
507
+        }
508
+        $x = '';
509
+
510
+        while ($j < $i) {
511
+            $z = $result[$j];
512
+            // j'aurais besoin de connaitre le nombre de lignes...
513
+            if (is_object($z)) {
514
+                $x .= "%$sep$j@";
515
+            } else {
516
+                $x .= $z;
517
+            }
518
+            $j++;
519
+        }
520
+        if (preg_match(CHAMP_ETENDU, $x)) {
521
+            $texte = $x;
522
+        } else {
523
+            return phraser_champs_exterieurs($x, $ligne, $sep, $result);
524
+        }
525
+    }
526 526
 }
527 527
 
528 528
 function phraser_vieux(&$champ) {
529
-	$nom = $champ->nom_champ;
530
-	if ($nom == 'EMBED_DOCUMENT') {
531
-		if (!function_exists('phraser_vieux_emb')) {
532
-			include_spip('public/normaliser');
533
-		}
534
-		phraser_vieux_emb($champ);
535
-	} elseif ($nom == 'EXPOSER') {
536
-		if (!function_exists('phraser_vieux_exposer')) {
537
-			include_spip('public/normaliser');
538
-		}
539
-		phraser_vieux_exposer($champ);
540
-	} elseif ($champ->param) {
541
-		if ($nom == 'FORMULAIRE_RECHERCHE') {
542
-			if (!function_exists('phraser_vieux_recherche')) {
543
-				include_spip('public/normaliser');
544
-			}
545
-			phraser_vieux_recherche($champ);
546
-		} elseif (preg_match(',^LOGO_[A-Z]+,', $nom)) {
547
-			if (!function_exists('phraser_vieux_logos')) {
548
-				include_spip('public/normaliser');
549
-			}
550
-			phraser_vieux_logos($champ);
551
-		} elseif ($nom == 'MODELE') {
552
-			if (!function_exists('phraser_vieux_modele')) {
553
-				include_spip('public/normaliser');
554
-			}
555
-			phraser_vieux_modele($champ);
556
-		} elseif ($nom == 'INCLURE' or $nom == 'INCLUDE') {
557
-			if (!function_exists('phraser_vieux_inclu')) {
558
-				include_spip('public/normaliser');
559
-			}
560
-			phraser_vieux_inclu($champ);
561
-		}
562
-	}
529
+    $nom = $champ->nom_champ;
530
+    if ($nom == 'EMBED_DOCUMENT') {
531
+        if (!function_exists('phraser_vieux_emb')) {
532
+            include_spip('public/normaliser');
533
+        }
534
+        phraser_vieux_emb($champ);
535
+    } elseif ($nom == 'EXPOSER') {
536
+        if (!function_exists('phraser_vieux_exposer')) {
537
+            include_spip('public/normaliser');
538
+        }
539
+        phraser_vieux_exposer($champ);
540
+    } elseif ($champ->param) {
541
+        if ($nom == 'FORMULAIRE_RECHERCHE') {
542
+            if (!function_exists('phraser_vieux_recherche')) {
543
+                include_spip('public/normaliser');
544
+            }
545
+            phraser_vieux_recherche($champ);
546
+        } elseif (preg_match(',^LOGO_[A-Z]+,', $nom)) {
547
+            if (!function_exists('phraser_vieux_logos')) {
548
+                include_spip('public/normaliser');
549
+            }
550
+            phraser_vieux_logos($champ);
551
+        } elseif ($nom == 'MODELE') {
552
+            if (!function_exists('phraser_vieux_modele')) {
553
+                include_spip('public/normaliser');
554
+            }
555
+            phraser_vieux_modele($champ);
556
+        } elseif ($nom == 'INCLURE' or $nom == 'INCLUDE') {
557
+            if (!function_exists('phraser_vieux_inclu')) {
558
+                include_spip('public/normaliser');
559
+            }
560
+            phraser_vieux_inclu($champ);
561
+        }
562
+    }
563 563
 }
564 564
 
565 565
 
@@ -587,200 +587,200 @@  discard block
 block discarded – undo
587 587
  **/
588 588
 function phraser_criteres($params, &$result) {
589 589
 
590
-	$err_ci = ''; // indiquera s'il y a eu une erreur
591
-	$args = [];
592
-	$type = $result->type_requete;
593
-	$doublons = [];
594
-	foreach ($params as $v) {
595
-		$var = $v[1][0];
596
-		$param = ($var->type != 'texte') ? '' : $var->texte;
597
-		if (((is_countable($v) ? count($v) : 0) > 2) && (!preg_match(',[^A-Za-z]IN[^A-Za-z],i', $param))) {
598
-			// plus d'un argument et pas le critere IN:
599
-			// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
600
-			if (
601
-				$var->type != 'texte'
602
-				or preg_match('/^(n|n-|(n-)?\d+)$/S', $param)
603
-			) {
604
-				$op = ',';
605
-				$not = false;
606
-				$cond = false;
607
-			} else {
608
-				// Le debut du premier argument est l'operateur
609
-				preg_match('/^([!]?)([a-zA-Z][a-zA-Z0-9_]*)[[:space:]]*(\??)[[:space:]]*(.*)$/ms', $param, $m);
610
-				$op = $m[2];
611
-				$not = (bool) $m[1];
612
-				$cond = $m[3];
613
-				// virer le premier argument,
614
-				// et mettre son reliquat eventuel
615
-				// Recopier pour ne pas alterer le texte source
616
-				// utile au debusqueur
617
-				if ($m[4]) {
618
-					// une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
619
-					if (preg_match(',^(["\'])(.*)\1$,', $m[4])) {
620
-						$c = null;
621
-						eval('$c = ' . $m[4] . ';');
622
-						if (isset($c)) {
623
-							$m[4] = $c;
624
-						}
625
-					}
626
-					$texte = new Texte();
627
-					$texte->texte = $m[4];
628
-					$v[1][0] = $texte;
629
-				} else {
630
-					array_shift($v[1]);
631
-				}
632
-			}
633
-			array_shift($v); // $v[O] est vide
634
-			$crit = new Critere();
635
-			$crit->op = $op;
636
-			$crit->not = $not;
637
-			$crit->cond = $cond;
638
-			$crit->exclus = '';
639
-			$crit->param = $v;
640
-			$args[] = $crit;
641
-		} else {
642
-			if ($var->type != 'texte') {
643
-				// cas 1 seul arg ne commencant pas par du texte brut:
644
-				// erreur ou critere infixe "/"
645
-				if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) != '/')) {
646
-					$err_ci = [
647
-						'zbug_critere_inconnu',
648
-						['critere' => $var->nom_champ]
649
-					];
650
-					erreur_squelette($err_ci, $result);
651
-				} else {
652
-					$crit = new Critere();
653
-					$crit->op = '/';
654
-					$crit->not = false;
655
-					$crit->exclus = '';
656
-					$crit->param = [[$v[1][0]], [$v[1][2]]];
657
-					$args[] = $crit;
658
-				}
659
-			} else {
660
-				// traiter qq lexemes particuliers pour faciliter la suite
661
-				// les separateurs
662
-				if ($var->apres) {
663
-					$result->separateur[] = $param;
664
-				} elseif (($param == 'tout') or ($param == 'tous')) {
665
-					$result->modificateur['tout'] = true;
666
-				} elseif ($param == 'plat') {
667
-					$result->modificateur['plat'] = true;
668
-				}
669
-
670
-				// Boucle hierarchie, analyser le critere id_rubrique
671
-				// et les autres critères {id_x} pour forcer {tout} sur
672
-				// ceux-ci pour avoir la rubrique mere...
673
-				// Les autres critères de la boucle hierarchie doivent être
674
-				// traités normalement.
675
-				elseif (
676
-					strcasecmp($type, 'hierarchie') == 0
677
-					and !preg_match(",^id_rubrique\b,", $param)
678
-					and preg_match(',^id_\w+\s*$,', $param)
679
-				) {
680
-					$result->modificateur['tout'] = true;
681
-				} elseif (strcasecmp($type, 'hierarchie') == 0 and $param == 'id_rubrique') {
682
-					// rien a faire sur {id_rubrique} tout seul
683
-				} else {
684
-					// pas d'emplacement statique, faut un dynamique
685
-					// mais il y a 2 cas qui ont les 2 !
686
-					if (($param == 'unique') || (preg_match(',^!?doublons *,', $param))) {
687
-						// cette variable sera inseree dans le code
688
-						// et son nom sert d'indicateur des maintenant
689
-						$result->doublons = '$doublons_index';
690
-						if ($param == 'unique') {
691
-							$param = 'doublons';
692
-						}
693
-					} elseif ($param == 'recherche') {
694
-						// meme chose (a cause de #nom_de_boucle:URL_*)
695
-						$result->hash = ' ';
696
-					}
697
-
698
-					if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
699
-						$crit = phraser_critere_infixe($m[1], $m[3], $v, '/', '', '');
700
-					} elseif (
701
-						preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC .
702
-						')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)
703
-					) {
704
-						$a2 = trim($m[8]);
705
-						if ($a2 and ($a2[0] == "'" or $a2[0] == '"') and ($a2[0] == substr($a2, -1))) {
706
-							$a2 = substr($a2, 1, -1);
707
-						}
708
-						$crit = phraser_critere_infixe(
709
-							$m[2],
710
-							$a2,
711
-							$v,
712
-							(($m[2] == 'lang_select') ? $m[2] : $m[7]),
713
-							$m[6],
714
-							$m[5]
715
-						);
716
-						$crit->exclus = $m[1];
717
-					} elseif (
718
-						preg_match('/^([!]?)\s*(' .
719
-						CHAMP_SQL_PLUS_FONC .
720
-						')\s*(\??)(.*)$/is', $param, $m)
721
-					) {
722
-						// contient aussi les comparaisons implicites !
723
-						// Comme ci-dessus:
724
-						// le premier arg contient l'operateur
725
-						array_shift($v);
726
-						if ($m[6]) {
727
-							$v[0][0] = new Texte();
728
-							$v[0][0]->texte = $m[6];
729
-						} else {
730
-							array_shift($v[0]);
731
-							if (!$v[0]) {
732
-								array_shift($v);
733
-							}
734
-						}
735
-						$crit = new Critere();
736
-						$crit->op = $m[2];
737
-						$crit->param = $v;
738
-						$crit->not = (bool) $m[1];
739
-						$crit->cond = $m[5];
740
-					} else {
741
-						$err_ci = [
742
-							'zbug_critere_inconnu',
743
-							['critere' => $param]
744
-						];
745
-						erreur_squelette($err_ci, $result);
746
-					}
747
-
748
-					if ((!preg_match(',^!?doublons *,', $param)) || $crit->not) {
749
-						$args[] = $crit;
750
-					} else {
751
-						$doublons[] = $crit;
752
-					}
753
-				}
754
-			}
755
-		}
756
-	}
757
-
758
-	// les doublons non nies doivent etre le dernier critere
759
-	// pour que la variable $doublon_index ait la bonne valeur
760
-	// cf critere_doublon
761
-	if ($doublons) {
762
-		$args = [...$args, ...$doublons];
763
-	}
764
-
765
-	// Si erreur, laisser la chaine dans ce champ pour le HTTP 503
766
-	if (!$err_ci) {
767
-		$result->criteres = $args;
768
-	}
590
+    $err_ci = ''; // indiquera s'il y a eu une erreur
591
+    $args = [];
592
+    $type = $result->type_requete;
593
+    $doublons = [];
594
+    foreach ($params as $v) {
595
+        $var = $v[1][0];
596
+        $param = ($var->type != 'texte') ? '' : $var->texte;
597
+        if (((is_countable($v) ? count($v) : 0) > 2) && (!preg_match(',[^A-Za-z]IN[^A-Za-z],i', $param))) {
598
+            // plus d'un argument et pas le critere IN:
599
+            // detecter comme on peut si c'est le critere implicite LIMIT debut, fin
600
+            if (
601
+                $var->type != 'texte'
602
+                or preg_match('/^(n|n-|(n-)?\d+)$/S', $param)
603
+            ) {
604
+                $op = ',';
605
+                $not = false;
606
+                $cond = false;
607
+            } else {
608
+                // Le debut du premier argument est l'operateur
609
+                preg_match('/^([!]?)([a-zA-Z][a-zA-Z0-9_]*)[[:space:]]*(\??)[[:space:]]*(.*)$/ms', $param, $m);
610
+                $op = $m[2];
611
+                $not = (bool) $m[1];
612
+                $cond = $m[3];
613
+                // virer le premier argument,
614
+                // et mettre son reliquat eventuel
615
+                // Recopier pour ne pas alterer le texte source
616
+                // utile au debusqueur
617
+                if ($m[4]) {
618
+                    // une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
619
+                    if (preg_match(',^(["\'])(.*)\1$,', $m[4])) {
620
+                        $c = null;
621
+                        eval('$c = ' . $m[4] . ';');
622
+                        if (isset($c)) {
623
+                            $m[4] = $c;
624
+                        }
625
+                    }
626
+                    $texte = new Texte();
627
+                    $texte->texte = $m[4];
628
+                    $v[1][0] = $texte;
629
+                } else {
630
+                    array_shift($v[1]);
631
+                }
632
+            }
633
+            array_shift($v); // $v[O] est vide
634
+            $crit = new Critere();
635
+            $crit->op = $op;
636
+            $crit->not = $not;
637
+            $crit->cond = $cond;
638
+            $crit->exclus = '';
639
+            $crit->param = $v;
640
+            $args[] = $crit;
641
+        } else {
642
+            if ($var->type != 'texte') {
643
+                // cas 1 seul arg ne commencant pas par du texte brut:
644
+                // erreur ou critere infixe "/"
645
+                if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) != '/')) {
646
+                    $err_ci = [
647
+                        'zbug_critere_inconnu',
648
+                        ['critere' => $var->nom_champ]
649
+                    ];
650
+                    erreur_squelette($err_ci, $result);
651
+                } else {
652
+                    $crit = new Critere();
653
+                    $crit->op = '/';
654
+                    $crit->not = false;
655
+                    $crit->exclus = '';
656
+                    $crit->param = [[$v[1][0]], [$v[1][2]]];
657
+                    $args[] = $crit;
658
+                }
659
+            } else {
660
+                // traiter qq lexemes particuliers pour faciliter la suite
661
+                // les separateurs
662
+                if ($var->apres) {
663
+                    $result->separateur[] = $param;
664
+                } elseif (($param == 'tout') or ($param == 'tous')) {
665
+                    $result->modificateur['tout'] = true;
666
+                } elseif ($param == 'plat') {
667
+                    $result->modificateur['plat'] = true;
668
+                }
669
+
670
+                // Boucle hierarchie, analyser le critere id_rubrique
671
+                // et les autres critères {id_x} pour forcer {tout} sur
672
+                // ceux-ci pour avoir la rubrique mere...
673
+                // Les autres critères de la boucle hierarchie doivent être
674
+                // traités normalement.
675
+                elseif (
676
+                    strcasecmp($type, 'hierarchie') == 0
677
+                    and !preg_match(",^id_rubrique\b,", $param)
678
+                    and preg_match(',^id_\w+\s*$,', $param)
679
+                ) {
680
+                    $result->modificateur['tout'] = true;
681
+                } elseif (strcasecmp($type, 'hierarchie') == 0 and $param == 'id_rubrique') {
682
+                    // rien a faire sur {id_rubrique} tout seul
683
+                } else {
684
+                    // pas d'emplacement statique, faut un dynamique
685
+                    // mais il y a 2 cas qui ont les 2 !
686
+                    if (($param == 'unique') || (preg_match(',^!?doublons *,', $param))) {
687
+                        // cette variable sera inseree dans le code
688
+                        // et son nom sert d'indicateur des maintenant
689
+                        $result->doublons = '$doublons_index';
690
+                        if ($param == 'unique') {
691
+                            $param = 'doublons';
692
+                        }
693
+                    } elseif ($param == 'recherche') {
694
+                        // meme chose (a cause de #nom_de_boucle:URL_*)
695
+                        $result->hash = ' ';
696
+                    }
697
+
698
+                    if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
699
+                        $crit = phraser_critere_infixe($m[1], $m[3], $v, '/', '', '');
700
+                    } elseif (
701
+                        preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC .
702
+                        ')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)
703
+                    ) {
704
+                        $a2 = trim($m[8]);
705
+                        if ($a2 and ($a2[0] == "'" or $a2[0] == '"') and ($a2[0] == substr($a2, -1))) {
706
+                            $a2 = substr($a2, 1, -1);
707
+                        }
708
+                        $crit = phraser_critere_infixe(
709
+                            $m[2],
710
+                            $a2,
711
+                            $v,
712
+                            (($m[2] == 'lang_select') ? $m[2] : $m[7]),
713
+                            $m[6],
714
+                            $m[5]
715
+                        );
716
+                        $crit->exclus = $m[1];
717
+                    } elseif (
718
+                        preg_match('/^([!]?)\s*(' .
719
+                        CHAMP_SQL_PLUS_FONC .
720
+                        ')\s*(\??)(.*)$/is', $param, $m)
721
+                    ) {
722
+                        // contient aussi les comparaisons implicites !
723
+                        // Comme ci-dessus:
724
+                        // le premier arg contient l'operateur
725
+                        array_shift($v);
726
+                        if ($m[6]) {
727
+                            $v[0][0] = new Texte();
728
+                            $v[0][0]->texte = $m[6];
729
+                        } else {
730
+                            array_shift($v[0]);
731
+                            if (!$v[0]) {
732
+                                array_shift($v);
733
+                            }
734
+                        }
735
+                        $crit = new Critere();
736
+                        $crit->op = $m[2];
737
+                        $crit->param = $v;
738
+                        $crit->not = (bool) $m[1];
739
+                        $crit->cond = $m[5];
740
+                    } else {
741
+                        $err_ci = [
742
+                            'zbug_critere_inconnu',
743
+                            ['critere' => $param]
744
+                        ];
745
+                        erreur_squelette($err_ci, $result);
746
+                    }
747
+
748
+                    if ((!preg_match(',^!?doublons *,', $param)) || $crit->not) {
749
+                        $args[] = $crit;
750
+                    } else {
751
+                        $doublons[] = $crit;
752
+                    }
753
+                }
754
+            }
755
+        }
756
+    }
757
+
758
+    // les doublons non nies doivent etre le dernier critere
759
+    // pour que la variable $doublon_index ait la bonne valeur
760
+    // cf critere_doublon
761
+    if ($doublons) {
762
+        $args = [...$args, ...$doublons];
763
+    }
764
+
765
+    // Si erreur, laisser la chaine dans ce champ pour le HTTP 503
766
+    if (!$err_ci) {
767
+        $result->criteres = $args;
768
+    }
769 769
 }
770 770
 
771 771
 function phraser_critere_infixe($arg1, $arg2, $args, $op, $not, $cond) {
772
-	$args[0] = new Texte();
773
-	$args[0]->texte = $arg1;
774
-	$args[0] = [$args[0]];
775
-	$args[1][0] = new Texte();
776
-	$args[1][0]->texte = $arg2;
777
-	$crit = new Critere();
778
-	$crit->op = $op;
779
-	$crit->not = $not;
780
-	$crit->cond = $cond;
781
-	$crit->param = $args;
782
-
783
-	return $crit;
772
+    $args[0] = new Texte();
773
+    $args[0]->texte = $arg1;
774
+    $args[0] = [$args[0]];
775
+    $args[1][0] = new Texte();
776
+    $args[1][0]->texte = $arg2;
777
+    $crit = new Critere();
778
+    $crit->op = $op;
779
+    $crit->not = $not;
780
+    $crit->cond = $cond;
781
+    $crit->param = $args;
782
+
783
+    return $crit;
784 784
 }
785 785
 
786 786
 /**
@@ -791,12 +791,12 @@  discard block
 block discarded – undo
791 791
  * @return int
792 792
  */
793 793
 function public_compte_ligne($texte, $debut = 0, $fin = null) {
794
-	if (is_null($fin)) {
795
-		return substr_count($texte, "\n", $debut);
796
-	}
797
-	else {
798
-		return substr_count($texte, "\n", $debut, $fin - $debut);
799
-	}
794
+    if (is_null($fin)) {
795
+        return substr_count($texte, "\n", $debut);
796
+    }
797
+    else {
798
+        return substr_count($texte, "\n", $debut, $fin - $debut);
799
+    }
800 800
 }
801 801
 
802 802
 
@@ -812,87 +812,87 @@  discard block
 block discarded – undo
812 812
  * @return array|null
813 813
  */
814 814
 function public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte = 0) {
815
-	$premiere_boucle = null;
816
-	$pos_derniere_boucle_anonyme = $pos_debut_texte;
817
-
818
-	$current_pos = $pos_debut_texte;
819
-	while (($pos_boucle = strpos($texte, BALISE_BOUCLE, $current_pos)) !== false) {
820
-		$current_pos = $pos_boucle + 1;
821
-		$pos_parent = strpos($texte, '(', $pos_boucle);
822
-
823
-		$id_boucle = '';
824
-		if ($pos_parent !== false) {
825
-			$id_boucle = trim(substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), $pos_parent - $pos_boucle - strlen(BALISE_BOUCLE)));
826
-		}
827
-		if (
828
-			$pos_parent === false
829
-			or (strlen($id_boucle) and !(is_numeric($id_boucle) or strpos($id_boucle, '_') === 0))
830
-		) {
831
-			$result = new Boucle();
832
-			$result->id_parent = $id_parent;
833
-			$result->descr = $descr;
834
-
835
-			// un id_boucle pour l'affichage de l'erreur
836
-			if (!strlen($id_boucle)) {
837
-				$id_boucle = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
838
-			}
839
-			$result->id_boucle = $id_boucle;
840
-			$err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
841
-			erreur_squelette($err_b, $result);
842
-
843
-			continue;
844
-		}
845
-		else {
846
-			$boucle = [
847
-				'id_boucle' => $id_boucle,
848
-				'id_boucle_err' => $id_boucle,
849
-				'debut_boucle' => $pos_boucle,
850
-				'pos_boucle' => $pos_boucle,
851
-				'pos_parent' => $pos_parent,
852
-				'pos_precond' => false,
853
-				'pos_precond_inside' => false,
854
-				'pos_preaff' => false,
855
-				'pos_preaff_inside' => false,
856
-			];
857
-
858
-			// un id_boucle pour l'affichage de l'erreur sur les boucle anonymes
859
-			if (!strlen($id_boucle)) {
860
-				$boucle['id_boucle_err'] = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
861
-			}
862
-
863
-			// trouver sa position de depart reelle : au <Bxx> ou au <BBxx>
864
-			$precond_boucle = BALISE_PRECOND_BOUCLE . $id_boucle . '>';
865
-			$pos_precond = strpos($texte, $precond_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
866
-			if (
867
-				$pos_precond !== false
868
-				and $pos_precond < $boucle['debut_boucle']
869
-			) {
870
-				$boucle['debut_boucle'] = $pos_precond;
871
-				$boucle['pos_precond'] = $pos_precond;
872
-				$boucle['pos_precond_inside'] = $pos_precond + strlen($precond_boucle);
873
-			}
874
-
875
-			$preaff_boucle = BALISE_PREAFF_BOUCLE . $id_boucle . '>';
876
-			$pos_preaff = strpos($texte, $preaff_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
877
-			if (
878
-				$pos_preaff !== false
879
-				and $pos_preaff < $boucle['debut_boucle']
880
-			) {
881
-				$boucle['debut_boucle'] = $pos_preaff;
882
-				$boucle['pos_preaff'] = $pos_preaff;
883
-				$boucle['pos_preaff_inside'] = $pos_preaff + strlen($preaff_boucle);
884
-			}
885
-			if (!strlen($id_boucle)) {
886
-				$pos_derniere_boucle_anonyme = $pos_boucle;
887
-			}
888
-
889
-			if (is_null($premiere_boucle) or $premiere_boucle['debut_boucle'] > $boucle['debut_boucle']) {
890
-				$premiere_boucle = $boucle;
891
-			}
892
-		}
893
-	}
894
-
895
-	return $premiere_boucle;
815
+    $premiere_boucle = null;
816
+    $pos_derniere_boucle_anonyme = $pos_debut_texte;
817
+
818
+    $current_pos = $pos_debut_texte;
819
+    while (($pos_boucle = strpos($texte, BALISE_BOUCLE, $current_pos)) !== false) {
820
+        $current_pos = $pos_boucle + 1;
821
+        $pos_parent = strpos($texte, '(', $pos_boucle);
822
+
823
+        $id_boucle = '';
824
+        if ($pos_parent !== false) {
825
+            $id_boucle = trim(substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), $pos_parent - $pos_boucle - strlen(BALISE_BOUCLE)));
826
+        }
827
+        if (
828
+            $pos_parent === false
829
+            or (strlen($id_boucle) and !(is_numeric($id_boucle) or strpos($id_boucle, '_') === 0))
830
+        ) {
831
+            $result = new Boucle();
832
+            $result->id_parent = $id_parent;
833
+            $result->descr = $descr;
834
+
835
+            // un id_boucle pour l'affichage de l'erreur
836
+            if (!strlen($id_boucle)) {
837
+                $id_boucle = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
838
+            }
839
+            $result->id_boucle = $id_boucle;
840
+            $err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
841
+            erreur_squelette($err_b, $result);
842
+
843
+            continue;
844
+        }
845
+        else {
846
+            $boucle = [
847
+                'id_boucle' => $id_boucle,
848
+                'id_boucle_err' => $id_boucle,
849
+                'debut_boucle' => $pos_boucle,
850
+                'pos_boucle' => $pos_boucle,
851
+                'pos_parent' => $pos_parent,
852
+                'pos_precond' => false,
853
+                'pos_precond_inside' => false,
854
+                'pos_preaff' => false,
855
+                'pos_preaff_inside' => false,
856
+            ];
857
+
858
+            // un id_boucle pour l'affichage de l'erreur sur les boucle anonymes
859
+            if (!strlen($id_boucle)) {
860
+                $boucle['id_boucle_err'] = substr($texte, $pos_boucle + strlen(BALISE_BOUCLE), 15);
861
+            }
862
+
863
+            // trouver sa position de depart reelle : au <Bxx> ou au <BBxx>
864
+            $precond_boucle = BALISE_PRECOND_BOUCLE . $id_boucle . '>';
865
+            $pos_precond = strpos($texte, $precond_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
866
+            if (
867
+                $pos_precond !== false
868
+                and $pos_precond < $boucle['debut_boucle']
869
+            ) {
870
+                $boucle['debut_boucle'] = $pos_precond;
871
+                $boucle['pos_precond'] = $pos_precond;
872
+                $boucle['pos_precond_inside'] = $pos_precond + strlen($precond_boucle);
873
+            }
874
+
875
+            $preaff_boucle = BALISE_PREAFF_BOUCLE . $id_boucle . '>';
876
+            $pos_preaff = strpos($texte, $preaff_boucle, $id_boucle ? $pos_debut_texte : $pos_derniere_boucle_anonyme);
877
+            if (
878
+                $pos_preaff !== false
879
+                and $pos_preaff < $boucle['debut_boucle']
880
+            ) {
881
+                $boucle['debut_boucle'] = $pos_preaff;
882
+                $boucle['pos_preaff'] = $pos_preaff;
883
+                $boucle['pos_preaff_inside'] = $pos_preaff + strlen($preaff_boucle);
884
+            }
885
+            if (!strlen($id_boucle)) {
886
+                $pos_derniere_boucle_anonyme = $pos_boucle;
887
+            }
888
+
889
+            if (is_null($premiere_boucle) or $premiere_boucle['debut_boucle'] > $boucle['debut_boucle']) {
890
+                $premiere_boucle = $boucle;
891
+            }
892
+        }
893
+    }
894
+
895
+    return $premiere_boucle;
896 896
 }
897 897
 
898 898
 /**
@@ -907,68 +907,68 @@  discard block
 block discarded – undo
907 907
  * @return mixed
908 908
  */
909 909
 function public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_debut_texte, $result) {
910
-	$id_boucle = $boucle['id_boucle'];
911
-	$pos_courante = $pos_debut_texte;
912
-
913
-	$boucle['pos_postcond'] = false;
914
-	$boucle['pos_postcond_inside'] = false;
915
-	$boucle['pos_altern'] = false;
916
-	$boucle['pos_altern_inside'] = false;
917
-	$boucle['pos_postaff'] = false;
918
-	$boucle['pos_postaff_inside'] = false;
919
-
920
-	$pos_anonyme_next = null;
921
-	// si c'est une boucle anonyme, chercher la position de la prochaine boucle anonyme
922
-	if (!strlen($id_boucle)) {
923
-		$pos_anonyme_next = strpos($texte, BALISE_BOUCLE . '(', $pos_courante);
924
-	}
925
-
926
-	//
927
-	// 1. Recuperer la partie conditionnelle apres
928
-	//
929
-	$apres_boucle = BALISE_POSTCOND_BOUCLE . $id_boucle . '>';
930
-	$pos_apres = strpos($texte, $apres_boucle, $pos_courante);
931
-	if (
932
-		$pos_apres !== false
933
-		and (!$pos_anonyme_next or $pos_apres < $pos_anonyme_next)
934
-	) {
935
-		$boucle['pos_postcond'] = $pos_apres;
936
-		$pos_apres += strlen($apres_boucle);
937
-		$boucle['pos_postcond_inside'] = $pos_apres;
938
-		$pos_courante = $pos_apres ;
939
-	}
940
-
941
-	//
942
-	// 2. Récuperer la partie alternative apres
943
-	//
944
-	$altern_boucle = BALISE_ALT_BOUCLE . $id_boucle . '>';
945
-	$pos_altern = strpos($texte, $altern_boucle, $pos_courante);
946
-	if (
947
-		$pos_altern !== false
948
-		and (!$pos_anonyme_next or $pos_altern < $pos_anonyme_next)
949
-	) {
950
-		$boucle['pos_altern'] = $pos_altern;
951
-		$pos_altern += strlen($altern_boucle);
952
-		$boucle['pos_altern_inside'] = $pos_altern;
953
-		$pos_courante = $pos_altern;
954
-	}
955
-
956
-	//
957
-	// 3. Recuperer la partie footer non alternative
958
-	//
959
-	$postaff_boucle = BALISE_POSTAFF_BOUCLE . $id_boucle . '>';
960
-	$pos_postaff = strpos($texte, $postaff_boucle, $pos_courante);
961
-	if (
962
-		$pos_postaff !== false
963
-		and (!$pos_anonyme_next or $pos_postaff < $pos_anonyme_next)
964
-	) {
965
-		$boucle['pos_postaff'] = $pos_postaff;
966
-		$pos_postaff += strlen($postaff_boucle);
967
-		$boucle['pos_postaff_inside'] = $pos_postaff;
968
-		$pos_courante = $pos_postaff ;
969
-	}
970
-
971
-	return $boucle;
910
+    $id_boucle = $boucle['id_boucle'];
911
+    $pos_courante = $pos_debut_texte;
912
+
913
+    $boucle['pos_postcond'] = false;
914
+    $boucle['pos_postcond_inside'] = false;
915
+    $boucle['pos_altern'] = false;
916
+    $boucle['pos_altern_inside'] = false;
917
+    $boucle['pos_postaff'] = false;
918
+    $boucle['pos_postaff_inside'] = false;
919
+
920
+    $pos_anonyme_next = null;
921
+    // si c'est une boucle anonyme, chercher la position de la prochaine boucle anonyme
922
+    if (!strlen($id_boucle)) {
923
+        $pos_anonyme_next = strpos($texte, BALISE_BOUCLE . '(', $pos_courante);
924
+    }
925
+
926
+    //
927
+    // 1. Recuperer la partie conditionnelle apres
928
+    //
929
+    $apres_boucle = BALISE_POSTCOND_BOUCLE . $id_boucle . '>';
930
+    $pos_apres = strpos($texte, $apres_boucle, $pos_courante);
931
+    if (
932
+        $pos_apres !== false
933
+        and (!$pos_anonyme_next or $pos_apres < $pos_anonyme_next)
934
+    ) {
935
+        $boucle['pos_postcond'] = $pos_apres;
936
+        $pos_apres += strlen($apres_boucle);
937
+        $boucle['pos_postcond_inside'] = $pos_apres;
938
+        $pos_courante = $pos_apres ;
939
+    }
940
+
941
+    //
942
+    // 2. Récuperer la partie alternative apres
943
+    //
944
+    $altern_boucle = BALISE_ALT_BOUCLE . $id_boucle . '>';
945
+    $pos_altern = strpos($texte, $altern_boucle, $pos_courante);
946
+    if (
947
+        $pos_altern !== false
948
+        and (!$pos_anonyme_next or $pos_altern < $pos_anonyme_next)
949
+    ) {
950
+        $boucle['pos_altern'] = $pos_altern;
951
+        $pos_altern += strlen($altern_boucle);
952
+        $boucle['pos_altern_inside'] = $pos_altern;
953
+        $pos_courante = $pos_altern;
954
+    }
955
+
956
+    //
957
+    // 3. Recuperer la partie footer non alternative
958
+    //
959
+    $postaff_boucle = BALISE_POSTAFF_BOUCLE . $id_boucle . '>';
960
+    $pos_postaff = strpos($texte, $postaff_boucle, $pos_courante);
961
+    if (
962
+        $pos_postaff !== false
963
+        and (!$pos_anonyme_next or $pos_postaff < $pos_anonyme_next)
964
+    ) {
965
+        $boucle['pos_postaff'] = $pos_postaff;
966
+        $pos_postaff += strlen($postaff_boucle);
967
+        $boucle['pos_postaff_inside'] = $pos_postaff;
968
+        $pos_courante = $pos_postaff ;
969
+    }
970
+
971
+    return $boucle;
972 972
 }
973 973
 
974 974
 
@@ -978,21 +978,21 @@  discard block
 block discarded – undo
978 978
  * @param null|object $boucle
979 979
  */
980 980
 function phraser_boucle_placeholder(&$champ, $boucle_placeholder = null, $boucle = null) {
981
-	static $boucles_connues = [];
982
-	// si c'est un appel pour memoriser une boucle, memorisons la
983
-	if (is_string($champ) and !empty($boucle_placeholder) and !empty($boucle)) {
984
-		$boucles_connues[$boucle_placeholder][$champ] = &$boucle;
985
-	}
986
-	else {
987
-		if (!empty($champ->nom_champ) and !empty($boucles_connues[$champ->nom_champ])) {
988
-			$placeholder = $champ->nom_champ;
989
-			$id = reset($champ->param[0][1]);
990
-			$id = $id->texte;
991
-			if (!empty($boucles_connues[$placeholder][$id])) {
992
-				$champ = $boucles_connues[$placeholder][$id];
993
-			}
994
-		}
995
-	}
981
+    static $boucles_connues = [];
982
+    // si c'est un appel pour memoriser une boucle, memorisons la
983
+    if (is_string($champ) and !empty($boucle_placeholder) and !empty($boucle)) {
984
+        $boucles_connues[$boucle_placeholder][$champ] = &$boucle;
985
+    }
986
+    else {
987
+        if (!empty($champ->nom_champ) and !empty($boucles_connues[$champ->nom_champ])) {
988
+            $placeholder = $champ->nom_champ;
989
+            $id = reset($champ->param[0][1]);
990
+            $id = $id->texte;
991
+            if (!empty($boucles_connues[$placeholder][$id])) {
992
+                $champ = $boucles_connues[$placeholder][$id];
993
+            }
994
+        }
995
+    }
996 996
 }
997 997
 
998 998
 
@@ -1005,274 +1005,274 @@  discard block
 block discarded – undo
1005 1005
  * @return string
1006 1006
  */
1007 1007
 function public_generer_boucle_placeholder($id_boucle, &$boucle, $boucle_placeholder, $nb_lignes) {
1008
-	$placeholder = "[(#{$boucle_placeholder}{" . $id_boucle . '})' . str_pad('', $nb_lignes, "\n") . ']';
1009
-	//memoriser la boucle a reinjecter
1010
-	$id_boucle = "$id_boucle";
1011
-	phraser_boucle_placeholder($id_boucle, $boucle_placeholder, $boucle);
1012
-	return $placeholder;
1008
+    $placeholder = "[(#{$boucle_placeholder}{" . $id_boucle . '})' . str_pad('', $nb_lignes, "\n") . ']';
1009
+    //memoriser la boucle a reinjecter
1010
+    $id_boucle = "$id_boucle";
1011
+    phraser_boucle_placeholder($id_boucle, $boucle_placeholder, $boucle);
1012
+    return $placeholder;
1013 1013
 }
1014 1014
 
1015 1015
 function public_phraser_html_dist($texte, $id_parent, &$boucles, $descr, $ligne_debut_texte = 1, $boucle_placeholder = null) {
1016 1016
 
1017
-	$all_res = [];
1018
-	// definir un placholder pour les boucles dont on est sur d'avoir aucune occurence dans le squelette
1019
-	if (is_null($boucle_placeholder)) {
1020
-		do {
1021
-			$boucle_placeholder = 'BOUCLE_PLACEHOLDER_' . strtoupper(md5(uniqid()));
1022
-		} while (strpos($texte, $boucle_placeholder) !== false);
1023
-	}
1024
-
1025
-	$ligne_debut_initial = $ligne_debut_texte;
1026
-	$pos_debut_texte = 0;
1027
-	while ($boucle = public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte)) {
1028
-		$err_b = ''; // indiquera s'il y a eu une erreur
1029
-		$result = new Boucle();
1030
-		$result->id_parent = $id_parent;
1031
-		$result->descr = $descr;
1032
-
1033
-		$pos_courante = $boucle['pos_boucle'];
1034
-		$pos_parent = $boucle['pos_parent'];
1035
-		$id_boucle_search = $id_boucle = $boucle['id_boucle'];
1036
-
1037
-		$ligne_preaff = $ligne_avant = $ligne_milieu = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_parent);
1038
-
1039
-		// boucle anonyme ?
1040
-		if (!strlen($id_boucle)) {
1041
-			$id_boucle = '_anon_L' . $ligne_milieu . '_' . substr(md5('anonyme:' . $id_parent . ':' . json_encode($boucle, JSON_THROW_ON_ERROR)), 0, 8);
1042
-		}
1043
-
1044
-		$pos_debut_boucle = $pos_courante;
1045
-
1046
-		$pos_milieu = $pos_parent;
1047
-
1048
-		// Regarder si on a une partie conditionnelle avant <B_xxx>
1049
-		if ($boucle['pos_precond'] !== false) {
1050
-			$pos_debut_boucle = $boucle['pos_precond'];
1051
-
1052
-			$pos_avant = $boucle['pos_precond_inside'];
1053
-			$result->avant = substr($texte, $pos_avant, $pos_courante - $pos_avant);
1054
-			$ligne_avant = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_avant);
1055
-		}
1056
-
1057
-		// Regarder si on a une partie inconditionnelle avant <BB_xxx>
1058
-		if ($boucle['pos_preaff'] !== false) {
1059
-			$end_preaff = $pos_debut_boucle;
1060
-
1061
-			$pos_preaff = $boucle['pos_preaff_inside'];
1062
-			$result->preaff = substr($texte, $pos_preaff, $end_preaff - $pos_preaff);
1063
-			$ligne_preaff = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_preaff);
1064
-		}
1065
-
1066
-		$result->id_boucle = $id_boucle;
1067
-
1068
-		if (
1069
-			!preg_match(SPEC_BOUCLE, $texte, $match, 0, $pos_milieu)
1070
-			or ($pos_match = strpos($texte, (string) $match[0], $pos_milieu)) === false
1071
-			or $pos_match > $pos_milieu
1072
-		) {
1073
-			$err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
1074
-			erreur_squelette($err_b, $result);
1075
-
1076
-			$ligne_debut_texte += public_compte_ligne($texte, $pos_debut_texte, $pos_courante + 1);
1077
-			$pos_debut_texte = $pos_courante + 1;
1078
-			continue;
1079
-		}
1080
-
1081
-		$result->type_requete = $match[0];
1082
-		$pos_milieu += strlen($match[0]);
1083
-		$pos_courante = $pos_milieu; // on s'en sert pour compter les lignes plus precisemment
1084
-
1085
-		$type = $match[1];
1086
-		$jointures = trim($match[2]);
1087
-		$table_optionnelle = ($match[3]);
1088
-		if ($jointures) {
1089
-			// on affecte pas ici les jointures explicites, mais dans la compilation
1090
-			// ou elles seront completees des jointures declarees
1091
-			$result->jointures_explicites = $jointures;
1092
-		}
1093
-
1094
-		if ($table_optionnelle) {
1095
-			$result->table_optionnelle = $type;
1096
-		}
1097
-
1098
-		// 1ere passe sur les criteres, vu comme des arguments sans fct
1099
-		// Resultat mis dans result->param
1100
-		$pos_fin_criteres = $pos_milieu;
1101
-		phraser_args($texte, '/>', '', $all_res, $result, $pos_fin_criteres);
1102
-
1103
-		// En 2e passe result->criteres contiendra un tableau
1104
-		// pour l'instant on met le source (chaine) :
1105
-		// si elle reste ici au final, c'est qu'elle contient une erreur
1106
-		$pos_courante = $pos_fin_criteres; // on s'en sert pour compter les lignes plus precisemment
1107
-		$result->criteres = substr($texte, $pos_milieu, $pos_fin_criteres - $pos_milieu);
1108
-		$pos_milieu = $pos_fin_criteres;
1109
-
1110
-		//
1111
-		// Recuperer la fin :
1112
-		//
1113
-		if ($texte[$pos_milieu] === '/') {
1114
-			// boucle autofermante : pas de partie conditionnelle apres
1115
-			$pos_courante += 2;
1116
-			$result->milieu = '';
1117
-		} else {
1118
-			$pos_milieu += 1;
1119
-
1120
-			$fin_boucle = BALISE_FIN_BOUCLE . $id_boucle_search . '>';
1121
-			$pos_fin = strpos($texte, $fin_boucle, $pos_milieu);
1122
-			if ($pos_fin === false) {
1123
-				$err_b = [
1124
-					'zbug_erreur_boucle_fermant',
1125
-					['id' => $id_boucle]
1126
-				];
1127
-				erreur_squelette($err_b, $result);
1128
-				$pos_courante += strlen($fin_boucle);
1129
-			}
1130
-			else {
1131
-				// verifier une eventuelle imbrication d'une boucle homonyme
1132
-				// (interdite, generera une erreur plus loin, mais permet de signaler la bonne erreur)
1133
-				$search_debut_boucle = BALISE_BOUCLE . $id_boucle_search . '(';
1134
-				$search_from = $pos_milieu;
1135
-				$nb_open = 1;
1136
-				$nb_close = 1;
1137
-				$maxiter = 0;
1138
-				do {
1139
-					while (
1140
-						$nb_close < $nb_open
1141
-						and $p = strpos($texte, $fin_boucle, $pos_fin + 1)
1142
-					) {
1143
-						$nb_close++;
1144
-						$pos_fin = $p;
1145
-					}
1146
-					// si on a pas trouve assez de boucles fermantes, sortir de la, on a fait de notre mieux
1147
-					if ($nb_close < $nb_open) {
1148
-						break;
1149
-					}
1150
-					while (
1151
-						$p = strpos($texte, $search_debut_boucle, $search_from)
1152
-						and $p < $pos_fin
1153
-					) {
1154
-						$nb_open++;
1155
-						$search_from = $p + 1;
1156
-					}
1157
-				} while ($nb_close < $nb_open and $maxiter++ < 5);
1158
-
1159
-				$pos_courante = $pos_fin + strlen($fin_boucle);
1160
-			}
1161
-			$result->milieu = substr($texte, $pos_milieu, $pos_fin - $pos_milieu);
1162
-		}
1163
-
1164
-		$ligne_suite = $ligne_apres = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_courante);
1165
-		$boucle = public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_courante, $result);
1166
-
1167
-		//
1168
-		// 1. Partie conditionnelle apres ?
1169
-		//
1170
-		if ($boucle['pos_postcond']) {
1171
-			$result->apres = substr($texte, $pos_courante, $boucle['pos_postcond'] - $pos_courante);
1172
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postcond_inside']);
1173
-			$pos_courante = $boucle['pos_postcond_inside'] ;
1174
-		}
1175
-
1176
-
1177
-		//
1178
-		// 2. Partie alternative apres ?
1179
-		//
1180
-		$ligne_altern = $ligne_suite;
1181
-		if ($boucle['pos_altern']) {
1182
-			$result->altern = substr($texte, $pos_courante, $boucle['pos_altern'] - $pos_courante);
1183
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_altern_inside']);
1184
-			$pos_courante = $boucle['pos_altern_inside'];
1185
-		}
1186
-
1187
-		//
1188
-		// 3. Partie footer non alternative ?
1189
-		//
1190
-		$ligne_postaff = $ligne_suite;
1191
-		if ($boucle['pos_postaff']) {
1192
-			$result->postaff = substr($texte, $pos_courante, $boucle['pos_postaff'] - $pos_courante);
1193
-			$ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postaff_inside']);
1194
-			$pos_courante = $boucle['pos_postaff_inside'];
1195
-		}
1196
-
1197
-		$result->ligne = $ligne_preaff;
1198
-
1199
-		if ($p = strpos($type, ':')) {
1200
-			$result->sql_serveur = substr($type, 0, $p);
1201
-			$type = substr($type, $p + 1);
1202
-		}
1203
-		$soustype = strtolower($type);
1204
-
1205
-		if (!isset($GLOBALS['table_des_tables'][$soustype])) {
1206
-			$soustype = $type;
1207
-		}
1208
-
1209
-		$result->type_requete = $soustype;
1210
-		// Lancer la 2e passe sur les criteres si la 1ere etait bonne
1211
-		if (!is_array($result->param)) {
1212
-			$err_b = true;
1213
-		} else {
1214
-			phraser_criteres($result->param, $result);
1215
-			if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
1216
-				$result->type_requete = TYPE_RECURSIF;
1217
-				$args = $result->param;
1218
-				array_unshift(
1219
-					$args,
1220
-					substr($type, strlen(TYPE_RECURSIF))
1221
-				);
1222
-				$result->param = $args;
1223
-			}
1224
-		}
1225
-
1226
-		$descr['id_mere_contexte'] = $id_boucle;
1227
-		$result->milieu = public_phraser_html_dist($result->milieu, $id_boucle, $boucles, $descr, $ligne_milieu, $boucle_placeholder);
1228
-		// reserver la place dans la pile des boucles pour compiler ensuite dans le bon ordre
1229
-		// ie les boucles qui apparaissent dans les partie conditionnelles doivent etre compilees apres cette boucle
1230
-		// si il y a deja une boucle de ce nom, cela declenchera une erreur ensuite
1231
-		if (empty($boucles[$id_boucle])) {
1232
-			$boucles[$id_boucle] = null;
1233
-		}
1234
-		$result->preaff = public_phraser_html_dist($result->preaff, $id_parent, $boucles, $descr, $ligne_preaff, $boucle_placeholder);
1235
-		$result->avant = public_phraser_html_dist($result->avant, $id_parent, $boucles, $descr, $ligne_avant, $boucle_placeholder);
1236
-		$result->apres = public_phraser_html_dist($result->apres, $id_parent, $boucles, $descr, $ligne_apres, $boucle_placeholder);
1237
-		$result->altern = public_phraser_html_dist($result->altern, $id_parent, $boucles, $descr, $ligne_altern, $boucle_placeholder);
1238
-		$result->postaff = public_phraser_html_dist($result->postaff, $id_parent, $boucles, $descr, $ligne_postaff, $boucle_placeholder);
1239
-
1240
-		// Prevenir le generateur de code que le squelette est faux
1241
-		if ($err_b) {
1242
-			$result->type_requete = false;
1243
-		}
1244
-
1245
-		// Verifier qu'il n'y a pas double definition
1246
-		// apres analyse des sous-parties (pas avant).
1247
-		if (!empty($boucles[$id_boucle])) {
1248
-			if ($boucles[$id_boucle]->type_requete !== false) {
1249
-				$err_b_d = [
1250
-					'zbug_erreur_boucle_double',
1251
-					['id' => $id_boucle]
1252
-				];
1253
-				erreur_squelette($err_b_d, $result);
1254
-				// Prevenir le generateur de code que le squelette est faux
1255
-				$boucles[$id_boucle]->type_requete = false;
1256
-			}
1257
-		} else {
1258
-			$boucles[$id_boucle] = $result;
1259
-		}
1260
-
1261
-		// remplacer la boucle par un placeholder qui compte le meme nombre de lignes
1262
-		$placeholder = public_generer_boucle_placeholder($id_boucle, $boucles[$id_boucle], $boucle_placeholder, $ligne_suite - $ligne_debut_texte);
1263
-		$longueur_boucle = $pos_courante - $boucle['debut_boucle'];
1264
-		$texte = substr_replace($texte, $placeholder, $boucle['debut_boucle'], $longueur_boucle);
1265
-		$pos_courante = $pos_courante - $longueur_boucle + strlen($placeholder);
1266
-
1267
-		// phraser la partie avant le debut de la boucle
1268
-		#$all_res = phraser_champs_etendus(substr($texte, $pos_debut_texte, $boucle['debut_boucle'] - $pos_debut_texte), $ligne_debut_texte, $all_res);
1269
-		#$all_res[] = &$boucles[$id_boucle];
1270
-
1271
-		$ligne_debut_texte = $ligne_suite;
1272
-		$pos_debut_texte = $pos_courante;
1273
-	}
1274
-
1275
-	$all_res = phraser_champs_etendus($texte, $ligne_debut_initial, $all_res);
1276
-
1277
-	return $all_res;
1017
+    $all_res = [];
1018
+    // definir un placholder pour les boucles dont on est sur d'avoir aucune occurence dans le squelette
1019
+    if (is_null($boucle_placeholder)) {
1020
+        do {
1021
+            $boucle_placeholder = 'BOUCLE_PLACEHOLDER_' . strtoupper(md5(uniqid()));
1022
+        } while (strpos($texte, $boucle_placeholder) !== false);
1023
+    }
1024
+
1025
+    $ligne_debut_initial = $ligne_debut_texte;
1026
+    $pos_debut_texte = 0;
1027
+    while ($boucle = public_trouver_premiere_boucle($texte, $id_parent, $descr, $pos_debut_texte)) {
1028
+        $err_b = ''; // indiquera s'il y a eu une erreur
1029
+        $result = new Boucle();
1030
+        $result->id_parent = $id_parent;
1031
+        $result->descr = $descr;
1032
+
1033
+        $pos_courante = $boucle['pos_boucle'];
1034
+        $pos_parent = $boucle['pos_parent'];
1035
+        $id_boucle_search = $id_boucle = $boucle['id_boucle'];
1036
+
1037
+        $ligne_preaff = $ligne_avant = $ligne_milieu = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_parent);
1038
+
1039
+        // boucle anonyme ?
1040
+        if (!strlen($id_boucle)) {
1041
+            $id_boucle = '_anon_L' . $ligne_milieu . '_' . substr(md5('anonyme:' . $id_parent . ':' . json_encode($boucle, JSON_THROW_ON_ERROR)), 0, 8);
1042
+        }
1043
+
1044
+        $pos_debut_boucle = $pos_courante;
1045
+
1046
+        $pos_milieu = $pos_parent;
1047
+
1048
+        // Regarder si on a une partie conditionnelle avant <B_xxx>
1049
+        if ($boucle['pos_precond'] !== false) {
1050
+            $pos_debut_boucle = $boucle['pos_precond'];
1051
+
1052
+            $pos_avant = $boucle['pos_precond_inside'];
1053
+            $result->avant = substr($texte, $pos_avant, $pos_courante - $pos_avant);
1054
+            $ligne_avant = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_avant);
1055
+        }
1056
+
1057
+        // Regarder si on a une partie inconditionnelle avant <BB_xxx>
1058
+        if ($boucle['pos_preaff'] !== false) {
1059
+            $end_preaff = $pos_debut_boucle;
1060
+
1061
+            $pos_preaff = $boucle['pos_preaff_inside'];
1062
+            $result->preaff = substr($texte, $pos_preaff, $end_preaff - $pos_preaff);
1063
+            $ligne_preaff = $ligne_debut_texte +  public_compte_ligne($texte, $pos_debut_texte, $pos_preaff);
1064
+        }
1065
+
1066
+        $result->id_boucle = $id_boucle;
1067
+
1068
+        if (
1069
+            !preg_match(SPEC_BOUCLE, $texte, $match, 0, $pos_milieu)
1070
+            or ($pos_match = strpos($texte, (string) $match[0], $pos_milieu)) === false
1071
+            or $pos_match > $pos_milieu
1072
+        ) {
1073
+            $err_b = ['zbug_erreur_boucle_syntaxe', ['id' => $id_boucle]];
1074
+            erreur_squelette($err_b, $result);
1075
+
1076
+            $ligne_debut_texte += public_compte_ligne($texte, $pos_debut_texte, $pos_courante + 1);
1077
+            $pos_debut_texte = $pos_courante + 1;
1078
+            continue;
1079
+        }
1080
+
1081
+        $result->type_requete = $match[0];
1082
+        $pos_milieu += strlen($match[0]);
1083
+        $pos_courante = $pos_milieu; // on s'en sert pour compter les lignes plus precisemment
1084
+
1085
+        $type = $match[1];
1086
+        $jointures = trim($match[2]);
1087
+        $table_optionnelle = ($match[3]);
1088
+        if ($jointures) {
1089
+            // on affecte pas ici les jointures explicites, mais dans la compilation
1090
+            // ou elles seront completees des jointures declarees
1091
+            $result->jointures_explicites = $jointures;
1092
+        }
1093
+
1094
+        if ($table_optionnelle) {
1095
+            $result->table_optionnelle = $type;
1096
+        }
1097
+
1098
+        // 1ere passe sur les criteres, vu comme des arguments sans fct
1099
+        // Resultat mis dans result->param
1100
+        $pos_fin_criteres = $pos_milieu;
1101
+        phraser_args($texte, '/>', '', $all_res, $result, $pos_fin_criteres);
1102
+
1103
+        // En 2e passe result->criteres contiendra un tableau
1104
+        // pour l'instant on met le source (chaine) :
1105
+        // si elle reste ici au final, c'est qu'elle contient une erreur
1106
+        $pos_courante = $pos_fin_criteres; // on s'en sert pour compter les lignes plus precisemment
1107
+        $result->criteres = substr($texte, $pos_milieu, $pos_fin_criteres - $pos_milieu);
1108
+        $pos_milieu = $pos_fin_criteres;
1109
+
1110
+        //
1111
+        // Recuperer la fin :
1112
+        //
1113
+        if ($texte[$pos_milieu] === '/') {
1114
+            // boucle autofermante : pas de partie conditionnelle apres
1115
+            $pos_courante += 2;
1116
+            $result->milieu = '';
1117
+        } else {
1118
+            $pos_milieu += 1;
1119
+
1120
+            $fin_boucle = BALISE_FIN_BOUCLE . $id_boucle_search . '>';
1121
+            $pos_fin = strpos($texte, $fin_boucle, $pos_milieu);
1122
+            if ($pos_fin === false) {
1123
+                $err_b = [
1124
+                    'zbug_erreur_boucle_fermant',
1125
+                    ['id' => $id_boucle]
1126
+                ];
1127
+                erreur_squelette($err_b, $result);
1128
+                $pos_courante += strlen($fin_boucle);
1129
+            }
1130
+            else {
1131
+                // verifier une eventuelle imbrication d'une boucle homonyme
1132
+                // (interdite, generera une erreur plus loin, mais permet de signaler la bonne erreur)
1133
+                $search_debut_boucle = BALISE_BOUCLE . $id_boucle_search . '(';
1134
+                $search_from = $pos_milieu;
1135
+                $nb_open = 1;
1136
+                $nb_close = 1;
1137
+                $maxiter = 0;
1138
+                do {
1139
+                    while (
1140
+                        $nb_close < $nb_open
1141
+                        and $p = strpos($texte, $fin_boucle, $pos_fin + 1)
1142
+                    ) {
1143
+                        $nb_close++;
1144
+                        $pos_fin = $p;
1145
+                    }
1146
+                    // si on a pas trouve assez de boucles fermantes, sortir de la, on a fait de notre mieux
1147
+                    if ($nb_close < $nb_open) {
1148
+                        break;
1149
+                    }
1150
+                    while (
1151
+                        $p = strpos($texte, $search_debut_boucle, $search_from)
1152
+                        and $p < $pos_fin
1153
+                    ) {
1154
+                        $nb_open++;
1155
+                        $search_from = $p + 1;
1156
+                    }
1157
+                } while ($nb_close < $nb_open and $maxiter++ < 5);
1158
+
1159
+                $pos_courante = $pos_fin + strlen($fin_boucle);
1160
+            }
1161
+            $result->milieu = substr($texte, $pos_milieu, $pos_fin - $pos_milieu);
1162
+        }
1163
+
1164
+        $ligne_suite = $ligne_apres = $ligne_debut_texte + public_compte_ligne($texte, $pos_debut_texte, $pos_courante);
1165
+        $boucle = public_trouver_fin_boucle($texte, $id_parent, $boucle, $pos_courante, $result);
1166
+
1167
+        //
1168
+        // 1. Partie conditionnelle apres ?
1169
+        //
1170
+        if ($boucle['pos_postcond']) {
1171
+            $result->apres = substr($texte, $pos_courante, $boucle['pos_postcond'] - $pos_courante);
1172
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postcond_inside']);
1173
+            $pos_courante = $boucle['pos_postcond_inside'] ;
1174
+        }
1175
+
1176
+
1177
+        //
1178
+        // 2. Partie alternative apres ?
1179
+        //
1180
+        $ligne_altern = $ligne_suite;
1181
+        if ($boucle['pos_altern']) {
1182
+            $result->altern = substr($texte, $pos_courante, $boucle['pos_altern'] - $pos_courante);
1183
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_altern_inside']);
1184
+            $pos_courante = $boucle['pos_altern_inside'];
1185
+        }
1186
+
1187
+        //
1188
+        // 3. Partie footer non alternative ?
1189
+        //
1190
+        $ligne_postaff = $ligne_suite;
1191
+        if ($boucle['pos_postaff']) {
1192
+            $result->postaff = substr($texte, $pos_courante, $boucle['pos_postaff'] - $pos_courante);
1193
+            $ligne_suite += public_compte_ligne($texte, $pos_courante, $boucle['pos_postaff_inside']);
1194
+            $pos_courante = $boucle['pos_postaff_inside'];
1195
+        }
1196
+
1197
+        $result->ligne = $ligne_preaff;
1198
+
1199
+        if ($p = strpos($type, ':')) {
1200
+            $result->sql_serveur = substr($type, 0, $p);
1201
+            $type = substr($type, $p + 1);
1202
+        }
1203
+        $soustype = strtolower($type);
1204
+
1205
+        if (!isset($GLOBALS['table_des_tables'][$soustype])) {
1206
+            $soustype = $type;
1207
+        }
1208
+
1209
+        $result->type_requete = $soustype;
1210
+        // Lancer la 2e passe sur les criteres si la 1ere etait bonne
1211
+        if (!is_array($result->param)) {
1212
+            $err_b = true;
1213
+        } else {
1214
+            phraser_criteres($result->param, $result);
1215
+            if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
1216
+                $result->type_requete = TYPE_RECURSIF;
1217
+                $args = $result->param;
1218
+                array_unshift(
1219
+                    $args,
1220
+                    substr($type, strlen(TYPE_RECURSIF))
1221
+                );
1222
+                $result->param = $args;
1223
+            }
1224
+        }
1225
+
1226
+        $descr['id_mere_contexte'] = $id_boucle;
1227
+        $result->milieu = public_phraser_html_dist($result->milieu, $id_boucle, $boucles, $descr, $ligne_milieu, $boucle_placeholder);
1228
+        // reserver la place dans la pile des boucles pour compiler ensuite dans le bon ordre
1229
+        // ie les boucles qui apparaissent dans les partie conditionnelles doivent etre compilees apres cette boucle
1230
+        // si il y a deja une boucle de ce nom, cela declenchera une erreur ensuite
1231
+        if (empty($boucles[$id_boucle])) {
1232
+            $boucles[$id_boucle] = null;
1233
+        }
1234
+        $result->preaff = public_phraser_html_dist($result->preaff, $id_parent, $boucles, $descr, $ligne_preaff, $boucle_placeholder);
1235
+        $result->avant = public_phraser_html_dist($result->avant, $id_parent, $boucles, $descr, $ligne_avant, $boucle_placeholder);
1236
+        $result->apres = public_phraser_html_dist($result->apres, $id_parent, $boucles, $descr, $ligne_apres, $boucle_placeholder);
1237
+        $result->altern = public_phraser_html_dist($result->altern, $id_parent, $boucles, $descr, $ligne_altern, $boucle_placeholder);
1238
+        $result->postaff = public_phraser_html_dist($result->postaff, $id_parent, $boucles, $descr, $ligne_postaff, $boucle_placeholder);
1239
+
1240
+        // Prevenir le generateur de code que le squelette est faux
1241
+        if ($err_b) {
1242
+            $result->type_requete = false;
1243
+        }
1244
+
1245
+        // Verifier qu'il n'y a pas double definition
1246
+        // apres analyse des sous-parties (pas avant).
1247
+        if (!empty($boucles[$id_boucle])) {
1248
+            if ($boucles[$id_boucle]->type_requete !== false) {
1249
+                $err_b_d = [
1250
+                    'zbug_erreur_boucle_double',
1251
+                    ['id' => $id_boucle]
1252
+                ];
1253
+                erreur_squelette($err_b_d, $result);
1254
+                // Prevenir le generateur de code que le squelette est faux
1255
+                $boucles[$id_boucle]->type_requete = false;
1256
+            }
1257
+        } else {
1258
+            $boucles[$id_boucle] = $result;
1259
+        }
1260
+
1261
+        // remplacer la boucle par un placeholder qui compte le meme nombre de lignes
1262
+        $placeholder = public_generer_boucle_placeholder($id_boucle, $boucles[$id_boucle], $boucle_placeholder, $ligne_suite - $ligne_debut_texte);
1263
+        $longueur_boucle = $pos_courante - $boucle['debut_boucle'];
1264
+        $texte = substr_replace($texte, $placeholder, $boucle['debut_boucle'], $longueur_boucle);
1265
+        $pos_courante = $pos_courante - $longueur_boucle + strlen($placeholder);
1266
+
1267
+        // phraser la partie avant le debut de la boucle
1268
+        #$all_res = phraser_champs_etendus(substr($texte, $pos_debut_texte, $boucle['debut_boucle'] - $pos_debut_texte), $ligne_debut_texte, $all_res);
1269
+        #$all_res[] = &$boucles[$id_boucle];
1270
+
1271
+        $ligne_debut_texte = $ligne_suite;
1272
+        $pos_debut_texte = $pos_courante;
1273
+    }
1274
+
1275
+    $all_res = phraser_champs_etendus($texte, $ligne_debut_initial, $all_res);
1276
+
1277
+    return $all_res;
1278 1278
 }
Please login to merge, or discard this patch.
ecrire/xml/valider.php 1 patch
Indentation   +320 added lines, -320 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
 /**
@@ -23,322 +23,322 @@  discard block
 block discarded – undo
23 23
  **/
24 24
 class ValidateurXML {
25 25
 
26
-	public function validerElement($phraseur, $name, $attrs) {
27
-		if (!($p = isset($this->dtc->elements[$name]))) {
28
-			if ($p = strpos($name, ':')) {
29
-				$name = substr($name, $p + 1);
30
-				$p = isset($this->dtc->elements[$name]);
31
-			}
32
-			if (!$p) {
33
-				coordonnees_erreur($this, " <b>$name</b>&nbsp;: "
34
-					. _T('zxml_inconnu_balise'));
35
-
36
-				return;
37
-			}
38
-		}
39
-		// controler les filles illegitimes, ca suffit
40
-		$depth = $this->depth;
41
-		$ouvrant = $this->ouvrant;
42
-		#spip_log("trouve $name apres " . $ouvrant[$depth]);
43
-		if (isset($ouvrant[$depth])) {
44
-			if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) {
45
-				$pere = $r[1];
46
-				#spip_log("pere $pere");
47
-				if (isset($this->dtc->elements[$pere])) {
48
-					$fils = $this->dtc->elements[$pere];
49
-					#spip_log("rejeton $name fils " . @join(',',$fils));
50
-					if (!($p = @in_array($name, $fils))) {
51
-						if ($p = strpos($name, ':')) {
52
-							$p = substr($name, $p + 1);
53
-							$p = @in_array($p, $fils);
54
-						}
55
-					}
56
-					if (!$p) {
57
-						$bons_peres = @join('</b>, <b>', $this->dtc->peres[$name]);
58
-						coordonnees_erreur($this, " <b>$name</b> "
59
-							. _T('zxml_non_fils')
60
-							. ' <b>'
61
-							. $pere
62
-							. '</b>'
63
-							. (!$bons_peres ? ''
64
-								: ('<p style="font-size: 80%"> ' . _T('zxml_mais_de') . ' <b>' . $bons_peres . '</b></p>')));
65
-					} elseif ($this->dtc->regles[$pere][0] == '/') {
66
-						$frat = substr($depth, 2);
67
-						if (!isset($this->fratrie[$frat])) {
68
-							$this->fratrie[$frat] = '';
69
-						}
70
-						$this->fratrie[$frat] .= "$name ";
71
-					}
72
-				}
73
-			}
74
-		}
75
-		// Init de la suite des balises a memoriser si regle difficile
76
-		if ($this->dtc->regles[$name] and $this->dtc->regles[$name][0] == '/') {
77
-			$this->fratrie[$depth] = '';
78
-		}
79
-		if (isset($this->dtc->attributs[$name])) {
80
-			foreach ($this->dtc->attributs[$name] as $n => $v) {
81
-				if (($v[1] == '#REQUIRED') and (!isset($attrs[$n]))) {
82
-					coordonnees_erreur($this, " <b>$n</b>"
83
-						. '&nbsp;:&nbsp;'
84
-						. _T('zxml_obligatoire_attribut')
85
-						. " <b>$name</b>");
86
-				}
87
-			}
88
-		}
89
-	}
90
-
91
-	public function validerAttribut($phraseur, $name, $val, $bal) {
92
-		// Si la balise est inconnue, eviter d'insister
93
-		if (!isset($this->dtc->attributs[$bal])) {
94
-			return;
95
-		}
96
-
97
-		$a = $this->dtc->attributs[$bal];
98
-		if (!isset($a[$name])) {
99
-			$bons = join(', ', array_keys($a));
100
-			if ($bons) {
101
-				$bons = " title=' " .
102
-					_T('zxml_connus_attributs') .
103
-					'&nbsp;: ' .
104
-					$bons .
105
-					"'";
106
-			}
107
-			$bons .= " style='font-weight: bold'";
108
-			coordonnees_erreur($this, " <b>$name</b> "
109
-				. _T('zxml_inconnu_attribut') . ' ' . _T('zxml_de')
110
-				. " <a$bons>$bal</a> ("
111
-				. _T('zxml_survoler')
112
-				. ')');
113
-		} else {
114
-			$type = $a[$name][0];
115
-			if (!preg_match('/^\w+$/', $type)) {
116
-				$this->valider_motif($phraseur, $name, $val, $bal, $type);
117
-			} else {
118
-				if (method_exists($this, $f = 'validerAttribut_' . $type)) {
119
-					$this->$f($phraseur, $name, $val, $bal);
120
-				}
121
-			}
122
-			#		else spip_log("$type type d'attribut inconnu");
123
-		}
124
-	}
125
-
126
-	public function validerAttribut_NMTOKEN($phraseur, $name, $val, $bal) {
127
-		$this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKEN);
128
-	}
129
-
130
-	public function validerAttribut_NMTOKENS($phraseur, $name, $val, $bal) {
131
-		$this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKENS);
132
-	}
133
-
134
-	public function validerAttribut_ID($phraseur, $name, $val, $bal) {
135
-		if (isset($this->ids[$val])) {
136
-			[$l, $c] = $this->ids[$val];
137
-			coordonnees_erreur($this, " <p><b>$val</b> "
138
-				. _T('zxml_valeur_attribut')
139
-				. " <b>$name</b> "
140
-				. _T('zxml_de')
141
-				. " <b>$bal</b> "
142
-				. _T('zxml_vu')
143
-				. " (L$l,C$c)");
144
-		} else {
145
-			$this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_ID);
146
-			$this->ids[$val] = [xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
147
-		}
148
-	}
149
-
150
-	public function validerAttribut_IDREF($phraseur, $name, $val, $bal) {
151
-		$this->idrefs[] = [$val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
152
-	}
153
-
154
-	public function validerAttribut_IDREFS($phraseur, $name, $val, $bal) {
155
-		$this->idrefss[] = [$val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
156
-	}
157
-
158
-	public function valider_motif($phraseur, $name, $val, $bal, $motif) {
159
-		if (!preg_match($motif, $val)) {
160
-			coordonnees_erreur($this, "<b>$val</b> "
161
-				. _T('zxml_valeur_attribut')
162
-				. " <b>$name</b> "
163
-				. _T('zxml_de')
164
-				. " <b>$bal</b> "
165
-				. _T('zxml_non_conforme')
166
-				. '</p><p>'
167
-				. '<b>' . $motif . '</b>');
168
-		}
169
-	}
170
-
171
-	public function valider_idref($nom, $ligne, $col) {
172
-		if (!isset($this->ids[$nom])) {
173
-			$this->err[] = [" <p><b>$nom</b> " . _T('zxml_inconnu_id'), $ligne, $col];
174
-		}
175
-	}
176
-
177
-	public function valider_passe2() {
178
-		if (!$this->err) {
179
-			foreach ($this->idrefs as $idref) {
180
-				[$nom, $ligne, $col] = $idref;
181
-				$this->valider_idref($nom, $ligne, $col);
182
-			}
183
-			foreach ($this->idrefss as $idref) {
184
-				[$noms, $ligne, $col] = $idref;
185
-				foreach (preg_split('/\s+/', $noms) as $nom) {
186
-					$this->valider_idref($nom, $ligne, $col);
187
-				}
188
-			}
189
-		}
190
-	}
191
-
192
-	public function debutElement($phraseur, $name, $attrs) {
193
-		if ($this->dtc->elements) {
194
-			$this->validerElement($phraseur, $name, $attrs);
195
-		}
196
-
197
-		if ($f = $this->process['debut']) {
198
-			$f($this, $name, $attrs);
199
-		}
200
-		$depth = $this->depth;
201
-		$this->debuts[$depth] = strlen($this->res);
202
-		foreach ($attrs as $k => $v) {
203
-			$this->validerAttribut($phraseur, $k, $v, $name);
204
-		}
205
-	}
206
-
207
-	public function finElement($phraseur, $name) {
208
-		$depth = $this->depth;
209
-		$contenu = $this->contenu;
210
-
211
-		$n = strlen($this->res);
212
-		$c = strlen(trim($contenu[$depth]));
213
-		$k = $this->debuts[$depth];
214
-
215
-		$regle = $this->dtc->regles[$name] ?? false;
216
-		$vide = ($regle == 'EMPTY');
217
-		// controler que les balises devant etre vides le sont
218
-		if ($vide) {
219
-			if ($n <> ($k + $c)) {
220
-				coordonnees_erreur($this, " <p><b>$name</b> " . _T('zxml_nonvide_balise'));
221
-			}
222
-			// pour les regles PCDATA ou iteration de disjonction, tout est fait
223
-		} elseif ($regle and ($regle != '*')) {
224
-			if ($regle == '+') {
225
-				// iteration de disjonction non vide: 1 balise au -
226
-				if ($n == $k) {
227
-					coordonnees_erreur($this, "<p>\n<b>$name</b> "
228
-						. _T('zxml_vide_balise'));
229
-				}
230
-			} else {
231
-				$f = $this->fratrie[substr($depth, 2)] ?? null;
232
-				if (is_null($f) or !preg_match($regle, $f)) {
233
-					coordonnees_erreur(
234
-						$this,
235
-						" <p>\n<b>$name</b> "
236
-						. _T('zxml_succession_fils_incorrecte')
237
-						. '&nbsp;: <b>'
238
-						. $f
239
-						. '</b>'
240
-					);
241
-				}
242
-			}
243
-		}
244
-		if ($f = $this->process['fin']) {
245
-			$f($this, $name, $vide);
246
-		}
247
-	}
248
-
249
-	public function textElement($phraseur, $data) {
250
-		if (trim($data)) {
251
-			$d = $this->depth;
252
-			$d = $this->ouvrant[$d];
253
-			preg_match('/^\s*(\S+)/', $d, $m);
254
-			if (isset($this->dtc->pcdata[$m[1]]) and ($this->dtc->pcdata[$m[1]])) {
255
-				coordonnees_erreur($this, ' <p><b>' . $m[1] . '</b> '
256
-					. _T('zxml_nonvide_balise')); // message a affiner
257
-			}
258
-		}
259
-		if ($f = $this->process['text']) {
260
-			$f($this, $data);
261
-		}
262
-	}
263
-
264
-	public function piElement($phraseur, $target, $data) {
265
-		if ($f = $this->process['pi']) {
266
-			$f($this, $target, $data);
267
-		}
268
-	}
269
-
270
-	// Denonciation des entitees XML inconnues
271
-	// Pour contourner le bug de conception de SAX qui ne signale pas si elles
272
-	// sont dans un attribut, les  entites les plus frequentes ont ete
273
-	// transcodees au prealable  (sauf & < > " que SAX traite correctement).
274
-	// On ne les verra donc pas passer a cette etape, contrairement a ce que
275
-	// le source de la page laisse legitimement supposer.
276
-
277
-	public function defaultElement($phraseur, $data) {
278
-		if (
279
-			!preg_match('/^<!--/', $data)
280
-			and (preg_match_all('/&([^;]*)?/', $data, $r, PREG_SET_ORDER))
281
-		) {
282
-			foreach ($r as $m) {
283
-				[$t, $e] = $m;
284
-				if (!isset($this->dtc->entites[$e])) {
285
-					coordonnees_erreur($this, " <b>$e</b> "
286
-						. _T('zxml_inconnu_entite')
287
-						. ' ');
288
-				}
289
-			}
290
-		}
291
-		if (isset($this->process['default']) and ($f = $this->process['default'])) {
292
-			$f($this, $data);
293
-		}
294
-	}
295
-
296
-	public function phraserTout($phraseur, $data) {
297
-		xml_parsestring($this, $data);
298
-
299
-		if (!$this->dtc or preg_match(',^' . _MESSAGE_DOCTYPE . ',', $data)) {
300
-			$this->err[] = ['DOCTYPE ?', 0, 0];
301
-		} else {
302
-			$this->valider_passe2();
303
-		}
304
-	}
305
-
306
-	/**
307
-	 * Constructeur
308
-	 *
309
-	 * @param array $process ?
310
-	 **/
311
-	public function __construct($process = []) {
312
-		if (is_array($process)) {
313
-			$this->process = $process;
314
-		}
315
-	}
316
-
317
-	public $ids = [];
318
-	public $idrefs = [];
319
-	public $idrefss = [];
320
-	public $debuts = [];
321
-	public $fratrie = [];
322
-
323
-	public $dtc = null;
324
-	public $sax = null;
325
-	public $depth = '';
326
-	public $entete = '';
327
-	public $page = '';
328
-	public $res = '';
329
-	public array $err = [];
330
-	public array $contenu = [];
331
-	public array $versions = [];
332
-
333
-	public array $ouvrant = [];
334
-	public array $reperes = [];
335
-	public array $process = [
336
-		'debut' => 'xml_debutElement',
337
-		'fin' => 'xml_finElement',
338
-		'text' => 'xml_textElement',
339
-		'pi' => 'xml_piElement',
340
-		'default' => 'xml_defaultElement'
341
-	];
26
+    public function validerElement($phraseur, $name, $attrs) {
27
+        if (!($p = isset($this->dtc->elements[$name]))) {
28
+            if ($p = strpos($name, ':')) {
29
+                $name = substr($name, $p + 1);
30
+                $p = isset($this->dtc->elements[$name]);
31
+            }
32
+            if (!$p) {
33
+                coordonnees_erreur($this, " <b>$name</b>&nbsp;: "
34
+                    . _T('zxml_inconnu_balise'));
35
+
36
+                return;
37
+            }
38
+        }
39
+        // controler les filles illegitimes, ca suffit
40
+        $depth = $this->depth;
41
+        $ouvrant = $this->ouvrant;
42
+        #spip_log("trouve $name apres " . $ouvrant[$depth]);
43
+        if (isset($ouvrant[$depth])) {
44
+            if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) {
45
+                $pere = $r[1];
46
+                #spip_log("pere $pere");
47
+                if (isset($this->dtc->elements[$pere])) {
48
+                    $fils = $this->dtc->elements[$pere];
49
+                    #spip_log("rejeton $name fils " . @join(',',$fils));
50
+                    if (!($p = @in_array($name, $fils))) {
51
+                        if ($p = strpos($name, ':')) {
52
+                            $p = substr($name, $p + 1);
53
+                            $p = @in_array($p, $fils);
54
+                        }
55
+                    }
56
+                    if (!$p) {
57
+                        $bons_peres = @join('</b>, <b>', $this->dtc->peres[$name]);
58
+                        coordonnees_erreur($this, " <b>$name</b> "
59
+                            . _T('zxml_non_fils')
60
+                            . ' <b>'
61
+                            . $pere
62
+                            . '</b>'
63
+                            . (!$bons_peres ? ''
64
+                                : ('<p style="font-size: 80%"> ' . _T('zxml_mais_de') . ' <b>' . $bons_peres . '</b></p>')));
65
+                    } elseif ($this->dtc->regles[$pere][0] == '/') {
66
+                        $frat = substr($depth, 2);
67
+                        if (!isset($this->fratrie[$frat])) {
68
+                            $this->fratrie[$frat] = '';
69
+                        }
70
+                        $this->fratrie[$frat] .= "$name ";
71
+                    }
72
+                }
73
+            }
74
+        }
75
+        // Init de la suite des balises a memoriser si regle difficile
76
+        if ($this->dtc->regles[$name] and $this->dtc->regles[$name][0] == '/') {
77
+            $this->fratrie[$depth] = '';
78
+        }
79
+        if (isset($this->dtc->attributs[$name])) {
80
+            foreach ($this->dtc->attributs[$name] as $n => $v) {
81
+                if (($v[1] == '#REQUIRED') and (!isset($attrs[$n]))) {
82
+                    coordonnees_erreur($this, " <b>$n</b>"
83
+                        . '&nbsp;:&nbsp;'
84
+                        . _T('zxml_obligatoire_attribut')
85
+                        . " <b>$name</b>");
86
+                }
87
+            }
88
+        }
89
+    }
90
+
91
+    public function validerAttribut($phraseur, $name, $val, $bal) {
92
+        // Si la balise est inconnue, eviter d'insister
93
+        if (!isset($this->dtc->attributs[$bal])) {
94
+            return;
95
+        }
96
+
97
+        $a = $this->dtc->attributs[$bal];
98
+        if (!isset($a[$name])) {
99
+            $bons = join(', ', array_keys($a));
100
+            if ($bons) {
101
+                $bons = " title=' " .
102
+                    _T('zxml_connus_attributs') .
103
+                    '&nbsp;: ' .
104
+                    $bons .
105
+                    "'";
106
+            }
107
+            $bons .= " style='font-weight: bold'";
108
+            coordonnees_erreur($this, " <b>$name</b> "
109
+                . _T('zxml_inconnu_attribut') . ' ' . _T('zxml_de')
110
+                . " <a$bons>$bal</a> ("
111
+                . _T('zxml_survoler')
112
+                . ')');
113
+        } else {
114
+            $type = $a[$name][0];
115
+            if (!preg_match('/^\w+$/', $type)) {
116
+                $this->valider_motif($phraseur, $name, $val, $bal, $type);
117
+            } else {
118
+                if (method_exists($this, $f = 'validerAttribut_' . $type)) {
119
+                    $this->$f($phraseur, $name, $val, $bal);
120
+                }
121
+            }
122
+            #		else spip_log("$type type d'attribut inconnu");
123
+        }
124
+    }
125
+
126
+    public function validerAttribut_NMTOKEN($phraseur, $name, $val, $bal) {
127
+        $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKEN);
128
+    }
129
+
130
+    public function validerAttribut_NMTOKENS($phraseur, $name, $val, $bal) {
131
+        $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKENS);
132
+    }
133
+
134
+    public function validerAttribut_ID($phraseur, $name, $val, $bal) {
135
+        if (isset($this->ids[$val])) {
136
+            [$l, $c] = $this->ids[$val];
137
+            coordonnees_erreur($this, " <p><b>$val</b> "
138
+                . _T('zxml_valeur_attribut')
139
+                . " <b>$name</b> "
140
+                . _T('zxml_de')
141
+                . " <b>$bal</b> "
142
+                . _T('zxml_vu')
143
+                . " (L$l,C$c)");
144
+        } else {
145
+            $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_ID);
146
+            $this->ids[$val] = [xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
147
+        }
148
+    }
149
+
150
+    public function validerAttribut_IDREF($phraseur, $name, $val, $bal) {
151
+        $this->idrefs[] = [$val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
152
+    }
153
+
154
+    public function validerAttribut_IDREFS($phraseur, $name, $val, $bal) {
155
+        $this->idrefss[] = [$val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)];
156
+    }
157
+
158
+    public function valider_motif($phraseur, $name, $val, $bal, $motif) {
159
+        if (!preg_match($motif, $val)) {
160
+            coordonnees_erreur($this, "<b>$val</b> "
161
+                . _T('zxml_valeur_attribut')
162
+                . " <b>$name</b> "
163
+                . _T('zxml_de')
164
+                . " <b>$bal</b> "
165
+                . _T('zxml_non_conforme')
166
+                . '</p><p>'
167
+                . '<b>' . $motif . '</b>');
168
+        }
169
+    }
170
+
171
+    public function valider_idref($nom, $ligne, $col) {
172
+        if (!isset($this->ids[$nom])) {
173
+            $this->err[] = [" <p><b>$nom</b> " . _T('zxml_inconnu_id'), $ligne, $col];
174
+        }
175
+    }
176
+
177
+    public function valider_passe2() {
178
+        if (!$this->err) {
179
+            foreach ($this->idrefs as $idref) {
180
+                [$nom, $ligne, $col] = $idref;
181
+                $this->valider_idref($nom, $ligne, $col);
182
+            }
183
+            foreach ($this->idrefss as $idref) {
184
+                [$noms, $ligne, $col] = $idref;
185
+                foreach (preg_split('/\s+/', $noms) as $nom) {
186
+                    $this->valider_idref($nom, $ligne, $col);
187
+                }
188
+            }
189
+        }
190
+    }
191
+
192
+    public function debutElement($phraseur, $name, $attrs) {
193
+        if ($this->dtc->elements) {
194
+            $this->validerElement($phraseur, $name, $attrs);
195
+        }
196
+
197
+        if ($f = $this->process['debut']) {
198
+            $f($this, $name, $attrs);
199
+        }
200
+        $depth = $this->depth;
201
+        $this->debuts[$depth] = strlen($this->res);
202
+        foreach ($attrs as $k => $v) {
203
+            $this->validerAttribut($phraseur, $k, $v, $name);
204
+        }
205
+    }
206
+
207
+    public function finElement($phraseur, $name) {
208
+        $depth = $this->depth;
209
+        $contenu = $this->contenu;
210
+
211
+        $n = strlen($this->res);
212
+        $c = strlen(trim($contenu[$depth]));
213
+        $k = $this->debuts[$depth];
214
+
215
+        $regle = $this->dtc->regles[$name] ?? false;
216
+        $vide = ($regle == 'EMPTY');
217
+        // controler que les balises devant etre vides le sont
218
+        if ($vide) {
219
+            if ($n <> ($k + $c)) {
220
+                coordonnees_erreur($this, " <p><b>$name</b> " . _T('zxml_nonvide_balise'));
221
+            }
222
+            // pour les regles PCDATA ou iteration de disjonction, tout est fait
223
+        } elseif ($regle and ($regle != '*')) {
224
+            if ($regle == '+') {
225
+                // iteration de disjonction non vide: 1 balise au -
226
+                if ($n == $k) {
227
+                    coordonnees_erreur($this, "<p>\n<b>$name</b> "
228
+                        . _T('zxml_vide_balise'));
229
+                }
230
+            } else {
231
+                $f = $this->fratrie[substr($depth, 2)] ?? null;
232
+                if (is_null($f) or !preg_match($regle, $f)) {
233
+                    coordonnees_erreur(
234
+                        $this,
235
+                        " <p>\n<b>$name</b> "
236
+                        . _T('zxml_succession_fils_incorrecte')
237
+                        . '&nbsp;: <b>'
238
+                        . $f
239
+                        . '</b>'
240
+                    );
241
+                }
242
+            }
243
+        }
244
+        if ($f = $this->process['fin']) {
245
+            $f($this, $name, $vide);
246
+        }
247
+    }
248
+
249
+    public function textElement($phraseur, $data) {
250
+        if (trim($data)) {
251
+            $d = $this->depth;
252
+            $d = $this->ouvrant[$d];
253
+            preg_match('/^\s*(\S+)/', $d, $m);
254
+            if (isset($this->dtc->pcdata[$m[1]]) and ($this->dtc->pcdata[$m[1]])) {
255
+                coordonnees_erreur($this, ' <p><b>' . $m[1] . '</b> '
256
+                    . _T('zxml_nonvide_balise')); // message a affiner
257
+            }
258
+        }
259
+        if ($f = $this->process['text']) {
260
+            $f($this, $data);
261
+        }
262
+    }
263
+
264
+    public function piElement($phraseur, $target, $data) {
265
+        if ($f = $this->process['pi']) {
266
+            $f($this, $target, $data);
267
+        }
268
+    }
269
+
270
+    // Denonciation des entitees XML inconnues
271
+    // Pour contourner le bug de conception de SAX qui ne signale pas si elles
272
+    // sont dans un attribut, les  entites les plus frequentes ont ete
273
+    // transcodees au prealable  (sauf & < > " que SAX traite correctement).
274
+    // On ne les verra donc pas passer a cette etape, contrairement a ce que
275
+    // le source de la page laisse legitimement supposer.
276
+
277
+    public function defaultElement($phraseur, $data) {
278
+        if (
279
+            !preg_match('/^<!--/', $data)
280
+            and (preg_match_all('/&([^;]*)?/', $data, $r, PREG_SET_ORDER))
281
+        ) {
282
+            foreach ($r as $m) {
283
+                [$t, $e] = $m;
284
+                if (!isset($this->dtc->entites[$e])) {
285
+                    coordonnees_erreur($this, " <b>$e</b> "
286
+                        . _T('zxml_inconnu_entite')
287
+                        . ' ');
288
+                }
289
+            }
290
+        }
291
+        if (isset($this->process['default']) and ($f = $this->process['default'])) {
292
+            $f($this, $data);
293
+        }
294
+    }
295
+
296
+    public function phraserTout($phraseur, $data) {
297
+        xml_parsestring($this, $data);
298
+
299
+        if (!$this->dtc or preg_match(',^' . _MESSAGE_DOCTYPE . ',', $data)) {
300
+            $this->err[] = ['DOCTYPE ?', 0, 0];
301
+        } else {
302
+            $this->valider_passe2();
303
+        }
304
+    }
305
+
306
+    /**
307
+     * Constructeur
308
+     *
309
+     * @param array $process ?
310
+     **/
311
+    public function __construct($process = []) {
312
+        if (is_array($process)) {
313
+            $this->process = $process;
314
+        }
315
+    }
316
+
317
+    public $ids = [];
318
+    public $idrefs = [];
319
+    public $idrefss = [];
320
+    public $debuts = [];
321
+    public $fratrie = [];
322
+
323
+    public $dtc = null;
324
+    public $sax = null;
325
+    public $depth = '';
326
+    public $entete = '';
327
+    public $page = '';
328
+    public $res = '';
329
+    public array $err = [];
330
+    public array $contenu = [];
331
+    public array $versions = [];
332
+
333
+    public array $ouvrant = [];
334
+    public array $reperes = [];
335
+    public array $process = [
336
+        'debut' => 'xml_debutElement',
337
+        'fin' => 'xml_finElement',
338
+        'text' => 'xml_textElement',
339
+        'pi' => 'xml_piElement',
340
+        'default' => 'xml_defaultElement'
341
+    ];
342 342
 }
343 343
 
344 344
 
@@ -348,8 +348,8 @@  discard block
 block discarded – undo
348 348
  *
349 349
  **/
350 350
 function xml_valider_dist($page, $apply = false, $process = false, $doctype = '', $charset = null) {
351
-	$f = new ValidateurXML($process);
352
-	$sax = charger_fonction('sax', 'xml');
351
+    $f = new ValidateurXML($process);
352
+    $sax = charger_fonction('sax', 'xml');
353 353
 
354
-	return $sax($page, $apply, $f, $doctype, $charset);
354
+    return $sax($page, $apply, $f, $doctype, $charset);
355 355
 }
Please login to merge, or discard this patch.
ecrire/req/sqlite_generique.php 1 patch
Indentation   +1999 added lines, -1999 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
  */
19 19
 
20 20
 if (!defined('_ECRIRE_INC_VERSION')) {
21
-	return;
21
+    return;
22 22
 }
23 23
 
24 24
 // TODO: get/set_caracteres ?
@@ -42,91 +42,91 @@  discard block
 block discarded – undo
42 42
  * @return array|bool
43 43
  */
44 44
 function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $sqlite_version = '') {
45
-	static $last_connect = [];
46
-
47
-	// si provient de selectdb
48
-	// un code pour etre sur que l'on vient de select_db()
49
-	if (strpos($db, $code = '@selectdb@') !== false) {
50
-		foreach (['addr', 'port', 'login', 'pass', 'prefixe'] as $a) {
51
-			$$a = $last_connect[$a];
52
-		}
53
-		$db = str_replace($code, '', $db);
54
-	}
55
-
56
-	/*
45
+    static $last_connect = [];
46
+
47
+    // si provient de selectdb
48
+    // un code pour etre sur que l'on vient de select_db()
49
+    if (strpos($db, $code = '@selectdb@') !== false) {
50
+        foreach (['addr', 'port', 'login', 'pass', 'prefixe'] as $a) {
51
+            $$a = $last_connect[$a];
52
+        }
53
+        $db = str_replace($code, '', $db);
54
+    }
55
+
56
+    /*
57 57
 	 * En sqlite, seule l'adresse du fichier est importante.
58 58
 	 * Ce sera $db le nom,
59 59
 	 * le path est $addr
60 60
 	 * (_DIR_DB si $addr est vide)
61 61
 	 */
62
-	_sqlite_init();
63
-
64
-	// determiner le dossier de la base : $addr ou _DIR_DB
65
-	$f = _DIR_DB;
66
-	if ($addr and strpos($addr, '/') !== false) {
67
-		$f = rtrim($addr, '/') . '/';
68
-	}
69
-
70
-	// un nom de base demande et impossible d'obtenir la base, on s'en va :
71
-	// il faut que la base existe ou que le repertoire parent soit writable
72
-	if ($db and !is_file($f .= $db . '.sqlite') and !is_writable(dirname($f))) {
73
-		spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.' . _LOG_HS);
74
-
75
-		return false;
76
-	}
77
-
78
-	// charger les modules sqlite au besoin
79
-	if (!_sqlite_charger_version($sqlite_version)) {
80
-		spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.' . _LOG_HS);
81
-
82
-		return false;
83
-	}
84
-
85
-	// chargement des constantes
86
-	// il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
87
-	$define = 'spip_sqlite' . $sqlite_version . '_constantes';
88
-	$define();
89
-
90
-	$ok = false;
91
-	if (!$db) {
92
-		// si pas de db ->
93
-		// base temporaire tant qu'on ne connait pas son vrai nom
94
-		// pour tester la connexion
95
-		$db = '_sqlite' . $sqlite_version . '_install';
96
-		$tmp = _DIR_DB . $db . '.sqlite';
97
-		$ok = $link = new \PDO("sqlite:$tmp");
98
-	} else {
99
-		// Ouvrir (eventuellement creer la base)
100
-		$ok = $link = new \PDO("sqlite:$f");
101
-	}
102
-
103
-	if (!$ok) {
104
-		$e = _sqlite_last_error_from_link($link);
105
-		spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.' . _LOG_HS);
106
-
107
-		return false;
108
-	}
109
-
110
-	if ($link) {
111
-		$last_connect = [
112
-			'addr' => $addr,
113
-			'port' => $port,
114
-			'login' => $login,
115
-			'pass' => $pass,
116
-			'db' => $db,
117
-			'prefixe' => $prefixe,
118
-		];
119
-		// etre sur qu'on definit bien les fonctions a chaque nouvelle connexion
120
-		include_spip('req/sqlite_fonctions');
121
-		_sqlite_init_functions($link);
122
-	}
123
-
124
-	return [
125
-		'db' => $db,
126
-		'prefixe' => $prefixe ? $prefixe : $db,
127
-		'link' => $link,
128
-		'total_requetes' => 0,
129
-	];
62
+    _sqlite_init();
63
+
64
+    // determiner le dossier de la base : $addr ou _DIR_DB
65
+    $f = _DIR_DB;
66
+    if ($addr and strpos($addr, '/') !== false) {
67
+        $f = rtrim($addr, '/') . '/';
68
+    }
69
+
70
+    // un nom de base demande et impossible d'obtenir la base, on s'en va :
71
+    // il faut que la base existe ou que le repertoire parent soit writable
72
+    if ($db and !is_file($f .= $db . '.sqlite') and !is_writable(dirname($f))) {
73
+        spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.' . _LOG_HS);
74
+
75
+        return false;
76
+    }
77
+
78
+    // charger les modules sqlite au besoin
79
+    if (!_sqlite_charger_version($sqlite_version)) {
80
+        spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.' . _LOG_HS);
81
+
82
+        return false;
83
+    }
84
+
85
+    // chargement des constantes
86
+    // il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
87
+    $define = 'spip_sqlite' . $sqlite_version . '_constantes';
88
+    $define();
89
+
90
+    $ok = false;
91
+    if (!$db) {
92
+        // si pas de db ->
93
+        // base temporaire tant qu'on ne connait pas son vrai nom
94
+        // pour tester la connexion
95
+        $db = '_sqlite' . $sqlite_version . '_install';
96
+        $tmp = _DIR_DB . $db . '.sqlite';
97
+        $ok = $link = new \PDO("sqlite:$tmp");
98
+    } else {
99
+        // Ouvrir (eventuellement creer la base)
100
+        $ok = $link = new \PDO("sqlite:$f");
101
+    }
102
+
103
+    if (!$ok) {
104
+        $e = _sqlite_last_error_from_link($link);
105
+        spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.' . _LOG_HS);
106
+
107
+        return false;
108
+    }
109
+
110
+    if ($link) {
111
+        $last_connect = [
112
+            'addr' => $addr,
113
+            'port' => $port,
114
+            'login' => $login,
115
+            'pass' => $pass,
116
+            'db' => $db,
117
+            'prefixe' => $prefixe,
118
+        ];
119
+        // etre sur qu'on definit bien les fonctions a chaque nouvelle connexion
120
+        include_spip('req/sqlite_fonctions');
121
+        _sqlite_init_functions($link);
122
+    }
123
+
124
+    return [
125
+        'db' => $db,
126
+        'prefixe' => $prefixe ? $prefixe : $db,
127
+        'link' => $link,
128
+        'total_requetes' => 0,
129
+    ];
130 130
 }
131 131
 
132 132
 
@@ -145,14 +145,14 @@  discard block
 block discarded – undo
145 145
  *    Resultat de la requete
146 146
  */
147 147
 function spip_sqlite_query($query, $serveur = '', $requeter = true) {
148
-	#spip_log("spip_sqlite_query() > $query",'sqlite.'._LOG_DEBUG);
149
-	#_sqlite_init(); // fait la premiere fois dans spip_sqlite
150
-	$query = spip_sqlite::traduire_requete($query, $serveur);
151
-	if (!$requeter) {
152
-		return $query;
153
-	}
148
+    #spip_log("spip_sqlite_query() > $query",'sqlite.'._LOG_DEBUG);
149
+    #_sqlite_init(); // fait la premiere fois dans spip_sqlite
150
+    $query = spip_sqlite::traduire_requete($query, $serveur);
151
+    if (!$requeter) {
152
+        return $query;
153
+    }
154 154
 
155
-	return spip_sqlite::executer_requete($query, $serveur);
155
+    return spip_sqlite::executer_requete($query, $serveur);
156 156
 }
157 157
 
158 158
 
@@ -169,11 +169,11 @@  discard block
 block discarded – undo
169 169
  */
170 170
 function spip_sqlite_alter($query, $serveur = '', $requeter = true) {
171 171
 
172
-	$query = spip_sqlite_query("ALTER $query", $serveur, false);
173
-	// traduire la requete pour recuperer les bons noms de table
174
-	$query = spip_sqlite::traduire_requete($query, $serveur);
172
+    $query = spip_sqlite_query("ALTER $query", $serveur, false);
173
+    // traduire la requete pour recuperer les bons noms de table
174
+    $query = spip_sqlite::traduire_requete($query, $serveur);
175 175
 
176
-	/*
176
+    /*
177 177
 		 * la il faut faire les transformations
178 178
 		 * si ALTER TABLE x (DROP|CHANGE) y
179 179
 		 *
@@ -182,251 +182,251 @@  discard block
 block discarded – undo
182 182
 		 * 3) faire chaque requete independemment
183 183
 		 */
184 184
 
185
-	// 1
186
-	if (preg_match('/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is', $query, $regs)) {
187
-		$debut = $regs[1];
188
-		$table = $regs[3];
189
-		$suite = $regs[4];
190
-	} else {
191
-		spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.' . _LOG_ERREUR);
192
-
193
-		return false;
194
-	}
195
-
196
-	// 2
197
-	// il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
198
-	// tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
199
-	// ou revoir l'api de sql_alter en creant un
200
-	// sql_alter_table($table,array($actions));
201
-	$todo = explode(',', $suite);
202
-
203
-	// on remet les morceaux dechires ensembles... que c'est laid !
204
-	$todo2 = [];
205
-	$i = 0;
206
-	$ouverte = false;
207
-	while ($do = array_shift($todo)) {
208
-		$todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
209
-		$o = (false !== strpos($do, '('));
210
-		$f = (false !== strpos($do, ')'));
211
-		if ($o and !$f) {
212
-			$ouverte = true;
213
-		} elseif ($f) {
214
-			$ouverte = false;
215
-		}
216
-		if (!$ouverte) {
217
-			$i++;
218
-		}
219
-	}
220
-
221
-	// 3
222
-	$resultats = [];
223
-	foreach ($todo2 as $do) {
224
-		$do = trim($do);
225
-		if (
226
-			!preg_match('/(DROP PRIMARY KEY|DROP KEY|DROP INDEX|DROP COLUMN|DROP'
227
-			. '|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
228
-			. '|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
229
-			. '|ADD COLUMN|ADD'
230
-			. ')\s*([^\s]*)\s*(.*)?/i', $do, $matches)
231
-		) {
232
-			spip_log(
233
-				"SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)",
234
-				'sqlite.' . _LOG_ERREUR
235
-			);
236
-
237
-			return false;
238
-		}
239
-
240
-		$cle = strtoupper($matches[1]);
241
-		$colonne_origine = $matches[2];
242
-		$colonne_destination = '';
243
-
244
-		$def = $matches[3];
245
-
246
-		// eluder une eventuelle clause before|after|first inutilisable
247
-		$defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is', '', $def));
248
-		$defo = $defr; // garder la def d'origine pour certains cas
249
-		// remplacer les definitions venant de mysql
250
-		$defr = _sqlite_remplacements_definitions_table($defr);
251
-
252
-		// reinjecter dans le do
253
-		$do = str_replace($def, $defr, $do);
254
-		$def = $defr;
255
-
256
-		switch ($cle) {
257
-			// suppression d'un index
258
-			case 'DROP KEY':
259
-			case 'DROP INDEX':
260
-				$nom_index = $colonne_origine;
261
-				spip_sqlite_drop_index($nom_index, $table, $serveur);
262
-				break;
263
-
264
-			// suppression d'une pk
265
-			case 'DROP PRIMARY KEY':
266
-				if (
267
-					!_sqlite_modifier_table(
268
-						$table,
269
-						$colonne_origine,
270
-						['key' => ['PRIMARY KEY' => '']],
271
-						$serveur
272
-					)
273
-				) {
274
-					return false;
275
-				}
276
-				break;
277
-			// suppression d'une colonne
278
-			case 'DROP COLUMN':
279
-			case 'DROP':
280
-				if (
281
-					!_sqlite_modifier_table(
282
-						$table,
283
-						[$colonne_origine => ''],
284
-						[],
285
-						$serveur
286
-					)
287
-				) {
288
-					return false;
289
-				}
290
-				break;
291
-
292
-			case 'CHANGE COLUMN':
293
-			case 'CHANGE':
294
-				// recuperer le nom de la future colonne
295
-				// on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
296
-				// en tenant compte de la cle primaire (ce qui est mieux)
297
-				$def = trim($defo);
298
-				$colonne_destination = substr($def, 0, strpos($def, ' '));
299
-				$def = substr($def, strlen($colonne_destination) + 1);
300
-
301
-				if (
302
-					!_sqlite_modifier_table(
303
-						$table,
304
-						[$colonne_origine => $colonne_destination],
305
-						['field' => [$colonne_destination => $def]],
306
-						$serveur
307
-					)
308
-				) {
309
-					return false;
310
-				}
311
-				break;
312
-
313
-			case 'MODIFY':
314
-				// on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
315
-				// en tenant compte de la cle primaire (ce qui est mieux)
316
-				if (
317
-					!_sqlite_modifier_table(
318
-						$table,
319
-						$colonne_origine,
320
-						['field' => [$colonne_origine => $defo]],
321
-						$serveur
322
-					)
323
-				) {
324
-					return false;
325
-				}
326
-				break;
327
-
328
-			// pas geres en sqlite2
329
-			case 'RENAME':
330
-				$do = 'RENAME TO' . substr($do, 6);
331
-			case 'RENAME TO':
332
-				if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
333
-					spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
334
-
335
-					return false;
336
-				}
337
-				break;
338
-
339
-			// ajout d'une pk
340
-			case 'ADD PRIMARY KEY':
341
-				$pk = trim(substr($do, 16));
342
-				$pk = ($pk[0] == '(') ? substr($pk, 1, -1) : $pk;
343
-				if (
344
-					!_sqlite_modifier_table(
345
-						$table,
346
-						$colonne_origine,
347
-						['key' => ['PRIMARY KEY' => $pk]],
348
-						$serveur
349
-					)
350
-				) {
351
-					return false;
352
-				}
353
-				break;
354
-			// ajout d'un index
355
-			case 'ADD UNIQUE KEY':
356
-			case 'ADD UNIQUE':
357
-				$unique = true;
358
-			case 'ADD INDEX':
359
-			case 'ADD KEY':
360
-				if (!isset($unique)) {
361
-					$unique = false;
362
-				}
363
-				// peut etre "(colonne)" ou "nom_index (colonnes)"
364
-				// bug potentiel si qqn met "(colonne, colonne)"
365
-				//
366
-				// nom_index (colonnes)
367
-				if ($def) {
368
-					$colonnes = substr($def, 1, -1);
369
-					$nom_index = $colonne_origine;
370
-				} else {
371
-					// (colonne)
372
-					if ($colonne_origine[0] == '(') {
373
-						$colonnes = substr($colonne_origine, 1, -1);
374
-						if (false !== strpos(',', $colonnes)) {
375
-							spip_log('SQLite : Erreur, impossible de creer un index sur plusieurs colonnes'
376
-								. " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite.' . _LOG_ERREUR);
377
-							break;
378
-						} else {
379
-							$nom_index = $colonnes;
380
-						}
381
-					} // nom_index
382
-					else {
383
-						$nom_index = $colonnes = $colonne_origine;
384
-					}
385
-				}
386
-				spip_sqlite_create_index($nom_index, $table, $colonnes, $unique, $serveur);
387
-				break;
388
-
389
-			// pas geres en sqlite2
390
-			case 'ADD COLUMN':
391
-				$do = 'ADD' . substr($do, 10);
392
-			case 'ADD':
393
-			default:
394
-				if (!preg_match(',primary\s+key,i', $do)) {
395
-					if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
396
-						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
397
-
398
-						return false;
399
-					}
400
-					break;
401
-				}
402
-				// ou si la colonne est aussi primary key
403
-				// cas du add id_truc int primary key
404
-				// ajout d'une colonne qui passe en primary key directe
405
-				else {
406
-					$def = trim(substr($do, 3));
407
-					$colonne_ajoutee = substr($def, 0, strpos($def, ' '));
408
-					$def = substr($def, strlen($colonne_ajoutee) + 1);
409
-					$opts = [];
410
-					if (preg_match(',primary\s+key,i', $def)) {
411
-						$opts['key'] = ['PRIMARY KEY' => $colonne_ajoutee];
412
-						$def = preg_replace(',primary\s+key,i', '', $def);
413
-					}
414
-					$opts['field'] = [$colonne_ajoutee => $def];
415
-					if (!_sqlite_modifier_table($table, [$colonne_ajoutee], $opts, $serveur)) {
416
-						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
417
-
418
-						return false;
419
-					}
420
-				}
421
-				break;
422
-		}
423
-		// tout est bon, ouf !
424
-		spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.' . _LOG_INFO);
425
-	}
426
-
427
-	spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.' . _LOG_INFO);
428
-
429
-	return true;
185
+    // 1
186
+    if (preg_match('/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is', $query, $regs)) {
187
+        $debut = $regs[1];
188
+        $table = $regs[3];
189
+        $suite = $regs[4];
190
+    } else {
191
+        spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.' . _LOG_ERREUR);
192
+
193
+        return false;
194
+    }
195
+
196
+    // 2
197
+    // il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
198
+    // tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
199
+    // ou revoir l'api de sql_alter en creant un
200
+    // sql_alter_table($table,array($actions));
201
+    $todo = explode(',', $suite);
202
+
203
+    // on remet les morceaux dechires ensembles... que c'est laid !
204
+    $todo2 = [];
205
+    $i = 0;
206
+    $ouverte = false;
207
+    while ($do = array_shift($todo)) {
208
+        $todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
209
+        $o = (false !== strpos($do, '('));
210
+        $f = (false !== strpos($do, ')'));
211
+        if ($o and !$f) {
212
+            $ouverte = true;
213
+        } elseif ($f) {
214
+            $ouverte = false;
215
+        }
216
+        if (!$ouverte) {
217
+            $i++;
218
+        }
219
+    }
220
+
221
+    // 3
222
+    $resultats = [];
223
+    foreach ($todo2 as $do) {
224
+        $do = trim($do);
225
+        if (
226
+            !preg_match('/(DROP PRIMARY KEY|DROP KEY|DROP INDEX|DROP COLUMN|DROP'
227
+            . '|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
228
+            . '|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
229
+            . '|ADD COLUMN|ADD'
230
+            . ')\s*([^\s]*)\s*(.*)?/i', $do, $matches)
231
+        ) {
232
+            spip_log(
233
+                "SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)",
234
+                'sqlite.' . _LOG_ERREUR
235
+            );
236
+
237
+            return false;
238
+        }
239
+
240
+        $cle = strtoupper($matches[1]);
241
+        $colonne_origine = $matches[2];
242
+        $colonne_destination = '';
243
+
244
+        $def = $matches[3];
245
+
246
+        // eluder une eventuelle clause before|after|first inutilisable
247
+        $defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is', '', $def));
248
+        $defo = $defr; // garder la def d'origine pour certains cas
249
+        // remplacer les definitions venant de mysql
250
+        $defr = _sqlite_remplacements_definitions_table($defr);
251
+
252
+        // reinjecter dans le do
253
+        $do = str_replace($def, $defr, $do);
254
+        $def = $defr;
255
+
256
+        switch ($cle) {
257
+            // suppression d'un index
258
+            case 'DROP KEY':
259
+            case 'DROP INDEX':
260
+                $nom_index = $colonne_origine;
261
+                spip_sqlite_drop_index($nom_index, $table, $serveur);
262
+                break;
263
+
264
+            // suppression d'une pk
265
+            case 'DROP PRIMARY KEY':
266
+                if (
267
+                    !_sqlite_modifier_table(
268
+                        $table,
269
+                        $colonne_origine,
270
+                        ['key' => ['PRIMARY KEY' => '']],
271
+                        $serveur
272
+                    )
273
+                ) {
274
+                    return false;
275
+                }
276
+                break;
277
+            // suppression d'une colonne
278
+            case 'DROP COLUMN':
279
+            case 'DROP':
280
+                if (
281
+                    !_sqlite_modifier_table(
282
+                        $table,
283
+                        [$colonne_origine => ''],
284
+                        [],
285
+                        $serveur
286
+                    )
287
+                ) {
288
+                    return false;
289
+                }
290
+                break;
291
+
292
+            case 'CHANGE COLUMN':
293
+            case 'CHANGE':
294
+                // recuperer le nom de la future colonne
295
+                // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
296
+                // en tenant compte de la cle primaire (ce qui est mieux)
297
+                $def = trim($defo);
298
+                $colonne_destination = substr($def, 0, strpos($def, ' '));
299
+                $def = substr($def, strlen($colonne_destination) + 1);
300
+
301
+                if (
302
+                    !_sqlite_modifier_table(
303
+                        $table,
304
+                        [$colonne_origine => $colonne_destination],
305
+                        ['field' => [$colonne_destination => $def]],
306
+                        $serveur
307
+                    )
308
+                ) {
309
+                    return false;
310
+                }
311
+                break;
312
+
313
+            case 'MODIFY':
314
+                // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
315
+                // en tenant compte de la cle primaire (ce qui est mieux)
316
+                if (
317
+                    !_sqlite_modifier_table(
318
+                        $table,
319
+                        $colonne_origine,
320
+                        ['field' => [$colonne_origine => $defo]],
321
+                        $serveur
322
+                    )
323
+                ) {
324
+                    return false;
325
+                }
326
+                break;
327
+
328
+            // pas geres en sqlite2
329
+            case 'RENAME':
330
+                $do = 'RENAME TO' . substr($do, 6);
331
+            case 'RENAME TO':
332
+                if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
333
+                    spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
334
+
335
+                    return false;
336
+                }
337
+                break;
338
+
339
+            // ajout d'une pk
340
+            case 'ADD PRIMARY KEY':
341
+                $pk = trim(substr($do, 16));
342
+                $pk = ($pk[0] == '(') ? substr($pk, 1, -1) : $pk;
343
+                if (
344
+                    !_sqlite_modifier_table(
345
+                        $table,
346
+                        $colonne_origine,
347
+                        ['key' => ['PRIMARY KEY' => $pk]],
348
+                        $serveur
349
+                    )
350
+                ) {
351
+                    return false;
352
+                }
353
+                break;
354
+            // ajout d'un index
355
+            case 'ADD UNIQUE KEY':
356
+            case 'ADD UNIQUE':
357
+                $unique = true;
358
+            case 'ADD INDEX':
359
+            case 'ADD KEY':
360
+                if (!isset($unique)) {
361
+                    $unique = false;
362
+                }
363
+                // peut etre "(colonne)" ou "nom_index (colonnes)"
364
+                // bug potentiel si qqn met "(colonne, colonne)"
365
+                //
366
+                // nom_index (colonnes)
367
+                if ($def) {
368
+                    $colonnes = substr($def, 1, -1);
369
+                    $nom_index = $colonne_origine;
370
+                } else {
371
+                    // (colonne)
372
+                    if ($colonne_origine[0] == '(') {
373
+                        $colonnes = substr($colonne_origine, 1, -1);
374
+                        if (false !== strpos(',', $colonnes)) {
375
+                            spip_log('SQLite : Erreur, impossible de creer un index sur plusieurs colonnes'
376
+                                . " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite.' . _LOG_ERREUR);
377
+                            break;
378
+                        } else {
379
+                            $nom_index = $colonnes;
380
+                        }
381
+                    } // nom_index
382
+                    else {
383
+                        $nom_index = $colonnes = $colonne_origine;
384
+                    }
385
+                }
386
+                spip_sqlite_create_index($nom_index, $table, $colonnes, $unique, $serveur);
387
+                break;
388
+
389
+            // pas geres en sqlite2
390
+            case 'ADD COLUMN':
391
+                $do = 'ADD' . substr($do, 10);
392
+            case 'ADD':
393
+            default:
394
+                if (!preg_match(',primary\s+key,i', $do)) {
395
+                    if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
396
+                        spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
397
+
398
+                        return false;
399
+                    }
400
+                    break;
401
+                }
402
+                // ou si la colonne est aussi primary key
403
+                // cas du add id_truc int primary key
404
+                // ajout d'une colonne qui passe en primary key directe
405
+                else {
406
+                    $def = trim(substr($do, 3));
407
+                    $colonne_ajoutee = substr($def, 0, strpos($def, ' '));
408
+                    $def = substr($def, strlen($colonne_ajoutee) + 1);
409
+                    $opts = [];
410
+                    if (preg_match(',primary\s+key,i', $def)) {
411
+                        $opts['key'] = ['PRIMARY KEY' => $colonne_ajoutee];
412
+                        $def = preg_replace(',primary\s+key,i', '', $def);
413
+                    }
414
+                    $opts['field'] = [$colonne_ajoutee => $def];
415
+                    if (!_sqlite_modifier_table($table, [$colonne_ajoutee], $opts, $serveur)) {
416
+                        spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
417
+
418
+                        return false;
419
+                    }
420
+                }
421
+                break;
422
+        }
423
+        // tout est bon, ouf !
424
+        spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.' . _LOG_INFO);
425
+    }
426
+
427
+    spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.' . _LOG_INFO);
428
+
429
+    return true;
430 430
 }
431 431
 
432 432
 
@@ -449,38 +449,38 @@  discard block
 block discarded – undo
449 449
  *     - true si la requête réussie, false sinon.
450 450
  */
451 451
 function spip_sqlite_create(
452
-	$nom,
453
-	$champs,
454
-	$cles,
455
-	$autoinc = false,
456
-	$temporary = false,
457
-	$serveur = '',
458
-	$requeter = true
452
+    $nom,
453
+    $champs,
454
+    $cles,
455
+    $autoinc = false,
456
+    $temporary = false,
457
+    $serveur = '',
458
+    $requeter = true
459 459
 ) {
460
-	$query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists = true, $serveur, $requeter);
461
-	if (!$query) {
462
-		return false;
463
-	}
464
-	$res = spip_sqlite_query($query, $serveur, $requeter);
465
-
466
-	// SQLite ne cree pas les KEY sur les requetes CREATE TABLE
467
-	// il faut donc les faire creer ensuite
468
-	if (!$requeter) {
469
-		return $res;
470
-	}
471
-
472
-	$ok = $res ? true : false;
473
-	if ($ok) {
474
-		foreach ($cles as $k => $v) {
475
-			if (preg_match(',^(UNIQUE KEY|KEY|UNIQUE)\s,i', $k, $m)) {
476
-				$index = trim(substr($k, strlen($m[1])));
477
-				$unique = (strlen($m[1]) > 3);
478
-				$ok &= spip_sqlite_create_index($index, $nom, $v, $unique, $serveur);
479
-			}
480
-		}
481
-	}
482
-
483
-	return $ok ? true : false;
460
+    $query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists = true, $serveur, $requeter);
461
+    if (!$query) {
462
+        return false;
463
+    }
464
+    $res = spip_sqlite_query($query, $serveur, $requeter);
465
+
466
+    // SQLite ne cree pas les KEY sur les requetes CREATE TABLE
467
+    // il faut donc les faire creer ensuite
468
+    if (!$requeter) {
469
+        return $res;
470
+    }
471
+
472
+    $ok = $res ? true : false;
473
+    if ($ok) {
474
+        foreach ($cles as $k => $v) {
475
+            if (preg_match(',^(UNIQUE KEY|KEY|UNIQUE)\s,i', $k, $m)) {
476
+                $index = trim(substr($k, strlen($m[1])));
477
+                $unique = (strlen($m[1]) > 3);
478
+                $ok &= spip_sqlite_create_index($index, $nom, $v, $unique, $serveur);
479
+            }
480
+        }
481
+    }
482
+
483
+    return $ok ? true : false;
484 484
 }
485 485
 
486 486
 /**
@@ -493,21 +493,21 @@  discard block
 block discarded – undo
493 493
  * @return bool true si la base est créee.
494 494
  **/
495 495
 function spip_sqlite_create_base($nom, $serveur = '', $option = true) {
496
-	$f = $nom . '.sqlite';
497
-	if (strpos($nom, '/') === false) {
498
-		$f = _DIR_DB . $f;
499
-	}
496
+    $f = $nom . '.sqlite';
497
+    if (strpos($nom, '/') === false) {
498
+        $f = _DIR_DB . $f;
499
+    }
500 500
 
501
-	$ok = new \PDO("sqlite:$f");
501
+    $ok = new \PDO("sqlite:$f");
502 502
 
503
-	if ($ok) {
504
-		unset($ok);
503
+    if ($ok) {
504
+        unset($ok);
505 505
 
506
-		return true;
507
-	}
508
-	unset($ok);
506
+        return true;
507
+    }
508
+    unset($ok);
509 509
 
510
-	return false;
510
+    return false;
511 511
 }
512 512
 
513 513
 
@@ -528,22 +528,22 @@  discard block
 block discarded – undo
528 528
  *     - string texte de la requête si $requeter vaut false
529 529
  */
530 530
 function spip_sqlite_create_view($nom, $query_select, $serveur = '', $requeter = true) {
531
-	if (!$query_select) {
532
-		return false;
533
-	}
534
-	// vue deja presente
535
-	if (sql_showtable($nom, false, $serveur)) {
536
-		spip_log(
537
-			"Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)",
538
-			'sqlite.' . _LOG_ERREUR
539
-		);
531
+    if (!$query_select) {
532
+        return false;
533
+    }
534
+    // vue deja presente
535
+    if (sql_showtable($nom, false, $serveur)) {
536
+        spip_log(
537
+            "Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)",
538
+            'sqlite.' . _LOG_ERREUR
539
+        );
540 540
 
541
-		return false;
542
-	}
541
+        return false;
542
+    }
543 543
 
544
-	$query = "CREATE VIEW $nom AS " . $query_select;
544
+    $query = "CREATE VIEW $nom AS " . $query_select;
545 545
 
546
-	return spip_sqlite_query($query, $serveur, $requeter);
546
+    return spip_sqlite_query($query, $serveur, $requeter);
547 547
 }
548 548
 
549 549
 /**
@@ -565,54 +565,54 @@  discard block
 block discarded – undo
565 565
  *    string : requête, false si erreur, true sinon.
566 566
  */
567 567
 function spip_sqlite_create_index($nom, $table, $champs, $unique = '', $serveur = '', $requeter = true) {
568
-	if (!($nom or $table or $champs)) {
569
-		spip_log(
570
-			"Champ manquant pour creer un index sqlite ($nom, $table, (" . join(',', $champs) . '))',
571
-			'sqlite.' . _LOG_ERREUR
572
-		);
573
-
574
-		return false;
575
-	}
576
-
577
-	// SQLite ne differentie pas noms des index en fonction des tables
578
-	// il faut donc creer des noms uniques d'index pour une base sqlite
579
-	$nom = $table . '_' . $nom;
580
-	// enlever d'eventuelles parentheses deja presentes sur champs
581
-	if (!is_array($champs)) {
582
-		if ($champs[0] == '(') {
583
-			$champs = substr($champs, 1, -1);
584
-		}
585
-		$champs = [$champs];
586
-		// supprimer l'info de longueur d'index mysql en fin de champ
587
-		$champs = preg_replace(',\(\d+\)$,', '', $champs);
588
-	}
589
-
590
-	$ifnotexists = '';
591
-	$version = spip_sqlite_fetch(spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur), '', $serveur);
592
-	if (!function_exists('spip_version_compare')) {
593
-		include_spip('plugins/installer');
594
-	}
595
-
596
-	if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
597
-		$ifnotexists = ' IF NOT EXISTS';
598
-	} else {
599
-		/* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
600
-		$a = spip_sqlite_showtable($table, $serveur);
601
-		if (isset($a['key']['KEY ' . $nom])) {
602
-			return true;
603
-		}
604
-	}
605
-
606
-	$query = 'CREATE ' . ($unique ? 'UNIQUE ' : '') . "INDEX$ifnotexists $nom ON $table (" . join(',', $champs) . ')';
607
-	$res = spip_sqlite_query($query, $serveur, $requeter);
608
-	if (!$requeter) {
609
-		return $res;
610
-	}
611
-	if ($res) {
612
-		return true;
613
-	} else {
614
-		return false;
615
-	}
568
+    if (!($nom or $table or $champs)) {
569
+        spip_log(
570
+            "Champ manquant pour creer un index sqlite ($nom, $table, (" . join(',', $champs) . '))',
571
+            'sqlite.' . _LOG_ERREUR
572
+        );
573
+
574
+        return false;
575
+    }
576
+
577
+    // SQLite ne differentie pas noms des index en fonction des tables
578
+    // il faut donc creer des noms uniques d'index pour une base sqlite
579
+    $nom = $table . '_' . $nom;
580
+    // enlever d'eventuelles parentheses deja presentes sur champs
581
+    if (!is_array($champs)) {
582
+        if ($champs[0] == '(') {
583
+            $champs = substr($champs, 1, -1);
584
+        }
585
+        $champs = [$champs];
586
+        // supprimer l'info de longueur d'index mysql en fin de champ
587
+        $champs = preg_replace(',\(\d+\)$,', '', $champs);
588
+    }
589
+
590
+    $ifnotexists = '';
591
+    $version = spip_sqlite_fetch(spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur), '', $serveur);
592
+    if (!function_exists('spip_version_compare')) {
593
+        include_spip('plugins/installer');
594
+    }
595
+
596
+    if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
597
+        $ifnotexists = ' IF NOT EXISTS';
598
+    } else {
599
+        /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
600
+        $a = spip_sqlite_showtable($table, $serveur);
601
+        if (isset($a['key']['KEY ' . $nom])) {
602
+            return true;
603
+        }
604
+    }
605
+
606
+    $query = 'CREATE ' . ($unique ? 'UNIQUE ' : '') . "INDEX$ifnotexists $nom ON $table (" . join(',', $champs) . ')';
607
+    $res = spip_sqlite_query($query, $serveur, $requeter);
608
+    if (!$requeter) {
609
+        return $res;
610
+    }
611
+    if ($res) {
612
+        return true;
613
+    } else {
614
+        return false;
615
+    }
616 616
 }
617 617
 
618 618
 /**
@@ -629,31 +629,31 @@  discard block
 block discarded – undo
629 629
  * @return int                 Nombre de lignes
630 630
  */
631 631
 function spip_sqlite_count($r, $serveur = '', $requeter = true) {
632
-	if (!$r) {
633
-		return 0;
634
-	}
635
-
636
-	// select ou autre (insert, update,...) ?
637
-	// (link,requete) a compter
638
-	if (is_array($r->spipSqliteRowCount)) {
639
-		list($link, $query) = $r->spipSqliteRowCount;
640
-		// amelioration possible a tester intensivement : pas de order by pour compter !
641
-		// $query = preg_replace(",ORDER BY .+(LIMIT\s|HAVING\s|GROUP BY\s|$),Uims","\\1",$query);
642
-		$query = "SELECT count(*) as zzzzsqlitecount FROM ($query)";
643
-		$l = $link->query($query);
644
-		$i = 0;
645
-		if ($l and $z = $l->fetch()) {
646
-			$i = $z['zzzzsqlitecount'];
647
-		}
648
-		$r->spipSqliteRowCount = $i;
649
-	}
650
-	if (isset($r->spipSqliteRowCount)) {
651
-		// Ce compte est faux s'il y a des limit dans la requete :(
652
-		// il retourne le nombre d'enregistrements sans le limit
653
-		return $r->spipSqliteRowCount;
654
-	} else {
655
-		return $r->rowCount();
656
-	}
632
+    if (!$r) {
633
+        return 0;
634
+    }
635
+
636
+    // select ou autre (insert, update,...) ?
637
+    // (link,requete) a compter
638
+    if (is_array($r->spipSqliteRowCount)) {
639
+        list($link, $query) = $r->spipSqliteRowCount;
640
+        // amelioration possible a tester intensivement : pas de order by pour compter !
641
+        // $query = preg_replace(",ORDER BY .+(LIMIT\s|HAVING\s|GROUP BY\s|$),Uims","\\1",$query);
642
+        $query = "SELECT count(*) as zzzzsqlitecount FROM ($query)";
643
+        $l = $link->query($query);
644
+        $i = 0;
645
+        if ($l and $z = $l->fetch()) {
646
+            $i = $z['zzzzsqlitecount'];
647
+        }
648
+        $r->spipSqliteRowCount = $i;
649
+    }
650
+    if (isset($r->spipSqliteRowCount)) {
651
+        // Ce compte est faux s'il y a des limit dans la requete :(
652
+        // il retourne le nombre d'enregistrements sans le limit
653
+        return $r->spipSqliteRowCount;
654
+    } else {
655
+        return $r->rowCount();
656
+    }
657 657
 }
658 658
 
659 659
 
@@ -672,30 +672,30 @@  discard block
 block discarded – undo
672 672
  *     - false si la requête a échouée
673 673
  **/
674 674
 function spip_sqlite_countsel(
675
-	$from = [],
676
-	$where = [],
677
-	$groupby = '',
678
-	$having = [],
679
-	$serveur = '',
680
-	$requeter = true
675
+    $from = [],
676
+    $where = [],
677
+    $groupby = '',
678
+    $having = [],
679
+    $serveur = '',
680
+    $requeter = true
681 681
 ) {
682
-	$c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
683
-	$r = spip_sqlite_select(
684
-		"COUNT($c)",
685
-		$from,
686
-		$where,
687
-		'',
688
-		'',
689
-		'',
690
-		$having,
691
-		$serveur,
692
-		$requeter
693
-	);
694
-	if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
695
-		list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
696
-	}
697
-
698
-	return $r;
682
+    $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
683
+    $r = spip_sqlite_select(
684
+        "COUNT($c)",
685
+        $from,
686
+        $where,
687
+        '',
688
+        '',
689
+        '',
690
+        $having,
691
+        $serveur,
692
+        $requeter
693
+    );
694
+    if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
695
+        list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
696
+    }
697
+
698
+    return $r;
699 699
 }
700 700
 
701 701
 
@@ -712,24 +712,24 @@  discard block
 block discarded – undo
712 712
  *     - False en cas d'erreur.
713 713
  **/
714 714
 function spip_sqlite_delete($table, $where = '', $serveur = '', $requeter = true) {
715
-	$res = spip_sqlite_query(
716
-		_sqlite_calculer_expression('DELETE FROM', $table, ',')
717
-		. _sqlite_calculer_expression('WHERE', $where),
718
-		$serveur,
719
-		$requeter
720
-	);
715
+    $res = spip_sqlite_query(
716
+        _sqlite_calculer_expression('DELETE FROM', $table, ',')
717
+        . _sqlite_calculer_expression('WHERE', $where),
718
+        $serveur,
719
+        $requeter
720
+    );
721 721
 
722
-	// renvoyer la requete inerte si demandee
723
-	if (!$requeter) {
724
-		return $res;
725
-	}
722
+    // renvoyer la requete inerte si demandee
723
+    if (!$requeter) {
724
+        return $res;
725
+    }
726 726
 
727
-	if ($res) {
728
-		$link = _sqlite_link($serveur);
729
-		return $res->rowCount();
730
-	} else {
731
-		return false;
732
-	}
727
+    if ($res) {
728
+        $link = _sqlite_link($serveur);
729
+        return $res->rowCount();
730
+    } else {
731
+        return false;
732
+    }
733 733
 }
734 734
 
735 735
 
@@ -745,15 +745,15 @@  discard block
 block discarded – undo
745 745
  *     - true si la requête a réussie, false sinon
746 746
  */
747 747
 function spip_sqlite_drop_table($table, $exist = '', $serveur = '', $requeter = true) {
748
-	if ($exist) {
749
-		$exist = ' IF EXISTS';
750
-	}
748
+    if ($exist) {
749
+        $exist = ' IF EXISTS';
750
+    }
751 751
 
752
-	if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter)) {
753
-		return true;
754
-	} else {
755
-		return false;
756
-	}
752
+    if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter)) {
753
+        return true;
754
+    } else {
755
+        return false;
756
+    }
757 757
 }
758 758
 
759 759
 
@@ -769,11 +769,11 @@  discard block
 block discarded – undo
769 769
  *     - true si la requête a réussie, false sinon
770 770
  */
771 771
 function spip_sqlite_drop_view($view, $exist = '', $serveur = '', $requeter = true) {
772
-	if ($exist) {
773
-		$exist = ' IF EXISTS';
774
-	}
772
+    if ($exist) {
773
+        $exist = ' IF EXISTS';
774
+    }
775 775
 
776
-	return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
776
+    return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
777 777
 }
778 778
 
779 779
 /**
@@ -787,20 +787,20 @@  discard block
 block discarded – undo
787 787
  * @return bool ou requete
788 788
  */
789 789
 function spip_sqlite_drop_index($nom, $table, $serveur = '', $requeter = true) {
790
-	if (!($nom or $table)) {
791
-		spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.' . _LOG_ERREUR);
790
+    if (!($nom or $table)) {
791
+        spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.' . _LOG_ERREUR);
792 792
 
793
-		return false;
794
-	}
793
+        return false;
794
+    }
795 795
 
796
-	// SQLite ne differentie pas noms des index en fonction des tables
797
-	// il faut donc creer des noms uniques d'index pour une base sqlite
798
-	$index = $table . '_' . $nom;
799
-	$exist = ' IF EXISTS';
796
+    // SQLite ne differentie pas noms des index en fonction des tables
797
+    // il faut donc creer des noms uniques d'index pour une base sqlite
798
+    $index = $table . '_' . $nom;
799
+    $exist = ' IF EXISTS';
800 800
 
801
-	$query = "DROP INDEX$exist $index";
801
+    $query = "DROP INDEX$exist $index";
802 802
 
803
-	return spip_sqlite_query($query, $serveur, $requeter);
803
+    return spip_sqlite_query($query, $serveur, $requeter);
804 804
 }
805 805
 
806 806
 /**
@@ -816,28 +816,28 @@  discard block
 block discarded – undo
816 816
  *     Erreur eventuelle
817 817
  **/
818 818
 function spip_sqlite_error($query = '', $serveur = '') {
819
-	$link = _sqlite_link($serveur);
819
+    $link = _sqlite_link($serveur);
820 820
 
821
-	if ($link) {
822
-		$errs = $link->errorInfo();
823
-		$s = _sqlite_last_error_from_link($link);
824
-	} else {
825
-		$s = ': aucune ressource sqlite (link)';
826
-	}
827
-	if ($s) {
828
-		$trace = debug_backtrace();
829
-		if ($trace[0]['function'] != 'spip_sqlite_error') {
830
-			spip_log("$s - $query - " . sql_error_backtrace(), 'sqlite.' . _LOG_ERREUR);
831
-		}
832
-	}
821
+    if ($link) {
822
+        $errs = $link->errorInfo();
823
+        $s = _sqlite_last_error_from_link($link);
824
+    } else {
825
+        $s = ': aucune ressource sqlite (link)';
826
+    }
827
+    if ($s) {
828
+        $trace = debug_backtrace();
829
+        if ($trace[0]['function'] != 'spip_sqlite_error') {
830
+            spip_log("$s - $query - " . sql_error_backtrace(), 'sqlite.' . _LOG_ERREUR);
831
+        }
832
+    }
833 833
 
834
-	return $s;
834
+    return $s;
835 835
 }
836 836
 
837 837
 function _sqlite_last_error_from_link($link) {
838
-	if ($link) {
839
-		$errs = $link->errorInfo();
840
-		/*
838
+    if ($link) {
839
+        $errs = $link->errorInfo();
840
+        /*
841 841
 			$errs[0]
842 842
 				numero SQLState ('HY000' souvent lors d'une erreur)
843 843
 				http://www.easysoft.com/developer/interfaces/odbc/sqlstate_status_return_codes.html
@@ -847,11 +847,11 @@  discard block
 block discarded – undo
847 847
 			$errs[2]
848 848
 				Le texte du message d'erreur
849 849
 		*/
850
-		if (ltrim($errs[0], '0')) { // 00000 si pas d'erreur
851
-			return "$errs[2]";
852
-		}
853
-	}
854
-	return '';
850
+        if (ltrim($errs[0], '0')) { // 00000 si pas d'erreur
851
+            return "$errs[2]";
852
+        }
853
+    }
854
+    return '';
855 855
 }
856 856
 
857 857
 /**
@@ -868,23 +868,23 @@  discard block
 block discarded – undo
868 868
  *    'HY000/1' : numéro de l'erreur SQLState / numéro d'erreur interne SQLite (en sqlite 3)
869 869
  **/
870 870
 function spip_sqlite_errno($serveur = '') {
871
-	$link = _sqlite_link($serveur);
871
+    $link = _sqlite_link($serveur);
872 872
 
873
-	if ($link) {
874
-		$t = $link->errorInfo();
875
-		$s = ltrim($t[0], '0'); // 00000 si pas d'erreur
876
-		if ($s) {
877
-			$s .= ' / ' . $t[1];
878
-		} // ajoute l'erreur du moteur SQLite
879
-	} else {
880
-		$s = ': aucune ressource sqlite (link)';
881
-	}
873
+    if ($link) {
874
+        $t = $link->errorInfo();
875
+        $s = ltrim($t[0], '0'); // 00000 si pas d'erreur
876
+        if ($s) {
877
+            $s .= ' / ' . $t[1];
878
+        } // ajoute l'erreur du moteur SQLite
879
+    } else {
880
+        $s = ': aucune ressource sqlite (link)';
881
+    }
882 882
 
883
-	if ($s) {
884
-		spip_log("Erreur sqlite $s", 'sqlite.' . _LOG_ERREUR);
885
-	}
883
+    if ($s) {
884
+        spip_log("Erreur sqlite $s", 'sqlite.' . _LOG_ERREUR);
885
+    }
886 886
 
887
-	return $s ? $s : 0;
887
+    return $s ? $s : 0;
888 888
 }
889 889
 
890 890
 
@@ -900,19 +900,19 @@  discard block
 block discarded – undo
900 900
  *     - false si on a pas pu avoir d'explication
901 901
  */
902 902
 function spip_sqlite_explain($query, $serveur = '', $requeter = true) {
903
-	if (strpos(ltrim($query), 'SELECT') !== 0) {
904
-		return [];
905
-	}
903
+    if (strpos(ltrim($query), 'SELECT') !== 0) {
904
+        return [];
905
+    }
906 906
 
907
-	$query = spip_sqlite::traduire_requete($query, $serveur);
908
-	$query = 'EXPLAIN ' . $query;
909
-	if (!$requeter) {
910
-		return $query;
911
-	}
912
-	// on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
913
-	$r = spip_sqlite::executer_requete($query, $serveur, false);
907
+    $query = spip_sqlite::traduire_requete($query, $serveur);
908
+    $query = 'EXPLAIN ' . $query;
909
+    if (!$requeter) {
910
+        return $query;
911
+    }
912
+    // on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
913
+    $r = spip_sqlite::executer_requete($query, $serveur, false);
914 914
 
915
-	return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
915
+    return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
916 916
 }
917 917
 
918 918
 
@@ -932,35 +932,35 @@  discard block
 block discarded – undo
932 932
  */
933 933
 function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true) {
934 934
 
935
-	$link = _sqlite_link($serveur);
936
-	$t = $t ? $t : SPIP_SQLITE3_ASSOC;
935
+    $link = _sqlite_link($serveur);
936
+    $t = $t ? $t : SPIP_SQLITE3_ASSOC;
937 937
 
938
-	if (!$r) {
939
-		return false;
940
-	}
938
+    if (!$r) {
939
+        return false;
940
+    }
941 941
 
942
-	$retour = $r->fetch($t);
942
+    $retour = $r->fetch($t);
943 943
 
944
-	if (!$retour) {
945
-		if ($r->errorCode() === '00000') {
946
-			return null;
947
-		}
948
-		return false;
949
-	}
944
+    if (!$retour) {
945
+        if ($r->errorCode() === '00000') {
946
+            return null;
947
+        }
948
+        return false;
949
+    }
950 950
 
951
-	// Renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
952
-	// suppression de 'table.' pour toutes les cles (c'est un peu violent !)
953
-	// c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
954
-	if (strpos(implode('', array_keys($retour)), '.') !== false) {
955
-		foreach ($retour as $cle => $val) {
956
-			if (($pos = strpos($cle, '.')) !== false) {
957
-				$retour[substr($cle, $pos + 1)] = &$retour[$cle];
958
-				unset($retour[$cle]);
959
-			}
960
-		}
961
-	}
951
+    // Renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
952
+    // suppression de 'table.' pour toutes les cles (c'est un peu violent !)
953
+    // c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
954
+    if (strpos(implode('', array_keys($retour)), '.') !== false) {
955
+        foreach ($retour as $cle => $val) {
956
+            if (($pos = strpos($cle, '.')) !== false) {
957
+                $retour[substr($cle, $pos + 1)] = &$retour[$cle];
958
+                unset($retour[$cle]);
959
+            }
960
+        }
961
+    }
962 962
 
963
-	return $retour;
963
+    return $retour;
964 964
 }
965 965
 
966 966
 /**
@@ -973,8 +973,8 @@  discard block
 block discarded – undo
973 973
  * @return bool True si déplacement réussi, false sinon.
974 974
  **/
975 975
 function spip_sqlite_seek($r, $row_number, $serveur = '', $requeter = true) {
976
-	// encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
977
-	return false;
976
+    // encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
977
+    return false;
978 978
 }
979 979
 
980 980
 
@@ -990,10 +990,10 @@  discard block
 block discarded – undo
990 990
  * @return bool                True si réussi
991 991
  */
992 992
 function spip_sqlite_free(&$r, $serveur = '', $requeter = true) {
993
-	unset($r);
993
+    unset($r);
994 994
 
995
-	return true;
996
-	//return sqlite_free_result($r);
995
+    return true;
996
+    //return sqlite_free_result($r);
997 997
 }
998 998
 
999 999
 
@@ -1008,8 +1008,8 @@  discard block
 block discarded – undo
1008 1008
  * @return void
1009 1009
  */
1010 1010
 function spip_sqlite_get_charset($charset = [], $serveur = '', $requeter = true) {
1011
-	//$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
1012
-	//return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
1011
+    //$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
1012
+    //return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
1013 1013
 }
1014 1014
 
1015 1015
 
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
  *     Valeur hexadécimale pour SQLite
1025 1025
  **/
1026 1026
 function spip_sqlite_hex($v) {
1027
-	return hexdec($v);
1027
+    return hexdec($v);
1028 1028
 }
1029 1029
 
1030 1030
 
@@ -1046,7 +1046,7 @@  discard block
 block discarded – undo
1046 1046
  *     Expression de requête SQL
1047 1047
  **/
1048 1048
 function spip_sqlite_in($val, $valeurs, $not = '', $serveur = '', $requeter = true) {
1049
-	return "($val $not IN ($valeurs))";
1049
+    return "($val $not IN ($valeurs))";
1050 1050
 }
1051 1051
 
1052 1052
 
@@ -1074,20 +1074,20 @@  discard block
 block discarded – undo
1074 1074
  **/
1075 1075
 function spip_sqlite_insert($table, $champs, $valeurs, $desc = [], $serveur = '', $requeter = true) {
1076 1076
 
1077
-	$query = "INSERT INTO $table " . ($champs ? "$champs VALUES $valeurs" : 'DEFAULT VALUES');
1078
-	if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
1079
-		if (!$requeter) {
1080
-			return $r;
1081
-		}
1082
-		$nb = spip_sqlite::last_insert_id($serveur);
1083
-	} else {
1084
-		$nb = false;
1085
-	}
1077
+    $query = "INSERT INTO $table " . ($champs ? "$champs VALUES $valeurs" : 'DEFAULT VALUES');
1078
+    if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
1079
+        if (!$requeter) {
1080
+            return $r;
1081
+        }
1082
+        $nb = spip_sqlite::last_insert_id($serveur);
1083
+    } else {
1084
+        $nb = false;
1085
+    }
1086 1086
 
1087
-	$err = spip_sqlite_error($query, $serveur);
1087
+    $err = spip_sqlite_error($query, $serveur);
1088 1088
 
1089
-	// cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1090
-	return isset($_GET['var_profile']) ? $r : $nb;
1089
+    // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1090
+    return isset($_GET['var_profile']) ? $r : $nb;
1091 1091
 }
1092 1092
 
1093 1093
 
@@ -1112,28 +1112,28 @@  discard block
 block discarded – undo
1112 1112
  *     - Tableau de description de la requête et du temps d'exécution, si var_profile activé
1113 1113
  **/
1114 1114
 function spip_sqlite_insertq($table, $couples = [], $desc = [], $serveur = '', $requeter = true) {
1115
-	if (!$desc) {
1116
-		$desc = description_table($table, $serveur);
1117
-	}
1118
-	if (!$desc) {
1119
-		die("$table insertion sans description");
1120
-	}
1121
-	$fields = isset($desc['field']) ? $desc['field'] : [];
1115
+    if (!$desc) {
1116
+        $desc = description_table($table, $serveur);
1117
+    }
1118
+    if (!$desc) {
1119
+        die("$table insertion sans description");
1120
+    }
1121
+    $fields = isset($desc['field']) ? $desc['field'] : [];
1122 1122
 
1123
-	foreach ($couples as $champ => $val) {
1124
-		$couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1125
-	}
1123
+    foreach ($couples as $champ => $val) {
1124
+        $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1125
+    }
1126 1126
 
1127
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1128
-	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1127
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1128
+    $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1129 1129
 
1130
-	$cles = $valeurs = '';
1131
-	if (count($couples)) {
1132
-		$cles = '(' . join(',', array_keys($couples)) . ')';
1133
-		$valeurs = '(' . join(',', $couples) . ')';
1134
-	}
1130
+    $cles = $valeurs = '';
1131
+    if (count($couples)) {
1132
+        $cles = '(' . join(',', array_keys($couples)) . ')';
1133
+        $valeurs = '(' . join(',', $couples) . ')';
1134
+    }
1135 1135
 
1136
-	return spip_sqlite_insert($table, $cles, $valeurs, $desc, $serveur, $requeter);
1136
+    return spip_sqlite_insert($table, $cles, $valeurs, $desc, $serveur, $requeter);
1137 1137
 }
1138 1138
 
1139 1139
 
@@ -1157,70 +1157,70 @@  discard block
 block discarded – undo
1157 1157
  *     - False en cas d'erreur.
1158 1158
  **/
1159 1159
 function spip_sqlite_insertq_multi($table, $tab_couples = [], $desc = [], $serveur = '', $requeter = true) {
1160
-	if (!$desc) {
1161
-		$desc = description_table($table, $serveur);
1162
-	}
1163
-	if (!$desc) {
1164
-		die("$table insertion sans description");
1165
-	}
1166
-	if (!isset($desc['field'])) {
1167
-		$desc['field'] = [];
1168
-	}
1169
-
1170
-	// recuperer les champs 'timestamp' pour mise a jour auto de ceux-ci
1171
-	$maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1172
-
1173
-	// seul le nom de la table est a traduire ici :
1174
-	// le faire une seule fois au debut
1175
-	$query_start = "INSERT INTO $table ";
1176
-	$query_start = spip_sqlite::traduire_requete($query_start, $serveur);
1177
-
1178
-	// ouvrir une transaction
1179
-	if ($requeter) {
1180
-		spip_sqlite::demarrer_transaction($serveur);
1181
-	}
1182
-
1183
-	while ($couples = array_shift($tab_couples)) {
1184
-		foreach ($couples as $champ => $val) {
1185
-			$couples[$champ] = _sqlite_calculer_cite($val, $desc['field'][$champ]);
1186
-		}
1187
-
1188
-		// inserer les champs timestamp par defaut
1189
-		$couples = array_merge($maj, $couples);
1190
-
1191
-		$champs = $valeurs = '';
1192
-		if (count($couples)) {
1193
-			$champs = '(' . join(',', array_keys($couples)) . ')';
1194
-			$valeurs = '(' . join(',', $couples) . ')';
1195
-			$query = $query_start . "$champs VALUES $valeurs";
1196
-		} else {
1197
-			$query = $query_start . 'DEFAULT VALUES';
1198
-		}
1199
-
1200
-		if ($requeter) {
1201
-			$retour = spip_sqlite::executer_requete($query, $serveur);
1202
-		}
1203
-
1204
-		// sur le dernier couple uniquement
1205
-		if (!count($tab_couples)) {
1206
-			$nb = 0;
1207
-			if ($requeter) {
1208
-				$nb = spip_sqlite::last_insert_id($serveur);
1209
-			} else {
1210
-				return $query;
1211
-			}
1212
-		}
1213
-
1214
-		$err = spip_sqlite_error($query, $serveur);
1215
-	}
1216
-
1217
-	if ($requeter) {
1218
-		spip_sqlite::finir_transaction($serveur);
1219
-	}
1220
-
1221
-	// renvoie le dernier id d'autoincrement ajoute
1222
-	// cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1223
-	return isset($_GET['var_profile']) ? $retour : $nb;
1160
+    if (!$desc) {
1161
+        $desc = description_table($table, $serveur);
1162
+    }
1163
+    if (!$desc) {
1164
+        die("$table insertion sans description");
1165
+    }
1166
+    if (!isset($desc['field'])) {
1167
+        $desc['field'] = [];
1168
+    }
1169
+
1170
+    // recuperer les champs 'timestamp' pour mise a jour auto de ceux-ci
1171
+    $maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1172
+
1173
+    // seul le nom de la table est a traduire ici :
1174
+    // le faire une seule fois au debut
1175
+    $query_start = "INSERT INTO $table ";
1176
+    $query_start = spip_sqlite::traduire_requete($query_start, $serveur);
1177
+
1178
+    // ouvrir une transaction
1179
+    if ($requeter) {
1180
+        spip_sqlite::demarrer_transaction($serveur);
1181
+    }
1182
+
1183
+    while ($couples = array_shift($tab_couples)) {
1184
+        foreach ($couples as $champ => $val) {
1185
+            $couples[$champ] = _sqlite_calculer_cite($val, $desc['field'][$champ]);
1186
+        }
1187
+
1188
+        // inserer les champs timestamp par defaut
1189
+        $couples = array_merge($maj, $couples);
1190
+
1191
+        $champs = $valeurs = '';
1192
+        if (count($couples)) {
1193
+            $champs = '(' . join(',', array_keys($couples)) . ')';
1194
+            $valeurs = '(' . join(',', $couples) . ')';
1195
+            $query = $query_start . "$champs VALUES $valeurs";
1196
+        } else {
1197
+            $query = $query_start . 'DEFAULT VALUES';
1198
+        }
1199
+
1200
+        if ($requeter) {
1201
+            $retour = spip_sqlite::executer_requete($query, $serveur);
1202
+        }
1203
+
1204
+        // sur le dernier couple uniquement
1205
+        if (!count($tab_couples)) {
1206
+            $nb = 0;
1207
+            if ($requeter) {
1208
+                $nb = spip_sqlite::last_insert_id($serveur);
1209
+            } else {
1210
+                return $query;
1211
+            }
1212
+        }
1213
+
1214
+        $err = spip_sqlite_error($query, $serveur);
1215
+    }
1216
+
1217
+    if ($requeter) {
1218
+        spip_sqlite::finir_transaction($serveur);
1219
+    }
1220
+
1221
+    // renvoie le dernier id d'autoincrement ajoute
1222
+    // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1223
+    return isset($_GET['var_profile']) ? $retour : $nb;
1224 1224
 }
1225 1225
 
1226 1226
 
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
  *     Toujours true.
1236 1236
  **/
1237 1237
 function spip_sqlite_preferer_transaction($serveur = '', $requeter = true) {
1238
-	return true;
1238
+    return true;
1239 1239
 }
1240 1240
 
1241 1241
 /**
@@ -1252,12 +1252,12 @@  discard block
 block discarded – undo
1252 1252
  *     string si texte de la requête demandé, true sinon
1253 1253
  **/
1254 1254
 function spip_sqlite_demarrer_transaction($serveur = '', $requeter = true) {
1255
-	if (!$requeter) {
1256
-		return 'BEGIN TRANSACTION';
1257
-	}
1258
-	spip_sqlite::demarrer_transaction($serveur);
1255
+    if (!$requeter) {
1256
+        return 'BEGIN TRANSACTION';
1257
+    }
1258
+    spip_sqlite::demarrer_transaction($serveur);
1259 1259
 
1260
-	return true;
1260
+    return true;
1261 1261
 }
1262 1262
 
1263 1263
 /**
@@ -1271,12 +1271,12 @@  discard block
 block discarded – undo
1271 1271
  *     string si texte de la requête demandé, true sinon
1272 1272
  **/
1273 1273
 function spip_sqlite_terminer_transaction($serveur = '', $requeter = true) {
1274
-	if (!$requeter) {
1275
-		return 'COMMIT';
1276
-	}
1277
-	spip_sqlite::finir_transaction($serveur);
1274
+    if (!$requeter) {
1275
+        return 'COMMIT';
1276
+    }
1277
+    spip_sqlite::finir_transaction($serveur);
1278 1278
 
1279
-	return true;
1279
+    return true;
1280 1280
 }
1281 1281
 
1282 1282
 
@@ -1291,27 +1291,27 @@  discard block
 block discarded – undo
1291 1291
  *     Liste des noms de bases
1292 1292
  **/
1293 1293
 function spip_sqlite_listdbs($serveur = '', $requeter = true) {
1294
-	_sqlite_init();
1294
+    _sqlite_init();
1295 1295
 
1296
-	if (!is_dir($d = substr(_DIR_DB, 0, -1))) {
1297
-		return [];
1298
-	}
1296
+    if (!is_dir($d = substr(_DIR_DB, 0, -1))) {
1297
+        return [];
1298
+    }
1299 1299
 
1300
-	include_spip('inc/flock');
1301
-	$bases = preg_files($d, $pattern = '(.*)\.sqlite$');
1302
-	$bds = [];
1300
+    include_spip('inc/flock');
1301
+    $bases = preg_files($d, $pattern = '(.*)\.sqlite$');
1302
+    $bds = [];
1303 1303
 
1304
-	foreach ($bases as $b) {
1305
-		// pas de bases commencant pas sqlite
1306
-		// (on s'en sert pour l'installation pour simuler la presence d'un serveur)
1307
-		// les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
1308
-		if (strpos($b, '_sqlite')) {
1309
-			continue;
1310
-		}
1311
-		$bds[] = preg_replace(";.*/$pattern;iS", '$1', $b);
1312
-	}
1304
+    foreach ($bases as $b) {
1305
+        // pas de bases commencant pas sqlite
1306
+        // (on s'en sert pour l'installation pour simuler la presence d'un serveur)
1307
+        // les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
1308
+        if (strpos($b, '_sqlite')) {
1309
+            continue;
1310
+        }
1311
+        $bds[] = preg_replace(";.*/$pattern;iS", '$1', $b);
1312
+    }
1313 1313
 
1314
-	return $bds;
1314
+    return $bds;
1315 1315
 }
1316 1316
 
1317 1317
 
@@ -1326,9 +1326,9 @@  discard block
 block discarded – undo
1326 1326
  * @return string       Texte de sélection pour la requête
1327 1327
  */
1328 1328
 function spip_sqlite_multi($objet, $lang) {
1329
-	$r = 'EXTRAIRE_MULTI(' . $objet . ", '" . $lang . "') AS multi";
1329
+    $r = 'EXTRAIRE_MULTI(' . $objet . ", '" . $lang . "') AS multi";
1330 1330
 
1331
-	return $r;
1331
+    return $r;
1332 1332
 }
1333 1333
 
1334 1334
 
@@ -1345,15 +1345,15 @@  discard block
 block discarded – undo
1345 1345
  * @return bool|string true / false / requete
1346 1346
  **/
1347 1347
 function spip_sqlite_optimize($table, $serveur = '', $requeter = true) {
1348
-	static $do = false;
1349
-	if ($requeter and $do) {
1350
-		return true;
1351
-	}
1352
-	if ($requeter) {
1353
-		$do = true;
1354
-	}
1348
+    static $do = false;
1349
+    if ($requeter and $do) {
1350
+        return true;
1351
+    }
1352
+    if ($requeter) {
1353
+        $do = true;
1354
+    }
1355 1355
 
1356
-	return spip_sqlite_query('VACUUM', $serveur, $requeter);
1356
+    return spip_sqlite_query('VACUUM', $serveur, $requeter);
1357 1357
 }
1358 1358
 
1359 1359
 
@@ -1370,15 +1370,15 @@  discard block
 block discarded – undo
1370 1370
  *    Donnée prête à être utilisée par le gestionnaire SQL
1371 1371
  */
1372 1372
 function spip_sqlite_quote($v, $type = '') {
1373
-	if (!is_array($v)) {
1374
-		return _sqlite_calculer_cite($v, $type);
1375
-	}
1376
-	// si c'est un tableau, le parcourir en propageant le type
1377
-	foreach ($v as $k => $r) {
1378
-		$v[$k] = spip_sqlite_quote($r, $type);
1379
-	}
1373
+    if (!is_array($v)) {
1374
+        return _sqlite_calculer_cite($v, $type);
1375
+    }
1376
+    // si c'est un tableau, le parcourir en propageant le type
1377
+    foreach ($v as $k => $r) {
1378
+        $v[$k] = spip_sqlite_quote($r, $type);
1379
+    }
1380 1380
 
1381
-	return join(',', $v);
1381
+    return join(',', $v);
1382 1382
 }
1383 1383
 
1384 1384
 
@@ -1395,9 +1395,9 @@  discard block
 block discarded – undo
1395 1395
  *     Expression SQL
1396 1396
  **/
1397 1397
 function spip_sqlite_date_proche($champ, $interval, $unite) {
1398
-	$op = (($interval <= 0) ? '>' : '<');
1398
+    $op = (($interval <= 0) ? '>' : '<');
1399 1399
 
1400
-	return "($champ $op datetime('" . date('Y-m-d H:i:s') . "', '$interval $unite'))";
1400
+    return "($champ $op datetime('" . date('Y-m-d H:i:s') . "', '$interval $unite'))";
1401 1401
 }
1402 1402
 
1403 1403
 
@@ -1415,48 +1415,48 @@  discard block
 block discarded – undo
1415 1415
  *     l'état de la table après la réparation
1416 1416
  */
1417 1417
 function spip_sqlite_repair($table, $serveur = '', $requeter = true) {
1418
-	if (
1419
-		$desc = spip_sqlite_showtable($table, $serveur)
1420
-		and isset($desc['field'])
1421
-		and is_array($desc['field'])
1422
-	) {
1423
-		foreach ($desc['field'] as $c => $d) {
1424
-			if (
1425
-				preg_match(',^(tinytext|mediumtext|text|longtext|varchar|char),i', $d)
1426
-				and stripos($d, 'NOT NULL') !== false
1427
-				and stripos($d, 'DEFAULT') === false
1428
-				/* pas touche aux cles primaires */
1429
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1430
-			) {
1431
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT ''", $serveur);
1432
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1433
-			}
1434
-			if (
1435
-				preg_match(',^(INTEGER),i', $d)
1436
-				and stripos($d, 'NOT NULL') !== false
1437
-				and stripos($d, 'DEFAULT') === false
1438
-				/* pas touche aux cles primaires */
1439
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1440
-			) {
1441
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0'", $serveur);
1442
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1443
-			}
1444
-			if (
1445
-				preg_match(',^(datetime),i', $d)
1446
-				and stripos($d, 'NOT NULL') !== false
1447
-				and stripos($d, 'DEFAULT') === false
1448
-				/* pas touche aux cles primaires */
1449
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1450
-			) {
1451
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0000-00-00 00:00:00'", $serveur);
1452
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1453
-			}
1454
-		}
1455
-
1456
-		return [' OK '];
1457
-	}
1458
-
1459
-	return [' ERROR '];
1418
+    if (
1419
+        $desc = spip_sqlite_showtable($table, $serveur)
1420
+        and isset($desc['field'])
1421
+        and is_array($desc['field'])
1422
+    ) {
1423
+        foreach ($desc['field'] as $c => $d) {
1424
+            if (
1425
+                preg_match(',^(tinytext|mediumtext|text|longtext|varchar|char),i', $d)
1426
+                and stripos($d, 'NOT NULL') !== false
1427
+                and stripos($d, 'DEFAULT') === false
1428
+                /* pas touche aux cles primaires */
1429
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1430
+            ) {
1431
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT ''", $serveur);
1432
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1433
+            }
1434
+            if (
1435
+                preg_match(',^(INTEGER),i', $d)
1436
+                and stripos($d, 'NOT NULL') !== false
1437
+                and stripos($d, 'DEFAULT') === false
1438
+                /* pas touche aux cles primaires */
1439
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1440
+            ) {
1441
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0'", $serveur);
1442
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1443
+            }
1444
+            if (
1445
+                preg_match(',^(datetime),i', $d)
1446
+                and stripos($d, 'NOT NULL') !== false
1447
+                and stripos($d, 'DEFAULT') === false
1448
+                /* pas touche aux cles primaires */
1449
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1450
+            ) {
1451
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0000-00-00 00:00:00'", $serveur);
1452
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1453
+            }
1454
+        }
1455
+
1456
+        return [' OK '];
1457
+    }
1458
+
1459
+    return [' ERROR '];
1460 1460
 }
1461 1461
 
1462 1462
 
@@ -1485,25 +1485,25 @@  discard block
 block discarded – undo
1485 1485
  *     - False en cas d'erreur.
1486 1486
  **/
1487 1487
 function spip_sqlite_replace($table, $couples, $desc = [], $serveur = '', $requeter = true) {
1488
-	if (!$desc) {
1489
-		$desc = description_table($table, $serveur);
1490
-	}
1491
-	if (!$desc) {
1492
-		die("$table insertion sans description");
1493
-	}
1494
-	$fields = isset($desc['field']) ? $desc['field'] : [];
1488
+    if (!$desc) {
1489
+        $desc = description_table($table, $serveur);
1490
+    }
1491
+    if (!$desc) {
1492
+        die("$table insertion sans description");
1493
+    }
1494
+    $fields = isset($desc['field']) ? $desc['field'] : [];
1495 1495
 
1496
-	foreach ($couples as $champ => $val) {
1497
-		$couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1498
-	}
1496
+    foreach ($couples as $champ => $val) {
1497
+        $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1498
+    }
1499 1499
 
1500
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1501
-	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1500
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1501
+    $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1502 1502
 
1503
-	return spip_sqlite_query("REPLACE INTO $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1504
-		',',
1505
-		$couples
1506
-	) . ')', $serveur);
1503
+    return spip_sqlite_query("REPLACE INTO $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1504
+        ',',
1505
+        $couples
1506
+    ) . ')', $serveur);
1507 1507
 }
1508 1508
 
1509 1509
 
@@ -1533,13 +1533,13 @@  discard block
 block discarded – undo
1533 1533
  **/
1534 1534
 function spip_sqlite_replace_multi($table, $tab_couples, $desc = [], $serveur = '', $requeter = true) {
1535 1535
 
1536
-	// boucler pour trainter chaque requete independemment
1537
-	foreach ($tab_couples as $couples) {
1538
-		$retour = spip_sqlite_replace($table, $couples, $desc, $serveur, $requeter);
1539
-	}
1536
+    // boucler pour trainter chaque requete independemment
1537
+    foreach ($tab_couples as $couples) {
1538
+        $retour = spip_sqlite_replace($table, $couples, $desc, $serveur, $requeter);
1539
+    }
1540 1540
 
1541
-	// renvoie le dernier id
1542
-	return $retour;
1541
+    // renvoie le dernier id
1542
+    return $retour;
1543 1543
 }
1544 1544
 
1545 1545
 
@@ -1566,44 +1566,44 @@  discard block
 block discarded – undo
1566 1566
  *     - array  : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
1567 1567
  */
1568 1568
 function spip_sqlite_select(
1569
-	$select,
1570
-	$from,
1571
-	$where = '',
1572
-	$groupby = '',
1573
-	$orderby = '',
1574
-	$limit = '',
1575
-	$having = '',
1576
-	$serveur = '',
1577
-	$requeter = true
1569
+    $select,
1570
+    $from,
1571
+    $where = '',
1572
+    $groupby = '',
1573
+    $orderby = '',
1574
+    $limit = '',
1575
+    $having = '',
1576
+    $serveur = '',
1577
+    $requeter = true
1578 1578
 ) {
1579 1579
 
1580
-	// version() n'est pas connu de sqlite
1581
-	$select = str_replace('version()', 'sqlite_version()', $select);
1580
+    // version() n'est pas connu de sqlite
1581
+    $select = str_replace('version()', 'sqlite_version()', $select);
1582 1582
 
1583
-	// recomposer from
1584
-	$from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
1583
+    // recomposer from
1584
+    $from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
1585 1585
 
1586
-	$query =
1587
-		_sqlite_calculer_expression('SELECT', $select, ', ')
1588
-		. _sqlite_calculer_expression('FROM', $from, ', ')
1589
-		. _sqlite_calculer_expression('WHERE', $where)
1590
-		. _sqlite_calculer_expression('GROUP BY', $groupby, ',')
1591
-		. _sqlite_calculer_expression('HAVING', $having)
1592
-		. ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) : '')
1593
-		. ($limit ? "\nLIMIT $limit" : '');
1586
+    $query =
1587
+        _sqlite_calculer_expression('SELECT', $select, ', ')
1588
+        . _sqlite_calculer_expression('FROM', $from, ', ')
1589
+        . _sqlite_calculer_expression('WHERE', $where)
1590
+        . _sqlite_calculer_expression('GROUP BY', $groupby, ',')
1591
+        . _sqlite_calculer_expression('HAVING', $having)
1592
+        . ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) : '')
1593
+        . ($limit ? "\nLIMIT $limit" : '');
1594 1594
 
1595
-	// dans un select, on doit renvoyer la requête en cas d'erreur
1596
-	$res = spip_sqlite_query($query, $serveur, $requeter);
1597
-	// texte de la requete demande ?
1598
-	if (!$requeter) {
1599
-		return $res;
1600
-	}
1601
-	// erreur survenue ?
1602
-	if ($res === false) {
1603
-		return spip_sqlite::traduire_requete($query, $serveur);
1604
-	}
1595
+    // dans un select, on doit renvoyer la requête en cas d'erreur
1596
+    $res = spip_sqlite_query($query, $serveur, $requeter);
1597
+    // texte de la requete demande ?
1598
+    if (!$requeter) {
1599
+        return $res;
1600
+    }
1601
+    // erreur survenue ?
1602
+    if ($res === false) {
1603
+        return spip_sqlite::traduire_requete($query, $serveur);
1604
+    }
1605 1605
 
1606
-	return $res;
1606
+    return $res;
1607 1607
 }
1608 1608
 
1609 1609
 
@@ -1622,32 +1622,32 @@  discard block
 block discarded – undo
1622 1622
  *     - False en cas d'erreur.
1623 1623
  **/
1624 1624
 function spip_sqlite_selectdb($db, $serveur = '', $requeter = true) {
1625
-	_sqlite_init();
1625
+    _sqlite_init();
1626 1626
 
1627
-	// interdire la creation d'une nouvelle base,
1628
-	// sauf si on est dans l'installation
1629
-	if (
1630
-		!is_file($f = _DIR_DB . $db . '.sqlite')
1631
-		&& (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)
1632
-	) {
1633
-		spip_log("Il est interdit de creer la base $db", 'sqlite.' . _LOG_HS);
1627
+    // interdire la creation d'une nouvelle base,
1628
+    // sauf si on est dans l'installation
1629
+    if (
1630
+        !is_file($f = _DIR_DB . $db . '.sqlite')
1631
+        && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)
1632
+    ) {
1633
+        spip_log("Il est interdit de creer la base $db", 'sqlite.' . _LOG_HS);
1634 1634
 
1635
-		return false;
1636
-	}
1635
+        return false;
1636
+    }
1637 1637
 
1638
-	// se connecter a la base indiquee
1639
-	// avec les identifiants connus
1640
-	$index = $serveur ? $serveur : 0;
1638
+    // se connecter a la base indiquee
1639
+    // avec les identifiants connus
1640
+    $index = $serveur ? $serveur : 0;
1641 1641
 
1642
-	if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db, $serveur, '', '')) {
1643
-		if (($db == $link['db']) && $GLOBALS['connexions'][$index] = $link) {
1644
-			return $db;
1645
-		}
1646
-	} else {
1647
-		spip_log("Impossible de selectionner la base $db", 'sqlite.' . _LOG_HS);
1642
+    if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db, $serveur, '', '')) {
1643
+        if (($db == $link['db']) && $GLOBALS['connexions'][$index] = $link) {
1644
+            return $db;
1645
+        }
1646
+    } else {
1647
+        spip_log("Impossible de selectionner la base $db", 'sqlite.' . _LOG_HS);
1648 1648
 
1649
-		return false;
1650
-	}
1649
+        return false;
1650
+    }
1651 1651
 }
1652 1652
 
1653 1653
 
@@ -1662,8 +1662,8 @@  discard block
 block discarded – undo
1662 1662
  * @return void
1663 1663
  */
1664 1664
 function spip_sqlite_set_charset($charset, $serveur = '', $requeter = true) {
1665
-	# spip_log("Gestion charset sql a ecrire : "."SET NAMES "._q($charset), 'sqlite.'._LOG_ERREUR);
1666
-	# return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
1665
+    # spip_log("Gestion charset sql a ecrire : "."SET NAMES "._q($charset), 'sqlite.'._LOG_ERREUR);
1666
+    # return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
1667 1667
 }
1668 1668
 
1669 1669
 
@@ -1681,24 +1681,24 @@  discard block
 block discarded – undo
1681 1681
  *     Ressource à utiliser avec sql_fetch()
1682 1682
  **/
1683 1683
 function spip_sqlite_showbase($match, $serveur = '', $requeter = true) {
1684
-	// type est le type d'entrée : table / index / view
1685
-	// on ne retourne que les tables (?) et non les vues...
1686
-	# ESCAPE non supporte par les versions sqlite <3
1687
-	#	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
1688
-	$match = preg_quote($match);
1689
-	$match = str_replace('\\\_', '[[TIRETBAS]]', $match);
1690
-	$match = str_replace('\\\%', '[[POURCENT]]', $match);
1691
-	$match = str_replace('_', '.', $match);
1692
-	$match = str_replace('%', '.*', $match);
1693
-	$match = str_replace('[[TIRETBAS]]', '_', $match);
1694
-	$match = str_replace('[[POURCENT]]', '%', $match);
1695
-	$match = "^$match$";
1696
-
1697
-	return spip_sqlite_query(
1698
-		"SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP " . _q($match),
1699
-		$serveur,
1700
-		$requeter
1701
-	);
1684
+    // type est le type d'entrée : table / index / view
1685
+    // on ne retourne que les tables (?) et non les vues...
1686
+    # ESCAPE non supporte par les versions sqlite <3
1687
+    #	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
1688
+    $match = preg_quote($match);
1689
+    $match = str_replace('\\\_', '[[TIRETBAS]]', $match);
1690
+    $match = str_replace('\\\%', '[[POURCENT]]', $match);
1691
+    $match = str_replace('_', '.', $match);
1692
+    $match = str_replace('%', '.*', $match);
1693
+    $match = str_replace('[[TIRETBAS]]', '_', $match);
1694
+    $match = str_replace('[[POURCENT]]', '%', $match);
1695
+    $match = "^$match$";
1696
+
1697
+    return spip_sqlite_query(
1698
+        "SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP " . _q($match),
1699
+        $serveur,
1700
+        $requeter
1701
+    );
1702 1702
 }
1703 1703
 
1704 1704
 /**
@@ -1716,19 +1716,19 @@  discard block
 block discarded – undo
1716 1716
  *     - string : requete sql, si $requeter = true
1717 1717
  **/
1718 1718
 function spip_sqlite_table_exists(string $table, $serveur = '', $requeter = true) {
1719
-	$r = spip_sqlite_query(
1720
-		'SELECT name FROM sqlite_master WHERE'
1721
-		. ' type=\'table\''
1722
-		. ' AND name=' . spip_sqlite_quote($table, 'string')
1723
-		. ' AND name NOT LIKE \'sqlite_%\'',
1724
-		$serveur,
1725
-		$requeter
1726
-	);
1727
-	if (!$requeter) {
1728
-		return $r;
1729
-	}
1730
-	$res = spip_sqlite_fetch($r);
1731
-	return (bool) $res;
1719
+    $r = spip_sqlite_query(
1720
+        'SELECT name FROM sqlite_master WHERE'
1721
+        . ' type=\'table\''
1722
+        . ' AND name=' . spip_sqlite_quote($table, 'string')
1723
+        . ' AND name NOT LIKE \'sqlite_%\'',
1724
+        $serveur,
1725
+        $requeter
1726
+    );
1727
+    if (!$requeter) {
1728
+        return $r;
1729
+    }
1730
+    $res = spip_sqlite_fetch($r);
1731
+    return (bool) $res;
1732 1732
 }
1733 1733
 
1734 1734
 define('_SQLITE_RE_SHOW_TABLE', '/^[^(),]*\(((?:[^()]*\((?:[^()]*\([^()]*\))?[^()]*\)[^()]*)*[^()]*)\)[^()]*$/');
@@ -1751,129 +1751,129 @@  discard block
 block discarded – undo
1751 1751
  *     - array description de la table sinon
1752 1752
  */
1753 1753
 function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true) {
1754
-	$query =
1755
-		'SELECT sql, type FROM'
1756
-		. ' (SELECT * FROM sqlite_master UNION ALL'
1757
-		. ' SELECT * FROM sqlite_temp_master)'
1758
-		. " WHERE tbl_name LIKE '$nom_table'"
1759
-		. " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
1760
-		. ' ORDER BY substr(type,2,1), name';
1761
-
1762
-	$a = spip_sqlite_query($query, $serveur, $requeter);
1763
-	if (!$a) {
1764
-		return '';
1765
-	}
1766
-	if (!$requeter) {
1767
-		return $a;
1768
-	}
1769
-	if (!($a = spip_sqlite_fetch($a, null, $serveur))) {
1770
-		return '';
1771
-	}
1772
-	$vue = ($a['type'] == 'view'); // table | vue
1773
-
1774
-	// c'est une table
1775
-	// il faut parser le create
1776
-	if (!$vue) {
1777
-		if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)) {
1778
-			return '';
1779
-		} else {
1780
-			$desc = $r[1];
1781
-			// extraction d'une KEY éventuelle en prenant garde de ne pas
1782
-			// relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
1783
-			if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
1784
-				$namedkeys = $r[2];
1785
-				$desc = $r[1];
1786
-			} else {
1787
-				$namedkeys = '';
1788
-			}
1789
-
1790
-			$fields = [];
1791
-			$keys = [];
1792
-
1793
-			// enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber
1794
-			// par exemple s'il contiennent une virgule.
1795
-			// /!\ cela peut aussi echapper le nom des champs si la table a eu des operations avec SQLite Manager !
1796
-			list($desc, $echaps) = query_echappe_textes($desc);
1797
-
1798
-			// separer toutes les descriptions de champs, separes par des virgules
1799
-			# /!\ explode peut exploser aussi DECIMAL(10,2) !
1800
-			$k_precedent = null;
1801
-			foreach (explode(',', $desc) as $v) {
1802
-				preg_match('/^\s*([^\s]+)\s+(.*)/', $v, $r);
1803
-				// Les cles de champs peuvent etre entourees
1804
-				// de guillements doubles " , simples ', graves ` ou de crochets [ ],  ou rien.
1805
-				// http://www.sqlite.org/lang_keywords.html
1806
-				$k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]...
1807
-				if ($char = strpbrk($k[0], '\'"[`')) {
1808
-					$k = trim($k, $char);
1809
-					if ($char == '[') {
1810
-						$k = rtrim($k, ']');
1811
-					}
1812
-				}
1813
-				$def = query_reinjecte_textes($r[2], $echaps); // valeur du champ
1814
-
1815
-				// rustine pour DECIMAL(10,2)
1816
-				// s'il y a une parenthèse fermante dans la clé
1817
-				// ou dans la définition sans qu'il n'y ait une ouverture avant
1818
-				if (false !== strpos($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
1819
-					$fields[$k_precedent] .= ',' . $k . ' ' . $def;
1820
-					continue;
1821
-				}
1822
-
1823
-				// la primary key peut etre dans une des descriptions de champs
1824
-				// et non en fin de table, cas encore decouvert avec Sqlite Manager
1825
-				if (stripos($r[2], 'PRIMARY KEY') !== false) {
1826
-					$keys['PRIMARY KEY'] = $k;
1827
-				}
1828
-
1829
-				$fields[$k] = $def;
1830
-				$k_precedent = $k;
1831
-			}
1832
-			// key inclues dans la requete
1833
-			foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
1834
-				if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
1835
-					$k = str_replace('`', '', trim($r[1]));
1836
-					$t = trim(strtolower(str_replace('`', '', $r[2])), '"');
1837
-					if ($k && !isset($keys[$k])) {
1838
-						$keys[$k] = $t;
1839
-					} else {
1840
-						$keys[] = $t;
1841
-					}
1842
-				}
1843
-			}
1844
-			// sinon ajouter les key index
1845
-			$query =
1846
-				'SELECT name,sql FROM'
1847
-				. ' (SELECT * FROM sqlite_master UNION ALL'
1848
-				. ' SELECT * FROM sqlite_temp_master)'
1849
-				. " WHERE tbl_name LIKE '$nom_table'"
1850
-				. " AND type='index' AND name NOT LIKE 'sqlite_%'"
1851
-				. 'ORDER BY substr(type,2,1), name';
1852
-			$a = spip_sqlite_query($query, $serveur, $requeter);
1853
-			while ($r = spip_sqlite_fetch($a, null, $serveur)) {
1854
-				$key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index
1855
-				$keytype = 'KEY';
1856
-				if (strpos($r['sql'], 'UNIQUE INDEX') !== false) {
1857
-					$keytype = 'UNIQUE KEY';
1858
-				}
1859
-				$colonnes = preg_replace(',.*\((.*)\).*,', '$1', $r['sql']);
1860
-				$keys[$keytype . ' ' . $key] = $colonnes;
1861
-			}
1862
-		}
1863
-	} // c'est une vue, on liste les champs disponibles simplement
1864
-	else {
1865
-		if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1
1866
-			$fields = [];
1867
-			foreach ($res as $c => $v) {
1868
-				$fields[$c] = '';
1869
-			}
1870
-			$keys = [];
1871
-		} else {
1872
-			return '';
1873
-		}
1874
-	}
1875
-
1876
-	return ['field' => $fields, 'key' => $keys];
1754
+    $query =
1755
+        'SELECT sql, type FROM'
1756
+        . ' (SELECT * FROM sqlite_master UNION ALL'
1757
+        . ' SELECT * FROM sqlite_temp_master)'
1758
+        . " WHERE tbl_name LIKE '$nom_table'"
1759
+        . " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
1760
+        . ' ORDER BY substr(type,2,1), name';
1761
+
1762
+    $a = spip_sqlite_query($query, $serveur, $requeter);
1763
+    if (!$a) {
1764
+        return '';
1765
+    }
1766
+    if (!$requeter) {
1767
+        return $a;
1768
+    }
1769
+    if (!($a = spip_sqlite_fetch($a, null, $serveur))) {
1770
+        return '';
1771
+    }
1772
+    $vue = ($a['type'] == 'view'); // table | vue
1773
+
1774
+    // c'est une table
1775
+    // il faut parser le create
1776
+    if (!$vue) {
1777
+        if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)) {
1778
+            return '';
1779
+        } else {
1780
+            $desc = $r[1];
1781
+            // extraction d'une KEY éventuelle en prenant garde de ne pas
1782
+            // relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
1783
+            if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
1784
+                $namedkeys = $r[2];
1785
+                $desc = $r[1];
1786
+            } else {
1787
+                $namedkeys = '';
1788
+            }
1789
+
1790
+            $fields = [];
1791
+            $keys = [];
1792
+
1793
+            // enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber
1794
+            // par exemple s'il contiennent une virgule.
1795
+            // /!\ cela peut aussi echapper le nom des champs si la table a eu des operations avec SQLite Manager !
1796
+            list($desc, $echaps) = query_echappe_textes($desc);
1797
+
1798
+            // separer toutes les descriptions de champs, separes par des virgules
1799
+            # /!\ explode peut exploser aussi DECIMAL(10,2) !
1800
+            $k_precedent = null;
1801
+            foreach (explode(',', $desc) as $v) {
1802
+                preg_match('/^\s*([^\s]+)\s+(.*)/', $v, $r);
1803
+                // Les cles de champs peuvent etre entourees
1804
+                // de guillements doubles " , simples ', graves ` ou de crochets [ ],  ou rien.
1805
+                // http://www.sqlite.org/lang_keywords.html
1806
+                $k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]...
1807
+                if ($char = strpbrk($k[0], '\'"[`')) {
1808
+                    $k = trim($k, $char);
1809
+                    if ($char == '[') {
1810
+                        $k = rtrim($k, ']');
1811
+                    }
1812
+                }
1813
+                $def = query_reinjecte_textes($r[2], $echaps); // valeur du champ
1814
+
1815
+                // rustine pour DECIMAL(10,2)
1816
+                // s'il y a une parenthèse fermante dans la clé
1817
+                // ou dans la définition sans qu'il n'y ait une ouverture avant
1818
+                if (false !== strpos($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
1819
+                    $fields[$k_precedent] .= ',' . $k . ' ' . $def;
1820
+                    continue;
1821
+                }
1822
+
1823
+                // la primary key peut etre dans une des descriptions de champs
1824
+                // et non en fin de table, cas encore decouvert avec Sqlite Manager
1825
+                if (stripos($r[2], 'PRIMARY KEY') !== false) {
1826
+                    $keys['PRIMARY KEY'] = $k;
1827
+                }
1828
+
1829
+                $fields[$k] = $def;
1830
+                $k_precedent = $k;
1831
+            }
1832
+            // key inclues dans la requete
1833
+            foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
1834
+                if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
1835
+                    $k = str_replace('`', '', trim($r[1]));
1836
+                    $t = trim(strtolower(str_replace('`', '', $r[2])), '"');
1837
+                    if ($k && !isset($keys[$k])) {
1838
+                        $keys[$k] = $t;
1839
+                    } else {
1840
+                        $keys[] = $t;
1841
+                    }
1842
+                }
1843
+            }
1844
+            // sinon ajouter les key index
1845
+            $query =
1846
+                'SELECT name,sql FROM'
1847
+                . ' (SELECT * FROM sqlite_master UNION ALL'
1848
+                . ' SELECT * FROM sqlite_temp_master)'
1849
+                . " WHERE tbl_name LIKE '$nom_table'"
1850
+                . " AND type='index' AND name NOT LIKE 'sqlite_%'"
1851
+                . 'ORDER BY substr(type,2,1), name';
1852
+            $a = spip_sqlite_query($query, $serveur, $requeter);
1853
+            while ($r = spip_sqlite_fetch($a, null, $serveur)) {
1854
+                $key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index
1855
+                $keytype = 'KEY';
1856
+                if (strpos($r['sql'], 'UNIQUE INDEX') !== false) {
1857
+                    $keytype = 'UNIQUE KEY';
1858
+                }
1859
+                $colonnes = preg_replace(',.*\((.*)\).*,', '$1', $r['sql']);
1860
+                $keys[$keytype . ' ' . $key] = $colonnes;
1861
+            }
1862
+        }
1863
+    } // c'est une vue, on liste les champs disponibles simplement
1864
+    else {
1865
+        if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1
1866
+            $fields = [];
1867
+            foreach ($res as $c => $v) {
1868
+                $fields[$c] = '';
1869
+            }
1870
+            $keys = [];
1871
+        } else {
1872
+            return '';
1873
+        }
1874
+    }
1875
+
1876
+    return ['field' => $fields, 'key' => $keys];
1877 1877
 }
1878 1878
 
1879 1879
 
@@ -1899,22 +1899,22 @@  discard block
 block discarded – undo
1899 1899
  *     - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
1900 1900
  */
1901 1901
 function spip_sqlite_update($table, $champs, $where = '', $desc = '', $serveur = '', $requeter = true) {
1902
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1903
-	$champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1902
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1903
+    $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1904 1904
 
1905
-	$set = [];
1906
-	foreach ($champs as $champ => $val) {
1907
-		$set[] = $champ . "=$val";
1908
-	}
1909
-	if (!empty($set)) {
1910
-		return spip_sqlite_query(
1911
-			_sqlite_calculer_expression('UPDATE', $table, ',')
1912
-			. _sqlite_calculer_expression('SET', $set, ',')
1913
-			. _sqlite_calculer_expression('WHERE', $where),
1914
-			$serveur,
1915
-			$requeter
1916
-		);
1917
-	}
1905
+    $set = [];
1906
+    foreach ($champs as $champ => $val) {
1907
+        $set[] = $champ . "=$val";
1908
+    }
1909
+    if (!empty($set)) {
1910
+        return spip_sqlite_query(
1911
+            _sqlite_calculer_expression('UPDATE', $table, ',')
1912
+            . _sqlite_calculer_expression('SET', $set, ',')
1913
+            . _sqlite_calculer_expression('WHERE', $where),
1914
+            $serveur,
1915
+            $requeter
1916
+        );
1917
+    }
1918 1918
 }
1919 1919
 
1920 1920
 
@@ -1944,38 +1944,38 @@  discard block
 block discarded – undo
1944 1944
  */
1945 1945
 function spip_sqlite_updateq($table, $champs, $where = '', $desc = [], $serveur = '', $requeter = true) {
1946 1946
 
1947
-	if (!$champs) {
1948
-		return;
1949
-	}
1950
-	if (!$desc) {
1951
-		$desc = description_table($table, $serveur);
1952
-	}
1953
-	if (!$desc) {
1954
-		die("$table insertion sans description");
1955
-	}
1956
-	$fields = $desc['field'];
1957
-
1958
-	$set = [];
1959
-	foreach ($champs as $champ => $val) {
1960
-		$set[$champ] = $champ . '=' . _sqlite_calculer_cite($val, isset($fields[$champ]) ? $fields[$champ] : '');
1961
-	}
1962
-
1963
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1964
-	// attention ils sont deja quotes
1965
-	$maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1966
-	foreach ($maj as $champ => $val) {
1967
-		if (!isset($set[$champ])) {
1968
-			$set[$champ] = $champ . '=' . $val;
1969
-		}
1970
-	}
1971
-
1972
-	return spip_sqlite_query(
1973
-		_sqlite_calculer_expression('UPDATE', $table, ',')
1974
-		. _sqlite_calculer_expression('SET', $set, ',')
1975
-		. _sqlite_calculer_expression('WHERE', $where),
1976
-		$serveur,
1977
-		$requeter
1978
-	);
1947
+    if (!$champs) {
1948
+        return;
1949
+    }
1950
+    if (!$desc) {
1951
+        $desc = description_table($table, $serveur);
1952
+    }
1953
+    if (!$desc) {
1954
+        die("$table insertion sans description");
1955
+    }
1956
+    $fields = $desc['field'];
1957
+
1958
+    $set = [];
1959
+    foreach ($champs as $champ => $val) {
1960
+        $set[$champ] = $champ . '=' . _sqlite_calculer_cite($val, isset($fields[$champ]) ? $fields[$champ] : '');
1961
+    }
1962
+
1963
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1964
+    // attention ils sont deja quotes
1965
+    $maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1966
+    foreach ($maj as $champ => $val) {
1967
+        if (!isset($set[$champ])) {
1968
+            $set[$champ] = $champ . '=' . $val;
1969
+        }
1970
+    }
1971
+
1972
+    return spip_sqlite_query(
1973
+        _sqlite_calculer_expression('UPDATE', $table, ',')
1974
+        . _sqlite_calculer_expression('SET', $set, ',')
1975
+        . _sqlite_calculer_expression('WHERE', $where),
1976
+        $serveur,
1977
+        $requeter
1978
+    );
1979 1979
 }
1980 1980
 
1981 1981
 
@@ -1993,17 +1993,17 @@  discard block
 block discarded – undo
1993 1993
  * @return void
1994 1994
  */
1995 1995
 function _sqlite_init() {
1996
-	if (!defined('_DIR_DB')) {
1997
-		define('_DIR_DB', _DIR_ETC . 'bases/');
1998
-	}
1999
-	if (!defined('_SQLITE_CHMOD')) {
2000
-		define('_SQLITE_CHMOD', _SPIP_CHMOD);
2001
-	}
1996
+    if (!defined('_DIR_DB')) {
1997
+        define('_DIR_DB', _DIR_ETC . 'bases/');
1998
+    }
1999
+    if (!defined('_SQLITE_CHMOD')) {
2000
+        define('_SQLITE_CHMOD', _SPIP_CHMOD);
2001
+    }
2002 2002
 
2003
-	if (!is_dir($d = _DIR_DB)) {
2004
-		include_spip('inc/flock');
2005
-		sous_repertoire($d);
2006
-	}
2003
+    if (!is_dir($d = _DIR_DB)) {
2004
+        include_spip('inc/flock');
2005
+        sous_repertoire($d);
2006
+    }
2007 2007
 }
2008 2008
 
2009 2009
 
@@ -2017,20 +2017,20 @@  discard block
 block discarded – undo
2017 2017
  * @return bool|int
2018 2018
  */
2019 2019
 function _sqlite_is_version($version = '', $link = '', $serveur = '', $requeter = true) {
2020
-	if ($link === '') {
2021
-		$link = _sqlite_link($serveur);
2022
-	}
2023
-	if (!$link) {
2024
-		return false;
2025
-	}
2020
+    if ($link === '') {
2021
+        $link = _sqlite_link($serveur);
2022
+    }
2023
+    if (!$link) {
2024
+        return false;
2025
+    }
2026 2026
 
2027
-	$v = 3;
2027
+    $v = 3;
2028 2028
 
2029
-	if (!$version) {
2030
-		return $v;
2031
-	}
2029
+    if (!$version) {
2030
+        return $v;
2031
+    }
2032 2032
 
2033
-	return ($version == $v);
2033
+    return ($version == $v);
2034 2034
 }
2035 2035
 
2036 2036
 
@@ -2041,9 +2041,9 @@  discard block
 block discarded – undo
2041 2041
  * @return PDO Information de connexion pour SQLite
2042 2042
  */
2043 2043
 function _sqlite_link($serveur = '') {
2044
-	$link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
2044
+    $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
2045 2045
 
2046
-	return $link;
2046
+    return $link;
2047 2047
 }
2048 2048
 
2049 2049
 
@@ -2058,55 +2058,55 @@  discard block
 block discarded – undo
2058 2058
  * @return string|number     Texte ou nombre échappé
2059 2059
  */
2060 2060
 function _sqlite_calculer_cite($v, $type) {
2061
-	if ($type) {
2062
-		if (
2063
-			is_null($v)
2064
-			and stripos($type, 'NOT NULL') === false
2065
-		) {
2066
-			// null php se traduit en NULL SQL
2067
-			return 'NULL';
2068
-		}
2069
-
2070
-		if (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
2071
-			return $v;
2072
-		}
2073
-		if (sql_test_int($type)) {
2074
-			if (is_numeric($v)) {
2075
-				return $v;
2076
-			} elseif ($v === null) {
2077
-				return 0;
2078
-			} elseif (ctype_xdigit(substr($v, 2)) and strncmp($v, '0x', 2) === 0) {
2079
-				return hexdec(substr($v, 2));
2080
-			} else {
2081
-				return intval($v);
2082
-			}
2083
-		}
2084
-	} else {
2085
-		// si on ne connait pas le type on le deduit de $v autant que possible
2086
-		if (is_bool($v)) {
2087
-			return strval(intval($v));
2088
-		}
2089
-		elseif (is_numeric($v)) {
2090
-			return strval($v);
2091
-		}
2092
-	}
2093
-
2094
-	// trouver un link sqlite pour faire l'echappement
2095
-	foreach ($GLOBALS['connexions'] as $s) {
2096
-		if (
2097
-			$l = $s['link']
2098
-			and is_object($l)
2099
-			and $l instanceof \PDO
2100
-			and $l->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'sqlite'
2101
-		) {
2102
-			return $l->quote($v);
2103
-		}
2104
-	}
2105
-
2106
-	// echapper les ' en ''
2107
-	spip_log('Pas de methode ->quote pour echapper', 'sqlite.' . _LOG_INFO_IMPORTANTE);
2108
-
2109
-	return ("'" . str_replace("'", "''", $v) . "'");
2061
+    if ($type) {
2062
+        if (
2063
+            is_null($v)
2064
+            and stripos($type, 'NOT NULL') === false
2065
+        ) {
2066
+            // null php se traduit en NULL SQL
2067
+            return 'NULL';
2068
+        }
2069
+
2070
+        if (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
2071
+            return $v;
2072
+        }
2073
+        if (sql_test_int($type)) {
2074
+            if (is_numeric($v)) {
2075
+                return $v;
2076
+            } elseif ($v === null) {
2077
+                return 0;
2078
+            } elseif (ctype_xdigit(substr($v, 2)) and strncmp($v, '0x', 2) === 0) {
2079
+                return hexdec(substr($v, 2));
2080
+            } else {
2081
+                return intval($v);
2082
+            }
2083
+        }
2084
+    } else {
2085
+        // si on ne connait pas le type on le deduit de $v autant que possible
2086
+        if (is_bool($v)) {
2087
+            return strval(intval($v));
2088
+        }
2089
+        elseif (is_numeric($v)) {
2090
+            return strval($v);
2091
+        }
2092
+    }
2093
+
2094
+    // trouver un link sqlite pour faire l'echappement
2095
+    foreach ($GLOBALS['connexions'] as $s) {
2096
+        if (
2097
+            $l = $s['link']
2098
+            and is_object($l)
2099
+            and $l instanceof \PDO
2100
+            and $l->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'sqlite'
2101
+        ) {
2102
+            return $l->quote($v);
2103
+        }
2104
+    }
2105
+
2106
+    // echapper les ' en ''
2107
+    spip_log('Pas de methode ->quote pour echapper', 'sqlite.' . _LOG_INFO_IMPORTANTE);
2108
+
2109
+    return ("'" . str_replace("'", "''", $v) . "'");
2110 2110
 }
2111 2111
 
2112 2112
 
@@ -2122,21 +2122,21 @@  discard block
 block discarded – undo
2122 2122
  * @return string            Texte de l'expression, une partie donc, du texte la requête.
2123 2123
  */
2124 2124
 function _sqlite_calculer_expression($expression, $v, $join = 'AND') {
2125
-	if (empty($v)) {
2126
-		return '';
2127
-	}
2125
+    if (empty($v)) {
2126
+        return '';
2127
+    }
2128 2128
 
2129
-	$exp = "\n$expression ";
2129
+    $exp = "\n$expression ";
2130 2130
 
2131
-	if (!is_array($v)) {
2132
-		return $exp . $v;
2133
-	} else {
2134
-		if (strtoupper($join) === 'AND') {
2135
-			return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
2136
-		} else {
2137
-			return $exp . join($join, $v);
2138
-		}
2139
-	}
2131
+    if (!is_array($v)) {
2132
+        return $exp . $v;
2133
+    } else {
2134
+        if (strtoupper($join) === 'AND') {
2135
+            return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
2136
+        } else {
2137
+            return $exp . join($join, $v);
2138
+        }
2139
+    }
2140 2140
 }
2141 2141
 
2142 2142
 
@@ -2152,7 +2152,7 @@  discard block
 block discarded – undo
2152 2152
  * @return string Texte du orderby préparé
2153 2153
  */
2154 2154
 function _sqlite_calculer_order($orderby) {
2155
-	return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
2155
+    return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
2156 2156
 }
2157 2157
 
2158 2158
 
@@ -2163,26 +2163,26 @@  discard block
 block discarded – undo
2163 2163
  * @return string Sélection de colonnes pour une clause SELECT
2164 2164
  */
2165 2165
 function _sqlite_calculer_select_as($args) {
2166
-	$res = '';
2167
-	foreach ($args as $k => $v) {
2168
-		if (substr($k, -1) == '@') {
2169
-			// c'est une jointure qui se refere au from precedent
2170
-			// pas de virgule
2171
-			$res .= '  ' . $v;
2172
-		} else {
2173
-			if (!is_numeric($k)) {
2174
-				$p = strpos($v, ' ');
2175
-				if ($p) {
2176
-					$v = substr($v, 0, $p) . " AS '$k'" . substr($v, $p);
2177
-				} else {
2178
-					$v .= " AS '$k'";
2179
-				}
2180
-			}
2181
-			$res .= ', ' . $v;
2182
-		}
2183
-	}
2184
-
2185
-	return substr($res, 2);
2166
+    $res = '';
2167
+    foreach ($args as $k => $v) {
2168
+        if (substr($k, -1) == '@') {
2169
+            // c'est une jointure qui se refere au from precedent
2170
+            // pas de virgule
2171
+            $res .= '  ' . $v;
2172
+        } else {
2173
+            if (!is_numeric($k)) {
2174
+                $p = strpos($v, ' ');
2175
+                if ($p) {
2176
+                    $v = substr($v, 0, $p) . " AS '$k'" . substr($v, $p);
2177
+                } else {
2178
+                    $v .= " AS '$k'";
2179
+                }
2180
+            }
2181
+            $res .= ', ' . $v;
2182
+        }
2183
+    }
2184
+
2185
+    return substr($res, 2);
2186 2186
 }
2187 2187
 
2188 2188
 
@@ -2205,26 +2205,26 @@  discard block
 block discarded – undo
2205 2205
  *     Contrainte pour clause WHERE
2206 2206
  */
2207 2207
 function _sqlite_calculer_where($v) {
2208
-	if (!is_array($v)) {
2209
-		return $v;
2210
-	}
2211
-
2212
-	$op = array_shift($v);
2213
-	if (!($n = count($v))) {
2214
-		return $op;
2215
-	} else {
2216
-		$arg = _sqlite_calculer_where(array_shift($v));
2217
-		if ($n == 1) {
2218
-			return "$op($arg)";
2219
-		} else {
2220
-			$arg2 = _sqlite_calculer_where(array_shift($v));
2221
-			if ($n == 2) {
2222
-				return "($arg $op $arg2)";
2223
-			} else {
2224
-				return "($arg $op ($arg2) : $v[0])";
2225
-			}
2226
-		}
2227
-	}
2208
+    if (!is_array($v)) {
2209
+        return $v;
2210
+    }
2211
+
2212
+    $op = array_shift($v);
2213
+    if (!($n = count($v))) {
2214
+        return $op;
2215
+    } else {
2216
+        $arg = _sqlite_calculer_where(array_shift($v));
2217
+        if ($n == 1) {
2218
+            return "$op($arg)";
2219
+        } else {
2220
+            $arg2 = _sqlite_calculer_where(array_shift($v));
2221
+            if ($n == 2) {
2222
+                return "($arg $op $arg2)";
2223
+            } else {
2224
+                return "($arg $op ($arg2) : $v[0])";
2225
+            }
2226
+        }
2227
+    }
2228 2228
 }
2229 2229
 
2230 2230
 
@@ -2239,19 +2239,19 @@  discard block
 block discarded – undo
2239 2239
  * @return array|bool
2240 2240
  */
2241 2241
 function _sqlite_charger_version($version = '') {
2242
-	$versions = [];
2242
+    $versions = [];
2243 2243
 
2244
-	// version 3
2245
-	if (!$version || $version == 3) {
2246
-		if (extension_loaded('pdo') && extension_loaded('pdo_sqlite')) {
2247
-			$versions[] = 3;
2248
-		}
2249
-	}
2250
-	if ($version) {
2251
-		return in_array($version, $versions);
2252
-	}
2244
+    // version 3
2245
+    if (!$version || $version == 3) {
2246
+        if (extension_loaded('pdo') && extension_loaded('pdo_sqlite')) {
2247
+            $versions[] = 3;
2248
+        }
2249
+    }
2250
+    if ($version) {
2251
+        return in_array($version, $versions);
2252
+    }
2253 2253
 
2254
-	return $versions;
2254
+    return $versions;
2255 2255
 }
2256 2256
 
2257 2257
 
@@ -2289,147 +2289,147 @@  discard block
 block discarded – undo
2289 2289
  */
2290 2290
 function _sqlite_modifier_table($table, $colonne, $opt = [], $serveur = '') {
2291 2291
 
2292
-	if (is_array($table)) {
2293
-		$table_destination = reset($table);
2294
-		$table_origine = key($table);
2295
-	} else {
2296
-		$table_origine = $table_destination = $table;
2297
-	}
2298
-	// ne prend actuellement qu'un changement
2299
-	// mais pourra etre adapte pour changer plus qu'une colonne a la fois
2300
-	if (is_array($colonne)) {
2301
-		$colonne_destination = reset($colonne);
2302
-		$colonne_origine = key($colonne);
2303
-	} else {
2304
-		$colonne_origine = $colonne_destination = $colonne;
2305
-	}
2306
-	if (!isset($opt['field'])) {
2307
-		$opt['field'] = [];
2308
-	}
2309
-	if (!isset($opt['key'])) {
2310
-		$opt['key'] = [];
2311
-	}
2312
-
2313
-	// si les noms de tables sont differents, pas besoin de table temporaire
2314
-	// on prendra directement le nom de la future table
2315
-	$meme_table = ($table_origine == $table_destination);
2316
-
2317
-	$def_origine = sql_showtable($table_origine, false, $serveur);
2318
-	if (!$def_origine or !isset($def_origine['field'])) {
2319
-		spip_log("Alter table impossible sur $table_origine : table non trouvee", 'sqlite' . _LOG_ERREUR);
2320
-
2321
-		return false;
2322
-	}
2323
-
2324
-
2325
-	$table_tmp = $table_origine . '_tmp';
2326
-
2327
-	// 1) creer une table temporaire avec les modifications
2328
-	// - DROP : suppression de la colonne
2329
-	// - CHANGE : modification de la colonne
2330
-	// (foreach pour conserver l'ordre des champs)
2331
-
2332
-	// field
2333
-	$fields = [];
2334
-	// pour le INSERT INTO plus loin
2335
-	// stocker la correspondance nouvelles->anciennes colonnes
2336
-	$fields_correspondances = [];
2337
-	foreach ($def_origine['field'] as $c => $d) {
2338
-		if ($colonne_origine && ($c == $colonne_origine)) {
2339
-			// si pas DROP
2340
-			if ($colonne_destination) {
2341
-				$fields[$colonne_destination] = $opt['field'][$colonne_destination];
2342
-				$fields_correspondances[$colonne_destination] = $c;
2343
-			}
2344
-		} else {
2345
-			$fields[$c] = $d;
2346
-			$fields_correspondances[$c] = $c;
2347
-		}
2348
-	}
2349
-	// cas de ADD sqlite2 (ajout du champ en fin de table):
2350
-	if (!$colonne_origine && $colonne_destination) {
2351
-		$fields[$colonne_destination] = $opt['field'][$colonne_destination];
2352
-	}
2353
-
2354
-	// key...
2355
-	$keys = [];
2356
-	foreach ($def_origine['key'] as $c => $d) {
2357
-		$c = str_replace($colonne_origine, $colonne_destination, $c);
2358
-		$d = str_replace($colonne_origine, $colonne_destination, $d);
2359
-		// seulement si on ne supprime pas la colonne !
2360
-		if ($d) {
2361
-			$keys[$c] = $d;
2362
-		}
2363
-	}
2364
-
2365
-	// autres keys, on merge
2366
-	$keys = array_merge($keys, $opt['key']);
2367
-	$queries = [];
2368
-
2369
-	// copier dans destination (si differente de origine), sinon tmp
2370
-	$table_copie = ($meme_table) ? $table_tmp : $table_destination;
2371
-	$autoinc = (isset($keys['PRIMARY KEY'])
2372
-		and $keys['PRIMARY KEY']
2373
-		and stripos($keys['PRIMARY KEY'], ',') === false
2374
-		and stripos($fields[$keys['PRIMARY KEY']], 'default') === false);
2375
-
2376
-	if (
2377
-		$q = _sqlite_requete_create(
2378
-			$table_copie,
2379
-			$fields,
2380
-			$keys,
2381
-			$autoinc,
2382
-			$temporary = false,
2383
-			$ifnotexists = true,
2384
-			$serveur
2385
-		)
2386
-	) {
2387
-		$queries[] = $q;
2388
-	}
2389
-
2390
-
2391
-	// 2) y copier les champs qui vont bien
2392
-	$champs_dest = join(', ', array_keys($fields_correspondances));
2393
-	$champs_ori = join(', ', $fields_correspondances);
2394
-	$queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
2395
-
2396
-	// 3) supprimer la table d'origine
2397
-	$queries[] = "DROP TABLE $table_origine";
2398
-
2399
-	// 4) renommer la table temporaire
2400
-	// avec le nom de la table destination
2401
-	// si necessaire
2402
-	if ($meme_table) {
2403
-		$queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
2404
-	}
2405
-
2406
-	// 5) remettre les index !
2407
-	foreach ($keys as $k => $v) {
2408
-		if ($k == 'PRIMARY KEY') {
2409
-		} else {
2410
-			// enlever KEY
2411
-			$k = substr($k, 4);
2412
-			$queries[] = "CREATE INDEX $table_destination" . "_$k ON $table_destination ($v)";
2413
-		}
2414
-	}
2415
-
2416
-
2417
-	if (count($queries)) {
2418
-		spip_sqlite::demarrer_transaction($serveur);
2419
-		// il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
2420
-		foreach ($queries as $q) {
2421
-			if (!spip_sqlite::executer_requete($q, $serveur)) {
2422
-				spip_log('SQLite : ALTER TABLE table :'
2423
-					. " Erreur a l'execution de la requete : $q", 'sqlite.' . _LOG_ERREUR);
2424
-				spip_sqlite::annuler_transaction($serveur);
2425
-
2426
-				return false;
2427
-			}
2428
-		}
2429
-		spip_sqlite::finir_transaction($serveur);
2430
-	}
2431
-
2432
-	return true;
2292
+    if (is_array($table)) {
2293
+        $table_destination = reset($table);
2294
+        $table_origine = key($table);
2295
+    } else {
2296
+        $table_origine = $table_destination = $table;
2297
+    }
2298
+    // ne prend actuellement qu'un changement
2299
+    // mais pourra etre adapte pour changer plus qu'une colonne a la fois
2300
+    if (is_array($colonne)) {
2301
+        $colonne_destination = reset($colonne);
2302
+        $colonne_origine = key($colonne);
2303
+    } else {
2304
+        $colonne_origine = $colonne_destination = $colonne;
2305
+    }
2306
+    if (!isset($opt['field'])) {
2307
+        $opt['field'] = [];
2308
+    }
2309
+    if (!isset($opt['key'])) {
2310
+        $opt['key'] = [];
2311
+    }
2312
+
2313
+    // si les noms de tables sont differents, pas besoin de table temporaire
2314
+    // on prendra directement le nom de la future table
2315
+    $meme_table = ($table_origine == $table_destination);
2316
+
2317
+    $def_origine = sql_showtable($table_origine, false, $serveur);
2318
+    if (!$def_origine or !isset($def_origine['field'])) {
2319
+        spip_log("Alter table impossible sur $table_origine : table non trouvee", 'sqlite' . _LOG_ERREUR);
2320
+
2321
+        return false;
2322
+    }
2323
+
2324
+
2325
+    $table_tmp = $table_origine . '_tmp';
2326
+
2327
+    // 1) creer une table temporaire avec les modifications
2328
+    // - DROP : suppression de la colonne
2329
+    // - CHANGE : modification de la colonne
2330
+    // (foreach pour conserver l'ordre des champs)
2331
+
2332
+    // field
2333
+    $fields = [];
2334
+    // pour le INSERT INTO plus loin
2335
+    // stocker la correspondance nouvelles->anciennes colonnes
2336
+    $fields_correspondances = [];
2337
+    foreach ($def_origine['field'] as $c => $d) {
2338
+        if ($colonne_origine && ($c == $colonne_origine)) {
2339
+            // si pas DROP
2340
+            if ($colonne_destination) {
2341
+                $fields[$colonne_destination] = $opt['field'][$colonne_destination];
2342
+                $fields_correspondances[$colonne_destination] = $c;
2343
+            }
2344
+        } else {
2345
+            $fields[$c] = $d;
2346
+            $fields_correspondances[$c] = $c;
2347
+        }
2348
+    }
2349
+    // cas de ADD sqlite2 (ajout du champ en fin de table):
2350
+    if (!$colonne_origine && $colonne_destination) {
2351
+        $fields[$colonne_destination] = $opt['field'][$colonne_destination];
2352
+    }
2353
+
2354
+    // key...
2355
+    $keys = [];
2356
+    foreach ($def_origine['key'] as $c => $d) {
2357
+        $c = str_replace($colonne_origine, $colonne_destination, $c);
2358
+        $d = str_replace($colonne_origine, $colonne_destination, $d);
2359
+        // seulement si on ne supprime pas la colonne !
2360
+        if ($d) {
2361
+            $keys[$c] = $d;
2362
+        }
2363
+    }
2364
+
2365
+    // autres keys, on merge
2366
+    $keys = array_merge($keys, $opt['key']);
2367
+    $queries = [];
2368
+
2369
+    // copier dans destination (si differente de origine), sinon tmp
2370
+    $table_copie = ($meme_table) ? $table_tmp : $table_destination;
2371
+    $autoinc = (isset($keys['PRIMARY KEY'])
2372
+        and $keys['PRIMARY KEY']
2373
+        and stripos($keys['PRIMARY KEY'], ',') === false
2374
+        and stripos($fields[$keys['PRIMARY KEY']], 'default') === false);
2375
+
2376
+    if (
2377
+        $q = _sqlite_requete_create(
2378
+            $table_copie,
2379
+            $fields,
2380
+            $keys,
2381
+            $autoinc,
2382
+            $temporary = false,
2383
+            $ifnotexists = true,
2384
+            $serveur
2385
+        )
2386
+    ) {
2387
+        $queries[] = $q;
2388
+    }
2389
+
2390
+
2391
+    // 2) y copier les champs qui vont bien
2392
+    $champs_dest = join(', ', array_keys($fields_correspondances));
2393
+    $champs_ori = join(', ', $fields_correspondances);
2394
+    $queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
2395
+
2396
+    // 3) supprimer la table d'origine
2397
+    $queries[] = "DROP TABLE $table_origine";
2398
+
2399
+    // 4) renommer la table temporaire
2400
+    // avec le nom de la table destination
2401
+    // si necessaire
2402
+    if ($meme_table) {
2403
+        $queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
2404
+    }
2405
+
2406
+    // 5) remettre les index !
2407
+    foreach ($keys as $k => $v) {
2408
+        if ($k == 'PRIMARY KEY') {
2409
+        } else {
2410
+            // enlever KEY
2411
+            $k = substr($k, 4);
2412
+            $queries[] = "CREATE INDEX $table_destination" . "_$k ON $table_destination ($v)";
2413
+        }
2414
+    }
2415
+
2416
+
2417
+    if (count($queries)) {
2418
+        spip_sqlite::demarrer_transaction($serveur);
2419
+        // il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
2420
+        foreach ($queries as $q) {
2421
+            if (!spip_sqlite::executer_requete($q, $serveur)) {
2422
+                spip_log('SQLite : ALTER TABLE table :'
2423
+                    . " Erreur a l'execution de la requete : $q", 'sqlite.' . _LOG_ERREUR);
2424
+                spip_sqlite::annuler_transaction($serveur);
2425
+
2426
+                return false;
2427
+            }
2428
+        }
2429
+        spip_sqlite::finir_transaction($serveur);
2430
+    }
2431
+
2432
+    return true;
2433 2433
 }
2434 2434
 
2435 2435
 
@@ -2439,61 +2439,61 @@  discard block
 block discarded – undo
2439 2439
  * @return array
2440 2440
  */
2441 2441
 function _sqlite_ref_fonctions() {
2442
-	$fonctions = [
2443
-		'alter' => 'spip_sqlite_alter',
2444
-		'count' => 'spip_sqlite_count',
2445
-		'countsel' => 'spip_sqlite_countsel',
2446
-		'create' => 'spip_sqlite_create',
2447
-		'create_base' => 'spip_sqlite_create_base',
2448
-		'create_view' => 'spip_sqlite_create_view',
2449
-		'date_proche' => 'spip_sqlite_date_proche',
2450
-		'delete' => 'spip_sqlite_delete',
2451
-		'drop_table' => 'spip_sqlite_drop_table',
2452
-		'drop_view' => 'spip_sqlite_drop_view',
2453
-		'errno' => 'spip_sqlite_errno',
2454
-		'error' => 'spip_sqlite_error',
2455
-		'explain' => 'spip_sqlite_explain',
2456
-		'fetch' => 'spip_sqlite_fetch',
2457
-		'seek' => 'spip_sqlite_seek',
2458
-		'free' => 'spip_sqlite_free',
2459
-		'hex' => 'spip_sqlite_hex',
2460
-		'in' => 'spip_sqlite_in',
2461
-		'insert' => 'spip_sqlite_insert',
2462
-		'insertq' => 'spip_sqlite_insertq',
2463
-		'insertq_multi' => 'spip_sqlite_insertq_multi',
2464
-		'listdbs' => 'spip_sqlite_listdbs',
2465
-		'multi' => 'spip_sqlite_multi',
2466
-		'optimize' => 'spip_sqlite_optimize',
2467
-		'query' => 'spip_sqlite_query',
2468
-		'quote' => 'spip_sqlite_quote',
2469
-		'repair' => 'spip_sqlite_repair',
2470
-		'replace' => 'spip_sqlite_replace',
2471
-		'replace_multi' => 'spip_sqlite_replace_multi',
2472
-		'select' => 'spip_sqlite_select',
2473
-		'selectdb' => 'spip_sqlite_selectdb',
2474
-		'set_charset' => 'spip_sqlite_set_charset',
2475
-		'get_charset' => 'spip_sqlite_get_charset',
2476
-		'showbase' => 'spip_sqlite_showbase',
2477
-		'showtable' => 'spip_sqlite_showtable',
2478
-		'table_exists' => 'spip_sqlite_table_exists',
2479
-		'update' => 'spip_sqlite_update',
2480
-		'updateq' => 'spip_sqlite_updateq',
2481
-		'preferer_transaction' => 'spip_sqlite_preferer_transaction',
2482
-		'demarrer_transaction' => 'spip_sqlite_demarrer_transaction',
2483
-		'terminer_transaction' => 'spip_sqlite_terminer_transaction',
2484
-	];
2485
-
2486
-	// association de chaque nom http d'un charset aux couples sqlite
2487
-	// SQLite supporte utf-8 et utf-16 uniquement.
2488
-	$charsets = [
2489
-		'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci'],
2490
-		//'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
2491
-		//'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
2492
-	];
2493
-
2494
-	$fonctions['charsets'] = $charsets;
2495
-
2496
-	return $fonctions;
2442
+    $fonctions = [
2443
+        'alter' => 'spip_sqlite_alter',
2444
+        'count' => 'spip_sqlite_count',
2445
+        'countsel' => 'spip_sqlite_countsel',
2446
+        'create' => 'spip_sqlite_create',
2447
+        'create_base' => 'spip_sqlite_create_base',
2448
+        'create_view' => 'spip_sqlite_create_view',
2449
+        'date_proche' => 'spip_sqlite_date_proche',
2450
+        'delete' => 'spip_sqlite_delete',
2451
+        'drop_table' => 'spip_sqlite_drop_table',
2452
+        'drop_view' => 'spip_sqlite_drop_view',
2453
+        'errno' => 'spip_sqlite_errno',
2454
+        'error' => 'spip_sqlite_error',
2455
+        'explain' => 'spip_sqlite_explain',
2456
+        'fetch' => 'spip_sqlite_fetch',
2457
+        'seek' => 'spip_sqlite_seek',
2458
+        'free' => 'spip_sqlite_free',
2459
+        'hex' => 'spip_sqlite_hex',
2460
+        'in' => 'spip_sqlite_in',
2461
+        'insert' => 'spip_sqlite_insert',
2462
+        'insertq' => 'spip_sqlite_insertq',
2463
+        'insertq_multi' => 'spip_sqlite_insertq_multi',
2464
+        'listdbs' => 'spip_sqlite_listdbs',
2465
+        'multi' => 'spip_sqlite_multi',
2466
+        'optimize' => 'spip_sqlite_optimize',
2467
+        'query' => 'spip_sqlite_query',
2468
+        'quote' => 'spip_sqlite_quote',
2469
+        'repair' => 'spip_sqlite_repair',
2470
+        'replace' => 'spip_sqlite_replace',
2471
+        'replace_multi' => 'spip_sqlite_replace_multi',
2472
+        'select' => 'spip_sqlite_select',
2473
+        'selectdb' => 'spip_sqlite_selectdb',
2474
+        'set_charset' => 'spip_sqlite_set_charset',
2475
+        'get_charset' => 'spip_sqlite_get_charset',
2476
+        'showbase' => 'spip_sqlite_showbase',
2477
+        'showtable' => 'spip_sqlite_showtable',
2478
+        'table_exists' => 'spip_sqlite_table_exists',
2479
+        'update' => 'spip_sqlite_update',
2480
+        'updateq' => 'spip_sqlite_updateq',
2481
+        'preferer_transaction' => 'spip_sqlite_preferer_transaction',
2482
+        'demarrer_transaction' => 'spip_sqlite_demarrer_transaction',
2483
+        'terminer_transaction' => 'spip_sqlite_terminer_transaction',
2484
+    ];
2485
+
2486
+    // association de chaque nom http d'un charset aux couples sqlite
2487
+    // SQLite supporte utf-8 et utf-16 uniquement.
2488
+    $charsets = [
2489
+        'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci'],
2490
+        //'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
2491
+        //'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
2492
+    ];
2493
+
2494
+    $fonctions['charsets'] = $charsets;
2495
+
2496
+    return $fonctions;
2497 2497
 }
2498 2498
 
2499 2499
 
@@ -2505,56 +2505,56 @@  discard block
 block discarded – undo
2505 2505
  * @return mixed
2506 2506
  */
2507 2507
 function _sqlite_remplacements_definitions_table($query, $autoinc = false) {
2508
-	// quelques remplacements
2509
-	$num = '(\s*\([0-9]*\))?';
2510
-	$enum = '(\s*\([^\)]*\))?';
2511
-
2512
-	$remplace = [
2513
-		'/enum' . $enum . '/is' => 'VARCHAR(255)',
2514
-		'/COLLATE \w+_bin/is' => 'COLLATE BINARY',
2515
-		'/COLLATE \w+_ci/is' => 'COLLATE NOCASE',
2516
-		'/auto_increment/is' => '',
2517
-		'/current_timestamp\(\)/is' => 'CURRENT_TIMESTAMP', // Fix export depuis mariaDB #4374
2518
-		'/(timestamp .* )ON .*$/is' => '\\1',
2519
-		'/character set \w+/is' => '',
2520
-		'/((big|small|medium|tiny)?int(eger)?)' . $num . '\s*unsigned/is' => '\\1 UNSIGNED',
2521
-		'/(text\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2522
-		'/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2523
-		'/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
2524
-		'/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
2525
-	];
2526
-
2527
-	// pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
2528
-	$remplace_autocinc = [
2529
-		'/(big|small|medium|tiny)?int(eger)?' . $num . '/is' => 'INTEGER'
2530
-	];
2531
-	// pour les int non autoincrement, il faut un DEFAULT
2532
-	$remplace_nonautocinc = [
2533
-		'/((big|small|medium|tiny)?int(eger)?' . $num . '\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
2534
-	];
2535
-
2536
-	if (is_string($query)) {
2537
-		$query = preg_replace(array_keys($remplace), $remplace, $query);
2538
-		if ($autoinc or preg_match(',AUTO_INCREMENT,is', $query)) {
2539
-			$query = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query);
2540
-		} else {
2541
-			$query = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query);
2542
-			$query = _sqlite_collate_ci($query);
2543
-		}
2544
-	} elseif (is_array($query)) {
2545
-		foreach ($query as $k => $q) {
2546
-			$ai = ($autoinc ? $k == $autoinc : preg_match(',AUTO_INCREMENT,is', $q));
2547
-			$query[$k] = preg_replace(array_keys($remplace), $remplace, $query[$k]);
2548
-			if ($ai) {
2549
-				$query[$k] = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query[$k]);
2550
-			} else {
2551
-				$query[$k] = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query[$k]);
2552
-				$query[$k] = _sqlite_collate_ci($query[$k]);
2553
-			}
2554
-		}
2555
-	}
2556
-
2557
-	return $query;
2508
+    // quelques remplacements
2509
+    $num = '(\s*\([0-9]*\))?';
2510
+    $enum = '(\s*\([^\)]*\))?';
2511
+
2512
+    $remplace = [
2513
+        '/enum' . $enum . '/is' => 'VARCHAR(255)',
2514
+        '/COLLATE \w+_bin/is' => 'COLLATE BINARY',
2515
+        '/COLLATE \w+_ci/is' => 'COLLATE NOCASE',
2516
+        '/auto_increment/is' => '',
2517
+        '/current_timestamp\(\)/is' => 'CURRENT_TIMESTAMP', // Fix export depuis mariaDB #4374
2518
+        '/(timestamp .* )ON .*$/is' => '\\1',
2519
+        '/character set \w+/is' => '',
2520
+        '/((big|small|medium|tiny)?int(eger)?)' . $num . '\s*unsigned/is' => '\\1 UNSIGNED',
2521
+        '/(text\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2522
+        '/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2523
+        '/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
2524
+        '/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
2525
+    ];
2526
+
2527
+    // pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
2528
+    $remplace_autocinc = [
2529
+        '/(big|small|medium|tiny)?int(eger)?' . $num . '/is' => 'INTEGER'
2530
+    ];
2531
+    // pour les int non autoincrement, il faut un DEFAULT
2532
+    $remplace_nonautocinc = [
2533
+        '/((big|small|medium|tiny)?int(eger)?' . $num . '\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
2534
+    ];
2535
+
2536
+    if (is_string($query)) {
2537
+        $query = preg_replace(array_keys($remplace), $remplace, $query);
2538
+        if ($autoinc or preg_match(',AUTO_INCREMENT,is', $query)) {
2539
+            $query = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query);
2540
+        } else {
2541
+            $query = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query);
2542
+            $query = _sqlite_collate_ci($query);
2543
+        }
2544
+    } elseif (is_array($query)) {
2545
+        foreach ($query as $k => $q) {
2546
+            $ai = ($autoinc ? $k == $autoinc : preg_match(',AUTO_INCREMENT,is', $q));
2547
+            $query[$k] = preg_replace(array_keys($remplace), $remplace, $query[$k]);
2548
+            if ($ai) {
2549
+                $query[$k] = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query[$k]);
2550
+            } else {
2551
+                $query[$k] = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query[$k]);
2552
+                $query[$k] = _sqlite_collate_ci($query[$k]);
2553
+            }
2554
+        }
2555
+    }
2556
+
2557
+    return $query;
2558 2558
 }
2559 2559
 
2560 2560
 /**
@@ -2565,17 +2565,17 @@  discard block
 block discarded – undo
2565 2565
  * @return string
2566 2566
  */
2567 2567
 function _sqlite_collate_ci($champ) {
2568
-	if (stripos($champ, 'COLLATE') !== false) {
2569
-		return $champ;
2570
-	}
2571
-	if (stripos($champ, 'BINARY') !== false) {
2572
-		return str_ireplace('BINARY', 'COLLATE BINARY', $champ);
2573
-	}
2574
-	if (preg_match(',^(char|varchar|(long|small|medium|tiny)?text),i', $champ)) {
2575
-		return $champ . ' COLLATE NOCASE';
2576
-	}
2568
+    if (stripos($champ, 'COLLATE') !== false) {
2569
+        return $champ;
2570
+    }
2571
+    if (stripos($champ, 'BINARY') !== false) {
2572
+        return str_ireplace('BINARY', 'COLLATE BINARY', $champ);
2573
+    }
2574
+    if (preg_match(',^(char|varchar|(long|small|medium|tiny)?text),i', $champ)) {
2575
+        return $champ . ' COLLATE NOCASE';
2576
+    }
2577 2577
 
2578
-	return $champ;
2578
+    return $champ;
2579 2579
 }
2580 2580
 
2581 2581
 
@@ -2594,84 +2594,84 @@  discard block
 block discarded – undo
2594 2594
  * @return bool|string
2595 2595
  */
2596 2596
 function _sqlite_requete_create(
2597
-	$nom,
2598
-	$champs,
2599
-	$cles,
2600
-	$autoinc = false,
2601
-	$temporary = false,
2602
-	$_ifnotexists = true,
2603
-	$serveur = '',
2604
-	$requeter = true
2597
+    $nom,
2598
+    $champs,
2599
+    $cles,
2600
+    $autoinc = false,
2601
+    $temporary = false,
2602
+    $_ifnotexists = true,
2603
+    $serveur = '',
2604
+    $requeter = true
2605 2605
 ) {
2606
-	$query = $keys = $s = $p = '';
2607
-
2608
-	// certains plugins declarent les tables  (permet leur inclusion dans le dump)
2609
-	// sans les renseigner (laisse le compilo recuperer la description)
2610
-	if (!is_array($champs) || !is_array($cles)) {
2611
-		return;
2612
-	}
2613
-
2614
-	// sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
2615
-	// il faut passer par des create index
2616
-	// Il gere par contre primary key !
2617
-	// Soit la PK est definie dans les cles, soit dans un champs
2618
-	// soit faussement dans les 2 (et dans ce cas, il faut l’enlever à un des 2 endroits !)
2619
-	$pk = 'PRIMARY KEY';
2620
-	// le champ de cle primaire
2621
-	$champ_pk = !empty($cles[$pk]) ? $cles[$pk] : '';
2622
-
2623
-	foreach ($champs as $k => $v) {
2624
-		if (false !== stripos($v, $pk)) {
2625
-			$champ_pk = $k;
2626
-			// on n'en a plus besoin dans field, vu que defini dans key
2627
-			$champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
2628
-			break;
2629
-		}
2630
-	}
2631
-
2632
-	if ($champ_pk) {
2633
-		$keys = "\n\t\t$pk ($champ_pk)";
2634
-	}
2635
-	// Pas de DEFAULT 0 sur les cles primaires en auto-increment
2636
-	if (
2637
-		isset($champs[$champ_pk])
2638
-		and stripos($champs[$champ_pk], 'default 0') !== false
2639
-	) {
2640
-		$champs[$champ_pk] = trim(str_ireplace('default 0', '', $champs[$champ_pk]));
2641
-	}
2642
-
2643
-	$champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $champ_pk : false);
2644
-	foreach ($champs as $k => $v) {
2645
-		$query .= "$s\n\t\t$k $v";
2646
-		$s = ',';
2647
-	}
2648
-
2649
-	$ifnotexists = '';
2650
-	if ($_ifnotexists) {
2651
-		$version = spip_sqlite_fetch(
2652
-			spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur),
2653
-			'',
2654
-			$serveur
2655
-		);
2656
-		if (!function_exists('spip_version_compare')) {
2657
-			include_spip('plugins/installer');
2658
-		}
2659
-
2660
-		if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
2661
-			$ifnotexists = ' IF NOT EXISTS';
2662
-		} else {
2663
-			/* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
2664
-			$a = spip_sqlite_showtable($nom, $serveur);
2665
-			if (isset($a['key']['KEY ' . $nom])) {
2666
-				return true;
2667
-			}
2668
-		}
2669
-	}
2670
-
2671
-	$temporary = $temporary ? ' TEMPORARY' : '';
2672
-	$q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
2673
-
2674
-	return $q;
2606
+    $query = $keys = $s = $p = '';
2607
+
2608
+    // certains plugins declarent les tables  (permet leur inclusion dans le dump)
2609
+    // sans les renseigner (laisse le compilo recuperer la description)
2610
+    if (!is_array($champs) || !is_array($cles)) {
2611
+        return;
2612
+    }
2613
+
2614
+    // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
2615
+    // il faut passer par des create index
2616
+    // Il gere par contre primary key !
2617
+    // Soit la PK est definie dans les cles, soit dans un champs
2618
+    // soit faussement dans les 2 (et dans ce cas, il faut l’enlever à un des 2 endroits !)
2619
+    $pk = 'PRIMARY KEY';
2620
+    // le champ de cle primaire
2621
+    $champ_pk = !empty($cles[$pk]) ? $cles[$pk] : '';
2622
+
2623
+    foreach ($champs as $k => $v) {
2624
+        if (false !== stripos($v, $pk)) {
2625
+            $champ_pk = $k;
2626
+            // on n'en a plus besoin dans field, vu que defini dans key
2627
+            $champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
2628
+            break;
2629
+        }
2630
+    }
2631
+
2632
+    if ($champ_pk) {
2633
+        $keys = "\n\t\t$pk ($champ_pk)";
2634
+    }
2635
+    // Pas de DEFAULT 0 sur les cles primaires en auto-increment
2636
+    if (
2637
+        isset($champs[$champ_pk])
2638
+        and stripos($champs[$champ_pk], 'default 0') !== false
2639
+    ) {
2640
+        $champs[$champ_pk] = trim(str_ireplace('default 0', '', $champs[$champ_pk]));
2641
+    }
2642
+
2643
+    $champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $champ_pk : false);
2644
+    foreach ($champs as $k => $v) {
2645
+        $query .= "$s\n\t\t$k $v";
2646
+        $s = ',';
2647
+    }
2648
+
2649
+    $ifnotexists = '';
2650
+    if ($_ifnotexists) {
2651
+        $version = spip_sqlite_fetch(
2652
+            spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur),
2653
+            '',
2654
+            $serveur
2655
+        );
2656
+        if (!function_exists('spip_version_compare')) {
2657
+            include_spip('plugins/installer');
2658
+        }
2659
+
2660
+        if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
2661
+            $ifnotexists = ' IF NOT EXISTS';
2662
+        } else {
2663
+            /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
2664
+            $a = spip_sqlite_showtable($nom, $serveur);
2665
+            if (isset($a['key']['KEY ' . $nom])) {
2666
+                return true;
2667
+            }
2668
+        }
2669
+    }
2670
+
2671
+    $temporary = $temporary ? ' TEMPORARY' : '';
2672
+    $q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
2673
+
2674
+    return $q;
2675 2675
 }
2676 2676
 
2677 2677
 
@@ -2690,41 +2690,41 @@  discard block
 block discarded – undo
2690 2690
  * @return
2691 2691
  */
2692 2692
 function _sqlite_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur = '') {
2693
-	static $tables = [];
2694
-
2695
-	if (!isset($tables[$table])) {
2696
-		if (!$desc) {
2697
-			$trouver_table = charger_fonction('trouver_table', 'base');
2698
-			$desc = $trouver_table($table, $serveur);
2699
-			// si pas de description, on ne fait rien, ou on die() ?
2700
-			if (!$desc) {
2701
-				return $couples;
2702
-			}
2703
-		}
2704
-
2705
-		// recherche des champs avec simplement 'TIMESTAMP'
2706
-		// cependant, il faudra peut etre etendre
2707
-		// avec la gestion de DEFAULT et ON UPDATE
2708
-		// mais ceux-ci ne sont pas utilises dans le core
2709
-		$tables[$table] = ['valeur' => [], 'cite' => [], 'desc' => []];
2710
-
2711
-		$now = _sqlite_func_now(true);
2712
-		foreach ($desc['field'] as $k => $v) {
2713
-			if (strpos(strtolower(ltrim($v)), 'timestamp') === 0) {
2714
-				$tables[$table]['desc'][$k] = $v;
2715
-				$tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2716
-			}
2717
-		}
2718
-	}
2719
-	else {
2720
-		$now = _sqlite_func_now(true);
2721
-		foreach (array_keys($tables[$table]['desc']) as $k) {
2722
-			$tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2723
-		}
2724
-	}
2725
-
2726
-	// ajout des champs type 'timestamp' absents
2727
-	return array_merge($tables[$table]['valeur'], $couples);
2693
+    static $tables = [];
2694
+
2695
+    if (!isset($tables[$table])) {
2696
+        if (!$desc) {
2697
+            $trouver_table = charger_fonction('trouver_table', 'base');
2698
+            $desc = $trouver_table($table, $serveur);
2699
+            // si pas de description, on ne fait rien, ou on die() ?
2700
+            if (!$desc) {
2701
+                return $couples;
2702
+            }
2703
+        }
2704
+
2705
+        // recherche des champs avec simplement 'TIMESTAMP'
2706
+        // cependant, il faudra peut etre etendre
2707
+        // avec la gestion de DEFAULT et ON UPDATE
2708
+        // mais ceux-ci ne sont pas utilises dans le core
2709
+        $tables[$table] = ['valeur' => [], 'cite' => [], 'desc' => []];
2710
+
2711
+        $now = _sqlite_func_now(true);
2712
+        foreach ($desc['field'] as $k => $v) {
2713
+            if (strpos(strtolower(ltrim($v)), 'timestamp') === 0) {
2714
+                $tables[$table]['desc'][$k] = $v;
2715
+                $tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2716
+            }
2717
+        }
2718
+    }
2719
+    else {
2720
+        $now = _sqlite_func_now(true);
2721
+        foreach (array_keys($tables[$table]['desc']) as $k) {
2722
+            $tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2723
+        }
2724
+    }
2725
+
2726
+    // ajout des champs type 'timestamp' absents
2727
+    return array_merge($tables[$table]['valeur'], $couples);
2728 2728
 }
2729 2729
 
2730 2730
 
@@ -2735,7 +2735,7 @@  discard block
 block discarded – undo
2735 2735
  * @return array|bool
2736 2736
  */
2737 2737
 function spip_versions_sqlite() {
2738
-	return _sqlite_charger_version();
2738
+    return _sqlite_charger_version();
2739 2739
 }
2740 2740
 
2741 2741
 /**
@@ -2743,114 +2743,114 @@  discard block
 block discarded – undo
2743 2743
  * encadrées de transactions.
2744 2744
  **/
2745 2745
 class spip_sqlite {
2746
-	/** @var sqlite_requeteur[] Liste des instances de requêteurs créés */
2747
-	public static $requeteurs = [];
2748
-	/** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
2749
-	public static $transaction_en_cours = [];
2750
-
2751
-
2752
-	/**
2753
-	 * Retourne une unique instance du requêteur
2754
-	 *
2755
-	 * Retourne une instance unique du requêteur pour une connexion SQLite
2756
-	 * donnée
2757
-	 *
2758
-	 * @param string $serveur
2759
-	 *    Nom du connecteur
2760
-	 * @return sqlite_requeteur
2761
-	 *    Instance unique du requêteur
2762
-	 **/
2763
-	public static function requeteur($serveur) {
2764
-		if (!isset(spip_sqlite::$requeteurs[$serveur])) {
2765
-			spip_sqlite::$requeteurs[$serveur] = new sqlite_requeteur($serveur);
2766
-		}
2767
-
2768
-		return spip_sqlite::$requeteurs[$serveur];
2769
-	}
2770
-
2771
-	/**
2772
-	 * Prépare le texte d'une requête avant son exécution
2773
-	 *
2774
-	 * Adapte la requête au format plus ou moins MySQL par un format
2775
-	 * compris de SQLite.
2776
-	 *
2777
-	 * Change les préfixes de tables SPIP par ceux véritables
2778
-	 *
2779
-	 * @param string $query Requête à préparer
2780
-	 * @param string $serveur Nom de la connexion
2781
-	 * @return string           Requête préparée
2782
-	 */
2783
-	public static function traduire_requete($query, $serveur) {
2784
-		$requeteur = spip_sqlite::requeteur($serveur);
2785
-		$traducteur = new sqlite_traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
2786
-
2787
-		return $traducteur->traduire_requete();
2788
-	}
2789
-
2790
-	/**
2791
-	 * Démarre une transaction
2792
-	 *
2793
-	 * @param string $serveur Nom de la connexion
2794
-	 **/
2795
-	public static function demarrer_transaction($serveur) {
2796
-		spip_sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
2797
-		spip_sqlite::$transaction_en_cours[$serveur] = true;
2798
-	}
2799
-
2800
-	/**
2801
-	 * Exécute la requête donnée
2802
-	 *
2803
-	 * @param string $query Requête
2804
-	 * @param string $serveur Nom de la connexion
2805
-	 * @param null|bool $tracer Demander des statistiques (temps) ?
2806
-	 **/
2807
-	public static function executer_requete($query, $serveur, $tracer = null) {
2808
-		$requeteur = spip_sqlite::requeteur($serveur);
2809
-
2810
-		return $requeteur->executer_requete($query, $tracer);
2811
-	}
2812
-
2813
-	/**
2814
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2815
-	 *
2816
-	 * @param string $serveur Nom de la connexion
2817
-	 * return int                Identifiant
2818
-	 **/
2819
-	public static function last_insert_id($serveur) {
2820
-		$requeteur = spip_sqlite::requeteur($serveur);
2821
-
2822
-		return $requeteur->last_insert_id($serveur);
2823
-	}
2824
-
2825
-	/**
2826
-	 * Annule une transaction
2827
-	 *
2828
-	 * @param string $serveur Nom de la connexion
2829
-	 **/
2830
-	public static function annuler_transaction($serveur) {
2831
-		spip_sqlite::executer_requete('ROLLBACK', $serveur);
2832
-		spip_sqlite::$transaction_en_cours[$serveur] = false;
2833
-	}
2834
-
2835
-	/**
2836
-	 * Termine une transaction
2837
-	 *
2838
-	 * @param string $serveur Nom de la connexion
2839
-	 **/
2840
-	public static function finir_transaction($serveur) {
2841
-		// si pas de transaction en cours, ne rien faire et le dire
2842
-		if (
2843
-			!isset(spip_sqlite::$transaction_en_cours[$serveur])
2844
-			or spip_sqlite::$transaction_en_cours[$serveur] == false
2845
-		) {
2846
-			return false;
2847
-		}
2848
-		// sinon fermer la transaction et retourner true
2849
-		spip_sqlite::executer_requete('COMMIT', $serveur);
2850
-		spip_sqlite::$transaction_en_cours[$serveur] = false;
2851
-
2852
-		return true;
2853
-	}
2746
+    /** @var sqlite_requeteur[] Liste des instances de requêteurs créés */
2747
+    public static $requeteurs = [];
2748
+    /** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
2749
+    public static $transaction_en_cours = [];
2750
+
2751
+
2752
+    /**
2753
+     * Retourne une unique instance du requêteur
2754
+     *
2755
+     * Retourne une instance unique du requêteur pour une connexion SQLite
2756
+     * donnée
2757
+     *
2758
+     * @param string $serveur
2759
+     *    Nom du connecteur
2760
+     * @return sqlite_requeteur
2761
+     *    Instance unique du requêteur
2762
+     **/
2763
+    public static function requeteur($serveur) {
2764
+        if (!isset(spip_sqlite::$requeteurs[$serveur])) {
2765
+            spip_sqlite::$requeteurs[$serveur] = new sqlite_requeteur($serveur);
2766
+        }
2767
+
2768
+        return spip_sqlite::$requeteurs[$serveur];
2769
+    }
2770
+
2771
+    /**
2772
+     * Prépare le texte d'une requête avant son exécution
2773
+     *
2774
+     * Adapte la requête au format plus ou moins MySQL par un format
2775
+     * compris de SQLite.
2776
+     *
2777
+     * Change les préfixes de tables SPIP par ceux véritables
2778
+     *
2779
+     * @param string $query Requête à préparer
2780
+     * @param string $serveur Nom de la connexion
2781
+     * @return string           Requête préparée
2782
+     */
2783
+    public static function traduire_requete($query, $serveur) {
2784
+        $requeteur = spip_sqlite::requeteur($serveur);
2785
+        $traducteur = new sqlite_traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
2786
+
2787
+        return $traducteur->traduire_requete();
2788
+    }
2789
+
2790
+    /**
2791
+     * Démarre une transaction
2792
+     *
2793
+     * @param string $serveur Nom de la connexion
2794
+     **/
2795
+    public static function demarrer_transaction($serveur) {
2796
+        spip_sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
2797
+        spip_sqlite::$transaction_en_cours[$serveur] = true;
2798
+    }
2799
+
2800
+    /**
2801
+     * Exécute la requête donnée
2802
+     *
2803
+     * @param string $query Requête
2804
+     * @param string $serveur Nom de la connexion
2805
+     * @param null|bool $tracer Demander des statistiques (temps) ?
2806
+     **/
2807
+    public static function executer_requete($query, $serveur, $tracer = null) {
2808
+        $requeteur = spip_sqlite::requeteur($serveur);
2809
+
2810
+        return $requeteur->executer_requete($query, $tracer);
2811
+    }
2812
+
2813
+    /**
2814
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2815
+     *
2816
+     * @param string $serveur Nom de la connexion
2817
+     * return int                Identifiant
2818
+     **/
2819
+    public static function last_insert_id($serveur) {
2820
+        $requeteur = spip_sqlite::requeteur($serveur);
2821
+
2822
+        return $requeteur->last_insert_id($serveur);
2823
+    }
2824
+
2825
+    /**
2826
+     * Annule une transaction
2827
+     *
2828
+     * @param string $serveur Nom de la connexion
2829
+     **/
2830
+    public static function annuler_transaction($serveur) {
2831
+        spip_sqlite::executer_requete('ROLLBACK', $serveur);
2832
+        spip_sqlite::$transaction_en_cours[$serveur] = false;
2833
+    }
2834
+
2835
+    /**
2836
+     * Termine une transaction
2837
+     *
2838
+     * @param string $serveur Nom de la connexion
2839
+     **/
2840
+    public static function finir_transaction($serveur) {
2841
+        // si pas de transaction en cours, ne rien faire et le dire
2842
+        if (
2843
+            !isset(spip_sqlite::$transaction_en_cours[$serveur])
2844
+            or spip_sqlite::$transaction_en_cours[$serveur] == false
2845
+        ) {
2846
+            return false;
2847
+        }
2848
+        // sinon fermer la transaction et retourner true
2849
+        spip_sqlite::executer_requete('COMMIT', $serveur);
2850
+        spip_sqlite::$transaction_en_cours[$serveur] = false;
2851
+
2852
+        return true;
2853
+    }
2854 2854
 }
2855 2855
 
2856 2856
 /*
@@ -2863,121 +2863,121 @@  discard block
 block discarded – undo
2863 2863
  */
2864 2864
 
2865 2865
 class sqlite_requeteur {
2866
-	/** @var string Texte de la requête */
2867
-	public $query = ''; // la requete
2868
-	/** @var string Nom de la connexion */
2869
-	public $serveur = '';
2870
-	/** @var PDO Identifiant de la connexion SQLite */
2871
-	public $link = '';
2872
-	/** @var string Prefixe des tables SPIP */
2873
-	public $prefixe = '';
2874
-	/** @var string Nom de la base de donnée */
2875
-	public $db = '';
2876
-	/** @var bool Doit-on tracer les requetes (var_profile) ? */
2877
-	public $tracer = false; // doit-on tracer les requetes (var_profile)
2878
-
2879
-	/** @var string Version de SQLite (2 ou 3) */
2880
-	public $sqlite_version = '';
2881
-
2882
-	/**
2883
-	 * Constructeur
2884
-	 *
2885
-	 * @param string $serveur
2886
-	 * @return bool
2887
-	 */
2888
-	public function __construct($serveur = '') {
2889
-		_sqlite_init();
2890
-		$this->serveur = strtolower($serveur);
2891
-
2892
-		if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
2893
-			spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
2894
-
2895
-			return false;
2896
-		}
2897
-
2898
-		$this->sqlite_version = _sqlite_is_version('', $this->link);
2899
-
2900
-		$this->prefixe = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['prefixe'];
2901
-		$this->db = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['db'];
2902
-
2903
-		// tracage des requetes ?
2904
-		$this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
2905
-	}
2906
-
2907
-	/**
2908
-	 * Lancer la requête transmise et faire le tracage si demandé
2909
-	 *
2910
-	 * @param string $query
2911
-	 *     Requête à exécuter
2912
-	 * @param bool|null $tracer
2913
-	 *     true pour tracer la requête
2914
-	 * @return bool|PDOStatement|array
2915
-	 */
2916
-	public function executer_requete($query, $tracer = null) {
2917
-		if (is_null($tracer)) {
2918
-			$tracer = $this->tracer;
2919
-		}
2920
-		$err = '';
2921
-		$t = 0;
2922
-		if ($tracer or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
2923
-			include_spip('public/tracer');
2924
-			$t = trace_query_start();
2925
-		}
2926
-
2927
-		# spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
2928
-		if ($this->link) {
2929
-			// memoriser la derniere erreur PHP vue
2930
-			$last_error = (function_exists('error_get_last') ? error_get_last() : '');
2931
-			$e = null;
2932
-			// sauver la derniere requete
2933
-			$GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $query;
2934
-			$GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['total_requetes']++;
2935
-
2936
-			try {
2937
-				$r = $this->link->query($query);
2938
-			} catch (\PDOException $e) {
2939
-				spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
2940
-				$r = false;
2941
-			}
2942
-
2943
-			// comptage : oblige de compter le nombre d'entrees retournees
2944
-			// par une requete SELECT
2945
-			// aucune autre solution ne donne le nombre attendu :( !
2946
-			// particulierement s'il y a des LIMIT dans la requete.
2947
-			if ($r and strtoupper(substr(ltrim($query), 0, 6)) === 'SELECT') {
2948
-				// noter le link et la query pour faire le comptage *si* on en a besoin
2949
-				$r->spipSqliteRowCount = [$this->link, $query];
2950
-			}
2951
-
2952
-			// loger les warnings/erreurs eventuels de sqlite remontant dans PHP
2953
-			if ($e and $e instanceof \PDOException) {
2954
-				$err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
2955
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2956
-			} elseif ($err = (function_exists('error_get_last') ? error_get_last() : '') and $err != $last_error) {
2957
-				$err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
2958
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2959
-			} else {
2960
-				$err = '';
2961
-			}
2962
-		} else {
2963
-			$r = false;
2964
-		}
2965
-
2966
-		if (spip_sqlite_errno($this->serveur)) {
2967
-			$err .= spip_sqlite_error($query, $this->serveur);
2968
-		}
2969
-
2970
-		return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
2971
-	}
2972
-
2973
-	/**
2974
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2975
-	 *
2976
-	 * @return string|false
2977
-	 **/
2978
-	public function last_insert_id() {
2979
-		return $this->link->lastInsertId();
2980
-	}
2866
+    /** @var string Texte de la requête */
2867
+    public $query = ''; // la requete
2868
+    /** @var string Nom de la connexion */
2869
+    public $serveur = '';
2870
+    /** @var PDO Identifiant de la connexion SQLite */
2871
+    public $link = '';
2872
+    /** @var string Prefixe des tables SPIP */
2873
+    public $prefixe = '';
2874
+    /** @var string Nom de la base de donnée */
2875
+    public $db = '';
2876
+    /** @var bool Doit-on tracer les requetes (var_profile) ? */
2877
+    public $tracer = false; // doit-on tracer les requetes (var_profile)
2878
+
2879
+    /** @var string Version de SQLite (2 ou 3) */
2880
+    public $sqlite_version = '';
2881
+
2882
+    /**
2883
+     * Constructeur
2884
+     *
2885
+     * @param string $serveur
2886
+     * @return bool
2887
+     */
2888
+    public function __construct($serveur = '') {
2889
+        _sqlite_init();
2890
+        $this->serveur = strtolower($serveur);
2891
+
2892
+        if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
2893
+            spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
2894
+
2895
+            return false;
2896
+        }
2897
+
2898
+        $this->sqlite_version = _sqlite_is_version('', $this->link);
2899
+
2900
+        $this->prefixe = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['prefixe'];
2901
+        $this->db = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['db'];
2902
+
2903
+        // tracage des requetes ?
2904
+        $this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
2905
+    }
2906
+
2907
+    /**
2908
+     * Lancer la requête transmise et faire le tracage si demandé
2909
+     *
2910
+     * @param string $query
2911
+     *     Requête à exécuter
2912
+     * @param bool|null $tracer
2913
+     *     true pour tracer la requête
2914
+     * @return bool|PDOStatement|array
2915
+     */
2916
+    public function executer_requete($query, $tracer = null) {
2917
+        if (is_null($tracer)) {
2918
+            $tracer = $this->tracer;
2919
+        }
2920
+        $err = '';
2921
+        $t = 0;
2922
+        if ($tracer or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
2923
+            include_spip('public/tracer');
2924
+            $t = trace_query_start();
2925
+        }
2926
+
2927
+        # spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
2928
+        if ($this->link) {
2929
+            // memoriser la derniere erreur PHP vue
2930
+            $last_error = (function_exists('error_get_last') ? error_get_last() : '');
2931
+            $e = null;
2932
+            // sauver la derniere requete
2933
+            $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $query;
2934
+            $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['total_requetes']++;
2935
+
2936
+            try {
2937
+                $r = $this->link->query($query);
2938
+            } catch (\PDOException $e) {
2939
+                spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
2940
+                $r = false;
2941
+            }
2942
+
2943
+            // comptage : oblige de compter le nombre d'entrees retournees
2944
+            // par une requete SELECT
2945
+            // aucune autre solution ne donne le nombre attendu :( !
2946
+            // particulierement s'il y a des LIMIT dans la requete.
2947
+            if ($r and strtoupper(substr(ltrim($query), 0, 6)) === 'SELECT') {
2948
+                // noter le link et la query pour faire le comptage *si* on en a besoin
2949
+                $r->spipSqliteRowCount = [$this->link, $query];
2950
+            }
2951
+
2952
+            // loger les warnings/erreurs eventuels de sqlite remontant dans PHP
2953
+            if ($e and $e instanceof \PDOException) {
2954
+                $err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
2955
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2956
+            } elseif ($err = (function_exists('error_get_last') ? error_get_last() : '') and $err != $last_error) {
2957
+                $err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
2958
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2959
+            } else {
2960
+                $err = '';
2961
+            }
2962
+        } else {
2963
+            $r = false;
2964
+        }
2965
+
2966
+        if (spip_sqlite_errno($this->serveur)) {
2967
+            $err .= spip_sqlite_error($query, $this->serveur);
2968
+        }
2969
+
2970
+        return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
2971
+    }
2972
+
2973
+    /**
2974
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2975
+     *
2976
+     * @return string|false
2977
+     **/
2978
+    public function last_insert_id() {
2979
+        return $this->link->lastInsertId();
2980
+    }
2981 2981
 }
2982 2982
 
2983 2983
 
@@ -2987,206 +2987,206 @@  discard block
 block discarded – undo
2987 2987
  * (fonction pour proteger les textes)
2988 2988
  */
2989 2989
 class sqlite_traducteur {
2990
-	/** @var string $query Texte de la requête */
2991
-	public $query = '';
2992
-	/** @var string $prefixe Préfixe des tables */
2993
-	public $prefixe = '';
2994
-	/** @var string $sqlite_version Version de sqlite (2 ou 3) */
2995
-	public $sqlite_version = '';
2996
-
2997
-	/** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
2998
-	 *
2999
-	 * @var array
3000
-	 */
3001
-	public $textes = [];
3002
-
3003
-	/**
3004
-	 * Constructeur
3005
-	 *
3006
-	 * @param string $query Requête à préparer
3007
-	 * @param string $prefixe Prefixe des tables à utiliser
3008
-	 * @param string $sqlite_version Version SQLite (2 ou 3)
3009
-	 */
3010
-	public function __construct($query, $prefixe, $sqlite_version) {
3011
-		$this->query = $query;
3012
-		$this->prefixe = $prefixe;
3013
-		$this->sqlite_version = $sqlite_version;
3014
-	}
3015
-
3016
-	/**
3017
-	 * Transformer la requete pour SQLite
3018
-	 *
3019
-	 * Enlève les textes, transforme la requête pour quelle soit
3020
-	 * bien interprétée par SQLite, puis remet les textes
3021
-	 * la fonction affecte `$this->query`
3022
-	 */
3023
-	public function traduire_requete() {
3024
-		//
3025
-		// 1) Protection des textes en les remplacant par des codes
3026
-		//
3027
-		// enlever les 'textes' et initialiser avec
3028
-		list($this->query, $textes) = query_echappe_textes($this->query);
3029
-
3030
-		//
3031
-		// 2) Corrections de la requete
3032
-		//
3033
-		// Correction Create Database
3034
-		// Create Database -> requete ignoree
3035
-		if (strpos($this->query, 'CREATE DATABASE') === 0) {
3036
-			spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
3037
-			$this->query = 'SELECT 1';
3038
-		}
3039
-
3040
-		// Correction Insert Ignore
3041
-		// INSERT IGNORE -> insert (tout court et pas 'insert or replace')
3042
-		if (strpos($this->query, 'INSERT IGNORE') === 0) {
3043
-			spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
3044
-			$this->query = 'INSERT ' . substr($this->query, '13');
3045
-		}
3046
-
3047
-		// Correction des dates avec INTERVAL
3048
-		// utiliser sql_date_proche() de preference
3049
-		if (strpos($this->query, 'INTERVAL') !== false) {
3050
-			$this->query = preg_replace_callback(
3051
-				'/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
3052
-				[&$this, '_remplacerDateParTime'],
3053
-				$this->query
3054
-			);
3055
-		}
3056
-
3057
-		if (strpos($this->query, 'LEFT(') !== false) {
3058
-			$this->query = str_replace('LEFT(', '_LEFT(', $this->query);
3059
-		}
3060
-
3061
-		if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
3062
-			$this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
3063
-		}
3064
-
3065
-
3066
-		// Correction Using
3067
-		// USING (non reconnu en sqlite2)
3068
-		// problematique car la jointure ne se fait pas du coup.
3069
-		if (($this->sqlite_version == 2) && (strpos($this->query, 'USING') !== false)) {
3070
-			spip_log(
3071
-				"'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
3072
-				'sqlite.' . _LOG_ERREUR
3073
-			);
3074
-			$this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
3075
-		}
3076
-
3077
-		// Correction Field
3078
-		// remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
3079
-		if (strpos($this->query, 'FIELD') !== false) {
3080
-			$this->query = preg_replace_callback(
3081
-				'/FIELD\s*\(([^\)]*)\)/',
3082
-				[&$this, '_remplacerFieldParCase'],
3083
-				$this->query
3084
-			);
3085
-		}
3086
-
3087
-		// Correction des noms de tables FROM
3088
-		// mettre les bons noms de table dans from, update, insert, replace...
3089
-		if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
3090
-			$suite = strstr($this->query, $regs[0]);
3091
-			$this->query = substr($this->query, 0, -strlen($suite));
3092
-		} else {
3093
-			$suite = '';
3094
-		}
3095
-		$pref = ($this->prefixe) ? $this->prefixe . '_' : '';
3096
-		$this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
3097
-
3098
-		// Correction zero AS x
3099
-		// pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
3100
-		// n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
3101
-		// il dit que x ne doit pas être un integer dans le order by !
3102
-		// on remplace du coup x par vide() dans ce cas uniquement
3103
-		//
3104
-		// apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
3105
-		// mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
3106
-		if ((strpos($this->query, '0 AS') !== false)) {
3107
-			// on ne remplace que dans ORDER BY ou GROUP BY
3108
-			if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
3109
-				$suite = strstr($this->query, $regs[0]);
3110
-				$this->query = substr($this->query, 0, -strlen($suite));
3111
-
3112
-				// on cherche les noms des x dans 0 AS x
3113
-				// on remplace dans $suite le nom par vide()
3114
-				preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
3115
-				foreach ($matches[1] as $m) {
3116
-					if (strpos($suite, $m) !== false) {
3117
-						$suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
3118
-					}
3119
-				}
3120
-				$this->query .= $suite;
3121
-			}
3122
-		}
3123
-
3124
-		// Correction possible des divisions entieres
3125
-		// Le standard SQL (lequel? ou?) semble indiquer que
3126
-		// a/b=c doit donner c entier si a et b sont entiers 4/3=1.
3127
-		// C'est ce que retournent effectivement SQL Server et SQLite
3128
-		// Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
3129
-		//
3130
-		// On peut forcer la conversion en multipliant par 1.0 avant la division
3131
-		// /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
3132
-		// cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
3133
-		//     http://www.sqlite.org/cvstrac/tktview?tn=3202
3134
-		// (4*1.0/3) n'est pas rendu dans ce cas !
3135
-		# $this->query = str_replace('/','* 1.00 / ',$this->query);
3136
-
3137
-
3138
-		// Correction critere REGEXP, non reconnu en sqlite2
3139
-		if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP') !== false)) {
3140
-			$this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
3141
-		}
3142
-
3143
-		//
3144
-		// 3) Remise en place des textes d'origine
3145
-		//
3146
-		// Correction Antiquotes et echappements
3147
-		// ` => rien
3148
-		if (strpos($this->query, '`') !== false) {
3149
-			$this->query = str_replace('`', '', $this->query);
3150
-		}
3151
-
3152
-		$this->query = query_reinjecte_textes($this->query, $textes);
3153
-
3154
-		return $this->query;
3155
-	}
3156
-
3157
-
3158
-	/**
3159
-	 * Callback pour remplacer `DATE_` / `INTERVAL`
3160
-	 * par `DATE ... strtotime`
3161
-	 *
3162
-	 * @param array $matches Captures
3163
-	 * @return string Texte de date compris par SQLite
3164
-	 */
3165
-	public function _remplacerDateParTime($matches) {
3166
-		$op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
3167
-
3168
-		return "datetime$matches[2] '$op$matches[3] $matches[4]')";
3169
-	}
3170
-
3171
-	/**
3172
-	 * Callback pour remplacer `FIELD(table,i,j,k...)`
3173
-	 * par `CASE WHEN table=i THEN n ... ELSE 0 END`
3174
-	 *
3175
-	 * @param array $matches Captures
3176
-	 * @return string Texte de liste ordonnée compris par SQLite
3177
-	 */
3178
-	public function _remplacerFieldParCase($matches) {
3179
-		$fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
3180
-		$t = explode(',', $fields);
3181
-		$index = array_shift($t);
3182
-
3183
-		$res = '';
3184
-		$n = 0;
3185
-		foreach ($t as $v) {
3186
-			$n++;
3187
-			$res .= "\nWHEN $index=$v THEN $n";
3188
-		}
3189
-
3190
-		return "CASE $res ELSE 0 END ";
3191
-	}
2990
+    /** @var string $query Texte de la requête */
2991
+    public $query = '';
2992
+    /** @var string $prefixe Préfixe des tables */
2993
+    public $prefixe = '';
2994
+    /** @var string $sqlite_version Version de sqlite (2 ou 3) */
2995
+    public $sqlite_version = '';
2996
+
2997
+    /** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
2998
+     *
2999
+     * @var array
3000
+     */
3001
+    public $textes = [];
3002
+
3003
+    /**
3004
+     * Constructeur
3005
+     *
3006
+     * @param string $query Requête à préparer
3007
+     * @param string $prefixe Prefixe des tables à utiliser
3008
+     * @param string $sqlite_version Version SQLite (2 ou 3)
3009
+     */
3010
+    public function __construct($query, $prefixe, $sqlite_version) {
3011
+        $this->query = $query;
3012
+        $this->prefixe = $prefixe;
3013
+        $this->sqlite_version = $sqlite_version;
3014
+    }
3015
+
3016
+    /**
3017
+     * Transformer la requete pour SQLite
3018
+     *
3019
+     * Enlève les textes, transforme la requête pour quelle soit
3020
+     * bien interprétée par SQLite, puis remet les textes
3021
+     * la fonction affecte `$this->query`
3022
+     */
3023
+    public function traduire_requete() {
3024
+        //
3025
+        // 1) Protection des textes en les remplacant par des codes
3026
+        //
3027
+        // enlever les 'textes' et initialiser avec
3028
+        list($this->query, $textes) = query_echappe_textes($this->query);
3029
+
3030
+        //
3031
+        // 2) Corrections de la requete
3032
+        //
3033
+        // Correction Create Database
3034
+        // Create Database -> requete ignoree
3035
+        if (strpos($this->query, 'CREATE DATABASE') === 0) {
3036
+            spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
3037
+            $this->query = 'SELECT 1';
3038
+        }
3039
+
3040
+        // Correction Insert Ignore
3041
+        // INSERT IGNORE -> insert (tout court et pas 'insert or replace')
3042
+        if (strpos($this->query, 'INSERT IGNORE') === 0) {
3043
+            spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
3044
+            $this->query = 'INSERT ' . substr($this->query, '13');
3045
+        }
3046
+
3047
+        // Correction des dates avec INTERVAL
3048
+        // utiliser sql_date_proche() de preference
3049
+        if (strpos($this->query, 'INTERVAL') !== false) {
3050
+            $this->query = preg_replace_callback(
3051
+                '/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
3052
+                [&$this, '_remplacerDateParTime'],
3053
+                $this->query
3054
+            );
3055
+        }
3056
+
3057
+        if (strpos($this->query, 'LEFT(') !== false) {
3058
+            $this->query = str_replace('LEFT(', '_LEFT(', $this->query);
3059
+        }
3060
+
3061
+        if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
3062
+            $this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
3063
+        }
3064
+
3065
+
3066
+        // Correction Using
3067
+        // USING (non reconnu en sqlite2)
3068
+        // problematique car la jointure ne se fait pas du coup.
3069
+        if (($this->sqlite_version == 2) && (strpos($this->query, 'USING') !== false)) {
3070
+            spip_log(
3071
+                "'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
3072
+                'sqlite.' . _LOG_ERREUR
3073
+            );
3074
+            $this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
3075
+        }
3076
+
3077
+        // Correction Field
3078
+        // remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
3079
+        if (strpos($this->query, 'FIELD') !== false) {
3080
+            $this->query = preg_replace_callback(
3081
+                '/FIELD\s*\(([^\)]*)\)/',
3082
+                [&$this, '_remplacerFieldParCase'],
3083
+                $this->query
3084
+            );
3085
+        }
3086
+
3087
+        // Correction des noms de tables FROM
3088
+        // mettre les bons noms de table dans from, update, insert, replace...
3089
+        if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
3090
+            $suite = strstr($this->query, $regs[0]);
3091
+            $this->query = substr($this->query, 0, -strlen($suite));
3092
+        } else {
3093
+            $suite = '';
3094
+        }
3095
+        $pref = ($this->prefixe) ? $this->prefixe . '_' : '';
3096
+        $this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
3097
+
3098
+        // Correction zero AS x
3099
+        // pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
3100
+        // n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
3101
+        // il dit que x ne doit pas être un integer dans le order by !
3102
+        // on remplace du coup x par vide() dans ce cas uniquement
3103
+        //
3104
+        // apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
3105
+        // mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
3106
+        if ((strpos($this->query, '0 AS') !== false)) {
3107
+            // on ne remplace que dans ORDER BY ou GROUP BY
3108
+            if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
3109
+                $suite = strstr($this->query, $regs[0]);
3110
+                $this->query = substr($this->query, 0, -strlen($suite));
3111
+
3112
+                // on cherche les noms des x dans 0 AS x
3113
+                // on remplace dans $suite le nom par vide()
3114
+                preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
3115
+                foreach ($matches[1] as $m) {
3116
+                    if (strpos($suite, $m) !== false) {
3117
+                        $suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
3118
+                    }
3119
+                }
3120
+                $this->query .= $suite;
3121
+            }
3122
+        }
3123
+
3124
+        // Correction possible des divisions entieres
3125
+        // Le standard SQL (lequel? ou?) semble indiquer que
3126
+        // a/b=c doit donner c entier si a et b sont entiers 4/3=1.
3127
+        // C'est ce que retournent effectivement SQL Server et SQLite
3128
+        // Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
3129
+        //
3130
+        // On peut forcer la conversion en multipliant par 1.0 avant la division
3131
+        // /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
3132
+        // cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
3133
+        //     http://www.sqlite.org/cvstrac/tktview?tn=3202
3134
+        // (4*1.0/3) n'est pas rendu dans ce cas !
3135
+        # $this->query = str_replace('/','* 1.00 / ',$this->query);
3136
+
3137
+
3138
+        // Correction critere REGEXP, non reconnu en sqlite2
3139
+        if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP') !== false)) {
3140
+            $this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
3141
+        }
3142
+
3143
+        //
3144
+        // 3) Remise en place des textes d'origine
3145
+        //
3146
+        // Correction Antiquotes et echappements
3147
+        // ` => rien
3148
+        if (strpos($this->query, '`') !== false) {
3149
+            $this->query = str_replace('`', '', $this->query);
3150
+        }
3151
+
3152
+        $this->query = query_reinjecte_textes($this->query, $textes);
3153
+
3154
+        return $this->query;
3155
+    }
3156
+
3157
+
3158
+    /**
3159
+     * Callback pour remplacer `DATE_` / `INTERVAL`
3160
+     * par `DATE ... strtotime`
3161
+     *
3162
+     * @param array $matches Captures
3163
+     * @return string Texte de date compris par SQLite
3164
+     */
3165
+    public function _remplacerDateParTime($matches) {
3166
+        $op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
3167
+
3168
+        return "datetime$matches[2] '$op$matches[3] $matches[4]')";
3169
+    }
3170
+
3171
+    /**
3172
+     * Callback pour remplacer `FIELD(table,i,j,k...)`
3173
+     * par `CASE WHEN table=i THEN n ... ELSE 0 END`
3174
+     *
3175
+     * @param array $matches Captures
3176
+     * @return string Texte de liste ordonnée compris par SQLite
3177
+     */
3178
+    public function _remplacerFieldParCase($matches) {
3179
+        $fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
3180
+        $t = explode(',', $fields);
3181
+        $index = array_shift($t);
3182
+
3183
+        $res = '';
3184
+        $n = 0;
3185
+        foreach ($t as $v) {
3186
+            $n++;
3187
+            $res .= "\nWHEN $index=$v THEN $n";
3188
+        }
3189
+
3190
+        return "CASE $res ELSE 0 END ";
3191
+    }
3192 3192
 }
Please login to merge, or discard this patch.
ecrire/balise/formulaire_.php 1 patch
Indentation   +251 added lines, -251 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,22 +35,22 @@  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
-		return array_map('protege_champ', $texte);
40
-	} elseif ($texte === null) {
41
-		return $texte;
42
-	} elseif (is_bool($texte)) {
43
-		return $texte ? '1' : '';
44
-	} elseif (is_string($texte) and $texte) {
45
-		if (preg_match(',^[abis]:\d+[:;],', $texte) and @unserialize($texte) !== false) {
46
-			// ne pas corrompre une valeur serialize
47
-			return $texte;
48
-		} elseif (strpbrk($texte, "&\"'<>") !== false) {
49
-			return spip_htmlspecialchars($texte, ENT_QUOTES);
50
-		}
51
-	}
52
-
53
-	return $texte;
38
+    if (is_array($texte)) {
39
+        return array_map('protege_champ', $texte);
40
+    } elseif ($texte === null) {
41
+        return $texte;
42
+    } elseif (is_bool($texte)) {
43
+        return $texte ? '1' : '';
44
+    } elseif (is_string($texte) and $texte) {
45
+        if (preg_match(',^[abis]:\d+[:;],', $texte) and @unserialize($texte) !== false) {
46
+            // ne pas corrompre une valeur serialize
47
+            return $texte;
48
+        } elseif (strpbrk($texte, "&\"'<>") !== false) {
49
+            return spip_htmlspecialchars($texte, ENT_QUOTES);
50
+        }
51
+    }
52
+
53
+    return $texte;
54 54
 }
55 55
 
56 56
 /**
@@ -64,17 +64,17 @@  discard block
 block discarded – undo
64 64
  *     - false : pas de squelette trouvé
65 65
  **/
66 66
 function existe_formulaire($form) {
67
-	if (substr($form, 0, 11) == 'FORMULAIRE_') {
68
-		$form = strtolower(substr($form, 11));
69
-	} else {
70
-		$form = strtolower($form);
71
-	}
67
+    if (substr($form, 0, 11) == 'FORMULAIRE_') {
68
+        $form = strtolower(substr($form, 11));
69
+    } else {
70
+        $form = strtolower($form);
71
+    }
72 72
 
73
-	if (!$form) {
74
-		return '';
75
-	} // on ne sait pas, le nom du formulaire n'est pas fourni ici
73
+    if (!$form) {
74
+        return '';
75
+    } // on ne sait pas, le nom du formulaire n'est pas fourni ici
76 76
 
77
-	return trouver_fond($form, 'formulaires/') ? $form : false;
77
+    return trouver_fond($form, 'formulaires/') ? $form : false;
78 78
 }
79 79
 
80 80
 /**
@@ -83,31 +83,31 @@  discard block
 block discarded – undo
83 83
  * @return false|array
84 84
  */
85 85
 function test_formulaire_inclus_par_modele() {
86
-	$trace = debug_backtrace(0, 20);
87
-	$trace_fonctions = array_column($trace, 'function');
88
-	$trace_fonctions = array_map('strtolower', $trace_fonctions);
89
-
90
-	// regarder si un flag a ete leve juste avant l'appel de balise_FORMULAIRE_dyn
91
-	if (
92
-		function_exists('arguments_balise_dyn_depuis_modele')
93
-		and $form = arguments_balise_dyn_depuis_modele(null, 'read')
94
-	) {
95
-		if (in_array('balise_formulaire__dyn', $trace_fonctions)) {
96
-			$k = array_search('balise_formulaire__dyn', $trace_fonctions);
97
-			if ($trace[$k]['args'][0] === $form) {
98
-				return $trace[$k]['args'];
99
-			}
100
-		}
101
-	}
102
-
103
-	// fallback qui ne repose pas sur le flag lie a l'analyse de contexte_compil,
104
-	// mais ne marche pas si executer_balise_dynamique est appelee via du php dans le squelette
105
-	if (in_array('eval', $trace_fonctions) and in_array('inclure_modele', $trace_fonctions)) {
106
-		$k = array_search('inclure_modele', $trace_fonctions);
107
-		// les arguments de recuperer_fond() passes par inclure_modele()
108
-		return $trace[$k - 1]['args'][1]['args'];
109
-	}
110
-	return false;
86
+    $trace = debug_backtrace(0, 20);
87
+    $trace_fonctions = array_column($trace, 'function');
88
+    $trace_fonctions = array_map('strtolower', $trace_fonctions);
89
+
90
+    // regarder si un flag a ete leve juste avant l'appel de balise_FORMULAIRE_dyn
91
+    if (
92
+        function_exists('arguments_balise_dyn_depuis_modele')
93
+        and $form = arguments_balise_dyn_depuis_modele(null, 'read')
94
+    ) {
95
+        if (in_array('balise_formulaire__dyn', $trace_fonctions)) {
96
+            $k = array_search('balise_formulaire__dyn', $trace_fonctions);
97
+            if ($trace[$k]['args'][0] === $form) {
98
+                return $trace[$k]['args'];
99
+            }
100
+        }
101
+    }
102
+
103
+    // fallback qui ne repose pas sur le flag lie a l'analyse de contexte_compil,
104
+    // mais ne marche pas si executer_balise_dynamique est appelee via du php dans le squelette
105
+    if (in_array('eval', $trace_fonctions) and in_array('inclure_modele', $trace_fonctions)) {
106
+        $k = array_search('inclure_modele', $trace_fonctions);
107
+        // les arguments de recuperer_fond() passes par inclure_modele()
108
+        return $trace[$k - 1]['args'][1]['args'];
109
+    }
110
+    return false;
111 111
 }
112 112
 
113 113
 /**
@@ -122,19 +122,19 @@  discard block
 block discarded – undo
122 122
  **/
123 123
 function balise_FORMULAIRE__dist($p) {
124 124
 
125
-	// Cas d'un #FORMULAIRE_TOTO inexistant : renvoyer la chaine vide.
126
-	// mais si #FORMULAIRE_{toto} on ne peut pas savoir a la compilation, continuer
127
-	if (existe_formulaire($p->nom_champ) === false) {
128
-		$p->code = "''";
129
-		$p->interdire_scripts = false;
125
+    // Cas d'un #FORMULAIRE_TOTO inexistant : renvoyer la chaine vide.
126
+    // mais si #FORMULAIRE_{toto} on ne peut pas savoir a la compilation, continuer
127
+    if (existe_formulaire($p->nom_champ) === false) {
128
+        $p->code = "''";
129
+        $p->interdire_scripts = false;
130 130
 
131
-		return $p;
132
-	}
131
+        return $p;
132
+    }
133 133
 
134
-	// sinon renvoyer un code php dynamique
135
-	$p = calculer_balise_dynamique($p, $p->nom_champ, []);
134
+    // sinon renvoyer un code php dynamique
135
+    $p = calculer_balise_dynamique($p, $p->nom_champ, []);
136 136
 
137
-	return $p;
137
+    return $p;
138 138
 }
139 139
 
140 140
 /**
@@ -154,17 +154,17 @@  discard block
 block discarded – undo
154 154
  *     - string : texte à afficher directement
155 155
  */
156 156
 function balise_FORMULAIRE__dyn($form, ...$args) {
157
-	$form = existe_formulaire($form);
158
-	if (!$form) {
159
-		return '';
160
-	}
157
+    $form = existe_formulaire($form);
158
+    if (!$form) {
159
+        return '';
160
+    }
161 161
 
162
-	$contexte = balise_FORMULAIRE__contexte($form, $args);
163
-	if (!is_array($contexte)) {
164
-		return $contexte;
165
-	}
162
+    $contexte = balise_FORMULAIRE__contexte($form, $args);
163
+    if (!is_array($contexte)) {
164
+        return $contexte;
165
+    }
166 166
 
167
-	return ["formulaires/$form", 3600, $contexte];
167
+    return ["formulaires/$form", 3600, $contexte];
168 168
 }
169 169
 
170 170
 /**
@@ -179,85 +179,85 @@  discard block
 block discarded – undo
179 179
  *     string: Formulaire non applicable (message d’explication)
180 180
  **/
181 181
 function balise_FORMULAIRE__contexte($form, $args) {
182
-	// tester si ce formulaire vient d'etre poste (memes arguments)
183
-	// pour ne pas confondre 2 #FORMULAIRES_XX identiques sur une meme page
184
-	// si poste, on recupere les erreurs
185
-
186
-	$je_suis_poste = false;
187
-	if (
188
-		$post_form = _request('formulaire_action')
189
-		and $post_form == $form
190
-		and $p = _request('formulaire_action_args')
191
-		and is_array($p = decoder_contexte_ajax($p, $post_form))
192
-	) {
193
-		// enlever le faux attribut de langue masque
194
-		array_shift($p);
195
-		if (formulaire__identifier($form, $args, $p)) {
196
-			$je_suis_poste = true;
197
-		}
198
-	}
199
-
200
-	$editable = true;
201
-	$erreurs = $post = [];
202
-	if ($je_suis_poste) {
203
-		$post = traiter_formulaires_dynamiques(true);
204
-		$e = "erreurs_$form";
205
-		$erreurs = $post[$e] ?? [];
206
-		$editable = "editable_$form";
207
-		$editable = (!isset($post[$e]))
208
-			|| (is_countable($erreurs) ? count($erreurs) : 0)
209
-			|| (isset($post[$editable]) && $post[$editable]);
210
-	}
211
-
212
-	$valeurs = formulaire__charger($form, $args, $je_suis_poste);
213
-
214
-	// si $valeurs n'est pas un tableau, le formulaire n'est pas applicable
215
-	// C'est plus fort qu'editable qui est gere par le squelette
216
-	// Idealement $valeur doit etre alors un message explicatif.
217
-	if (!is_array($valeurs)) {
218
-		return is_string($valeurs) ? $valeurs : '';
219
-	}
220
-
221
-	// charger peut passer une action si le formulaire ne tourne pas sur self()
222
-	// ou une action vide si elle ne sert pas
223
-	$action = $valeurs['action'] ?? self('&amp;', true);
224
-	// bug IEx : si action finit par /
225
-	// IE croit que le <form ... action=../ > est autoferme
226
-	if (substr($action, -1) == '/') {
227
-		// on ajoute une ancre pour feinter IE, au pire ca tue l'ancre qui finit par un /
228
-		$action .= '#';
229
-	}
230
-
231
-	// recuperer la saisie en cours si erreurs
232
-	// seulement si c'est ce formulaire qui est poste
233
-	// ou si on le demande explicitement par le parametre _forcer_request = true
234
-	$dispo = ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request']));
235
-	foreach (array_keys($valeurs) as $champ) {
236
-		if ($champ[0] !== '_' and !in_array($champ, ['message_ok', 'message_erreur', 'editable'])) {
237
-			if ($dispo and (($v = _request($champ)) !== null)) {
238
-				$valeurs[$champ] = $v;
239
-			}
240
-			// nettoyer l'url des champs qui vont etre saisis
241
-			if ($action) {
242
-				$action = parametre_url($action, $champ, '');
243
-			}
244
-			// proteger les ' et les " dans les champs que l'on va injecter
245
-			$valeurs[$champ] = protege_champ($valeurs[$champ]);
246
-		}
247
-	}
248
-
249
-	if ($action) {
250
-		// nettoyer l'url
251
-		$action = parametre_url($action, 'formulaire_action', '');
252
-		$action = parametre_url($action, 'formulaire_action_args', '');
253
-		$action = parametre_url($action, 'formulaire_action_sign', '');
254
-	}
255
-
256
-	/**
257
-	 * @deprecated 4.0
258
-	 * 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
259
-	 */
260
-	/*
182
+    // tester si ce formulaire vient d'etre poste (memes arguments)
183
+    // pour ne pas confondre 2 #FORMULAIRES_XX identiques sur une meme page
184
+    // si poste, on recupere les erreurs
185
+
186
+    $je_suis_poste = false;
187
+    if (
188
+        $post_form = _request('formulaire_action')
189
+        and $post_form == $form
190
+        and $p = _request('formulaire_action_args')
191
+        and is_array($p = decoder_contexte_ajax($p, $post_form))
192
+    ) {
193
+        // enlever le faux attribut de langue masque
194
+        array_shift($p);
195
+        if (formulaire__identifier($form, $args, $p)) {
196
+            $je_suis_poste = true;
197
+        }
198
+    }
199
+
200
+    $editable = true;
201
+    $erreurs = $post = [];
202
+    if ($je_suis_poste) {
203
+        $post = traiter_formulaires_dynamiques(true);
204
+        $e = "erreurs_$form";
205
+        $erreurs = $post[$e] ?? [];
206
+        $editable = "editable_$form";
207
+        $editable = (!isset($post[$e]))
208
+            || (is_countable($erreurs) ? count($erreurs) : 0)
209
+            || (isset($post[$editable]) && $post[$editable]);
210
+    }
211
+
212
+    $valeurs = formulaire__charger($form, $args, $je_suis_poste);
213
+
214
+    // si $valeurs n'est pas un tableau, le formulaire n'est pas applicable
215
+    // C'est plus fort qu'editable qui est gere par le squelette
216
+    // Idealement $valeur doit etre alors un message explicatif.
217
+    if (!is_array($valeurs)) {
218
+        return is_string($valeurs) ? $valeurs : '';
219
+    }
220
+
221
+    // charger peut passer une action si le formulaire ne tourne pas sur self()
222
+    // ou une action vide si elle ne sert pas
223
+    $action = $valeurs['action'] ?? self('&amp;', true);
224
+    // bug IEx : si action finit par /
225
+    // IE croit que le <form ... action=../ > est autoferme
226
+    if (substr($action, -1) == '/') {
227
+        // on ajoute une ancre pour feinter IE, au pire ca tue l'ancre qui finit par un /
228
+        $action .= '#';
229
+    }
230
+
231
+    // recuperer la saisie en cours si erreurs
232
+    // seulement si c'est ce formulaire qui est poste
233
+    // ou si on le demande explicitement par le parametre _forcer_request = true
234
+    $dispo = ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request']));
235
+    foreach (array_keys($valeurs) as $champ) {
236
+        if ($champ[0] !== '_' and !in_array($champ, ['message_ok', 'message_erreur', 'editable'])) {
237
+            if ($dispo and (($v = _request($champ)) !== null)) {
238
+                $valeurs[$champ] = $v;
239
+            }
240
+            // nettoyer l'url des champs qui vont etre saisis
241
+            if ($action) {
242
+                $action = parametre_url($action, $champ, '');
243
+            }
244
+            // proteger les ' et les " dans les champs que l'on va injecter
245
+            $valeurs[$champ] = protege_champ($valeurs[$champ]);
246
+        }
247
+    }
248
+
249
+    if ($action) {
250
+        // nettoyer l'url
251
+        $action = parametre_url($action, 'formulaire_action', '');
252
+        $action = parametre_url($action, 'formulaire_action_args', '');
253
+        $action = parametre_url($action, 'formulaire_action_sign', '');
254
+    }
255
+
256
+    /**
257
+     * @deprecated 4.0
258
+     * 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
259
+     */
260
+    /*
261 261
 	if (isset($valeurs['_action'])) {
262 262
 		$securiser_action = charger_fonction('securiser_action', 'inc');
263 263
 		$secu = $securiser_action(reset($valeurs['_action']), end($valeurs['_action']), '', -1);
@@ -267,59 +267,59 @@  discard block
 block discarded – undo
267 267
 	}
268 268
 	*/
269 269
 
270
-	// empiler la lang en tant que premier argument implicite du CVT
271
-	// pour permettre de la restaurer au moment du Verifier et du Traiter
272
-	array_unshift($args, $GLOBALS['spip_lang']);
273
-
274
-	$valeurs['formulaire_args'] = encoder_contexte_ajax($args, $form);
275
-	$valeurs['erreurs'] = $erreurs;
276
-	$valeurs['action'] = $action;
277
-	$valeurs['form'] = $form;
278
-
279
-	$valeurs['formulaire_sign'] = '';
280
-	if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
281
-		$securiser_action = charger_fonction('securiser_action', 'inc');
282
-		$secu = $securiser_action($valeurs['form'], $valeurs['formulaire_args'], '', -1);
283
-		$valeurs['formulaire_sign'] = $secu['hash'];
284
-	}
285
-
286
-	if (!isset($valeurs['id'])) {
287
-		$valeurs['id'] = 'new';
288
-	}
289
-	// editable peut venir de charger() ou de traiter() sinon
290
-	if (!isset($valeurs['editable'])) {
291
-		$valeurs['editable'] = $editable;
292
-	}
293
-	// dans tous les cas, renvoyer un espace ou vide (et pas un booleen)
294
-	$valeurs['editable'] = ($valeurs['editable'] ? ' ' : '');
295
-
296
-	if ($je_suis_poste) {
297
-		$valeurs['message_erreur'] = '';
298
-		if (isset($erreurs['message_erreur'])) {
299
-			$valeurs['message_erreur'] = $erreurs['message_erreur'];
300
-		}
301
-
302
-		$valeurs['message_ok'] = '';
303
-		if (isset($post["message_ok_$form"])) {
304
-			$valeurs['message_ok'] = $post["message_ok_$form"];
305
-		} elseif (isset($erreurs['message_ok'])) {
306
-			$valeurs['message_ok'] = $erreurs['message_ok'];
307
-		}
308
-
309
-		// accessibilite : encapsuler toutes les erreurs dans un role='alert'
310
-		// uniquement si c'est une string et au premier niveau (on ne touche pas au tableaux)
311
-		// et si $k ne commence pas par un _ (c'est bien une vrai erreur sur un vrai champ)
312
-		if (html5_permis()) {
313
-			foreach ($erreurs as $k => $v) {
314
-				if (is_string($v) and strlen(trim($v)) and strpos($k, '_') !== 0) {
315
-					// on encapsule dans un span car ces messages sont en general simple, juste du texte, et deja dans un span dans le form
316
-					$valeurs['erreurs'][$k] = "<span role='alert'>" . $erreurs[$k] . '</span>';
317
-				}
318
-			}
319
-		}
320
-	}
321
-
322
-	return $valeurs;
270
+    // empiler la lang en tant que premier argument implicite du CVT
271
+    // pour permettre de la restaurer au moment du Verifier et du Traiter
272
+    array_unshift($args, $GLOBALS['spip_lang']);
273
+
274
+    $valeurs['formulaire_args'] = encoder_contexte_ajax($args, $form);
275
+    $valeurs['erreurs'] = $erreurs;
276
+    $valeurs['action'] = $action;
277
+    $valeurs['form'] = $form;
278
+
279
+    $valeurs['formulaire_sign'] = '';
280
+    if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
281
+        $securiser_action = charger_fonction('securiser_action', 'inc');
282
+        $secu = $securiser_action($valeurs['form'], $valeurs['formulaire_args'], '', -1);
283
+        $valeurs['formulaire_sign'] = $secu['hash'];
284
+    }
285
+
286
+    if (!isset($valeurs['id'])) {
287
+        $valeurs['id'] = 'new';
288
+    }
289
+    // editable peut venir de charger() ou de traiter() sinon
290
+    if (!isset($valeurs['editable'])) {
291
+        $valeurs['editable'] = $editable;
292
+    }
293
+    // dans tous les cas, renvoyer un espace ou vide (et pas un booleen)
294
+    $valeurs['editable'] = ($valeurs['editable'] ? ' ' : '');
295
+
296
+    if ($je_suis_poste) {
297
+        $valeurs['message_erreur'] = '';
298
+        if (isset($erreurs['message_erreur'])) {
299
+            $valeurs['message_erreur'] = $erreurs['message_erreur'];
300
+        }
301
+
302
+        $valeurs['message_ok'] = '';
303
+        if (isset($post["message_ok_$form"])) {
304
+            $valeurs['message_ok'] = $post["message_ok_$form"];
305
+        } elseif (isset($erreurs['message_ok'])) {
306
+            $valeurs['message_ok'] = $erreurs['message_ok'];
307
+        }
308
+
309
+        // accessibilite : encapsuler toutes les erreurs dans un role='alert'
310
+        // uniquement si c'est une string et au premier niveau (on ne touche pas au tableaux)
311
+        // et si $k ne commence pas par un _ (c'est bien une vrai erreur sur un vrai champ)
312
+        if (html5_permis()) {
313
+            foreach ($erreurs as $k => $v) {
314
+                if (is_string($v) and strlen(trim($v)) and strpos($k, '_') !== 0) {
315
+                    // on encapsule dans un span car ces messages sont en general simple, juste du texte, et deja dans un span dans le form
316
+                    $valeurs['erreurs'][$k] = "<span role='alert'>" . $erreurs[$k] . '</span>';
317
+                }
318
+            }
319
+        }
320
+    }
321
+
322
+    return $valeurs;
323 323
 }
324 324
 
325 325
 /**
@@ -331,51 +331,51 @@  discard block
 block discarded – undo
331 331
  * @return array
332 332
  */
333 333
 function formulaire__charger($form, $args, $poste) {
334
-	if ($charger_valeurs = charger_fonction('charger', "formulaires/$form", true)) {
335
-		$valeurs = $charger_valeurs(...$args);
336
-	} else {
337
-		$valeurs = [];
338
-	}
339
-
340
-	$valeurs = pipeline(
341
-		'formulaire_charger',
342
-		[
343
-			'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
344
-			'data' => $valeurs
345
-		]
346
-	);
347
-
348
-	// prise en charge CVT multi etape
349
-	if (is_array($valeurs) and isset($valeurs['_etapes'])) {
350
-		include_spip('inc/cvt_multietapes');
351
-		$valeurs = cvtmulti_formulaire_charger_etapes(
352
-			['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
353
-			$valeurs
354
-		);
355
-	}
356
-
357
-	// si $valeurs et false ou une chaine, pas de formulaire, donc pas de pipeline !
358
-	if (is_array($valeurs)) {
359
-		if (!isset($valeurs['_pipelines'])) {
360
-			$valeurs['_pipelines'] = [];
361
-		}
362
-		// l'ancien argument _pipeline devient maintenant _pipelines
363
-		// reinjectons le vieux _pipeline au debut de _pipelines
364
-		if (isset($valeurs['_pipeline'])) {
365
-			$pipe = is_array($valeurs['_pipeline']) ? reset($valeurs['_pipeline']) : $valeurs['_pipeline'];
366
-			$args = is_array($valeurs['_pipeline']) ? end($valeurs['_pipeline']) : [];
367
-
368
-			$pipelines = [$pipe => $args];
369
-			$valeurs['_pipelines'] = array_merge($pipelines, $valeurs['_pipelines']);
370
-		}
371
-
372
-		// et enfin, ajoutons systematiquement un pipeline sur le squelette du formulaire
373
-		// qui constitue le cas le plus courant d'utilisation du pipeline recuperer_fond
374
-		// (performance, cela evite de s'injecter dans recuperer_fond utilise pour *tous* les squelettes)
375
-		$valeurs['_pipelines']['formulaire_fond'] = ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste];
376
-	}
377
-
378
-	return $valeurs;
334
+    if ($charger_valeurs = charger_fonction('charger', "formulaires/$form", true)) {
335
+        $valeurs = $charger_valeurs(...$args);
336
+    } else {
337
+        $valeurs = [];
338
+    }
339
+
340
+    $valeurs = pipeline(
341
+        'formulaire_charger',
342
+        [
343
+            'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
344
+            'data' => $valeurs
345
+        ]
346
+    );
347
+
348
+    // prise en charge CVT multi etape
349
+    if (is_array($valeurs) and isset($valeurs['_etapes'])) {
350
+        include_spip('inc/cvt_multietapes');
351
+        $valeurs = cvtmulti_formulaire_charger_etapes(
352
+            ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste],
353
+            $valeurs
354
+        );
355
+    }
356
+
357
+    // si $valeurs et false ou une chaine, pas de formulaire, donc pas de pipeline !
358
+    if (is_array($valeurs)) {
359
+        if (!isset($valeurs['_pipelines'])) {
360
+            $valeurs['_pipelines'] = [];
361
+        }
362
+        // l'ancien argument _pipeline devient maintenant _pipelines
363
+        // reinjectons le vieux _pipeline au debut de _pipelines
364
+        if (isset($valeurs['_pipeline'])) {
365
+            $pipe = is_array($valeurs['_pipeline']) ? reset($valeurs['_pipeline']) : $valeurs['_pipeline'];
366
+            $args = is_array($valeurs['_pipeline']) ? end($valeurs['_pipeline']) : [];
367
+
368
+            $pipelines = [$pipe => $args];
369
+            $valeurs['_pipelines'] = array_merge($pipelines, $valeurs['_pipelines']);
370
+        }
371
+
372
+        // et enfin, ajoutons systematiquement un pipeline sur le squelette du formulaire
373
+        // qui constitue le cas le plus courant d'utilisation du pipeline recuperer_fond
374
+        // (performance, cela evite de s'injecter dans recuperer_fond utilise pour *tous* les squelettes)
375
+        $valeurs['_pipelines']['formulaire_fond'] = ['form' => $form, 'args' => $args, 'je_suis_poste' => $poste];
376
+    }
377
+
378
+    return $valeurs;
379 379
 }
380 380
 
381 381
 /**
@@ -394,9 +394,9 @@  discard block
 block discarded – undo
394 394
  * @return bool
395 395
  */
396 396
 function formulaire__identifier($form, $args, $p) {
397
-	if ($identifier_args = charger_fonction('identifier', "formulaires/$form", true)) {
398
-		return $identifier_args(...$args) === $identifier_args(...$p);
399
-	}
397
+    if ($identifier_args = charger_fonction('identifier', "formulaires/$form", true)) {
398
+        return $identifier_args(...$args) === $identifier_args(...$p);
399
+    }
400 400
 
401
-	return $args === $p;
401
+    return $args === $p;
402 402
 }
Please login to merge, or discard this patch.
ecrire/public/references.php 1 patch
Indentation   +561 added lines, -561 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Compilateur\References
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 /**
@@ -41,14 +41,14 @@  discard block
 block discarded – undo
41 41
  *     - '' si une référence explicite incorrecte est envoyée
42 42
  */
43 43
 function index_boucle($p) {
44
-	if (strlen($p->nom_boucle)) {
45
-		// retourne l’index explicite demandé s’il existe
46
-		if (!empty($p->boucles[$p->nom_boucle])) {
47
-			return $p->nom_boucle;
48
-		}
49
-		return '';
50
-	}
51
-	return $p->id_boucle;
44
+    if (strlen($p->nom_boucle)) {
45
+        // retourne l’index explicite demandé s’il existe
46
+        if (!empty($p->boucles[$p->nom_boucle])) {
47
+            return $p->nom_boucle;
48
+        }
49
+        return '';
50
+    }
51
+    return $p->id_boucle;
52 52
 }
53 53
 
54 54
 
@@ -71,17 +71,17 @@  discard block
 block discarded – undo
71 71
  *     - '' si une référence explicite incorrecte est envoyée
72 72
  */
73 73
 function index_boucle_mere($p) {
74
-	if (strlen($p->nom_boucle)) {
75
-		// retourne l’index explicite demandé s’il existe
76
-		if (!empty($p->boucles[$p->nom_boucle])) {
77
-			return $p->nom_boucle;
78
-		}
79
-		return '';
80
-	}
81
-	if (!empty($p->descr['id_mere'])) {
82
-		return $p->descr['id_mere'];
83
-	}
84
-	return '';
74
+    if (strlen($p->nom_boucle)) {
75
+        // retourne l’index explicite demandé s’il existe
76
+        if (!empty($p->boucles[$p->nom_boucle])) {
77
+            return $p->nom_boucle;
78
+        }
79
+        return '';
80
+    }
81
+    if (!empty($p->descr['id_mere'])) {
82
+        return $p->descr['id_mere'];
83
+    }
84
+    return '';
85 85
 }
86 86
 
87 87
 /**
@@ -115,74 +115,74 @@  discard block
 block discarded – undo
115 115
  *     Code PHP pour obtenir le champ SQL
116 116
  */
117 117
 function index_pile(
118
-	$idb,
119
-	$nom_champ,
120
-	&$boucles,
121
-	$explicite = '',
122
-	$defaut = null,
123
-	$remonte_pile = true,
124
-	$select = true
118
+    $idb,
119
+    $nom_champ,
120
+    &$boucles,
121
+    $explicite = '',
122
+    $defaut = null,
123
+    $remonte_pile = true,
124
+    $select = true
125 125
 ) {
126
-	if (!is_string($defaut)) {
127
-		$defaut = '($Pile[0][\'' . strtolower($nom_champ) . '\'] ?? null)';
128
-	}
129
-
130
-	$idb_origine = $idb;
131
-	$nom_champ_origine = $nom_champ;
132
-
133
-	$i = 0;
134
-	if (strlen($explicite)) {
135
-		// Recherche d'un champ dans un etage superieur
136
-		while (($idb !== $explicite) && ($idb !== '')) {
137
-			#	spip_log("Cherchexpl: $nom_champ '$explicite' '$idb' '$i'");
138
-			$i++;
139
-			$idb = $boucles[$idb]->id_parent;
140
-		}
141
-	}
142
-
143
-	#	spip_log("Cherche: $nom_champ a partir de '$idb'");
144
-	$nom_champ = strtolower($nom_champ);
145
-	$conditionnel = [];
146
-	// attention: entre la boucle nommee 0, "" et le tableau vide,
147
-	// il y a incoherences qu'il vaut mieux eviter
148
-	while (isset($boucles[$idb])) {
149
-		$joker = true;
150
-		// modifie $joker si tous les champs sont autorisés.
151
-		// $t = le select pour le champ, si on l'a trouvé (ou si joker)
152
-		// $c = le nom du champ demandé
153
-		[$t, $c] = index_tables_en_pile($idb, $nom_champ, $boucles, $joker);
154
-		if ($t) {
155
-			if ($select and !in_array($t, $boucles[$idb]->select)) {
156
-				$boucles[$idb]->select[] = $t;
157
-			}
158
-			// renseigner la boucle source de ce champ pour les traitements
159
-			$boucles[$idb_origine]->index_champ[$nom_champ_origine] = $idb;
160
-			$champ = '$Pile[$SP' . ($i ? "-$i" : '') . '][\'' . $c . '\']';
161
-			if (!$joker) {
162
-				return index_compose($conditionnel, $champ);
163
-			}
164
-
165
-			// tant que l'on trouve des tables avec joker, on continue
166
-			// avec la boucle parente et on conditionne à l'exécution
167
-			// la présence du champ. Si le champ existe à l'exécution
168
-			// dans une boucle, il est pris, sinon on le cherche dans le parent...
169
-			$conditionnel[] = "isset($champ)?$champ";
170
-		}
171
-
172
-		if ($remonte_pile) {
173
-			#	spip_log("On remonte vers $i");
174
-			// Sinon on remonte d'un cran
175
-			$idb = $boucles[$idb]->id_parent;
176
-			$i++;
177
-		} else {
178
-			$idb = null;
179
-		}
180
-	}
181
-
182
-	#	spip_log("Pas vu $nom_champ");
183
-	// esperons qu'il y sera
184
-	// ou qu'on a fourni une valeur par "defaut" plus pertinent
185
-	return index_compose($conditionnel, $defaut);
126
+    if (!is_string($defaut)) {
127
+        $defaut = '($Pile[0][\'' . strtolower($nom_champ) . '\'] ?? null)';
128
+    }
129
+
130
+    $idb_origine = $idb;
131
+    $nom_champ_origine = $nom_champ;
132
+
133
+    $i = 0;
134
+    if (strlen($explicite)) {
135
+        // Recherche d'un champ dans un etage superieur
136
+        while (($idb !== $explicite) && ($idb !== '')) {
137
+            #	spip_log("Cherchexpl: $nom_champ '$explicite' '$idb' '$i'");
138
+            $i++;
139
+            $idb = $boucles[$idb]->id_parent;
140
+        }
141
+    }
142
+
143
+    #	spip_log("Cherche: $nom_champ a partir de '$idb'");
144
+    $nom_champ = strtolower($nom_champ);
145
+    $conditionnel = [];
146
+    // attention: entre la boucle nommee 0, "" et le tableau vide,
147
+    // il y a incoherences qu'il vaut mieux eviter
148
+    while (isset($boucles[$idb])) {
149
+        $joker = true;
150
+        // modifie $joker si tous les champs sont autorisés.
151
+        // $t = le select pour le champ, si on l'a trouvé (ou si joker)
152
+        // $c = le nom du champ demandé
153
+        [$t, $c] = index_tables_en_pile($idb, $nom_champ, $boucles, $joker);
154
+        if ($t) {
155
+            if ($select and !in_array($t, $boucles[$idb]->select)) {
156
+                $boucles[$idb]->select[] = $t;
157
+            }
158
+            // renseigner la boucle source de ce champ pour les traitements
159
+            $boucles[$idb_origine]->index_champ[$nom_champ_origine] = $idb;
160
+            $champ = '$Pile[$SP' . ($i ? "-$i" : '') . '][\'' . $c . '\']';
161
+            if (!$joker) {
162
+                return index_compose($conditionnel, $champ);
163
+            }
164
+
165
+            // tant que l'on trouve des tables avec joker, on continue
166
+            // avec la boucle parente et on conditionne à l'exécution
167
+            // la présence du champ. Si le champ existe à l'exécution
168
+            // dans une boucle, il est pris, sinon on le cherche dans le parent...
169
+            $conditionnel[] = "isset($champ)?$champ";
170
+        }
171
+
172
+        if ($remonte_pile) {
173
+            #	spip_log("On remonte vers $i");
174
+            // Sinon on remonte d'un cran
175
+            $idb = $boucles[$idb]->id_parent;
176
+            $i++;
177
+        } else {
178
+            $idb = null;
179
+        }
180
+    }
181
+
182
+    #	spip_log("Pas vu $nom_champ");
183
+    // esperons qu'il y sera
184
+    // ou qu'on a fourni une valeur par "defaut" plus pertinent
185
+    return index_compose($conditionnel, $defaut);
186 186
 }
187 187
 
188 188
 /**
@@ -196,12 +196,12 @@  discard block
 block discarded – undo
196 196
  * @return string              Code PHP complet de recherche d'un champ
197 197
  */
198 198
 function index_compose($conditionnel, $defaut) {
199
-	while ($c = array_pop($conditionnel)) {
200
-		// si on passe defaut = '', ne pas générer d'erreur de compilation.
201
-		$defaut = "($c:(" . ($defaut ?: "''") . '))';
202
-	}
199
+    while ($c = array_pop($conditionnel)) {
200
+        // si on passe defaut = '', ne pas générer d'erreur de compilation.
201
+        $defaut = "($c:(" . ($defaut ?: "''") . '))';
202
+    }
203 203
 
204
-	return $defaut;
204
+    return $defaut;
205 205
 }
206 206
 
207 207
 /**
@@ -237,97 +237,97 @@  discard block
 block discarded – undo
237 237
  **/
238 238
 function index_tables_en_pile($idb, $nom_champ, &$boucles, &$joker) {
239 239
 
240
-	$r = $boucles[$idb]->type_requete;
241
-	// boucle recursive, c'est foutu...
242
-	if ($r == TYPE_RECURSIF) {
243
-		return [];
244
-	}
245
-	if (!$r) {
246
-		$joker = false; // indiquer a l'appelant
247
-		# continuer pour chercher l'erreur suivante
248
-		return ["'#" . $r . ':' . $nom_champ . "'", ''];
249
-	}
250
-
251
-	$desc = $boucles[$idb]->show;
252
-	// le nom du champ est il une exception de la table ? un alias ?
253
-	$excep = $GLOBALS['exceptions_des_tables'][$r] ?? '';
254
-	if ($excep) {
255
-		$excep = $excep[$nom_champ] ?? '';
256
-	}
257
-
258
-	// il y a un alias connu pour ce champ
259
-	if ($excep) {
260
-		$joker = false; // indiquer a l'appelant
261
-		return index_exception($boucles[$idb], $desc, $nom_champ, $excep);
262
-	}
263
-
264
-	// le champ existe dans la table, on le prend.
265
-	if (isset($desc['field'][$nom_champ])) {
266
-		$t = $boucles[$idb]->id_table ?? '';
267
-		$joker = false; // indiquer a l'appelant
268
-		// note: dans certains cas ('valeur' d’une boucle DATA, sans id_table), retourne ['.valeur', 'valeur'] …
269
-		return ["$t.$nom_champ", $nom_champ];
270
-	}
271
-
272
-	// Tous les champs sont-ils acceptés ?
273
-	// Si oui, on retourne le champ, et on lève le flag joker
274
-	// C'est le cas des itérateurs DATA qui acceptent tout
275
-	// et testent la présence du champ à l'exécution et non à la compilation
276
-	// car ils ne connaissent pas ici leurs contenus.
277
-	if (
278
-		/*$joker AND */
279
-		isset($desc['field']['*'])
280
-	) {
281
-		$joker = true; // indiquer a l'appelant
282
-		return [$nom_champ, $nom_champ];
283
-	}
284
-
285
-	$joker = false; // indiquer a l'appelant
286
-
287
-	// la table de jointure est explicitement indiquée (rubrique.titre)
288
-	if (preg_match('/^(.*)\.(.*)$/', $nom_champ, $r)) {
289
-		[, $_table, $_nom_champ] = $r;
290
-		if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) {
291
-			$_alias = $cle . '_' . $_nom_champ;
292
-			return index_exception(
293
-				$boucles[$idb],
294
-				$desc,
295
-				$_alias,
296
-				[$_table, $_nom_champ]
297
-			);
298
-		}
299
-		return ['', ''];
300
-	}
301
-
302
-	// pas d'alias, pas de champ, pas de joker...
303
-	// tenter via une jointure...
304
-
305
-	// regarder si le champ est deja dans une jointure existante
306
-	// sinon, si il y a des joitures explicites, la construire
307
-	if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) {
308
-		if ($boucles[$idb]->jointures_explicites) {
309
-			// [todo] Ne pas lancer que lorsque il y a des jointures explicites !!!!
310
-			// fonctionnel, il suffit d'utiliser $boucles[$idb]->jointures au lieu de jointures_explicites
311
-			// mais est-ce ce qu'on veut ?
312
-			$jointures = preg_split('/\s+/', $boucles[$idb]->jointures_explicites);
313
-			if ($cle = trouver_jointure_champ($nom_champ, $boucles[$idb], $jointures)) {
314
-				$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb]);
315
-			}
316
-		}
317
-	}
318
-
319
-	if ($t) {
320
-		// si on a trouvé une jointure possible, on fait comme
321
-		// si c'était une exception pour le champ demandé
322
-		return index_exception(
323
-			$boucles[$idb],
324
-			$desc,
325
-			$nom_champ,
326
-			[$t[1]['id_table'], reset($t[2])]
327
-		);
328
-	}
329
-
330
-	return ['', ''];
240
+    $r = $boucles[$idb]->type_requete;
241
+    // boucle recursive, c'est foutu...
242
+    if ($r == TYPE_RECURSIF) {
243
+        return [];
244
+    }
245
+    if (!$r) {
246
+        $joker = false; // indiquer a l'appelant
247
+        # continuer pour chercher l'erreur suivante
248
+        return ["'#" . $r . ':' . $nom_champ . "'", ''];
249
+    }
250
+
251
+    $desc = $boucles[$idb]->show;
252
+    // le nom du champ est il une exception de la table ? un alias ?
253
+    $excep = $GLOBALS['exceptions_des_tables'][$r] ?? '';
254
+    if ($excep) {
255
+        $excep = $excep[$nom_champ] ?? '';
256
+    }
257
+
258
+    // il y a un alias connu pour ce champ
259
+    if ($excep) {
260
+        $joker = false; // indiquer a l'appelant
261
+        return index_exception($boucles[$idb], $desc, $nom_champ, $excep);
262
+    }
263
+
264
+    // le champ existe dans la table, on le prend.
265
+    if (isset($desc['field'][$nom_champ])) {
266
+        $t = $boucles[$idb]->id_table ?? '';
267
+        $joker = false; // indiquer a l'appelant
268
+        // note: dans certains cas ('valeur' d’une boucle DATA, sans id_table), retourne ['.valeur', 'valeur'] …
269
+        return ["$t.$nom_champ", $nom_champ];
270
+    }
271
+
272
+    // Tous les champs sont-ils acceptés ?
273
+    // Si oui, on retourne le champ, et on lève le flag joker
274
+    // C'est le cas des itérateurs DATA qui acceptent tout
275
+    // et testent la présence du champ à l'exécution et non à la compilation
276
+    // car ils ne connaissent pas ici leurs contenus.
277
+    if (
278
+        /*$joker AND */
279
+        isset($desc['field']['*'])
280
+    ) {
281
+        $joker = true; // indiquer a l'appelant
282
+        return [$nom_champ, $nom_champ];
283
+    }
284
+
285
+    $joker = false; // indiquer a l'appelant
286
+
287
+    // la table de jointure est explicitement indiquée (rubrique.titre)
288
+    if (preg_match('/^(.*)\.(.*)$/', $nom_champ, $r)) {
289
+        [, $_table, $_nom_champ] = $r;
290
+        if ($cle = trouver_jointure_champ($_nom_champ, $boucles[$idb], [$_table])) {
291
+            $_alias = $cle . '_' . $_nom_champ;
292
+            return index_exception(
293
+                $boucles[$idb],
294
+                $desc,
295
+                $_alias,
296
+                [$_table, $_nom_champ]
297
+            );
298
+        }
299
+        return ['', ''];
300
+    }
301
+
302
+    // pas d'alias, pas de champ, pas de joker...
303
+    // tenter via une jointure...
304
+
305
+    // regarder si le champ est deja dans une jointure existante
306
+    // sinon, si il y a des joitures explicites, la construire
307
+    if (!$t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb])) {
308
+        if ($boucles[$idb]->jointures_explicites) {
309
+            // [todo] Ne pas lancer que lorsque il y a des jointures explicites !!!!
310
+            // fonctionnel, il suffit d'utiliser $boucles[$idb]->jointures au lieu de jointures_explicites
311
+            // mais est-ce ce qu'on veut ?
312
+            $jointures = preg_split('/\s+/', $boucles[$idb]->jointures_explicites);
313
+            if ($cle = trouver_jointure_champ($nom_champ, $boucles[$idb], $jointures)) {
314
+                $t = trouver_champ_exterieur($nom_champ, $boucles[$idb]->from, $boucles[$idb]);
315
+            }
316
+        }
317
+    }
318
+
319
+    if ($t) {
320
+        // si on a trouvé une jointure possible, on fait comme
321
+        // si c'était une exception pour le champ demandé
322
+        return index_exception(
323
+            $boucles[$idb],
324
+            $desc,
325
+            $nom_champ,
326
+            [$t[1]['id_table'], reset($t[2])]
327
+        );
328
+    }
329
+
330
+    return ['', ''];
331 331
 }
332 332
 
333 333
 
@@ -355,52 +355,52 @@  discard block
 block discarded – undo
355 355
  *     est une expression pour le SELECT de la boucle du style "mots.titre AS titre_mot"
356 356
  **/
357 357
 function index_exception(&$boucle, $desc, $nom_champ, $excep) {
358
-	static $trouver_table;
359
-	if (!$trouver_table) {
360
-		$trouver_table = charger_fonction('trouver_table', 'base');
361
-	}
362
-
363
-	if (is_array($excep)) {
364
-		// permettre aux plugins de gerer eux meme des jointures derogatoire ingerables
365
-		$t = null;
366
-		if (count($excep) == 3) {
367
-			$index_exception_derogatoire = array_pop($excep);
368
-			$t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep);
369
-		}
370
-		if ($t == null) {
371
-			[$e, $x] = $excep;  #PHP4 affecte de gauche a droite
372
-			$excep = $x;    #PHP5 de droite a gauche !
373
-			$j = $trouver_table($e, $boucle->sql_serveur);
374
-			if (!$j) {
375
-				return ['', ''];
376
-			}
377
-			$e = $j['table'];
378
-			if (!$t = array_search($e, $boucle->from)) {
379
-				$k = $j['key']['PRIMARY KEY'];
380
-				if (strpos($k, ',')) {
381
-					$l = (preg_split('/\s*,\s*/', $k));
382
-					$k = $desc['key']['PRIMARY KEY'];
383
-					if (!in_array($k, $l)) {
384
-						spip_log("jointure impossible $e " . join(',', $l));
385
-
386
-						return ['', ''];
387
-					}
388
-				}
389
-				$k = [$boucle->id_table, [$e], $k];
390
-				fabrique_jointures($boucle, [$k]);
391
-				$t = array_search($e, $boucle->from);
392
-			}
393
-		}
394
-	} else {
395
-		$t = $boucle->id_table;
396
-	}
397
-	// demander a SQL de gerer le synonyme
398
-	// ca permet que excep soit dynamique (Cedric, 2/3/06)
399
-	if ($excep != $nom_champ) {
400
-		$excep .= ' AS ' . $nom_champ;
401
-	}
402
-
403
-	return ["$t.$excep", $nom_champ];
358
+    static $trouver_table;
359
+    if (!$trouver_table) {
360
+        $trouver_table = charger_fonction('trouver_table', 'base');
361
+    }
362
+
363
+    if (is_array($excep)) {
364
+        // permettre aux plugins de gerer eux meme des jointures derogatoire ingerables
365
+        $t = null;
366
+        if (count($excep) == 3) {
367
+            $index_exception_derogatoire = array_pop($excep);
368
+            $t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep);
369
+        }
370
+        if ($t == null) {
371
+            [$e, $x] = $excep;  #PHP4 affecte de gauche a droite
372
+            $excep = $x;    #PHP5 de droite a gauche !
373
+            $j = $trouver_table($e, $boucle->sql_serveur);
374
+            if (!$j) {
375
+                return ['', ''];
376
+            }
377
+            $e = $j['table'];
378
+            if (!$t = array_search($e, $boucle->from)) {
379
+                $k = $j['key']['PRIMARY KEY'];
380
+                if (strpos($k, ',')) {
381
+                    $l = (preg_split('/\s*,\s*/', $k));
382
+                    $k = $desc['key']['PRIMARY KEY'];
383
+                    if (!in_array($k, $l)) {
384
+                        spip_log("jointure impossible $e " . join(',', $l));
385
+
386
+                        return ['', ''];
387
+                    }
388
+                }
389
+                $k = [$boucle->id_table, [$e], $k];
390
+                fabrique_jointures($boucle, [$k]);
391
+                $t = array_search($e, $boucle->from);
392
+            }
393
+        }
394
+    } else {
395
+        $t = $boucle->id_table;
396
+    }
397
+    // demander a SQL de gerer le synonyme
398
+    // ca permet que excep soit dynamique (Cedric, 2/3/06)
399
+    if ($excep != $nom_champ) {
400
+        $excep .= ' AS ' . $nom_champ;
401
+    }
402
+
403
+    return ["$t.$excep", $nom_champ];
404 404
 }
405 405
 
406 406
 /**
@@ -425,7 +425,7 @@  discard block
 block discarded – undo
425 425
  *     Code PHP pour retrouver le champ
426 426
  */
427 427
 function champ_sql($champ, $p, $defaut = null, $remonte_pile = true) {
428
-	return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle, $defaut, $remonte_pile);
428
+    return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle, $defaut, $remonte_pile);
429 429
 }
430 430
 
431 431
 
@@ -445,9 +445,9 @@  discard block
 block discarded – undo
445 445
  *     Code PHP pour d'exécution de la balise et de ses filtres
446 446
  **/
447 447
 function calculer_champ($p) {
448
-	$p = calculer_balise($p->nom_champ, $p);
448
+    $p = calculer_balise($p->nom_champ, $p);
449 449
 
450
-	return applique_filtres($p);
450
+    return applique_filtres($p);
451 451
 }
452 452
 
453 453
 
@@ -484,26 +484,26 @@  discard block
 block discarded – undo
484 484
  **/
485 485
 function calculer_balise(string $nom, \Champ $p): \Champ {
486 486
 
487
-	// S'agit-t-il d'une balise_XXXX[_dist]() ?
488
-	if ($f = charger_fonction($nom, 'balise', true)) {
489
-		$p->balise_calculee = true;
490
-		$res = $f($p);
491
-		if ($res !== null and is_object($res)) {
492
-			return $res;
493
-		}
494
-	}
495
-
496
-	// Certaines des balises comportant un _ sont generiques
497
-	if ($balise_generique = chercher_balise_generique($nom)) {
498
-		$res = $balise_generique['fonction_generique']($p);
499
-		if ($res !== null and is_object($res)) {
500
-			return $res;
501
-		}
502
-	}
503
-
504
-	$f = charger_fonction('DEFAUT', 'calculer_balise');
505
-
506
-	return $f($nom, $p);
487
+    // S'agit-t-il d'une balise_XXXX[_dist]() ?
488
+    if ($f = charger_fonction($nom, 'balise', true)) {
489
+        $p->balise_calculee = true;
490
+        $res = $f($p);
491
+        if ($res !== null and is_object($res)) {
492
+            return $res;
493
+        }
494
+    }
495
+
496
+    // Certaines des balises comportant un _ sont generiques
497
+    if ($balise_generique = chercher_balise_generique($nom)) {
498
+        $res = $balise_generique['fonction_generique']($p);
499
+        if ($res !== null and is_object($res)) {
500
+            return $res;
501
+        }
502
+    }
503
+
504
+    $f = charger_fonction('DEFAUT', 'calculer_balise');
505
+
506
+    return $f($nom, $p);
507 507
 }
508 508
 
509 509
 
@@ -531,37 +531,37 @@  discard block
 block discarded – undo
531 531
  **/
532 532
 function calculer_balise_DEFAUT_dist($nom, $p) {
533 533
 
534
-	// ca pourrait etre un champ SQL homonyme,
535
-	$p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle);
536
-
537
-	// compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
538
-	// il faut recracher {...} quand ce n'est finalement pas des args
539
-	if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
540
-		$code = addslashes($p->fonctions[0][1]);
541
-		$p->code .= " . '$code'";
542
-	}
543
-
544
-	// ne pas passer le filtre securite sur les id_xxx
545
-	if (strpos($nom, 'ID_') === 0) {
546
-		$p->interdire_scripts = false;
547
-	}
548
-
549
-	// Compatibilite ascendante avec les couleurs html (#FEFEFE) :
550
-	// SI le champ SQL n'est pas trouve
551
-	// ET si la balise a une forme de couleur
552
-	// ET s'il n'y a ni filtre ni etoile
553
-	// ALORS retourner la couleur.
554
-	// Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)]
555
-	if (
556
-		preg_match('/^[A-F]{1,6}$/i', $nom)
557
-		and !$p->etoile
558
-		and !$p->fonctions
559
-	) {
560
-		$p->code = "'#$nom'";
561
-		$p->interdire_scripts = false;
562
-	}
563
-
564
-	return $p;
534
+    // ca pourrait etre un champ SQL homonyme,
535
+    $p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle);
536
+
537
+    // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
538
+    // il faut recracher {...} quand ce n'est finalement pas des args
539
+    if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
540
+        $code = addslashes($p->fonctions[0][1]);
541
+        $p->code .= " . '$code'";
542
+    }
543
+
544
+    // ne pas passer le filtre securite sur les id_xxx
545
+    if (strpos($nom, 'ID_') === 0) {
546
+        $p->interdire_scripts = false;
547
+    }
548
+
549
+    // Compatibilite ascendante avec les couleurs html (#FEFEFE) :
550
+    // SI le champ SQL n'est pas trouve
551
+    // ET si la balise a une forme de couleur
552
+    // ET s'il n'y a ni filtre ni etoile
553
+    // ALORS retourner la couleur.
554
+    // Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)]
555
+    if (
556
+        preg_match('/^[A-F]{1,6}$/i', $nom)
557
+        and !$p->etoile
558
+        and !$p->fonctions
559
+    ) {
560
+        $p->code = "'#$nom'";
561
+        $p->interdire_scripts = false;
562
+    }
563
+
564
+    return $p;
565 565
 }
566 566
 
567 567
 
@@ -609,53 +609,53 @@  discard block
 block discarded – undo
609 609
  **/
610 610
 function calculer_balise_dynamique($p, $nom, $l, $supp = []) {
611 611
 
612
-	if (!balise_distante_interdite($p)) {
613
-		$p->code = "''";
614
-
615
-		return $p;
616
-	}
617
-	// compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
618
-	// il faut recracher {...} quand ce n'est finalement pas des args
619
-	if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
620
-		$p->fonctions = [];
621
-	}
622
-
623
-	if ($p->param and ($c = $p->param[0])) {
624
-		// liste d'arguments commence toujours par la chaine vide
625
-		array_shift($c);
626
-		// construire la liste d'arguments comme pour un filtre
627
-		$param = compose_filtres_args($p, $c, ',');
628
-	} else {
629
-		$param = '';
630
-	}
631
-	$collecte = collecter_balise_dynamique($l, $p, $nom);
632
-
633
-	$dans_un_modele = false;
634
-	if (!empty($p->descr['sourcefile'])
635
-	  and $f = $p->descr['sourcefile']
636
-	  and basename(dirname($f)) === 'modeles'
637
-	) {
638
-		$dans_un_modele = true;
639
-	}
640
-
641
-	// un modele est toujours inséré en texte dans son contenant
642
-	// donc si on est dans le public avec un cache on va perdre le dynamisme
643
-	// et on risque de mettre en cache les valeurs pre-remplies du formulaire
644
-	// on passe donc par une fonction proxy qui si besoin va collecter les arguments
645
-	// et injecter le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
646
-	// (dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave))
647
-	$p->code = sprintf(
648
-		$dans_un_modele ? CODE_EXECUTER_BALISE_MODELE : CODE_EXECUTER_BALISE,
649
-		$nom,
650
-		join(',', $collecte),
651
-		($collecte ? $param : substr($param, 1)), # virer la virgule
652
-		memoriser_contexte_compil($p),
653
-		(!$supp ? '' : (', ' . join(',', $supp)))
654
-	);
655
-
656
-	$p->interdire_scripts = false;
657
-
658
-	return $p;
612
+    if (!balise_distante_interdite($p)) {
613
+        $p->code = "''";
614
+
615
+        return $p;
616
+    }
617
+    // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour
618
+    // il faut recracher {...} quand ce n'est finalement pas des args
619
+    if ($p->fonctions and (!$p->fonctions[0][0]) and $p->fonctions[0][1]) {
620
+        $p->fonctions = [];
621
+    }
622
+
623
+    if ($p->param and ($c = $p->param[0])) {
624
+        // liste d'arguments commence toujours par la chaine vide
625
+        array_shift($c);
626
+        // construire la liste d'arguments comme pour un filtre
627
+        $param = compose_filtres_args($p, $c, ',');
628
+    } else {
629
+        $param = '';
630
+    }
631
+    $collecte = collecter_balise_dynamique($l, $p, $nom);
632
+
633
+    $dans_un_modele = false;
634
+    if (!empty($p->descr['sourcefile'])
635
+      and $f = $p->descr['sourcefile']
636
+      and basename(dirname($f)) === 'modeles'
637
+    ) {
638
+        $dans_un_modele = true;
639
+    }
640
+
641
+    // un modele est toujours inséré en texte dans son contenant
642
+    // donc si on est dans le public avec un cache on va perdre le dynamisme
643
+    // et on risque de mettre en cache les valeurs pre-remplies du formulaire
644
+    // on passe donc par une fonction proxy qui si besoin va collecter les arguments
645
+    // et injecter le PHP qui va appeler la fonction pour generer le formulaire au lieu de directement la fonction
646
+    // (dans l'espace prive on a pas de cache, donc pas de soucis (et un leak serait moins grave))
647
+    $p->code = sprintf(
648
+        $dans_un_modele ? CODE_EXECUTER_BALISE_MODELE : CODE_EXECUTER_BALISE,
649
+        $nom,
650
+        join(',', $collecte),
651
+        ($collecte ? $param : substr($param, 1)), # virer la virgule
652
+        memoriser_contexte_compil($p),
653
+        (!$supp ? '' : (', ' . join(',', $supp)))
654
+    );
655
+
656
+    $p->interdire_scripts = false;
657
+
658
+    return $p;
659 659
 }
660 660
 
661 661
 
@@ -685,17 +685,17 @@  discard block
 block discarded – undo
685 685
  *     Liste des codes PHP d'éxecution des balises collectées
686 686
  **/
687 687
 function collecter_balise_dynamique(array $l, \Champ &$p, string $nom): array {
688
-	$args = [];
689
-	foreach ($l as $c) {
690
-		if ($c === null) {
691
-			$args[] = 'null';
692
-		} else {
693
-			$x = calculer_balise($c, $p);
694
-			$args[] = $x->code;
695
-		}
696
-	}
697
-
698
-	return $args;
688
+    $args = [];
689
+    foreach ($l as $c) {
690
+        if ($c === null) {
691
+            $args[] = 'null';
692
+        } else {
693
+            $x = calculer_balise($c, $p);
694
+            $args[] = $x->code;
695
+        }
696
+    }
697
+
698
+    return $args;
699 699
 }
700 700
 
701 701
 
@@ -710,22 +710,22 @@  discard block
 block discarded – undo
710 710
  *     Nom de la connexion
711 711
  **/
712 712
 function trouver_nom_serveur_distant($p) {
713
-	$nom = $p->id_boucle;
714
-	if (
715
-		$nom
716
-		and isset($p->boucles[$nom])
717
-	) {
718
-		$s = $p->boucles[$nom]->sql_serveur;
719
-		if (
720
-			strlen($s)
721
-			and strlen($serveur = strtolower($s))
722
-			and !in_array($serveur, $GLOBALS['exception_des_connect'])
723
-		) {
724
-			return $serveur;
725
-		}
726
-	}
727
-
728
-	return '';
713
+    $nom = $p->id_boucle;
714
+    if (
715
+        $nom
716
+        and isset($p->boucles[$nom])
717
+    ) {
718
+        $s = $p->boucles[$nom]->sql_serveur;
719
+        if (
720
+            strlen($s)
721
+            and strlen($serveur = strtolower($s))
722
+            and !in_array($serveur, $GLOBALS['exception_des_connect'])
723
+        ) {
724
+            return $serveur;
725
+        }
726
+    }
727
+
728
+    return '';
729 729
 }
730 730
 
731 731
 
@@ -749,15 +749,15 @@  discard block
 block discarded – undo
749 749
  *     - false : La balise est interdite car le serveur est distant
750 750
  **/
751 751
 function balise_distante_interdite($p) {
752
-	$nom = $p->id_boucle;
752
+    $nom = $p->id_boucle;
753 753
 
754
-	if ($nom and trouver_nom_serveur_distant($p)) {
755
-		spip_log($nom . ':' . $p->nom_champ . ' ' . _T('zbug_distant_interdit'));
754
+    if ($nom and trouver_nom_serveur_distant($p)) {
755
+        spip_log($nom . ':' . $p->nom_champ . ' ' . _T('zbug_distant_interdit'));
756 756
 
757
-		return false;
758
-	}
757
+        return false;
758
+    }
759 759
 
760
-	return true;
760
+    return true;
761 761
 }
762 762
 
763 763
 
@@ -767,84 +767,84 @@  discard block
 block discarded – undo
767 767
 //
768 768
 function champs_traitements($p) {
769 769
 
770
-	if (isset($GLOBALS['table_des_traitements'][$p->nom_champ])) {
771
-		$ps = $GLOBALS['table_des_traitements'][$p->nom_champ];
772
-	} else {
773
-		// quand on utilise un traitement catch-all *
774
-		// celui-ci ne s'applique pas sur les balises calculees qui peuvent gerer
775
-		// leur propre securite
776
-		if (!$p->balise_calculee) {
777
-			$ps = $GLOBALS['table_des_traitements']['*'];
778
-		} else {
779
-			$ps = false;
780
-		}
781
-	}
782
-
783
-	if (is_array($ps)) {
784
-		// Recuperer le type de boucle (articles, DATA) et la table SQL sur laquelle elle porte
785
-		$idb = index_boucle($p);
786
-		// si le champ a ete trouve dans une boucle parente sa source est renseignee ici
787
-		if (!empty($p->boucles[$idb]->index_champ[$p->nom_champ])) {
788
-			$idb = $p->boucles[$idb]->index_champ[$p->nom_champ];
789
-		}
790
-
791
-		// mais on peut aussi etre hors boucle. Se mefier.
792
-		$type_requete = $p->boucles[$idb]->type_requete ?? false;
793
-		$table_sql = $p->boucles[$idb]->show['table_sql'] ?? false;
794
-
795
-		// bien prendre en compte les alias de boucles (hierarchie => rubrique, syndication => syncdic, etc.)
796
-		if ($type_requete and isset($GLOBALS['table_des_tables'][$type_requete])) {
797
-			$type_alias = $type_requete;
798
-			$type_requete = $GLOBALS['table_des_tables'][$type_requete];
799
-		} else {
800
-			$type_alias = false;
801
-		}
802
-
803
-		// le traitement peut n'etre defini que pour une table en particulier "spip_articles"
804
-		if ($table_sql and isset($ps[$table_sql])) {
805
-			$ps = $ps[$table_sql];
806
-		} // ou pour une boucle en particulier "DATA","articles"
807
-		elseif ($type_requete and isset($ps[$type_requete])) {
808
-			$ps = $ps[$type_requete];
809
-		} // ou pour une boucle utilisant un alias ("hierarchie")
810
-		elseif ($type_alias and isset($ps[$type_alias])) {
811
-			$ps = $ps[$type_alias];
812
-		} // ou pour indifféremment quelle que soit la boucle
813
-		elseif (isset($ps[0])) {
814
-			$ps = $ps[0];
815
-		} else {
816
-			$ps = false;
817
-		}
818
-	}
819
-
820
-	if (!$ps) {
821
-		return $p->code;
822
-	}
823
-
824
-	// Si une boucle DOCUMENTS{doublons} est presente dans le squelette,
825
-	// ou si in INCLURE contient {doublons}
826
-	// on insere une fonction de remplissage du tableau des doublons
827
-	// dans les filtres propre() ou typo()
828
-	// (qui traitent les raccourcis <docXX> referencant les docs)
829
-
830
-	if (
831
-		isset($p->descr['documents'])
832
-		and
833
-		$p->descr['documents']
834
-		and (
835
-			(strpos($ps, 'propre') !== false)
836
-			or
837
-			(strpos($ps, 'typo') !== false)
838
-		)
839
-	) {
840
-		$ps = 'traiter_doublons_documents($doublons, ' . $ps . ')';
841
-	}
842
-
843
-	// La protection des champs par |safehtml est assuree par les extensions
844
-	// dans la declaration des traitements des champs sensibles
845
-
846
-	// Remplacer enfin le placeholder %s par le vrai code de la balise
847
-	return str_replace('%s', $p->code, $ps);
770
+    if (isset($GLOBALS['table_des_traitements'][$p->nom_champ])) {
771
+        $ps = $GLOBALS['table_des_traitements'][$p->nom_champ];
772
+    } else {
773
+        // quand on utilise un traitement catch-all *
774
+        // celui-ci ne s'applique pas sur les balises calculees qui peuvent gerer
775
+        // leur propre securite
776
+        if (!$p->balise_calculee) {
777
+            $ps = $GLOBALS['table_des_traitements']['*'];
778
+        } else {
779
+            $ps = false;
780
+        }
781
+    }
782
+
783
+    if (is_array($ps)) {
784
+        // Recuperer le type de boucle (articles, DATA) et la table SQL sur laquelle elle porte
785
+        $idb = index_boucle($p);
786
+        // si le champ a ete trouve dans une boucle parente sa source est renseignee ici
787
+        if (!empty($p->boucles[$idb]->index_champ[$p->nom_champ])) {
788
+            $idb = $p->boucles[$idb]->index_champ[$p->nom_champ];
789
+        }
790
+
791
+        // mais on peut aussi etre hors boucle. Se mefier.
792
+        $type_requete = $p->boucles[$idb]->type_requete ?? false;
793
+        $table_sql = $p->boucles[$idb]->show['table_sql'] ?? false;
794
+
795
+        // bien prendre en compte les alias de boucles (hierarchie => rubrique, syndication => syncdic, etc.)
796
+        if ($type_requete and isset($GLOBALS['table_des_tables'][$type_requete])) {
797
+            $type_alias = $type_requete;
798
+            $type_requete = $GLOBALS['table_des_tables'][$type_requete];
799
+        } else {
800
+            $type_alias = false;
801
+        }
802
+
803
+        // le traitement peut n'etre defini que pour une table en particulier "spip_articles"
804
+        if ($table_sql and isset($ps[$table_sql])) {
805
+            $ps = $ps[$table_sql];
806
+        } // ou pour une boucle en particulier "DATA","articles"
807
+        elseif ($type_requete and isset($ps[$type_requete])) {
808
+            $ps = $ps[$type_requete];
809
+        } // ou pour une boucle utilisant un alias ("hierarchie")
810
+        elseif ($type_alias and isset($ps[$type_alias])) {
811
+            $ps = $ps[$type_alias];
812
+        } // ou pour indifféremment quelle que soit la boucle
813
+        elseif (isset($ps[0])) {
814
+            $ps = $ps[0];
815
+        } else {
816
+            $ps = false;
817
+        }
818
+    }
819
+
820
+    if (!$ps) {
821
+        return $p->code;
822
+    }
823
+
824
+    // Si une boucle DOCUMENTS{doublons} est presente dans le squelette,
825
+    // ou si in INCLURE contient {doublons}
826
+    // on insere une fonction de remplissage du tableau des doublons
827
+    // dans les filtres propre() ou typo()
828
+    // (qui traitent les raccourcis <docXX> referencant les docs)
829
+
830
+    if (
831
+        isset($p->descr['documents'])
832
+        and
833
+        $p->descr['documents']
834
+        and (
835
+            (strpos($ps, 'propre') !== false)
836
+            or
837
+            (strpos($ps, 'typo') !== false)
838
+        )
839
+    ) {
840
+        $ps = 'traiter_doublons_documents($doublons, ' . $ps . ')';
841
+    }
842
+
843
+    // La protection des champs par |safehtml est assuree par les extensions
844
+    // dans la declaration des traitements des champs sensibles
845
+
846
+    // Remplacer enfin le placeholder %s par le vrai code de la balise
847
+    return str_replace('%s', $p->code, $ps);
848 848
 }
849 849
 
850 850
 
@@ -856,110 +856,110 @@  discard block
 block discarded – undo
856 856
 //
857 857
 function applique_filtres($p) {
858 858
 
859
-	// Traitements standards (cf. supra)
860
-	if ($p->etoile == '') {
861
-		$code = champs_traitements($p);
862
-	} else {
863
-		$code = $p->code;
864
-	}
859
+    // Traitements standards (cf. supra)
860
+    if ($p->etoile == '') {
861
+        $code = champs_traitements($p);
862
+    } else {
863
+        $code = $p->code;
864
+    }
865 865
 
866
-	// Appliquer les filtres perso
867
-	if ($p->param) {
868
-		$code = compose_filtres($p, $code);
869
-	}
866
+    // Appliquer les filtres perso
867
+    if ($p->param) {
868
+        $code = compose_filtres($p, $code);
869
+    }
870 870
 
871
-	// S'il y a un lien avec la session, ajouter un code qui levera
872
-	// un drapeau dans la structure d'invalidation $Cache
873
-	if (isset($p->descr['session'])) {
874
-		$code = "invalideur_session(\$Cache, $code)";
875
-	}
871
+    // S'il y a un lien avec la session, ajouter un code qui levera
872
+    // un drapeau dans la structure d'invalidation $Cache
873
+    if (isset($p->descr['session'])) {
874
+        $code = "invalideur_session(\$Cache, $code)";
875
+    }
876 876
 
877
-	$code = sandbox_composer_interdire_scripts($code, $p);
877
+    $code = sandbox_composer_interdire_scripts($code, $p);
878 878
 
879
-	return $code;
879
+    return $code;
880 880
 }
881 881
 
882 882
 // Cf. function pipeline dans ecrire/inc_utils.php
883 883
 function compose_filtres(&$p, $code) {
884 884
 
885
-	$image_miette = false;
886
-	foreach ($p->param as $filtre) {
887
-		$fonc = array_shift($filtre);
888
-		if (!$fonc) {
889
-			continue;
890
-		} // normalement qu'au premier tour.
891
-		$is_filtre_image = ((substr($fonc, 0, 6) == 'image_') and $fonc != 'image_graver');
892
-		if ($image_miette and !$is_filtre_image) {
893
-			// il faut graver maintenant car apres le filtre en cours
894
-			// on est pas sur d'avoir encore le nom du fichier dans le pipe
895
-			$code = "filtrer('image_graver', $code)";
896
-			$image_miette = false;
897
-		}
898
-
899
-		// recuperer les arguments du filtre,
900
-		// a separer par "," ou ":" dans le cas du filtre "?{a,b}"
901
-		$countfiltre = is_countable($filtre) ? count($filtre) : 0;
902
-		if ($fonc !== '?') {
903
-			$sep = ',';
904
-		} else {
905
-			$sep = ':';
906
-			// |?{a,b} *doit* avoir exactement 2 arguments ; on les force
907
-			if ($countfiltre != 2) {
908
-				$filtre = [$filtre[0] ?? '', $filtre[1] ?? ''];
909
-				$countfiltre = 2;
910
-			}
911
-		}
912
-		$arglist = compose_filtres_args($p, $filtre, $sep);
913
-		$logique = filtre_logique($fonc, $code, substr($arglist, 1));
914
-		if ($logique) {
915
-			$code = $logique;
916
-		} else {
917
-			$code = sandbox_composer_filtre($fonc, $code, $arglist, $p, $countfiltre);
918
-			if ($is_filtre_image) {
919
-				$image_miette = true;
920
-			}
921
-		}
922
-	}
923
-	// ramasser les images intermediaires inutiles et graver l'image finale
924
-	if ($image_miette) {
925
-		$code = "filtrer('image_graver',$code)";
926
-	}
927
-
928
-	return $code;
885
+    $image_miette = false;
886
+    foreach ($p->param as $filtre) {
887
+        $fonc = array_shift($filtre);
888
+        if (!$fonc) {
889
+            continue;
890
+        } // normalement qu'au premier tour.
891
+        $is_filtre_image = ((substr($fonc, 0, 6) == 'image_') and $fonc != 'image_graver');
892
+        if ($image_miette and !$is_filtre_image) {
893
+            // il faut graver maintenant car apres le filtre en cours
894
+            // on est pas sur d'avoir encore le nom du fichier dans le pipe
895
+            $code = "filtrer('image_graver', $code)";
896
+            $image_miette = false;
897
+        }
898
+
899
+        // recuperer les arguments du filtre,
900
+        // a separer par "," ou ":" dans le cas du filtre "?{a,b}"
901
+        $countfiltre = is_countable($filtre) ? count($filtre) : 0;
902
+        if ($fonc !== '?') {
903
+            $sep = ',';
904
+        } else {
905
+            $sep = ':';
906
+            // |?{a,b} *doit* avoir exactement 2 arguments ; on les force
907
+            if ($countfiltre != 2) {
908
+                $filtre = [$filtre[0] ?? '', $filtre[1] ?? ''];
909
+                $countfiltre = 2;
910
+            }
911
+        }
912
+        $arglist = compose_filtres_args($p, $filtre, $sep);
913
+        $logique = filtre_logique($fonc, $code, substr($arglist, 1));
914
+        if ($logique) {
915
+            $code = $logique;
916
+        } else {
917
+            $code = sandbox_composer_filtre($fonc, $code, $arglist, $p, $countfiltre);
918
+            if ($is_filtre_image) {
919
+                $image_miette = true;
920
+            }
921
+        }
922
+    }
923
+    // ramasser les images intermediaires inutiles et graver l'image finale
924
+    if ($image_miette) {
925
+        $code = "filtrer('image_graver',$code)";
926
+    }
927
+
928
+    return $code;
929 929
 }
930 930
 
931 931
 // Filtres et,ou,oui,non,sinon,xou,xor,and,or,not,yes
932 932
 // et comparateurs
933 933
 function filtre_logique($fonc, $code, $arg) {
934 934
 
935
-	switch (true) {
936
-		case in_array($fonc, $GLOBALS['table_criteres_infixes']):
937
-			return "($code $fonc $arg)";
938
-		case ($fonc == 'and') or ($fonc == 'et'):
939
-			return "((($code) AND ($arg)) ?' ' :'')";
940
-		case ($fonc == 'or') or ($fonc == 'ou'):
941
-			return "((($code) OR ($arg)) ?' ' :'')";
942
-		case ($fonc == 'xor') or ($fonc == 'xou'):
943
-			return "((($code) XOR ($arg)) ?' ' :'')";
944
-		case ($fonc == 'sinon'):
945
-			return "(((\$a = $code) OR (is_string(\$a) AND strlen(\$a))) ? \$a : $arg)";
946
-		case ($fonc == 'not') or ($fonc == 'non'):
947
-			return "(($code) ?'' :' ')";
948
-		case ($fonc == 'yes') or ($fonc == 'oui'):
949
-			return "(($code) ?' ' :'')";
950
-	}
951
-
952
-	return '';
935
+    switch (true) {
936
+        case in_array($fonc, $GLOBALS['table_criteres_infixes']):
937
+            return "($code $fonc $arg)";
938
+        case ($fonc == 'and') or ($fonc == 'et'):
939
+            return "((($code) AND ($arg)) ?' ' :'')";
940
+        case ($fonc == 'or') or ($fonc == 'ou'):
941
+            return "((($code) OR ($arg)) ?' ' :'')";
942
+        case ($fonc == 'xor') or ($fonc == 'xou'):
943
+            return "((($code) XOR ($arg)) ?' ' :'')";
944
+        case ($fonc == 'sinon'):
945
+            return "(((\$a = $code) OR (is_string(\$a) AND strlen(\$a))) ? \$a : $arg)";
946
+        case ($fonc == 'not') or ($fonc == 'non'):
947
+            return "(($code) ?'' :' ')";
948
+        case ($fonc == 'yes') or ($fonc == 'oui'):
949
+            return "(($code) ?' ' :'')";
950
+    }
951
+
952
+    return '';
953 953
 }
954 954
 
955 955
 function compose_filtres_args($p, $args, $sep) {
956
-	$arglist = '';
957
-	foreach ($args as $arg) {
958
-		$arglist .= $sep .
959
-			calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle);
960
-	}
956
+    $arglist = '';
957
+    foreach ($args as $arg) {
958
+        $arglist .= $sep .
959
+            calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle);
960
+    }
961 961
 
962
-	return $arglist;
962
+    return $arglist;
963 963
 }
964 964
 
965 965
 
@@ -977,15 +977,15 @@  discard block
 block discarded – undo
977 977
  **/
978 978
 function calculer_argument_precedent($idb, $nom_champ, &$boucles, $defaut = null) {
979 979
 
980
-	// si recursif, forcer l'extraction du champ SQL mais ignorer le code
981
-	if ($boucles[$idb]->externe) {
982
-		index_pile($idb, $nom_champ, $boucles, '', $defaut);
983
-		// retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
984
-		// on ignore le defaut fourni dans ce cas
985
-		$defaut = "(\$Pile[\$SP]['$nom_champ'] ?? null)";
986
-	}
980
+    // si recursif, forcer l'extraction du champ SQL mais ignorer le code
981
+    if ($boucles[$idb]->externe) {
982
+        index_pile($idb, $nom_champ, $boucles, '', $defaut);
983
+        // retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle
984
+        // on ignore le defaut fourni dans ce cas
985
+        $defaut = "(\$Pile[\$SP]['$nom_champ'] ?? null)";
986
+    }
987 987
 
988
-	return index_pile($boucles[$idb]->id_parent, $nom_champ, $boucles, '', $defaut);
988
+    return index_pile($boucles[$idb]->id_parent, $nom_champ, $boucles, '', $defaut);
989 989
 }
990 990
 
991 991
 //
@@ -999,30 +999,30 @@  discard block
 block discarded – undo
999 999
 //
1000 1000
 
1001 1001
 function rindex_pile($p, $champ, $motif) {
1002
-	$n = 0;
1003
-	$b = $p->id_boucle;
1004
-	$p->code = '';
1005
-	while ($b != '') {
1006
-		foreach ($p->boucles[$b]->criteres as $critere) {
1007
-			if ($critere->op == $motif) {
1008
-				$p->code = '$Pile[$SP' . (($n == 0) ? '' : "-$n") .
1009
-					"]['$champ']";
1010
-				$b = '';
1011
-				break 2;
1012
-			}
1013
-		}
1014
-		$n++;
1015
-		$b = $p->boucles[$b]->id_parent;
1016
-	}
1017
-
1018
-	// si on est hors d'une boucle de {recherche}, cette balise est vide
1019
-	if (!$p->code) {
1020
-		$p->code = "''";
1021
-	}
1022
-
1023
-	$p->interdire_scripts = false;
1024
-
1025
-	return $p;
1002
+    $n = 0;
1003
+    $b = $p->id_boucle;
1004
+    $p->code = '';
1005
+    while ($b != '') {
1006
+        foreach ($p->boucles[$b]->criteres as $critere) {
1007
+            if ($critere->op == $motif) {
1008
+                $p->code = '$Pile[$SP' . (($n == 0) ? '' : "-$n") .
1009
+                    "]['$champ']";
1010
+                $b = '';
1011
+                break 2;
1012
+            }
1013
+        }
1014
+        $n++;
1015
+        $b = $p->boucles[$b]->id_parent;
1016
+    }
1017
+
1018
+    // si on est hors d'une boucle de {recherche}, cette balise est vide
1019
+    if (!$p->code) {
1020
+        $p->code = "''";
1021
+    }
1022
+
1023
+    $p->interdire_scripts = false;
1024
+
1025
+    return $p;
1026 1026
 }
1027 1027
 
1028 1028
 /**
@@ -1032,7 +1032,7 @@  discard block
 block discarded – undo
1032 1032
  * @return string Nom de la balise, avec indication de boucle explicite si présent.
1033 1033
  */
1034 1034
 function zbug_presenter_champ($p, $champ = '') {
1035
-	$balise = $champ ?: $p->nom_champ;
1036
-	$explicite = $p->nom_boucle ? $p->nom_boucle . ':' : '';
1037
-	return "#{$explicite}{$balise}";
1035
+    $balise = $champ ?: $p->nom_champ;
1036
+    $explicite = $p->nom_boucle ? $p->nom_boucle . ':' : '';
1037
+    return "#{$explicite}{$balise}";
1038 1038
 }
Please login to merge, or discard this patch.
ecrire/public/composer.php 1 patch
Indentation   +768 added lines, -768 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
  **/
19 19
 
20 20
 if (!defined('_ECRIRE_INC_VERSION')) {
21
-	return;
21
+    return;
22 22
 }
23 23
 
24 24
 include_spip('inc/texte');
@@ -42,234 +42,234 @@  discard block
 block discarded – undo
42 42
 
43 43
 function public_composer_dist($squelette, $mime_type, $gram, $source, string $connect = '') {
44 44
 
45
-	$skel = null;
46
-	$boucle = null;
47
-	$nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
48
-
49
-	//  si deja en memoire (INCLURE  a repetition) c'est bon.
50
-	if (function_exists($nom)) {
51
-		return $nom;
52
-	}
53
-
54
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
55
-		$GLOBALS['debug_objets']['courant'] = $nom;
56
-	}
57
-
58
-	$phpfile = sous_repertoire(_DIR_SKELS, '', false, true) . $nom . '.php';
59
-
60
-	// si squelette est deja compile et perenne, le charger
61
-	if (!squelette_obsolete($phpfile, $source)) {
62
-		include_once $phpfile;
63
-		#if (!squelette_obsolete($phpfile, $source)
64
-		#  AND lire_fichier ($phpfile, $skel_code,
65
-		#  array('critique' => 'oui', 'phpcheck' => 'oui'))){
66
-		## eval('?'.'>'.$skel_code);
67
-		#	 spip_log($skel_code, 'comp')
68
-		#}
69
-	}
70
-
71
-	if (file_exists($lib = $squelette . '_fonctions' . '.php')) {
72
-		include_once $lib;
73
-	}
74
-
75
-	// tester si le eval ci-dessus a mis le squelette en memoire
76
-
77
-	if (function_exists($nom)) {
78
-		return $nom;
79
-	}
80
-
81
-	// charger le source, si possible, et compiler
82
-	$skel_code = '';
83
-	if (lire_fichier($source, $skel)) {
84
-		$compiler = charger_fonction('compiler', 'public');
85
-		$skel_code = $compiler($skel, $nom, $gram, $source, $connect);
86
-	}
87
-
88
-	// Ne plus rien faire si le compilateur n'a pas pu operer.
89
-	if (!$skel_code) {
90
-		return false;
91
-	}
92
-
93
-	foreach ($skel_code as $id => $boucle) {
94
-		$f = $boucle->return;
95
-		try {
96
-			eval("return true; $f ;");
97
-		} catch (\ParseError $e) {
98
-			// Code syntaxiquement faux (critere etc mal programme')
99
-			$msg = _T('zbug_erreur_compilation') . ' | Line ' . $e->getLine() . ' : ' . $e->getMessage();
100
-			erreur_squelette($msg, $boucle);
101
-			// continuer pour trouver d'autres fautes eventuelles
102
-			// mais prevenir que c'est mort
103
-			$nom = '';
104
-		}
105
-
106
-		// Contexte de compil inutile a present
107
-		// (mais la derniere valeur de $boucle est utilisee ci-dessous)
108
-		$skel_code[$id] = $f;
109
-	}
110
-
111
-	$code = '';
112
-	if ($nom) {
113
-		// Si le code est bon, concatener et mettre en cache
114
-		if (function_exists($nom)) {
115
-			$code = squelette_traduit($skel, $source, $phpfile, $skel_code);
116
-		} else {
117
-			// code semantiquement faux: bug du compilateur
118
-			// $boucle est en fait ici la fct principale du squelette
119
-			$msg = _T('zbug_erreur_compilation');
120
-			erreur_squelette($msg, $boucle);
121
-			$nom = '';
122
-		}
123
-	}
124
-
125
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
126
-		// Tracer ce qui vient d'etre compile
127
-		$GLOBALS['debug_objets']['code'][$nom . 'tout'] = $code;
128
-
129
-		// si c'est ce que demande le debusqueur, lui passer la main
130
-		if (
131
-			$GLOBALS['debug_objets']['sourcefile']
132
-			and (_request('var_mode_objet') == $nom)
133
-			and (_request('var_mode_affiche') == 'code')
134
-		) {
135
-			erreur_squelette();
136
-		}
137
-	}
138
-
139
-	return $nom ?: false;
45
+    $skel = null;
46
+    $boucle = null;
47
+    $nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
48
+
49
+    //  si deja en memoire (INCLURE  a repetition) c'est bon.
50
+    if (function_exists($nom)) {
51
+        return $nom;
52
+    }
53
+
54
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
55
+        $GLOBALS['debug_objets']['courant'] = $nom;
56
+    }
57
+
58
+    $phpfile = sous_repertoire(_DIR_SKELS, '', false, true) . $nom . '.php';
59
+
60
+    // si squelette est deja compile et perenne, le charger
61
+    if (!squelette_obsolete($phpfile, $source)) {
62
+        include_once $phpfile;
63
+        #if (!squelette_obsolete($phpfile, $source)
64
+        #  AND lire_fichier ($phpfile, $skel_code,
65
+        #  array('critique' => 'oui', 'phpcheck' => 'oui'))){
66
+        ## eval('?'.'>'.$skel_code);
67
+        #	 spip_log($skel_code, 'comp')
68
+        #}
69
+    }
70
+
71
+    if (file_exists($lib = $squelette . '_fonctions' . '.php')) {
72
+        include_once $lib;
73
+    }
74
+
75
+    // tester si le eval ci-dessus a mis le squelette en memoire
76
+
77
+    if (function_exists($nom)) {
78
+        return $nom;
79
+    }
80
+
81
+    // charger le source, si possible, et compiler
82
+    $skel_code = '';
83
+    if (lire_fichier($source, $skel)) {
84
+        $compiler = charger_fonction('compiler', 'public');
85
+        $skel_code = $compiler($skel, $nom, $gram, $source, $connect);
86
+    }
87
+
88
+    // Ne plus rien faire si le compilateur n'a pas pu operer.
89
+    if (!$skel_code) {
90
+        return false;
91
+    }
92
+
93
+    foreach ($skel_code as $id => $boucle) {
94
+        $f = $boucle->return;
95
+        try {
96
+            eval("return true; $f ;");
97
+        } catch (\ParseError $e) {
98
+            // Code syntaxiquement faux (critere etc mal programme')
99
+            $msg = _T('zbug_erreur_compilation') . ' | Line ' . $e->getLine() . ' : ' . $e->getMessage();
100
+            erreur_squelette($msg, $boucle);
101
+            // continuer pour trouver d'autres fautes eventuelles
102
+            // mais prevenir que c'est mort
103
+            $nom = '';
104
+        }
105
+
106
+        // Contexte de compil inutile a present
107
+        // (mais la derniere valeur de $boucle est utilisee ci-dessous)
108
+        $skel_code[$id] = $f;
109
+    }
110
+
111
+    $code = '';
112
+    if ($nom) {
113
+        // Si le code est bon, concatener et mettre en cache
114
+        if (function_exists($nom)) {
115
+            $code = squelette_traduit($skel, $source, $phpfile, $skel_code);
116
+        } else {
117
+            // code semantiquement faux: bug du compilateur
118
+            // $boucle est en fait ici la fct principale du squelette
119
+            $msg = _T('zbug_erreur_compilation');
120
+            erreur_squelette($msg, $boucle);
121
+            $nom = '';
122
+        }
123
+    }
124
+
125
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
126
+        // Tracer ce qui vient d'etre compile
127
+        $GLOBALS['debug_objets']['code'][$nom . 'tout'] = $code;
128
+
129
+        // si c'est ce que demande le debusqueur, lui passer la main
130
+        if (
131
+            $GLOBALS['debug_objets']['sourcefile']
132
+            and (_request('var_mode_objet') == $nom)
133
+            and (_request('var_mode_affiche') == 'code')
134
+        ) {
135
+            erreur_squelette();
136
+        }
137
+    }
138
+
139
+    return $nom ?: false;
140 140
 }
141 141
 
142 142
 function squelette_traduit($squelette, $sourcefile, $phpfile, $boucles) {
143 143
 
144
-	$code = null;
145
-	// Le dernier index est '' (fonction principale)
146
-	$noms = substr(join(', ', array_keys($boucles)), 0, -2);
147
-	if (CODE_COMMENTE) {
148
-		$code = "
144
+    $code = null;
145
+    // Le dernier index est '' (fonction principale)
146
+    $noms = substr(join(', ', array_keys($boucles)), 0, -2);
147
+    if (CODE_COMMENTE) {
148
+        $code = "
149 149
 /*
150 150
  * Squelette : $sourcefile
151 151
  * Date :      " . gmdate('D, d M Y H:i:s', @filemtime($sourcefile)) . ' GMT
152 152
  * Compile :   ' . gmdate('D, d M Y H:i:s', time()) . ' GMT
153 153
  * ' . (!$boucles ? 'Pas de boucle' : ('Boucles :   ' . $noms)) . '
154 154
  */ ';
155
-	}
155
+    }
156 156
 
157
-	$code = '<' . "?php\n" . $code . join('', $boucles) . "\n";
158
-	if (!defined('_VAR_NOCACHE') or !_VAR_NOCACHE) {
159
-		ecrire_fichier($phpfile, $code);
160
-	}
157
+    $code = '<' . "?php\n" . $code . join('', $boucles) . "\n";
158
+    if (!defined('_VAR_NOCACHE') or !_VAR_NOCACHE) {
159
+        ecrire_fichier($phpfile, $code);
160
+    }
161 161
 
162
-	return $code;
162
+    return $code;
163 163
 }
164 164
 
165 165
 // Le squelette compile est-il trop vieux ?
166 166
 function squelette_obsolete($skel, $squelette) {
167
-	static $date_change = null;
168
-	// ne verifier la date de mes_fonctions et mes_options qu'une seule fois
169
-	// par hit
170
-	if (is_null($date_change)) {
171
-		if (@file_exists($fonc = 'mes_fonctions.php')) {
172
-			$date_change = @filemtime($fonc);
173
-		} # compatibilite
174
-		if (defined('_FILE_OPTIONS')) {
175
-			$date_change = max($date_change, @filemtime(_FILE_OPTIONS));
176
-		}
177
-	}
178
-
179
-	return (
180
-		(defined('_VAR_MODE') and in_array(_VAR_MODE, ['recalcul', 'preview', 'debug']))
181
-		or !@file_exists($skel)
182
-		or ((@file_exists($squelette) ? @filemtime($squelette) : 0)
183
-			> ($date = @filemtime($skel)))
184
-		or ($date_change > $date)
185
-	);
167
+    static $date_change = null;
168
+    // ne verifier la date de mes_fonctions et mes_options qu'une seule fois
169
+    // par hit
170
+    if (is_null($date_change)) {
171
+        if (@file_exists($fonc = 'mes_fonctions.php')) {
172
+            $date_change = @filemtime($fonc);
173
+        } # compatibilite
174
+        if (defined('_FILE_OPTIONS')) {
175
+            $date_change = max($date_change, @filemtime(_FILE_OPTIONS));
176
+        }
177
+    }
178
+
179
+    return (
180
+        (defined('_VAR_MODE') and in_array(_VAR_MODE, ['recalcul', 'preview', 'debug']))
181
+        or !@file_exists($skel)
182
+        or ((@file_exists($squelette) ? @filemtime($squelette) : 0)
183
+            > ($date = @filemtime($skel)))
184
+        or ($date_change > $date)
185
+    );
186 186
 }
187 187
 
188 188
 // Activer l'invalideur de session
189 189
 function invalideur_session(&$Cache, $code = null) {
190
-	$Cache['session'] = spip_session();
190
+    $Cache['session'] = spip_session();
191 191
 
192
-	return $code;
192
+    return $code;
193 193
 }
194 194
 
195 195
 
196 196
 function analyse_resultat_skel($nom, $cache, $corps, $source = '') {
197
-	static $filtres = [];
198
-	$headers = [];
199
-	$corps ??= '';
200
-
201
-	// Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
202
-	// note: on essaie d'attrapper aussi certains de ces entetes codes
203
-	// "a la main" dans les squelettes, mais evidemment sans exhaustivite
204
-	if (
205
-		stripos($corps, 'header') !== false
206
-		and preg_match_all(
207
-			'/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
208
-			$corps,
209
-			$regs,
210
-			PREG_SET_ORDER
211
-		)
212
-	) {
213
-		foreach ($regs as $r) {
214
-			$corps = str_replace($r[0], '', $corps);
215
-			# $j = Content-Type, et pas content-TYPE.
216
-			$j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
217
-
218
-			if ($j == 'X-Spip-Filtre' and isset($headers[$j])) {
219
-				$headers[$j] .= '|' . $r[3];
220
-			} else {
221
-				$headers[$j] = str_replace(['\\\\',"\\'",'\\"'], ['\\',"'",'"'], $r[3]);
222
-			}
223
-		}
224
-	}
225
-	// S'agit-il d'un resultat constant ou contenant du code php
226
-	$process_ins = (
227
-		strpos($corps, '<' . '?') === false
228
-		or
229
-		(strpos($corps, '<' . '?xml') !== false and
230
-			strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
231
-	)
232
-		? 'html'
233
-		: 'php';
234
-
235
-	$skel = [
236
-		'squelette' => $nom,
237
-		'source' => $source,
238
-		'process_ins' => $process_ins,
239
-		'invalideurs' => $cache,
240
-		'entetes' => $headers,
241
-		'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0
242
-	];
243
-
244
-	// traiter #FILTRE{} et filtres
245
-	if (!isset($filtres[$nom])) {
246
-		$filtres[$nom] = pipeline('declarer_filtres_squelettes', ['args' => $skel, 'data' => []]);
247
-	}
248
-	$filtres_headers = [];
249
-	if (isset($headers['X-Spip-Filtre']) and strlen($headers['X-Spip-Filtre'])) {
250
-		$filtres_headers = array_filter(explode('|', $headers['X-Spip-Filtre']));
251
-		unset($headers['X-Spip-Filtre']);
252
-	}
253
-	if (is_array($filtres[$nom]) || $filtres[$nom] instanceof \Countable ? count($filtres[$nom]) : 0 or count($filtres_headers)) {
254
-		include_spip('public/sandbox');
255
-		$corps = sandbox_filtrer_squelette($skel, $corps, $filtres_headers, $filtres[$nom]);
256
-
257
-		if ($process_ins == 'html') {
258
-			$skel['process_ins'] = (
259
-				strpos($corps, '<' . '?') === false
260
-				or
261
-				(strpos($corps, '<' . '?xml') !== false and
262
-					strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
263
-			)
264
-				? 'html'
265
-				: 'php';
266
-		}
267
-	}
268
-
269
-	$skel['entetes'] = $headers;
270
-	$skel['texte'] = $corps;
271
-
272
-	return $skel;
197
+    static $filtres = [];
198
+    $headers = [];
199
+    $corps ??= '';
200
+
201
+    // Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
202
+    // note: on essaie d'attrapper aussi certains de ces entetes codes
203
+    // "a la main" dans les squelettes, mais evidemment sans exhaustivite
204
+    if (
205
+        stripos($corps, 'header') !== false
206
+        and preg_match_all(
207
+            '/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
208
+            $corps,
209
+            $regs,
210
+            PREG_SET_ORDER
211
+        )
212
+    ) {
213
+        foreach ($regs as $r) {
214
+            $corps = str_replace($r[0], '', $corps);
215
+            # $j = Content-Type, et pas content-TYPE.
216
+            $j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
217
+
218
+            if ($j == 'X-Spip-Filtre' and isset($headers[$j])) {
219
+                $headers[$j] .= '|' . $r[3];
220
+            } else {
221
+                $headers[$j] = str_replace(['\\\\',"\\'",'\\"'], ['\\',"'",'"'], $r[3]);
222
+            }
223
+        }
224
+    }
225
+    // S'agit-il d'un resultat constant ou contenant du code php
226
+    $process_ins = (
227
+        strpos($corps, '<' . '?') === false
228
+        or
229
+        (strpos($corps, '<' . '?xml') !== false and
230
+            strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
231
+    )
232
+        ? 'html'
233
+        : 'php';
234
+
235
+    $skel = [
236
+        'squelette' => $nom,
237
+        'source' => $source,
238
+        'process_ins' => $process_ins,
239
+        'invalideurs' => $cache,
240
+        'entetes' => $headers,
241
+        'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0
242
+    ];
243
+
244
+    // traiter #FILTRE{} et filtres
245
+    if (!isset($filtres[$nom])) {
246
+        $filtres[$nom] = pipeline('declarer_filtres_squelettes', ['args' => $skel, 'data' => []]);
247
+    }
248
+    $filtres_headers = [];
249
+    if (isset($headers['X-Spip-Filtre']) and strlen($headers['X-Spip-Filtre'])) {
250
+        $filtres_headers = array_filter(explode('|', $headers['X-Spip-Filtre']));
251
+        unset($headers['X-Spip-Filtre']);
252
+    }
253
+    if (is_array($filtres[$nom]) || $filtres[$nom] instanceof \Countable ? count($filtres[$nom]) : 0 or count($filtres_headers)) {
254
+        include_spip('public/sandbox');
255
+        $corps = sandbox_filtrer_squelette($skel, $corps, $filtres_headers, $filtres[$nom]);
256
+
257
+        if ($process_ins == 'html') {
258
+            $skel['process_ins'] = (
259
+                strpos($corps, '<' . '?') === false
260
+                or
261
+                (strpos($corps, '<' . '?xml') !== false and
262
+                    strpos(str_replace('<' . '?xml', '', $corps), '<' . '?') === false)
263
+            )
264
+                ? 'html'
265
+                : 'php';
266
+        }
267
+    }
268
+
269
+    $skel['entetes'] = $headers;
270
+    $skel['texte'] = $corps;
271
+
272
+    return $skel;
273 273
 }
274 274
 
275 275
 //
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 inserer_balise_dynamique(balise_%s_dyn(%s), array(%s));
284 284
 if ($lang_select) lang_select();
285 285
 ?'
286
-	. '>');
286
+    . '>');
287 287
 
288 288
 /**
289 289
  * Synthétise une balise dynamique : crée l'appel à l'inclusion
@@ -303,35 +303,35 @@  discard block
 block discarded – undo
303 303
  *     Code PHP pour inclure le squelette de la balise dynamique
304 304
  **/
305 305
 function synthetiser_balise_dynamique($nom, $args, $file, $context_compil) {
306
-	if (
307
-		strncmp($file, '/', 1) !== 0
308
-		// pas de lien symbolique sous Windows
309
-		and !(stristr(PHP_OS, 'WIN') and strpos($file, ':') !== false)
310
-	) {
311
-		$file = './" . _DIR_RACINE . "' . $file;
312
-	}
313
-
314
-	$lang = $context_compil[4];
315
-	if (preg_match(',\W,', $lang)) {
316
-		$lang = '';
317
-	}
318
-
319
-	$args = array_map('argumenter_squelette', $args);
320
-	if (!empty($context_compil['appel_php_depuis_modele'])) {
321
-		$args[0] = 'arguments_balise_dyn_depuis_modele(' . $args[0] . ')';
322
-	}
323
-	$args = join(', ', $args);
324
-
325
-	$r = sprintf(
326
-		CODE_INCLURE_BALISE,
327
-		$file,
328
-		$lang,
329
-		$nom,
330
-		$args,
331
-		join(', ', array_map('_q', $context_compil))
332
-	);
333
-
334
-	return $r;
306
+    if (
307
+        strncmp($file, '/', 1) !== 0
308
+        // pas de lien symbolique sous Windows
309
+        and !(stristr(PHP_OS, 'WIN') and strpos($file, ':') !== false)
310
+    ) {
311
+        $file = './" . _DIR_RACINE . "' . $file;
312
+    }
313
+
314
+    $lang = $context_compil[4];
315
+    if (preg_match(',\W,', $lang)) {
316
+        $lang = '';
317
+    }
318
+
319
+    $args = array_map('argumenter_squelette', $args);
320
+    if (!empty($context_compil['appel_php_depuis_modele'])) {
321
+        $args[0] = 'arguments_balise_dyn_depuis_modele(' . $args[0] . ')';
322
+    }
323
+    $args = join(', ', $args);
324
+
325
+    $r = sprintf(
326
+        CODE_INCLURE_BALISE,
327
+        $file,
328
+        $lang,
329
+        $nom,
330
+        $args,
331
+        join(', ', array_map('_q', $context_compil))
332
+    );
333
+
334
+    return $r;
335 335
 }
336 336
 
337 337
 /**
@@ -349,18 +349,18 @@  discard block
 block discarded – undo
349 349
  **/
350 350
 function argumenter_squelette($v) {
351 351
 
352
-	if (is_object($v)) {
353
-		return var_export($v, true);
354
-	} elseif (!is_array($v)) {
355
-		return "'" . texte_script((string) $v) . "'";
356
-	} else {
357
-		$out = [];
358
-		foreach ($v as $k => $val) {
359
-			$out [] = argumenter_squelette($k) . '=>' . argumenter_squelette($val);
360
-		}
361
-
362
-		return 'array(' . join(', ', $out) . ')';
363
-	}
352
+    if (is_object($v)) {
353
+        return var_export($v, true);
354
+    } elseif (!is_array($v)) {
355
+        return "'" . texte_script((string) $v) . "'";
356
+    } else {
357
+        $out = [];
358
+        foreach ($v as $k => $val) {
359
+            $out [] = argumenter_squelette($k) . '=>' . argumenter_squelette($val);
360
+        }
361
+
362
+        return 'array(' . join(', ', $out) . ')';
363
+    }
364 364
 }
365 365
 
366 366
 /**
@@ -379,13 +379,13 @@  discard block
 block discarded – undo
379 379
  * @return string
380 380
  */
381 381
 function executer_balise_dynamique_dans_un_modele(...$args) {
382
-	if (test_espace_prive()) {
383
-		return executer_balise_dynamique(...$args);
384
-	}
385
-	else {
386
-		$str_args = base64_encode(serialize($args));
387
-		return "<?" . "php \$_zargs=unserialize(base64_decode('$str_args'));echo executer_balise_dynamique(...\$_zargs); ?".">\n";
388
-	}
382
+    if (test_espace_prive()) {
383
+        return executer_balise_dynamique(...$args);
384
+    }
385
+    else {
386
+        $str_args = base64_encode(serialize($args));
387
+        return "<?" . "php \$_zargs=unserialize(base64_decode('$str_args'));echo executer_balise_dynamique(...\$_zargs); ?".">\n";
388
+    }
389 389
 }
390 390
 
391 391
 
@@ -416,87 +416,87 @@  discard block
 block discarded – undo
416 416
  *     Code PHP d'exécutant l'inclusion du squelette (ou texte) de la balise dynamique
417 417
  **/
418 418
 function executer_balise_dynamique($nom, $args, $context_compil) {
419
-	/** @var string Nom de la balise à charger (balise demandée ou balise générique) */
420
-	$nom_balise = $nom;
421
-	/** @var string Nom de la balise générique (si utilisée) */
422
-	$nom_balise_generique = '';
423
-
424
-	$appel_php_depuis_modele = false;
425
-	if (
426
-		is_array($context_compil)
427
-		and !is_numeric($context_compil[3])
428
-		and empty($context_compil[0])
429
-		and empty($context_compil[1])
430
-		and empty($context_compil[2])
431
-		and empty($context_compil[3])
432
-	) {
433
-		$appel_php_depuis_modele = true;
434
-	}
435
-
436
-	if (!$fonction_balise = charger_fonction($nom_balise, 'balise', true)) {
437
-		// Calculer un nom générique (ie. 'formulaire_' dans 'formulaire_editer_article')
438
-		if ($balise_generique = chercher_balise_generique($nom)) {
439
-			// injecter en premier arg le nom de la balise
440
-			array_unshift($args, $nom);
441
-			$nom_balise_generique = $balise_generique['nom_generique'];
442
-			$fonction_balise = $balise_generique['fonction_generique'];
443
-			$nom_balise = $nom_balise_generique;
444
-		}
445
-		unset($balise_generique);
446
-	}
447
-
448
-	if (!$fonction_balise) {
449
-		$msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
450
-		erreur_squelette($msg, $context_compil);
451
-
452
-		return '';
453
-	}
454
-
455
-	// retrouver le fichier qui a déclaré la fonction
456
-	// même si la fonction dynamique est déclarée dans un fichier de fonctions.
457
-	// Attention sous windows, getFileName() retourne un antislash.
458
-	$reflector = new ReflectionFunction($fonction_balise);
459
-	$file = str_replace('\\', '/', $reflector->getFileName());
460
-	if (strncmp($file, str_replace('\\', '/', _ROOT_RACINE), strlen(_ROOT_RACINE)) === 0) {
461
-		$file = substr($file, strlen(_ROOT_RACINE));
462
-	}
463
-
464
-	// Y a-t-il une fonction de traitement des arguments ?
465
-	$f = 'balise_' . $nom_balise . '_stat';
466
-
467
-	$r = !function_exists($f) ? $args : $f($args, $context_compil);
468
-
469
-	if (!is_array($r)) {
470
-		return $r;
471
-	}
472
-
473
-	// verifier que la fonction dyn est la,
474
-	// sinon se replier sur la generique si elle existe
475
-	if (!function_exists('balise_' . $nom_balise . '_dyn')) {
476
-		if (
477
-			$balise_generique = chercher_balise_generique($nom)
478
-			and $nom_balise_generique = $balise_generique['nom_generique']
479
-			and $file = include_spip('balise/' . strtolower($nom_balise_generique))
480
-			and function_exists('balise_' . $nom_balise_generique . '_dyn')
481
-		) {
482
-			// et lui injecter en premier arg le nom de la balise
483
-			array_unshift($r, $nom);
484
-			$nom_balise = $nom_balise_generique;
485
-			if (!_DIR_RESTREINT) {
486
-				$file = _DIR_RESTREINT_ABS . $file;
487
-			}
488
-		} else {
489
-			$msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
490
-			erreur_squelette($msg, $context_compil);
491
-
492
-			return '';
493
-		}
494
-	}
495
-
496
-	if ($appel_php_depuis_modele) {
497
-		$context_compil['appel_php_depuis_modele'] = true;
498
-	}
499
-	return synthetiser_balise_dynamique($nom_balise, $r, $file, $context_compil);
419
+    /** @var string Nom de la balise à charger (balise demandée ou balise générique) */
420
+    $nom_balise = $nom;
421
+    /** @var string Nom de la balise générique (si utilisée) */
422
+    $nom_balise_generique = '';
423
+
424
+    $appel_php_depuis_modele = false;
425
+    if (
426
+        is_array($context_compil)
427
+        and !is_numeric($context_compil[3])
428
+        and empty($context_compil[0])
429
+        and empty($context_compil[1])
430
+        and empty($context_compil[2])
431
+        and empty($context_compil[3])
432
+    ) {
433
+        $appel_php_depuis_modele = true;
434
+    }
435
+
436
+    if (!$fonction_balise = charger_fonction($nom_balise, 'balise', true)) {
437
+        // Calculer un nom générique (ie. 'formulaire_' dans 'formulaire_editer_article')
438
+        if ($balise_generique = chercher_balise_generique($nom)) {
439
+            // injecter en premier arg le nom de la balise
440
+            array_unshift($args, $nom);
441
+            $nom_balise_generique = $balise_generique['nom_generique'];
442
+            $fonction_balise = $balise_generique['fonction_generique'];
443
+            $nom_balise = $nom_balise_generique;
444
+        }
445
+        unset($balise_generique);
446
+    }
447
+
448
+    if (!$fonction_balise) {
449
+        $msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
450
+        erreur_squelette($msg, $context_compil);
451
+
452
+        return '';
453
+    }
454
+
455
+    // retrouver le fichier qui a déclaré la fonction
456
+    // même si la fonction dynamique est déclarée dans un fichier de fonctions.
457
+    // Attention sous windows, getFileName() retourne un antislash.
458
+    $reflector = new ReflectionFunction($fonction_balise);
459
+    $file = str_replace('\\', '/', $reflector->getFileName());
460
+    if (strncmp($file, str_replace('\\', '/', _ROOT_RACINE), strlen(_ROOT_RACINE)) === 0) {
461
+        $file = substr($file, strlen(_ROOT_RACINE));
462
+    }
463
+
464
+    // Y a-t-il une fonction de traitement des arguments ?
465
+    $f = 'balise_' . $nom_balise . '_stat';
466
+
467
+    $r = !function_exists($f) ? $args : $f($args, $context_compil);
468
+
469
+    if (!is_array($r)) {
470
+        return $r;
471
+    }
472
+
473
+    // verifier que la fonction dyn est la,
474
+    // sinon se replier sur la generique si elle existe
475
+    if (!function_exists('balise_' . $nom_balise . '_dyn')) {
476
+        if (
477
+            $balise_generique = chercher_balise_generique($nom)
478
+            and $nom_balise_generique = $balise_generique['nom_generique']
479
+            and $file = include_spip('balise/' . strtolower($nom_balise_generique))
480
+            and function_exists('balise_' . $nom_balise_generique . '_dyn')
481
+        ) {
482
+            // et lui injecter en premier arg le nom de la balise
483
+            array_unshift($r, $nom);
484
+            $nom_balise = $nom_balise_generique;
485
+            if (!_DIR_RESTREINT) {
486
+                $file = _DIR_RESTREINT_ABS . $file;
487
+            }
488
+        } else {
489
+            $msg = ['zbug_balise_inexistante', ['from' => 'CVT', 'balise' => $nom]];
490
+            erreur_squelette($msg, $context_compil);
491
+
492
+            return '';
493
+        }
494
+    }
495
+
496
+    if ($appel_php_depuis_modele) {
497
+        $context_compil['appel_php_depuis_modele'] = true;
498
+    }
499
+    return synthetiser_balise_dynamique($nom_balise, $r, $file, $context_compil);
500 500
 }
501 501
 
502 502
 /**
@@ -511,23 +511,23 @@  discard block
 block discarded – undo
511 511
  * @return array|null
512 512
  */
513 513
 function chercher_balise_generique($nom) {
514
-	if (false === strpos($nom, '_')) {
515
-		return null;
516
-	}
517
-	$nom_generique = $nom;
518
-	while (false !== ($p = strrpos($nom_generique, '_'))) {
519
-		$nom_generique = substr($nom_generique, 0, $p + 1);
520
-		$fonction_generique = charger_fonction($nom_generique, 'balise', true);
521
-		if ($fonction_generique) {
522
-			return [
523
-				'nom' => $nom,
524
-				'nom_generique' => $nom_generique,
525
-				'fonction_generique' => $fonction_generique,
526
-			];
527
-		}
528
-		$nom_generique = substr($nom_generique, 0, -1);
529
-	}
530
-	return null;
514
+    if (false === strpos($nom, '_')) {
515
+        return null;
516
+    }
517
+    $nom_generique = $nom;
518
+    while (false !== ($p = strrpos($nom_generique, '_'))) {
519
+        $nom_generique = substr($nom_generique, 0, $p + 1);
520
+        $fonction_generique = charger_fonction($nom_generique, 'balise', true);
521
+        if ($fonction_generique) {
522
+            return [
523
+                'nom' => $nom,
524
+                'nom_generique' => $nom_generique,
525
+                'fonction_generique' => $fonction_generique,
526
+            ];
527
+        }
528
+        $nom_generique = substr($nom_generique, 0, -1);
529
+    }
530
+    return null;
531 531
 }
532 532
 
533 533
 
@@ -551,50 +551,50 @@  discard block
 block discarded – undo
551 551
  * @return null;
552 552
  **/
553 553
 function lang_select_public($lang, $lang_select, $titre = null) {
554
-	// Cas 1. forcer_lang = true et pas de critere {lang_select}
555
-	if (
556
-		isset($GLOBALS['forcer_lang']) and $GLOBALS['forcer_lang']
557
-		and $lang_select !== 'oui'
558
-	) {
559
-		$lang = $GLOBALS['spip_lang'];
560
-	} // Cas 2. l'objet n'a pas de langue definie (ou definie a '')
561
-	elseif (!strlen($lang)) {
562
-		$lang = $GLOBALS['spip_lang'];
563
-	} // Cas 3. l'objet est multilingue !
564
-	elseif (
565
-		$lang_select !== 'oui'
566
-		and strlen($titre) > 10
567
-		and strpos($titre, '<multi>') !== false
568
-		and strpos(echappe_html($titre), '<multi>') !== false
569
-	) {
570
-		$lang = $GLOBALS['spip_lang'];
571
-	}
572
-
573
-	// faire un lang_select() eventuellement sur la langue inchangee
574
-	lang_select($lang);
575
-
576
-	return;
554
+    // Cas 1. forcer_lang = true et pas de critere {lang_select}
555
+    if (
556
+        isset($GLOBALS['forcer_lang']) and $GLOBALS['forcer_lang']
557
+        and $lang_select !== 'oui'
558
+    ) {
559
+        $lang = $GLOBALS['spip_lang'];
560
+    } // Cas 2. l'objet n'a pas de langue definie (ou definie a '')
561
+    elseif (!strlen($lang)) {
562
+        $lang = $GLOBALS['spip_lang'];
563
+    } // Cas 3. l'objet est multilingue !
564
+    elseif (
565
+        $lang_select !== 'oui'
566
+        and strlen($titre) > 10
567
+        and strpos($titre, '<multi>') !== false
568
+        and strpos(echappe_html($titre), '<multi>') !== false
569
+    ) {
570
+        $lang = $GLOBALS['spip_lang'];
571
+    }
572
+
573
+    // faire un lang_select() eventuellement sur la langue inchangee
574
+    lang_select($lang);
575
+
576
+    return;
577 577
 }
578 578
 
579 579
 
580 580
 // Si un tableau &doublons[articles] est passe en parametre,
581 581
 // il faut le nettoyer car il pourrait etre injecte en SQL
582 582
 function nettoyer_env_doublons($envd) {
583
-	foreach ($envd as $table => $liste) {
584
-		$n = '';
585
-		foreach (explode(',', $liste) as $val) {
586
-			if ($a = intval($val) and $val === strval($a)) {
587
-				$n .= ',' . $val;
588
-			}
589
-		}
590
-		if (strlen($n)) {
591
-			$envd[$table] = $n;
592
-		} else {
593
-			unset($envd[$table]);
594
-		}
595
-	}
596
-
597
-	return $envd;
583
+    foreach ($envd as $table => $liste) {
584
+        $n = '';
585
+        foreach (explode(',', $liste) as $val) {
586
+            if ($a = intval($val) and $val === strval($a)) {
587
+                $n .= ',' . $val;
588
+            }
589
+        }
590
+        if (strlen($n)) {
591
+            $envd[$table] = $n;
592
+        } else {
593
+            unset($envd[$table]);
594
+        }
595
+    }
596
+
597
+    return $envd;
598 598
 }
599 599
 
600 600
 /**
@@ -613,21 +613,21 @@  discard block
 block discarded – undo
613 613
  *     Opérateur trouvé (SELF ou SUBSELECT) sinon false.
614 614
  **/
615 615
 function match_self($w) {
616
-	if (is_string($w)) {
617
-		return false;
618
-	}
619
-	if (is_array($w)) {
620
-		if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
621
-			return $w;
622
-		}
623
-		foreach (array_filter($w, 'is_array') as $sw) {
624
-			if ($m = match_self($sw)) {
625
-				return $m;
626
-			}
627
-		}
628
-	}
629
-
630
-	return false;
616
+    if (is_string($w)) {
617
+        return false;
618
+    }
619
+    if (is_array($w)) {
620
+        if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
621
+            return $w;
622
+        }
623
+        foreach (array_filter($w, 'is_array') as $sw) {
624
+            if ($m = match_self($sw)) {
625
+                return $m;
626
+            }
627
+        }
628
+    }
629
+
630
+    return false;
631 631
 }
632 632
 
633 633
 /**
@@ -643,16 +643,16 @@  discard block
 block discarded – undo
643 643
  *     est remplacée par son code.
644 644
  **/
645 645
 function remplace_sous_requete($w, $sousrequete) {
646
-	if (is_array($w)) {
647
-		if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
648
-			return $sousrequete;
649
-		}
650
-		foreach ($w as $k => $sw) {
651
-			$w[$k] = remplace_sous_requete($sw, $sousrequete);
652
-		}
653
-	}
654
-
655
-	return $w;
646
+    if (is_array($w)) {
647
+        if (in_array(reset($w), ['SELF', 'SUBSELECT'])) {
648
+            return $sousrequete;
649
+        }
650
+        foreach ($w as $k => $sw) {
651
+            $w[$k] = remplace_sous_requete($sw, $sousrequete);
652
+        }
653
+    }
654
+
655
+    return $w;
656 656
 }
657 657
 
658 658
 /**
@@ -666,17 +666,17 @@  discard block
 block discarded – undo
666 666
  *     - Conditions avec des sous requêtes
667 667
  **/
668 668
 function trouver_sous_requetes($where) {
669
-	$where_simples = [];
670
-	$where_sous = [];
671
-	foreach ($where as $k => $w) {
672
-		if (match_self($w)) {
673
-			$where_sous[$k] = $w;
674
-		} else {
675
-			$where_simples[$k] = $w;
676
-		}
677
-	}
678
-
679
-	return [$where_simples, $where_sous];
669
+    $where_simples = [];
670
+    $where_sous = [];
671
+    foreach ($where as $k => $w) {
672
+        if (match_self($w)) {
673
+            $where_sous[$k] = $w;
674
+        } else {
675
+            $where_simples[$k] = $w;
676
+        }
677
+    }
678
+
679
+    return [$where_simples, $where_sous];
680 680
 }
681 681
 
682 682
 
@@ -702,292 +702,292 @@  discard block
 block discarded – undo
702 702
  * @return resource
703 703
  */
704 704
 function calculer_select(
705
-	$select = [],
706
-	$from = [],
707
-	$from_type = [],
708
-	$where = [],
709
-	$join = [],
710
-	$groupby = [],
711
-	$orderby = [],
712
-	$limit = '',
713
-	$having = [],
714
-	$table = '',
715
-	$id = '',
716
-	$serveur = '',
717
-	$requeter = true
705
+    $select = [],
706
+    $from = [],
707
+    $from_type = [],
708
+    $where = [],
709
+    $join = [],
710
+    $groupby = [],
711
+    $orderby = [],
712
+    $limit = '',
713
+    $having = [],
714
+    $table = '',
715
+    $id = '',
716
+    $serveur = '',
717
+    $requeter = true
718 718
 ) {
719 719
 
720
-	// retirer les criteres vides:
721
-	// {X ?} avec X absent de l'URL
722
-	// {par #ENV{X}} avec X absent de l'URL
723
-	// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
724
-	$menage = false;
725
-	foreach ($where as $k => $v) {
726
-		if (is_array($v) and count($v)) {
727
-			if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
728
-				$op = false;
729
-			} elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
730
-				$op = false;
731
-			} else {
732
-				$op = $v[0] ?: $v;
733
-			}
734
-		} else {
735
-			$op = $v;
736
-		}
737
-		if ((!$op) or ($op == 1) or ($op == '0=0')) {
738
-			unset($where[$k]);
739
-			$menage = true;
740
-		}
741
-	}
742
-
743
-	// evacuer les eventuels groupby vide issus d'un calcul dynamique
744
-	$groupby = array_diff($groupby, ['']);
745
-
746
-	// remplacer les sous requetes recursives au calcul
747
-	[$where_simples, $where_sous] = trouver_sous_requetes($where);
748
-	foreach ($where_sous as $k => $w) {
749
-		$menage = true;
750
-		// on recupere la sous requete
751
-		$sous = match_self($w);
752
-		if ($sous[0] == 'SELF') {
753
-			// c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
754
-			array_push($where_simples, $sous[2]);
755
-			$wheresub = [
756
-				$sous[2],
757
-				'0=0'
758
-			]; // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
759
-			$jsub = $join;
760
-			// trouver les jointures utiles a
761
-			// reinjecter dans le where de la sous requete les conditions supplementaires des jointures qui y sont mentionnees
762
-			// ie L1.objet='article'
763
-			// on construit le where une fois, puis on ajoute les where complentaires si besoin, et on reconstruit le where en fonction
764
-			$i = 0;
765
-			do {
766
-				$where[$k] = remplace_sous_requete($w, '(' . calculer_select(
767
-					[$sous[1] . ' AS id'],
768
-					$from,
769
-					$from_type,
770
-					$wheresub,
771
-					$jsub,
772
-					[],
773
-					[],
774
-					'',
775
-					$having,
776
-					$table,
777
-					$id,
778
-					$serveur,
779
-					false
780
-				) . ')');
781
-				if (!$i) {
782
-					$i = 1;
783
-					$wherestring = calculer_where_to_string($where[$k]);
784
-					foreach ($join as $cle => $wj) {
785
-						if (
786
-							(is_countable($wj) ? count($wj) : 0) == 4
787
-							and strpos($wherestring, (string) "{$cle}.") !== false
788
-						) {
789
-							$i = 0;
790
-							$wheresub[] = $wj[3];
791
-							unset($jsub[$cle][3]);
792
-						}
793
-					}
794
-				}
795
-			} while ($i++ < 1);
796
-		}
797
-		if ($sous[0] == 'SUBSELECT') {
798
-			// c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
799
-			array_push($where_simples, $sous[3]); // est-ce utile dans ce cas ?
800
-			$where[$k] = remplace_sous_requete($w, '(' . calculer_select(
801
-				$sous[1], # select
802
-				$sous[2], #from
803
-				[], #from_type
804
-				$sous[3] ? (is_array($sous[3]) ? $sous[3] : [$sous[3]]) : [],
805
-				#where, qui peut etre de la forme string comme dans sql_select
806
-					[], #join
807
-				$sous[4] ?: [], #groupby
808
-				$sous[5] ?: [], #orderby
809
-				$sous[6], #limit
810
-				$sous[7] ?: [], #having
811
-				$table,
812
-				$id,
813
-				$serveur,
814
-				false
815
-			) . ')');
816
-		}
817
-		array_pop($where_simples);
818
-	}
819
-
820
-	foreach ($having as $k => $v) {
821
-		if ((!$v) or ($v == 1) or ($v == '0=0')) {
822
-			unset($having[$k]);
823
-		}
824
-	}
825
-
826
-	// Installer les jointures.
827
-	// Retirer celles seulement utiles aux criteres finalement absents mais
828
-	// parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
829
-	// si elle est seulement utile a Ln+1 elle meme inutile
830
-
831
-	$afrom = [];
832
-	$equiv = [];
833
-	$k = count($join);
834
-	foreach (array_reverse($join, true) as $cledef => $j) {
835
-		$cle = $cledef;
836
-		// le format de join est :
837
-		// array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
838
-		$join[$cle] = array_values($join[$cle]); // recalculer les cles car des unset ont pu perturber
839
-		if (count($join[$cle]) == 2) {
840
-			$join[$cle][] = $join[$cle][1];
841
-		}
842
-		if ((is_array($join[$cle]) || $join[$cle] instanceof \Countable ? count($join[$cle]) : 0) == 3) {
843
-			$join[$cle][] = '';
844
-		}
845
-		[$t, $c, $carr, $and] = $join[$cle];
846
-		// si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
847
-		// pour compat avec ancienne convention
848
-		if (is_numeric($cle)) {
849
-			$cle = "L$k";
850
-		}
851
-		$cle_where_lie = "JOIN-$cle";
852
-		if (
853
-			!$menage
854
-			or isset($afrom[$cle])
855
-			or calculer_jointnul($cle, $select)
856
-			or calculer_jointnul($cle, array_diff_key($join, [$cle => $join[$cle]]))
857
-			or calculer_jointnul($cle, $having)
858
-			or calculer_jointnul($cle, array_diff_key($where_simples, [$cle_where_lie => '']))
859
-		) {
860
-			// corriger les references non explicites dans select
861
-			// ou groupby
862
-			foreach ($select as $i => $s) {
863
-				if ($s == $c) {
864
-					$select[$i] = "$cle.$c AS $c";
865
-					break;
866
-				}
867
-			}
868
-			foreach ($groupby as $i => $g) {
869
-				if ($g == $c) {
870
-					$groupby[$i] = "$cle.$c";
871
-					break;
872
-				}
873
-			}
874
-			// on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
875
-			// sans recours a preg_match
876
-			// un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
877
-			$afrom[$t][$cle] = [
878
-				"\n" .
879
-				($from_type[$cle] ?? 'INNER') . ' JOIN',
880
-				$from[$cle],
881
-				"AS $cle",
882
-				'ON (',
883
-				"$cle.$c",
884
-				'=',
885
-				"$t.$carr",
886
-				($and ? 'AND ' . $and : '') .
887
-				')'
888
-			];
889
-			if (isset($afrom[$cle])) {
890
-				$afrom[$t] = $afrom[$t] + $afrom[$cle];
891
-				unset($afrom[$cle]);
892
-			}
893
-			$equiv[] = $carr;
894
-		} else {
895
-			unset($join[$cledef]);
896
-			if (isset($where_simples[$cle_where_lie])) {
897
-				unset($where_simples[$cle_where_lie]);
898
-				unset($where[$cle_where_lie]);
899
-			}
900
-		}
901
-		unset($from[$cle]);
902
-		$k--;
903
-	}
904
-
905
-	if (count($afrom)) {
906
-		// Regarder si la table principale ne sert finalement a rien comme dans
907
-		//<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
908
-		//<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
909
-		//<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
910
-		// ou dans
911
-		//<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
912
-		// qui comporte plusieurs jointures
913
-		// ou dans
914
-		// <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
915
-		// <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
916
-		// penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
917
-		// <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
918
-		// penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
919
-		// <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
920
-
921
-		$t = key($from);
922
-		$c = current($from);
923
-		reset($from);
924
-		$e = '/\b(' . "$t\\." . join('|' . $t . '\.', $equiv) . ')\b/';
925
-		if (
926
-			!(strpos($t, ' ') or // jointure des le depart cf boucle_doc
927
-				calculer_jointnul($t, $select, $e) or
928
-				calculer_jointnul($t, $join, $e) or
929
-				calculer_jointnul($t, $where, $e) or
930
-				calculer_jointnul($t, $orderby, $e) or
931
-				calculer_jointnul($t, $groupby, $e) or
932
-				calculer_jointnul($t, $having, $e))
933
-			&& count($afrom[$t])
934
-		) {
935
-			$nfrom = reset($afrom[$t]);
936
-			$nt = array_key_first($afrom[$t]);
937
-			unset($from[$t]);
938
-			$from[$nt] = $nfrom[1];
939
-			unset($afrom[$t][$nt]);
940
-			$afrom[$nt] = $afrom[$t];
941
-			unset($afrom[$t]);
942
-			$e = '/\b' . preg_quote($nfrom[6]) . '\b/';
943
-			$t = $nfrom[4];
944
-			$alias = '';
945
-			// verifier que les deux cles sont homonymes, sinon installer un alias dans le select
946
-			$oldcle = explode('.', $nfrom[6]);
947
-			$oldcle = end($oldcle);
948
-			$newcle = explode('.', $nfrom[4]);
949
-			$newcle = end($newcle);
950
-			if ($newcle != $oldcle) {
951
-				// si l'ancienne cle etait deja dans le select avec un AS
952
-				// reprendre simplement ce AS
953
-				$as = '/\b' . preg_quote($nfrom[6]) . '\s+(AS\s+\w+)\b/';
954
-				if (preg_match($as, implode(',', $select), $m)) {
955
-					$alias = '';
956
-				} else {
957
-					$alias = ', ' . $nfrom[4] . " AS $oldcle";
958
-				}
959
-			}
960
-			$select = remplacer_jointnul($t . $alias, $select, $e);
961
-			$join = remplacer_jointnul($t, $join, $e);
962
-			$where = remplacer_jointnul($t, $where, $e);
963
-			$having = remplacer_jointnul($t, $having, $e);
964
-			$groupby = remplacer_jointnul($t, $groupby, $e);
965
-			$orderby = remplacer_jointnul($t, $orderby, $e);
966
-		}
967
-		$from = reinjecte_joint($afrom, $from);
968
-	}
969
-	if (empty($GLOBALS['debug']) or !is_array($GLOBALS['debug'])) {
970
-		$wasdebug = empty($GLOBALS['debug']) ? false : $GLOBALS['debug'];
971
-		$GLOBALS['debug'] = [];
972
-		if ($wasdebug) {
973
-			$GLOBALS['debug']['debug'] = true;
974
-		}
975
-	}
976
-	$GLOBALS['debug']['aucasou'] = [$table, $id, $serveur, $requeter];
977
-	$r = sql_select(
978
-		$select,
979
-		$from,
980
-		$where,
981
-		$groupby,
982
-		array_filter($orderby),
983
-		$limit,
984
-		$having,
985
-		$serveur,
986
-		$requeter
987
-	);
988
-	unset($GLOBALS['debug']['aucasou']);
989
-
990
-	return $r;
720
+    // retirer les criteres vides:
721
+    // {X ?} avec X absent de l'URL
722
+    // {par #ENV{X}} avec X absent de l'URL
723
+    // IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
724
+    $menage = false;
725
+    foreach ($where as $k => $v) {
726
+        if (is_array($v) and count($v)) {
727
+            if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
728
+                $op = false;
729
+            } elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
730
+                $op = false;
731
+            } else {
732
+                $op = $v[0] ?: $v;
733
+            }
734
+        } else {
735
+            $op = $v;
736
+        }
737
+        if ((!$op) or ($op == 1) or ($op == '0=0')) {
738
+            unset($where[$k]);
739
+            $menage = true;
740
+        }
741
+    }
742
+
743
+    // evacuer les eventuels groupby vide issus d'un calcul dynamique
744
+    $groupby = array_diff($groupby, ['']);
745
+
746
+    // remplacer les sous requetes recursives au calcul
747
+    [$where_simples, $where_sous] = trouver_sous_requetes($where);
748
+    foreach ($where_sous as $k => $w) {
749
+        $menage = true;
750
+        // on recupere la sous requete
751
+        $sous = match_self($w);
752
+        if ($sous[0] == 'SELF') {
753
+            // c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
754
+            array_push($where_simples, $sous[2]);
755
+            $wheresub = [
756
+                $sous[2],
757
+                '0=0'
758
+            ]; // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
759
+            $jsub = $join;
760
+            // trouver les jointures utiles a
761
+            // reinjecter dans le where de la sous requete les conditions supplementaires des jointures qui y sont mentionnees
762
+            // ie L1.objet='article'
763
+            // on construit le where une fois, puis on ajoute les where complentaires si besoin, et on reconstruit le where en fonction
764
+            $i = 0;
765
+            do {
766
+                $where[$k] = remplace_sous_requete($w, '(' . calculer_select(
767
+                    [$sous[1] . ' AS id'],
768
+                    $from,
769
+                    $from_type,
770
+                    $wheresub,
771
+                    $jsub,
772
+                    [],
773
+                    [],
774
+                    '',
775
+                    $having,
776
+                    $table,
777
+                    $id,
778
+                    $serveur,
779
+                    false
780
+                ) . ')');
781
+                if (!$i) {
782
+                    $i = 1;
783
+                    $wherestring = calculer_where_to_string($where[$k]);
784
+                    foreach ($join as $cle => $wj) {
785
+                        if (
786
+                            (is_countable($wj) ? count($wj) : 0) == 4
787
+                            and strpos($wherestring, (string) "{$cle}.") !== false
788
+                        ) {
789
+                            $i = 0;
790
+                            $wheresub[] = $wj[3];
791
+                            unset($jsub[$cle][3]);
792
+                        }
793
+                    }
794
+                }
795
+            } while ($i++ < 1);
796
+        }
797
+        if ($sous[0] == 'SUBSELECT') {
798
+            // c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
799
+            array_push($where_simples, $sous[3]); // est-ce utile dans ce cas ?
800
+            $where[$k] = remplace_sous_requete($w, '(' . calculer_select(
801
+                $sous[1], # select
802
+                $sous[2], #from
803
+                [], #from_type
804
+                $sous[3] ? (is_array($sous[3]) ? $sous[3] : [$sous[3]]) : [],
805
+                #where, qui peut etre de la forme string comme dans sql_select
806
+                    [], #join
807
+                $sous[4] ?: [], #groupby
808
+                $sous[5] ?: [], #orderby
809
+                $sous[6], #limit
810
+                $sous[7] ?: [], #having
811
+                $table,
812
+                $id,
813
+                $serveur,
814
+                false
815
+            ) . ')');
816
+        }
817
+        array_pop($where_simples);
818
+    }
819
+
820
+    foreach ($having as $k => $v) {
821
+        if ((!$v) or ($v == 1) or ($v == '0=0')) {
822
+            unset($having[$k]);
823
+        }
824
+    }
825
+
826
+    // Installer les jointures.
827
+    // Retirer celles seulement utiles aux criteres finalement absents mais
828
+    // parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
829
+    // si elle est seulement utile a Ln+1 elle meme inutile
830
+
831
+    $afrom = [];
832
+    $equiv = [];
833
+    $k = count($join);
834
+    foreach (array_reverse($join, true) as $cledef => $j) {
835
+        $cle = $cledef;
836
+        // le format de join est :
837
+        // array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
838
+        $join[$cle] = array_values($join[$cle]); // recalculer les cles car des unset ont pu perturber
839
+        if (count($join[$cle]) == 2) {
840
+            $join[$cle][] = $join[$cle][1];
841
+        }
842
+        if ((is_array($join[$cle]) || $join[$cle] instanceof \Countable ? count($join[$cle]) : 0) == 3) {
843
+            $join[$cle][] = '';
844
+        }
845
+        [$t, $c, $carr, $and] = $join[$cle];
846
+        // si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
847
+        // pour compat avec ancienne convention
848
+        if (is_numeric($cle)) {
849
+            $cle = "L$k";
850
+        }
851
+        $cle_where_lie = "JOIN-$cle";
852
+        if (
853
+            !$menage
854
+            or isset($afrom[$cle])
855
+            or calculer_jointnul($cle, $select)
856
+            or calculer_jointnul($cle, array_diff_key($join, [$cle => $join[$cle]]))
857
+            or calculer_jointnul($cle, $having)
858
+            or calculer_jointnul($cle, array_diff_key($where_simples, [$cle_where_lie => '']))
859
+        ) {
860
+            // corriger les references non explicites dans select
861
+            // ou groupby
862
+            foreach ($select as $i => $s) {
863
+                if ($s == $c) {
864
+                    $select[$i] = "$cle.$c AS $c";
865
+                    break;
866
+                }
867
+            }
868
+            foreach ($groupby as $i => $g) {
869
+                if ($g == $c) {
870
+                    $groupby[$i] = "$cle.$c";
871
+                    break;
872
+                }
873
+            }
874
+            // on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
875
+            // sans recours a preg_match
876
+            // un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
877
+            $afrom[$t][$cle] = [
878
+                "\n" .
879
+                ($from_type[$cle] ?? 'INNER') . ' JOIN',
880
+                $from[$cle],
881
+                "AS $cle",
882
+                'ON (',
883
+                "$cle.$c",
884
+                '=',
885
+                "$t.$carr",
886
+                ($and ? 'AND ' . $and : '') .
887
+                ')'
888
+            ];
889
+            if (isset($afrom[$cle])) {
890
+                $afrom[$t] = $afrom[$t] + $afrom[$cle];
891
+                unset($afrom[$cle]);
892
+            }
893
+            $equiv[] = $carr;
894
+        } else {
895
+            unset($join[$cledef]);
896
+            if (isset($where_simples[$cle_where_lie])) {
897
+                unset($where_simples[$cle_where_lie]);
898
+                unset($where[$cle_where_lie]);
899
+            }
900
+        }
901
+        unset($from[$cle]);
902
+        $k--;
903
+    }
904
+
905
+    if (count($afrom)) {
906
+        // Regarder si la table principale ne sert finalement a rien comme dans
907
+        //<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
908
+        //<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
909
+        //<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
910
+        // ou dans
911
+        //<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
912
+        // qui comporte plusieurs jointures
913
+        // ou dans
914
+        // <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
915
+        // <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
916
+        // penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
917
+        // <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
918
+        // penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
919
+        // <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
920
+
921
+        $t = key($from);
922
+        $c = current($from);
923
+        reset($from);
924
+        $e = '/\b(' . "$t\\." . join('|' . $t . '\.', $equiv) . ')\b/';
925
+        if (
926
+            !(strpos($t, ' ') or // jointure des le depart cf boucle_doc
927
+                calculer_jointnul($t, $select, $e) or
928
+                calculer_jointnul($t, $join, $e) or
929
+                calculer_jointnul($t, $where, $e) or
930
+                calculer_jointnul($t, $orderby, $e) or
931
+                calculer_jointnul($t, $groupby, $e) or
932
+                calculer_jointnul($t, $having, $e))
933
+            && count($afrom[$t])
934
+        ) {
935
+            $nfrom = reset($afrom[$t]);
936
+            $nt = array_key_first($afrom[$t]);
937
+            unset($from[$t]);
938
+            $from[$nt] = $nfrom[1];
939
+            unset($afrom[$t][$nt]);
940
+            $afrom[$nt] = $afrom[$t];
941
+            unset($afrom[$t]);
942
+            $e = '/\b' . preg_quote($nfrom[6]) . '\b/';
943
+            $t = $nfrom[4];
944
+            $alias = '';
945
+            // verifier que les deux cles sont homonymes, sinon installer un alias dans le select
946
+            $oldcle = explode('.', $nfrom[6]);
947
+            $oldcle = end($oldcle);
948
+            $newcle = explode('.', $nfrom[4]);
949
+            $newcle = end($newcle);
950
+            if ($newcle != $oldcle) {
951
+                // si l'ancienne cle etait deja dans le select avec un AS
952
+                // reprendre simplement ce AS
953
+                $as = '/\b' . preg_quote($nfrom[6]) . '\s+(AS\s+\w+)\b/';
954
+                if (preg_match($as, implode(',', $select), $m)) {
955
+                    $alias = '';
956
+                } else {
957
+                    $alias = ', ' . $nfrom[4] . " AS $oldcle";
958
+                }
959
+            }
960
+            $select = remplacer_jointnul($t . $alias, $select, $e);
961
+            $join = remplacer_jointnul($t, $join, $e);
962
+            $where = remplacer_jointnul($t, $where, $e);
963
+            $having = remplacer_jointnul($t, $having, $e);
964
+            $groupby = remplacer_jointnul($t, $groupby, $e);
965
+            $orderby = remplacer_jointnul($t, $orderby, $e);
966
+        }
967
+        $from = reinjecte_joint($afrom, $from);
968
+    }
969
+    if (empty($GLOBALS['debug']) or !is_array($GLOBALS['debug'])) {
970
+        $wasdebug = empty($GLOBALS['debug']) ? false : $GLOBALS['debug'];
971
+        $GLOBALS['debug'] = [];
972
+        if ($wasdebug) {
973
+            $GLOBALS['debug']['debug'] = true;
974
+        }
975
+    }
976
+    $GLOBALS['debug']['aucasou'] = [$table, $id, $serveur, $requeter];
977
+    $r = sql_select(
978
+        $select,
979
+        $from,
980
+        $where,
981
+        $groupby,
982
+        array_filter($orderby),
983
+        $limit,
984
+        $having,
985
+        $serveur,
986
+        $requeter
987
+    );
988
+    unset($GLOBALS['debug']['aucasou']);
989
+
990
+    return $r;
991 991
 }
992 992
 
993 993
 /**
@@ -998,79 +998,79 @@  discard block
 block discarded – undo
998 998
  * @return string
999 999
  */
1000 1000
 function calculer_where_to_string($v, $join = 'AND') {
1001
-	if (empty($v)) {
1002
-		return '';
1003
-	}
1004
-
1005
-	if (!is_array($v)) {
1006
-		return $v;
1007
-	} else {
1008
-		$exp = '';
1009
-		if (strtoupper($join) === 'AND') {
1010
-			return $exp . join(" $join ", array_map('calculer_where_to_string', $v));
1011
-		} else {
1012
-			return $exp . join($join, $v);
1013
-		}
1014
-	}
1001
+    if (empty($v)) {
1002
+        return '';
1003
+    }
1004
+
1005
+    if (!is_array($v)) {
1006
+        return $v;
1007
+    } else {
1008
+        $exp = '';
1009
+        if (strtoupper($join) === 'AND') {
1010
+            return $exp . join(" $join ", array_map('calculer_where_to_string', $v));
1011
+        } else {
1012
+            return $exp . join($join, $v);
1013
+        }
1014
+    }
1015 1015
 }
1016 1016
 
1017 1017
 
1018 1018
 //condition suffisante (mais non necessaire) pour qu'une table soit utile
1019 1019
 
1020 1020
 function calculer_jointnul($cle, $exp, $equiv = '') {
1021
-	if (!is_array($exp)) {
1022
-		if ($equiv) {
1023
-			$exp = preg_replace($equiv, '', $exp);
1024
-		}
1025
-
1026
-		return preg_match("/\\b$cle\\./", $exp);
1027
-	} else {
1028
-		foreach ($exp as $v) {
1029
-			if (calculer_jointnul($cle, $v, $equiv)) {
1030
-				return true;
1031
-			}
1032
-		}
1033
-
1034
-		return false;
1035
-	}
1021
+    if (!is_array($exp)) {
1022
+        if ($equiv) {
1023
+            $exp = preg_replace($equiv, '', $exp);
1024
+        }
1025
+
1026
+        return preg_match("/\\b$cle\\./", $exp);
1027
+    } else {
1028
+        foreach ($exp as $v) {
1029
+            if (calculer_jointnul($cle, $v, $equiv)) {
1030
+                return true;
1031
+            }
1032
+        }
1033
+
1034
+        return false;
1035
+    }
1036 1036
 }
1037 1037
 
1038 1038
 function reinjecte_joint($afrom, $from) {
1039
-	$from_synth = [];
1040
-	foreach ($from as $k => $v) {
1041
-		$from_synth[$k] = $from[$k];
1042
-		if (isset($afrom[$k])) {
1043
-			foreach ($afrom[$k] as $kk => $vv) {
1044
-				$afrom[$k][$kk] = implode(' ', $afrom[$k][$kk]);
1045
-			}
1046
-			$from_synth["$k@"] = implode(' ', $afrom[$k]);
1047
-			unset($afrom[$k]);
1048
-		}
1049
-	}
1050
-
1051
-	return $from_synth;
1039
+    $from_synth = [];
1040
+    foreach ($from as $k => $v) {
1041
+        $from_synth[$k] = $from[$k];
1042
+        if (isset($afrom[$k])) {
1043
+            foreach ($afrom[$k] as $kk => $vv) {
1044
+                $afrom[$k][$kk] = implode(' ', $afrom[$k][$kk]);
1045
+            }
1046
+            $from_synth["$k@"] = implode(' ', $afrom[$k]);
1047
+            unset($afrom[$k]);
1048
+        }
1049
+    }
1050
+
1051
+    return $from_synth;
1052 1052
 }
1053 1053
 
1054 1054
 function remplacer_jointnul($cle, $exp, $equiv = '') {
1055
-	if (!is_array($exp)) {
1056
-		return preg_replace($equiv, $cle, $exp);
1057
-	} else {
1058
-		foreach ($exp as $k => $v) {
1059
-			$exp[$k] = remplacer_jointnul($cle, $v, $equiv);
1060
-		}
1061
-
1062
-		return $exp;
1063
-	}
1055
+    if (!is_array($exp)) {
1056
+        return preg_replace($equiv, $cle, $exp);
1057
+    } else {
1058
+        foreach ($exp as $k => $v) {
1059
+            $exp[$k] = remplacer_jointnul($cle, $v, $equiv);
1060
+        }
1061
+
1062
+        return $exp;
1063
+    }
1064 1064
 }
1065 1065
 
1066 1066
 // calcul du nom du squelette
1067 1067
 function calculer_nom_fonction_squel($skel, $mime_type = 'html', string $connect = '') {
1068
-	// ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
1069
-	if ($l = strlen(_DIR_RACINE) and strncmp($skel, _DIR_RACINE, $l) == 0) {
1070
-		$skel = substr($skel, strlen(_DIR_RACINE));
1071
-	}
1072
-
1073
-	return $mime_type
1074
-	. (!$connect ? '' : preg_replace('/\W/', '_', $connect)) . '_'
1075
-	. md5($GLOBALS['spip_version_code'] . ' * ' . $skel . (isset($GLOBALS['marqueur_skel']) ? '*' . $GLOBALS['marqueur_skel'] : ''));
1068
+    // ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
1069
+    if ($l = strlen(_DIR_RACINE) and strncmp($skel, _DIR_RACINE, $l) == 0) {
1070
+        $skel = substr($skel, strlen(_DIR_RACINE));
1071
+    }
1072
+
1073
+    return $mime_type
1074
+    . (!$connect ? '' : preg_replace('/\W/', '_', $connect)) . '_'
1075
+    . md5($GLOBALS['spip_version_code'] . ' * ' . $skel . (isset($GLOBALS['marqueur_skel']) ? '*' . $GLOBALS['marqueur_skel'] : ''));
1076 1076
 }
Please login to merge, or discard this patch.