Completed
Push — master ( cacd66...717daf )
by cam
02:37 queued 21s
created
ecrire/base/upgrade.php 1 patch
Indentation   +284 added lines, -284 removed lines patch added patch discarded remove patch
@@ -17,17 +17,17 @@  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
 if (!defined('_UPGRADE_TIME_OUT')) {
24
-	/**
25
-	 * Durée en secondes pour relancer les scripts de mises à jour, x secondes
26
-	 * avant que la durée d'exécution du script provoque un timeout
27
-	 *
28
-	 * @var int
29
-	 **/
30
-	define('_UPGRADE_TIME_OUT', 20);
24
+    /**
25
+     * Durée en secondes pour relancer les scripts de mises à jour, x secondes
26
+     * avant que la durée d'exécution du script provoque un timeout
27
+     *
28
+     * @var int
29
+     **/
30
+    define('_UPGRADE_TIME_OUT', 20);
31 31
 }
32 32
 
33 33
 /**
@@ -50,40 +50,40 @@  discard block
 block discarded – undo
50 50
  * @return void
51 51
  */
52 52
 function base_upgrade_dist($titre = '', $reprise = '') {
53
-	if (!$titre) {
54
-		return;
55
-	} // anti-testeur automatique
56
-	if ($GLOBALS['spip_version_base'] != $GLOBALS['meta']['version_installee']) {
57
-		if (!is_numeric(_request('reinstall'))) {
58
-			include_spip('base/create');
59
-			spip_log('recree les tables eventuellement disparues', 'maj.' . _LOG_INFO_IMPORTANTE);
60
-			creer_base();
61
-		}
62
-
63
-		// quand on rentre par ici, c'est toujours une mise a jour de SPIP
64
-		// lancement de l'upgrade SPIP
65
-		$res = maj_base();
66
-
67
-		if ($res) {
68
-			// on arrete tout ici !
69
-			exit;
70
-		}
71
-	}
72
-	spip_log('Fin de mise a jour SQL. Debut m-a-j acces et config', 'maj.' . _LOG_INFO_IMPORTANTE);
73
-
74
-	// supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
75
-	@spip_unlink(_CACHE_RUBRIQUES);
76
-	@spip_unlink(_CACHE_PIPELINES);
77
-	@spip_unlink(_CACHE_PLUGINS_PATH);
78
-	@spip_unlink(_CACHE_PLUGINS_OPT);
79
-	@spip_unlink(_CACHE_PLUGINS_FCT);
80
-	@spip_unlink(_CACHE_CHEMIN);
81
-	@spip_unlink(_DIR_TMP . 'plugin_xml_cache.gz');
82
-
83
-	include_spip('inc/auth');
84
-	auth_synchroniser_distant();
85
-	$config = charger_fonction('config', 'inc');
86
-	$config();
53
+    if (!$titre) {
54
+        return;
55
+    } // anti-testeur automatique
56
+    if ($GLOBALS['spip_version_base'] != $GLOBALS['meta']['version_installee']) {
57
+        if (!is_numeric(_request('reinstall'))) {
58
+            include_spip('base/create');
59
+            spip_log('recree les tables eventuellement disparues', 'maj.' . _LOG_INFO_IMPORTANTE);
60
+            creer_base();
61
+        }
62
+
63
+        // quand on rentre par ici, c'est toujours une mise a jour de SPIP
64
+        // lancement de l'upgrade SPIP
65
+        $res = maj_base();
66
+
67
+        if ($res) {
68
+            // on arrete tout ici !
69
+            exit;
70
+        }
71
+    }
72
+    spip_log('Fin de mise a jour SQL. Debut m-a-j acces et config', 'maj.' . _LOG_INFO_IMPORTANTE);
73
+
74
+    // supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
75
+    @spip_unlink(_CACHE_RUBRIQUES);
76
+    @spip_unlink(_CACHE_PIPELINES);
77
+    @spip_unlink(_CACHE_PLUGINS_PATH);
78
+    @spip_unlink(_CACHE_PLUGINS_OPT);
79
+    @spip_unlink(_CACHE_PLUGINS_FCT);
80
+    @spip_unlink(_CACHE_CHEMIN);
81
+    @spip_unlink(_DIR_TMP . 'plugin_xml_cache.gz');
82
+
83
+    include_spip('inc/auth');
84
+    auth_synchroniser_distant();
85
+    $config = charger_fonction('config', 'inc');
86
+    $config();
87 87
 }
88 88
 
89 89
 /**
@@ -114,51 +114,51 @@  discard block
 block discarded – undo
114 114
  */
115 115
 function maj_base($version_cible = 0, $redirect = '', $debut_page = true) {
116 116
 
117
-	$version_installee = $GLOBALS['meta']['version_installee'] ?? null;
118
-
119
-	spip_log(
120
-		"Version anterieure: $version_installee. Courante: " . $GLOBALS['spip_version_base'],
121
-		'maj.' . _LOG_INFO_IMPORTANTE
122
-	);
123
-	if (!$version_installee or ($GLOBALS['spip_version_base'] < $version_installee)) {
124
-		sql_replace(
125
-			'spip_meta',
126
-			[
127
-				'nom' => 'version_installee',
128
-				'valeur' => $GLOBALS['spip_version_base'],
129
-				'impt' => 'non'
130
-			]
131
-		);
132
-		return false;
133
-	}
134
-	if (!upgrade_test()) {
135
-		return true;
136
-	}
137
-
138
-	$cible = ($version_cible ?: $GLOBALS['spip_version_base']);
139
-
140
-	if ($version_installee < 2021_01_01_00) {
141
-		include_spip('maj/legacy/v21');
142
-		include_spip('maj/legacy/v30');
143
-		include_spip('maj/legacy/v31');
144
-		include_spip('maj/legacy/v32');
145
-		include_spip('maj/legacy/v40');
146
-	}
147
-
148
-	include_spip('maj/2021');
149
-
150
-	ksort($GLOBALS['maj']);
151
-	$res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, $debut_page);
152
-	if ($res) {
153
-		if (!is_array($res)) {
154
-			spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
155
-		} else {
156
-			echo _T('avis_operation_echec') . ' ' . join(' ', $res);
157
-			echo install_fin_html();
158
-		}
159
-	}
160
-
161
-	return $res;
117
+    $version_installee = $GLOBALS['meta']['version_installee'] ?? null;
118
+
119
+    spip_log(
120
+        "Version anterieure: $version_installee. Courante: " . $GLOBALS['spip_version_base'],
121
+        'maj.' . _LOG_INFO_IMPORTANTE
122
+    );
123
+    if (!$version_installee or ($GLOBALS['spip_version_base'] < $version_installee)) {
124
+        sql_replace(
125
+            'spip_meta',
126
+            [
127
+                'nom' => 'version_installee',
128
+                'valeur' => $GLOBALS['spip_version_base'],
129
+                'impt' => 'non'
130
+            ]
131
+        );
132
+        return false;
133
+    }
134
+    if (!upgrade_test()) {
135
+        return true;
136
+    }
137
+
138
+    $cible = ($version_cible ?: $GLOBALS['spip_version_base']);
139
+
140
+    if ($version_installee < 2021_01_01_00) {
141
+        include_spip('maj/legacy/v21');
142
+        include_spip('maj/legacy/v30');
143
+        include_spip('maj/legacy/v31');
144
+        include_spip('maj/legacy/v32');
145
+        include_spip('maj/legacy/v40');
146
+    }
147
+
148
+    include_spip('maj/2021');
149
+
150
+    ksort($GLOBALS['maj']);
151
+    $res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, $debut_page);
152
+    if ($res) {
153
+        if (!is_array($res)) {
154
+            spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
155
+        } else {
156
+            echo _T('avis_operation_echec') . ' ' . join(' ', $res);
157
+            echo install_fin_html();
158
+        }
159
+    }
160
+
161
+    return $res;
162 162
 }
163 163
 
164 164
 /**
@@ -200,53 +200,53 @@  discard block
 block discarded – undo
200 200
  */
201 201
 function maj_plugin($nom_meta_base_version, $version_cible, $maj, $table_meta = 'meta') {
202 202
 
203
-	if ($table_meta !== 'meta') {
204
-		installer_table_meta($table_meta);
205
-	}
206
-
207
-	$current_version = null;
208
-
209
-	if (
210
-		(!isset($GLOBALS[$table_meta][$nom_meta_base_version]))
211
-		|| (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version], $version_cible, '='))
212
-	) {
213
-		// $maj['create'] contient les directives propres a la premiere creation de base
214
-		// c'est une operation derogatoire qui fait aboutir directement dans la version_cible
215
-		if (isset($maj['create'])) {
216
-			if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])) {
217
-				// installation : on ne fait que l'operation create
218
-				$maj = ['init' => $maj['create']];
219
-				// et on lui ajoute un appel a inc/config
220
-				// pour creer les metas par defaut
221
-				$config = charger_fonction('config', 'inc');
222
-				$maj[$version_cible] = [[$config]];
223
-			}
224
-			// dans tous les cas enlever cet index du tableau
225
-			unset($maj['create']);
226
-		}
227
-		// si init, deja dans le bon ordre
228
-		if (!isset($maj['init'])) {
229
-			include_spip('inc/plugin'); // pour spip_version_compare
230
-			uksort($maj, 'spip_version_compare');
231
-		}
232
-
233
-		// la redirection se fait par defaut sur la page d'administration des plugins
234
-		// sauf lorsque nous sommes sur l'installation de SPIP
235
-		// ou define _REDIRECT_MAJ_PLUGIN
236
-		$redirect = (defined('_REDIRECT_MAJ_PLUGIN') ? _REDIRECT_MAJ_PLUGIN : generer_url_ecrire('admin_plugin'));
237
-		if (defined('_ECRIRE_INSTALL')) {
238
-			$redirect = parametre_url(generer_url_ecrire('install'), 'etape', _request('etape'));
239
-		}
240
-
241
-		$res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
242
-		if ($res) {
243
-			if (!is_array($res)) {
244
-				spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
245
-			} else {
246
-				echo '<p>' . _T('avis_operation_echec') . ' ' . join(' ', $res) . '</p>';
247
-			}
248
-		}
249
-	}
203
+    if ($table_meta !== 'meta') {
204
+        installer_table_meta($table_meta);
205
+    }
206
+
207
+    $current_version = null;
208
+
209
+    if (
210
+        (!isset($GLOBALS[$table_meta][$nom_meta_base_version]))
211
+        || (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version], $version_cible, '='))
212
+    ) {
213
+        // $maj['create'] contient les directives propres a la premiere creation de base
214
+        // c'est une operation derogatoire qui fait aboutir directement dans la version_cible
215
+        if (isset($maj['create'])) {
216
+            if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])) {
217
+                // installation : on ne fait que l'operation create
218
+                $maj = ['init' => $maj['create']];
219
+                // et on lui ajoute un appel a inc/config
220
+                // pour creer les metas par defaut
221
+                $config = charger_fonction('config', 'inc');
222
+                $maj[$version_cible] = [[$config]];
223
+            }
224
+            // dans tous les cas enlever cet index du tableau
225
+            unset($maj['create']);
226
+        }
227
+        // si init, deja dans le bon ordre
228
+        if (!isset($maj['init'])) {
229
+            include_spip('inc/plugin'); // pour spip_version_compare
230
+            uksort($maj, 'spip_version_compare');
231
+        }
232
+
233
+        // la redirection se fait par defaut sur la page d'administration des plugins
234
+        // sauf lorsque nous sommes sur l'installation de SPIP
235
+        // ou define _REDIRECT_MAJ_PLUGIN
236
+        $redirect = (defined('_REDIRECT_MAJ_PLUGIN') ? _REDIRECT_MAJ_PLUGIN : generer_url_ecrire('admin_plugin'));
237
+        if (defined('_ECRIRE_INSTALL')) {
238
+            $redirect = parametre_url(generer_url_ecrire('install'), 'etape', _request('etape'));
239
+        }
240
+
241
+        $res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
242
+        if ($res) {
243
+            if (!is_array($res)) {
244
+                spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
245
+            } else {
246
+                echo '<p>' . _T('avis_operation_echec') . ' ' . join(' ', $res) . '</p>';
247
+            }
248
+        }
249
+    }
250 250
 }
251 251
 
252 252
 /**
@@ -263,17 +263,17 @@  discard block
 block discarded – undo
263 263
  * @return void
264 264
  */
265 265
 function relance_maj($meta, $table, $redirect = '') {
266
-	include_spip('inc/headers');
267
-	if (!$redirect) {
268
-		// recuperer la valeur installee en cours
269
-		// on la tronque numeriquement, elle ne sert pas reellement
270
-		// sauf pour verifier que ce n'est pas oui ou non
271
-		// sinon is_numeric va echouer sur un numero de version 1.2.3
272
-		$installee = intval($GLOBALS[$table][$meta]);
273
-		$redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
274
-	}
275
-	echo redirige_formulaire($redirect);
276
-	exit();
266
+    include_spip('inc/headers');
267
+    if (!$redirect) {
268
+        // recuperer la valeur installee en cours
269
+        // on la tronque numeriquement, elle ne sert pas reellement
270
+        // sauf pour verifier que ce n'est pas oui ou non
271
+        // sinon is_numeric va echouer sur un numero de version 1.2.3
272
+        $installee = intval($GLOBALS[$table][$meta]);
273
+        $redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
274
+    }
275
+    echo redirige_formulaire($redirect);
276
+    exit();
277 277
 }
278 278
 
279 279
 /**
@@ -286,28 +286,28 @@  discard block
 block discarded – undo
286 286
  * @return void
287 287
  */
288 288
 function maj_debut_page($installee, $meta, $table) {
289
-	static $done = false;
290
-	if ($done) {
291
-		return;
292
-	}
293
-	include_spip('inc/minipres');
294
-	if (function_exists('ini_set')) {
295
-		@ini_set('zlib.output_compression', '0'); // pour permettre l'affichage au fur et a mesure
296
-	}
297
-	$timeout = _UPGRADE_TIME_OUT * 2;
298
-	$titre = _T('titre_page_upgrade');
299
-	$balise_img = charger_filtre('balise_img');
300
-	$titre .= $balise_img(chemin_image('loader.svg'), '', 'loader');
301
-	echo(install_debut_html($titre));
302
-	// script de rechargement auto sur timeout
303
-	$redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
304
-	echo http_script("window.setTimeout('location.href=\"" . $redirect . "\";'," . ($timeout * 1000) . ')');
305
-	echo "<div style='text-align: left'>\n";
306
-	if (ob_get_level()) {
307
-		ob_flush();
308
-	}
309
-	flush();
310
-	$done = true;
289
+    static $done = false;
290
+    if ($done) {
291
+        return;
292
+    }
293
+    include_spip('inc/minipres');
294
+    if (function_exists('ini_set')) {
295
+        @ini_set('zlib.output_compression', '0'); // pour permettre l'affichage au fur et a mesure
296
+    }
297
+    $timeout = _UPGRADE_TIME_OUT * 2;
298
+    $titre = _T('titre_page_upgrade');
299
+    $balise_img = charger_filtre('balise_img');
300
+    $titre .= $balise_img(chemin_image('loader.svg'), '', 'loader');
301
+    echo(install_debut_html($titre));
302
+    // script de rechargement auto sur timeout
303
+    $redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
304
+    echo http_script("window.setTimeout('location.href=\"" . $redirect . "\";'," . ($timeout * 1000) . ')');
305
+    echo "<div style='text-align: left'>\n";
306
+    if (ob_get_level()) {
307
+        ob_flush();
308
+    }
309
+    flush();
310
+    $done = true;
311 311
 }
312 312
 
313 313
 
@@ -351,64 +351,64 @@  discard block
 block discarded – undo
351 351
  *    - tableau vide sinon.
352 352
  */
353 353
 function maj_while($installee, $cible, $maj, $meta = '', $table = 'meta', $redirect = '', $debut_page = false) {
354
-	# inclusions pour que les procedures d'upgrade disposent des fonctions de base
355
-	include_spip('base/create');
356
-	include_spip('base/abstract_sql');
357
-	$trouver_table = charger_fonction('trouver_table', 'base');
358
-	include_spip('inc/plugin'); // pour spip_version_compare
359
-	$n = 0;
360
-	$time = time();
361
-
362
-	if (!defined('_TIME_OUT')) {
363
-		/**
364
-		 * Définir le timeout qui peut-être utilisé dans les fonctions
365
-		 * de mises à jour qui durent trop longtemps
366
-		 *
367
-		 * À utiliser tel que : `if (time() >= _TIME_OUT)`
368
-		 *
369
-		 * @var int
370
-		 */
371
-		define('_TIME_OUT', $time + _UPGRADE_TIME_OUT);
372
-	}
373
-
374
-	foreach ($maj as $v => $operations) {
375
-		// si une maj pour cette version
376
-		if (
377
-			$v == 'init' or
378
-			(spip_version_compare($v, $installee, '>')
379
-				and spip_version_compare($v, $cible, '<='))
380
-		) {
381
-			if ($debut_page) {
382
-				maj_debut_page($v, $meta, $table);
383
-			}
384
-			echo "MAJ $v";
385
-			$etape = serie_alter($v, $operations, $meta, $table, $redirect);
386
-			$trouver_table(''); // vider le cache des descriptions de table
387
-			# echec sur une etape en cours ?
388
-			# on sort
389
-			if ($etape) {
390
-				return [$v, $etape];
391
-			}
392
-			$n = time() - $time;
393
-			spip_log("$table $meta: $v en $n secondes", 'maj.' . _LOG_INFO_IMPORTANTE);
394
-			if ($meta) {
395
-				ecrire_meta($meta, $installee = $v, 'oui', $table);
396
-			}
397
-			echo (_IS_CLI ? "\n" : '<br />');
398
-		}
399
-		if (time() >= _TIME_OUT) {
400
-			relance_maj($meta, $table, $redirect);
401
-		}
402
-	}
403
-	$trouver_table(''); // vider le cache des descriptions de table
404
-	// indispensable pour les chgt de versions qui n'ecrivent pas en base
405
-	// tant pis pour la redondance eventuelle avec ci-dessus
406
-	if ($meta) {
407
-		ecrire_meta($meta, $cible, 'oui', $table);
408
-	}
409
-	spip_log("MAJ terminee. $meta: $installee", 'maj.' . _LOG_INFO_IMPORTANTE);
410
-
411
-	return [];
354
+    # inclusions pour que les procedures d'upgrade disposent des fonctions de base
355
+    include_spip('base/create');
356
+    include_spip('base/abstract_sql');
357
+    $trouver_table = charger_fonction('trouver_table', 'base');
358
+    include_spip('inc/plugin'); // pour spip_version_compare
359
+    $n = 0;
360
+    $time = time();
361
+
362
+    if (!defined('_TIME_OUT')) {
363
+        /**
364
+         * Définir le timeout qui peut-être utilisé dans les fonctions
365
+         * de mises à jour qui durent trop longtemps
366
+         *
367
+         * À utiliser tel que : `if (time() >= _TIME_OUT)`
368
+         *
369
+         * @var int
370
+         */
371
+        define('_TIME_OUT', $time + _UPGRADE_TIME_OUT);
372
+    }
373
+
374
+    foreach ($maj as $v => $operations) {
375
+        // si une maj pour cette version
376
+        if (
377
+            $v == 'init' or
378
+            (spip_version_compare($v, $installee, '>')
379
+                and spip_version_compare($v, $cible, '<='))
380
+        ) {
381
+            if ($debut_page) {
382
+                maj_debut_page($v, $meta, $table);
383
+            }
384
+            echo "MAJ $v";
385
+            $etape = serie_alter($v, $operations, $meta, $table, $redirect);
386
+            $trouver_table(''); // vider le cache des descriptions de table
387
+            # echec sur une etape en cours ?
388
+            # on sort
389
+            if ($etape) {
390
+                return [$v, $etape];
391
+            }
392
+            $n = time() - $time;
393
+            spip_log("$table $meta: $v en $n secondes", 'maj.' . _LOG_INFO_IMPORTANTE);
394
+            if ($meta) {
395
+                ecrire_meta($meta, $installee = $v, 'oui', $table);
396
+            }
397
+            echo (_IS_CLI ? "\n" : '<br />');
398
+        }
399
+        if (time() >= _TIME_OUT) {
400
+            relance_maj($meta, $table, $redirect);
401
+        }
402
+    }
403
+    $trouver_table(''); // vider le cache des descriptions de table
404
+    // indispensable pour les chgt de versions qui n'ecrivent pas en base
405
+    // tant pis pour la redondance eventuelle avec ci-dessus
406
+    if ($meta) {
407
+        ecrire_meta($meta, $cible, 'oui', $table);
408
+    }
409
+    spip_log("MAJ terminee. $meta: $installee", 'maj.' . _LOG_INFO_IMPORTANTE);
410
+
411
+    return [];
412 412
 }
413 413
 
414 414
 /**
@@ -431,53 +431,53 @@  discard block
 block discarded – undo
431 431
  * @return int
432 432
  */
433 433
 function serie_alter($serie, $q = [], $meta = '', $table = 'meta', $redirect = '') {
434
-	$meta2 = $meta . '_maj_' . $serie;
435
-	$etape = 0;
436
-	if (isset($GLOBALS[$table][$meta2])) {
437
-		$etape = intval($GLOBALS[$table][$meta2]);
438
-	}
439
-	foreach ($q as $i => $r) {
440
-		if ($i >= $etape) {
441
-			$msg = "maj $table $meta2 etape $i";
442
-			if (
443
-				is_array($r)
444
-				and function_exists($f = array_shift($r))
445
-			) {
446
-				// note: $r (arguments de la fonction $f) peut avoir des données tabulaires
447
-				spip_log("$msg: $f " . @join(',', $r), 'maj.' . _LOG_INFO_IMPORTANTE);
448
-				// pour les fonctions atomiques sql_xx
449
-				// on enregistre le meta avant de lancer la fonction,
450
-				// de maniere a eviter de boucler sur timeout
451
-				// mais pour les fonctions complexes,
452
-				// il faut les rejouer jusqu'a achevement.
453
-				// C'est a elle d'assurer qu'elles progressent a chaque rappel
454
-				if (strncmp($f, 'sql_', 4) == 0) {
455
-					ecrire_meta($meta2, $i + 1, 'non', $table);
456
-				}
457
-				echo (_IS_CLI ? '.' : " <span title='$i'>.</span>");
458
-				$f(...$r);
459
-				// si temps imparti depasse, on relance sans ecrire en meta
460
-				// car on est peut etre sorti sur timeout si c'est une fonction longue
461
-				if (time() >= _TIME_OUT) {
462
-					relance_maj($meta, $table, $redirect);
463
-				}
464
-				ecrire_meta($meta2, $i + 1, 'non', $table);
465
-				spip_log("$meta2: ok", 'maj.' . _LOG_INFO_IMPORTANTE);
466
-			} else {
467
-				if (!is_array($r)) {
468
-					spip_log("maj $i format incorrect", 'maj.' . _LOG_ERREUR);
469
-				} else {
470
-					spip_log("maj $i fonction $f non definie", 'maj.' . _LOG_ERREUR);
471
-				}
472
-				// en cas d'erreur serieuse, on s'arrete
473
-				// mais on permet de passer par dessus en rechargeant la page.
474
-				return $i + 1;
475
-			}
476
-		}
477
-	}
478
-	effacer_meta($meta2, $table);
479
-
480
-	return 0;
434
+    $meta2 = $meta . '_maj_' . $serie;
435
+    $etape = 0;
436
+    if (isset($GLOBALS[$table][$meta2])) {
437
+        $etape = intval($GLOBALS[$table][$meta2]);
438
+    }
439
+    foreach ($q as $i => $r) {
440
+        if ($i >= $etape) {
441
+            $msg = "maj $table $meta2 etape $i";
442
+            if (
443
+                is_array($r)
444
+                and function_exists($f = array_shift($r))
445
+            ) {
446
+                // note: $r (arguments de la fonction $f) peut avoir des données tabulaires
447
+                spip_log("$msg: $f " . @join(',', $r), 'maj.' . _LOG_INFO_IMPORTANTE);
448
+                // pour les fonctions atomiques sql_xx
449
+                // on enregistre le meta avant de lancer la fonction,
450
+                // de maniere a eviter de boucler sur timeout
451
+                // mais pour les fonctions complexes,
452
+                // il faut les rejouer jusqu'a achevement.
453
+                // C'est a elle d'assurer qu'elles progressent a chaque rappel
454
+                if (strncmp($f, 'sql_', 4) == 0) {
455
+                    ecrire_meta($meta2, $i + 1, 'non', $table);
456
+                }
457
+                echo (_IS_CLI ? '.' : " <span title='$i'>.</span>");
458
+                $f(...$r);
459
+                // si temps imparti depasse, on relance sans ecrire en meta
460
+                // car on est peut etre sorti sur timeout si c'est une fonction longue
461
+                if (time() >= _TIME_OUT) {
462
+                    relance_maj($meta, $table, $redirect);
463
+                }
464
+                ecrire_meta($meta2, $i + 1, 'non', $table);
465
+                spip_log("$meta2: ok", 'maj.' . _LOG_INFO_IMPORTANTE);
466
+            } else {
467
+                if (!is_array($r)) {
468
+                    spip_log("maj $i format incorrect", 'maj.' . _LOG_ERREUR);
469
+                } else {
470
+                    spip_log("maj $i fonction $f non definie", 'maj.' . _LOG_ERREUR);
471
+                }
472
+                // en cas d'erreur serieuse, on s'arrete
473
+                // mais on permet de passer par dessus en rechargeant la page.
474
+                return $i + 1;
475
+            }
476
+        }
477
+    }
478
+    effacer_meta($meta2, $table);
479
+
480
+    return 0;
481 481
 }
482 482
 
483 483
 /**
@@ -486,16 +486,16 @@  discard block
 block discarded – undo
486 486
  * @return bool True si possible.
487 487
  **/
488 488
 function upgrade_test() {
489
-	sql_drop_table('spip_test', true);
490
-	sql_create('spip_test', ['a' => 'int']);
491
-	sql_alter('TABLE spip_test ADD b INT');
492
-	sql_insertq('spip_test', ['b' => 1], ['field' => ['b' => 'int']]);
493
-	$result = sql_select('b', 'spip_test');
494
-	// ne pas garder le resultat de la requete sinon sqlite3
495
-	// ne peut pas supprimer la table spip_test lors du sql_alter qui suit
496
-	// car cette table serait alors 'verouillee'
497
-	$result = $result ? true : false;
498
-	sql_alter('TABLE spip_test DROP b');
499
-
500
-	return $result;
489
+    sql_drop_table('spip_test', true);
490
+    sql_create('spip_test', ['a' => 'int']);
491
+    sql_alter('TABLE spip_test ADD b INT');
492
+    sql_insertq('spip_test', ['b' => 1], ['field' => ['b' => 'int']]);
493
+    $result = sql_select('b', 'spip_test');
494
+    // ne pas garder le resultat de la requete sinon sqlite3
495
+    // ne peut pas supprimer la table spip_test lors du sql_alter qui suit
496
+    // car cette table serait alors 'verouillee'
497
+    $result = $result ? true : false;
498
+    sql_alter('TABLE spip_test DROP b');
499
+
500
+    return $result;
501 501
 }
Please login to merge, or discard this patch.
ecrire/xml/sax.php 1 patch
Indentation   +257 added lines, -257 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
 include_spip('inc/charsets');
@@ -24,222 +24,222 @@  discard block
 block discarded – undo
24 24
  * @return string
25 25
  */
26 26
 function xml_entites_html($texte) {
27
-	if (
28
-		!is_string($texte) or !$texte
29
-		or strpbrk($texte, "&\"'<>") == false
30
-	) {
31
-		return $texte;
32
-	}
33
-
34
-	if (!function_exists('spip_htmlspecialchars')) {
35
-		include_spip('inc/filtres_mini');
36
-	}
37
-	$texte = spip_htmlspecialchars($texte, ENT_QUOTES);
38
-
39
-	return $texte;
27
+    if (
28
+        !is_string($texte) or !$texte
29
+        or strpbrk($texte, "&\"'<>") == false
30
+    ) {
31
+        return $texte;
32
+    }
33
+
34
+    if (!function_exists('spip_htmlspecialchars')) {
35
+        include_spip('inc/filtres_mini');
36
+    }
37
+    $texte = spip_htmlspecialchars($texte, ENT_QUOTES);
38
+
39
+    return $texte;
40 40
 }
41 41
 
42 42
 function xml_debutElement($phraseur, $name, $attrs) {
43
-	$depth = $phraseur->depth;
44
-
45
-	$t = $phraseur->ouvrant[$depth] ?? ' ';
46
-	// espace initial signifie: deja integree au resultat
47
-	if ($t[0] != ' ') {
48
-		$phraseur->res .= '<' . $t . '>';
49
-		$phraseur->ouvrant[$depth] = ' ' . $t;
50
-	}
51
-	$t = $phraseur->contenu[$depth];
52
-	// n'indenter que s'il y a un separateur avant
53
-	$phraseur->res .= preg_replace("/[\n\t ]+$/", "\n$depth", $t);
54
-	$phraseur->contenu[$depth] = '';
55
-	$att = '';
56
-	$sep = ' ';
57
-	foreach ($attrs as $k => $v) {
58
-		$delim = strpos($v, "'") === false ? "'" : '"';
59
-		$val = xml_entites_html($v);
60
-		$att .= $sep . $k . '=' . $delim
61
-			. ($delim !== '"' ? str_replace('&quot;', '"', $val) : $val)
62
-			. $delim;
63
-		$sep = "\n $depth";
64
-	}
65
-	$phraseur->depth .= '  ';
66
-	$phraseur->contenu[$phraseur->depth] = '';
67
-	$phraseur->ouvrant[$phraseur->depth] = $name . $att;
68
-	$phraseur->reperes[$phraseur->depth] = xml_get_current_line_number($phraseur->sax);
43
+    $depth = $phraseur->depth;
44
+
45
+    $t = $phraseur->ouvrant[$depth] ?? ' ';
46
+    // espace initial signifie: deja integree au resultat
47
+    if ($t[0] != ' ') {
48
+        $phraseur->res .= '<' . $t . '>';
49
+        $phraseur->ouvrant[$depth] = ' ' . $t;
50
+    }
51
+    $t = $phraseur->contenu[$depth];
52
+    // n'indenter que s'il y a un separateur avant
53
+    $phraseur->res .= preg_replace("/[\n\t ]+$/", "\n$depth", $t);
54
+    $phraseur->contenu[$depth] = '';
55
+    $att = '';
56
+    $sep = ' ';
57
+    foreach ($attrs as $k => $v) {
58
+        $delim = strpos($v, "'") === false ? "'" : '"';
59
+        $val = xml_entites_html($v);
60
+        $att .= $sep . $k . '=' . $delim
61
+            . ($delim !== '"' ? str_replace('&quot;', '"', $val) : $val)
62
+            . $delim;
63
+        $sep = "\n $depth";
64
+    }
65
+    $phraseur->depth .= '  ';
66
+    $phraseur->contenu[$phraseur->depth] = '';
67
+    $phraseur->ouvrant[$phraseur->depth] = $name . $att;
68
+    $phraseur->reperes[$phraseur->depth] = xml_get_current_line_number($phraseur->sax);
69 69
 }
70 70
 
71 71
 function xml_finElement($phraseur, $name, $fusion_bal = false) {
72
-	$ouv = $phraseur->ouvrant[$phraseur->depth];
73
-
74
-	if ($ouv[0] != ' ') {
75
-		$phraseur->ouvrant[$phraseur->depth] = ' ' . $ouv;
76
-	} else {
77
-		$ouv = '';
78
-	}
79
-	$t = $phraseur->contenu[$phraseur->depth];
80
-	$phraseur->depth = substr($phraseur->depth, 2);
81
-	$t = preg_replace("/[\n\t ]+$/", "\n" . $phraseur->depth, $t);
82
-
83
-	// fusion <balise></balise> en <balise />.
84
-	// ATTENTION,  certains clients http croient que fusion ==> pas d'atttributs
85
-	// en particulier pour les balises Script et A.
86
-	// en presence d'attributs ne le faire que si la DTD est dispo et d'accord
87
-	// (param fusion_bal)
88
-
89
-	if ($t || (($ouv != $name) and !$fusion_bal)) {
90
-		$phraseur->res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . '</' . $name . '>';
91
-	} else {
92
-		$phraseur->res .= ($ouv ? ('<' . $ouv . ' />') : ('</' . $name . '>'));
93
-	}
72
+    $ouv = $phraseur->ouvrant[$phraseur->depth];
73
+
74
+    if ($ouv[0] != ' ') {
75
+        $phraseur->ouvrant[$phraseur->depth] = ' ' . $ouv;
76
+    } else {
77
+        $ouv = '';
78
+    }
79
+    $t = $phraseur->contenu[$phraseur->depth];
80
+    $phraseur->depth = substr($phraseur->depth, 2);
81
+    $t = preg_replace("/[\n\t ]+$/", "\n" . $phraseur->depth, $t);
82
+
83
+    // fusion <balise></balise> en <balise />.
84
+    // ATTENTION,  certains clients http croient que fusion ==> pas d'atttributs
85
+    // en particulier pour les balises Script et A.
86
+    // en presence d'attributs ne le faire que si la DTD est dispo et d'accord
87
+    // (param fusion_bal)
88
+
89
+    if ($t || (($ouv != $name) and !$fusion_bal)) {
90
+        $phraseur->res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . '</' . $name . '>';
91
+    } else {
92
+        $phraseur->res .= ($ouv ? ('<' . $ouv . ' />') : ('</' . $name . '>'));
93
+    }
94 94
 }
95 95
 
96 96
 function xml_textElement($phraseur, $data) {
97
-	$depth = $phraseur->depth;
98
-	$phraseur->contenu[$depth] .= preg_match('/^script/', $phraseur->ouvrant[$depth])
99
-		? $data
100
-		: xml_entites_html($data);
97
+    $depth = $phraseur->depth;
98
+    $phraseur->contenu[$depth] .= preg_match('/^script/', $phraseur->ouvrant[$depth])
99
+        ? $data
100
+        : xml_entites_html($data);
101 101
 }
102 102
 
103 103
 function xml_piElement($phraseur, $target, $data) {
104
-	$depth = $phraseur->depth;
105
-
106
-	if (strtolower($target) != 'php') {
107
-		$phraseur->contenu[$depth] .= $data;
108
-	} else {
109
-		ob_start();
110
-		eval($data);
111
-		$data = ob_get_contents();
112
-		ob_end_clean();
113
-		$phraseur->contenu[$depth] .= $data;
114
-	}
104
+    $depth = $phraseur->depth;
105
+
106
+    if (strtolower($target) != 'php') {
107
+        $phraseur->contenu[$depth] .= $data;
108
+    } else {
109
+        ob_start();
110
+        eval($data);
111
+        $data = ob_get_contents();
112
+        ob_end_clean();
113
+        $phraseur->contenu[$depth] .= $data;
114
+    }
115 115
 }
116 116
 
117 117
 
118 118
 function xml_defaultElement($phraseur, $data) {
119
-	$depth = $phraseur->depth;
119
+    $depth = $phraseur->depth;
120 120
 
121
-	if (!isset($phraseur->contenu[$depth])) {
122
-		$phraseur->contenu[$depth] = '';
123
-	}
124
-	$phraseur->contenu[$depth] .= $data;
121
+    if (!isset($phraseur->contenu[$depth])) {
122
+        $phraseur->contenu[$depth] = '';
123
+    }
124
+    $phraseur->contenu[$depth] .= $data;
125 125
 }
126 126
 
127 127
 function xml_parsestring($phraseur, $data) {
128
-	$phraseur->contenu[$phraseur->depth] = '';
129
-
130
-	if (!xml_parse($phraseur->sax, $data, true)) {
131
-		coordonnees_erreur(
132
-			$phraseur,
133
-			xml_error_string(xml_get_error_code($phraseur->sax))
134
-			. "<br />\n" .
135
-			(!$phraseur->depth ? '' :
136
-				('(' .
137
-					_T('erreur_balise_non_fermee') .
138
-					' <tt>' .
139
-					$phraseur->ouvrant[$phraseur->depth] .
140
-					'</tt> ' .
141
-					_T('ligne') .
142
-					' ' .
143
-					$phraseur->reperes[$phraseur->depth] .
144
-			") <br />\n"))
145
-		);
146
-	}
128
+    $phraseur->contenu[$phraseur->depth] = '';
129
+
130
+    if (!xml_parse($phraseur->sax, $data, true)) {
131
+        coordonnees_erreur(
132
+            $phraseur,
133
+            xml_error_string(xml_get_error_code($phraseur->sax))
134
+            . "<br />\n" .
135
+            (!$phraseur->depth ? '' :
136
+                ('(' .
137
+                    _T('erreur_balise_non_fermee') .
138
+                    ' <tt>' .
139
+                    $phraseur->ouvrant[$phraseur->depth] .
140
+                    '</tt> ' .
141
+                    _T('ligne') .
142
+                    ' ' .
143
+                    $phraseur->reperes[$phraseur->depth] .
144
+            ") <br />\n"))
145
+        );
146
+    }
147 147
 }
148 148
 
149 149
 function coordonnees_erreur($phraseur, $msg) {
150
-	$entete_length = substr_count($phraseur->entete, "\n");
151
-	$phraseur->err[] = [
152
-		$msg,
153
-		xml_get_current_line_number($phraseur->sax) + $entete_length,
154
-		xml_get_current_column_number($phraseur->sax)
155
-	];
150
+    $entete_length = substr_count($phraseur->entete, "\n");
151
+    $phraseur->err[] = [
152
+        $msg,
153
+        xml_get_current_line_number($phraseur->sax) + $entete_length,
154
+        xml_get_current_column_number($phraseur->sax)
155
+    ];
156 156
 }
157 157
 
158 158
 function xml_sax_dist($page, $apply = false, $phraseur = null, $doctype = '', $charset = null) {
159
-	if (is_null($charset)) {
160
-		$charset = $GLOBALS['meta']['charset'];
161
-	}
162
-	if ($apply) {
163
-		ob_start();
164
-		if (is_array($apply)) {
165
-			$r = $page(...$apply);
166
-		} else {
167
-			$r = $page();
168
-		}
169
-		$page = ob_get_contents();
170
-		ob_end_clean();
171
-		// fonction sans aucun "echo", ca doit etre le resultat
172
-		if (!$page) {
173
-			$page = $r;
174
-		}
175
-	}
176
-
177
-	if (!$page) {
178
-		return '';
179
-	}
180
-	// charger la DTD et transcoder les entites,
181
-	// et escamoter le doctype que sax mange en php5 mais pas en  php4
182
-	if (!$doctype) {
183
-		if (!$r = analyser_doctype($page)) {
184
-			$page = _MESSAGE_DOCTYPE . _DOCTYPE_ECRIRE
185
-				. preg_replace(_REGEXP_DOCTYPE, '', $page);
186
-			$r = analyser_doctype($page);
187
-		}
188
-		[$entete, $avail, $grammaire, $rotlvl] = array_pad($r, 4, null);
189
-		$page = substr($page, strlen($entete));
190
-	} else {
191
-		$avail = 'SYSTEM';
192
-		$grammaire = $doctype;
193
-		$rotlvl = basename($grammaire);
194
-	}
195
-
196
-	include_spip('xml/analyser_dtd');
197
-	$dtc = charger_dtd($grammaire, $avail, $rotlvl);
198
-	$page = sax_bug($page, $dtc, $charset);
199
-
200
-	// compatibilite Tidy espace public
201
-	if (!$phraseur) {
202
-		$indenter_xml = charger_fonction('indenter', 'xml');
203
-
204
-		return $indenter_xml($page, $apply);
205
-	}
206
-
207
-	$xml_parser = xml_parser_create($charset);
208
-
209
-	xml_set_element_handler(
210
-		$xml_parser,
211
-		[$phraseur, 'debutElement'],
212
-		[$phraseur, 'finElement']
213
-	);
214
-
215
-	xml_set_character_data_handler(
216
-		$xml_parser,
217
-		[$phraseur, 'textElement']
218
-	);
219
-
220
-	xml_set_processing_instruction_handler(
221
-		$xml_parser,
222
-		[$phraseur, 'piElement']
223
-	);
224
-
225
-	xml_set_default_handler(
226
-		$xml_parser,
227
-		[$phraseur, 'defaultElement']
228
-	);
229
-
230
-	xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
231
-
232
-	$phraseur->sax = $xml_parser;
233
-	if (isset($entete)) {
234
-		$phraseur->entete = $entete;
235
-	}
236
-	$phraseur->page = $page;
237
-	$phraseur->dtc = $dtc;
238
-	$phraseur->phraserTout($xml_parser, $page);
239
-	xml_parser_free($xml_parser);
240
-	$phraseur->sax = '';
241
-
242
-	return $phraseur;
159
+    if (is_null($charset)) {
160
+        $charset = $GLOBALS['meta']['charset'];
161
+    }
162
+    if ($apply) {
163
+        ob_start();
164
+        if (is_array($apply)) {
165
+            $r = $page(...$apply);
166
+        } else {
167
+            $r = $page();
168
+        }
169
+        $page = ob_get_contents();
170
+        ob_end_clean();
171
+        // fonction sans aucun "echo", ca doit etre le resultat
172
+        if (!$page) {
173
+            $page = $r;
174
+        }
175
+    }
176
+
177
+    if (!$page) {
178
+        return '';
179
+    }
180
+    // charger la DTD et transcoder les entites,
181
+    // et escamoter le doctype que sax mange en php5 mais pas en  php4
182
+    if (!$doctype) {
183
+        if (!$r = analyser_doctype($page)) {
184
+            $page = _MESSAGE_DOCTYPE . _DOCTYPE_ECRIRE
185
+                . preg_replace(_REGEXP_DOCTYPE, '', $page);
186
+            $r = analyser_doctype($page);
187
+        }
188
+        [$entete, $avail, $grammaire, $rotlvl] = array_pad($r, 4, null);
189
+        $page = substr($page, strlen($entete));
190
+    } else {
191
+        $avail = 'SYSTEM';
192
+        $grammaire = $doctype;
193
+        $rotlvl = basename($grammaire);
194
+    }
195
+
196
+    include_spip('xml/analyser_dtd');
197
+    $dtc = charger_dtd($grammaire, $avail, $rotlvl);
198
+    $page = sax_bug($page, $dtc, $charset);
199
+
200
+    // compatibilite Tidy espace public
201
+    if (!$phraseur) {
202
+        $indenter_xml = charger_fonction('indenter', 'xml');
203
+
204
+        return $indenter_xml($page, $apply);
205
+    }
206
+
207
+    $xml_parser = xml_parser_create($charset);
208
+
209
+    xml_set_element_handler(
210
+        $xml_parser,
211
+        [$phraseur, 'debutElement'],
212
+        [$phraseur, 'finElement']
213
+    );
214
+
215
+    xml_set_character_data_handler(
216
+        $xml_parser,
217
+        [$phraseur, 'textElement']
218
+    );
219
+
220
+    xml_set_processing_instruction_handler(
221
+        $xml_parser,
222
+        [$phraseur, 'piElement']
223
+    );
224
+
225
+    xml_set_default_handler(
226
+        $xml_parser,
227
+        [$phraseur, 'defaultElement']
228
+    );
229
+
230
+    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
231
+
232
+    $phraseur->sax = $xml_parser;
233
+    if (isset($entete)) {
234
+        $phraseur->entete = $entete;
235
+    }
236
+    $phraseur->page = $page;
237
+    $phraseur->dtc = $dtc;
238
+    $phraseur->phraserTout($xml_parser, $page);
239
+    xml_parser_free($xml_parser);
240
+    $phraseur->sax = '';
241
+
242
+    return $phraseur;
243 243
 }
244 244
 
245 245
 // SAX ne dit pas si une Entite est dans un attribut ou non.
@@ -250,24 +250,24 @@  discard block
 block discarded – undo
250 250
 // sinon on se rabat sur ce qu'en connait SPIP en standard.
251 251
 
252 252
 function sax_bug($data, $dtc, $charset = null) {
253
-	if (is_null($charset)) {
254
-		$charset = $GLOBALS['meta']['charset'];
255
-	}
256
-
257
-	if ($dtc) {
258
-		$trans = [];
259
-
260
-		foreach ($dtc->entites as $k => $v) {
261
-			if (!strpos(' amp lt gt quot ', (string) $k)) {
262
-				$trans["&$k;"] = $v;
263
-			}
264
-		}
265
-		$data = strtr($data, $trans);
266
-	} else {
267
-		$data = html2unicode($data, true);
268
-	}
269
-
270
-	return unicode2charset($data, $charset);
253
+    if (is_null($charset)) {
254
+        $charset = $GLOBALS['meta']['charset'];
255
+    }
256
+
257
+    if ($dtc) {
258
+        $trans = [];
259
+
260
+        foreach ($dtc->entites as $k => $v) {
261
+            if (!strpos(' amp lt gt quot ', (string) $k)) {
262
+                $trans["&$k;"] = $v;
263
+            }
264
+        }
265
+        $data = strtr($data, $trans);
266
+    } else {
267
+        $data = html2unicode($data, true);
268
+    }
269
+
270
+    return unicode2charset($data, $charset);
271 271
 }
272 272
 
273 273
 // Retirer < ? xml... ? > et autre PI, ainsi que les commentaires en debut
@@ -277,52 +277,52 @@  discard block
 block discarded – undo
277 277
 // les autres formats RSS n'ont pas de DTD,
278 278
 // mais un XML Schema que SPIP ne fait pas encore lire.
279 279
 function analyser_doctype($data) {
280
-	if (!preg_match(_REGEXP_DOCTYPE, $data, $page)) {
281
-		if (preg_match(_REGEXP_XML, $data, $page)) {
282
-			[, $entete, $topelement] = $page;
283
-			if ($topelement == 'rss') {
284
-				return [
285
-					$entete,
286
-					'PUBLIC',
287
-					_DOCTYPE_RSS,
288
-					'rss-0.91.dtd'
289
-				];
290
-			} else {
291
-				$dtd = $topelement . '.dtd';
292
-				$f = find_in_path($dtd);
293
-				if (file_exists($f)) {
294
-					return [$entete, 'SYSTEM', $f, $dtd];
295
-				}
296
-			}
297
-		}
298
-		spip_log('Dtd pas vu pour ' . substr($data, 0, 100));
299
-
300
-		return [];
301
-	}
302
-	[$entete, , $topelement, $avail, $suite] = $page;
303
-
304
-	if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r)) {
305
-		if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r)) {
306
-			return [];
307
-		}
308
-	}
309
-	[, $rotlvl, $suite] = $r;
310
-
311
-	if (!$suite) {
312
-		if ($avail != 'SYSTEM') {
313
-			return [];
314
-		}
315
-		$grammaire = $rotlvl;
316
-		$rotlvl = '';
317
-	} else {
318
-		if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r)) {
319
-			if (!preg_match("/^'([^']*)'\s*$/", $suite, $r)) {
320
-				return [];
321
-			}
322
-		}
323
-
324
-		$grammaire = $r[1];
325
-	}
326
-
327
-	return [$entete, $avail, $grammaire, $rotlvl];
280
+    if (!preg_match(_REGEXP_DOCTYPE, $data, $page)) {
281
+        if (preg_match(_REGEXP_XML, $data, $page)) {
282
+            [, $entete, $topelement] = $page;
283
+            if ($topelement == 'rss') {
284
+                return [
285
+                    $entete,
286
+                    'PUBLIC',
287
+                    _DOCTYPE_RSS,
288
+                    'rss-0.91.dtd'
289
+                ];
290
+            } else {
291
+                $dtd = $topelement . '.dtd';
292
+                $f = find_in_path($dtd);
293
+                if (file_exists($f)) {
294
+                    return [$entete, 'SYSTEM', $f, $dtd];
295
+                }
296
+            }
297
+        }
298
+        spip_log('Dtd pas vu pour ' . substr($data, 0, 100));
299
+
300
+        return [];
301
+    }
302
+    [$entete, , $topelement, $avail, $suite] = $page;
303
+
304
+    if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r)) {
305
+        if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r)) {
306
+            return [];
307
+        }
308
+    }
309
+    [, $rotlvl, $suite] = $r;
310
+
311
+    if (!$suite) {
312
+        if ($avail != 'SYSTEM') {
313
+            return [];
314
+        }
315
+        $grammaire = $rotlvl;
316
+        $rotlvl = '';
317
+    } else {
318
+        if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r)) {
319
+            if (!preg_match("/^'([^']*)'\s*$/", $suite, $r)) {
320
+                return [];
321
+            }
322
+        }
323
+
324
+        $grammaire = $r[1];
325
+    }
326
+
327
+    return [$entete, $avail, $grammaire, $rotlvl];
328 328
 }
Please login to merge, or discard this patch.
ecrire/public/compiler.php 1 patch
Indentation   +1208 added lines, -1208 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,19 +744,19 @@  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
-	$p->id_boucle = $context_compil[2] ?? '';
756
-	$p->ligne = $context_compil[3] ?? '';
757
-	$p->lang = $context_compil[4] ?? '';
758
-
759
-	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
+    $p->id_boucle = $context_compil[2] ?? '';
756
+    $p->ligne = $context_compil[3] ?? '';
757
+    $p->lang = $context_compil[4] ?? '';
758
+
759
+    return $p;
760 760
 }
761 761
 
762 762
 /**
@@ -782,12 +782,12 @@  discard block
 block discarded – undo
782 782
  *    - index 1 : Code de l'affectation
783 783
  **/
784 784
 function calculer_dec($nom, $val) {
785
-	$static = 'if (!isset($command[\'' . $nom . '\'])) ';
786
-	// si une variable apparait dans le calcul de la clause
787
-	// il faut la re-evaluer a chaque passage
788
-	if (
789
-		strpos($val, '$') !== false
790
-		/*
785
+    $static = 'if (!isset($command[\'' . $nom . '\'])) ';
786
+    // si une variable apparait dans le calcul de la clause
787
+    // il faut la re-evaluer a chaque passage
788
+    if (
789
+        strpos($val, '$') !== false
790
+        /*
791 791
 		OR strpos($val, 'sql_') !== false
792 792
 		OR (
793 793
 			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
@@ -795,11 +795,11 @@  discard block
 block discarded – undo
795 795
 			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
796 796
 			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
797 797
 		)*/
798
-	) {
799
-		$static = '';
800
-	}
798
+    ) {
799
+        $static = '';
800
+    }
801 801
 
802
-	return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
802
+    return [$static, '$command[\'' . $nom . '\'] = ' . $val . ';'];
803 803
 }
804 804
 
805 805
 /**
@@ -819,32 +819,32 @@  discard block
 block discarded – undo
819 819
  *     Expression PHP décrivant un texte ou un tableau
820 820
  **/
821 821
 function calculer_dump_array($a) {
822
-	if (!is_array($a)) {
823
-		return $a;
824
-	}
825
-	$res = '';
826
-	if ($a and $a[0] == "'?'") {
827
-		return ('(' . calculer_dump_array($a[1]) .
828
-			' ? ' . calculer_dump_array($a[2]) .
829
-			' : ' . calculer_dump_array($a[3]) .
830
-			')');
831
-	} else {
832
-		foreach ($a as $k => $v) {
833
-			$showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
834
-			$res .= ', ' . $showk . calculer_dump_array($v);
835
-		}
836
-
837
-		return "\n\t\t\tarray(" . substr($res, 2) . ')';
838
-	}
822
+    if (!is_array($a)) {
823
+        return $a;
824
+    }
825
+    $res = '';
826
+    if ($a and $a[0] == "'?'") {
827
+        return ('(' . calculer_dump_array($a[1]) .
828
+            ' ? ' . calculer_dump_array($a[2]) .
829
+            ' : ' . calculer_dump_array($a[3]) .
830
+            ')');
831
+    } else {
832
+        foreach ($a as $k => $v) {
833
+            $showk = (is_numeric($k) ? '' : sql_quote($k) . ' => ');
834
+            $res .= ', ' . $showk . calculer_dump_array($v);
835
+        }
836
+
837
+        return "\n\t\t\tarray(" . substr($res, 2) . ')';
838
+    }
839 839
 }
840 840
 
841 841
 function calculer_dump_join($a) {
842
-	$res = '';
843
-	foreach ($a as $k => $v) {
844
-		$res .= ", '$k' => array(" . implode(',', $v) . ')';
845
-	}
842
+    $res = '';
843
+    foreach ($a as $k => $v) {
844
+        $res .= ", '$k' => array(" . implode(',', $v) . ')';
845
+    }
846 846
 
847
-	return 'array(' . substr($res, 2) . ')';
847
+    return 'array(' . substr($res, 2) . ')';
848 848
 }
849 849
 
850 850
 /**
@@ -856,12 +856,12 @@  discard block
 block discarded – undo
856 856
  *     Code PHP construisant un tableau des alias et noms des tables du FROM
857 857
  **/
858 858
 function calculer_from(&$boucle) {
859
-	$res = '';
860
-	foreach ($boucle->from as $k => $v) {
861
-		$res .= ",'$k' => '$v'";
862
-	}
859
+    $res = '';
860
+    foreach ($boucle->from as $k => $v) {
861
+        $res .= ",'$k' => '$v'";
862
+    }
863 863
 
864
-	return 'array(' . substr($res, 1) . ')';
864
+    return 'array(' . substr($res, 1) . ')';
865 865
 }
866 866
 
867 867
 /**
@@ -874,30 +874,30 @@  discard block
 block discarded – undo
874 874
  *     Code PHP construisant un tableau des alias et type de jointure du FROM
875 875
  **/
876 876
 function calculer_from_type(&$boucle) {
877
-	$res = '';
878
-	foreach ($boucle->from_type as $k => $v) {
879
-		$res .= ",'$k' => '$v'";
880
-	}
877
+    $res = '';
878
+    foreach ($boucle->from_type as $k => $v) {
879
+        $res .= ",'$k' => '$v'";
880
+    }
881 881
 
882
-	return 'array(' . substr($res, 1) . ')';
882
+    return 'array(' . substr($res, 1) . ')';
883 883
 }
884 884
 
885 885
 function calculer_order(&$boucle) {
886
-	if (
887
-		!$order = $boucle->order
888
-		and !$order = $boucle->default_order
889
-	) {
890
-		$order = [];
891
-	}
892
-
893
-	/*if (isset($boucle->modificateur['collate'])){
886
+    if (
887
+        !$order = $boucle->order
888
+        and !$order = $boucle->default_order
889
+    ) {
890
+        $order = [];
891
+    }
892
+
893
+    /*if (isset($boucle->modificateur['collate'])){
894 894
 		$col = "." . $boucle->modificateur['collate'];
895 895
 		foreach($order as $k=>$o)
896 896
 			if (strpos($order[$k],'COLLATE')===false)
897 897
 				$order[$k].= $col;
898 898
 	}*/
899 899
 
900
-	return join(', ', $order);
900
+    return join(', ', $order);
901 901
 }
902 902
 
903 903
 // Production du code PHP a partir de la sequence livree par le phraseur
@@ -906,62 +906,62 @@  discard block
 block discarded – undo
906 906
 // (qui sera argument d'un Return ou la partie droite d'une affectation).
907 907
 
908 908
 function calculer_liste($tableau, $descr, &$boucles, $id_boucle = '') {
909
-	if (!$tableau) {
910
-		return "''";
911
-	}
912
-	if (is_string($descr)) {
913
-		if (isset($boucles[$descr])) {
914
-			$idb = $descr;
915
-			$descr = [];
916
-			if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
917
-				$descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
918
-			}
919
-			if (isset($boucles[$idb]->descr['sourcefile'])) {
920
-				$descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
921
-			}
922
-		}
923
-		else {
924
-			$descr = [];
925
-		}
926
-	}
927
-	if (!isset($descr['niv'])) {
928
-		$descr['niv'] = 0;
929
-	}
930
-	$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
931
-	if ($codes === false) {
932
-		return false;
933
-	}
934
-	$n = is_countable($codes) ? count($codes) : 0;
935
-	if (!$n) {
936
-		return "''";
937
-	}
938
-	$tab = str_repeat("\t", $descr['niv']);
939
-	if (_request('var_mode_affiche') != 'validation') {
940
-		if ($n == 1) {
941
-			return $codes[0];
942
-		} else {
943
-			$res = '';
944
-			foreach ($codes as $code) {
945
-				if (
946
-					!preg_match("/^'[^']*'$/", $code)
947
-					or substr($res, -1, 1) !== "'"
948
-				) {
949
-					$res .= " .\n$tab$code";
950
-				} else {
951
-					$res = substr($res, 0, -1) . substr($code, 1);
952
-				}
953
-			}
954
-
955
-			return '(' . substr($res, 2 + $descr['niv']) . ')';
956
-		}
957
-	} else {
958
-		$nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
959
-
960
-		return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
961
-			" ,\n$tab",
962
-			$codes
963
-		) . ')))';
964
-	}
909
+    if (!$tableau) {
910
+        return "''";
911
+    }
912
+    if (is_string($descr)) {
913
+        if (isset($boucles[$descr])) {
914
+            $idb = $descr;
915
+            $descr = [];
916
+            if (isset($boucles[$idb]->descr['id_mere_contexte'])) {
917
+                $descr['id_mere'] = $boucles[$idb]->descr['id_mere_contexte'];
918
+            }
919
+            if (isset($boucles[$idb]->descr['sourcefile'])) {
920
+                $descr['sourcefile'] = $boucles[$idb]->descr['sourcefile'];
921
+            }
922
+        }
923
+        else {
924
+            $descr = [];
925
+        }
926
+    }
927
+    if (!isset($descr['niv'])) {
928
+        $descr['niv'] = 0;
929
+    }
930
+    $codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
931
+    if ($codes === false) {
932
+        return false;
933
+    }
934
+    $n = is_countable($codes) ? count($codes) : 0;
935
+    if (!$n) {
936
+        return "''";
937
+    }
938
+    $tab = str_repeat("\t", $descr['niv']);
939
+    if (_request('var_mode_affiche') != 'validation') {
940
+        if ($n == 1) {
941
+            return $codes[0];
942
+        } else {
943
+            $res = '';
944
+            foreach ($codes as $code) {
945
+                if (
946
+                    !preg_match("/^'[^']*'$/", $code)
947
+                    or substr($res, -1, 1) !== "'"
948
+                ) {
949
+                    $res .= " .\n$tab$code";
950
+                } else {
951
+                    $res = substr($res, 0, -1) . substr($code, 1);
952
+                }
953
+            }
954
+
955
+            return '(' . substr($res, 2 + $descr['niv']) . ')';
956
+        }
957
+    } else {
958
+        $nom = $descr['nom'] . $id_boucle . ($descr['niv'] ?: '');
959
+
960
+        return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(
961
+            " ,\n$tab",
962
+            $codes
963
+        ) . ')))';
964
+    }
965 965
 }
966 966
 
967 967
 
@@ -971,213 +971,213 @@  discard block
 block discarded – undo
971 971
 
972 972
 function compile_cas($tableau, $descr, &$boucles, $id_boucle) {
973 973
 
974
-	$codes = [];
975
-	// cas de la boucle recursive
976
-	if (is_array($id_boucle)) {
977
-		$id_boucle = $id_boucle[0];
978
-	}
979
-	$type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
980
-	$tab = str_repeat("\t", ++$descr['niv']);
981
-	$mode = _request('var_mode_affiche');
982
-	$err_e_c = '';
983
-	// chaque commentaire introduit dans le code doit commencer
984
-	// par un caractere distinguant le cas, pour exploitation par debug.
985
-	foreach ($tableau as $p) {
986
-		switch ($p->type) {
987
-			// texte seul
988
-			case 'texte':
989
-				$code = sandbox_composer_texte($p->texte, $p);
990
-				$commentaire = strlen($p->texte) . ' signes';
991
-				$avant = '';
992
-				$apres = '';
993
-				$altern = "''";
994
-				break;
995
-
996
-			case 'polyglotte':
997
-				$code = '';
998
-				foreach ($p->traductions as $k => $v) {
999
-					$code .= ",'" .
1000
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1001
-						"' => '" .
1002
-						str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1003
-						"'";
1004
-				}
1005
-				$code = 'choisir_traduction(array(' .
1006
-					substr($code, 1) .
1007
-					'))';
1008
-				$commentaire = '&';
1009
-				$avant = '';
1010
-				$apres = '';
1011
-				$altern = "''";
1012
-				break;
1013
-
1014
-			// inclure
1015
-			case 'include':
1016
-				$p->descr = $descr;
1017
-				$code = calculer_inclure($p, $boucles, $id_boucle);
1018
-				if ($code === false) {
1019
-					$err_e_c = true;
1020
-					$code = "''";
1021
-				} else {
1022
-					$commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1023
-					$avant = '';
1024
-					$apres = '';
1025
-					$altern = "''";
1026
-				}
1027
-				break;
1028
-
1029
-			// boucle
1030
-			case TYPE_RECURSIF:
1031
-				$nom = $p->id_boucle;
1032
-				$newdescr = $descr;
1033
-				$newdescr['id_mere'] = $nom;
1034
-				$newdescr['niv']++;
1035
-				$preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1036
-				$avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1037
-				$apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1038
-				$postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1039
-				$newdescr['niv']--;
1040
-				$altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1041
-				if (
1042
-					$preaff === false
1043
-					or $avant === false
1044
-					or $apres === false
1045
-					or $altern === false
1046
-					or $postaff === false
1047
-				) {
1048
-					$err_e_c = true;
1049
-					$code = "''";
1050
-				} else {
1051
-					$code = 'BOUCLE' .
1052
-						str_replace('-', '_', $nom) . $descr['nom'] .
1053
-						'($Cache, $Pile, $doublons, $Numrows, $SP)';
1054
-					$commentaire = "?$nom";
1055
-					if (
1056
-						!$boucles[$nom]->milieu
1057
-						and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1058
-					) {
1059
-						if ($preaff != "''") {
1060
-							$code .= "\n. $preaff";
1061
-						}
1062
-						if ($altern != "''") {
1063
-							$code .= "\n. $altern";
1064
-						}
1065
-						if ($postaff != "''") {
1066
-							$code .= "\n. $postaff";
1067
-						}
1068
-						if ($avant <> "''" or $apres <> "''") {
1069
-							spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1070
-						}
1071
-						$avant = $apres = $altern = "''";
1072
-					} else {
1073
-						if ($preaff != "''") {
1074
-							$avant = compile_concatene_parties_codes($preaff, $avant);
1075
-							$altern = compile_concatene_parties_codes($preaff, $altern);
1076
-						}
1077
-						if ($postaff != "''") {
1078
-							$apres = compile_concatene_parties_codes($apres, $postaff);
1079
-							$altern = compile_concatene_parties_codes($altern, $postaff);
1080
-						}
1081
-						if ($altern != "''") {
1082
-							$altern = "($altern)";
1083
-						}
1084
-					}
1085
-				}
1086
-				break;
1087
-
1088
-			case 'idiome':
1089
-				$l = [];
1090
-				$code = '';
1091
-				foreach ($p->arg as $k => $v) {
1092
-					$_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1093
-					if ($k) {
1094
-						$l[] = _q($k) . ' => ' . $_v;
1095
-					} else {
1096
-						$code = $_v;
1097
-					}
1098
-				}
1099
-				// Si le module n'est pas fourni, l'expliciter sauf si calculé
1100
-				if ($p->module) {
1101
-					$m = $p->module . ':' . $p->nom_champ;
1102
-				} elseif ($p->nom_champ) {
1103
-					$m = MODULES_IDIOMES . ':' . $p->nom_champ;
1104
-				} else {
1105
-					$m = '';
1106
-				}
1107
-
1108
-				$code = (!$code ? "'$m'" :
1109
-						($m ? "'$m' . $code" :
1110
-							("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1111
-					. (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1112
-				$code = "_T($code)";
1113
-				if ($p->param) {
1114
-					$p->id_boucle = $id_boucle;
1115
-					$p->boucles = &$boucles;
1116
-					$code = compose_filtres($p, $code);
1117
-				}
1118
-				$commentaire = ':';
1119
-				$avant = '';
1120
-				$apres = '';
1121
-				$altern = "''";
1122
-				break;
1123
-
1124
-			case 'champ':
1125
-				// cette structure pourrait etre completee des le phrase' (a faire)
1126
-				$p->id_boucle = $id_boucle;
1127
-				$p->boucles = &$boucles;
1128
-				$p->descr = $descr;
1129
-				#$p->interdire_scripts = true;
1130
-				$p->type_requete = $type;
1131
-
1132
-				$code = calculer_champ($p);
1133
-				$commentaire = '#' . $p->nom_champ . $p->etoile;
1134
-				$avant = calculer_liste(
1135
-					$p->avant,
1136
-					$descr,
1137
-					$boucles,
1138
-					$id_boucle
1139
-				);
1140
-				$apres = calculer_liste(
1141
-					$p->apres,
1142
-					$descr,
1143
-					$boucles,
1144
-					$id_boucle
1145
-				);
1146
-				$altern = "''";
1147
-				// Si la valeur est destinee a une comparaison a ''
1148
-				// forcer la conversion en une chaine par strval
1149
-				// si ca peut etre autre chose qu'une chaine
1150
-				if (
1151
-					($avant != "''" or $apres != "''")
1152
-					and $code[0] != "'"
974
+    $codes = [];
975
+    // cas de la boucle recursive
976
+    if (is_array($id_boucle)) {
977
+        $id_boucle = $id_boucle[0];
978
+    }
979
+    $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
980
+    $tab = str_repeat("\t", ++$descr['niv']);
981
+    $mode = _request('var_mode_affiche');
982
+    $err_e_c = '';
983
+    // chaque commentaire introduit dans le code doit commencer
984
+    // par un caractere distinguant le cas, pour exploitation par debug.
985
+    foreach ($tableau as $p) {
986
+        switch ($p->type) {
987
+            // texte seul
988
+            case 'texte':
989
+                $code = sandbox_composer_texte($p->texte, $p);
990
+                $commentaire = strlen($p->texte) . ' signes';
991
+                $avant = '';
992
+                $apres = '';
993
+                $altern = "''";
994
+                break;
995
+
996
+            case 'polyglotte':
997
+                $code = '';
998
+                foreach ($p->traductions as $k => $v) {
999
+                    $code .= ",'" .
1000
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $k) .
1001
+                        "' => '" .
1002
+                        str_replace(['\\', "'"], ['\\\\', "\\'"], $v) .
1003
+                        "'";
1004
+                }
1005
+                $code = 'choisir_traduction(array(' .
1006
+                    substr($code, 1) .
1007
+                    '))';
1008
+                $commentaire = '&';
1009
+                $avant = '';
1010
+                $apres = '';
1011
+                $altern = "''";
1012
+                break;
1013
+
1014
+            // inclure
1015
+            case 'include':
1016
+                $p->descr = $descr;
1017
+                $code = calculer_inclure($p, $boucles, $id_boucle);
1018
+                if ($code === false) {
1019
+                    $err_e_c = true;
1020
+                    $code = "''";
1021
+                } else {
1022
+                    $commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
1023
+                    $avant = '';
1024
+                    $apres = '';
1025
+                    $altern = "''";
1026
+                }
1027
+                break;
1028
+
1029
+            // boucle
1030
+            case TYPE_RECURSIF:
1031
+                $nom = $p->id_boucle;
1032
+                $newdescr = $descr;
1033
+                $newdescr['id_mere'] = $nom;
1034
+                $newdescr['niv']++;
1035
+                $preaff = calculer_liste($p->preaff, $newdescr, $boucles, $id_boucle);
1036
+                $avant = calculer_liste($p->avant, $newdescr, $boucles, $id_boucle);
1037
+                $apres = calculer_liste($p->apres, $newdescr, $boucles, $id_boucle);
1038
+                $postaff = calculer_liste($p->postaff, $newdescr, $boucles, $id_boucle);
1039
+                $newdescr['niv']--;
1040
+                $altern = calculer_liste($p->altern, $newdescr, $boucles, $id_boucle);
1041
+                if (
1042
+                    $preaff === false
1043
+                    or $avant === false
1044
+                    or $apres === false
1045
+                    or $altern === false
1046
+                    or $postaff === false
1047
+                ) {
1048
+                    $err_e_c = true;
1049
+                    $code = "''";
1050
+                } else {
1051
+                    $code = 'BOUCLE' .
1052
+                        str_replace('-', '_', $nom) . $descr['nom'] .
1053
+                        '($Cache, $Pile, $doublons, $Numrows, $SP)';
1054
+                    $commentaire = "?$nom";
1055
+                    if (
1056
+                        !$boucles[$nom]->milieu
1057
+                        and $boucles[$nom]->type_requete <> TYPE_RECURSIF
1058
+                    ) {
1059
+                        if ($preaff != "''") {
1060
+                            $code .= "\n. $preaff";
1061
+                        }
1062
+                        if ($altern != "''") {
1063
+                            $code .= "\n. $altern";
1064
+                        }
1065
+                        if ($postaff != "''") {
1066
+                            $code .= "\n. $postaff";
1067
+                        }
1068
+                        if ($avant <> "''" or $apres <> "''") {
1069
+                            spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]");
1070
+                        }
1071
+                        $avant = $apres = $altern = "''";
1072
+                    } else {
1073
+                        if ($preaff != "''") {
1074
+                            $avant = compile_concatene_parties_codes($preaff, $avant);
1075
+                            $altern = compile_concatene_parties_codes($preaff, $altern);
1076
+                        }
1077
+                        if ($postaff != "''") {
1078
+                            $apres = compile_concatene_parties_codes($apres, $postaff);
1079
+                            $altern = compile_concatene_parties_codes($altern, $postaff);
1080
+                        }
1081
+                        if ($altern != "''") {
1082
+                            $altern = "($altern)";
1083
+                        }
1084
+                    }
1085
+                }
1086
+                break;
1087
+
1088
+            case 'idiome':
1089
+                $l = [];
1090
+                $code = '';
1091
+                foreach ($p->arg as $k => $v) {
1092
+                    $_v = calculer_liste($v, $descr, $boucles, $id_boucle);
1093
+                    if ($k) {
1094
+                        $l[] = _q($k) . ' => ' . $_v;
1095
+                    } else {
1096
+                        $code = $_v;
1097
+                    }
1098
+                }
1099
+                // Si le module n'est pas fourni, l'expliciter sauf si calculé
1100
+                if ($p->module) {
1101
+                    $m = $p->module . ':' . $p->nom_champ;
1102
+                } elseif ($p->nom_champ) {
1103
+                    $m = MODULES_IDIOMES . ':' . $p->nom_champ;
1104
+                } else {
1105
+                    $m = '';
1106
+                }
1107
+
1108
+                $code = (!$code ? "'$m'" :
1109
+                        ($m ? "'$m' . $code" :
1110
+                            ("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
1111
+                    . (!$l ? '' : (', array(' . implode(",\n", $l) . ')'));
1112
+                $code = "_T($code)";
1113
+                if ($p->param) {
1114
+                    $p->id_boucle = $id_boucle;
1115
+                    $p->boucles = &$boucles;
1116
+                    $code = compose_filtres($p, $code);
1117
+                }
1118
+                $commentaire = ':';
1119
+                $avant = '';
1120
+                $apres = '';
1121
+                $altern = "''";
1122
+                break;
1123
+
1124
+            case 'champ':
1125
+                // cette structure pourrait etre completee des le phrase' (a faire)
1126
+                $p->id_boucle = $id_boucle;
1127
+                $p->boucles = &$boucles;
1128
+                $p->descr = $descr;
1129
+                #$p->interdire_scripts = true;
1130
+                $p->type_requete = $type;
1131
+
1132
+                $code = calculer_champ($p);
1133
+                $commentaire = '#' . $p->nom_champ . $p->etoile;
1134
+                $avant = calculer_liste(
1135
+                    $p->avant,
1136
+                    $descr,
1137
+                    $boucles,
1138
+                    $id_boucle
1139
+                );
1140
+                $apres = calculer_liste(
1141
+                    $p->apres,
1142
+                    $descr,
1143
+                    $boucles,
1144
+                    $id_boucle
1145
+                );
1146
+                $altern = "''";
1147
+                // Si la valeur est destinee a une comparaison a ''
1148
+                // forcer la conversion en une chaine par strval
1149
+                // si ca peut etre autre chose qu'une chaine
1150
+                if (
1151
+                    ($avant != "''" or $apres != "''")
1152
+                    and $code[0] != "'"
1153 1153
 #			AND (strpos($code,'interdire_scripts') !== 0)
1154
-					and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1155
-					and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1156
-					and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1157
-				) {
1158
-					$code = "strval($code)";
1159
-				}
1160
-				break;
1161
-
1162
-			default:
1163
-				// Erreur de construction de l'arbre de syntaxe abstraite
1164
-				$code = "''";
1165
-				$p->descr = $descr;
1166
-				$err_e_c = _T('zbug_erreur_compilation');
1167
-				erreur_squelette($err_e_c, $p);
1168
-		} // switch
1169
-
1170
-		if ($code != "''") {
1171
-			$code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1172
-			$codes[] = (($mode == 'validation') ?
1173
-				"array($code, '$commentaire', " . $p->ligne . ')'
1174
-				: (($mode == 'code') ?
1175
-					"\n// $commentaire\n$code" :
1176
-					$code));
1177
-		}
1178
-	} // foreach
1179
-
1180
-	return $err_e_c ? false : $codes;
1154
+                    and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
1155
+                    and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
1156
+                    and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)
1157
+                ) {
1158
+                    $code = "strval($code)";
1159
+                }
1160
+                break;
1161
+
1162
+            default:
1163
+                // Erreur de construction de l'arbre de syntaxe abstraite
1164
+                $code = "''";
1165
+                $p->descr = $descr;
1166
+                $err_e_c = _T('zbug_erreur_compilation');
1167
+                erreur_squelette($err_e_c, $p);
1168
+        } // switch
1169
+
1170
+        if ($code != "''") {
1171
+            $code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
1172
+            $codes[] = (($mode == 'validation') ?
1173
+                "array($code, '$commentaire', " . $p->ligne . ')'
1174
+                : (($mode == 'code') ?
1175
+                    "\n// $commentaire\n$code" :
1176
+                    $code));
1177
+        }
1178
+    } // foreach
1179
+
1180
+    return $err_e_c ? false : $codes;
1181 1181
 }
1182 1182
 
1183 1183
 /**
@@ -1187,13 +1187,13 @@  discard block
 block discarded – undo
1187 1187
  * @return string
1188 1188
  */
1189 1189
 function compile_concatene_parties_codes($partie1, $partie2) {
1190
-	if ($partie1 === "''") {
1191
-		return $partie2;
1192
-	}
1193
-	if ($partie2 === "''") {
1194
-		return $partie1;
1195
-	}
1196
-	return "$partie1\n. $partie2";
1190
+    if ($partie1 === "''") {
1191
+        return $partie2;
1192
+    }
1193
+    if ($partie2 === "''") {
1194
+        return $partie1;
1195
+    }
1196
+    return "$partie1\n. $partie2";
1197 1197
 }
1198 1198
 
1199 1199
 
@@ -1217,56 +1217,56 @@  discard block
 block discarded – undo
1217 1217
  * @return mixed|string
1218 1218
  */
1219 1219
 function compile_retour($code, $avant, $apres, $altern, $tab, $n) {
1220
-	if ($avant === "''") {
1221
-		$avant = '';
1222
-	}
1223
-	if ($apres === "''") {
1224
-		$apres = '';
1225
-	}
1226
-	if ($avant or $apres or ($altern !== "''")) {
1227
-		if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1228
-			$t = $code;
1229
-			$cond = '';
1230
-		} elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1231
-			$t = $r[2];
1232
-			$cond = '!' . $r[1];
1233
-		} else {
1234
-			if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1235
-				$t = $r[2];
1236
-				$cond = $r[1];
1237
-			} else {
1238
-				$t = '$t' . $n;
1239
-				$cond = "($t = $code)!==''";
1240
-			}
1241
-		}
1242
-
1243
-		$res = (!$avant ? '' : "$avant . ") .
1244
-			$t .
1245
-			(!$apres ? '' : " . $apres");
1246
-
1247
-		if ($res !== $t) {
1248
-			$res = "($res)";
1249
-		}
1250
-
1251
-		$code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1252
-	}
1253
-
1254
-	return $code;
1220
+    if ($avant === "''") {
1221
+        $avant = '';
1222
+    }
1223
+    if ($apres === "''") {
1224
+        $apres = '';
1225
+    }
1226
+    if ($avant or $apres or ($altern !== "''")) {
1227
+        if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
1228
+            $t = $code;
1229
+            $cond = '';
1230
+        } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) {
1231
+            $t = $r[2];
1232
+            $cond = '!' . $r[1];
1233
+        } else {
1234
+            if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) {
1235
+                $t = $r[2];
1236
+                $cond = $r[1];
1237
+            } else {
1238
+                $t = '$t' . $n;
1239
+                $cond = "($t = $code)!==''";
1240
+            }
1241
+        }
1242
+
1243
+        $res = (!$avant ? '' : "$avant . ") .
1244
+            $t .
1245
+            (!$apres ? '' : " . $apres");
1246
+
1247
+        if ($res !== $t) {
1248
+            $res = "($res)";
1249
+        }
1250
+
1251
+        $code = (!$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)");
1252
+    }
1253
+
1254
+    return $code;
1255 1255
 }
1256 1256
 
1257 1257
 
1258 1258
 function compile_inclure_doublons($lexemes) {
1259
-	foreach ($lexemes as $v) {
1260
-		if ($v->type === 'include' and $v->param) {
1261
-			foreach ($v->param as $r) {
1262
-				if (trim($r[0]) === 'doublons') {
1263
-					return true;
1264
-				}
1265
-			}
1266
-		}
1267
-	}
1268
-
1269
-	return false;
1259
+    foreach ($lexemes as $v) {
1260
+        if ($v->type === 'include' and $v->param) {
1261
+            foreach ($v->param as $r) {
1262
+                if (trim($r[0]) === 'doublons') {
1263
+                    return true;
1264
+                }
1265
+            }
1266
+        }
1267
+    }
1268
+
1269
+    return false;
1270 1270
 }
1271 1271
 
1272 1272
 // Prend en argument le texte d'un squelette, le nom de son fichier d'origine,
@@ -1285,354 +1285,354 @@  discard block
 block discarded – undo
1285 1285
 // En cas d'erreur, elle retournera un tableau des 2 premiers elements seulement
1286 1286
 
1287 1287
 function public_compiler_dist($squelette, $nom, $gram, $sourcefile, string $connect = '') {
1288
-	// Pre-traitement : reperer le charset du squelette, et le convertir
1289
-	// Bonus : supprime le BOM
1290
-	include_spip('inc/charsets');
1291
-	$squelette = transcoder_page($squelette);
1292
-
1293
-	// rendre inertes les echappements de #[](){}<>
1294
-	$i = 0;
1295
-	while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1296
-		$i++;
1297
-	}
1298
-	$squelette = preg_replace_callback(
1299
-		',\\\\([#[()\]{}<>]),',
1300
-		fn($a) => "$inerte-" . ord($a[1]) . '-',
1301
-		$squelette,
1302
-		-1,
1303
-		$esc
1304
-	);
1305
-
1306
-	$descr = [
1307
-		'nom' => $nom,
1308
-		'gram' => $gram,
1309
-		'sourcefile' => $sourcefile,
1310
-		'squelette' => $squelette
1311
-	];
1312
-
1313
-	// Phraser le squelette, selon sa grammaire
1314
-
1315
-	$boucles = [];
1316
-	$f = charger_fonction('phraser_' . $gram, 'public');
1317
-
1318
-	$squelette = $f($squelette, '', $boucles, $descr);
1319
-
1320
-	$boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1321
-
1322
-	// restituer les echappements
1323
-	if ($esc) {
1324
-		foreach ($boucles as $i => $boucle) {
1325
-			$boucles[$i]->return = preg_replace_callback(
1326
-				",$inerte-(\d+)-,",
1327
-				fn($a) => chr($a[1]),
1328
-				$boucle->return
1329
-			);
1330
-			$boucles[$i]->descr['squelette'] = preg_replace_callback(
1331
-				",$inerte-(\d+)-,",
1332
-				fn($a) => '\\\\' . chr($a[1]),
1333
-				$boucle->descr['squelette']
1334
-			);
1335
-		}
1336
-	}
1337
-
1338
-	$debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1339
-	if ($debug) {
1340
-		include_spip('public/decompiler');
1341
-		foreach ($boucles as $id => $boucle) {
1342
-			if ($id) {
1343
-				$decomp = "\n/* BOUCLE " .
1344
-					$boucle->type_requete .
1345
-					' ' .
1346
-					str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1347
-					($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1348
-					" */\n";
1349
-			} else {
1350
-				$decomp = ("\n/*\n" .
1351
-					str_replace('*/', '* /', public_decompiler($squelette, $gram))
1352
-					. "\n*/");
1353
-			}
1354
-			$boucles[$id]->return = $decomp . $boucle->return;
1355
-			$GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1356
-		}
1357
-	}
1358
-
1359
-	return $boucles;
1288
+    // Pre-traitement : reperer le charset du squelette, et le convertir
1289
+    // Bonus : supprime le BOM
1290
+    include_spip('inc/charsets');
1291
+    $squelette = transcoder_page($squelette);
1292
+
1293
+    // rendre inertes les echappements de #[](){}<>
1294
+    $i = 0;
1295
+    while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
1296
+        $i++;
1297
+    }
1298
+    $squelette = preg_replace_callback(
1299
+        ',\\\\([#[()\]{}<>]),',
1300
+        fn($a) => "$inerte-" . ord($a[1]) . '-',
1301
+        $squelette,
1302
+        -1,
1303
+        $esc
1304
+    );
1305
+
1306
+    $descr = [
1307
+        'nom' => $nom,
1308
+        'gram' => $gram,
1309
+        'sourcefile' => $sourcefile,
1310
+        'squelette' => $squelette
1311
+    ];
1312
+
1313
+    // Phraser le squelette, selon sa grammaire
1314
+
1315
+    $boucles = [];
1316
+    $f = charger_fonction('phraser_' . $gram, 'public');
1317
+
1318
+    $squelette = $f($squelette, '', $boucles, $descr);
1319
+
1320
+    $boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1321
+
1322
+    // restituer les echappements
1323
+    if ($esc) {
1324
+        foreach ($boucles as $i => $boucle) {
1325
+            $boucles[$i]->return = preg_replace_callback(
1326
+                ",$inerte-(\d+)-,",
1327
+                fn($a) => chr($a[1]),
1328
+                $boucle->return
1329
+            );
1330
+            $boucles[$i]->descr['squelette'] = preg_replace_callback(
1331
+                ",$inerte-(\d+)-,",
1332
+                fn($a) => '\\\\' . chr($a[1]),
1333
+                $boucle->descr['squelette']
1334
+            );
1335
+        }
1336
+    }
1337
+
1338
+    $debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug');
1339
+    if ($debug) {
1340
+        include_spip('public/decompiler');
1341
+        foreach ($boucles as $id => $boucle) {
1342
+            if ($id) {
1343
+                $decomp = "\n/* BOUCLE " .
1344
+                    $boucle->type_requete .
1345
+                    ' ' .
1346
+                    str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1347
+                    ($boucle->debug ? "\n *\n * " . implode("\n * ", $boucle->debug) . "\n" : '') .
1348
+                    " */\n";
1349
+            } else {
1350
+                $decomp = ("\n/*\n" .
1351
+                    str_replace('*/', '* /', public_decompiler($squelette, $gram))
1352
+                    . "\n*/");
1353
+            }
1354
+            $boucles[$id]->return = $decomp . $boucle->return;
1355
+            $GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return;
1356
+        }
1357
+    }
1358
+
1359
+    return $boucles;
1360 1360
 }
1361 1361
 
1362 1362
 // Point d'entree pour arbre de syntaxe abstraite fourni en premier argument
1363 1363
 // Autres specifications comme ci-dessus
1364 1364
 
1365 1365
 function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, string $connect = '') {
1366
-	static $trouver_table;
1367
-	spip_timer('calcul_skel');
1368
-
1369
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1370
-		$GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1371
-		$GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1372
-
1373
-		if (!isset($GLOBALS['debug_objets']['principal'])) {
1374
-			$GLOBALS['debug_objets']['principal'] = $nom;
1375
-		}
1376
-	}
1377
-	foreach ($boucles as $id => $boucle) {
1378
-		$GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1379
-	}
1380
-	$descr['documents'] = compile_inclure_doublons($squelette);
1381
-
1382
-	// Demander la description des tables une fois pour toutes
1383
-	if (!$trouver_table) {
1384
-		$trouver_table = charger_fonction('trouver_table', 'base');
1385
-	}
1386
-
1387
-	// reperer si les doublons sont demandes
1388
-	// pour un inclure ou une boucle document
1389
-	// c'est utile a la fonction champs_traitements
1390
-	foreach ($boucles as $id => $boucle) {
1391
-		if (!($type = $boucle->type_requete)) {
1392
-			continue;
1393
-		}
1394
-		if (
1395
-			!$descr['documents'] and (
1396
-				(($type == 'documents') and $boucle->doublons) or
1397
-				compile_inclure_doublons($boucle->avant) or
1398
-				compile_inclure_doublons($boucle->apres) or
1399
-				compile_inclure_doublons($boucle->milieu) or
1400
-				compile_inclure_doublons($boucle->altern))
1401
-		) {
1402
-			$descr['documents'] = true;
1403
-		}
1404
-		if ($type != TYPE_RECURSIF) {
1405
-			if (!$boucles[$id]->sql_serveur and $connect) {
1406
-				$boucles[$id]->sql_serveur = $connect;
1407
-			}
1408
-
1409
-			// chercher dans les iterateurs du repertoire iterateur/
1410
-			if (
1411
-				$g = charger_fonction(
1412
-					preg_replace('/\W/', '_', $boucle->type_requete),
1413
-					'iterateur',
1414
-					true
1415
-				)
1416
-			) {
1417
-				$boucles[$id] = $g($boucle);
1418
-
1419
-				// sinon, en cas de requeteur d'un type predefini,
1420
-				// utiliser les informations donnees par le requeteur
1421
-				// cas "php:xx" et "data:xx".
1422
-			} else {
1423
-				if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1424
-					$requeteur($boucles, $boucle, $id);
1425
-
1426
-					// utiliser la description des champs transmis
1427
-				} else {
1428
-					$show = $trouver_table($type, $boucles[$id]->sql_serveur);
1429
-					// si la table n'existe pas avec le connecteur par defaut,
1430
-					// c'est peut etre une table qui necessite son connecteur dedie fourni
1431
-					// permet une ecriture allegee (GEO) -> (geo:GEO)
1432
-					if (
1433
-						!$show
1434
-						and $show = $trouver_table($type, strtolower($type))
1435
-					) {
1436
-						$boucles[$id]->sql_serveur = strtolower($type);
1437
-					}
1438
-					if ($show) {
1439
-						$boucles[$id]->show = $show;
1440
-						// recopie les infos les plus importantes
1441
-						$boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1442
-						$boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1443
-						$boucles[$id]->from[$x] = $nom_table = $show['table'];
1444
-						$boucles[$id]->iterateur = 'SQL';
1445
-
1446
-						if (empty($boucles[$id]->descr)) {
1447
-							$boucles[$id]->descr = &$descr;
1448
-						}
1449
-						if (
1450
-							(!$boucles[$id]->jointures)
1451
-							and is_array($show['tables_jointures'])
1452
-							and count($x = $show['tables_jointures'])
1453
-						) {
1454
-							$boucles[$id]->jointures = $x;
1455
-						}
1456
-						if ($boucles[$id]->jointures_explicites) {
1457
-							$jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1458
-							while ($j = array_pop($jointures)) {
1459
-								array_unshift($boucles[$id]->jointures, $j);
1460
-							}
1461
-						}
1462
-					} else {
1463
-						// Pas une erreur si la table est optionnelle
1464
-						if ($boucles[$id]->table_optionnelle) {
1465
-							$boucles[$id]->type_requete = '';
1466
-						} else {
1467
-							$boucles[$id]->type_requete = false;
1468
-							$boucle = $boucles[$id];
1469
-							$x = (!$boucle->sql_serveur ? '' :
1470
-									($boucle->sql_serveur . ':')) .
1471
-								$type;
1472
-							$msg = [
1473
-								'zbug_table_inconnue',
1474
-								['table' => $x]
1475
-							];
1476
-							erreur_squelette($msg, $boucle);
1477
-						}
1478
-					}
1479
-				}
1480
-			}
1481
-		}
1482
-	}
1483
-
1484
-	// Commencer par reperer les boucles appelees explicitement
1485
-	// car elles indexent les arguments de maniere derogatoire
1486
-	foreach ($boucles as $id => $boucle) {
1487
-		if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1488
-			$boucles[$id]->descr = &$descr;
1489
-			$rec = &$boucles[$boucle->param[0]];
1490
-			if (!$rec) {
1491
-				$msg = [
1492
-					'zbug_boucle_recursive_undef',
1493
-					['nom' => $boucle->param[0]]
1494
-				];
1495
-				erreur_squelette($msg, $boucle);
1496
-				$boucles[$id]->type_requete = false;
1497
-			} else {
1498
-				$rec->externe = $id;
1499
-				$descr['id_mere'] = $id;
1500
-				$boucles[$id]->return =
1501
-					calculer_liste(
1502
-						[$rec],
1503
-						$descr,
1504
-						$boucles,
1505
-						$boucle->param
1506
-					);
1507
-			}
1508
-		}
1509
-	}
1510
-	foreach ($boucles as $id => $boucle) {
1511
-		$id = strval($id); // attention au type dans index_pile
1512
-		$type = $boucle->type_requete;
1513
-		if ($type and $type != TYPE_RECURSIF) {
1514
-			$res = '';
1515
-			if ($boucle->param) {
1516
-				// retourne un tableau en cas d'erreur
1517
-				$res = calculer_criteres($id, $boucles);
1518
-			}
1519
-			$descr['id_mere'] = $id;
1520
-			$boucles[$id]->return =
1521
-				calculer_liste(
1522
-					$boucle->milieu,
1523
-					$descr,
1524
-					$boucles,
1525
-					$id
1526
-				);
1527
-			// Si les criteres se sont mal compiles
1528
-			// ne pas tenter d'assembler le code final
1529
-			// (mais compiler le corps pour detection d'erreurs)
1530
-			if (is_array($res)) {
1531
-				$boucles[$id]->type_requete = false;
1532
-			}
1533
-		}
1534
-	}
1535
-
1536
-	// idem pour la racine
1537
-	$descr['id_mere'] = '';
1538
-	$corps = calculer_liste($squelette, $descr, $boucles);
1539
-
1540
-
1541
-	// Calcul du corps de toutes les fonctions PHP,
1542
-	// en particulier les requetes SQL et TOTAL_BOUCLE
1543
-	// de'terminables seulement maintenant
1544
-
1545
-	foreach ($boucles as $id => $boucle) {
1546
-		$boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1547
-		if ($boucle->return === false) {
1548
-			$corps = false;
1549
-			continue;
1550
-		}
1551
-		// appeler la fonction de definition de la boucle
1552
-
1553
-		if ($req = $boucle->type_requete) {
1554
-			// boucle personnalisée ?
1555
-			$table = strtoupper($boucle->type_requete);
1556
-			$serveur = strtolower($boucle->sql_serveur);
1557
-			if (
1558
-				// fonction de boucle avec serveur & table
1559
-				(!$serveur or
1560
-					((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1561
-						and (!function_exists($f = $f . '_dist'))
1562
-					)
1563
-				)
1564
-				// fonction de boucle avec table
1565
-				and (!function_exists($f = 'boucle_' . $table))
1566
-				and (!function_exists($f = $f . '_dist'))
1567
-			) {
1568
-				// fonction de boucle standard
1569
-				if (!function_exists($f = 'boucle_DEFAUT')) {
1570
-					$f = 'boucle_DEFAUT_dist';
1571
-				}
1572
-			}
1573
-
1574
-			$req = "\n\n\tstatic \$command = array();\n\t" .
1575
-				"static \$connect;\n\t" .
1576
-				"\$command['connect'] = \$connect = " .
1577
-				_q($boucle->sql_serveur) .
1578
-				';' .
1579
-				$f($id, $boucles);
1580
-		} else {
1581
-			$req = ("\n\treturn '';");
1582
-		}
1583
-
1584
-		$boucles[$id]->return =
1585
-			"\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1586
-			'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1587
-			$req .
1588
-			"\n}\n";
1589
-	}
1590
-
1591
-	// Au final, si le corps ou un critere au moins s'est mal compile
1592
-	// retourner False, sinon inserer leur decompilation
1593
-	if (is_bool($corps)) {
1594
-		return false;
1595
-	}
1596
-
1597
-	$principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1366
+    static $trouver_table;
1367
+    spip_timer('calcul_skel');
1368
+
1369
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
1370
+        $GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1371
+        $GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1372
+
1373
+        if (!isset($GLOBALS['debug_objets']['principal'])) {
1374
+            $GLOBALS['debug_objets']['principal'] = $nom;
1375
+        }
1376
+    }
1377
+    foreach ($boucles as $id => $boucle) {
1378
+        $GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle;
1379
+    }
1380
+    $descr['documents'] = compile_inclure_doublons($squelette);
1381
+
1382
+    // Demander la description des tables une fois pour toutes
1383
+    if (!$trouver_table) {
1384
+        $trouver_table = charger_fonction('trouver_table', 'base');
1385
+    }
1386
+
1387
+    // reperer si les doublons sont demandes
1388
+    // pour un inclure ou une boucle document
1389
+    // c'est utile a la fonction champs_traitements
1390
+    foreach ($boucles as $id => $boucle) {
1391
+        if (!($type = $boucle->type_requete)) {
1392
+            continue;
1393
+        }
1394
+        if (
1395
+            !$descr['documents'] and (
1396
+                (($type == 'documents') and $boucle->doublons) or
1397
+                compile_inclure_doublons($boucle->avant) or
1398
+                compile_inclure_doublons($boucle->apres) or
1399
+                compile_inclure_doublons($boucle->milieu) or
1400
+                compile_inclure_doublons($boucle->altern))
1401
+        ) {
1402
+            $descr['documents'] = true;
1403
+        }
1404
+        if ($type != TYPE_RECURSIF) {
1405
+            if (!$boucles[$id]->sql_serveur and $connect) {
1406
+                $boucles[$id]->sql_serveur = $connect;
1407
+            }
1408
+
1409
+            // chercher dans les iterateurs du repertoire iterateur/
1410
+            if (
1411
+                $g = charger_fonction(
1412
+                    preg_replace('/\W/', '_', $boucle->type_requete),
1413
+                    'iterateur',
1414
+                    true
1415
+                )
1416
+            ) {
1417
+                $boucles[$id] = $g($boucle);
1418
+
1419
+                // sinon, en cas de requeteur d'un type predefini,
1420
+                // utiliser les informations donnees par le requeteur
1421
+                // cas "php:xx" et "data:xx".
1422
+            } else {
1423
+                if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1424
+                    $requeteur($boucles, $boucle, $id);
1425
+
1426
+                    // utiliser la description des champs transmis
1427
+                } else {
1428
+                    $show = $trouver_table($type, $boucles[$id]->sql_serveur);
1429
+                    // si la table n'existe pas avec le connecteur par defaut,
1430
+                    // c'est peut etre une table qui necessite son connecteur dedie fourni
1431
+                    // permet une ecriture allegee (GEO) -> (geo:GEO)
1432
+                    if (
1433
+                        !$show
1434
+                        and $show = $trouver_table($type, strtolower($type))
1435
+                    ) {
1436
+                        $boucles[$id]->sql_serveur = strtolower($type);
1437
+                    }
1438
+                    if ($show) {
1439
+                        $boucles[$id]->show = $show;
1440
+                        // recopie les infos les plus importantes
1441
+                        $boucles[$id]->primary = $show['key']['PRIMARY KEY'] ?? '';
1442
+                        $boucles[$id]->id_table = $x = preg_replace(',^spip_,', '', $show['id_table']);
1443
+                        $boucles[$id]->from[$x] = $nom_table = $show['table'];
1444
+                        $boucles[$id]->iterateur = 'SQL';
1445
+
1446
+                        if (empty($boucles[$id]->descr)) {
1447
+                            $boucles[$id]->descr = &$descr;
1448
+                        }
1449
+                        if (
1450
+                            (!$boucles[$id]->jointures)
1451
+                            and is_array($show['tables_jointures'])
1452
+                            and count($x = $show['tables_jointures'])
1453
+                        ) {
1454
+                            $boucles[$id]->jointures = $x;
1455
+                        }
1456
+                        if ($boucles[$id]->jointures_explicites) {
1457
+                            $jointures = preg_split('/\s+/', $boucles[$id]->jointures_explicites);
1458
+                            while ($j = array_pop($jointures)) {
1459
+                                array_unshift($boucles[$id]->jointures, $j);
1460
+                            }
1461
+                        }
1462
+                    } else {
1463
+                        // Pas une erreur si la table est optionnelle
1464
+                        if ($boucles[$id]->table_optionnelle) {
1465
+                            $boucles[$id]->type_requete = '';
1466
+                        } else {
1467
+                            $boucles[$id]->type_requete = false;
1468
+                            $boucle = $boucles[$id];
1469
+                            $x = (!$boucle->sql_serveur ? '' :
1470
+                                    ($boucle->sql_serveur . ':')) .
1471
+                                $type;
1472
+                            $msg = [
1473
+                                'zbug_table_inconnue',
1474
+                                ['table' => $x]
1475
+                            ];
1476
+                            erreur_squelette($msg, $boucle);
1477
+                        }
1478
+                    }
1479
+                }
1480
+            }
1481
+        }
1482
+    }
1483
+
1484
+    // Commencer par reperer les boucles appelees explicitement
1485
+    // car elles indexent les arguments de maniere derogatoire
1486
+    foreach ($boucles as $id => $boucle) {
1487
+        if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) {
1488
+            $boucles[$id]->descr = &$descr;
1489
+            $rec = &$boucles[$boucle->param[0]];
1490
+            if (!$rec) {
1491
+                $msg = [
1492
+                    'zbug_boucle_recursive_undef',
1493
+                    ['nom' => $boucle->param[0]]
1494
+                ];
1495
+                erreur_squelette($msg, $boucle);
1496
+                $boucles[$id]->type_requete = false;
1497
+            } else {
1498
+                $rec->externe = $id;
1499
+                $descr['id_mere'] = $id;
1500
+                $boucles[$id]->return =
1501
+                    calculer_liste(
1502
+                        [$rec],
1503
+                        $descr,
1504
+                        $boucles,
1505
+                        $boucle->param
1506
+                    );
1507
+            }
1508
+        }
1509
+    }
1510
+    foreach ($boucles as $id => $boucle) {
1511
+        $id = strval($id); // attention au type dans index_pile
1512
+        $type = $boucle->type_requete;
1513
+        if ($type and $type != TYPE_RECURSIF) {
1514
+            $res = '';
1515
+            if ($boucle->param) {
1516
+                // retourne un tableau en cas d'erreur
1517
+                $res = calculer_criteres($id, $boucles);
1518
+            }
1519
+            $descr['id_mere'] = $id;
1520
+            $boucles[$id]->return =
1521
+                calculer_liste(
1522
+                    $boucle->milieu,
1523
+                    $descr,
1524
+                    $boucles,
1525
+                    $id
1526
+                );
1527
+            // Si les criteres se sont mal compiles
1528
+            // ne pas tenter d'assembler le code final
1529
+            // (mais compiler le corps pour detection d'erreurs)
1530
+            if (is_array($res)) {
1531
+                $boucles[$id]->type_requete = false;
1532
+            }
1533
+        }
1534
+    }
1535
+
1536
+    // idem pour la racine
1537
+    $descr['id_mere'] = '';
1538
+    $corps = calculer_liste($squelette, $descr, $boucles);
1539
+
1540
+
1541
+    // Calcul du corps de toutes les fonctions PHP,
1542
+    // en particulier les requetes SQL et TOTAL_BOUCLE
1543
+    // de'terminables seulement maintenant
1544
+
1545
+    foreach ($boucles as $id => $boucle) {
1546
+        $boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1547
+        if ($boucle->return === false) {
1548
+            $corps = false;
1549
+            continue;
1550
+        }
1551
+        // appeler la fonction de definition de la boucle
1552
+
1553
+        if ($req = $boucle->type_requete) {
1554
+            // boucle personnalisée ?
1555
+            $table = strtoupper($boucle->type_requete);
1556
+            $serveur = strtolower($boucle->sql_serveur);
1557
+            if (
1558
+                // fonction de boucle avec serveur & table
1559
+                (!$serveur or
1560
+                    ((!function_exists($f = 'boucle_' . $serveur . '_' . $table))
1561
+                        and (!function_exists($f = $f . '_dist'))
1562
+                    )
1563
+                )
1564
+                // fonction de boucle avec table
1565
+                and (!function_exists($f = 'boucle_' . $table))
1566
+                and (!function_exists($f = $f . '_dist'))
1567
+            ) {
1568
+                // fonction de boucle standard
1569
+                if (!function_exists($f = 'boucle_DEFAUT')) {
1570
+                    $f = 'boucle_DEFAUT_dist';
1571
+                }
1572
+            }
1573
+
1574
+            $req = "\n\n\tstatic \$command = array();\n\t" .
1575
+                "static \$connect;\n\t" .
1576
+                "\$command['connect'] = \$connect = " .
1577
+                _q($boucle->sql_serveur) .
1578
+                ';' .
1579
+                $f($id, $boucles);
1580
+        } else {
1581
+            $req = ("\n\treturn '';");
1582
+        }
1583
+
1584
+        $boucles[$id]->return =
1585
+            "\n\nfunction BOUCLE" . strtr($id, '-', '_') . $nom .
1586
+            '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1587
+            $req .
1588
+            "\n}\n";
1589
+    }
1590
+
1591
+    // Au final, si le corps ou un critere au moins s'est mal compile
1592
+    // retourner False, sinon inserer leur decompilation
1593
+    if (is_bool($corps)) {
1594
+        return false;
1595
+    }
1596
+
1597
+    $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) {
1598 1598
 '
1599
-		// reporter de maniere securisee les doublons inclus
1600
-		. '
1599
+        // reporter de maniere securisee les doublons inclus
1600
+        . '
1601 1601
 	if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"]))
1602 1602
 		$doublons = nettoyer_env_doublons($Pile[0]["doublons"]);
1603 1603
 
1604 1604
 	$connect = ' .
1605
-		_q($connect) . ';
1605
+        _q($connect) . ';
1606 1606
 	$page = ' .
1607
-		// ATTENTION, le calcul de l'expression $corps affectera $Cache
1608
-		// c'est pourquoi on l'affecte a la variable auxiliaire $page.
1609
-		// avant de referencer $Cache
1610
-		$corps . ';
1607
+        // ATTENTION, le calcul de l'expression $corps affectera $Cache
1608
+        // c'est pourquoi on l'affecte a la variable auxiliaire $page.
1609
+        // avant de referencer $Cache
1610
+        $corps . ';
1611 1611
 
1612 1612
 	return analyse_resultat_skel(' . var_export($nom, true)
1613
-		. ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1613
+        . ', $Cache, $page, ' . var_export($sourcefile, true) . ');
1614 1614
 }';
1615 1615
 
1616
-	$secondes = spip_timer('calcul_skel');
1617
-	spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1618
-	// $connect n'est pas sûr : on nettoie
1619
-	$connect = preg_replace(',[^\w],', '', $connect);
1616
+    $secondes = spip_timer('calcul_skel');
1617
+    spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1618
+    // $connect n'est pas sûr : on nettoie
1619
+    $connect = preg_replace(',[^\w],', '', $connect);
1620 1620
 
1621
-	// Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1622
-	$code = new Boucle();
1623
-	$code->descr = $descr;
1624
-	$code->return = '
1621
+    // Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1622
+    $code = new Boucle();
1623
+    $code->descr = $descr;
1624
+    $code->return = '
1625 1625
 //
1626 1626
 // Fonction principale du squelette ' .
1627
-		$sourcefile .
1628
-		($connect ? " pour $connect" : '') .
1629
-		(!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1630
-		"\n//\n" .
1631
-		$principal;
1627
+        $sourcefile .
1628
+        ($connect ? " pour $connect" : '') .
1629
+        (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1630
+        "\n//\n" .
1631
+        $principal;
1632 1632
 
1633
-	$boucles[''] = $code;
1633
+    $boucles[''] = $code;
1634 1634
 
1635
-	return $boucles;
1635
+    return $boucles;
1636 1636
 }
1637 1637
 
1638 1638
 
@@ -1649,18 +1649,18 @@  discard block
 block discarded – undo
1649 1649
  *
1650 1650
  **/
1651 1651
 function requeteur_php_dist(&$boucles, &$boucle, &$id) {
1652
-	if (class_exists($boucle->type_requete)) {
1653
-		$g = charger_fonction('php', 'iterateur');
1654
-		$boucles[$id] = $g($boucle, $boucle->type_requete);
1655
-	} else {
1656
-		$x = $boucle->type_requete;
1657
-		$boucle->type_requete = false;
1658
-		$msg = [
1659
-			'zbug_iterateur_inconnu',
1660
-			['iterateur' => $x]
1661
-		];
1662
-		erreur_squelette($msg, $boucle);
1663
-	}
1652
+    if (class_exists($boucle->type_requete)) {
1653
+        $g = charger_fonction('php', 'iterateur');
1654
+        $boucles[$id] = $g($boucle, $boucle->type_requete);
1655
+    } else {
1656
+        $x = $boucle->type_requete;
1657
+        $boucle->type_requete = false;
1658
+        $msg = [
1659
+            'zbug_iterateur_inconnu',
1660
+            ['iterateur' => $x]
1661
+        ];
1662
+        erreur_squelette($msg, $boucle);
1663
+    }
1664 1664
 }
1665 1665
 
1666 1666
 
@@ -1678,22 +1678,22 @@  discard block
 block discarded – undo
1678 1678
  *
1679 1679
  **/
1680 1680
 function requeteur_data_dist(&$boucles, &$boucle, &$id) {
1681
-	include_spip('iterateur/data');
1682
-	if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1683
-		$g = charger_fonction('data', 'iterateur');
1684
-		$boucles[$id] = $g($boucle);
1685
-		// from[0] stocke le type de data (rss, yql, ...)
1686
-		$boucles[$id]->from[] = $boucle->type_requete;
1687
-	} else {
1688
-		$x = $boucle->type_requete;
1689
-		$boucle->type_requete = false;
1690
-		$msg = [
1691
-			'zbug_requeteur_inconnu',
1692
-			[
1693
-				'requeteur' => 'data',
1694
-				'type' => $x
1695
-			]
1696
-		];
1697
-		erreur_squelette($msg, $boucle);
1698
-	}
1681
+    include_spip('iterateur/data');
1682
+    if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) {
1683
+        $g = charger_fonction('data', 'iterateur');
1684
+        $boucles[$id] = $g($boucle);
1685
+        // from[0] stocke le type de data (rss, yql, ...)
1686
+        $boucles[$id]->from[] = $boucle->type_requete;
1687
+    } else {
1688
+        $x = $boucle->type_requete;
1689
+        $boucle->type_requete = false;
1690
+        $msg = [
1691
+            'zbug_requeteur_inconnu',
1692
+            [
1693
+                'requeteur' => 'data',
1694
+                'type' => $x
1695
+            ]
1696
+        ];
1697
+        erreur_squelette($msg, $boucle);
1698
+    }
1699 1699
 }
Please login to merge, or discard this patch.
ecrire/iterateur/data.php 1 patch
Indentation   +640 added lines, -640 removed lines patch added patch discarded remove patch
@@ -17,11 +17,11 @@  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
 if (!defined('_DATA_SOURCE_MAX_SIZE')) {
24
-	define('_DATA_SOURCE_MAX_SIZE', 2 * 1_048_576);
24
+    define('_DATA_SOURCE_MAX_SIZE', 2 * 1_048_576);
25 25
 }
26 26
 
27 27
 
@@ -42,17 +42,17 @@  discard block
 block discarded – undo
42 42
  *     Description de la boucle complétée des champs
43 43
  */
44 44
 function iterateur_DATA_dist($b) {
45
-	$b->iterateur = 'DATA'; # designe la classe d'iterateur
46
-	$b->show = [
47
-		'field' => [
48
-			'cle' => 'STRING',
49
-			'valeur' => 'STRING',
50
-			'*' => 'ALL' // Champ joker *
51
-		]
52
-	];
53
-	$b->select[] = '.valeur';
54
-
55
-	return $b;
45
+    $b->iterateur = 'DATA'; # designe la classe d'iterateur
46
+    $b->show = [
47
+        'field' => [
48
+            'cle' => 'STRING',
49
+            'valeur' => 'STRING',
50
+            '*' => 'ALL' // Champ joker *
51
+        ]
52
+    ];
53
+    $b->select[] = '.valeur';
54
+
55
+    return $b;
56 56
 }
57 57
 
58 58
 
@@ -62,522 +62,522 @@  discard block
 block discarded – undo
62 62
  * Pour itérer sur des données quelconques (transformables en tableau)
63 63
  */
64 64
 class IterateurDATA implements Iterator {
65
-	/**
66
-	 * tableau de donnees
67
-	 *
68
-	 * @var array
69
-	 */
70
-	protected $tableau = [];
71
-
72
-	/**
73
-	 * Conditions de filtrage
74
-	 * ie criteres de selection
75
-	 *
76
-	 * @var array
77
-	 */
78
-	protected $filtre = [];
79
-
80
-
81
-	/**
82
-	 * Cle courante
83
-	 *
84
-	 * @var null
85
-	 */
86
-	protected $cle = null;
87
-
88
-	/**
89
-	 * Valeur courante
90
-	 *
91
-	 * @var null
92
-	 */
93
-	protected $valeur = null;
94
-
95
-	/**
96
-	 * Erreur presente ?
97
-	 *
98
-	 * @var bool
99
-	 **/
100
-	public $err = false;
101
-
102
-	/**
103
-	 * Calcul du total des elements
104
-	 *
105
-	 * @var int|null
106
-	 **/
107
-	public $total = null;
108
-
109
-	/**
110
-	 * Constructeur
111
-	 *
112
-	 * @param  $command
113
-	 * @param array $info
114
-	 */
115
-	public function __construct($command, $info = []) {
116
-		$this->type = 'DATA';
117
-		$this->command = $command;
118
-		$this->info = $info;
119
-
120
-		$this->select($command);
121
-	}
122
-
123
-	/**
124
-	 * Revenir au depart
125
-	 *
126
-	 * @return void
127
-	 */
128
-	public function rewind(): void {
129
-		reset($this->tableau);
130
-		$this->cle = array_key_first($this->tableau);
131
-		$this->valeur = current($this->tableau);
132
-		next($this->tableau);
133
-	}
134
-
135
-	/**
136
-	 * Déclarer les critères exceptions
137
-	 *
138
-	 * @return array
139
-	 */
140
-	public function exception_des_criteres() {
141
-		return ['tableau'];
142
-	}
143
-
144
-	/**
145
-	 * Récupérer depuis le cache si possible
146
-	 *
147
-	 * @param string $cle
148
-	 * @return mixed
149
-	 */
150
-	protected function cache_get($cle) {
151
-		if (!$cle) {
152
-			return;
153
-		}
154
-		# utiliser memoization si dispo
155
-		if (!function_exists('cache_get')) {
156
-			return;
157
-		}
158
-
159
-		return cache_get($cle);
160
-	}
161
-
162
-	/**
163
-	 * Stocker en cache si possible
164
-	 *
165
-	 * @param string $cle
166
-	 * @param int $ttl
167
-	 * @param null|mixed $valeur
168
-	 * @return bool
169
-	 */
170
-	protected function cache_set($cle, $ttl, $valeur = null) {
171
-		if (!$cle) {
172
-			return;
173
-		}
174
-		if (is_null($valeur)) {
175
-			$valeur = $this->tableau;
176
-		}
177
-		# utiliser memoization si dispo
178
-		if (!function_exists('cache_set')) {
179
-			return;
180
-		}
181
-
182
-		return cache_set(
183
-			$cle,
184
-			[
185
-				'data' => $valeur,
186
-				'time' => time(),
187
-				'ttl' => $ttl
188
-			],
189
-			3600 + $ttl
190
-		);
191
-		# conserver le cache 1h de plus que la validite demandee,
192
-		# pour le cas ou le serveur distant ne reponde plus
193
-	}
194
-
195
-	/**
196
-	 * Aller chercher les données de la boucle DATA
197
-	 *
198
-	 * @throws Exception
199
-	 * @param array $command
200
-	 * @return void
201
-	 */
202
-	protected function select($command) {
203
-
204
-		// l'iterateur DATA peut etre appele en passant (data:type)
205
-		// le type se retrouve dans la commande 'from'
206
-		// dans ce cas la le critere {source}, si present, n'a pas besoin du 1er argument
207
-		if (isset($this->command['from'][0])) {
208
-			if (isset($this->command['source']) and is_array($this->command['source'])) {
209
-				array_unshift($this->command['source'], $this->command['sourcemode']);
210
-			}
211
-			$this->command['sourcemode'] = $this->command['from'][0];
212
-		}
213
-
214
-		// cherchons differents moyens de creer le tableau de donnees
215
-		// les commandes connues pour l'iterateur DATA
216
-		// sont : {tableau #ARRAY} ; {cle=...} ; {valeur=...}
217
-
218
-		// {source format, [URL], [arg2]...}
219
-		if (
220
-			isset($this->command['source'])
221
-			and isset($this->command['sourcemode'])
222
-		) {
223
-			$this->select_source();
224
-		}
225
-
226
-		// Critere {liste X1, X2, X3}
227
-		if (isset($this->command['liste'])) {
228
-			$this->select_liste();
229
-		}
230
-		if (isset($this->command['enum'])) {
231
-			$this->select_enum();
232
-		}
233
-
234
-		// Si a ce stade on n'a pas de table, il y a un bug
235
-		if (!is_array($this->tableau)) {
236
-			$this->err = true;
237
-			spip_log('erreur datasource ' . var_export($command, true));
238
-		}
239
-
240
-		// {datapath query.results}
241
-		// extraire le chemin "query.results" du tableau de donnees
242
-		if (
243
-			!$this->err
244
-			and isset($this->command['datapath'])
245
-			and is_array($this->command['datapath'])
246
-		) {
247
-			$this->select_datapath();
248
-		}
249
-
250
-		// tri {par x}
251
-		if ($this->command['orderby']) {
252
-			$this->select_orderby();
253
-		}
254
-
255
-		// grouper les resultats {fusion /x/y/z} ;
256
-		if ($this->command['groupby']) {
257
-			$this->select_groupby();
258
-		}
259
-
260
-		$this->rewind();
261
-		#var_dump($this->tableau);
262
-	}
263
-
264
-
265
-	/**
266
-	 * Aller chercher les donnees de la boucle DATA
267
-	 * depuis une source
268
-	 * {source format, [URL], [arg2]...}
269
-	 */
270
-	protected function select_source() {
271
-		# un peu crado : avant de charger le cache il faut charger
272
-		# les class indispensables, sinon PHP ne saura pas gerer
273
-		# l'objet en cache ; cf plugins/icalendar
274
-		# perf : pas de fonction table_to_array ! (table est deja un array)
275
-		if (
276
-			isset($this->command['sourcemode'])
277
-			and !in_array($this->command['sourcemode'], ['table', 'array', 'tableau'])
278
-		) {
279
-			charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true);
280
-		}
281
-
282
-		# le premier argument peut etre un array, une URL etc.
283
-		$src = $this->command['source'][0];
284
-
285
-		# avons-nous un cache dispo ?
286
-		$cle = null;
287
-		if (is_string($src)) {
288
-			$cle = 'datasource_' . md5($this->command['sourcemode'] . ':' . var_export($this->command['source'], true));
289
-		}
290
-
291
-		$cache = $this->cache_get($cle);
292
-		if (isset($this->command['datacache'])) {
293
-			$ttl = intval($this->command['datacache']);
294
-		}
295
-		if (
296
-			$cache
297
-			and ($cache['time'] + ($ttl ?? $cache['ttl'])
298
-				> time())
299
-			and !(_request('var_mode') === 'recalcul'
300
-				and include_spip('inc/autoriser')
301
-				and autoriser('recalcul')
302
-			)
303
-		) {
304
-			$this->tableau = $cache['data'];
305
-		} else {
306
-			try {
307
-				if (
308
-					isset($this->command['sourcemode'])
309
-					and in_array(
310
-						$this->command['sourcemode'],
311
-						['table', 'array', 'tableau']
312
-					)
313
-				) {
314
-					if (
315
-						is_array($a = $src)
316
-						or (is_string($a)
317
-							and $a = str_replace('&quot;', '"', $a) # fragile!
318
-							and is_array($a = @unserialize($a)))
319
-					) {
320
-						$this->tableau = $a;
321
-					}
322
-				} else {
323
-					$data = $src;
324
-					if (is_string($src)) {
325
-						if (tester_url_absolue($src)) {
326
-							include_spip('inc/distant');
327
-							$data = recuperer_url($src, ['taille_max' => _DATA_SOURCE_MAX_SIZE]);
328
-							$data = $data['page'] ?? '';
329
-							if (!$data) {
330
-								throw new Exception('404');
331
-							}
332
-							if (!isset($ttl)) {
333
-								$ttl = 24 * 3600;
334
-							}
335
-						} elseif (@is_dir($src)) {
336
-							$data = $src;
337
-						} elseif (@is_readable($src) && @is_file($src)) {
338
-							$data = spip_file_get_contents($src);
339
-						}
340
-						if (!isset($ttl)) {
341
-							$ttl = 10;
342
-						}
343
-					}
344
-
345
-					if (
346
-						!$this->err
347
-						and $data_to_array = charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true)
348
-					) {
349
-						$args = $this->command['source'];
350
-						$args[0] = $data;
351
-						if (is_array($a = $data_to_array(...$args))) {
352
-							$this->tableau = $a;
353
-						}
354
-					}
355
-				}
356
-
357
-				if (!is_array($this->tableau)) {
358
-					$this->err = true;
359
-				}
360
-
361
-				if (!$this->err and isset($ttl) and $ttl > 0) {
362
-					$this->cache_set($cle, $ttl);
363
-				}
364
-			} catch (Exception $e) {
365
-				$e = $e->getMessage();
366
-				$err = sprintf(
367
-					"[%s, %s] $e",
368
-					$src,
369
-					$this->command['sourcemode']
370
-				);
371
-				erreur_squelette([$err, []]);
372
-				$this->err = true;
373
-			}
374
-		}
375
-
376
-		# en cas d'erreur, utiliser le cache si encore dispo
377
-		if (
378
-			$this->err
379
-			and $cache
380
-		) {
381
-			$this->tableau = $cache['data'];
382
-			$this->err = false;
383
-		}
384
-	}
385
-
386
-
387
-	/**
388
-	 * Retourne un tableau donne depuis un critère liste
389
-	 *
390
-	 * Critère `{liste X1, X2, X3}`
391
-	 *
392
-	 * @see critere_DATA_liste_dist()
393
-	 *
394
-	 **/
395
-	protected function select_liste() {
396
-		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
397
-		if (!isset($this->command['liste'][1])) {
398
-			if (!is_array($this->command['liste'][0])) {
399
-				$this->command['liste'] = explode(',', $this->command['liste'][0]);
400
-			} else {
401
-				$this->command['liste'] = $this->command['liste'][0];
402
-			}
403
-		}
404
-		$this->tableau = $this->command['liste'];
405
-	}
406
-
407
-	/**
408
-	 * Retourne un tableau donne depuis un critere liste
409
-	 * Critere {enum Xmin, Xmax}
410
-	 *
411
-	 **/
412
-	protected function select_enum() {
413
-		# s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
414
-		if (!isset($this->command['enum'][1])) {
415
-			if (!is_array($this->command['enum'][0])) {
416
-				$this->command['enum'] = explode(',', $this->command['enum'][0]);
417
-			} else {
418
-				$this->command['enum'] = $this->command['enum'][0];
419
-			}
420
-		}
421
-		if ((is_countable($this->command['enum']) ? count($this->command['enum']) : 0) >= 3) {
422
-			$enum = range(
423
-				array_shift($this->command['enum']),
424
-				array_shift($this->command['enum']),
425
-				array_shift($this->command['enum'])
426
-			);
427
-		} else {
428
-			$enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']));
429
-		}
430
-		$this->tableau = $enum;
431
-	}
432
-
433
-
434
-	/**
435
-	 * extraire le chemin "query.results" du tableau de donnees
436
-	 * {datapath query.results}
437
-	 *
438
-	 **/
439
-	protected function select_datapath() {
440
-		$base = reset($this->command['datapath']);
441
-		if (strlen($base = ltrim(trim($base), '/'))) {
442
-			$this->tableau = table_valeur($this->tableau, $base);
443
-			if (!is_array($this->tableau)) {
444
-				$this->tableau = [];
445
-				$this->err = true;
446
-				spip_log("datapath '$base' absent");
447
-			}
448
-		}
449
-	}
450
-
451
-	/**
452
-	 * Ordonner les resultats
453
-	 * {par x}
454
-	 *
455
-	 **/
456
-	protected function select_orderby() {
457
-		$sortfunc = '';
458
-		$aleas = 0;
459
-		foreach ($this->command['orderby'] as $tri) {
460
-			// virer le / initial pour les criteres de la forme {par /xx}
461
-			if (preg_match(',^\.?([/\w:_-]+)( DESC)?$,iS', ltrim($tri, '/'), $r)) {
462
-				$r = array_pad($r, 3, null);
463
-
464
-				// tri par cle
465
-				if ($r[1] == 'cle') {
466
-					if (isset($r[2]) and $r[2]) {
467
-						krsort($this->tableau);
468
-					} else {
469
-						ksort($this->tableau);
470
-					}
471
-				} # {par hasard}
472
-				else {
473
-					if ($r[1] == 'hasard') {
474
-						$k = array_keys($this->tableau);
475
-						shuffle($k);
476
-						$v = [];
477
-						foreach ($k as $cle) {
478
-							$v[$cle] = $this->tableau[$cle];
479
-						}
480
-						$this->tableau = $v;
481
-					} else {
482
-						# {par valeur}
483
-						if ($r[1] == 'valeur') {
484
-							$tv = '%s';
485
-						} # {par valeur/xx/yy} ??
486
-						else {
487
-							$tv = 'table_valeur(%s, ' . var_export($r[1], true) . ')';
488
-						}
489
-						$sortfunc .= '
65
+    /**
66
+     * tableau de donnees
67
+     *
68
+     * @var array
69
+     */
70
+    protected $tableau = [];
71
+
72
+    /**
73
+     * Conditions de filtrage
74
+     * ie criteres de selection
75
+     *
76
+     * @var array
77
+     */
78
+    protected $filtre = [];
79
+
80
+
81
+    /**
82
+     * Cle courante
83
+     *
84
+     * @var null
85
+     */
86
+    protected $cle = null;
87
+
88
+    /**
89
+     * Valeur courante
90
+     *
91
+     * @var null
92
+     */
93
+    protected $valeur = null;
94
+
95
+    /**
96
+     * Erreur presente ?
97
+     *
98
+     * @var bool
99
+     **/
100
+    public $err = false;
101
+
102
+    /**
103
+     * Calcul du total des elements
104
+     *
105
+     * @var int|null
106
+     **/
107
+    public $total = null;
108
+
109
+    /**
110
+     * Constructeur
111
+     *
112
+     * @param  $command
113
+     * @param array $info
114
+     */
115
+    public function __construct($command, $info = []) {
116
+        $this->type = 'DATA';
117
+        $this->command = $command;
118
+        $this->info = $info;
119
+
120
+        $this->select($command);
121
+    }
122
+
123
+    /**
124
+     * Revenir au depart
125
+     *
126
+     * @return void
127
+     */
128
+    public function rewind(): void {
129
+        reset($this->tableau);
130
+        $this->cle = array_key_first($this->tableau);
131
+        $this->valeur = current($this->tableau);
132
+        next($this->tableau);
133
+    }
134
+
135
+    /**
136
+     * Déclarer les critères exceptions
137
+     *
138
+     * @return array
139
+     */
140
+    public function exception_des_criteres() {
141
+        return ['tableau'];
142
+    }
143
+
144
+    /**
145
+     * Récupérer depuis le cache si possible
146
+     *
147
+     * @param string $cle
148
+     * @return mixed
149
+     */
150
+    protected function cache_get($cle) {
151
+        if (!$cle) {
152
+            return;
153
+        }
154
+        # utiliser memoization si dispo
155
+        if (!function_exists('cache_get')) {
156
+            return;
157
+        }
158
+
159
+        return cache_get($cle);
160
+    }
161
+
162
+    /**
163
+     * Stocker en cache si possible
164
+     *
165
+     * @param string $cle
166
+     * @param int $ttl
167
+     * @param null|mixed $valeur
168
+     * @return bool
169
+     */
170
+    protected function cache_set($cle, $ttl, $valeur = null) {
171
+        if (!$cle) {
172
+            return;
173
+        }
174
+        if (is_null($valeur)) {
175
+            $valeur = $this->tableau;
176
+        }
177
+        # utiliser memoization si dispo
178
+        if (!function_exists('cache_set')) {
179
+            return;
180
+        }
181
+
182
+        return cache_set(
183
+            $cle,
184
+            [
185
+                'data' => $valeur,
186
+                'time' => time(),
187
+                'ttl' => $ttl
188
+            ],
189
+            3600 + $ttl
190
+        );
191
+        # conserver le cache 1h de plus que la validite demandee,
192
+        # pour le cas ou le serveur distant ne reponde plus
193
+    }
194
+
195
+    /**
196
+     * Aller chercher les données de la boucle DATA
197
+     *
198
+     * @throws Exception
199
+     * @param array $command
200
+     * @return void
201
+     */
202
+    protected function select($command) {
203
+
204
+        // l'iterateur DATA peut etre appele en passant (data:type)
205
+        // le type se retrouve dans la commande 'from'
206
+        // dans ce cas la le critere {source}, si present, n'a pas besoin du 1er argument
207
+        if (isset($this->command['from'][0])) {
208
+            if (isset($this->command['source']) and is_array($this->command['source'])) {
209
+                array_unshift($this->command['source'], $this->command['sourcemode']);
210
+            }
211
+            $this->command['sourcemode'] = $this->command['from'][0];
212
+        }
213
+
214
+        // cherchons differents moyens de creer le tableau de donnees
215
+        // les commandes connues pour l'iterateur DATA
216
+        // sont : {tableau #ARRAY} ; {cle=...} ; {valeur=...}
217
+
218
+        // {source format, [URL], [arg2]...}
219
+        if (
220
+            isset($this->command['source'])
221
+            and isset($this->command['sourcemode'])
222
+        ) {
223
+            $this->select_source();
224
+        }
225
+
226
+        // Critere {liste X1, X2, X3}
227
+        if (isset($this->command['liste'])) {
228
+            $this->select_liste();
229
+        }
230
+        if (isset($this->command['enum'])) {
231
+            $this->select_enum();
232
+        }
233
+
234
+        // Si a ce stade on n'a pas de table, il y a un bug
235
+        if (!is_array($this->tableau)) {
236
+            $this->err = true;
237
+            spip_log('erreur datasource ' . var_export($command, true));
238
+        }
239
+
240
+        // {datapath query.results}
241
+        // extraire le chemin "query.results" du tableau de donnees
242
+        if (
243
+            !$this->err
244
+            and isset($this->command['datapath'])
245
+            and is_array($this->command['datapath'])
246
+        ) {
247
+            $this->select_datapath();
248
+        }
249
+
250
+        // tri {par x}
251
+        if ($this->command['orderby']) {
252
+            $this->select_orderby();
253
+        }
254
+
255
+        // grouper les resultats {fusion /x/y/z} ;
256
+        if ($this->command['groupby']) {
257
+            $this->select_groupby();
258
+        }
259
+
260
+        $this->rewind();
261
+        #var_dump($this->tableau);
262
+    }
263
+
264
+
265
+    /**
266
+     * Aller chercher les donnees de la boucle DATA
267
+     * depuis une source
268
+     * {source format, [URL], [arg2]...}
269
+     */
270
+    protected function select_source() {
271
+        # un peu crado : avant de charger le cache il faut charger
272
+        # les class indispensables, sinon PHP ne saura pas gerer
273
+        # l'objet en cache ; cf plugins/icalendar
274
+        # perf : pas de fonction table_to_array ! (table est deja un array)
275
+        if (
276
+            isset($this->command['sourcemode'])
277
+            and !in_array($this->command['sourcemode'], ['table', 'array', 'tableau'])
278
+        ) {
279
+            charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true);
280
+        }
281
+
282
+        # le premier argument peut etre un array, une URL etc.
283
+        $src = $this->command['source'][0];
284
+
285
+        # avons-nous un cache dispo ?
286
+        $cle = null;
287
+        if (is_string($src)) {
288
+            $cle = 'datasource_' . md5($this->command['sourcemode'] . ':' . var_export($this->command['source'], true));
289
+        }
290
+
291
+        $cache = $this->cache_get($cle);
292
+        if (isset($this->command['datacache'])) {
293
+            $ttl = intval($this->command['datacache']);
294
+        }
295
+        if (
296
+            $cache
297
+            and ($cache['time'] + ($ttl ?? $cache['ttl'])
298
+                > time())
299
+            and !(_request('var_mode') === 'recalcul'
300
+                and include_spip('inc/autoriser')
301
+                and autoriser('recalcul')
302
+            )
303
+        ) {
304
+            $this->tableau = $cache['data'];
305
+        } else {
306
+            try {
307
+                if (
308
+                    isset($this->command['sourcemode'])
309
+                    and in_array(
310
+                        $this->command['sourcemode'],
311
+                        ['table', 'array', 'tableau']
312
+                    )
313
+                ) {
314
+                    if (
315
+                        is_array($a = $src)
316
+                        or (is_string($a)
317
+                            and $a = str_replace('&quot;', '"', $a) # fragile!
318
+                            and is_array($a = @unserialize($a)))
319
+                    ) {
320
+                        $this->tableau = $a;
321
+                    }
322
+                } else {
323
+                    $data = $src;
324
+                    if (is_string($src)) {
325
+                        if (tester_url_absolue($src)) {
326
+                            include_spip('inc/distant');
327
+                            $data = recuperer_url($src, ['taille_max' => _DATA_SOURCE_MAX_SIZE]);
328
+                            $data = $data['page'] ?? '';
329
+                            if (!$data) {
330
+                                throw new Exception('404');
331
+                            }
332
+                            if (!isset($ttl)) {
333
+                                $ttl = 24 * 3600;
334
+                            }
335
+                        } elseif (@is_dir($src)) {
336
+                            $data = $src;
337
+                        } elseif (@is_readable($src) && @is_file($src)) {
338
+                            $data = spip_file_get_contents($src);
339
+                        }
340
+                        if (!isset($ttl)) {
341
+                            $ttl = 10;
342
+                        }
343
+                    }
344
+
345
+                    if (
346
+                        !$this->err
347
+                        and $data_to_array = charger_fonction($this->command['sourcemode'] . '_to_array', 'inc', true)
348
+                    ) {
349
+                        $args = $this->command['source'];
350
+                        $args[0] = $data;
351
+                        if (is_array($a = $data_to_array(...$args))) {
352
+                            $this->tableau = $a;
353
+                        }
354
+                    }
355
+                }
356
+
357
+                if (!is_array($this->tableau)) {
358
+                    $this->err = true;
359
+                }
360
+
361
+                if (!$this->err and isset($ttl) and $ttl > 0) {
362
+                    $this->cache_set($cle, $ttl);
363
+                }
364
+            } catch (Exception $e) {
365
+                $e = $e->getMessage();
366
+                $err = sprintf(
367
+                    "[%s, %s] $e",
368
+                    $src,
369
+                    $this->command['sourcemode']
370
+                );
371
+                erreur_squelette([$err, []]);
372
+                $this->err = true;
373
+            }
374
+        }
375
+
376
+        # en cas d'erreur, utiliser le cache si encore dispo
377
+        if (
378
+            $this->err
379
+            and $cache
380
+        ) {
381
+            $this->tableau = $cache['data'];
382
+            $this->err = false;
383
+        }
384
+    }
385
+
386
+
387
+    /**
388
+     * Retourne un tableau donne depuis un critère liste
389
+     *
390
+     * Critère `{liste X1, X2, X3}`
391
+     *
392
+     * @see critere_DATA_liste_dist()
393
+     *
394
+     **/
395
+    protected function select_liste() {
396
+        # s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
397
+        if (!isset($this->command['liste'][1])) {
398
+            if (!is_array($this->command['liste'][0])) {
399
+                $this->command['liste'] = explode(',', $this->command['liste'][0]);
400
+            } else {
401
+                $this->command['liste'] = $this->command['liste'][0];
402
+            }
403
+        }
404
+        $this->tableau = $this->command['liste'];
405
+    }
406
+
407
+    /**
408
+     * Retourne un tableau donne depuis un critere liste
409
+     * Critere {enum Xmin, Xmax}
410
+     *
411
+     **/
412
+    protected function select_enum() {
413
+        # s'il n'y a qu'une valeur dans la liste, sans doute une #BALISE
414
+        if (!isset($this->command['enum'][1])) {
415
+            if (!is_array($this->command['enum'][0])) {
416
+                $this->command['enum'] = explode(',', $this->command['enum'][0]);
417
+            } else {
418
+                $this->command['enum'] = $this->command['enum'][0];
419
+            }
420
+        }
421
+        if ((is_countable($this->command['enum']) ? count($this->command['enum']) : 0) >= 3) {
422
+            $enum = range(
423
+                array_shift($this->command['enum']),
424
+                array_shift($this->command['enum']),
425
+                array_shift($this->command['enum'])
426
+            );
427
+        } else {
428
+            $enum = range(array_shift($this->command['enum']), array_shift($this->command['enum']));
429
+        }
430
+        $this->tableau = $enum;
431
+    }
432
+
433
+
434
+    /**
435
+     * extraire le chemin "query.results" du tableau de donnees
436
+     * {datapath query.results}
437
+     *
438
+     **/
439
+    protected function select_datapath() {
440
+        $base = reset($this->command['datapath']);
441
+        if (strlen($base = ltrim(trim($base), '/'))) {
442
+            $this->tableau = table_valeur($this->tableau, $base);
443
+            if (!is_array($this->tableau)) {
444
+                $this->tableau = [];
445
+                $this->err = true;
446
+                spip_log("datapath '$base' absent");
447
+            }
448
+        }
449
+    }
450
+
451
+    /**
452
+     * Ordonner les resultats
453
+     * {par x}
454
+     *
455
+     **/
456
+    protected function select_orderby() {
457
+        $sortfunc = '';
458
+        $aleas = 0;
459
+        foreach ($this->command['orderby'] as $tri) {
460
+            // virer le / initial pour les criteres de la forme {par /xx}
461
+            if (preg_match(',^\.?([/\w:_-]+)( DESC)?$,iS', ltrim($tri, '/'), $r)) {
462
+                $r = array_pad($r, 3, null);
463
+
464
+                // tri par cle
465
+                if ($r[1] == 'cle') {
466
+                    if (isset($r[2]) and $r[2]) {
467
+                        krsort($this->tableau);
468
+                    } else {
469
+                        ksort($this->tableau);
470
+                    }
471
+                } # {par hasard}
472
+                else {
473
+                    if ($r[1] == 'hasard') {
474
+                        $k = array_keys($this->tableau);
475
+                        shuffle($k);
476
+                        $v = [];
477
+                        foreach ($k as $cle) {
478
+                            $v[$cle] = $this->tableau[$cle];
479
+                        }
480
+                        $this->tableau = $v;
481
+                    } else {
482
+                        # {par valeur}
483
+                        if ($r[1] == 'valeur') {
484
+                            $tv = '%s';
485
+                        } # {par valeur/xx/yy} ??
486
+                        else {
487
+                            $tv = 'table_valeur(%s, ' . var_export($r[1], true) . ')';
488
+                        }
489
+                        $sortfunc .= '
490 490
 					$a = ' . sprintf($tv, '$aa') . ';
491 491
 					$b = ' . sprintf($tv, '$bb') . ';
492 492
 					if ($a <> $b)
493 493
 						return ($a ' . (!empty($r[2]) ? '>' : '<') . ' $b) ? -1 : 1;';
494
-					}
495
-				}
496
-			}
497
-		}
498
-
499
-		if ($sortfunc) {
500
-			$sortfunc .= "\n return 0;";
501
-			uasort($this->tableau, fn($aa, $bb) => eval($sortfunc));
502
-		}
503
-	}
504
-
505
-
506
-	/**
507
-	 * Grouper les resultats
508
-	 * {fusion /x/y/z}
509
-	 *
510
-	 **/
511
-	protected function select_groupby() {
512
-		// virer le / initial pour les criteres de la forme {fusion /xx}
513
-		if (strlen($fusion = ltrim($this->command['groupby'][0], '/'))) {
514
-			$vu = [];
515
-			foreach ($this->tableau as $k => $v) {
516
-				$val = table_valeur($v, $fusion);
517
-				if (isset($vu[$val])) {
518
-					unset($this->tableau[$k]);
519
-				} else {
520
-					$vu[$val] = true;
521
-				}
522
-			}
523
-		}
524
-	}
525
-
526
-
527
-	/**
528
-	 * L'iterateur est-il encore valide ?
529
-	 *
530
-	 * @return bool
531
-	 */
532
-	public function valid(): bool {
533
-		return !is_null($this->cle);
534
-	}
535
-
536
-	/**
537
-	 * Retourner la valeur
538
-	 *
539
-	 * @return mixed
540
-	 */
541
-	#[\ReturnTypeWillChange]
542
-	public function current() {
543
-		return $this->valeur;
544
-	}
545
-
546
-	/**
547
-	 * Retourner la cle
548
-	 *
549
-	 * @return mixed
550
-	 */
551
-	#[\ReturnTypeWillChange]
552
-	public function key() {
553
-		return $this->cle;
554
-	}
555
-
556
-	/**
557
-	 * Passer a la valeur suivante
558
-	 *
559
-	 * @return void
560
-	 */
561
-	public function next(): void {
562
-		if ($this->valid()) {
563
-			$this->cle = key($this->tableau);
564
-			$this->valeur = current($this->tableau);
565
-			next($this->tableau);
566
-		}
567
-	}
568
-
569
-	/**
570
-	 * Compter le nombre total de resultats
571
-	 *
572
-	 * @return int
573
-	 */
574
-	public function count() {
575
-		if (is_null($this->total)) {
576
-			$this->total = count($this->tableau);
577
-		}
578
-
579
-		return $this->total;
580
-	}
494
+                    }
495
+                }
496
+            }
497
+        }
498
+
499
+        if ($sortfunc) {
500
+            $sortfunc .= "\n return 0;";
501
+            uasort($this->tableau, fn($aa, $bb) => eval($sortfunc));
502
+        }
503
+    }
504
+
505
+
506
+    /**
507
+     * Grouper les resultats
508
+     * {fusion /x/y/z}
509
+     *
510
+     **/
511
+    protected function select_groupby() {
512
+        // virer le / initial pour les criteres de la forme {fusion /xx}
513
+        if (strlen($fusion = ltrim($this->command['groupby'][0], '/'))) {
514
+            $vu = [];
515
+            foreach ($this->tableau as $k => $v) {
516
+                $val = table_valeur($v, $fusion);
517
+                if (isset($vu[$val])) {
518
+                    unset($this->tableau[$k]);
519
+                } else {
520
+                    $vu[$val] = true;
521
+                }
522
+            }
523
+        }
524
+    }
525
+
526
+
527
+    /**
528
+     * L'iterateur est-il encore valide ?
529
+     *
530
+     * @return bool
531
+     */
532
+    public function valid(): bool {
533
+        return !is_null($this->cle);
534
+    }
535
+
536
+    /**
537
+     * Retourner la valeur
538
+     *
539
+     * @return mixed
540
+     */
541
+    #[\ReturnTypeWillChange]
542
+    public function current() {
543
+        return $this->valeur;
544
+    }
545
+
546
+    /**
547
+     * Retourner la cle
548
+     *
549
+     * @return mixed
550
+     */
551
+    #[\ReturnTypeWillChange]
552
+    public function key() {
553
+        return $this->cle;
554
+    }
555
+
556
+    /**
557
+     * Passer a la valeur suivante
558
+     *
559
+     * @return void
560
+     */
561
+    public function next(): void {
562
+        if ($this->valid()) {
563
+            $this->cle = key($this->tableau);
564
+            $this->valeur = current($this->tableau);
565
+            next($this->tableau);
566
+        }
567
+    }
568
+
569
+    /**
570
+     * Compter le nombre total de resultats
571
+     *
572
+     * @return int
573
+     */
574
+    public function count() {
575
+        if (is_null($this->total)) {
576
+            $this->total = count($this->tableau);
577
+        }
578
+
579
+        return $this->total;
580
+    }
581 581
 }
582 582
 
583 583
 /*
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
  * @return array
592 592
  */
593 593
 function inc_file_to_array_dist($data) {
594
-	return preg_split('/\r?\n/', $data);
594
+    return preg_split('/\r?\n/', $data);
595 595
 }
596 596
 
597 597
 /**
@@ -600,9 +600,9 @@  discard block
 block discarded – undo
600 600
  * @return array
601 601
  */
602 602
 function inc_plugins_to_array_dist() {
603
-	include_spip('inc/plugin');
603
+    include_spip('inc/plugin');
604 604
 
605
-	return liste_chemin_plugin_actifs();
605
+    return liste_chemin_plugin_actifs();
606 606
 }
607 607
 
608 608
 /**
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
  * @return array
613 613
  */
614 614
 function inc_xml_to_array_dist($data) {
615
-	return @XMLObjectToArray(new SimpleXmlIterator($data));
615
+    return @XMLObjectToArray(new SimpleXmlIterator($data));
616 616
 }
617 617
 
618 618
 /**
@@ -624,14 +624,14 @@  discard block
 block discarded – undo
624 624
  *
625 625
  */
626 626
 function inc_object_to_array($object) {
627
-	if (!is_object($object) && !is_array($object)) {
628
-		return $object;
629
-	}
630
-	if (is_object($object)) {
631
-		$object = get_object_vars($object);
632
-	}
633
-
634
-	return array_map('inc_object_to_array', $object);
627
+    if (!is_object($object) && !is_array($object)) {
628
+        return $object;
629
+    }
630
+    if (is_object($object)) {
631
+        $object = get_object_vars($object);
632
+    }
633
+
634
+    return array_map('inc_object_to_array', $object);
635 635
 }
636 636
 
637 637
 /**
@@ -641,20 +641,20 @@  discard block
 block discarded – undo
641 641
  * @return array|bool
642 642
  */
643 643
 function inc_sql_to_array_dist($data) {
644
-	# sortir le connecteur de $data
645
-	preg_match(',^(?:(\w+):)?(.*)$,Sm', $data, $v);
646
-	$serveur = (string)$v[1];
647
-	$req = trim($v[2]);
648
-	if ($s = sql_query($req, $serveur)) {
649
-		$r = [];
650
-		while ($t = sql_fetch($s)) {
651
-			$r[] = $t;
652
-		}
653
-
654
-		return $r;
655
-	}
656
-
657
-	return false;
644
+    # sortir le connecteur de $data
645
+    preg_match(',^(?:(\w+):)?(.*)$,Sm', $data, $v);
646
+    $serveur = (string)$v[1];
647
+    $req = trim($v[2]);
648
+    if ($s = sql_query($req, $serveur)) {
649
+        $r = [];
650
+        while ($t = sql_fetch($s)) {
651
+            $r[] = $t;
652
+        }
653
+
654
+        return $r;
655
+    }
656
+
657
+    return false;
658 658
 }
659 659
 
660 660
 /**
@@ -664,13 +664,13 @@  discard block
 block discarded – undo
664 664
  * @return array|bool
665 665
  */
666 666
 function inc_json_to_array_dist($data) {
667
-	try {
668
-		$json = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
669
-	} catch (JsonException $e) {
670
-		$json = null;
671
-		spip_log('Failed to parse Json data : ' . $e->getMessage(), _LOG_INFO);
672
-	}
673
-	return is_array($json) ? (array) $json : [];
667
+    try {
668
+        $json = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
669
+    } catch (JsonException $e) {
670
+        $json = null;
671
+        spip_log('Failed to parse Json data : ' . $e->getMessage(), _LOG_INFO);
672
+    }
673
+    return is_array($json) ? (array) $json : [];
674 674
 }
675 675
 
676 676
 /**
@@ -680,30 +680,30 @@  discard block
 block discarded – undo
680 680
  * @return array|bool
681 681
  */
682 682
 function inc_csv_to_array_dist($data) {
683
-	include_spip('inc/csv');
684
-	[$entete, $csv] = analyse_csv($data);
685
-	array_unshift($csv, $entete);
686
-
687
-	include_spip('inc/charsets');
688
-	$i = 1;
689
-	foreach ($entete as $k => $v) {
690
-		if (trim($v) == '') {
691
-			$v = 'col' . $i;
692
-		} // reperer des eventuelles cases vides
693
-		if (is_numeric($v) and $v < 0) {
694
-			$v = '__' . $v;
695
-		} // ne pas risquer d'ecraser une cle numerique
696
-		if (is_numeric($v)) {
697
-			$v = '_' . $v;
698
-		} // ne pas risquer d'ecraser une cle numerique
699
-		$v = strtolower(preg_replace(',\W+,', '_', translitteration($v)));
700
-		foreach ($csv as &$item) {
701
-			$item[$v] = &$item[$k];
702
-		}
703
-		$i++;
704
-	}
705
-
706
-	return $csv;
683
+    include_spip('inc/csv');
684
+    [$entete, $csv] = analyse_csv($data);
685
+    array_unshift($csv, $entete);
686
+
687
+    include_spip('inc/charsets');
688
+    $i = 1;
689
+    foreach ($entete as $k => $v) {
690
+        if (trim($v) == '') {
691
+            $v = 'col' . $i;
692
+        } // reperer des eventuelles cases vides
693
+        if (is_numeric($v) and $v < 0) {
694
+            $v = '__' . $v;
695
+        } // ne pas risquer d'ecraser une cle numerique
696
+        if (is_numeric($v)) {
697
+            $v = '_' . $v;
698
+        } // ne pas risquer d'ecraser une cle numerique
699
+        $v = strtolower(preg_replace(',\W+,', '_', translitteration($v)));
700
+        foreach ($csv as &$item) {
701
+            $item[$v] = &$item[$k];
702
+        }
703
+        $i++;
704
+    }
705
+
706
+    return $csv;
707 707
 }
708 708
 
709 709
 /**
@@ -713,13 +713,13 @@  discard block
 block discarded – undo
713 713
  * @return array|bool
714 714
  */
715 715
 function inc_rss_to_array_dist($data) {
716
-	$tableau = null;
717
-	include_spip('inc/syndic');
718
-	if (is_array($rss = analyser_backend($data))) {
719
-		$tableau = $rss;
720
-	}
716
+    $tableau = null;
717
+    include_spip('inc/syndic');
718
+    if (is_array($rss = analyser_backend($data))) {
719
+        $tableau = $rss;
720
+    }
721 721
 
722
-	return $tableau;
722
+    return $tableau;
723 723
 }
724 724
 
725 725
 /**
@@ -729,9 +729,9 @@  discard block
 block discarded – undo
729 729
  * @return array|bool
730 730
  */
731 731
 function inc_atom_to_array_dist($data) {
732
-	$rss_to_array = charger_fonction('rss_to_array', 'inc');
732
+    $rss_to_array = charger_fonction('rss_to_array', 'inc');
733 733
 
734
-	return $rss_to_array($data);
734
+    return $rss_to_array($data);
735 735
 }
736 736
 
737 737
 /**
@@ -742,12 +742,12 @@  discard block
 block discarded – undo
742 742
  * @return array|bool
743 743
  */
744 744
 function inc_glob_to_array_dist($data) {
745
-	$a = glob(
746
-		$data,
747
-		GLOB_MARK | GLOB_NOSORT | GLOB_BRACE
748
-	);
745
+    $a = glob(
746
+        $data,
747
+        GLOB_MARK | GLOB_NOSORT | GLOB_BRACE
748
+    );
749 749
 
750
-	return $a ?: [];
750
+    return $a ?: [];
751 751
 }
752 752
 
753 753
 /**
@@ -758,14 +758,14 @@  discard block
 block discarded – undo
758 758
  * @throws Exception
759 759
  */
760 760
 function inc_yaml_to_array_dist($data) {
761
-	include_spip('inc/yaml-mini');
762
-	if (!function_exists('yaml_decode')) {
763
-		throw new Exception('YAML: impossible de trouver la fonction yaml_decode');
761
+    include_spip('inc/yaml-mini');
762
+    if (!function_exists('yaml_decode')) {
763
+        throw new Exception('YAML: impossible de trouver la fonction yaml_decode');
764 764
 
765
-		return false;
766
-	}
765
+        return false;
766
+    }
767 767
 
768
-	return yaml_decode($data);
768
+    return yaml_decode($data);
769 769
 }
770 770
 
771 771
 
@@ -780,7 +780,7 @@  discard block
 block discarded – undo
780 780
  * @return array|bool
781 781
  */
782 782
 function inc_pregfiles_to_array_dist($dir, $regexp = -1, $limit = 10000) {
783
-	return (array)preg_files($dir, $regexp, $limit);
783
+    return (array)preg_files($dir, $regexp, $limit);
784 784
 }
785 785
 
786 786
 /**
@@ -792,23 +792,23 @@  discard block
 block discarded – undo
792 792
  * @return array|bool
793 793
  */
794 794
 function inc_ls_to_array_dist($data) {
795
-	$glob_to_array = charger_fonction('glob_to_array', 'inc');
796
-	$a = $glob_to_array($data);
797
-	foreach ($a as &$v) {
798
-		$b = (array)@stat($v);
799
-		foreach ($b as $k => $ignore) {
800
-			if (is_numeric($k)) {
801
-				unset($b[$k]);
802
-			}
803
-		}
804
-		$b['file'] = preg_replace('`/$`', '', $v) ;
805
-		$v = array_merge(
806
-			pathinfo($v),
807
-			$b
808
-		);
809
-	}
810
-
811
-	return $a;
795
+    $glob_to_array = charger_fonction('glob_to_array', 'inc');
796
+    $a = $glob_to_array($data);
797
+    foreach ($a as &$v) {
798
+        $b = (array)@stat($v);
799
+        foreach ($b as $k => $ignore) {
800
+            if (is_numeric($k)) {
801
+                unset($b[$k]);
802
+            }
803
+        }
804
+        $b['file'] = preg_replace('`/$`', '', $v) ;
805
+        $v = array_merge(
806
+            pathinfo($v),
807
+            $b
808
+        );
809
+    }
810
+
811
+    return $a;
812 812
 }
813 813
 
814 814
 /**
@@ -818,25 +818,25 @@  discard block
 block discarded – undo
818 818
  * @return array|bool
819 819
  */
820 820
 function XMLObjectToArray($object) {
821
-	$xml_array = [];
822
-	for ($object->rewind(); $object->valid(); $object->next()) {
823
-		if (array_key_exists($key = $object->key(), $xml_array)) {
824
-			$key .= '-' . uniqid();
825
-		}
826
-		$vars = get_object_vars($object->current());
827
-		if (isset($vars['@attributes'])) {
828
-			foreach ($vars['@attributes'] as $k => $v) {
829
-				$xml_array[$key][$k] = $v;
830
-			}
831
-		}
832
-		if ($object->hasChildren()) {
833
-			$xml_array[$key][] = XMLObjectToArray(
834
-				$object->current()
835
-			);
836
-		} else {
837
-			$xml_array[$key][] = strval($object->current());
838
-		}
839
-	}
840
-
841
-	return $xml_array;
821
+    $xml_array = [];
822
+    for ($object->rewind(); $object->valid(); $object->next()) {
823
+        if (array_key_exists($key = $object->key(), $xml_array)) {
824
+            $key .= '-' . uniqid();
825
+        }
826
+        $vars = get_object_vars($object->current());
827
+        if (isset($vars['@attributes'])) {
828
+            foreach ($vars['@attributes'] as $k => $v) {
829
+                $xml_array[$key][$k] = $v;
830
+            }
831
+        }
832
+        if ($object->hasChildren()) {
833
+            $xml_array[$key][] = XMLObjectToArray(
834
+                $object->current()
835
+            );
836
+        } else {
837
+            $xml_array[$key][] = strval($object->current());
838
+        }
839
+    }
840
+
841
+    return $xml_array;
842 842
 }
Please login to merge, or discard this patch.
ecrire/iterateur/sql.php 1 patch
Indentation   +204 added lines, -204 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,210 +27,210 @@  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 $firstseek = false;
45
-
46
-	/**
47
-	 * Erreur presente ?
48
-	 *
49
-	 * @var bool
50
-	 **/
51
-	public $err = false;
52
-
53
-	/**
54
-	 * Calcul du total des elements
55
-	 *
56
-	 * @var int|null
57
-	 **/
58
-	public $total = null;
59
-
60
-	/**
61
-	 * selectionner les donnees, ie faire la requete SQL
62
-	 *
63
-	 * @return void
64
-	 */
65
-	protected function select() {
66
-		$this->row = null;
67
-		$v = &$this->command;
68
-		$this->sqlresult = calculer_select(
69
-			$v['select'],
70
-			$v['from'],
71
-			$v['type'],
72
-			$v['where'],
73
-			$v['join'],
74
-			$v['groupby'],
75
-			$v['orderby'],
76
-			$v['limit'],
77
-			$v['having'],
78
-			$v['table'],
79
-			$v['id'],
80
-			$v['connect'],
81
-			$this->info
82
-		);
83
-		$this->err = !$this->sqlresult;
84
-		$this->firstseek = false;
85
-		$this->pos = -1;
86
-
87
-		// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
88
-		//$this->total = $this->count();
89
-	}
90
-
91
-	/*
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 $firstseek = false;
45
+
46
+    /**
47
+     * Erreur presente ?
48
+     *
49
+     * @var bool
50
+     **/
51
+    public $err = false;
52
+
53
+    /**
54
+     * Calcul du total des elements
55
+     *
56
+     * @var int|null
57
+     **/
58
+    public $total = null;
59
+
60
+    /**
61
+     * selectionner les donnees, ie faire la requete SQL
62
+     *
63
+     * @return void
64
+     */
65
+    protected function select() {
66
+        $this->row = null;
67
+        $v = &$this->command;
68
+        $this->sqlresult = calculer_select(
69
+            $v['select'],
70
+            $v['from'],
71
+            $v['type'],
72
+            $v['where'],
73
+            $v['join'],
74
+            $v['groupby'],
75
+            $v['orderby'],
76
+            $v['limit'],
77
+            $v['having'],
78
+            $v['table'],
79
+            $v['id'],
80
+            $v['connect'],
81
+            $this->info
82
+        );
83
+        $this->err = !$this->sqlresult;
84
+        $this->firstseek = false;
85
+        $this->pos = -1;
86
+
87
+        // pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
88
+        //$this->total = $this->count();
89
+    }
90
+
91
+    /*
92 92
 	 * array command: les commandes d'initialisation
93 93
 	 * array info: les infos sur le squelette
94 94
 	 */
95
-	public function __construct($command, $info = []) {
96
-		$this->type = 'SQL';
97
-		$this->command = $command;
98
-		$this->info = $info;
99
-		$this->select();
100
-	}
101
-
102
-	/**
103
-	 * Rembobiner
104
-	 *
105
-	 * @return bool
106
-	 */
107
-	public function rewind(): void {
108
-		if ($this->pos > 0) {
109
-			$this->seek(0);
110
-		}
111
-	}
112
-
113
-	/**
114
-	 * Verifier l'etat de l'iterateur
115
-	 *
116
-	 * @return bool
117
-	 */
118
-	public function valid(): bool {
119
-		if ($this->err) {
120
-			return false;
121
-		}
122
-		if (!$this->firstseek) {
123
-			$this->next();
124
-		}
125
-
126
-		return is_array($this->row);
127
-	}
128
-
129
-	/**
130
-	 * Valeurs sur la position courante
131
-	 *
132
-	 * @return array
133
-	 */
134
-	#[\ReturnTypeWillChange]
135
-	public function current() {
136
-		return $this->row;
137
-	}
138
-
139
-	#[\ReturnTypeWillChange]
140
-	public function key() {
141
-		return $this->pos;
142
-	}
143
-
144
-	/**
145
-	 * Sauter a une position absolue
146
-	 *
147
-	 * @param int $n
148
-	 * @param null|string $continue
149
-	 * @return bool
150
-	 */
151
-	public function seek($n = 0, $continue = null) {
152
-		if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
153
-			// SQLite ne sait pas seek(), il faut relancer la query
154
-			// si la position courante est apres la position visee
155
-			// il faut relancer la requete
156
-			if ($this->pos > $n) {
157
-				$this->free();
158
-				$this->select();
159
-				$this->valid();
160
-			}
161
-			// et utiliser la methode par defaut pour se deplacer au bon endroit
162
-			// (sera fait en cas d'echec de cette fonction)
163
-			return false;
164
-		}
165
-		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
166
-		$this->pos = min($n, $this->count());
167
-
168
-		return true;
169
-	}
170
-
171
-	/**
172
-	 * Avancer d'un cran
173
-	 *
174
-	 * @return void
175
-	 */
176
-	public function next(): void {
177
-		$this->row = sql_fetch($this->sqlresult, $this->command['connect']);
178
-		$this->pos++;
179
-		$this->firstseek |= true;
180
-	}
181
-
182
-	/**
183
-	 * Avancer et retourner les donnees pour le nouvel element
184
-	 *
185
-	 * @return array|bool|null
186
-	 */
187
-	public function fetch() {
188
-		if ($this->valid()) {
189
-			$r = $this->current();
190
-			$this->next();
191
-		} else {
192
-			$r = false;
193
-		}
194
-
195
-		return $r;
196
-	}
197
-
198
-	/**
199
-	 * liberer les ressources
200
-	 *
201
-	 * @return bool
202
-	 */
203
-	public function free() {
204
-		if (!$this->sqlresult) {
205
-			return true;
206
-		}
207
-		$a = sql_free($this->sqlresult, $this->command['connect']);
208
-		$this->sqlresult = null;
209
-
210
-		return $a;
211
-	}
212
-
213
-	/**
214
-	 * Compter le nombre de resultats
215
-	 *
216
-	 * @return int
217
-	 */
218
-	public function count() {
219
-		if (is_null($this->total)) {
220
-			if (!$this->sqlresult) {
221
-				$this->total = 0;
222
-			} else {
223
-				# cas count(*)
224
-				if (in_array('count(*)', $this->command['select'])) {
225
-					$this->valid();
226
-					$s = $this->current();
227
-					$this->total = $s['count(*)'];
228
-				} else {
229
-					$this->total = sql_count($this->sqlresult, $this->command['connect']);
230
-				}
231
-			}
232
-		}
233
-
234
-		return $this->total;
235
-	}
95
+    public function __construct($command, $info = []) {
96
+        $this->type = 'SQL';
97
+        $this->command = $command;
98
+        $this->info = $info;
99
+        $this->select();
100
+    }
101
+
102
+    /**
103
+     * Rembobiner
104
+     *
105
+     * @return bool
106
+     */
107
+    public function rewind(): void {
108
+        if ($this->pos > 0) {
109
+            $this->seek(0);
110
+        }
111
+    }
112
+
113
+    /**
114
+     * Verifier l'etat de l'iterateur
115
+     *
116
+     * @return bool
117
+     */
118
+    public function valid(): bool {
119
+        if ($this->err) {
120
+            return false;
121
+        }
122
+        if (!$this->firstseek) {
123
+            $this->next();
124
+        }
125
+
126
+        return is_array($this->row);
127
+    }
128
+
129
+    /**
130
+     * Valeurs sur la position courante
131
+     *
132
+     * @return array
133
+     */
134
+    #[\ReturnTypeWillChange]
135
+    public function current() {
136
+        return $this->row;
137
+    }
138
+
139
+    #[\ReturnTypeWillChange]
140
+    public function key() {
141
+        return $this->pos;
142
+    }
143
+
144
+    /**
145
+     * Sauter a une position absolue
146
+     *
147
+     * @param int $n
148
+     * @param null|string $continue
149
+     * @return bool
150
+     */
151
+    public function seek($n = 0, $continue = null) {
152
+        if (!sql_seek($this->sqlresult, $n, $this->command['connect'], $continue)) {
153
+            // SQLite ne sait pas seek(), il faut relancer la query
154
+            // si la position courante est apres la position visee
155
+            // il faut relancer la requete
156
+            if ($this->pos > $n) {
157
+                $this->free();
158
+                $this->select();
159
+                $this->valid();
160
+            }
161
+            // et utiliser la methode par defaut pour se deplacer au bon endroit
162
+            // (sera fait en cas d'echec de cette fonction)
163
+            return false;
164
+        }
165
+        $this->row = sql_fetch($this->sqlresult, $this->command['connect']);
166
+        $this->pos = min($n, $this->count());
167
+
168
+        return true;
169
+    }
170
+
171
+    /**
172
+     * Avancer d'un cran
173
+     *
174
+     * @return void
175
+     */
176
+    public function next(): void {
177
+        $this->row = sql_fetch($this->sqlresult, $this->command['connect']);
178
+        $this->pos++;
179
+        $this->firstseek |= true;
180
+    }
181
+
182
+    /**
183
+     * Avancer et retourner les donnees pour le nouvel element
184
+     *
185
+     * @return array|bool|null
186
+     */
187
+    public function fetch() {
188
+        if ($this->valid()) {
189
+            $r = $this->current();
190
+            $this->next();
191
+        } else {
192
+            $r = false;
193
+        }
194
+
195
+        return $r;
196
+    }
197
+
198
+    /**
199
+     * liberer les ressources
200
+     *
201
+     * @return bool
202
+     */
203
+    public function free() {
204
+        if (!$this->sqlresult) {
205
+            return true;
206
+        }
207
+        $a = sql_free($this->sqlresult, $this->command['connect']);
208
+        $this->sqlresult = null;
209
+
210
+        return $a;
211
+    }
212
+
213
+    /**
214
+     * Compter le nombre de resultats
215
+     *
216
+     * @return int
217
+     */
218
+    public function count() {
219
+        if (is_null($this->total)) {
220
+            if (!$this->sqlresult) {
221
+                $this->total = 0;
222
+            } else {
223
+                # cas count(*)
224
+                if (in_array('count(*)', $this->command['select'])) {
225
+                    $this->valid();
226
+                    $s = $this->current();
227
+                    $this->total = $s['count(*)'];
228
+                } else {
229
+                    $this->total = sql_count($this->sqlresult, $this->command['connect']);
230
+                }
231
+            }
232
+        }
233
+
234
+        return $this->total;
235
+    }
236 236
 }
Please login to merge, or discard this patch.
ecrire/action/api_transmettre.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -17,91 +17,91 @@
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 
24 24
 function action_api_transmettre_dist($arg = null) {
25 25
 
26
-	// Obtenir l'argument 'id_auteur/cle/format/fond'
27
-	if (is_null($arg)) {
28
-		$arg = _request('arg');
29
-	}
30
-
31
-	$args = explode('/', $arg);
32
-
33
-	if (count($args) !== 4) {
34
-		action_api_transmettre_fail($arg);
35
-	}
36
-
37
-	[$id_auteur, $cle, $format, $fond] = $args;
38
-	$id_auteur = intval($id_auteur);
39
-
40
-	if (preg_match(',[^\w\\.-],', $format)) {
41
-		action_api_transmettre_fail("format $format ??");
42
-	}
43
-	if (preg_match(',[^\w\\.-],', $fond)) {
44
-		action_api_transmettre_fail("fond $fond ??");
45
-	}
46
-
47
-	// verifier la cle
48
-	//[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
49
-	//[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
50
-
51
-	$qs = $_SERVER['QUERY_STRING'];
52
-	// retirer action et arg de la qs
53
-	$contexte = [];
54
-	parse_str($qs, $contexte);
55
-	foreach ($contexte as $k => $v) {
56
-		if (in_array($k, ['action', 'arg', 'var_mode'])) {
57
-			unset($contexte[$k]);
58
-		}
59
-	}
60
-	$qs = http_build_query($contexte);
61
-	if (!securiser_acces_low_sec(intval($id_auteur), $cle, "transmettre/$format", $fond, $qs)) {
62
-		// si le autoriser low_sec n'est pas bon, on peut valider l'appel si l'auteur est identifie
63
-		include_spip('inc/autoriser');
64
-		$autoriser_type = preg_replace(',\W+,', '', "_{$format}{$fond}");
65
-		if (
66
-			!$id_auteur
67
-			or empty($GLOBALS['visiteur_session']['id_auteur'])
68
-			or $GLOBALS['visiteur_session']['id_auteur'] != $id_auteur
69
-			or !autoriser('transmettre', $autoriser_type, $id_auteur)
70
-		) {
71
-			action_api_transmettre_fail("auth QS $qs ??");
72
-		}
73
-	}
74
-
75
-	$contexte['id_auteur'] = $id_auteur;
76
-
77
-	$fond = "transmettre/$format/$fond";
78
-
79
-	if (!trouver_fond($fond)) {
80
-		$fond = "prive/$fond";
81
-	}
82
-
83
-	if (!trouver_fond($fond)) {
84
-		action_api_transmettre_fail("fond $fond ??");
85
-	}
86
-
87
-	$res = recuperer_fond($fond, $contexte, ['raw' => true]);
88
-	if (!empty($res['entetes'])) {
89
-		foreach ($res['entetes'] as $h => $v) {
90
-			header("$h: $v");
91
-		}
92
-	}
93
-
94
-	$res = ltrim($res['texte']);
95
-	if (empty($res)) {
96
-		spip_log("$arg $qs resultat vide", 'transmettre' . _LOG_INFO_IMPORTANTE);
97
-	}
98
-
99
-	echo $res;
100
-	exit();
26
+    // Obtenir l'argument 'id_auteur/cle/format/fond'
27
+    if (is_null($arg)) {
28
+        $arg = _request('arg');
29
+    }
30
+
31
+    $args = explode('/', $arg);
32
+
33
+    if (count($args) !== 4) {
34
+        action_api_transmettre_fail($arg);
35
+    }
36
+
37
+    [$id_auteur, $cle, $format, $fond] = $args;
38
+    $id_auteur = intval($id_auteur);
39
+
40
+    if (preg_match(',[^\w\\.-],', $format)) {
41
+        action_api_transmettre_fail("format $format ??");
42
+    }
43
+    if (preg_match(',[^\w\\.-],', $fond)) {
44
+        action_api_transmettre_fail("fond $fond ??");
45
+    }
46
+
47
+    // verifier la cle
48
+    //[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
49
+    //[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
50
+
51
+    $qs = $_SERVER['QUERY_STRING'];
52
+    // retirer action et arg de la qs
53
+    $contexte = [];
54
+    parse_str($qs, $contexte);
55
+    foreach ($contexte as $k => $v) {
56
+        if (in_array($k, ['action', 'arg', 'var_mode'])) {
57
+            unset($contexte[$k]);
58
+        }
59
+    }
60
+    $qs = http_build_query($contexte);
61
+    if (!securiser_acces_low_sec(intval($id_auteur), $cle, "transmettre/$format", $fond, $qs)) {
62
+        // si le autoriser low_sec n'est pas bon, on peut valider l'appel si l'auteur est identifie
63
+        include_spip('inc/autoriser');
64
+        $autoriser_type = preg_replace(',\W+,', '', "_{$format}{$fond}");
65
+        if (
66
+            !$id_auteur
67
+            or empty($GLOBALS['visiteur_session']['id_auteur'])
68
+            or $GLOBALS['visiteur_session']['id_auteur'] != $id_auteur
69
+            or !autoriser('transmettre', $autoriser_type, $id_auteur)
70
+        ) {
71
+            action_api_transmettre_fail("auth QS $qs ??");
72
+        }
73
+    }
74
+
75
+    $contexte['id_auteur'] = $id_auteur;
76
+
77
+    $fond = "transmettre/$format/$fond";
78
+
79
+    if (!trouver_fond($fond)) {
80
+        $fond = "prive/$fond";
81
+    }
82
+
83
+    if (!trouver_fond($fond)) {
84
+        action_api_transmettre_fail("fond $fond ??");
85
+    }
86
+
87
+    $res = recuperer_fond($fond, $contexte, ['raw' => true]);
88
+    if (!empty($res['entetes'])) {
89
+        foreach ($res['entetes'] as $h => $v) {
90
+            header("$h: $v");
91
+        }
92
+    }
93
+
94
+    $res = ltrim($res['texte']);
95
+    if (empty($res)) {
96
+        spip_log("$arg $qs resultat vide", 'transmettre' . _LOG_INFO_IMPORTANTE);
97
+    }
98
+
99
+    echo $res;
100
+    exit();
101 101
 }
102 102
 
103 103
 function action_api_transmettre_fail($arg) {
104
-	include_spip('inc/minipres');
105
-	echo minipres(_T('info_acces_interdit'), $arg);
106
-	exit;
104
+    include_spip('inc/minipres');
105
+    echo minipres(_T('info_acces_interdit'), $arg);
106
+    exit;
107 107
 }
Please login to merge, or discard this patch.
ecrire/public/iterateur.php 1 patch
Indentation   +654 added lines, -654 removed lines patch added patch discarded remove patch
@@ -11,7 +11,7 @@  discard block
 block discarded – undo
11 11
 \***************************************************************************/
12 12
 
13 13
 if (!defined('_ECRIRE_INC_VERSION')) {
14
-	return;
14
+    return;
15 15
 }
16 16
 
17 17
 /**
@@ -21,667 +21,667 @@  discard block
 block discarded – undo
21 21
  *
22 22
  */
23 23
 class IterFactory {
24
-	public static function create($iterateur, $command, $info = null) {
25
-
26
-		$iter = null;
27
-		// cas des SI {si expression} analises tres tot
28
-		// pour eviter le chargement de tout iterateur
29
-		if (isset($command['si'])) {
30
-			foreach ($command['si'] as $si) {
31
-				if (!$si) {
32
-					// $command pour boucle SQL peut generer des erreurs de compilation
33
-					// s'il est transmis alors qu'on est dans un iterateur vide
34
-					return new IterDecorator(new EmptyIterator(), [], $info);
35
-				}
36
-			}
37
-		}
38
-
39
-		// chercher un iterateur PHP existant (par exemple dans SPL)
40
-		// (il faudrait passer l'argument ->sql_serveur
41
-		// pour etre certain qu'on est sur un "php:")
42
-		if (class_exists($iterateur)) {
43
-			$a = $command['args'] ?? [];
44
-
45
-			// permettre de passer un Iterateur directement {args #ITERATEUR} :
46
-			// si on recoit deja un iterateur en argument, on l'utilise
47
-			if ((is_countable($a) ? count($a) : 0) == 1 and is_object($a[0]) and is_subclass_of($a[0], \Iterator::class)) {
48
-				$iter = $a[0];
49
-
50
-				// sinon, on cree un iterateur du type donne
51
-			} else {
52
-				// arguments de creation de l'iterateur...
53
-				// (pas glop)
54
-				try {
55
-					switch (is_countable($a) ? count($a) : 0) {
56
-						case 0:
57
-							$iter = new $iterateur();
58
-							break;
59
-						case 1:
60
-							$iter = new $iterateur($a[0]);
61
-							break;
62
-						case 2:
63
-							$iter = new $iterateur($a[0], $a[1]);
64
-							break;
65
-						case 3:
66
-							$iter = new $iterateur($a[0], $a[1], $a[2]);
67
-							break;
68
-						case 4:
69
-							$iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
70
-							break;
71
-					}
72
-				} catch (Exception $e) {
73
-					spip_log("Erreur de chargement de l'iterateur $iterateur");
74
-					spip_log($e->getMessage());
75
-					$iter = new EmptyIterator();
76
-				}
77
-			}
78
-		} else {
79
-			// chercher la classe d'iterateur
80
-			// IterateurXXX
81
-			// definie dans le fichier iterateurs/xxx.php
82
-			$class = 'Iterateur' . $iterateur;
83
-			if (!class_exists($class)) {
84
-				if (
85
-					!include_spip('iterateur/' . strtolower($iterateur))
86
-					or !class_exists($class)
87
-				) {
88
-					die("Iterateur $iterateur non trouv&#233;");
89
-					// si l'iterateur n'existe pas, on se rabat sur le generique
90
-					# $iter = new EmptyIterator();
91
-				}
92
-			}
93
-			$iter = new $class($command, $info);
94
-		}
95
-
96
-		return new IterDecorator($iter, $command, $info);
97
-	}
24
+    public static function create($iterateur, $command, $info = null) {
25
+
26
+        $iter = null;
27
+        // cas des SI {si expression} analises tres tot
28
+        // pour eviter le chargement de tout iterateur
29
+        if (isset($command['si'])) {
30
+            foreach ($command['si'] as $si) {
31
+                if (!$si) {
32
+                    // $command pour boucle SQL peut generer des erreurs de compilation
33
+                    // s'il est transmis alors qu'on est dans un iterateur vide
34
+                    return new IterDecorator(new EmptyIterator(), [], $info);
35
+                }
36
+            }
37
+        }
38
+
39
+        // chercher un iterateur PHP existant (par exemple dans SPL)
40
+        // (il faudrait passer l'argument ->sql_serveur
41
+        // pour etre certain qu'on est sur un "php:")
42
+        if (class_exists($iterateur)) {
43
+            $a = $command['args'] ?? [];
44
+
45
+            // permettre de passer un Iterateur directement {args #ITERATEUR} :
46
+            // si on recoit deja un iterateur en argument, on l'utilise
47
+            if ((is_countable($a) ? count($a) : 0) == 1 and is_object($a[0]) and is_subclass_of($a[0], \Iterator::class)) {
48
+                $iter = $a[0];
49
+
50
+                // sinon, on cree un iterateur du type donne
51
+            } else {
52
+                // arguments de creation de l'iterateur...
53
+                // (pas glop)
54
+                try {
55
+                    switch (is_countable($a) ? count($a) : 0) {
56
+                        case 0:
57
+                            $iter = new $iterateur();
58
+                            break;
59
+                        case 1:
60
+                            $iter = new $iterateur($a[0]);
61
+                            break;
62
+                        case 2:
63
+                            $iter = new $iterateur($a[0], $a[1]);
64
+                            break;
65
+                        case 3:
66
+                            $iter = new $iterateur($a[0], $a[1], $a[2]);
67
+                            break;
68
+                        case 4:
69
+                            $iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
70
+                            break;
71
+                    }
72
+                } catch (Exception $e) {
73
+                    spip_log("Erreur de chargement de l'iterateur $iterateur");
74
+                    spip_log($e->getMessage());
75
+                    $iter = new EmptyIterator();
76
+                }
77
+            }
78
+        } else {
79
+            // chercher la classe d'iterateur
80
+            // IterateurXXX
81
+            // definie dans le fichier iterateurs/xxx.php
82
+            $class = 'Iterateur' . $iterateur;
83
+            if (!class_exists($class)) {
84
+                if (
85
+                    !include_spip('iterateur/' . strtolower($iterateur))
86
+                    or !class_exists($class)
87
+                ) {
88
+                    die("Iterateur $iterateur non trouv&#233;");
89
+                    // si l'iterateur n'existe pas, on se rabat sur le generique
90
+                    # $iter = new EmptyIterator();
91
+                }
92
+            }
93
+            $iter = new $class($command, $info);
94
+        }
95
+
96
+        return new IterDecorator($iter, $command, $info);
97
+    }
98 98
 }
99 99
 
100 100
 
101 101
 class IterDecorator extends FilterIterator {
102
-	private $iter;
103
-
104
-	/**
105
-	 * Conditions de filtrage
106
-	 * ie criteres de selection
107
-	 *
108
-	 * @var array
109
-	 */
110
-	protected $filtre = [];
111
-
112
-	/**
113
-	 * Fonction de filtrage compilee a partir des criteres de filtre
114
-	 *
115
-	 * @var string
116
-	 */
117
-	protected $func_filtre = null;
118
-
119
-	/**
120
-	 * Critere {offset, limit}
121
-	 *
122
-	 * @var int
123
-	 * @var int
124
-	 */
125
-	protected $offset = null;
126
-	protected $limit = null;
127
-
128
-	/**
129
-	 * nombre d'elements recuperes depuis la position 0,
130
-	 * en tenant compte des filtres
131
-	 *
132
-	 * @var int
133
-	 */
134
-	protected $fetched = 0;
135
-
136
-	/**
137
-	 * Y a t'il une erreur ?
138
-	 *
139
-	 * @var bool
140
-	 **/
141
-	protected $err = false;
142
-
143
-	/**
144
-	 * Drapeau a activer en cas d'echec
145
-	 * (select SQL errone, non chargement des DATA, etc)
146
-	 */
147
-	public function err() {
148
-		if (method_exists($this->iter, 'err')) {
149
-			return $this->iter->err();
150
-		}
151
-		if (property_exists($this->iter, 'err')) {
152
-			return $this->iter->err;
153
-		}
154
-
155
-		return false;
156
-	}
157
-
158
-	public function __construct(Iterator $iter, $command, $info) {
159
-		parent::__construct($iter);
160
-		parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
161
-
162
-		// recuperer l'iterateur transmis
163
-		$this->iter = $this->getInnerIterator();
164
-		$this->command = $command;
165
-		$this->info = $info;
166
-		$this->pos = 0;
167
-		$this->fetched = 0;
168
-
169
-		// chercher la liste des champs a retourner par
170
-		// fetch si l'objet ne les calcule pas tout seul
171
-		if (!method_exists($this->iter, 'fetch')) {
172
-			$this->calculer_select();
173
-			$this->calculer_filtres();
174
-		}
175
-
176
-		// emptyIterator critere {si} faux n'a pas d'erreur !
177
-		if (isset($this->iter->err)) {
178
-			$this->err = $this->iter->err;
179
-		}
180
-
181
-		// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
182
-		//$this->total = $this->count();
183
-	}
184
-
185
-
186
-	// calcule les elements a retournes par fetch()
187
-	// enleve les elements inutiles du select()
188
-	//
189
-	private function calculer_select() {
190
-		if ($select = &$this->command['select']) {
191
-			foreach ($select as $s) {
192
-				// /!\ $s = '.nom'
193
-				if ($s[0] == '.') {
194
-					$s = substr($s, 1);
195
-				}
196
-				$this->select[] = $s;
197
-			}
198
-		}
199
-	}
200
-
201
-	// recuperer la valeur d'une balise #X
202
-	// en fonction des methodes
203
-	// et proprietes disponibles
204
-	public function get_select($nom) {
205
-		if (
206
-			is_object($this->iter)
207
-			and method_exists($this->iter, $nom)
208
-		) {
209
-			try {
210
-				return $this->iter->$nom();
211
-			} catch (Exception $e) {
212
-				// #GETCHILDREN sur un fichier de DirectoryIterator ...
213
-				spip_log("Methode $nom en echec sur " . get_class($this->iter));
214
-				spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
215
-
216
-				return '';
217
-			}
218
-		}
219
-		/*
102
+    private $iter;
103
+
104
+    /**
105
+     * Conditions de filtrage
106
+     * ie criteres de selection
107
+     *
108
+     * @var array
109
+     */
110
+    protected $filtre = [];
111
+
112
+    /**
113
+     * Fonction de filtrage compilee a partir des criteres de filtre
114
+     *
115
+     * @var string
116
+     */
117
+    protected $func_filtre = null;
118
+
119
+    /**
120
+     * Critere {offset, limit}
121
+     *
122
+     * @var int
123
+     * @var int
124
+     */
125
+    protected $offset = null;
126
+    protected $limit = null;
127
+
128
+    /**
129
+     * nombre d'elements recuperes depuis la position 0,
130
+     * en tenant compte des filtres
131
+     *
132
+     * @var int
133
+     */
134
+    protected $fetched = 0;
135
+
136
+    /**
137
+     * Y a t'il une erreur ?
138
+     *
139
+     * @var bool
140
+     **/
141
+    protected $err = false;
142
+
143
+    /**
144
+     * Drapeau a activer en cas d'echec
145
+     * (select SQL errone, non chargement des DATA, etc)
146
+     */
147
+    public function err() {
148
+        if (method_exists($this->iter, 'err')) {
149
+            return $this->iter->err();
150
+        }
151
+        if (property_exists($this->iter, 'err')) {
152
+            return $this->iter->err;
153
+        }
154
+
155
+        return false;
156
+    }
157
+
158
+    public function __construct(Iterator $iter, $command, $info) {
159
+        parent::__construct($iter);
160
+        parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
161
+
162
+        // recuperer l'iterateur transmis
163
+        $this->iter = $this->getInnerIterator();
164
+        $this->command = $command;
165
+        $this->info = $info;
166
+        $this->pos = 0;
167
+        $this->fetched = 0;
168
+
169
+        // chercher la liste des champs a retourner par
170
+        // fetch si l'objet ne les calcule pas tout seul
171
+        if (!method_exists($this->iter, 'fetch')) {
172
+            $this->calculer_select();
173
+            $this->calculer_filtres();
174
+        }
175
+
176
+        // emptyIterator critere {si} faux n'a pas d'erreur !
177
+        if (isset($this->iter->err)) {
178
+            $this->err = $this->iter->err;
179
+        }
180
+
181
+        // pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
182
+        //$this->total = $this->count();
183
+    }
184
+
185
+
186
+    // calcule les elements a retournes par fetch()
187
+    // enleve les elements inutiles du select()
188
+    //
189
+    private function calculer_select() {
190
+        if ($select = &$this->command['select']) {
191
+            foreach ($select as $s) {
192
+                // /!\ $s = '.nom'
193
+                if ($s[0] == '.') {
194
+                    $s = substr($s, 1);
195
+                }
196
+                $this->select[] = $s;
197
+            }
198
+        }
199
+    }
200
+
201
+    // recuperer la valeur d'une balise #X
202
+    // en fonction des methodes
203
+    // et proprietes disponibles
204
+    public function get_select($nom) {
205
+        if (
206
+            is_object($this->iter)
207
+            and method_exists($this->iter, $nom)
208
+        ) {
209
+            try {
210
+                return $this->iter->$nom();
211
+            } catch (Exception $e) {
212
+                // #GETCHILDREN sur un fichier de DirectoryIterator ...
213
+                spip_log("Methode $nom en echec sur " . get_class($this->iter));
214
+                spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
215
+
216
+                return '';
217
+            }
218
+        }
219
+        /*
220 220
 		if (property_exists($this->iter, $nom)) {
221 221
 			return $this->iter->$nom;
222 222
 		}*/
223
-		// cle et valeur par defaut
224
-		// ICI PLANTAGE SI ON NE CONTROLE PAS $nom
225
-		if (
226
-			in_array($nom, ['cle', 'valeur'])
227
-			and method_exists($this, $nom)
228
-		) {
229
-			return $this->$nom();
230
-		}
231
-
232
-		// Par defaut chercher en xpath dans la valeur()
233
-		return table_valeur($this->valeur(), $nom, null);
234
-	}
235
-
236
-
237
-	private function calculer_filtres() {
238
-
239
-		// Issu de calculer_select() de public/composer L.519
240
-		// TODO: externaliser...
241
-		//
242
-		// retirer les criteres vides:
243
-		// {X ?} avec X absent de l'URL
244
-		// {par #ENV{X}} avec X absent de l'URL
245
-		// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
246
-		if ($where = &$this->command['where']) {
247
-			foreach ($where as $k => $v) {
248
-				$this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
249
-			}
250
-		}
251
-
252
-		// critere {2,7}
253
-		if (isset($this->command['limit']) and $this->command['limit']) {
254
-			$limit = explode(',', $this->command['limit']);
255
-			$this->offset = $limit[0];
256
-			$this->limit = $limit[1];
257
-		}
258
-
259
-		// Creer la fonction de filtrage sur $this
260
-		if ($this->filtre) {
261
-			if ($filtres = $this->assembler_filtres($this->filtre)) {
262
-				$filtres = 'return ' . $filtres . ';';
263
-				$this->func_filtre = fn() => eval($filtres);
264
-			}
265
-			else {
266
-				$this->func_filtre = null;
267
-			}
268
-		}
269
-	}
270
-
271
-	/**
272
-	 * Assembler le tableau de filtres traduits depuis les conditions SQL
273
-	 * les filtres vides ou null sont ignores
274
-	 * @param $filtres
275
-	 * @param string $operateur
276
-	 * @return string|null
277
-	 */
278
-	protected function assembler_filtres($filtres, $operateur = 'AND') {
279
-
280
-		$filtres_string = [];
281
-		foreach ($filtres as $k => $v) {
282
-			// si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
283
-			if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
284
-				$op = array_shift($v);
285
-				$v = $this->assembler_filtres($v, $op);
286
-			}
287
-			if (is_null($v) or !is_string($v) or empty($v)) {
288
-				continue;
289
-			}
290
-			$filtres_string[] = $v;
291
-		}
292
-
293
-		if (!count($filtres_string)) {
294
-			return null;
295
-		}
296
-
297
-		return '(' . implode(") $operateur (", $filtres_string) . ')';
298
-	}
299
-
300
-	/**
301
-	 * Traduire un element du tableau where SQL en un filtre
302
-	 * @param $v
303
-	 * @return string|array|null
304
-	 */
305
-	protected function traduire_condition_sql_en_filtre($v) {
306
-		if (is_array($v)) {
307
-			if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
308
-				return 'true';
309
-			} elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
310
-				return 'true';
311
-			} else {
312
-				$op = $v[0] ?: $v;
313
-			}
314
-		} else {
315
-			$op = $v;
316
-		}
317
-		if ((!$op) or ($op == 1) or ($op == '0=0')) {
318
-			return 'true';
319
-		}
320
-		if ($op === '0=1') {
321
-			return 'false';
322
-		}
323
-		// traiter {cle IN a,b} ou {valeur !IN a,b}
324
-		if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
325
-			return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
326
-		}
327
-
328
-		// 3 possibilites : count($v) =
329
-		// * 1 : {x y} ; on recoit $v[0] = y
330
-		// * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
331
-		// * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
332
-
333
-		// 1 : forcement traite par un critere, on passe
334
-		if (!$v or !is_array($v) or count($v) == 1) {
335
-			return null; // sera ignore
336
-		}
337
-		if (count($v) == 2 and is_array($v[1])) {
338
-			return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
339
-		}
340
-		if (count($v) == 3) {
341
-			// traiter le OR/AND suivi de 2 valeurs
342
-			if (in_array($op, ['OR', 'AND'])) {
343
-				array_shift($v);
344
-				foreach (array_keys($v) as $k) {
345
-					$v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
346
-					if ($v[$k] === null) {
347
-						unset($v[$k]);
348
-					}
349
-					elseif ($v[$k] === 'true') {
350
-						if ($op === 'OR') {
351
-							return 'true';
352
-						}
353
-						if ($op === 'AND') {
354
-							unset($v[$k]);
355
-						}
356
-					}
357
-					elseif ($v[$k] === 'false') {
358
-						if ($op === 'OR') {
359
-							unset($v[$k]);
360
-						}
361
-						if ($op === 'AND') {
362
-							return 'false';
363
-						}
364
-					}
365
-				}
366
-				if (!count($v)) {
367
-					return null;
368
-				}
369
-				if (count($v) === 1) {
370
-					return reset($v);
371
-				}
372
-				array_unshift($v, $op);
373
-				return $v;
374
-			}
375
-			return $this->composer_filtre($v[1], $v[0], $v[2]);
376
-		}
377
-
378
-		return null;  // sera ignore
379
-	}
380
-
381
-	/**
382
-	 * Calculer un filtre sur un champ du tableau
383
-	 * @param $cle
384
-	 * @param $op
385
-	 * @param $valeur
386
-	 * @param false $not
387
-	 * @return string|null
388
-	 */
389
-	protected function composer_filtre($cle, $op, $valeur, $not = false) {
390
-		if (method_exists($this->iter, 'exception_des_criteres')) {
391
-			if (in_array($cle, $this->iter->exception_des_criteres())) {
392
-				return null;
393
-			}
394
-		}
395
-		// TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
396
-		# mais c'est normalement deja opere par calculer_critere_infixe()
397
-		# qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
398
-		# ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
399
-		# il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
400
-
401
-		# if (!in_array($cle, array('cle', 'valeur')))
402
-		#	return;
403
-
404
-		$a = '$this->get_select(\'' . $cle . '\')';
405
-
406
-		$filtre = '';
407
-
408
-		if ($op == 'REGEXP') {
409
-			$filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
410
-			$op = '';
411
-		} else {
412
-			if ($op == 'LIKE') {
413
-				$valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
414
-				$filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
415
-				$op = '';
416
-			} else {
417
-				if ($op == '=') {
418
-					$op = '==';
419
-				} else {
420
-					if ($op == 'IN') {
421
-						$filtre = 'in_array(' . $a . ', array' . $valeur . ')';
422
-						$op = '';
423
-					} else {
424
-						if (!in_array($op, ['<', '<=', '>', '>='])) {
425
-							spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
426
-							$op = '';
427
-						}
428
-					}
429
-				}
430
-			}
431
-		}
432
-
433
-		if ($op) {
434
-			$filtre = $a . $op . str_replace('\"', '"', $valeur);
435
-		}
436
-
437
-		if ($not) {
438
-			$filtre = "!($filtre)";
439
-		}
440
-
441
-		return $filtre;
442
-	}
443
-
444
-
445
-	public function next(): void {
446
-		$this->pos++;
447
-		parent::next();
448
-	}
449
-
450
-	/**
451
-	 * revient au depart
452
-	 *
453
-	 * @return void
454
-	 */
455
-	public function rewind(): void {
456
-		$this->pos = 0;
457
-		$this->fetched = 0;
458
-		parent::rewind();
459
-	}
460
-
461
-
462
-	# Extension SPIP des iterateurs PHP
463
-	/**
464
-	 * type de l'iterateur
465
-	 *
466
-	 * @var string
467
-	 */
468
-	protected $type;
469
-
470
-	/**
471
-	 * parametres de l'iterateur
472
-	 *
473
-	 * @var array
474
-	 */
475
-	protected $command;
476
-
477
-	/**
478
-	 * infos de compilateur
479
-	 *
480
-	 * @var array
481
-	 */
482
-	protected $info;
483
-
484
-	/**
485
-	 * position courante de l'iterateur
486
-	 *
487
-	 * @var int
488
-	 */
489
-	protected $pos = null;
490
-
491
-	/**
492
-	 * nombre total resultats dans l'iterateur
493
-	 *
494
-	 * @var int
495
-	 */
496
-	protected $total = null;
497
-
498
-	/**
499
-	 * nombre maximal de recherche pour $total
500
-	 * si l'iterateur n'implemente pas de fonction specifique
501
-	 */
502
-	protected $max = 100000;
503
-
504
-
505
-	/**
506
-	 * Liste des champs a inserer dans les $row
507
-	 * retournes par ->fetch()
508
-	 */
509
-	protected $select = [];
510
-
511
-
512
-	/**
513
-	 * aller a la position absolue n,
514
-	 * comptee depuis le debut
515
-	 *
516
-	 * @param int $n
517
-	 *   absolute pos
518
-	 * @param string $continue
519
-	 *   param for sql_ api
520
-	 * @return bool
521
-	 *   success or fail if not implemented
522
-	 */
523
-	public function seek($n = 0, $continue = null) {
524
-		if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
525
-			$this->seek_loop($n);
526
-		}
527
-		$this->pos = $n;
528
-		$this->fetched = $n;
529
-
530
-		return true;
531
-	}
532
-
533
-	/*
223
+        // cle et valeur par defaut
224
+        // ICI PLANTAGE SI ON NE CONTROLE PAS $nom
225
+        if (
226
+            in_array($nom, ['cle', 'valeur'])
227
+            and method_exists($this, $nom)
228
+        ) {
229
+            return $this->$nom();
230
+        }
231
+
232
+        // Par defaut chercher en xpath dans la valeur()
233
+        return table_valeur($this->valeur(), $nom, null);
234
+    }
235
+
236
+
237
+    private function calculer_filtres() {
238
+
239
+        // Issu de calculer_select() de public/composer L.519
240
+        // TODO: externaliser...
241
+        //
242
+        // retirer les criteres vides:
243
+        // {X ?} avec X absent de l'URL
244
+        // {par #ENV{X}} avec X absent de l'URL
245
+        // IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
246
+        if ($where = &$this->command['where']) {
247
+            foreach ($where as $k => $v) {
248
+                $this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
249
+            }
250
+        }
251
+
252
+        // critere {2,7}
253
+        if (isset($this->command['limit']) and $this->command['limit']) {
254
+            $limit = explode(',', $this->command['limit']);
255
+            $this->offset = $limit[0];
256
+            $this->limit = $limit[1];
257
+        }
258
+
259
+        // Creer la fonction de filtrage sur $this
260
+        if ($this->filtre) {
261
+            if ($filtres = $this->assembler_filtres($this->filtre)) {
262
+                $filtres = 'return ' . $filtres . ';';
263
+                $this->func_filtre = fn() => eval($filtres);
264
+            }
265
+            else {
266
+                $this->func_filtre = null;
267
+            }
268
+        }
269
+    }
270
+
271
+    /**
272
+     * Assembler le tableau de filtres traduits depuis les conditions SQL
273
+     * les filtres vides ou null sont ignores
274
+     * @param $filtres
275
+     * @param string $operateur
276
+     * @return string|null
277
+     */
278
+    protected function assembler_filtres($filtres, $operateur = 'AND') {
279
+
280
+        $filtres_string = [];
281
+        foreach ($filtres as $k => $v) {
282
+            // si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
283
+            if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
284
+                $op = array_shift($v);
285
+                $v = $this->assembler_filtres($v, $op);
286
+            }
287
+            if (is_null($v) or !is_string($v) or empty($v)) {
288
+                continue;
289
+            }
290
+            $filtres_string[] = $v;
291
+        }
292
+
293
+        if (!count($filtres_string)) {
294
+            return null;
295
+        }
296
+
297
+        return '(' . implode(") $operateur (", $filtres_string) . ')';
298
+    }
299
+
300
+    /**
301
+     * Traduire un element du tableau where SQL en un filtre
302
+     * @param $v
303
+     * @return string|array|null
304
+     */
305
+    protected function traduire_condition_sql_en_filtre($v) {
306
+        if (is_array($v)) {
307
+            if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
308
+                return 'true';
309
+            } elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
310
+                return 'true';
311
+            } else {
312
+                $op = $v[0] ?: $v;
313
+            }
314
+        } else {
315
+            $op = $v;
316
+        }
317
+        if ((!$op) or ($op == 1) or ($op == '0=0')) {
318
+            return 'true';
319
+        }
320
+        if ($op === '0=1') {
321
+            return 'false';
322
+        }
323
+        // traiter {cle IN a,b} ou {valeur !IN a,b}
324
+        if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
325
+            return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
326
+        }
327
+
328
+        // 3 possibilites : count($v) =
329
+        // * 1 : {x y} ; on recoit $v[0] = y
330
+        // * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
331
+        // * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
332
+
333
+        // 1 : forcement traite par un critere, on passe
334
+        if (!$v or !is_array($v) or count($v) == 1) {
335
+            return null; // sera ignore
336
+        }
337
+        if (count($v) == 2 and is_array($v[1])) {
338
+            return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
339
+        }
340
+        if (count($v) == 3) {
341
+            // traiter le OR/AND suivi de 2 valeurs
342
+            if (in_array($op, ['OR', 'AND'])) {
343
+                array_shift($v);
344
+                foreach (array_keys($v) as $k) {
345
+                    $v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
346
+                    if ($v[$k] === null) {
347
+                        unset($v[$k]);
348
+                    }
349
+                    elseif ($v[$k] === 'true') {
350
+                        if ($op === 'OR') {
351
+                            return 'true';
352
+                        }
353
+                        if ($op === 'AND') {
354
+                            unset($v[$k]);
355
+                        }
356
+                    }
357
+                    elseif ($v[$k] === 'false') {
358
+                        if ($op === 'OR') {
359
+                            unset($v[$k]);
360
+                        }
361
+                        if ($op === 'AND') {
362
+                            return 'false';
363
+                        }
364
+                    }
365
+                }
366
+                if (!count($v)) {
367
+                    return null;
368
+                }
369
+                if (count($v) === 1) {
370
+                    return reset($v);
371
+                }
372
+                array_unshift($v, $op);
373
+                return $v;
374
+            }
375
+            return $this->composer_filtre($v[1], $v[0], $v[2]);
376
+        }
377
+
378
+        return null;  // sera ignore
379
+    }
380
+
381
+    /**
382
+     * Calculer un filtre sur un champ du tableau
383
+     * @param $cle
384
+     * @param $op
385
+     * @param $valeur
386
+     * @param false $not
387
+     * @return string|null
388
+     */
389
+    protected function composer_filtre($cle, $op, $valeur, $not = false) {
390
+        if (method_exists($this->iter, 'exception_des_criteres')) {
391
+            if (in_array($cle, $this->iter->exception_des_criteres())) {
392
+                return null;
393
+            }
394
+        }
395
+        // TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
396
+        # mais c'est normalement deja opere par calculer_critere_infixe()
397
+        # qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
398
+        # ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
399
+        # il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
400
+
401
+        # if (!in_array($cle, array('cle', 'valeur')))
402
+        #	return;
403
+
404
+        $a = '$this->get_select(\'' . $cle . '\')';
405
+
406
+        $filtre = '';
407
+
408
+        if ($op == 'REGEXP') {
409
+            $filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
410
+            $op = '';
411
+        } else {
412
+            if ($op == 'LIKE') {
413
+                $valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
414
+                $filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
415
+                $op = '';
416
+            } else {
417
+                if ($op == '=') {
418
+                    $op = '==';
419
+                } else {
420
+                    if ($op == 'IN') {
421
+                        $filtre = 'in_array(' . $a . ', array' . $valeur . ')';
422
+                        $op = '';
423
+                    } else {
424
+                        if (!in_array($op, ['<', '<=', '>', '>='])) {
425
+                            spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
426
+                            $op = '';
427
+                        }
428
+                    }
429
+                }
430
+            }
431
+        }
432
+
433
+        if ($op) {
434
+            $filtre = $a . $op . str_replace('\"', '"', $valeur);
435
+        }
436
+
437
+        if ($not) {
438
+            $filtre = "!($filtre)";
439
+        }
440
+
441
+        return $filtre;
442
+    }
443
+
444
+
445
+    public function next(): void {
446
+        $this->pos++;
447
+        parent::next();
448
+    }
449
+
450
+    /**
451
+     * revient au depart
452
+     *
453
+     * @return void
454
+     */
455
+    public function rewind(): void {
456
+        $this->pos = 0;
457
+        $this->fetched = 0;
458
+        parent::rewind();
459
+    }
460
+
461
+
462
+    # Extension SPIP des iterateurs PHP
463
+    /**
464
+     * type de l'iterateur
465
+     *
466
+     * @var string
467
+     */
468
+    protected $type;
469
+
470
+    /**
471
+     * parametres de l'iterateur
472
+     *
473
+     * @var array
474
+     */
475
+    protected $command;
476
+
477
+    /**
478
+     * infos de compilateur
479
+     *
480
+     * @var array
481
+     */
482
+    protected $info;
483
+
484
+    /**
485
+     * position courante de l'iterateur
486
+     *
487
+     * @var int
488
+     */
489
+    protected $pos = null;
490
+
491
+    /**
492
+     * nombre total resultats dans l'iterateur
493
+     *
494
+     * @var int
495
+     */
496
+    protected $total = null;
497
+
498
+    /**
499
+     * nombre maximal de recherche pour $total
500
+     * si l'iterateur n'implemente pas de fonction specifique
501
+     */
502
+    protected $max = 100000;
503
+
504
+
505
+    /**
506
+     * Liste des champs a inserer dans les $row
507
+     * retournes par ->fetch()
508
+     */
509
+    protected $select = [];
510
+
511
+
512
+    /**
513
+     * aller a la position absolue n,
514
+     * comptee depuis le debut
515
+     *
516
+     * @param int $n
517
+     *   absolute pos
518
+     * @param string $continue
519
+     *   param for sql_ api
520
+     * @return bool
521
+     *   success or fail if not implemented
522
+     */
523
+    public function seek($n = 0, $continue = null) {
524
+        if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
525
+            $this->seek_loop($n);
526
+        }
527
+        $this->pos = $n;
528
+        $this->fetched = $n;
529
+
530
+        return true;
531
+    }
532
+
533
+    /*
534 534
 	 * aller a la position $n en parcourant
535 535
 	 * un par un tous les elements
536 536
 	 */
537
-	private function seek_loop($n) {
538
-		if ($this->pos > $n) {
539
-			$this->rewind();
540
-		}
541
-
542
-		while ($this->pos < $n and $this->valid()) {
543
-			$this->next();
544
-		}
545
-
546
-		return true;
547
-	}
548
-
549
-	/**
550
-	 * Avancer de $saut pas
551
-	 *
552
-	 * @param  $saut
553
-	 * @param  $max
554
-	 * @return int
555
-	 */
556
-	public function skip($saut, $max = null) {
557
-		// pas de saut en arriere autorise pour cette fonction
558
-		if (($saut = intval($saut)) <= 0) {
559
-			return $this->pos;
560
-		}
561
-		$seek = $this->pos + $saut;
562
-		// si le saut fait depasser le maxi, on libere la resource
563
-		// et on sort
564
-		if (is_null($max)) {
565
-			$max = $this->count();
566
-		}
567
-
568
-		if ($seek >= $max or $seek >= $this->count()) {
569
-			// sortie plus rapide que de faire next() jusqu'a la fin !
570
-			$this->free();
571
-
572
-			return $max;
573
-		}
574
-
575
-		$this->seek($seek);
576
-
577
-		return $this->pos;
578
-	}
579
-
580
-	/**
581
-	 * Renvoyer un tableau des donnees correspondantes
582
-	 * a la position courante de l'iterateur
583
-	 * en controlant si on respecte le filtre
584
-	 * Appliquer aussi le critere {offset,limit}
585
-	 *
586
-	 * @return array|bool
587
-	 */
588
-	public function fetch() {
589
-		if (method_exists($this->iter, 'fetch')) {
590
-			return $this->iter->fetch();
591
-		} else {
592
-			while (
593
-				$this->valid()
594
-				and (
595
-					!$this->accept()
596
-					or (isset($this->offset) and $this->fetched++ < $this->offset)
597
-				)
598
-			) {
599
-				$this->next();
600
-			}
601
-
602
-			if (!$this->valid()) {
603
-				return false;
604
-			}
605
-
606
-			if (
607
-				isset($this->limit)
608
-				and $this->fetched > $this->offset + $this->limit
609
-			) {
610
-				return false;
611
-			}
612
-
613
-			$r = [];
614
-			foreach ($this->select as $nom) {
615
-				$r[$nom] = $this->get_select($nom);
616
-			}
617
-			$this->next();
618
-
619
-			return $r;
620
-		}
621
-	}
622
-
623
-	// retourner la cle pour #CLE
624
-	public function cle() {
625
-		return $this->key();
626
-	}
627
-
628
-	// retourner la valeur pour #VALEUR
629
-	public function valeur() {
630
-		return $this->current();
631
-	}
632
-
633
-	/**
634
-	 * Accepte-t-on l'entree courante lue ?
635
-	 * On execute les filtres pour le savoir.
636
-	 **/
637
-	public function accept(): bool {
638
-		if ($f = $this->func_filtre) {
639
-			return $f();
640
-		}
641
-
642
-		return true;
643
-	}
644
-
645
-	/**
646
-	 * liberer la ressource
647
-	 *
648
-	 * @return bool
649
-	 */
650
-	public function free() {
651
-		if (method_exists($this->iter, 'free')) {
652
-			$this->iter->free();
653
-		}
654
-		$this->pos = $this->total = 0;
655
-
656
-		return true;
657
-	}
658
-
659
-	/**
660
-	 * Compter le nombre total de resultats
661
-	 * pour #TOTAL_BOUCLE
662
-	 *
663
-	 * @return int
664
-	 */
665
-	public function count() {
666
-		if (is_null($this->total)) {
667
-			if (
668
-				method_exists($this->iter, 'count')
669
-				and !$this->func_filtre
670
-			) {
671
-				return $this->total = $this->iter->count();
672
-			} else {
673
-				// compter les lignes et rembobiner
674
-				$total = 0;
675
-				$pos = $this->pos; // sauver la position
676
-				$this->rewind();
677
-				while ($this->fetch() and $total < $this->max) {
678
-					$total++;
679
-				}
680
-				$this->seek($pos);
681
-				$this->total = $total;
682
-			}
683
-		}
684
-
685
-		return $this->total;
686
-	}
537
+    private function seek_loop($n) {
538
+        if ($this->pos > $n) {
539
+            $this->rewind();
540
+        }
541
+
542
+        while ($this->pos < $n and $this->valid()) {
543
+            $this->next();
544
+        }
545
+
546
+        return true;
547
+    }
548
+
549
+    /**
550
+     * Avancer de $saut pas
551
+     *
552
+     * @param  $saut
553
+     * @param  $max
554
+     * @return int
555
+     */
556
+    public function skip($saut, $max = null) {
557
+        // pas de saut en arriere autorise pour cette fonction
558
+        if (($saut = intval($saut)) <= 0) {
559
+            return $this->pos;
560
+        }
561
+        $seek = $this->pos + $saut;
562
+        // si le saut fait depasser le maxi, on libere la resource
563
+        // et on sort
564
+        if (is_null($max)) {
565
+            $max = $this->count();
566
+        }
567
+
568
+        if ($seek >= $max or $seek >= $this->count()) {
569
+            // sortie plus rapide que de faire next() jusqu'a la fin !
570
+            $this->free();
571
+
572
+            return $max;
573
+        }
574
+
575
+        $this->seek($seek);
576
+
577
+        return $this->pos;
578
+    }
579
+
580
+    /**
581
+     * Renvoyer un tableau des donnees correspondantes
582
+     * a la position courante de l'iterateur
583
+     * en controlant si on respecte le filtre
584
+     * Appliquer aussi le critere {offset,limit}
585
+     *
586
+     * @return array|bool
587
+     */
588
+    public function fetch() {
589
+        if (method_exists($this->iter, 'fetch')) {
590
+            return $this->iter->fetch();
591
+        } else {
592
+            while (
593
+                $this->valid()
594
+                and (
595
+                    !$this->accept()
596
+                    or (isset($this->offset) and $this->fetched++ < $this->offset)
597
+                )
598
+            ) {
599
+                $this->next();
600
+            }
601
+
602
+            if (!$this->valid()) {
603
+                return false;
604
+            }
605
+
606
+            if (
607
+                isset($this->limit)
608
+                and $this->fetched > $this->offset + $this->limit
609
+            ) {
610
+                return false;
611
+            }
612
+
613
+            $r = [];
614
+            foreach ($this->select as $nom) {
615
+                $r[$nom] = $this->get_select($nom);
616
+            }
617
+            $this->next();
618
+
619
+            return $r;
620
+        }
621
+    }
622
+
623
+    // retourner la cle pour #CLE
624
+    public function cle() {
625
+        return $this->key();
626
+    }
627
+
628
+    // retourner la valeur pour #VALEUR
629
+    public function valeur() {
630
+        return $this->current();
631
+    }
632
+
633
+    /**
634
+     * Accepte-t-on l'entree courante lue ?
635
+     * On execute les filtres pour le savoir.
636
+     **/
637
+    public function accept(): bool {
638
+        if ($f = $this->func_filtre) {
639
+            return $f();
640
+        }
641
+
642
+        return true;
643
+    }
644
+
645
+    /**
646
+     * liberer la ressource
647
+     *
648
+     * @return bool
649
+     */
650
+    public function free() {
651
+        if (method_exists($this->iter, 'free')) {
652
+            $this->iter->free();
653
+        }
654
+        $this->pos = $this->total = 0;
655
+
656
+        return true;
657
+    }
658
+
659
+    /**
660
+     * Compter le nombre total de resultats
661
+     * pour #TOTAL_BOUCLE
662
+     *
663
+     * @return int
664
+     */
665
+    public function count() {
666
+        if (is_null($this->total)) {
667
+            if (
668
+                method_exists($this->iter, 'count')
669
+                and !$this->func_filtre
670
+            ) {
671
+                return $this->total = $this->iter->count();
672
+            } else {
673
+                // compter les lignes et rembobiner
674
+                $total = 0;
675
+                $pos = $this->pos; // sauver la position
676
+                $this->rewind();
677
+                while ($this->fetch() and $total < $this->max) {
678
+                    $total++;
679
+                }
680
+                $this->seek($pos);
681
+                $this->total = $total;
682
+            }
683
+        }
684
+
685
+        return $this->total;
686
+    }
687 687
 }
Please login to merge, or discard this patch.
ecrire/inc/minipres.php 1 patch
Indentation   +138 added lines, -138 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Minipres
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 include_spip('inc/headers');
@@ -46,61 +46,61 @@  discard block
 block discarded – undo
46 46
  */
47 47
 function install_debut_html($titre = 'AUTO', $onLoad = '', $all_inline = false) {
48 48
 
49
-	utiliser_langue_visiteur();
50
-
51
-	http_no_cache();
52
-
53
-	if ($titre == 'AUTO') {
54
-		$titre = _T('info_installation_systeme_publication');
55
-	}
56
-
57
-	# le charset est en utf-8, pour recuperer le nom comme il faut
58
-	# lors de l'installation
59
-	if (!headers_sent()) {
60
-		header('Content-Type: text/html; charset=utf-8');
61
-	}
62
-
63
-	$css = '';
64
-	$files = ['reset.css', 'clear.css', 'minipres.css'];
65
-	if ($all_inline) {
66
-		// inliner les CSS (optimisation de la page minipres qui passe en un seul hit a la demande)
67
-		foreach ($files as $name) {
68
-			$file = direction_css(find_in_theme($name));
69
-			if (function_exists('minifier')) {
70
-				$file = minifier($file);
71
-			} else {
72
-				$file = url_absolue_css($file); // precaution
73
-			}
74
-			lire_fichier($file, $c);
75
-			$css .= $c;
76
-		}
77
-		$css = "<style type='text/css'>" . $css . '</style>';
78
-	} else {
79
-		foreach ($files as $name) {
80
-			$file = direction_css(find_in_theme($name));
81
-			$css .= "<link rel='stylesheet' href='$file' type='text/css' />\n";
82
-		}
83
-	}
84
-
85
-	// au cas ou minipres() est appele avant spip_initialisation_suite()
86
-	if (!defined('_DOCTYPE_ECRIRE')) {
87
-		define('_DOCTYPE_ECRIRE', '');
88
-	}
89
-
90
-	return _DOCTYPE_ECRIRE .
91
-	html_lang_attributes() .
92
-	"<head>\n" .
93
-	'<title>' .
94
-	textebrut($titre) .
95
-	"</title>\n" .
96
-	"<meta name='viewport' content='width=device-width' />\n" .
97
-	$css .
98
-	'</head>
49
+    utiliser_langue_visiteur();
50
+
51
+    http_no_cache();
52
+
53
+    if ($titre == 'AUTO') {
54
+        $titre = _T('info_installation_systeme_publication');
55
+    }
56
+
57
+    # le charset est en utf-8, pour recuperer le nom comme il faut
58
+    # lors de l'installation
59
+    if (!headers_sent()) {
60
+        header('Content-Type: text/html; charset=utf-8');
61
+    }
62
+
63
+    $css = '';
64
+    $files = ['reset.css', 'clear.css', 'minipres.css'];
65
+    if ($all_inline) {
66
+        // inliner les CSS (optimisation de la page minipres qui passe en un seul hit a la demande)
67
+        foreach ($files as $name) {
68
+            $file = direction_css(find_in_theme($name));
69
+            if (function_exists('minifier')) {
70
+                $file = minifier($file);
71
+            } else {
72
+                $file = url_absolue_css($file); // precaution
73
+            }
74
+            lire_fichier($file, $c);
75
+            $css .= $c;
76
+        }
77
+        $css = "<style type='text/css'>" . $css . '</style>';
78
+    } else {
79
+        foreach ($files as $name) {
80
+            $file = direction_css(find_in_theme($name));
81
+            $css .= "<link rel='stylesheet' href='$file' type='text/css' />\n";
82
+        }
83
+    }
84
+
85
+    // au cas ou minipres() est appele avant spip_initialisation_suite()
86
+    if (!defined('_DOCTYPE_ECRIRE')) {
87
+        define('_DOCTYPE_ECRIRE', '');
88
+    }
89
+
90
+    return _DOCTYPE_ECRIRE .
91
+    html_lang_attributes() .
92
+    "<head>\n" .
93
+    '<title>' .
94
+    textebrut($titre) .
95
+    "</title>\n" .
96
+    "<meta name='viewport' content='width=device-width' />\n" .
97
+    $css .
98
+    '</head>
99 99
 <body' . $onLoad . " class='minipres'>
100 100
 	<div id='minipres'>
101 101
 	<h1>" .
102
-	$titre .
103
-	"</h1>
102
+    $titre .
103
+    "</h1>
104 104
 	<div>\n";
105 105
 }
106 106
 
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
  * @return string Code HTML
111 111
  */
112 112
 function install_fin_html() {
113
-	return "\n\t</div>\n\t</div>\n</body>\n</html>";
113
+    return "\n\t</div>\n\t</div>\n</body>\n</html>";
114 114
 }
115 115
 
116 116
 
@@ -148,88 +148,88 @@  discard block
 block discarded – undo
148 148
  */
149 149
 function minipres($titre = '', $corps = '', $options = []) {
150 150
 
151
-	// compat signature old
152
-	// minipres($titre='', $corps="", $onload='', $all_inline = false)
153
-	$args = func_get_args();
154
-	if (isset($args[2]) and is_string($args[2])) {
155
-		$options = ['onload' => $args[2]];
156
-	}
157
-	if (isset($args[3])) {
158
-		$options['all_inline'] = $args[3];
159
-	}
160
-
161
-	$options = array_merge([
162
-		'onload' => '',
163
-		'all_inline' => false,
164
-	], $options);
165
-
166
-	if (!defined('_AJAX')) {
167
-		define('_AJAX', false);
168
-	} // par securite
169
-	if (!$titre) {
170
-		if (!isset($options['status'])) {
171
-			$options['status'] = 403;
172
-		}
173
-		if (
174
-			!$titre = _request('action')
175
-			and !$titre = _request('exec')
176
-			and !$titre = _request('page')
177
-		) {
178
-			$titre = '?';
179
-		}
180
-
181
-		$titre = spip_htmlspecialchars($titre);
182
-
183
-		$titre = ($titre == 'install')
184
-			? _T('avis_espace_interdit')
185
-			: $titre . '&nbsp;: ' . _T('info_acces_interdit');
186
-
187
-		$statut = $GLOBALS['visiteur_session']['statut'] ?? '';
188
-		$nom = $GLOBALS['visiteur_session']['nom'] ?? '';
189
-
190
-		if ($statut != '0minirezo') {
191
-			$titre = _T('info_acces_interdit');
192
-		}
193
-
194
-		if ($statut and test_espace_prive()) {
195
-			$corps = bouton_action(_T('public:accueil_site'), generer_url_ecrire('accueil'));
196
-		}
197
-		elseif (!empty($_COOKIE['spip_admin'])) {
198
-			$corps = bouton_action(_T('public:lien_connecter'), generer_url_public('login'));
199
-		}
200
-		else {
201
-			$corps = bouton_action(_T('public:accueil_site'), $GLOBALS['meta']['adresse_site']);
202
-		}
203
-		$corps = "<div class='boutons'>$corps</div>";
204
-		spip_log($nom . " $titre " . $_SERVER['REQUEST_URI']);
205
-	}
206
-
207
-	if (!_AJAX) {
208
-		if (isset($options['status'])) {
209
-			http_response_code($options['status']);
210
-		}
211
-
212
-		$html = install_debut_html($titre, $options['onload'], $options['all_inline'])
213
-				. $corps
214
-				. install_fin_html();
215
-
216
-		if (
217
-			$GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
218
-			and empty($options['all_inline'])
219
-		) {
220
-			define('_SET_HTML_BASE', true);
221
-			include_spip('public/assembler');
222
-			$GLOBALS['html'] = true;
223
-			page_base_href($html);
224
-		}
225
-		return $html;
226
-	} else {
227
-		include_spip('inc/headers');
228
-		include_spip('inc/actions');
229
-		$url = self('&', true);
230
-		foreach ($_POST as $v => $c) {
231
-			$url = parametre_url($url, $v, $c, '&');
232
-		}
233
-		ajax_retour('<div>' . $titre . redirige_formulaire($url) . '</div>', false);
234
-	}
151
+    // compat signature old
152
+    // minipres($titre='', $corps="", $onload='', $all_inline = false)
153
+    $args = func_get_args();
154
+    if (isset($args[2]) and is_string($args[2])) {
155
+        $options = ['onload' => $args[2]];
156
+    }
157
+    if (isset($args[3])) {
158
+        $options['all_inline'] = $args[3];
159
+    }
160
+
161
+    $options = array_merge([
162
+        'onload' => '',
163
+        'all_inline' => false,
164
+    ], $options);
165
+
166
+    if (!defined('_AJAX')) {
167
+        define('_AJAX', false);
168
+    } // par securite
169
+    if (!$titre) {
170
+        if (!isset($options['status'])) {
171
+            $options['status'] = 403;
172
+        }
173
+        if (
174
+            !$titre = _request('action')
175
+            and !$titre = _request('exec')
176
+            and !$titre = _request('page')
177
+        ) {
178
+            $titre = '?';
179
+        }
180
+
181
+        $titre = spip_htmlspecialchars($titre);
182
+
183
+        $titre = ($titre == 'install')
184
+            ? _T('avis_espace_interdit')
185
+            : $titre . '&nbsp;: ' . _T('info_acces_interdit');
186
+
187
+        $statut = $GLOBALS['visiteur_session']['statut'] ?? '';
188
+        $nom = $GLOBALS['visiteur_session']['nom'] ?? '';
189
+
190
+        if ($statut != '0minirezo') {
191
+            $titre = _T('info_acces_interdit');
192
+        }
193
+
194
+        if ($statut and test_espace_prive()) {
195
+            $corps = bouton_action(_T('public:accueil_site'), generer_url_ecrire('accueil'));
196
+        }
197
+        elseif (!empty($_COOKIE['spip_admin'])) {
198
+            $corps = bouton_action(_T('public:lien_connecter'), generer_url_public('login'));
199
+        }
200
+        else {
201
+            $corps = bouton_action(_T('public:accueil_site'), $GLOBALS['meta']['adresse_site']);
202
+        }
203
+        $corps = "<div class='boutons'>$corps</div>";
204
+        spip_log($nom . " $titre " . $_SERVER['REQUEST_URI']);
205
+    }
206
+
207
+    if (!_AJAX) {
208
+        if (isset($options['status'])) {
209
+            http_response_code($options['status']);
210
+        }
211
+
212
+        $html = install_debut_html($titre, $options['onload'], $options['all_inline'])
213
+                . $corps
214
+                . install_fin_html();
215
+
216
+        if (
217
+            $GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
218
+            and empty($options['all_inline'])
219
+        ) {
220
+            define('_SET_HTML_BASE', true);
221
+            include_spip('public/assembler');
222
+            $GLOBALS['html'] = true;
223
+            page_base_href($html);
224
+        }
225
+        return $html;
226
+    } else {
227
+        include_spip('inc/headers');
228
+        include_spip('inc/actions');
229
+        $url = self('&', true);
230
+        foreach ($_POST as $v => $c) {
231
+            $url = parametre_url($url, $v, $c, '&');
232
+        }
233
+        ajax_retour('<div>' . $titre . redirige_formulaire($url) . '</div>', false);
234
+    }
235 235
 }
Please login to merge, or discard this patch.
ecrire/inc/documents.php 1 patch
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
  */
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 /**
@@ -30,12 +30,12 @@  discard block
 block discarded – undo
30 30
  * @return string
31 31
  */
32 32
 function set_spip_doc(?string $fichier): string {
33
-	if ($fichier and strpos($fichier, (string) _DIR_IMG) === 0) {
34
-		return substr($fichier, strlen(_DIR_IMG));
35
-	} else {
36
-		// ex: fichier distant
37
-		return $fichier ?? '';
38
-	}
33
+    if ($fichier and strpos($fichier, (string) _DIR_IMG) === 0) {
34
+        return substr($fichier, strlen(_DIR_IMG));
35
+    } else {
36
+        // ex: fichier distant
37
+        return $fichier ?? '';
38
+    }
39 39
 }
40 40
 
41 41
 /**
@@ -47,26 +47,26 @@  discard block
 block discarded – undo
47 47
  * @return bool|string
48 48
  */
49 49
 function get_spip_doc(?string $fichier) {
50
-	if ($fichier === null) {
51
-		return false;
52
-	}
53
-
54
-	// fichier distant
55
-	if (tester_url_absolue($fichier)) {
56
-		return $fichier;
57
-	}
58
-
59
-	// gestion d'erreurs, fichier=''
60
-	if (!strlen($fichier)) {
61
-		return false;
62
-	}
63
-
64
-	if (strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) !== 0) {
65
-		$fichier = _DIR_IMG . $fichier;
66
-	}
67
-
68
-	// fichier normal
69
-	return $fichier;
50
+    if ($fichier === null) {
51
+        return false;
52
+    }
53
+
54
+    // fichier distant
55
+    if (tester_url_absolue($fichier)) {
56
+        return $fichier;
57
+    }
58
+
59
+    // gestion d'erreurs, fichier=''
60
+    if (!strlen($fichier)) {
61
+        return false;
62
+    }
63
+
64
+    if (strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) !== 0) {
65
+        $fichier = _DIR_IMG . $fichier;
66
+    }
67
+
68
+    // fichier normal
69
+    return $fichier;
70 70
 }
71 71
 
72 72
 /**
@@ -80,26 +80,26 @@  discard block
 block discarded – undo
80 80
  * @return string
81 81
  */
82 82
 function creer_repertoire_documents($ext) {
83
-	$rep = sous_repertoire(_DIR_IMG, $ext);
84
-
85
-	if (!$ext or !$rep) {
86
-		spip_log("creer_repertoire_documents '$rep' interdit");
87
-		exit;
88
-	}
89
-
90
-	// Cette variable de configuration peut etre posee par un plugin
91
-	// par exemple acces_restreint
92
-	// sauf pour logo/ utilise pour stocker les logoon et logooff
93
-	if (
94
-		isset($GLOBALS['meta']['creer_htaccess'])
95
-		and $GLOBALS['meta']['creer_htaccess'] == 'oui'
96
-		and $ext !== 'logo'
97
-	) {
98
-		include_spip('inc/acces');
99
-		verifier_htaccess($rep);
100
-	}
101
-
102
-	return $rep;
83
+    $rep = sous_repertoire(_DIR_IMG, $ext);
84
+
85
+    if (!$ext or !$rep) {
86
+        spip_log("creer_repertoire_documents '$rep' interdit");
87
+        exit;
88
+    }
89
+
90
+    // Cette variable de configuration peut etre posee par un plugin
91
+    // par exemple acces_restreint
92
+    // sauf pour logo/ utilise pour stocker les logoon et logooff
93
+    if (
94
+        isset($GLOBALS['meta']['creer_htaccess'])
95
+        and $GLOBALS['meta']['creer_htaccess'] == 'oui'
96
+        and $ext !== 'logo'
97
+    ) {
98
+        include_spip('inc/acces');
99
+        verifier_htaccess($rep);
100
+    }
101
+
102
+    return $rep;
103 103
 }
104 104
 
105 105
 /**
@@ -108,22 +108,22 @@  discard block
 block discarded – undo
108 108
  * @param string $nom
109 109
  */
110 110
 function effacer_repertoire_temporaire($nom) {
111
-	if ($d = opendir($nom)) {
112
-		while (($f = readdir($d)) !== false) {
113
-			if (is_file("$nom/$f")) {
114
-				spip_unlink("$nom/$f");
115
-			} else {
116
-				if (
117
-					$f <> '.' and $f <> '..'
118
-					and is_dir("$nom/$f")
119
-				) {
120
-					effacer_repertoire_temporaire("$nom/$f");
121
-				}
122
-			}
123
-		}
124
-	}
125
-	closedir($d);
126
-	@rmdir($nom);
111
+    if ($d = opendir($nom)) {
112
+        while (($f = readdir($d)) !== false) {
113
+            if (is_file("$nom/$f")) {
114
+                spip_unlink("$nom/$f");
115
+            } else {
116
+                if (
117
+                    $f <> '.' and $f <> '..'
118
+                    and is_dir("$nom/$f")
119
+                ) {
120
+                    effacer_repertoire_temporaire("$nom/$f");
121
+                }
122
+            }
123
+        }
124
+    }
125
+    closedir($d);
126
+    @rmdir($nom);
127 127
 }
128 128
 
129 129
 //
@@ -140,45 +140,45 @@  discard block
 block discarded – undo
140 140
  */
141 141
 function copier_document($ext, $orig, $source, $subdir = null) {
142 142
 
143
-	$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
144
-	$dir = creer_repertoire_documents($subdir ?: $ext);
145
-
146
-	$dest = preg_replace('/<[^>]*>/', '', basename($orig));
147
-	$dest = preg_replace('/\.([^.]+)$/', '', $dest);
148
-	$dest = translitteration($dest);
149
-	$dest = preg_replace('/[^.=\w-]+/', '_', $dest);
150
-
151
-	// ne pas accepter de noms de la forme -r90.jpg qui sont reserves
152
-	// pour les images transformees par rotation (action/documenter)
153
-	$dest = preg_replace(',-r(90|180|270)$,', '', $dest);
154
-
155
-	while (preg_match(',\.(\w+)$,', $dest, $m)) {
156
-		if (
157
-			!function_exists('verifier_upload_autorise')
158
-			or !$r = verifier_upload_autorise($dest)
159
-			or $r['autozip']
160
-		) {
161
-			$dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
162
-			break;
163
-		}
164
-		else {
165
-			$dest = substr($dest, 0, -strlen($m[0]));
166
-			$ext = $m[1] . '.' . $ext;
167
-		}
168
-	}
169
-
170
-	// Si le document "source" est deja au bon endroit, ne rien faire
171
-	if ($source == ($dir . $dest . '.' . $ext)) {
172
-		return $source;
173
-	}
174
-
175
-	// sinon tourner jusqu'a trouver un numero correct
176
-	$n = 0;
177
-	while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
178
-		;
179
-	}
180
-
181
-	return deplacer_fichier_upload($source, $newFile);
143
+    $orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
144
+    $dir = creer_repertoire_documents($subdir ?: $ext);
145
+
146
+    $dest = preg_replace('/<[^>]*>/', '', basename($orig));
147
+    $dest = preg_replace('/\.([^.]+)$/', '', $dest);
148
+    $dest = translitteration($dest);
149
+    $dest = preg_replace('/[^.=\w-]+/', '_', $dest);
150
+
151
+    // ne pas accepter de noms de la forme -r90.jpg qui sont reserves
152
+    // pour les images transformees par rotation (action/documenter)
153
+    $dest = preg_replace(',-r(90|180|270)$,', '', $dest);
154
+
155
+    while (preg_match(',\.(\w+)$,', $dest, $m)) {
156
+        if (
157
+            !function_exists('verifier_upload_autorise')
158
+            or !$r = verifier_upload_autorise($dest)
159
+            or $r['autozip']
160
+        ) {
161
+            $dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
162
+            break;
163
+        }
164
+        else {
165
+            $dest = substr($dest, 0, -strlen($m[0]));
166
+            $ext = $m[1] . '.' . $ext;
167
+        }
168
+    }
169
+
170
+    // Si le document "source" est deja au bon endroit, ne rien faire
171
+    if ($source == ($dir . $dest . '.' . $ext)) {
172
+        return $source;
173
+    }
174
+
175
+    // sinon tourner jusqu'a trouver un numero correct
176
+    $n = 0;
177
+    while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
178
+        ;
179
+    }
180
+
181
+    return deplacer_fichier_upload($source, $newFile);
182 182
 }
183 183
 
184 184
 /**
@@ -193,28 +193,28 @@  discard block
 block discarded – undo
193 193
  * @return bool|string
194 194
  */
195 195
 function determine_upload($type = '') {
196
-	if (!function_exists('autoriser')) {
197
-		include_spip('inc/autoriser');
198
-	}
199
-
200
-	if (
201
-		!autoriser('chargerftp')
202
-		or $type == 'logos'
203
-	) { # on ne le permet pas pour les logos
204
-	return false;
205
-	}
206
-
207
-	$repertoire = _DIR_TRANSFERT;
208
-	if (!@is_dir($repertoire)) {
209
-		$repertoire = str_replace(_DIR_TMP, '', $repertoire);
210
-		$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
211
-	}
212
-
213
-	if (!$GLOBALS['visiteur_session']['restreint']) {
214
-		return $repertoire;
215
-	} else {
216
-		return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
217
-	}
196
+    if (!function_exists('autoriser')) {
197
+        include_spip('inc/autoriser');
198
+    }
199
+
200
+    if (
201
+        !autoriser('chargerftp')
202
+        or $type == 'logos'
203
+    ) { # on ne le permet pas pour les logos
204
+    return false;
205
+    }
206
+
207
+    $repertoire = _DIR_TRANSFERT;
208
+    if (!@is_dir($repertoire)) {
209
+        $repertoire = str_replace(_DIR_TMP, '', $repertoire);
210
+        $repertoire = sous_repertoire(_DIR_TMP, $repertoire);
211
+    }
212
+
213
+    if (!$GLOBALS['visiteur_session']['restreint']) {
214
+        return $repertoire;
215
+    } else {
216
+        return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
217
+    }
218 218
 }
219 219
 
220 220
 /**
@@ -233,35 +233,35 @@  discard block
 block discarded – undo
233 233
  * @return bool|mixed|string
234 234
  */
235 235
 function deplacer_fichier_upload($source, $dest, $move = false) {
236
-	// Securite
237
-	if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
238
-		$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
239
-	} else {
240
-		$dest = preg_replace(',\.\.+,', '.', $dest);
241
-	}
242
-
243
-	if ($move) {
244
-		$ok = @rename($source, $dest);
245
-	} else {
246
-		$ok = @copy($source, $dest);
247
-	}
248
-	if (!$ok) {
249
-		$ok = @move_uploaded_file($source, $dest);
250
-	}
251
-	if ($ok) {
252
-		@chmod($dest, _SPIP_CHMOD & ~0111);
253
-	} else {
254
-		$f = @fopen($dest, 'w');
255
-		if ($f) {
256
-			fclose($f);
257
-		} else {
258
-			include_spip('inc/flock');
259
-			raler_fichier($dest);
260
-		}
261
-		spip_unlink($dest);
262
-	}
263
-
264
-	return $ok ? $dest : false;
236
+    // Securite
237
+    if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
238
+        $dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
239
+    } else {
240
+        $dest = preg_replace(',\.\.+,', '.', $dest);
241
+    }
242
+
243
+    if ($move) {
244
+        $ok = @rename($source, $dest);
245
+    } else {
246
+        $ok = @copy($source, $dest);
247
+    }
248
+    if (!$ok) {
249
+        $ok = @move_uploaded_file($source, $dest);
250
+    }
251
+    if ($ok) {
252
+        @chmod($dest, _SPIP_CHMOD & ~0111);
253
+    } else {
254
+        $f = @fopen($dest, 'w');
255
+        if ($f) {
256
+            fclose($f);
257
+        } else {
258
+            include_spip('inc/flock');
259
+            raler_fichier($dest);
260
+        }
261
+        spip_unlink($dest);
262
+    }
263
+
264
+    return $ok ? $dest : false;
265 265
 }
266 266
 
267 267
 
@@ -285,60 +285,60 @@  discard block
 block discarded – undo
285 285
  */
286 286
 function check_upload_error($error, $msg = '', $return = false) {
287 287
 
288
-	if (!$error) {
289
-		return false;
290
-	}
291
-
292
-	spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
293
-
294
-	switch ($error) {
295
-		case 4: /* UPLOAD_ERR_NO_FILE */
296
-			return true;
297
-
298
-		# on peut affiner les differents messages d'erreur
299
-		case 1: /* UPLOAD_ERR_INI_SIZE */
300
-			$msg = _T(
301
-				'upload_limit',
302
-				['max' => ini_get('upload_max_filesize')]
303
-			);
304
-			break;
305
-		case 2: /* UPLOAD_ERR_FORM_SIZE */
306
-			$msg = _T(
307
-				'upload_limit',
308
-				['max' => ini_get('upload_max_filesize')]
309
-			);
310
-			break;
311
-		case 3: /* UPLOAD_ERR_PARTIAL  */
312
-			$msg = _T(
313
-				'upload_limit',
314
-				['max' => ini_get('upload_max_filesize')]
315
-			);
316
-			break;
317
-
318
-		default: /* autre */
319
-			if (!$msg) {
320
-				$msg = _T('pass_erreur') . ' ' . $error
321
-					. '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
322
-			}
323
-			break;
324
-	}
325
-
326
-	spip_log("erreur upload $error");
327
-	if ($return) {
328
-		return $msg;
329
-	}
330
-
331
-	if (_request('iframe') == 'iframe') {
332
-		echo "<div class='upload_answer upload_error'>$msg</div>";
333
-		exit;
334
-	}
335
-
336
-	include_spip('inc/minipres');
337
-	echo minipres(
338
-		$msg,
339
-		"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
340
-	);
341
-	exit;
288
+    if (!$error) {
289
+        return false;
290
+    }
291
+
292
+    spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
293
+
294
+    switch ($error) {
295
+        case 4: /* UPLOAD_ERR_NO_FILE */
296
+            return true;
297
+
298
+        # on peut affiner les differents messages d'erreur
299
+        case 1: /* UPLOAD_ERR_INI_SIZE */
300
+            $msg = _T(
301
+                'upload_limit',
302
+                ['max' => ini_get('upload_max_filesize')]
303
+            );
304
+            break;
305
+        case 2: /* UPLOAD_ERR_FORM_SIZE */
306
+            $msg = _T(
307
+                'upload_limit',
308
+                ['max' => ini_get('upload_max_filesize')]
309
+            );
310
+            break;
311
+        case 3: /* UPLOAD_ERR_PARTIAL  */
312
+            $msg = _T(
313
+                'upload_limit',
314
+                ['max' => ini_get('upload_max_filesize')]
315
+            );
316
+            break;
317
+
318
+        default: /* autre */
319
+            if (!$msg) {
320
+                $msg = _T('pass_erreur') . ' ' . $error
321
+                    . '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
322
+            }
323
+            break;
324
+    }
325
+
326
+    spip_log("erreur upload $error");
327
+    if ($return) {
328
+        return $msg;
329
+    }
330
+
331
+    if (_request('iframe') == 'iframe') {
332
+        echo "<div class='upload_answer upload_error'>$msg</div>";
333
+        exit;
334
+    }
335
+
336
+    include_spip('inc/minipres');
337
+    echo minipres(
338
+        $msg,
339
+        "<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
340
+    );
341
+    exit;
342 342
 }
343 343
 
344 344
 /**
@@ -355,24 +355,24 @@  discard block
 block discarded – undo
355 355
  * @return string
356 356
  */
357 357
 function corriger_extension($ext) {
358
-	$ext = preg_replace(',[^a-z0-9],i', '', $ext);
359
-	switch ($ext) {
360
-		case 'htm':
361
-			$ext = 'html';
362
-			break;
363
-		case 'jpeg':
364
-			$ext = 'jpg';
365
-			break;
366
-		case 'tiff':
367
-			$ext = 'tif';
368
-			break;
369
-		case 'aif':
370
-			$ext = 'aiff';
371
-			break;
372
-		case 'mpeg':
373
-			$ext = 'mpg';
374
-			break;
375
-	}
376
-
377
-	return $ext;
358
+    $ext = preg_replace(',[^a-z0-9],i', '', $ext);
359
+    switch ($ext) {
360
+        case 'htm':
361
+            $ext = 'html';
362
+            break;
363
+        case 'jpeg':
364
+            $ext = 'jpg';
365
+            break;
366
+        case 'tiff':
367
+            $ext = 'tif';
368
+            break;
369
+        case 'aif':
370
+            $ext = 'aiff';
371
+            break;
372
+        case 'mpeg':
373
+            $ext = 'mpg';
374
+            break;
375
+    }
376
+
377
+    return $ext;
378 378
 }
Please login to merge, or discard this patch.