Completed
Push — master ( b872a5...71c68d )
by cam
01:07
created
ecrire/maj/2021.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -19,15 +19,15 @@
 block discarded – undo
19 19
  * @package SPIP\Core\SQL\Upgrade
20 20
  **/
21 21
 if (!defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 $GLOBALS['maj'][2021_02_18_00] = [
26
-	['sql_alter', "TABLE spip_auteurs CHANGE imessage imessage VARCHAR(3) DEFAULT '' NOT NULL" ],
27
-	['sql_updateq', 'spip_auteurs', ['imessage' => 'oui'], "imessage != 'non' OR imessage IS NULL" ],
26
+    ['sql_alter', "TABLE spip_auteurs CHANGE imessage imessage VARCHAR(3) DEFAULT '' NOT NULL" ],
27
+    ['sql_updateq', 'spip_auteurs', ['imessage' => 'oui'], "imessage != 'non' OR imessage IS NULL" ],
28 28
 ];
29 29
 
30 30
 $GLOBALS['maj'][2022_02_23_02] = [
31
-	['sql_alter', "TABLE spip_auteurs ADD backup_cles mediumtext DEFAULT '' NOT NULL" ],
32
-	['sql_delete', 'spip_meta', "nom='secret_du_site'" ],
31
+    ['sql_alter', "TABLE spip_auteurs ADD backup_cles mediumtext DEFAULT '' NOT NULL" ],
32
+    ['sql_delete', 'spip_meta', "nom='secret_du_site'" ],
33 33
 ];
Please login to merge, or discard this patch.
ecrire/public/interfaces.php 1 patch
Indentation   +922 added lines, -922 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 
@@ -34,53 +34,53 @@  discard block
 block discarded – undo
34 34
  * @package SPIP\Core\Compilateur\AST
35 35
  */
36 36
 class Contexte {
37
-	/**
38
-	 * Description du squelette
39
-	 *
40
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
41
-	 *
42
-	 * Peut contenir les index :
43
-	 *
44
-	 * - nom : Nom du fichier de cache
45
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
46
-	 * - sourcefile : Chemin du squelette
47
-	 * - squelette : Code du squelette
48
-	 * - id_mere : Identifiant de la boucle parente
49
-	 * - documents : Pour embed et img dans les textes
50
-	 * - session : Pour un cache sessionné par auteur
51
-	 * - niv : Niveau de tabulation
52
-	 *
53
-	 * @var array
54
-	 */
55
-	public $descr = [];
56
-
57
-	/**
58
-	 * Identifiant de la boucle
59
-	 *
60
-	 * @var string
61
-	 */
62
-	public $id_boucle = '';
63
-
64
-	/**
65
-	 * Numéro de ligne dans le code source du squelette
66
-	 *
67
-	 * @var int
68
-	 */
69
-	public $ligne = 0;
70
-
71
-	/**
72
-	 * Langue d'exécution
73
-	 *
74
-	 * @var string
75
-	 */
76
-	public $lang = '';
77
-
78
-	/**
79
-	 * Résultat de la compilation: toujours une expression PHP
80
-	 *
81
-	 * @var string
82
-	 */
83
-	public $code = '';
37
+    /**
38
+     * Description du squelette
39
+     *
40
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
41
+     *
42
+     * Peut contenir les index :
43
+     *
44
+     * - nom : Nom du fichier de cache
45
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
46
+     * - sourcefile : Chemin du squelette
47
+     * - squelette : Code du squelette
48
+     * - id_mere : Identifiant de la boucle parente
49
+     * - documents : Pour embed et img dans les textes
50
+     * - session : Pour un cache sessionné par auteur
51
+     * - niv : Niveau de tabulation
52
+     *
53
+     * @var array
54
+     */
55
+    public $descr = [];
56
+
57
+    /**
58
+     * Identifiant de la boucle
59
+     *
60
+     * @var string
61
+     */
62
+    public $id_boucle = '';
63
+
64
+    /**
65
+     * Numéro de ligne dans le code source du squelette
66
+     *
67
+     * @var int
68
+     */
69
+    public $ligne = 0;
70
+
71
+    /**
72
+     * Langue d'exécution
73
+     *
74
+     * @var string
75
+     */
76
+    public $lang = '';
77
+
78
+    /**
79
+     * Résultat de la compilation: toujours une expression PHP
80
+     *
81
+     * @var string
82
+     */
83
+    public $code = '';
84 84
 }
85 85
 
86 86
 
@@ -90,44 +90,44 @@  discard block
 block discarded – undo
90 90
  * @package SPIP\Core\Compilateur\AST
91 91
  **/
92 92
 class Texte {
93
-	/**
94
-	 * Type de noeud
95
-	 *
96
-	 * @var string
97
-	 */
98
-	public $type = 'texte';
99
-
100
-	/**
101
-	 * Le texte
102
-	 *
103
-	 * @var string
104
-	 */
105
-	public $texte;
106
-
107
-	/**
108
-	 * Contenu avant le texte.
109
-	 *
110
-	 * Vide ou apostrophe simple ou double si le texte en était entouré
111
-	 *
112
-	 * @var string|array
113
-	 */
114
-	public $avant = '';
115
-
116
-	/**
117
-	 * Contenu après le texte.
118
-	 *
119
-	 * Vide ou apostrophe simple ou double si le texte en était entouré
120
-	 *
121
-	 * @var string|array
122
-	 */
123
-	public $apres = '';
124
-
125
-	/**
126
-	 * Numéro de ligne dans le code source du squelette
127
-	 *
128
-	 * @var int
129
-	 */
130
-	public $ligne = 0;
93
+    /**
94
+     * Type de noeud
95
+     *
96
+     * @var string
97
+     */
98
+    public $type = 'texte';
99
+
100
+    /**
101
+     * Le texte
102
+     *
103
+     * @var string
104
+     */
105
+    public $texte;
106
+
107
+    /**
108
+     * Contenu avant le texte.
109
+     *
110
+     * Vide ou apostrophe simple ou double si le texte en était entouré
111
+     *
112
+     * @var string|array
113
+     */
114
+    public $avant = '';
115
+
116
+    /**
117
+     * Contenu après le texte.
118
+     *
119
+     * Vide ou apostrophe simple ou double si le texte en était entouré
120
+     *
121
+     * @var string|array
122
+     */
123
+    public $apres = '';
124
+
125
+    /**
126
+     * Numéro de ligne dans le code source du squelette
127
+     *
128
+     * @var int
129
+     */
130
+    public $ligne = 0;
131 131
 }
132 132
 
133 133
 /**
@@ -136,50 +136,50 @@  discard block
 block discarded – undo
136 136
  * @package SPIP\Core\Compilateur\AST
137 137
  **/
138 138
 class Inclure {
139
-	/**
140
-	 * Type de noeud
141
-	 *
142
-	 * @var string
143
-	 */
144
-	public $type = 'include';
145
-
146
-	/**
147
-	 * Nom d'un fichier inclu
148
-	 *
149
-	 * - Objet Texte si inclusion d'un autre squelette
150
-	 * - chaîne si inclusion d'un fichier PHP directement
151
-	 *
152
-	 * @var string|Texte
153
-	 */
154
-	public $texte;
155
-
156
-	/**
157
-	 * Inutilisé, propriété générique de l'AST
158
-	 *
159
-	 * @var string|array
160
-	 */
161
-	public $avant = '';
162
-
163
-	/**
164
-	 * Inutilisé, propriété générique de l'AST
165
-	 *
166
-	 * @var string|array
167
-	 */
168
-	public $apres = '';
169
-
170
-	/**
171
-	 * Numéro de ligne dans le code source du squelette
172
-	 *
173
-	 * @var int
174
-	 */
175
-	public $ligne = 0;
176
-
177
-	/**
178
-	 * Valeurs des paramètres
179
-	 *
180
-	 * @var array
181
-	 */
182
-	public $param = [];
139
+    /**
140
+     * Type de noeud
141
+     *
142
+     * @var string
143
+     */
144
+    public $type = 'include';
145
+
146
+    /**
147
+     * Nom d'un fichier inclu
148
+     *
149
+     * - Objet Texte si inclusion d'un autre squelette
150
+     * - chaîne si inclusion d'un fichier PHP directement
151
+     *
152
+     * @var string|Texte
153
+     */
154
+    public $texte;
155
+
156
+    /**
157
+     * Inutilisé, propriété générique de l'AST
158
+     *
159
+     * @var string|array
160
+     */
161
+    public $avant = '';
162
+
163
+    /**
164
+     * Inutilisé, propriété générique de l'AST
165
+     *
166
+     * @var string|array
167
+     */
168
+    public $apres = '';
169
+
170
+    /**
171
+     * Numéro de ligne dans le code source du squelette
172
+     *
173
+     * @var int
174
+     */
175
+    public $ligne = 0;
176
+
177
+    /**
178
+     * Valeurs des paramètres
179
+     *
180
+     * @var array
181
+     */
182
+    public $param = [];
183 183
 }
184 184
 
185 185
 
@@ -189,392 +189,392 @@  discard block
 block discarded – undo
189 189
  * @package SPIP\Core\Compilateur\AST
190 190
  **/
191 191
 class Boucle {
192
-	/**
193
-	 * Type de noeud
194
-	 *
195
-	 * @var string
196
-	 */
197
-	public $type = 'boucle';
198
-
199
-	/**
200
-	 * Identifiant de la boucle
201
-	 *
202
-	 * @var string
203
-	 */
204
-	public $id_boucle;
205
-
206
-	/**
207
-	 * Identifiant de la boucle parente
208
-	 *
209
-	 * @var string
210
-	 */
211
-	public $id_parent = '';
212
-
213
-	/**
214
-	 * Partie avant toujours affichee
215
-	 *
216
-	 * @var string|array
217
-	 */
218
-	public $preaff = '';
219
-
220
-	/**
221
-	 * Partie optionnelle avant
222
-	 *
223
-	 * @var string|array
224
-	 */
225
-	public $avant = '';
226
-
227
-	/**
228
-	 * Pour chaque élément
229
-	 *
230
-	 * @var string|array
231
-	 */
232
-	public $milieu = '';
233
-
234
-	/**
235
-	 * Partie optionnelle après
236
-	 *
237
-	 * @var string|array
238
-	 */
239
-	public $apres = '';
240
-
241
-	/**
242
-	 * Partie alternative, si pas de résultat dans la boucle
243
-	 *
244
-	 * @var string|array
245
-	 */
246
-	public $altern = '';
247
-
248
-	/**
249
-	 * Partie apres toujours affichee
250
-	 *
251
-	 * @var string|array
252
-	 */
253
-	public $postaff = '';
254
-
255
-
256
-	/**
257
-	 * La boucle doit-elle sélectionner la langue ?
258
-	 *
259
-	 * @var string|null
260
-	 */
261
-	public $lang_select;
262
-
263
-	/**
264
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
265
-	 *
266
-	 * @var string|null
267
-	 */
268
-	public $type_requete;
269
-
270
-	/**
271
-	 * La table est elle optionnelle ?
272
-	 *
273
-	 * Si oui, aucune erreur ne sera générée si la table demandée n'est pas présente
274
-	 *
275
-	 * @var bool
276
-	 */
277
-	public $table_optionnelle = false;
278
-
279
-	/**
280
-	 * Nom du fichier de connexion
281
-	 *
282
-	 * @var string
283
-	 */
284
-	public $sql_serveur = '';
285
-
286
-	/**
287
-	 * Paramètres de la boucle
288
-	 *
289
-	 * Description des paramètres passés à la boucle, qui servent ensuite
290
-	 * au calcul des critères
291
-	 *
292
-	 * @var array
293
-	 */
294
-	public $param = [];
295
-
296
-	/**
297
-	 * Critères de la boucle
298
-	 *
299
-	 * @var Critere[]
300
-	 */
301
-	public $criteres = [];
302
-
303
-	/**
304
-	 * Textes insérés entre 2 éléments de boucle (critère inter)
305
-	 *
306
-	 * @var string[]
307
-	 */
308
-	public $separateur = [];
309
-
310
-	/**
311
-	 * Liste des jointures possibles avec cette table
312
-	 *
313
-	 * Les jointures par défaut de la table sont complétées en priorité
314
-	 * des jointures déclarées explicitement sur la boucle
315
-	 *
316
-	 * @see base_trouver_table_dist()
317
-	 * @var array
318
-	 */
319
-	public $jointures = [];
320
-
321
-	/**
322
-	 * Jointures explicites avec cette table
323
-	 *
324
-	 * Ces jointures sont utilisées en priorité par rapport aux jointures
325
-	 * normales possibles pour retrouver les colonnes demandées extérieures
326
-	 * à la boucle.
327
-	 *
328
-	 * @var string|bool
329
-	 */
330
-	public $jointures_explicites = false;
331
-
332
-	/**
333
-	 * Nom de la variable PHP stockant le noms de doublons utilisés "$doublons_index"
334
-	 *
335
-	 * @var string|null
336
-	 */
337
-	public $doublons;
338
-
339
-	/**
340
-	 * Code PHP ajouté au début de chaque itération de boucle.
341
-	 *
342
-	 * Utilisé entre autre par les critères {pagination}, {n-a,b}, {a/b}...
343
-	 *
344
-	 * @var string
345
-	 */
346
-	public $partie = '';
347
-
348
-	/**
349
-	 * Nombre de divisions de la boucle, d'éléments à afficher,
350
-	 * ou de soustractions d'éléments à faire
351
-	 *
352
-	 * Dans les critères limitant le nombre d'éléments affichés
353
-	 * {a,b}, {a,n-b}, {a/b}, {pagination b}, b est affecté à total_parties.
354
-	 *
355
-	 * @var string
356
-	 */
357
-	public $total_parties = '';
358
-
359
-	/**
360
-	 * Code PHP ajouté avant l'itération de boucle.
361
-	 *
362
-	 * Utilisé entre autre par les critères {pagination}, {a,b}, {a/b}
363
-	 * pour initialiser les variables de début et de fin d'itération.
364
-	 *
365
-	 * @var string
366
-	 */
367
-	public $mode_partie = '';
368
-
369
-	/**
370
-	 * Identifiant d'une boucle qui appelle celle-ci de manière récursive
371
-	 *
372
-	 * Si une boucle est appelée de manière récursive quelque part par
373
-	 * une autre boucle comme <BOUCLE_rec(boucle_identifiant) />, cette
374
-	 * boucle (identifiant) reçoit dans cette propriété l'identifiant
375
-	 * de l'appelant (rec)
376
-	 *
377
-	 * @var string
378
-	 */
379
-	public $externe = '';
380
-
381
-	// champs pour la construction de la requete SQL
382
-
383
-	/**
384
-	 * Liste des champs à récupérer par la boucle
385
-	 *
386
-	 * Expression 'table.nom_champ' ou calculée 'nom_champ AS x'
387
-	 *
388
-	 * @var string[]
389
-	 */
390
-	public $select = [];
391
-
392
-	/**
393
-	 * Liste des alias / tables SQL utilisées dans la boucle
394
-	 *
395
-	 * L'index est un identifiant (xx dans spip_xx assez souvent) qui servira
396
-	 * d'alias au nom de la table ; la valeur est le nom de la table SQL désirée.
397
-	 *
398
-	 * L'index 0 peut définir le type de sources de données de l'itérateur DATA
399
-	 *
400
-	 * @var string[]
401
-	 */
402
-	public $from = [];
403
-
404
-	/**
405
-	 * Liste des alias / type de jointures utilisées dans la boucle
406
-	 *
407
-	 * L'index est le nom d'alias (comme pour la propriété $from), et la valeur
408
-	 * un type de jointure parmi 'INNER', 'LEFT', 'RIGHT', 'OUTER'.
409
-	 *
410
-	 * Lorsque le type n'est pas déclaré pour un alias, c'est 'INNER'
411
-	 * qui sera utilisé par défaut (créant donc un INNER JOIN).
412
-	 *
413
-	 * @var string[]
414
-	 */
415
-	public $from_type = [];
416
-
417
-	/**
418
-	 * Liste des conditions WHERE de la boucle
419
-	 *
420
-	 * Permet de restreindre les éléments retournés par une boucle
421
-	 * en fonctions des conditions transmises dans ce tableau.
422
-	 *
423
-	 * Ce tableau peut avoir plusieurs niveaux de profondeur.
424
-	 *
425
-	 * Les éléments du premier niveau sont reliés par des AND, donc
426
-	 * chaque élément ajouté directement au where par
427
-	 * $boucle->where[] = array(...) ou $boucle->where[] = "'expression'"
428
-	 * est une condition AND en plus.
429
-	 *
430
-	 * Par contre, lorsqu'on indique un tableau, il peut décrire des relations
431
-	 * internes différentes. Soit $expr un tableau d'expressions quelconques de 3 valeurs :
432
-	 * $expr = array(operateur, val1, val2)
433
-	 *
434
-	 * Ces 3 valeurs sont des expressions PHP. L'index 0 désigne l'opérateur
435
-	 * à réaliser tel que :
436
-	 *
437
-	 * - "'='" , "'>='", "'<'", "'IN'", "'REGEXP'", "'LIKE'", ... :
438
-	 *    val1 et val2 sont des champs et valeurs à utiliser dans la comparaison
439
-	 *    suivant cet ordre : "val1 operateur val2".
440
-	 *    Exemple : $boucle->where[] = array("'='", "'articles.statut'", "'\"publie\"'");
441
-	 * - "'AND'", "'OR'", "'NOT'" :
442
-	 *    dans ce cas val1 et val2 sont également des expressions
443
-	 *    de comparaison complètes, et peuvent être eux-même des tableaux comme $expr
444
-	 *    Exemples :
445
-	 *    $boucle->where[] = array("'OR'", $expr1, $expr2);
446
-	 *    $boucle->where[] = array("'NOT'", $expr); // val2 n'existe pas avec NOT
447
-	 *
448
-	 * D'autres noms sont possibles pour l'opérateur (le nombre de valeurs diffère) :
449
-	 * - "'SELF'", "'SUBSELECT'" : indiquent des sous requêtes
450
-	 * - "'?'" : indique une condition à faire évaluer (val1 ? val2 : val3)
451
-	 *
452
-	 * @var array
453
-	 */
454
-	public $where = [];
455
-
456
-	public $join = [];
457
-	public $having = [];
458
-	public $limit = '';
459
-	public $group = [];
460
-	public $order = [];
461
-	public $default_order = [];
462
-	public $date = 'date';
463
-	public $hash = '';
464
-	public $in = '';
465
-	public $sous_requete = false;
466
-
467
-	/**
468
-	 * Code PHP qui sera ajouté en tout début de la fonction de boucle
469
-	 *
470
-	 * Il sert à insérer le code calculant une hierarchie
471
-	 *
472
-	 * @var string
473
-	 */
474
-	public $hierarchie = '';
475
-
476
-	// champs pour la construction du corps PHP
477
-
478
-	/**
479
-	 * Description des sources de données de la boucle
480
-	 *
481
-	 * Description des données de la boucle issu de trouver_table
482
-	 * dans le cadre de l'itérateur SQL et contenant au moins l'index 'field'.
483
-	 *
484
-	 * @see base_trouver_table_dist()
485
-	 * @var array
486
-	 */
487
-	public $show = [];
488
-
489
-	/**
490
-	 * Nom de la table SQL principale de la boucle, sans son préfixe
491
-	 *
492
-	 * @var string
493
-	 */
494
-	public $id_table;
495
-
496
-	/**
497
-	 * Nom de la clé primaire de la table SQL principale de la boucle
498
-	 *
499
-	 * @var string
500
-	 */
501
-	public $primary;
502
-
503
-	/**
504
-	 * Code PHP compilé de la boucle
505
-	 *
506
-	 * @var string
507
-	 */
508
-	public $return;
509
-
510
-	public $numrows = false;
511
-	public $cptrows = false;
512
-
513
-	/**
514
-	 * Description du squelette
515
-	 *
516
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
517
-	 *
518
-	 * Peut contenir les index :
519
-	 *
520
-	 * - nom : Nom du fichier de cache
521
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
522
-	 * - sourcefile : Chemin du squelette
523
-	 * - squelette : Code du squelette
524
-	 * - id_mere : Identifiant de la boucle parente
525
-	 * - documents : Pour embed et img dans les textes
526
-	 * - session : Pour un cache sessionné par auteur
527
-	 * - niv : Niveau de tabulation
528
-	 *
529
-	 * @var array
530
-	 */
531
-	public $descr = [];
532
-
533
-	/**
534
-	 * Numéro de ligne dans le code source du squelette
535
-	 *
536
-	 * @var int
537
-	 */
538
-	public $ligne = 0;
539
-
540
-
541
-	/**
542
-	 * table pour stocker les modificateurs de boucle tels que tout, plat ...,
543
-	 * utilisable par les plugins egalement
544
-	 *
545
-	 * @var array<string, mixed>
546
-	 */
547
-	public $modificateur = [];
548
-
549
-	/**
550
-	 * Type d'itérateur utilisé pour cette boucle
551
-	 *
552
-	 * - 'SQL' dans le cadre d'une boucle sur une table SQL
553
-	 * - 'DATA' pour l'itérateur DATA, ...
554
-	 *
555
-	 * @var string
556
-	 */
557
-	public $iterateur = ''; // type d'iterateur
558
-
559
-	/**
560
-	 * @var array $debug Textes qui seront insérés dans l’entête de boucle du mode debug
561
-	 */
562
-	public $debug = [];
563
-
564
-	/**
565
-	 * Index de la boucle dont le champ présent dans cette boucle est originaire,
566
-	 * notamment si le champ a été trouve dans une boucle parente
567
-	 *
568
-	 * Tableau nom du champ => index de boucle
569
-	 *
570
-	 * @var array $index_champ
571
-	*/
572
-	public $index_champ = [];
573
-
574
-	// obsoletes, conserves provisoirement pour compatibilite
575
-	public $tout = false;
576
-	public $plat = false;
577
-	public $lien = false;
192
+    /**
193
+     * Type de noeud
194
+     *
195
+     * @var string
196
+     */
197
+    public $type = 'boucle';
198
+
199
+    /**
200
+     * Identifiant de la boucle
201
+     *
202
+     * @var string
203
+     */
204
+    public $id_boucle;
205
+
206
+    /**
207
+     * Identifiant de la boucle parente
208
+     *
209
+     * @var string
210
+     */
211
+    public $id_parent = '';
212
+
213
+    /**
214
+     * Partie avant toujours affichee
215
+     *
216
+     * @var string|array
217
+     */
218
+    public $preaff = '';
219
+
220
+    /**
221
+     * Partie optionnelle avant
222
+     *
223
+     * @var string|array
224
+     */
225
+    public $avant = '';
226
+
227
+    /**
228
+     * Pour chaque élément
229
+     *
230
+     * @var string|array
231
+     */
232
+    public $milieu = '';
233
+
234
+    /**
235
+     * Partie optionnelle après
236
+     *
237
+     * @var string|array
238
+     */
239
+    public $apres = '';
240
+
241
+    /**
242
+     * Partie alternative, si pas de résultat dans la boucle
243
+     *
244
+     * @var string|array
245
+     */
246
+    public $altern = '';
247
+
248
+    /**
249
+     * Partie apres toujours affichee
250
+     *
251
+     * @var string|array
252
+     */
253
+    public $postaff = '';
254
+
255
+
256
+    /**
257
+     * La boucle doit-elle sélectionner la langue ?
258
+     *
259
+     * @var string|null
260
+     */
261
+    public $lang_select;
262
+
263
+    /**
264
+     * Alias de table d'application de la requête ou nom complet de la table SQL
265
+     *
266
+     * @var string|null
267
+     */
268
+    public $type_requete;
269
+
270
+    /**
271
+     * La table est elle optionnelle ?
272
+     *
273
+     * Si oui, aucune erreur ne sera générée si la table demandée n'est pas présente
274
+     *
275
+     * @var bool
276
+     */
277
+    public $table_optionnelle = false;
278
+
279
+    /**
280
+     * Nom du fichier de connexion
281
+     *
282
+     * @var string
283
+     */
284
+    public $sql_serveur = '';
285
+
286
+    /**
287
+     * Paramètres de la boucle
288
+     *
289
+     * Description des paramètres passés à la boucle, qui servent ensuite
290
+     * au calcul des critères
291
+     *
292
+     * @var array
293
+     */
294
+    public $param = [];
295
+
296
+    /**
297
+     * Critères de la boucle
298
+     *
299
+     * @var Critere[]
300
+     */
301
+    public $criteres = [];
302
+
303
+    /**
304
+     * Textes insérés entre 2 éléments de boucle (critère inter)
305
+     *
306
+     * @var string[]
307
+     */
308
+    public $separateur = [];
309
+
310
+    /**
311
+     * Liste des jointures possibles avec cette table
312
+     *
313
+     * Les jointures par défaut de la table sont complétées en priorité
314
+     * des jointures déclarées explicitement sur la boucle
315
+     *
316
+     * @see base_trouver_table_dist()
317
+     * @var array
318
+     */
319
+    public $jointures = [];
320
+
321
+    /**
322
+     * Jointures explicites avec cette table
323
+     *
324
+     * Ces jointures sont utilisées en priorité par rapport aux jointures
325
+     * normales possibles pour retrouver les colonnes demandées extérieures
326
+     * à la boucle.
327
+     *
328
+     * @var string|bool
329
+     */
330
+    public $jointures_explicites = false;
331
+
332
+    /**
333
+     * Nom de la variable PHP stockant le noms de doublons utilisés "$doublons_index"
334
+     *
335
+     * @var string|null
336
+     */
337
+    public $doublons;
338
+
339
+    /**
340
+     * Code PHP ajouté au début de chaque itération de boucle.
341
+     *
342
+     * Utilisé entre autre par les critères {pagination}, {n-a,b}, {a/b}...
343
+     *
344
+     * @var string
345
+     */
346
+    public $partie = '';
347
+
348
+    /**
349
+     * Nombre de divisions de la boucle, d'éléments à afficher,
350
+     * ou de soustractions d'éléments à faire
351
+     *
352
+     * Dans les critères limitant le nombre d'éléments affichés
353
+     * {a,b}, {a,n-b}, {a/b}, {pagination b}, b est affecté à total_parties.
354
+     *
355
+     * @var string
356
+     */
357
+    public $total_parties = '';
358
+
359
+    /**
360
+     * Code PHP ajouté avant l'itération de boucle.
361
+     *
362
+     * Utilisé entre autre par les critères {pagination}, {a,b}, {a/b}
363
+     * pour initialiser les variables de début et de fin d'itération.
364
+     *
365
+     * @var string
366
+     */
367
+    public $mode_partie = '';
368
+
369
+    /**
370
+     * Identifiant d'une boucle qui appelle celle-ci de manière récursive
371
+     *
372
+     * Si une boucle est appelée de manière récursive quelque part par
373
+     * une autre boucle comme <BOUCLE_rec(boucle_identifiant) />, cette
374
+     * boucle (identifiant) reçoit dans cette propriété l'identifiant
375
+     * de l'appelant (rec)
376
+     *
377
+     * @var string
378
+     */
379
+    public $externe = '';
380
+
381
+    // champs pour la construction de la requete SQL
382
+
383
+    /**
384
+     * Liste des champs à récupérer par la boucle
385
+     *
386
+     * Expression 'table.nom_champ' ou calculée 'nom_champ AS x'
387
+     *
388
+     * @var string[]
389
+     */
390
+    public $select = [];
391
+
392
+    /**
393
+     * Liste des alias / tables SQL utilisées dans la boucle
394
+     *
395
+     * L'index est un identifiant (xx dans spip_xx assez souvent) qui servira
396
+     * d'alias au nom de la table ; la valeur est le nom de la table SQL désirée.
397
+     *
398
+     * L'index 0 peut définir le type de sources de données de l'itérateur DATA
399
+     *
400
+     * @var string[]
401
+     */
402
+    public $from = [];
403
+
404
+    /**
405
+     * Liste des alias / type de jointures utilisées dans la boucle
406
+     *
407
+     * L'index est le nom d'alias (comme pour la propriété $from), et la valeur
408
+     * un type de jointure parmi 'INNER', 'LEFT', 'RIGHT', 'OUTER'.
409
+     *
410
+     * Lorsque le type n'est pas déclaré pour un alias, c'est 'INNER'
411
+     * qui sera utilisé par défaut (créant donc un INNER JOIN).
412
+     *
413
+     * @var string[]
414
+     */
415
+    public $from_type = [];
416
+
417
+    /**
418
+     * Liste des conditions WHERE de la boucle
419
+     *
420
+     * Permet de restreindre les éléments retournés par une boucle
421
+     * en fonctions des conditions transmises dans ce tableau.
422
+     *
423
+     * Ce tableau peut avoir plusieurs niveaux de profondeur.
424
+     *
425
+     * Les éléments du premier niveau sont reliés par des AND, donc
426
+     * chaque élément ajouté directement au where par
427
+     * $boucle->where[] = array(...) ou $boucle->where[] = "'expression'"
428
+     * est une condition AND en plus.
429
+     *
430
+     * Par contre, lorsqu'on indique un tableau, il peut décrire des relations
431
+     * internes différentes. Soit $expr un tableau d'expressions quelconques de 3 valeurs :
432
+     * $expr = array(operateur, val1, val2)
433
+     *
434
+     * Ces 3 valeurs sont des expressions PHP. L'index 0 désigne l'opérateur
435
+     * à réaliser tel que :
436
+     *
437
+     * - "'='" , "'>='", "'<'", "'IN'", "'REGEXP'", "'LIKE'", ... :
438
+     *    val1 et val2 sont des champs et valeurs à utiliser dans la comparaison
439
+     *    suivant cet ordre : "val1 operateur val2".
440
+     *    Exemple : $boucle->where[] = array("'='", "'articles.statut'", "'\"publie\"'");
441
+     * - "'AND'", "'OR'", "'NOT'" :
442
+     *    dans ce cas val1 et val2 sont également des expressions
443
+     *    de comparaison complètes, et peuvent être eux-même des tableaux comme $expr
444
+     *    Exemples :
445
+     *    $boucle->where[] = array("'OR'", $expr1, $expr2);
446
+     *    $boucle->where[] = array("'NOT'", $expr); // val2 n'existe pas avec NOT
447
+     *
448
+     * D'autres noms sont possibles pour l'opérateur (le nombre de valeurs diffère) :
449
+     * - "'SELF'", "'SUBSELECT'" : indiquent des sous requêtes
450
+     * - "'?'" : indique une condition à faire évaluer (val1 ? val2 : val3)
451
+     *
452
+     * @var array
453
+     */
454
+    public $where = [];
455
+
456
+    public $join = [];
457
+    public $having = [];
458
+    public $limit = '';
459
+    public $group = [];
460
+    public $order = [];
461
+    public $default_order = [];
462
+    public $date = 'date';
463
+    public $hash = '';
464
+    public $in = '';
465
+    public $sous_requete = false;
466
+
467
+    /**
468
+     * Code PHP qui sera ajouté en tout début de la fonction de boucle
469
+     *
470
+     * Il sert à insérer le code calculant une hierarchie
471
+     *
472
+     * @var string
473
+     */
474
+    public $hierarchie = '';
475
+
476
+    // champs pour la construction du corps PHP
477
+
478
+    /**
479
+     * Description des sources de données de la boucle
480
+     *
481
+     * Description des données de la boucle issu de trouver_table
482
+     * dans le cadre de l'itérateur SQL et contenant au moins l'index 'field'.
483
+     *
484
+     * @see base_trouver_table_dist()
485
+     * @var array
486
+     */
487
+    public $show = [];
488
+
489
+    /**
490
+     * Nom de la table SQL principale de la boucle, sans son préfixe
491
+     *
492
+     * @var string
493
+     */
494
+    public $id_table;
495
+
496
+    /**
497
+     * Nom de la clé primaire de la table SQL principale de la boucle
498
+     *
499
+     * @var string
500
+     */
501
+    public $primary;
502
+
503
+    /**
504
+     * Code PHP compilé de la boucle
505
+     *
506
+     * @var string
507
+     */
508
+    public $return;
509
+
510
+    public $numrows = false;
511
+    public $cptrows = false;
512
+
513
+    /**
514
+     * Description du squelette
515
+     *
516
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
517
+     *
518
+     * Peut contenir les index :
519
+     *
520
+     * - nom : Nom du fichier de cache
521
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
522
+     * - sourcefile : Chemin du squelette
523
+     * - squelette : Code du squelette
524
+     * - id_mere : Identifiant de la boucle parente
525
+     * - documents : Pour embed et img dans les textes
526
+     * - session : Pour un cache sessionné par auteur
527
+     * - niv : Niveau de tabulation
528
+     *
529
+     * @var array
530
+     */
531
+    public $descr = [];
532
+
533
+    /**
534
+     * Numéro de ligne dans le code source du squelette
535
+     *
536
+     * @var int
537
+     */
538
+    public $ligne = 0;
539
+
540
+
541
+    /**
542
+     * table pour stocker les modificateurs de boucle tels que tout, plat ...,
543
+     * utilisable par les plugins egalement
544
+     *
545
+     * @var array<string, mixed>
546
+     */
547
+    public $modificateur = [];
548
+
549
+    /**
550
+     * Type d'itérateur utilisé pour cette boucle
551
+     *
552
+     * - 'SQL' dans le cadre d'une boucle sur une table SQL
553
+     * - 'DATA' pour l'itérateur DATA, ...
554
+     *
555
+     * @var string
556
+     */
557
+    public $iterateur = ''; // type d'iterateur
558
+
559
+    /**
560
+     * @var array $debug Textes qui seront insérés dans l’entête de boucle du mode debug
561
+     */
562
+    public $debug = [];
563
+
564
+    /**
565
+     * Index de la boucle dont le champ présent dans cette boucle est originaire,
566
+     * notamment si le champ a été trouve dans une boucle parente
567
+     *
568
+     * Tableau nom du champ => index de boucle
569
+     *
570
+     * @var array $index_champ
571
+     */
572
+    public $index_champ = [];
573
+
574
+    // obsoletes, conserves provisoirement pour compatibilite
575
+    public $tout = false;
576
+    public $plat = false;
577
+    public $lien = false;
578 578
 }
579 579
 
580 580
 /**
@@ -585,56 +585,56 @@  discard block
 block discarded – undo
585 585
  * @package SPIP\Core\Compilateur\AST
586 586
  **/
587 587
 class Critere {
588
-	/**
589
-	 * Type de noeud
590
-	 *
591
-	 * @var string
592
-	 */
593
-	public $type = 'critere';
594
-
595
-	/**
596
-	 * Opérateur (>, <, >=, IN, ...)
597
-	 *
598
-	 * @var null|string
599
-	 */
600
-	public $op;
601
-
602
-	/**
603
-	 * Présence d'une négation (truc !op valeur)
604
-	 *
605
-	 * @var null|string
606
-	 */
607
-	public $not;
608
-
609
-	/**
610
-	 * Présence d'une exclusion (!truc op valeur)
611
-	 *
612
-	 * @var null|string
613
-	 */
614
-	public $exclus;
615
-
616
-	/**
617
-	 * Présence d'une condition dans le critère (truc ?)
618
-	 *
619
-	 * @var bool
620
-	 */
621
-	public $cond = false;
622
-
623
-	/**
624
-	 * Paramètres du critère
625
-	 * - $param[0] : élément avant l'opérateur
626
-	 * - $param[1..n] : éléments après l'opérateur
627
-	 *
628
-	 * @var array
629
-	 */
630
-	public $param = [];
631
-
632
-	/**
633
-	 * Numéro de ligne dans le code source du squelette
634
-	 *
635
-	 * @var int
636
-	 */
637
-	public $ligne = 0;
588
+    /**
589
+     * Type de noeud
590
+     *
591
+     * @var string
592
+     */
593
+    public $type = 'critere';
594
+
595
+    /**
596
+     * Opérateur (>, <, >=, IN, ...)
597
+     *
598
+     * @var null|string
599
+     */
600
+    public $op;
601
+
602
+    /**
603
+     * Présence d'une négation (truc !op valeur)
604
+     *
605
+     * @var null|string
606
+     */
607
+    public $not;
608
+
609
+    /**
610
+     * Présence d'une exclusion (!truc op valeur)
611
+     *
612
+     * @var null|string
613
+     */
614
+    public $exclus;
615
+
616
+    /**
617
+     * Présence d'une condition dans le critère (truc ?)
618
+     *
619
+     * @var bool
620
+     */
621
+    public $cond = false;
622
+
623
+    /**
624
+     * Paramètres du critère
625
+     * - $param[0] : élément avant l'opérateur
626
+     * - $param[1..n] : éléments après l'opérateur
627
+     *
628
+     * @var array
629
+     */
630
+    public $param = [];
631
+
632
+    /**
633
+     * Numéro de ligne dans le code source du squelette
634
+     *
635
+     * @var int
636
+     */
637
+    public $ligne = 0;
638 638
 }
639 639
 
640 640
 /**
@@ -643,139 +643,139 @@  discard block
 block discarded – undo
643 643
  * @package SPIP\Core\Compilateur\AST
644 644
  **/
645 645
 class Champ {
646
-	/**
647
-	 * Type de noeud
648
-	 *
649
-	 * @var string
650
-	 */
651
-	public $type = 'champ';
652
-
653
-	/**
654
-	 * Nom du champ demandé. Exemple 'ID_ARTICLE'
655
-	 *
656
-	 * @var string|null
657
-	 */
658
-	public $nom_champ;
659
-
660
-	/**
661
-	 * Identifiant de la boucle parente si explicité
662
-	 *
663
-	 * @var string|null
664
-	 */
665
-	public $nom_boucle = '';
666
-
667
-	/**
668
-	 * Partie optionnelle avant
669
-	 *
670
-	 * @var null|string|array
671
-	 */
672
-	public $avant;
673
-
674
-	/**
675
-	 * Partie optionnelle après
676
-	 *
677
-	 * @var null|string|array
678
-	 */
679
-	public $apres;
680
-
681
-	/**
682
-	 * Étoiles : annuler des automatismes
683
-	 *
684
-	 * - '*' annule les filtres automatiques
685
-	 * - '**' annule en plus les protections de scripts
686
-	 *
687
-	 * @var null|string
688
-	 */
689
-	public $etoile;
690
-
691
-	/**
692
-	 * Arguments et filtres explicites sur la balise
693
-	 *
694
-	 * - $param[0] contient les arguments de la balise
695
-	 * - $param[1..n] contient les filtres à appliquer à la balise
696
-	 *
697
-	 * @var array
698
-	 */
699
-	public $param = [];
700
-
701
-	/**
702
-	 * Source des filtres  (compatibilité) (?)
703
-	 *
704
-	 * @var array|null
705
-	 */
706
-	public $fonctions = [];
707
-
708
-	/**
709
-	 * Identifiant de la boucle
710
-	 *
711
-	 * @var string
712
-	 */
713
-	public $id_boucle = '';
714
-
715
-	/**
716
-	 * AST du squelette, liste de toutes les boucles
717
-	 *
718
-	 * @var Boucles[]
719
-	 */
720
-	public $boucles;
721
-
722
-	/**
723
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
724
-	 *
725
-	 * @var string|null
726
-	 */
727
-	public $type_requete;
728
-
729
-	/**
730
-	 * Résultat de la compilation: toujours une expression PHP
731
-	 *
732
-	 * @var string
733
-	 */
734
-	public $code = '';
735
-
736
-	/**
737
-	 * Interdire les scripts
738
-	 *
739
-	 * false si on est sûr de cette balise
740
-	 *
741
-	 * @see interdire_scripts()
742
-	 * @var bool
743
-	 */
744
-	public $interdire_scripts = true;
745
-
746
-	/**
747
-	 * Description du squelette
748
-	 *
749
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
750
-	 *
751
-	 * Peut contenir les index :
752
-	 *
753
-	 * - nom : Nom du fichier de cache
754
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
755
-	 * - sourcefile : Chemin du squelette
756
-	 * - squelette : Code du squelette
757
-	 * - id_mere : Identifiant de la boucle parente
758
-	 * - documents : Pour embed et img dans les textes
759
-	 * - session : Pour un cache sessionné par auteur
760
-	 * - niv : Niveau de tabulation
761
-	 *
762
-	 * @var array
763
-	 */
764
-	public $descr = [];
765
-
766
-	/**
767
-	 * Numéro de ligne dans le code source du squelette
768
-	 *
769
-	 * @var int
770
-	 */
771
-	public $ligne = 0;
772
-
773
-	/**
774
-	 * Drapeau pour reperer les balises calculées par une fonction explicite
775
-	 *
776
-	 * @var bool
777
-	 */
778
-	public $balise_calculee = false;
646
+    /**
647
+     * Type de noeud
648
+     *
649
+     * @var string
650
+     */
651
+    public $type = 'champ';
652
+
653
+    /**
654
+     * Nom du champ demandé. Exemple 'ID_ARTICLE'
655
+     *
656
+     * @var string|null
657
+     */
658
+    public $nom_champ;
659
+
660
+    /**
661
+     * Identifiant de la boucle parente si explicité
662
+     *
663
+     * @var string|null
664
+     */
665
+    public $nom_boucle = '';
666
+
667
+    /**
668
+     * Partie optionnelle avant
669
+     *
670
+     * @var null|string|array
671
+     */
672
+    public $avant;
673
+
674
+    /**
675
+     * Partie optionnelle après
676
+     *
677
+     * @var null|string|array
678
+     */
679
+    public $apres;
680
+
681
+    /**
682
+     * Étoiles : annuler des automatismes
683
+     *
684
+     * - '*' annule les filtres automatiques
685
+     * - '**' annule en plus les protections de scripts
686
+     *
687
+     * @var null|string
688
+     */
689
+    public $etoile;
690
+
691
+    /**
692
+     * Arguments et filtres explicites sur la balise
693
+     *
694
+     * - $param[0] contient les arguments de la balise
695
+     * - $param[1..n] contient les filtres à appliquer à la balise
696
+     *
697
+     * @var array
698
+     */
699
+    public $param = [];
700
+
701
+    /**
702
+     * Source des filtres  (compatibilité) (?)
703
+     *
704
+     * @var array|null
705
+     */
706
+    public $fonctions = [];
707
+
708
+    /**
709
+     * Identifiant de la boucle
710
+     *
711
+     * @var string
712
+     */
713
+    public $id_boucle = '';
714
+
715
+    /**
716
+     * AST du squelette, liste de toutes les boucles
717
+     *
718
+     * @var Boucles[]
719
+     */
720
+    public $boucles;
721
+
722
+    /**
723
+     * Alias de table d'application de la requête ou nom complet de la table SQL
724
+     *
725
+     * @var string|null
726
+     */
727
+    public $type_requete;
728
+
729
+    /**
730
+     * Résultat de la compilation: toujours une expression PHP
731
+     *
732
+     * @var string
733
+     */
734
+    public $code = '';
735
+
736
+    /**
737
+     * Interdire les scripts
738
+     *
739
+     * false si on est sûr de cette balise
740
+     *
741
+     * @see interdire_scripts()
742
+     * @var bool
743
+     */
744
+    public $interdire_scripts = true;
745
+
746
+    /**
747
+     * Description du squelette
748
+     *
749
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
750
+     *
751
+     * Peut contenir les index :
752
+     *
753
+     * - nom : Nom du fichier de cache
754
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
755
+     * - sourcefile : Chemin du squelette
756
+     * - squelette : Code du squelette
757
+     * - id_mere : Identifiant de la boucle parente
758
+     * - documents : Pour embed et img dans les textes
759
+     * - session : Pour un cache sessionné par auteur
760
+     * - niv : Niveau de tabulation
761
+     *
762
+     * @var array
763
+     */
764
+    public $descr = [];
765
+
766
+    /**
767
+     * Numéro de ligne dans le code source du squelette
768
+     *
769
+     * @var int
770
+     */
771
+    public $ligne = 0;
772
+
773
+    /**
774
+     * Drapeau pour reperer les balises calculées par une fonction explicite
775
+     *
776
+     * @var bool
777
+     */
778
+    public $balise_calculee = false;
779 779
 }
780 780
 
781 781
 
@@ -783,123 +783,123 @@  discard block
 block discarded – undo
783 783
  * Description d'une chaîne de langue
784 784
  **/
785 785
 class Idiome {
786
-	/**
787
-	 * Type de noeud
788
-	 *
789
-	 * @var string
790
-	 */
791
-	public $type = 'idiome';
792
-
793
-	/**
794
-	 * Clé de traduction demandée. Exemple 'item_oui'
795
-	 *
796
-	 * @var string
797
-	 */
798
-	public $nom_champ = '';
799
-
800
-	/**
801
-	 * Module de langue où chercher la clé de traduction. Exemple 'medias'
802
-	 *
803
-	 * @var string
804
-	 */
805
-	public $module = '';
806
-
807
-	/**
808
-	 * Arguments à passer à la chaîne
809
-	 *
810
-	 * @var array
811
-	 */
812
-	public $arg = [];
813
-
814
-	/**
815
-	 * Filtres à appliquer au résultat
816
-	 *
817
-	 * @var array
818
-	 */
819
-	public $param = [];
820
-
821
-	/**
822
-	 * Source des filtres  (compatibilité) (?)
823
-	 *
824
-	 * @var array|null
825
-	 */
826
-	public $fonctions = [];
827
-
828
-	/**
829
-	 * Inutilisé, propriété générique de l'AST
830
-	 *
831
-	 * @var string|array
832
-	 */
833
-	public $avant = '';
834
-
835
-	/**
836
-	 * Inutilisé, propriété générique de l'AST
837
-	 *
838
-	 * @var string|array
839
-	 */
840
-	public $apres = '';
841
-
842
-	/**
843
-	 * Identifiant de la boucle
844
-	 *
845
-	 * @var string
846
-	 */
847
-	public $id_boucle = '';
848
-
849
-	/**
850
-	 * AST du squelette, liste de toutes les boucles
851
-	 *
852
-	 * @var Boucles[]
853
-	 */
854
-	public $boucles;
855
-
856
-	/**
857
-	 * Alias de table d'application de la requête ou nom complet de la table SQL
858
-	 *
859
-	 * @var string|null
860
-	 */
861
-	public $type_requete;
862
-
863
-	/**
864
-	 * Résultat de la compilation: toujours une expression PHP
865
-	 *
866
-	 * @var string
867
-	 */
868
-	public $code = '';
869
-
870
-	/**
871
-	 * Interdire les scripts
872
-	 *
873
-	 * @see interdire_scripts()
874
-	 * @var bool
875
-	 */
876
-	public $interdire_scripts = false;
877
-
878
-	/**
879
-	 * Description du squelette
880
-	 *
881
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
882
-	 *
883
-	 * Peut contenir les index :
884
-	 * - nom : Nom du fichier de cache
885
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
886
-	 * - sourcefile : Chemin du squelette
887
-	 * - squelette : Code du squelette
888
-	 * - id_mere : Identifiant de la boucle parente
889
-	 * - documents : Pour embed et img dans les textes
890
-	 * - session : Pour un cache sessionné par auteur
891
-	 * - niv : Niveau de tabulation
892
-	 *
893
-	 * @var array
894
-	 */
895
-	public $descr = [];
896
-
897
-	/**
898
-	 * Numéro de ligne dans le code source du squelette
899
-	 *
900
-	 * @var int
901
-	 */
902
-	public $ligne = 0;
786
+    /**
787
+     * Type de noeud
788
+     *
789
+     * @var string
790
+     */
791
+    public $type = 'idiome';
792
+
793
+    /**
794
+     * Clé de traduction demandée. Exemple 'item_oui'
795
+     *
796
+     * @var string
797
+     */
798
+    public $nom_champ = '';
799
+
800
+    /**
801
+     * Module de langue où chercher la clé de traduction. Exemple 'medias'
802
+     *
803
+     * @var string
804
+     */
805
+    public $module = '';
806
+
807
+    /**
808
+     * Arguments à passer à la chaîne
809
+     *
810
+     * @var array
811
+     */
812
+    public $arg = [];
813
+
814
+    /**
815
+     * Filtres à appliquer au résultat
816
+     *
817
+     * @var array
818
+     */
819
+    public $param = [];
820
+
821
+    /**
822
+     * Source des filtres  (compatibilité) (?)
823
+     *
824
+     * @var array|null
825
+     */
826
+    public $fonctions = [];
827
+
828
+    /**
829
+     * Inutilisé, propriété générique de l'AST
830
+     *
831
+     * @var string|array
832
+     */
833
+    public $avant = '';
834
+
835
+    /**
836
+     * Inutilisé, propriété générique de l'AST
837
+     *
838
+     * @var string|array
839
+     */
840
+    public $apres = '';
841
+
842
+    /**
843
+     * Identifiant de la boucle
844
+     *
845
+     * @var string
846
+     */
847
+    public $id_boucle = '';
848
+
849
+    /**
850
+     * AST du squelette, liste de toutes les boucles
851
+     *
852
+     * @var Boucles[]
853
+     */
854
+    public $boucles;
855
+
856
+    /**
857
+     * Alias de table d'application de la requête ou nom complet de la table SQL
858
+     *
859
+     * @var string|null
860
+     */
861
+    public $type_requete;
862
+
863
+    /**
864
+     * Résultat de la compilation: toujours une expression PHP
865
+     *
866
+     * @var string
867
+     */
868
+    public $code = '';
869
+
870
+    /**
871
+     * Interdire les scripts
872
+     *
873
+     * @see interdire_scripts()
874
+     * @var bool
875
+     */
876
+    public $interdire_scripts = false;
877
+
878
+    /**
879
+     * Description du squelette
880
+     *
881
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
882
+     *
883
+     * Peut contenir les index :
884
+     * - nom : Nom du fichier de cache
885
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
886
+     * - sourcefile : Chemin du squelette
887
+     * - squelette : Code du squelette
888
+     * - id_mere : Identifiant de la boucle parente
889
+     * - documents : Pour embed et img dans les textes
890
+     * - session : Pour un cache sessionné par auteur
891
+     * - niv : Niveau de tabulation
892
+     *
893
+     * @var array
894
+     */
895
+    public $descr = [];
896
+
897
+    /**
898
+     * Numéro de ligne dans le code source du squelette
899
+     *
900
+     * @var int
901
+     */
902
+    public $ligne = 0;
903 903
 }
904 904
 
905 905
 /**
@@ -908,28 +908,28 @@  discard block
 block discarded – undo
908 908
  * @package SPIP\Core\Compilateur\AST
909 909
  **/
910 910
 class Polyglotte {
911
-	/**
912
-	 * Type de noeud
913
-	 *
914
-	 * @var string
915
-	 */
916
-	public $type = 'polyglotte';
917
-
918
-	/**
919
-	 * Tableau des traductions possibles classées par langue
920
-	 *
921
-	 * Tableau code de langue => texte
922
-	 *
923
-	 * @var array
924
-	 */
925
-	public $traductions = [];
926
-
927
-	/**
928
-	 * Numéro de ligne dans le code source du squelette
929
-	 *
930
-	 * @var int
931
-	 */
932
-	public $ligne = 0;
911
+    /**
912
+     * Type de noeud
913
+     *
914
+     * @var string
915
+     */
916
+    public $type = 'polyglotte';
917
+
918
+    /**
919
+     * Tableau des traductions possibles classées par langue
920
+     *
921
+     * Tableau code de langue => texte
922
+     *
923
+     * @var array
924
+     */
925
+    public $traductions = [];
926
+
927
+    /**
928
+     * Numéro de ligne dans le code source du squelette
929
+     *
930
+     * @var int
931
+     */
932
+    public $ligne = 0;
933 933
 }
934 934
 
935 935
 
@@ -952,90 +952,90 @@  discard block
 block discarded – undo
952 952
  */
953 953
 function declarer_interfaces() {
954 954
 
955
-	$GLOBALS['table_des_tables']['articles'] = 'articles';
956
-	$GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
957
-	$GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
958
-	$GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
959
-
960
-	// definition des statuts de publication
961
-	$GLOBALS['table_statut'] = [];
962
-
963
-	//
964
-	// tableau des tables de jointures
965
-	// Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
966
-	$GLOBALS['tables_jointures'] = [];
967
-	$GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
968
-
969
-	// $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
970
-	$GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
971
-
972
-
973
-	if (!defined('_TRAITEMENT_TYPO')) {
974
-		define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
975
-	}
976
-	if (!defined('_TRAITEMENT_RACCOURCIS')) {
977
-		define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
978
-	}
979
-	if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
980
-		define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
981
-	}
982
-	$GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
983
-	$GLOBALS['table_des_traitements']['NOM_SITE']['spip_auteurs'] = 'entites_html(%s)';
984
-	$GLOBALS['table_des_traitements']['NOM']['spip_auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
985
-	$GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
986
-	$GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
987
-	$GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
988
-	$GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
989
-	$GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
990
-	$GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
991
-	$GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
992
-	$GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
993
-	$GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
994
-	$GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
995
-	$GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
996
-	$GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
997
-	$GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
998
-	$GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
999
-	$GLOBALS['table_des_traitements']['TAGS'][] = '%s';
1000
-	$GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
1001
-	$GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
1002
-	$GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
1003
-	$GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
1004
-	$GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
1005
-	$GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
1006
-
1007
-	// valeur par defaut pour les balises non listees ci-dessus
1008
-	$GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
1009
-	// toujours securiser les DATA
1010
-	$GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
1011
-	// expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
1012
-	$GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
1013
-
1014
-
1015
-	// gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
1016
-	$interfaces = pipeline(
1017
-		'declarer_tables_interfaces',
1018
-		[
1019
-			'table_des_tables' => $GLOBALS['table_des_tables'],
1020
-			'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
1021
-			'table_date' => $GLOBALS['table_date'],
1022
-			'table_titre' => $GLOBALS['table_titre'],
1023
-			'tables_jointures' => $GLOBALS['tables_jointures'],
1024
-			'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
1025
-			'table_des_traitements' => $GLOBALS['table_des_traitements'],
1026
-			'table_statut' => $GLOBALS['table_statut'],
1027
-		]
1028
-	);
1029
-	if ($interfaces) {
1030
-		$GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
1031
-		$GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
1032
-		$GLOBALS['table_date'] = $interfaces['table_date'];
1033
-		$GLOBALS['table_titre'] = $interfaces['table_titre'];
1034
-		$GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
1035
-		$GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
1036
-		$GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
1037
-		$GLOBALS['table_statut'] = $interfaces['table_statut'];
1038
-	}
955
+    $GLOBALS['table_des_tables']['articles'] = 'articles';
956
+    $GLOBALS['table_des_tables']['auteurs'] = 'auteurs';
957
+    $GLOBALS['table_des_tables']['rubriques'] = 'rubriques';
958
+    $GLOBALS['table_des_tables']['hierarchie'] = 'rubriques';
959
+
960
+    // definition des statuts de publication
961
+    $GLOBALS['table_statut'] = [];
962
+
963
+    //
964
+    // tableau des tables de jointures
965
+    // Ex: gestion du critere {id_mot} dans la boucle(ARTICLES)
966
+    $GLOBALS['tables_jointures'] = [];
967
+    $GLOBALS['tables_jointures']['spip_jobs'][] = 'jobs_liens';
968
+
969
+    // $GLOBALS['exceptions_des_jointures']['titre_mot'] = array('spip_mots', 'titre'); // pour exemple
970
+    $GLOBALS['exceptions_des_jointures']['profondeur'] = ['spip_rubriques', 'profondeur'];
971
+
972
+
973
+    if (!defined('_TRAITEMENT_TYPO')) {
974
+        define('_TRAITEMENT_TYPO', 'typo(%s, "TYPO", $connect, $Pile[0])');
975
+    }
976
+    if (!defined('_TRAITEMENT_RACCOURCIS')) {
977
+        define('_TRAITEMENT_RACCOURCIS', 'propre(%s, $connect, $Pile[0])');
978
+    }
979
+    if (!defined('_TRAITEMENT_TYPO_SANS_NUMERO')) {
980
+        define('_TRAITEMENT_TYPO_SANS_NUMERO', 'supprimer_numero(typo(%s, "TYPO", $connect, $Pile[0]))');
981
+    }
982
+    $GLOBALS['table_des_traitements']['BIO'][] = 'safehtml(' . _TRAITEMENT_RACCOURCIS . ')';
983
+    $GLOBALS['table_des_traitements']['NOM_SITE']['spip_auteurs'] = 'entites_html(%s)';
984
+    $GLOBALS['table_des_traitements']['NOM']['spip_auteurs'] = 'safehtml(' . _TRAITEMENT_TYPO_SANS_NUMERO . ')';
985
+    $GLOBALS['table_des_traitements']['CHAPO'][] = _TRAITEMENT_RACCOURCIS;
986
+    $GLOBALS['table_des_traitements']['DATE'][] = 'normaliser_date(%s)';
987
+    $GLOBALS['table_des_traitements']['DATE_REDAC'][] = 'normaliser_date(%s)';
988
+    $GLOBALS['table_des_traitements']['DATE_MODIF'][] = 'normaliser_date(%s)';
989
+    $GLOBALS['table_des_traitements']['DATE_NOUVEAUTES'][] = 'normaliser_date(%s)';
990
+    $GLOBALS['table_des_traitements']['DESCRIPTIF'][] = _TRAITEMENT_RACCOURCIS;
991
+    $GLOBALS['table_des_traitements']['INTRODUCTION'][] = _TRAITEMENT_RACCOURCIS;
992
+    $GLOBALS['table_des_traitements']['NOM_SITE_SPIP'][] = _TRAITEMENT_TYPO;
993
+    $GLOBALS['table_des_traitements']['NOM'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
994
+    $GLOBALS['table_des_traitements']['AUTEUR'][] = _TRAITEMENT_TYPO;
995
+    $GLOBALS['table_des_traitements']['PS'][] = _TRAITEMENT_RACCOURCIS;
996
+    $GLOBALS['table_des_traitements']['SOURCE'][] = _TRAITEMENT_TYPO;
997
+    $GLOBALS['table_des_traitements']['SOUSTITRE'][] = _TRAITEMENT_TYPO;
998
+    $GLOBALS['table_des_traitements']['SURTITRE'][] = _TRAITEMENT_TYPO;
999
+    $GLOBALS['table_des_traitements']['TAGS'][] = '%s';
1000
+    $GLOBALS['table_des_traitements']['TEXTE'][] = _TRAITEMENT_RACCOURCIS;
1001
+    $GLOBALS['table_des_traitements']['TITRE'][] = _TRAITEMENT_TYPO_SANS_NUMERO;
1002
+    $GLOBALS['table_des_traitements']['TYPE'][] = _TRAITEMENT_TYPO;
1003
+    $GLOBALS['table_des_traitements']['DESCRIPTIF_SITE_SPIP'][] = _TRAITEMENT_RACCOURCIS;
1004
+    $GLOBALS['table_des_traitements']['SLOGAN_SITE_SPIP'][] = _TRAITEMENT_TYPO;
1005
+    $GLOBALS['table_des_traitements']['ENV'][] = 'entites_html(%s,true)';
1006
+
1007
+    // valeur par defaut pour les balises non listees ci-dessus
1008
+    $GLOBALS['table_des_traitements']['*'][] = false; // pas de traitement, mais permet au compilo de trouver la declaration suivante
1009
+    // toujours securiser les DATA
1010
+    $GLOBALS['table_des_traitements']['*']['DATA'] = 'safehtml(%s)';
1011
+    // expliciter pour VALEUR qui est un champ calcule et ne sera pas protege par le catch-all *
1012
+    $GLOBALS['table_des_traitements']['VALEUR']['DATA'] = 'safehtml(%s)';
1013
+
1014
+
1015
+    // gerer l'affectation en 2 temps car si le pipe n'est pas encore declare, on ecrase les globales
1016
+    $interfaces = pipeline(
1017
+        'declarer_tables_interfaces',
1018
+        [
1019
+            'table_des_tables' => $GLOBALS['table_des_tables'],
1020
+            'exceptions_des_tables' => $GLOBALS['exceptions_des_tables'],
1021
+            'table_date' => $GLOBALS['table_date'],
1022
+            'table_titre' => $GLOBALS['table_titre'],
1023
+            'tables_jointures' => $GLOBALS['tables_jointures'],
1024
+            'exceptions_des_jointures' => $GLOBALS['exceptions_des_jointures'],
1025
+            'table_des_traitements' => $GLOBALS['table_des_traitements'],
1026
+            'table_statut' => $GLOBALS['table_statut'],
1027
+        ]
1028
+    );
1029
+    if ($interfaces) {
1030
+        $GLOBALS['table_des_tables'] = $interfaces['table_des_tables'];
1031
+        $GLOBALS['exceptions_des_tables'] = $interfaces['exceptions_des_tables'];
1032
+        $GLOBALS['table_date'] = $interfaces['table_date'];
1033
+        $GLOBALS['table_titre'] = $interfaces['table_titre'];
1034
+        $GLOBALS['tables_jointures'] = $interfaces['tables_jointures'];
1035
+        $GLOBALS['exceptions_des_jointures'] = $interfaces['exceptions_des_jointures'];
1036
+        $GLOBALS['table_des_traitements'] = $interfaces['table_des_traitements'];
1037
+        $GLOBALS['table_statut'] = $interfaces['table_statut'];
1038
+    }
1039 1039
 }
1040 1040
 
1041 1041
 declarer_interfaces();
Please login to merge, or discard this patch.
ecrire/inc/securiser_action.php 1 patch
Indentation   +188 added lines, -188 removed lines patch added patch discarded remove patch
@@ -16,10 +16,10 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Actions
17 17
  **/
18 18
 
19
- use Spip\Chiffrer\SpipCles;
19
+    use Spip\Chiffrer\SpipCles;
20 20
 
21 21
 if (!defined('_ECRIRE_INC_VERSION')) {
22
-	return;
22
+    return;
23 23
 }
24 24
 
25 25
 /**
@@ -52,19 +52,19 @@  discard block
 block discarded – undo
52 52
  * @return array|string
53 53
  */
54 54
 function inc_securiser_action_dist($action = '', $arg = '', $redirect = '', $mode = false, $att = '', $public = false) {
55
-	if ($action) {
56
-		return securiser_action_auteur($action, $arg, $redirect, $mode, $att, $public);
57
-	} else {
58
-		$arg = _request('arg');
59
-		$hash = _request('hash');
60
-		$action = _request('action') ?: _request('formulaire_action');
61
-		if ($a = verifier_action_auteur("$action-$arg", $hash)) {
62
-			return $arg;
63
-		}
64
-		include_spip('inc/minipres');
65
-		echo minipres();
66
-		exit;
67
-	}
55
+    if ($action) {
56
+        return securiser_action_auteur($action, $arg, $redirect, $mode, $att, $public);
57
+    } else {
58
+        $arg = _request('arg');
59
+        $hash = _request('hash');
60
+        $action = _request('action') ?: _request('formulaire_action');
61
+        if ($a = verifier_action_auteur("$action-$arg", $hash)) {
62
+            return $arg;
63
+        }
64
+        include_spip('inc/minipres');
65
+        echo minipres();
66
+        exit;
67
+    }
68 68
 }
69 69
 
70 70
 /**
@@ -83,29 +83,29 @@  discard block
 block discarded – undo
83 83
  */
84 84
 function demander_confirmation_avant_action($titre, $titre_bouton, $url_action = null) {
85 85
 
86
-	if (!$url_action) {
87
-		$url_action = self();
88
-		$action = _request('action');
89
-		$url_action = parametre_url($url_action, 'action', $action, '&');
90
-	}
91
-	else {
92
-		$action = parametre_url($url_action, 'action');
93
-	}
94
-
95
-	$arg = parametre_url($url_action, 'arg');
96
-	$confirm = md5("$action:$arg:" . realpath(__FILE__));
97
-	if (_request('confirm_action') === $confirm) {
98
-		return true;
99
-	}
100
-
101
-	$url_confirm = parametre_url($url_action, 'confirm_action', $confirm, '&');
102
-	include_spip('inc/filtres');
103
-	$bouton_action = bouton_action($titre_bouton, $url_confirm);
104
-	$corps = "<div style='text-align:center;'>$bouton_action</div>";
105
-
106
-	include_spip('inc/minipres');
107
-	echo minipres($titre, $corps);
108
-	exit;
86
+    if (!$url_action) {
87
+        $url_action = self();
88
+        $action = _request('action');
89
+        $url_action = parametre_url($url_action, 'action', $action, '&');
90
+    }
91
+    else {
92
+        $action = parametre_url($url_action, 'action');
93
+    }
94
+
95
+    $arg = parametre_url($url_action, 'arg');
96
+    $confirm = md5("$action:$arg:" . realpath(__FILE__));
97
+    if (_request('confirm_action') === $confirm) {
98
+        return true;
99
+    }
100
+
101
+    $url_confirm = parametre_url($url_action, 'confirm_action', $confirm, '&');
102
+    include_spip('inc/filtres');
103
+    $bouton_action = bouton_action($titre_bouton, $url_confirm);
104
+    $corps = "<div style='text-align:center;'>$bouton_action</div>";
105
+
106
+    include_spip('inc/minipres');
107
+    echo minipres($titre, $corps);
108
+    exit;
109 109
 }
110 110
 
111 111
 /**
@@ -136,34 +136,34 @@  discard block
 block discarded – undo
136 136
  */
137 137
 function securiser_action_auteur($action, $arg, $redirect = '', $mode = false, $att = '', $public = false) {
138 138
 
139
-	// mode URL ou array
140
-	if (!is_string($mode)) {
141
-		$hash = calculer_action_auteur("$action-$arg", is_numeric($att) ? $att : null);
142
-
143
-		$r = rawurlencode($redirect);
144
-		if ($mode === -1) {
145
-			return ['action' => $action, 'arg' => $arg, 'hash' => $hash];
146
-		} else {
147
-			return generer_url_action(
148
-				$action,
149
-				'arg=' . rawurlencode($arg) . "&hash=$hash" . (!$r ? '' : "&redirect=$r"),
150
-				$mode,
151
-				$public
152
-			);
153
-		}
154
-	}
155
-
156
-	// mode formulaire
157
-	$hash = calculer_action_auteur("$action-$arg");
158
-	$att .= " style='margin: 0px; border: 0px'";
159
-	if ($redirect) {
160
-		$redirect = "\n\t\t<input name='redirect' type='hidden' value='" . str_replace("'", '&#39;', $redirect) . "' />";
161
-	}
162
-	$mode .= $redirect . "
139
+    // mode URL ou array
140
+    if (!is_string($mode)) {
141
+        $hash = calculer_action_auteur("$action-$arg", is_numeric($att) ? $att : null);
142
+
143
+        $r = rawurlencode($redirect);
144
+        if ($mode === -1) {
145
+            return ['action' => $action, 'arg' => $arg, 'hash' => $hash];
146
+        } else {
147
+            return generer_url_action(
148
+                $action,
149
+                'arg=' . rawurlencode($arg) . "&hash=$hash" . (!$r ? '' : "&redirect=$r"),
150
+                $mode,
151
+                $public
152
+            );
153
+        }
154
+    }
155
+
156
+    // mode formulaire
157
+    $hash = calculer_action_auteur("$action-$arg");
158
+    $att .= " style='margin: 0px; border: 0px'";
159
+    if ($redirect) {
160
+        $redirect = "\n\t\t<input name='redirect' type='hidden' value='" . str_replace("'", '&#39;', $redirect) . "' />";
161
+    }
162
+    $mode .= $redirect . "
163 163
 <input name='hash' type='hidden' value='$hash' />
164 164
 <input name='arg' type='hidden' value='$arg' />";
165 165
 
166
-	return generer_form_action($action, $mode, $att, $public);
166
+    return generer_form_action($action, $mode, $att, $public);
167 167
 }
168 168
 
169 169
 /**
@@ -173,48 +173,48 @@  discard block
 block discarded – undo
173 173
  * @return array
174 174
  */
175 175
 function caracteriser_auteur($id_auteur = null) {
176
-	static $caracterisation = [];
177
-
178
-	if (is_null($id_auteur) and !isset($GLOBALS['visiteur_session']['id_auteur'])) {
179
-		// si l'auteur courant n'est pas connu alors qu'il peut demander une action
180
-		// c'est une connexion par php_auth ou 1 instal, on se rabat sur le cookie.
181
-		// S'il n'avait pas le droit de realiser cette action, le hash sera faux.
182
-		if (
183
-			isset($_COOKIE['spip_session'])
184
-			and (preg_match('/^(\d+)/', $_COOKIE['spip_session'], $r))
185
-		) {
186
-			return [$r[1], ''];
187
-			// Necessaire aux forums anonymes.
188
-			// Pour le reste, ca echouera.
189
-		} else {
190
-			return ['0', ''];
191
-		}
192
-	}
193
-	// Eviter l'acces SQL si le pass est connu de PHP
194
-	if (is_null($id_auteur)) {
195
-		$id_auteur = $GLOBALS['visiteur_session']['id_auteur'] ?? 0;
196
-		if (isset($GLOBALS['visiteur_session']['pass']) and $GLOBALS['visiteur_session']['pass']) {
197
-			return $caracterisation[$id_auteur] = [$id_auteur, $GLOBALS['visiteur_session']['pass']];
198
-		}
199
-	}
200
-
201
-	if (isset($caracterisation[$id_auteur])) {
202
-		return $caracterisation[$id_auteur];
203
-	}
204
-
205
-	if ($id_auteur) {
206
-		include_spip('base/abstract_sql');
207
-		$t = sql_fetsel('id_auteur, pass', 'spip_auteurs', "id_auteur=$id_auteur");
208
-		if ($t) {
209
-			return $caracterisation[$id_auteur] = [$t['id_auteur'], $t['pass']];
210
-		}
211
-		include_spip('inc/minipres');
212
-		echo minipres();
213
-		exit;
214
-	} // Visiteur anonyme, pour ls forums par exemple
215
-	else {
216
-		return ['0', ''];
217
-	}
176
+    static $caracterisation = [];
177
+
178
+    if (is_null($id_auteur) and !isset($GLOBALS['visiteur_session']['id_auteur'])) {
179
+        // si l'auteur courant n'est pas connu alors qu'il peut demander une action
180
+        // c'est une connexion par php_auth ou 1 instal, on se rabat sur le cookie.
181
+        // S'il n'avait pas le droit de realiser cette action, le hash sera faux.
182
+        if (
183
+            isset($_COOKIE['spip_session'])
184
+            and (preg_match('/^(\d+)/', $_COOKIE['spip_session'], $r))
185
+        ) {
186
+            return [$r[1], ''];
187
+            // Necessaire aux forums anonymes.
188
+            // Pour le reste, ca echouera.
189
+        } else {
190
+            return ['0', ''];
191
+        }
192
+    }
193
+    // Eviter l'acces SQL si le pass est connu de PHP
194
+    if (is_null($id_auteur)) {
195
+        $id_auteur = $GLOBALS['visiteur_session']['id_auteur'] ?? 0;
196
+        if (isset($GLOBALS['visiteur_session']['pass']) and $GLOBALS['visiteur_session']['pass']) {
197
+            return $caracterisation[$id_auteur] = [$id_auteur, $GLOBALS['visiteur_session']['pass']];
198
+        }
199
+    }
200
+
201
+    if (isset($caracterisation[$id_auteur])) {
202
+        return $caracterisation[$id_auteur];
203
+    }
204
+
205
+    if ($id_auteur) {
206
+        include_spip('base/abstract_sql');
207
+        $t = sql_fetsel('id_auteur, pass', 'spip_auteurs', "id_auteur=$id_auteur");
208
+        if ($t) {
209
+            return $caracterisation[$id_auteur] = [$t['id_auteur'], $t['pass']];
210
+        }
211
+        include_spip('inc/minipres');
212
+        echo minipres();
213
+        exit;
214
+    } // Visiteur anonyme, pour ls forums par exemple
215
+    else {
216
+        return ['0', ''];
217
+    }
218 218
 }
219 219
 
220 220
 /**
@@ -229,30 +229,30 @@  discard block
 block discarded – undo
229 229
  * @return string
230 230
  */
231 231
 function _action_auteur(string $action, int $id_auteur, ?string $pass, string $alea): string {
232
-	static $sha = [];
233
-	$pass = $pass ?? '';
234
-	$entry = "$action:$id_auteur:$pass:$alea";
235
-	if (!isset($sha[$entry])) {
236
-		$sha[$entry] = hash_hmac('sha256', "$action::$id_auteur", "$pass::" . _action_get_alea($alea));
237
-	}
238
-
239
-	return $sha[$entry];
232
+    static $sha = [];
233
+    $pass = $pass ?? '';
234
+    $entry = "$action:$id_auteur:$pass:$alea";
235
+    if (!isset($sha[$entry])) {
236
+        $sha[$entry] = hash_hmac('sha256', "$action::$id_auteur", "$pass::" . _action_get_alea($alea));
237
+    }
238
+
239
+    return $sha[$entry];
240 240
 }
241 241
 
242 242
 function _action_get_alea(string $alea): string {
243
-	if (!isset($GLOBALS['meta'][$alea])) {
244
-		if (!$exec = _request('exec') or !autoriser_sans_cookie($exec)) {
245
-			include_spip('inc/acces');
246
-			charger_aleas();
247
-			if (empty($GLOBALS['meta'][$alea])) {
248
-				include_spip('inc/minipres');
249
-				echo minipres();
250
-				spip_log("$alea indisponible");
251
-				exit;
252
-			}
253
-		}
254
-	}
255
-	return $GLOBALS['meta'][$alea] ?? '';
243
+    if (!isset($GLOBALS['meta'][$alea])) {
244
+        if (!$exec = _request('exec') or !autoriser_sans_cookie($exec)) {
245
+            include_spip('inc/acces');
246
+            charger_aleas();
247
+            if (empty($GLOBALS['meta'][$alea])) {
248
+                include_spip('inc/minipres');
249
+                echo minipres();
250
+                spip_log("$alea indisponible");
251
+                exit;
252
+            }
253
+        }
254
+    }
255
+    return $GLOBALS['meta'][$alea] ?? '';
256 256
 }
257 257
 
258 258
 /**
@@ -263,9 +263,9 @@  discard block
 block discarded – undo
263 263
  * @return string
264 264
  */
265 265
 function calculer_action_auteur($action, $id_auteur = null) {
266
-	[$id_auteur, $pass] = caracteriser_auteur($id_auteur);
266
+    [$id_auteur, $pass] = caracteriser_auteur($id_auteur);
267 267
 
268
-	return _action_auteur($action, $id_auteur, $pass, 'alea_ephemere');
268
+    return _action_auteur($action, $id_auteur, $pass, 'alea_ephemere');
269 269
 }
270 270
 
271 271
 
@@ -278,15 +278,15 @@  discard block
 block discarded – undo
278 278
  * @return bool
279 279
  */
280 280
 function verifier_action_auteur($action, $hash) {
281
-	[$id_auteur, $pass] = caracteriser_auteur();
282
-	if (
283
-		hash_equals($hash, _action_auteur($action, $id_auteur, $pass, 'alea_ephemere'))
284
-		or hash_equals($hash, _action_auteur($action, $id_auteur, $pass, 'alea_ephemere_ancien'))
285
-	) {
286
-		return true;
287
-	}
288
-
289
-	return false;
281
+    [$id_auteur, $pass] = caracteriser_auteur();
282
+    if (
283
+        hash_equals($hash, _action_auteur($action, $id_auteur, $pass, 'alea_ephemere'))
284
+        or hash_equals($hash, _action_auteur($action, $id_auteur, $pass, 'alea_ephemere_ancien'))
285
+    ) {
286
+        return true;
287
+    }
288
+
289
+    return false;
290 290
 }
291 291
 
292 292
 //
@@ -301,8 +301,8 @@  discard block
 block discarded – undo
301 301
  * @return string
302 302
  */
303 303
 function secret_du_site() {
304
-	include_spip('inc/chiffrer');
305
-	return SpipCles::secret_du_site();
304
+    include_spip('inc/chiffrer');
305
+    return SpipCles::secret_du_site();
306 306
 }
307 307
 
308 308
 /**
@@ -312,7 +312,7 @@  discard block
 block discarded – undo
312 312
  * @return string
313 313
  */
314 314
 function calculer_cle_action($action) {
315
-	return hash_hmac('sha256', $action, secret_du_site());
315
+    return hash_hmac('sha256', $action, secret_du_site());
316 316
 }
317 317
 
318 318
 /**
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
  * @return bool
324 324
  */
325 325
 function verifier_cle_action($action, $cle) {
326
-	return hash_equals($cle, calculer_cle_action($action));
326
+    return hash_equals($cle, calculer_cle_action($action));
327 327
 }
328 328
 
329 329
 
@@ -340,19 +340,19 @@  discard block
 block discarded – undo
340 340
  * @return string Token, de la forme "{id}*{hash}"
341 341
  */
342 342
 function calculer_token_previsu($url, $id_auteur = null, $alea = 'alea_ephemere') {
343
-	if (is_null($id_auteur)) {
344
-		if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
345
-			$id_auteur = $GLOBALS['visiteur_session']['id_auteur'];
346
-		}
347
-	}
348
-	if (!$id_auteur = intval($id_auteur)) {
349
-		return '';
350
-	}
351
-	// On nettoie l’URL de tous les var_.
352
-	$url = nettoyer_uri_var($url);
353
-
354
-	$token = _action_auteur('previsualiser-' . $url, $id_auteur, secret_du_site(), $alea);
355
-	return "$id_auteur-$token";
343
+    if (is_null($id_auteur)) {
344
+        if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
345
+            $id_auteur = $GLOBALS['visiteur_session']['id_auteur'];
346
+        }
347
+    }
348
+    if (!$id_auteur = intval($id_auteur)) {
349
+        return '';
350
+    }
351
+    // On nettoie l’URL de tous les var_.
352
+    $url = nettoyer_uri_var($url);
353
+
354
+    $token = _action_auteur('previsualiser-' . $url, $id_auteur, secret_du_site(), $alea);
355
+    return "$id_auteur-$token";
356 356
 }
357 357
 
358 358
 
@@ -370,31 +370,31 @@  discard block
 block discarded – undo
370 370
  *     + Tableau (id auteur, type d’objet, id_objet) sinon.
371 371
  */
372 372
 function verifier_token_previsu($token) {
373
-	// retrouver auteur / hash
374
-	$e = explode('-', $token, 2);
375
-	if (count($e) == 2 and is_numeric(reset($e))) {
376
-		$id_auteur = intval(reset($e));
377
-	} else {
378
-		return false;
379
-	}
380
-
381
-	// calculer le type et id de l’url actuelle
382
-	include_spip('inc/urls');
383
-	include_spip('inc/filtres_mini');
384
-	$url = url_absolue(self());
385
-
386
-	// verifier le token
387
-	$_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere');
388
-	if (!$_token or !hash_equals($token, $_token)) {
389
-		$_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere_ancien');
390
-		if (!$_token or !hash_equals($token, $_token)) {
391
-			return false;
392
-		}
393
-	}
394
-
395
-	return [
396
-		'id_auteur' => $id_auteur,
397
-	];
373
+    // retrouver auteur / hash
374
+    $e = explode('-', $token, 2);
375
+    if (count($e) == 2 and is_numeric(reset($e))) {
376
+        $id_auteur = intval(reset($e));
377
+    } else {
378
+        return false;
379
+    }
380
+
381
+    // calculer le type et id de l’url actuelle
382
+    include_spip('inc/urls');
383
+    include_spip('inc/filtres_mini');
384
+    $url = url_absolue(self());
385
+
386
+    // verifier le token
387
+    $_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere');
388
+    if (!$_token or !hash_equals($token, $_token)) {
389
+        $_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere_ancien');
390
+        if (!$_token or !hash_equals($token, $_token)) {
391
+            return false;
392
+        }
393
+    }
394
+
395
+    return [
396
+        'id_auteur' => $id_auteur,
397
+    ];
398 398
 }
399 399
 
400 400
 /**
@@ -403,13 +403,13 @@  discard block
 block discarded – undo
403 403
  * @return bool|array
404 404
  */
405 405
 function decrire_token_previsu() {
406
-	static $desc = null;
407
-	if (is_null($desc)) {
408
-		if ($token = _request('var_previewtoken')) {
409
-			$desc = verifier_token_previsu($token);
410
-		} else {
411
-			$desc = false;
412
-		}
413
-	}
414
-	return $desc;
406
+    static $desc = null;
407
+    if (is_null($desc)) {
408
+        if ($token = _request('var_previewtoken')) {
409
+            $desc = verifier_token_previsu($token);
410
+        } else {
411
+            $desc = false;
412
+        }
413
+    }
414
+    return $desc;
415 415
 }
Please login to merge, or discard this patch.
ecrire/inc/presenter_enfants.php 1 patch
Indentation   +180 added lines, -180 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/autoriser');
@@ -30,80 +30,80 @@  discard block
 block discarded – undo
30 30
  *  Un tableau des sous rubriques
31 31
  */
32 32
 function enfant_rub($collection, $debut = 0, $limite = 500) {
33
-	$voir_logo = (isset($GLOBALS['meta']['image_process']) and $GLOBALS['meta']['image_process'] != 'non');
34
-	$logo = '';
35
-
36
-	if ($voir_logo) {
37
-		$chercher_logo = charger_fonction('chercher_logo', 'inc');
38
-		include_spip('inc/filtres_images_mini');
39
-	}
40
-
41
-	$res = [];
42
-
43
-	$result = sql_select(
44
-		'id_rubrique, id_parent, titre, descriptif, lang',
45
-		'spip_rubriques',
46
-		'id_parent=' . intval($collection),
47
-		'',
48
-		'0+titre,titre',
49
-		$debut == -1 ? '' : "$debut,$limite"
50
-	);
51
-	while ($row = sql_fetch($result)) {
52
-		$id_rubrique = $row['id_rubrique'];
53
-		$id_parent = $row['id_parent'];
54
-		// pour etre sur de passer par tous les traitements
55
-		$titre = generer_objet_info($id_rubrique, 'rubrique', 'titre');
56
-		if ('' !== ($rang = recuperer_numero($row['titre']))) {
57
-			$rang = "<span class='rang'>$rang.</span> ";
58
-		}
59
-
60
-		if (autoriser('voir', 'rubrique', $id_rubrique)) {
61
-			$les_sous_enfants = sous_enfant_rub($id_rubrique);
62
-
63
-			changer_typo($row['lang']);
64
-			$lang_dir = lang_dir($row['lang']);
65
-			$descriptif = propre($row['descriptif']);
66
-
67
-			if ($voir_logo) {
68
-				if ($logo = $chercher_logo($id_rubrique, 'id_rubrique', 'on')) {
69
-					[$fid, $dir, $nom, $format] = $logo;
70
-					$logo = image_recadre_avec_fallback("<img src='$fid' alt='' />", 70, 70);
71
-					if ($logo) {
72
-						$logo = wrap(inserer_attribut($logo, 'class', 'logo'), '<span class="logo-carre">');
73
-					}
74
-				}
75
-			}
76
-
77
-			$lib_bouton = (!acces_restreint_rubrique($id_rubrique) ? '' :
78
-					http_img_pack(
79
-						'auteur-0minirezo-16.png',
80
-						'',
81
-						" width='16' height='16'",
82
-						_T('image_administrer_rubrique')
83
-					)) .
84
-				" <a class='titremlien' dir='$lang_dir'" .
85
-				($row['lang'] !== $GLOBALS['spip_lang'] ? " hreflang='" . $row['lang'] . "'" : '') .
86
-				" href='" .
87
-				generer_objet_url($id_rubrique, 'rubrique') .
88
-				"'><span class='titre'>" .
89
-				$rang . $titre
90
-				. '</span>'
91
-				. (is_string($logo) ? $logo : '')
92
-				. '</a>';
93
-
94
-			$titre = bouton_block_depliable($lib_bouton, $les_sous_enfants ? false : -1, "enfants$id_rubrique")
95
-				. (!$descriptif ? '' : "\n<div class='descriptif'>$descriptif</div>")
96
-				;
97
-
98
-			$res[] =
99
-				debut_cadre_sous_rub(($id_parent ? 'rubrique-24.png' : 'secteur-24.png'), true, '', $titre) .
100
-				$les_sous_enfants .
101
-				fin_cadre_sous_rub();
102
-		}
103
-	}
104
-
105
-	changer_typo($GLOBALS['spip_lang']); # remettre la typo de l'interface pour la suite
106
-	return $res;
33
+    $voir_logo = (isset($GLOBALS['meta']['image_process']) and $GLOBALS['meta']['image_process'] != 'non');
34
+    $logo = '';
35
+
36
+    if ($voir_logo) {
37
+        $chercher_logo = charger_fonction('chercher_logo', 'inc');
38
+        include_spip('inc/filtres_images_mini');
39
+    }
40
+
41
+    $res = [];
42
+
43
+    $result = sql_select(
44
+        'id_rubrique, id_parent, titre, descriptif, lang',
45
+        'spip_rubriques',
46
+        'id_parent=' . intval($collection),
47
+        '',
48
+        '0+titre,titre',
49
+        $debut == -1 ? '' : "$debut,$limite"
50
+    );
51
+    while ($row = sql_fetch($result)) {
52
+        $id_rubrique = $row['id_rubrique'];
53
+        $id_parent = $row['id_parent'];
54
+        // pour etre sur de passer par tous les traitements
55
+        $titre = generer_objet_info($id_rubrique, 'rubrique', 'titre');
56
+        if ('' !== ($rang = recuperer_numero($row['titre']))) {
57
+            $rang = "<span class='rang'>$rang.</span> ";
58
+        }
59
+
60
+        if (autoriser('voir', 'rubrique', $id_rubrique)) {
61
+            $les_sous_enfants = sous_enfant_rub($id_rubrique);
62
+
63
+            changer_typo($row['lang']);
64
+            $lang_dir = lang_dir($row['lang']);
65
+            $descriptif = propre($row['descriptif']);
66
+
67
+            if ($voir_logo) {
68
+                if ($logo = $chercher_logo($id_rubrique, 'id_rubrique', 'on')) {
69
+                    [$fid, $dir, $nom, $format] = $logo;
70
+                    $logo = image_recadre_avec_fallback("<img src='$fid' alt='' />", 70, 70);
71
+                    if ($logo) {
72
+                        $logo = wrap(inserer_attribut($logo, 'class', 'logo'), '<span class="logo-carre">');
73
+                    }
74
+                }
75
+            }
76
+
77
+            $lib_bouton = (!acces_restreint_rubrique($id_rubrique) ? '' :
78
+                    http_img_pack(
79
+                        'auteur-0minirezo-16.png',
80
+                        '',
81
+                        " width='16' height='16'",
82
+                        _T('image_administrer_rubrique')
83
+                    )) .
84
+                " <a class='titremlien' dir='$lang_dir'" .
85
+                ($row['lang'] !== $GLOBALS['spip_lang'] ? " hreflang='" . $row['lang'] . "'" : '') .
86
+                " href='" .
87
+                generer_objet_url($id_rubrique, 'rubrique') .
88
+                "'><span class='titre'>" .
89
+                $rang . $titre
90
+                . '</span>'
91
+                . (is_string($logo) ? $logo : '')
92
+                . '</a>';
93
+
94
+            $titre = bouton_block_depliable($lib_bouton, $les_sous_enfants ? false : -1, "enfants$id_rubrique")
95
+                . (!$descriptif ? '' : "\n<div class='descriptif'>$descriptif</div>")
96
+                ;
97
+
98
+            $res[] =
99
+                debut_cadre_sous_rub(($id_parent ? 'rubrique-24.png' : 'secteur-24.png'), true, '', $titre) .
100
+                $les_sous_enfants .
101
+                fin_cadre_sous_rub();
102
+        }
103
+    }
104
+
105
+    changer_typo($GLOBALS['spip_lang']); # remettre la typo de l'interface pour la suite
106
+    return $res;
107 107
 }
108 108
 
109 109
 /**
@@ -116,71 +116,71 @@  discard block
 block discarded – undo
116 116
  *  Le contenu du bloc dépliable
117 117
  */
118 118
 function sous_enfant_rub($collection2) {
119
-	$nb = sql_countsel('spip_rubriques', 'id_parent=' . intval($collection2));
120
-
121
-	$retour = '';
122
-	$pagination = '';
123
-	$debut = 0;
124
-	$limite = 500;
125
-
126
-	/**
127
-	 * On ne va afficher que 500 résultats max
128
-	 * Si > 500 on affiche une pagination
129
-	 */
130
-	if ($nb > $limite) {
131
-		$debut = _request('debut_rubrique' . $collection2) ?: $debut;
132
-		$pagination = chercher_filtre('pagination');
133
-		$pagination = '<nav class="pagination">' . $pagination(
134
-			$nb,
135
-			'_rubrique' . $collection2,
136
-			$debut,
137
-			$limite,
138
-			true,
139
-			'prive'
140
-		) . '</nav>';
141
-		$limite = $debut + $limite;
142
-	}
143
-
144
-	$result = sql_select(
145
-		'id_rubrique, id_parent, titre, lang',
146
-		'spip_rubriques',
147
-		'id_parent=' . intval($collection2),
148
-		'',
149
-		'0+titre,titre',
150
-		$debut == -1 ? '' : "$debut,$limite"
151
-	);
152
-
153
-	while ($row = sql_fetch($result)) {
154
-		$id_rubrique2 = $row['id_rubrique'];
155
-		$titre2 = generer_objet_info(
156
-			$id_rubrique2,
157
-			'rubrique',
158
-			'titre'
159
-		); // pour etre sur de passer par tous les traitements
160
-		if ('' !== ($rang2 = recuperer_numero($row['titre']))) {
161
-			$rang2 = "<span class='rang'>$rang2.</span> ";
162
-		}
163
-
164
-		changer_typo($row['lang']);
165
-		$lang_dir = lang_dir($row['lang']);
166
-		if (autoriser('voir', 'rubrique', $id_rubrique2)) {
167
-			$retour .= "\n<li class='item' dir='$lang_dir'><a href='" . generer_objet_url(
168
-				$id_rubrique2,
169
-				'rubrique'
170
-			) . "'>" . $rang2 . $titre2 . "</a></li>\n";
171
-		}
172
-	}
173
-
174
-	$retour = $pagination . $retour . $pagination;
175
-
176
-	if (!$retour) {
177
-		return '';
178
-	}
179
-
180
-	return debut_block_depliable($debut > 0 ? true : false, "enfants$collection2")
181
-	. "\n<ul class='liste-items sous-sous-rub'>\n"
182
-	. $retour
183
-	. "</ul>\n" . fin_block() . "\n\n";
119
+    $nb = sql_countsel('spip_rubriques', 'id_parent=' . intval($collection2));
120
+
121
+    $retour = '';
122
+    $pagination = '';
123
+    $debut = 0;
124
+    $limite = 500;
125
+
126
+    /**
127
+     * On ne va afficher que 500 résultats max
128
+     * Si > 500 on affiche une pagination
129
+     */
130
+    if ($nb > $limite) {
131
+        $debut = _request('debut_rubrique' . $collection2) ?: $debut;
132
+        $pagination = chercher_filtre('pagination');
133
+        $pagination = '<nav class="pagination">' . $pagination(
134
+            $nb,
135
+            '_rubrique' . $collection2,
136
+            $debut,
137
+            $limite,
138
+            true,
139
+            'prive'
140
+        ) . '</nav>';
141
+        $limite = $debut + $limite;
142
+    }
143
+
144
+    $result = sql_select(
145
+        'id_rubrique, id_parent, titre, lang',
146
+        'spip_rubriques',
147
+        'id_parent=' . intval($collection2),
148
+        '',
149
+        '0+titre,titre',
150
+        $debut == -1 ? '' : "$debut,$limite"
151
+    );
152
+
153
+    while ($row = sql_fetch($result)) {
154
+        $id_rubrique2 = $row['id_rubrique'];
155
+        $titre2 = generer_objet_info(
156
+            $id_rubrique2,
157
+            'rubrique',
158
+            'titre'
159
+        ); // pour etre sur de passer par tous les traitements
160
+        if ('' !== ($rang2 = recuperer_numero($row['titre']))) {
161
+            $rang2 = "<span class='rang'>$rang2.</span> ";
162
+        }
163
+
164
+        changer_typo($row['lang']);
165
+        $lang_dir = lang_dir($row['lang']);
166
+        if (autoriser('voir', 'rubrique', $id_rubrique2)) {
167
+            $retour .= "\n<li class='item' dir='$lang_dir'><a href='" . generer_objet_url(
168
+                $id_rubrique2,
169
+                'rubrique'
170
+            ) . "'>" . $rang2 . $titre2 . "</a></li>\n";
171
+        }
172
+    }
173
+
174
+    $retour = $pagination . $retour . $pagination;
175
+
176
+    if (!$retour) {
177
+        return '';
178
+    }
179
+
180
+    return debut_block_depliable($debut > 0 ? true : false, "enfants$collection2")
181
+    . "\n<ul class='liste-items sous-sous-rub'>\n"
182
+    . $retour
183
+    . "</ul>\n" . fin_block() . "\n\n";
184 184
 }
185 185
 
186 186
 /**
@@ -195,44 +195,44 @@  discard block
 block discarded – undo
195 195
  *  Le contenu textuel affiché, la liste des sous rubriques
196 196
  */
197 197
 function afficher_enfant_rub($id_rubrique = 0) {
198
-	$pagination = '';
199
-	$debut = 0;
200
-	$limite = 500;
201
-
202
-	$nb = sql_countsel('spip_rubriques', 'id_parent=' . intval($id_rubrique));
203
-
204
-	if ($nb > $limite) {
205
-		$debut = _request('debut_rubrique' . $id_rubrique) ?: $debut;
206
-		$pagination = chercher_filtre('pagination');
207
-		$pagination = '<br class="nettoyeur"><nav class="pagination">' .
208
-			$pagination($nb, '_rubrique' . $id_rubrique, $debut, $limite, true, 'prive') .
209
-		'</nav>';
210
-	}
211
-
212
-	$les_enfants = enfant_rub($id_rubrique, $debut, $limite);
213
-
214
-	if (!$n = count($les_enfants)) {
215
-		return '';
216
-	}
217
-
218
-	if ($n == 1) {
219
-		$les_enfants = reset($les_enfants);
220
-		$les_enfants2 = '';
221
-	} else {
222
-		$n = ceil($n / 2);
223
-		$les_enfants2 = implode('', array_slice($les_enfants, $n));
224
-		$les_enfants = implode('', array_slice($les_enfants, 0, $n));
225
-	}
226
-
227
-	$res =
228
-		$pagination
229
-		. "<div class='gauche'>"
230
-		. $les_enfants
231
-		. '</div>'
232
-		. "<div class='droite'>"
233
-		. $les_enfants2
234
-		. '</div>'
235
-		. $pagination;
236
-
237
-	return $res;
198
+    $pagination = '';
199
+    $debut = 0;
200
+    $limite = 500;
201
+
202
+    $nb = sql_countsel('spip_rubriques', 'id_parent=' . intval($id_rubrique));
203
+
204
+    if ($nb > $limite) {
205
+        $debut = _request('debut_rubrique' . $id_rubrique) ?: $debut;
206
+        $pagination = chercher_filtre('pagination');
207
+        $pagination = '<br class="nettoyeur"><nav class="pagination">' .
208
+            $pagination($nb, '_rubrique' . $id_rubrique, $debut, $limite, true, 'prive') .
209
+        '</nav>';
210
+    }
211
+
212
+    $les_enfants = enfant_rub($id_rubrique, $debut, $limite);
213
+
214
+    if (!$n = count($les_enfants)) {
215
+        return '';
216
+    }
217
+
218
+    if ($n == 1) {
219
+        $les_enfants = reset($les_enfants);
220
+        $les_enfants2 = '';
221
+    } else {
222
+        $n = ceil($n / 2);
223
+        $les_enfants2 = implode('', array_slice($les_enfants, $n));
224
+        $les_enfants = implode('', array_slice($les_enfants, 0, $n));
225
+    }
226
+
227
+    $res =
228
+        $pagination
229
+        . "<div class='gauche'>"
230
+        . $les_enfants
231
+        . '</div>'
232
+        . "<div class='droite'>"
233
+        . $les_enfants2
234
+        . '</div>'
235
+        . $pagination;
236
+
237
+    return $res;
238 238
 }
Please login to merge, or discard this patch.
ecrire/public/decompiler.php 1 patch
Indentation   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -11,129 +11,129 @@  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
 // Decompilation de l'arbre de syntaxe abstraite d'un squelette SPIP
18 18
 
19 19
 function decompiler_boucle($struct, $fmt = '', $prof = 0) {
20
-	$nom = $struct->id_boucle;
21
-	$preaff = decompiler_($struct->preaff, $fmt, $prof);
22
-	$avant = decompiler_($struct->avant, $fmt, $prof);
23
-	$apres = decompiler_($struct->apres, $fmt, $prof);
24
-	$altern = decompiler_($struct->altern, $fmt, $prof);
25
-	$milieu = decompiler_($struct->milieu, $fmt, $prof);
26
-	$postaff = decompiler_($struct->postaff, $fmt, $prof);
27
-
28
-	$type = $struct->sql_serveur ? "$struct->sql_serveur:" : '';
29
-	$type .= ($struct->type_requete ?: $struct->table_optionnelle);
30
-
31
-	if ($struct->jointures_explicites) {
32
-		$type .= ' ' . $struct->jointures_explicites;
33
-	}
34
-	if ($struct->table_optionnelle) {
35
-		$type .= '?';
36
-	}
37
-	// Revoir le cas de la boucle recursive
38
-
39
-	$crit = $struct->param;
40
-	if ($crit and !is_array($crit[0])) {
41
-		$type = strtolower($type) . array_shift($crit);
42
-	}
43
-	$crit = decompiler_criteres($struct, $fmt, $prof);
44
-
45
-	$f = 'format_boucle_' . $fmt;
46
-
47
-	return $f($preaff, $avant, $nom, $type, $crit, $milieu, $apres, $altern, $postaff, $prof);
20
+    $nom = $struct->id_boucle;
21
+    $preaff = decompiler_($struct->preaff, $fmt, $prof);
22
+    $avant = decompiler_($struct->avant, $fmt, $prof);
23
+    $apres = decompiler_($struct->apres, $fmt, $prof);
24
+    $altern = decompiler_($struct->altern, $fmt, $prof);
25
+    $milieu = decompiler_($struct->milieu, $fmt, $prof);
26
+    $postaff = decompiler_($struct->postaff, $fmt, $prof);
27
+
28
+    $type = $struct->sql_serveur ? "$struct->sql_serveur:" : '';
29
+    $type .= ($struct->type_requete ?: $struct->table_optionnelle);
30
+
31
+    if ($struct->jointures_explicites) {
32
+        $type .= ' ' . $struct->jointures_explicites;
33
+    }
34
+    if ($struct->table_optionnelle) {
35
+        $type .= '?';
36
+    }
37
+    // Revoir le cas de la boucle recursive
38
+
39
+    $crit = $struct->param;
40
+    if ($crit and !is_array($crit[0])) {
41
+        $type = strtolower($type) . array_shift($crit);
42
+    }
43
+    $crit = decompiler_criteres($struct, $fmt, $prof);
44
+
45
+    $f = 'format_boucle_' . $fmt;
46
+
47
+    return $f($preaff, $avant, $nom, $type, $crit, $milieu, $apres, $altern, $postaff, $prof);
48 48
 }
49 49
 
50 50
 function decompiler_include($struct, $fmt = '', $prof = 0) {
51
-	$res = [];
52
-	foreach ($struct->param ?: [] as $couple) {
53
-		array_shift($couple);
54
-		foreach ($couple as $v) {
55
-			$res[] = decompiler_($v, $fmt, $prof);
56
-		}
57
-	}
58
-	$file = is_string($struct->texte) ? $struct->texte :
59
-		decompiler_($struct->texte, $fmt, $prof);
60
-	$f = 'format_inclure_' . $fmt;
61
-
62
-	return $f($file, $res, $prof);
51
+    $res = [];
52
+    foreach ($struct->param ?: [] as $couple) {
53
+        array_shift($couple);
54
+        foreach ($couple as $v) {
55
+            $res[] = decompiler_($v, $fmt, $prof);
56
+        }
57
+    }
58
+    $file = is_string($struct->texte) ? $struct->texte :
59
+        decompiler_($struct->texte, $fmt, $prof);
60
+    $f = 'format_inclure_' . $fmt;
61
+
62
+    return $f($file, $res, $prof);
63 63
 }
64 64
 
65 65
 function decompiler_texte($struct, $fmt = '', $prof = 0) {
66
-	$f = 'format_texte_' . $fmt;
66
+    $f = 'format_texte_' . $fmt;
67 67
 
68
-	return strlen($struct->texte) ? $f($struct->texte, $prof) : '';
68
+    return strlen($struct->texte) ? $f($struct->texte, $prof) : '';
69 69
 }
70 70
 
71 71
 function decompiler_polyglotte($struct, $fmt = '', $prof = 0) {
72
-	$f = 'format_polyglotte_' . $fmt;
72
+    $f = 'format_polyglotte_' . $fmt;
73 73
 
74
-	return $f($struct->traductions, $prof);
74
+    return $f($struct->traductions, $prof);
75 75
 }
76 76
 
77 77
 function decompiler_idiome($struct, $fmt = '', $prof = 0) {
78
-	$args = [];
79
-	foreach ($struct->arg as $k => $v) {
80
-		$args[$k] = public_decompiler($v, $fmt, $prof);
81
-	}
78
+    $args = [];
79
+    foreach ($struct->arg as $k => $v) {
80
+        $args[$k] = public_decompiler($v, $fmt, $prof);
81
+    }
82 82
 
83
-	$filtres = decompiler_liste($struct->param, $fmt, $prof);
83
+    $filtres = decompiler_liste($struct->param, $fmt, $prof);
84 84
 
85
-	$f = 'format_idiome_' . $fmt;
85
+    $f = 'format_idiome_' . $fmt;
86 86
 
87
-	return $f($struct->nom_champ, $struct->module, $args, $filtres, $prof);
87
+    return $f($struct->nom_champ, $struct->module, $args, $filtres, $prof);
88 88
 }
89 89
 
90 90
 function decompiler_champ($struct, $fmt = '', $prof = 0) {
91
-	$avant = decompiler_($struct->avant, $fmt, $prof);
92
-	$apres = decompiler_($struct->apres, $fmt, $prof);
93
-	$args = $filtres = '';
94
-	if ($p = $struct->param) {
95
-		if ($p[0][0] === '') {
96
-			$args = decompiler_liste([array_shift($p)], $fmt, $prof);
97
-		}
98
-		$filtres = decompiler_liste($p, $fmt, $prof);
99
-	}
100
-	$f = 'format_champ_' . $fmt;
101
-
102
-	return $f($struct->nom_champ, $struct->nom_boucle, $struct->etoile, $avant, $apres, $args, $filtres, $prof);
91
+    $avant = decompiler_($struct->avant, $fmt, $prof);
92
+    $apres = decompiler_($struct->apres, $fmt, $prof);
93
+    $args = $filtres = '';
94
+    if ($p = $struct->param) {
95
+        if ($p[0][0] === '') {
96
+            $args = decompiler_liste([array_shift($p)], $fmt, $prof);
97
+        }
98
+        $filtres = decompiler_liste($p, $fmt, $prof);
99
+    }
100
+    $f = 'format_champ_' . $fmt;
101
+
102
+    return $f($struct->nom_champ, $struct->nom_boucle, $struct->etoile, $avant, $apres, $args, $filtres, $prof);
103 103
 }
104 104
 
105 105
 function decompiler_liste($sources, $fmt = '', $prof = 0) {
106
-	if (!is_array($sources)) {
107
-		return '';
108
-	}
109
-	$f = 'format_liste_' . $fmt;
110
-	$res = '';
111
-	foreach ($sources as $arg) {
112
-		if (!is_array($arg)) {
113
-			continue; // ne devrait pas arriver.
114
-		} else {
115
-			$r = array_shift($arg);
116
-		}
117
-		$args = [];
118
-		foreach ($arg as $v) {
119
-			// cas des arguments entoures de ' ou "
120
-			if (
121
-				((is_countable($v) ? count($v) : 0) == 1)
122
-				and $v[0]->type == 'texte'
123
-				and (strlen($v[0]->apres) == 1)
124
-				and $v[0]->apres == $v[0]->avant
125
-			) {
126
-				$args[] = $v[0]->avant . $v[0]->texte . $v[0]->apres;
127
-			} else {
128
-				$args[] = decompiler_($v, $fmt, 0 - $prof);
129
-			}
130
-		}
131
-		if (($r !== '') or $args) {
132
-			$res .= $f($r, $args, $prof);
133
-		}
134
-	}
135
-
136
-	return $res;
106
+    if (!is_array($sources)) {
107
+        return '';
108
+    }
109
+    $f = 'format_liste_' . $fmt;
110
+    $res = '';
111
+    foreach ($sources as $arg) {
112
+        if (!is_array($arg)) {
113
+            continue; // ne devrait pas arriver.
114
+        } else {
115
+            $r = array_shift($arg);
116
+        }
117
+        $args = [];
118
+        foreach ($arg as $v) {
119
+            // cas des arguments entoures de ' ou "
120
+            if (
121
+                ((is_countable($v) ? count($v) : 0) == 1)
122
+                and $v[0]->type == 'texte'
123
+                and (strlen($v[0]->apres) == 1)
124
+                and $v[0]->apres == $v[0]->avant
125
+            ) {
126
+                $args[] = $v[0]->avant . $v[0]->texte . $v[0]->apres;
127
+            } else {
128
+                $args[] = decompiler_($v, $fmt, 0 - $prof);
129
+            }
130
+        }
131
+        if (($r !== '') or $args) {
132
+            $res .= $f($r, $args, $prof);
133
+        }
134
+    }
135
+
136
+    return $res;
137 137
 }
138 138
 
139 139
 // Decompilation des criteres: on triche et on deroge:
@@ -141,93 +141,93 @@  discard block
 block discarded – undo
141 141
 // - le champ apres signale le critere {"separateur"} ou {'separateur'}
142 142
 // - les champs sont implicitement etendus (crochets implicites mais interdits)
143 143
 function decompiler_criteres($boucle, $fmt = '', $prof = 0) {
144
-	$sources = $boucle->param;
145
-	if (!is_array($sources)) {
146
-		return '';
147
-	}
148
-	$res = '';
149
-	$f = 'format_critere_' . $fmt;
150
-	foreach ($sources as $crit) {
151
-		if (!is_array($crit)) {
152
-			continue;
153
-		} // boucle recursive
154
-		array_shift($crit);
155
-		$args = [];
156
-		foreach ($crit as $i => $v) {
157
-			if (
158
-				((is_countable($v) ? count($v) : 0) == 1)
159
-				and $v[0]->type == 'texte'
160
-				and $v[0]->apres
161
-			) {
162
-				$args[] = [['texte', ($v[0]->apres . $v[0]->texte . $v[0]->apres)]];
163
-			} else {
164
-				$res2 = [];
165
-				foreach ($v as $k => $p) {
166
-					if (
167
-						isset($p->type)
168
-						and function_exists($d = 'decompiler_' . $p->type)
169
-					) {
170
-						$r = $d($p, $fmt, (0 - $prof));
171
-						$res2[] = [$p->type, $r];
172
-					} else {
173
-						spip_log("critere $i / $k mal forme");
174
-					}
175
-				}
176
-				$args[] = $res2;
177
-			}
178
-		}
179
-		$res .= $f($args);
180
-	}
181
-
182
-	return $res;
144
+    $sources = $boucle->param;
145
+    if (!is_array($sources)) {
146
+        return '';
147
+    }
148
+    $res = '';
149
+    $f = 'format_critere_' . $fmt;
150
+    foreach ($sources as $crit) {
151
+        if (!is_array($crit)) {
152
+            continue;
153
+        } // boucle recursive
154
+        array_shift($crit);
155
+        $args = [];
156
+        foreach ($crit as $i => $v) {
157
+            if (
158
+                ((is_countable($v) ? count($v) : 0) == 1)
159
+                and $v[0]->type == 'texte'
160
+                and $v[0]->apres
161
+            ) {
162
+                $args[] = [['texte', ($v[0]->apres . $v[0]->texte . $v[0]->apres)]];
163
+            } else {
164
+                $res2 = [];
165
+                foreach ($v as $k => $p) {
166
+                    if (
167
+                        isset($p->type)
168
+                        and function_exists($d = 'decompiler_' . $p->type)
169
+                    ) {
170
+                        $r = $d($p, $fmt, (0 - $prof));
171
+                        $res2[] = [$p->type, $r];
172
+                    } else {
173
+                        spip_log("critere $i / $k mal forme");
174
+                    }
175
+                }
176
+                $args[] = $res2;
177
+            }
178
+        }
179
+        $res .= $f($args);
180
+    }
181
+
182
+    return $res;
183 183
 }
184 184
 
185 185
 
186 186
 function decompiler_($liste, $fmt = '', $prof = 0) {
187
-	if (!is_array($liste)) {
188
-		return '';
189
-	}
190
-	$prof2 = ($prof < 0) ? ($prof - 1) : ($prof + 1);
191
-	$contenu = [];
192
-	foreach ($liste as $k => $p) {
193
-		if (!isset($p->type)) {
194
-			continue;
195
-		} #??????
196
-		$d = 'decompiler_' . $p->type;
197
-		$next = $liste[$k + 1] ?? false;
198
-		// Forcer le champ etendu si son source (pas les reecritures)
199
-		// contenait des args et s'il est suivi d'espaces,
200
-		// le champ simple les eliminant est un bug helas perenne.
201
-
202
-		if (
203
-			$next
204
-			and ($next->type == 'texte')
205
-			and $p->type == 'champ'
206
-			and !$p->apres
207
-			and !$p->avant
208
-			and $p->fonctions
209
-		) {
210
-			$n = strlen($next->texte) - strlen(ltrim($next->texte));
211
-			if ($n) {
212
-				$champ = new Texte();
213
-				$champ->texte = substr($next->texte, 0, $n);
214
-				$champ->ligne = $p->ligne;
215
-				$p->apres = [$champ];
216
-				$next->texte = substr($next->texte, $n);
217
-			}
218
-		}
219
-		$contenu[] = [$d($p, $fmt, $prof2), $p->type];
220
-	}
221
-	$f = 'format_suite_' . $fmt;
222
-
223
-	return $f($contenu);
187
+    if (!is_array($liste)) {
188
+        return '';
189
+    }
190
+    $prof2 = ($prof < 0) ? ($prof - 1) : ($prof + 1);
191
+    $contenu = [];
192
+    foreach ($liste as $k => $p) {
193
+        if (!isset($p->type)) {
194
+            continue;
195
+        } #??????
196
+        $d = 'decompiler_' . $p->type;
197
+        $next = $liste[$k + 1] ?? false;
198
+        // Forcer le champ etendu si son source (pas les reecritures)
199
+        // contenait des args et s'il est suivi d'espaces,
200
+        // le champ simple les eliminant est un bug helas perenne.
201
+
202
+        if (
203
+            $next
204
+            and ($next->type == 'texte')
205
+            and $p->type == 'champ'
206
+            and !$p->apres
207
+            and !$p->avant
208
+            and $p->fonctions
209
+        ) {
210
+            $n = strlen($next->texte) - strlen(ltrim($next->texte));
211
+            if ($n) {
212
+                $champ = new Texte();
213
+                $champ->texte = substr($next->texte, 0, $n);
214
+                $champ->ligne = $p->ligne;
215
+                $p->apres = [$champ];
216
+                $next->texte = substr($next->texte, $n);
217
+            }
218
+        }
219
+        $contenu[] = [$d($p, $fmt, $prof2), $p->type];
220
+    }
221
+    $f = 'format_suite_' . $fmt;
222
+
223
+    return $f($contenu);
224 224
 }
225 225
 
226 226
 function public_decompiler($liste, $fmt = '', $prof = 0, $quoi = '') {
227
-	if (!include_spip('public/format_' . $fmt)) {
228
-		return "'$fmt'?";
229
-	}
230
-	$f = 'decompiler_' . $quoi;
227
+    if (!include_spip('public/format_' . $fmt)) {
228
+        return "'$fmt'?";
229
+    }
230
+    $f = 'decompiler_' . $quoi;
231 231
 
232
-	return $f($liste, $fmt, $prof);
232
+    return $f($liste, $fmt, $prof);
233 233
 }
Please login to merge, or discard this patch.
ecrire/public/parametrer.php 1 patch
Indentation   +246 added lines, -246 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_fichiers_fonctions();
@@ -30,177 +30,177 @@  discard block
 block discarded – undo
30 30
 # En cas d'erreur process_ins est absent et texte est un tableau de 2 chaines
31 31
 
32 32
 function public_parametrer_dist($fond, $contexte = '', $cache = '', string $connect = '') {
33
-	static $composer, $styliser, $notes = null;
34
-	$page = tester_redirection($fond, $contexte, $connect);
35
-	if ($page) {
36
-		return $page;
37
-	}
38
-
39
-	if (isset($contexte['lang'])) {
40
-		$lang = $contexte['lang'];
41
-	} elseif (!isset($lang)) {
42
-		$lang = $GLOBALS['meta']['langue_site'];
43
-	}
44
-
45
-	$select = ((!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang']) and $lang <> $GLOBALS['spip_lang']);
46
-	if ($select) {
47
-		$select = lang_select($lang);
48
-	}
49
-
50
-	$debug = (defined('_VAR_MODE') && _VAR_MODE == 'debug');
51
-
52
-	if (!$styliser) {
53
-		$styliser = charger_fonction('styliser', 'public');
54
-	}
55
-	[$skel, $mime_type, $gram, $sourcefile] =
56
-		$styliser($fond, $contexte, $GLOBALS['spip_lang'], $connect);
57
-
58
-	if ($skel) {
59
-		// sauver le nom de l'eventuel squelette en cours d'execution
60
-		// (recursion possible a cause des modeles)
61
-		if ($debug) {
62
-			$courant = $GLOBALS['debug_objets']['courant'] ?? null;
63
-			$GLOBALS['debug_objets']['contexte'][$sourcefile] = $contexte;
64
-		}
65
-
66
-		// charger le squelette en specifiant les langages cibles et source
67
-		// au cas il faudrait le compiler (source posterieure au resultat)
68
-
69
-		if (!$composer) {
70
-			$composer = charger_fonction('composer', 'public');
71
-		}
72
-		$fonc = $composer($skel, $mime_type, $gram, $sourcefile, $connect);
73
-	} else {
74
-		$fonc = '';
75
-	}
76
-
77
-	if (!$fonc) { // squelette inconnu (==='') ou faux (===false)
78
-		$page = $fonc;
79
-	} else {
80
-		// Preparer l'appel de la fonction principale du squelette
81
-
82
-		spip_timer($a = 'calcul page ' . random_int(0, 1000));
83
-
84
-		// On cree un marqueur de notes unique lie a cette composition
85
-		// et on enregistre l'etat courant des globales de notes...
86
-		if (is_null($notes)) {
87
-			$notes = charger_fonction('notes', 'inc', true);
88
-		}
89
-		if ($notes) {
90
-			$notes('', 'empiler');
91
-		}
92
-
93
-		// Rajouter d'office ces deux parametres
94
-		// (mais vaudrait mieux que le compilateur sache le simuler
95
-		// car ca interdit l'usage de criteres conditionnels dessus).
96
-		if (!isset($contexte['date'])) {
97
-			$contexte['date'] = date('Y-m-d H:i:s');
98
-			$contexte['date_default'] = true;
99
-		} else {
100
-			$contexte['date'] = normaliser_date($contexte['date'], true);
101
-		}
102
-
103
-		if (!isset($contexte['date_redac'])) {
104
-			$contexte['date_redac'] = date('Y-m-d H:i:s');
105
-			$contexte['date_redac_default'] = true;
106
-		} else {
107
-			$contexte['date_redac'] = normaliser_date($contexte['date_redac'], true);
108
-		}
109
-
110
-		// Passer le nom du cache pour produire sa destruction automatique
111
-		try {
112
-			$page = $fonc(['cache' => $cache], [$contexte]);
113
-		} catch (Throwable $e) {
114
-			$msg = _T('zbug_erreur_execution_page') . " $sourcefile";
115
-			$full_msg = $msg . ' | File ' . $e->getFile() . ' Line ' . $e->getLine() . ' : ' . $e->getMessage();
116
-			$full_msg = str_replace(_ROOT_RACINE, '[…]/', $full_msg);
117
-			$corps = "<pre>$msg</pre>";
118
-			$page = analyse_resultat_skel($fond, ['cache' => $cache], $corps, $sourcefile);
119
-			erreur_squelette($full_msg);
120
-			unset($msg, $full_msg, $corps);
121
-		}
122
-
123
-		// Restituer les globales de notes telles qu'elles etaient avant l'appel
124
-		// Si l'inclus n'a pas affiche ses notes, tant pis (elles *doivent*
125
-		// etre dans son resultat, autrement elles ne seraient pas prises en
126
-		// compte a chaque calcul d'un texte contenant un modele, mais seulement
127
-		// quand le modele serait calcule, et on aurait des resultats incoherents)
128
-		if ($notes) {
129
-			$notes('', 'depiler');
130
-		}
131
-
132
-		// reinjecter en dynamique la pile des notes
133
-		// si il y a des inclure dynamiques
134
-		// si la pile n'est pas vide
135
-		// la generalisation de cette injection permettrait de corriger le point juste au dessus
136
-		// en faisant remonter les notes a l'incluant (A tester et valider avant application)
137
-		if ($notes) {
138
-			$page['notes'] = $notes('', 'sauver_etat');
139
-		}
140
-
141
-		// spip_log: un joli contexte
142
-		$infos = presenter_contexte(array_filter($contexte));
143
-
144
-		$profile = spip_timer($a);
145
-		spip_log("calcul ($profile) [$skel] $infos"
146
-			. ' (' . strlen($page['texte']) . ' octets)');
147
-
148
-		if (defined('_CALCUL_PROFILER') and intval($profile) > _CALCUL_PROFILER) {
149
-			spip_log("calcul ($profile) [$skel] $infos"
150
-				. ' (' . strlen($page['texte']) . ' octets) | ' . $_SERVER['REQUEST_URI'], 'profiler' . _LOG_AVERTISSEMENT);
151
-		}
152
-
153
-		if ($debug) {
154
-			// si c'est ce que demande le debusqueur, lui passer la main
155
-			$t = strlen($page['texte']) ? $page['texte'] : ' ';
156
-			$GLOBALS['debug_objets']['resultat'][$fonc . 'tout'] = $t;
157
-			$GLOBALS['debug_objets']['courant'] = $courant;
158
-			$GLOBALS['debug_objets']['profile'][$sourcefile] = $profile;
159
-			if (
160
-				$GLOBALS['debug_objets']['sourcefile']
161
-				and (_request('var_mode_objet') == $fonc)
162
-				and (_request('var_mode_affiche') == 'resultat')
163
-			) {
164
-				erreur_squelette();
165
-			}
166
-		}
167
-		// Si #CACHE{} n'etait pas la, le mettre a $delais
168
-		if (!isset($page['entetes']['X-Spip-Cache'])) {
169
-			// Dans l'espace prive ou dans un modeles/ on pose un cache 0 par defaut
170
-			// si aucun #CACHE{} spécifié
171
-			// le contexte implicite qui conditionne le cache assure qu'on retombe pas sur le meme
172
-			// entre public et prive
173
-			if (test_espace_prive() or strncmp($fond, 'modeles/', 8) == 0) {
174
-				$page['entetes']['X-Spip-Cache'] = 0;
175
-			} else {
176
-				$page['entetes']['X-Spip-Cache'] = $GLOBALS['delais'] ?? 36000;
177
-			}
178
-		}
179
-
180
-		$page['contexte'] = $contexte;
181
-
182
-		// faire remonter le fichier source
183
-		static $js_inclus = false;
184
-		if (defined('_VAR_INCLURE') and _VAR_INCLURE) {
185
-			$page['sourcefile'] = $sourcefile;
186
-			$page['texte'] =
187
-				"<div class='inclure_blocs'><h6>" . $page['sourcefile'] . '</h6>' . $page['texte'] . '</div>'
188
-				. ($js_inclus ? '' : "<script type='text/javascript'>jQuery(function(){jQuery('.inclure_blocs > h6:first-child').hover(function(){jQuery(this).parent().addClass('hover')},function(){jQuery(this).parent().removeClass('hover')})});</script>");
189
-			$js_inclus = true;
190
-		}
191
-
192
-		// Si un modele contenait #SESSION, on note l'info dans $page
193
-		if (isset($GLOBALS['cache_utilise_session'])) {
194
-			$page['invalideurs']['session'] = $GLOBALS['cache_utilise_session'];
195
-			unset($GLOBALS['cache_utilise_session']);
196
-		}
197
-	}
198
-
199
-	if ($select) {
200
-		lang_select();
201
-	}
202
-
203
-	return $page;
33
+    static $composer, $styliser, $notes = null;
34
+    $page = tester_redirection($fond, $contexte, $connect);
35
+    if ($page) {
36
+        return $page;
37
+    }
38
+
39
+    if (isset($contexte['lang'])) {
40
+        $lang = $contexte['lang'];
41
+    } elseif (!isset($lang)) {
42
+        $lang = $GLOBALS['meta']['langue_site'];
43
+    }
44
+
45
+    $select = ((!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang']) and $lang <> $GLOBALS['spip_lang']);
46
+    if ($select) {
47
+        $select = lang_select($lang);
48
+    }
49
+
50
+    $debug = (defined('_VAR_MODE') && _VAR_MODE == 'debug');
51
+
52
+    if (!$styliser) {
53
+        $styliser = charger_fonction('styliser', 'public');
54
+    }
55
+    [$skel, $mime_type, $gram, $sourcefile] =
56
+        $styliser($fond, $contexte, $GLOBALS['spip_lang'], $connect);
57
+
58
+    if ($skel) {
59
+        // sauver le nom de l'eventuel squelette en cours d'execution
60
+        // (recursion possible a cause des modeles)
61
+        if ($debug) {
62
+            $courant = $GLOBALS['debug_objets']['courant'] ?? null;
63
+            $GLOBALS['debug_objets']['contexte'][$sourcefile] = $contexte;
64
+        }
65
+
66
+        // charger le squelette en specifiant les langages cibles et source
67
+        // au cas il faudrait le compiler (source posterieure au resultat)
68
+
69
+        if (!$composer) {
70
+            $composer = charger_fonction('composer', 'public');
71
+        }
72
+        $fonc = $composer($skel, $mime_type, $gram, $sourcefile, $connect);
73
+    } else {
74
+        $fonc = '';
75
+    }
76
+
77
+    if (!$fonc) { // squelette inconnu (==='') ou faux (===false)
78
+        $page = $fonc;
79
+    } else {
80
+        // Preparer l'appel de la fonction principale du squelette
81
+
82
+        spip_timer($a = 'calcul page ' . random_int(0, 1000));
83
+
84
+        // On cree un marqueur de notes unique lie a cette composition
85
+        // et on enregistre l'etat courant des globales de notes...
86
+        if (is_null($notes)) {
87
+            $notes = charger_fonction('notes', 'inc', true);
88
+        }
89
+        if ($notes) {
90
+            $notes('', 'empiler');
91
+        }
92
+
93
+        // Rajouter d'office ces deux parametres
94
+        // (mais vaudrait mieux que le compilateur sache le simuler
95
+        // car ca interdit l'usage de criteres conditionnels dessus).
96
+        if (!isset($contexte['date'])) {
97
+            $contexte['date'] = date('Y-m-d H:i:s');
98
+            $contexte['date_default'] = true;
99
+        } else {
100
+            $contexte['date'] = normaliser_date($contexte['date'], true);
101
+        }
102
+
103
+        if (!isset($contexte['date_redac'])) {
104
+            $contexte['date_redac'] = date('Y-m-d H:i:s');
105
+            $contexte['date_redac_default'] = true;
106
+        } else {
107
+            $contexte['date_redac'] = normaliser_date($contexte['date_redac'], true);
108
+        }
109
+
110
+        // Passer le nom du cache pour produire sa destruction automatique
111
+        try {
112
+            $page = $fonc(['cache' => $cache], [$contexte]);
113
+        } catch (Throwable $e) {
114
+            $msg = _T('zbug_erreur_execution_page') . " $sourcefile";
115
+            $full_msg = $msg . ' | File ' . $e->getFile() . ' Line ' . $e->getLine() . ' : ' . $e->getMessage();
116
+            $full_msg = str_replace(_ROOT_RACINE, '[…]/', $full_msg);
117
+            $corps = "<pre>$msg</pre>";
118
+            $page = analyse_resultat_skel($fond, ['cache' => $cache], $corps, $sourcefile);
119
+            erreur_squelette($full_msg);
120
+            unset($msg, $full_msg, $corps);
121
+        }
122
+
123
+        // Restituer les globales de notes telles qu'elles etaient avant l'appel
124
+        // Si l'inclus n'a pas affiche ses notes, tant pis (elles *doivent*
125
+        // etre dans son resultat, autrement elles ne seraient pas prises en
126
+        // compte a chaque calcul d'un texte contenant un modele, mais seulement
127
+        // quand le modele serait calcule, et on aurait des resultats incoherents)
128
+        if ($notes) {
129
+            $notes('', 'depiler');
130
+        }
131
+
132
+        // reinjecter en dynamique la pile des notes
133
+        // si il y a des inclure dynamiques
134
+        // si la pile n'est pas vide
135
+        // la generalisation de cette injection permettrait de corriger le point juste au dessus
136
+        // en faisant remonter les notes a l'incluant (A tester et valider avant application)
137
+        if ($notes) {
138
+            $page['notes'] = $notes('', 'sauver_etat');
139
+        }
140
+
141
+        // spip_log: un joli contexte
142
+        $infos = presenter_contexte(array_filter($contexte));
143
+
144
+        $profile = spip_timer($a);
145
+        spip_log("calcul ($profile) [$skel] $infos"
146
+            . ' (' . strlen($page['texte']) . ' octets)');
147
+
148
+        if (defined('_CALCUL_PROFILER') and intval($profile) > _CALCUL_PROFILER) {
149
+            spip_log("calcul ($profile) [$skel] $infos"
150
+                . ' (' . strlen($page['texte']) . ' octets) | ' . $_SERVER['REQUEST_URI'], 'profiler' . _LOG_AVERTISSEMENT);
151
+        }
152
+
153
+        if ($debug) {
154
+            // si c'est ce que demande le debusqueur, lui passer la main
155
+            $t = strlen($page['texte']) ? $page['texte'] : ' ';
156
+            $GLOBALS['debug_objets']['resultat'][$fonc . 'tout'] = $t;
157
+            $GLOBALS['debug_objets']['courant'] = $courant;
158
+            $GLOBALS['debug_objets']['profile'][$sourcefile] = $profile;
159
+            if (
160
+                $GLOBALS['debug_objets']['sourcefile']
161
+                and (_request('var_mode_objet') == $fonc)
162
+                and (_request('var_mode_affiche') == 'resultat')
163
+            ) {
164
+                erreur_squelette();
165
+            }
166
+        }
167
+        // Si #CACHE{} n'etait pas la, le mettre a $delais
168
+        if (!isset($page['entetes']['X-Spip-Cache'])) {
169
+            // Dans l'espace prive ou dans un modeles/ on pose un cache 0 par defaut
170
+            // si aucun #CACHE{} spécifié
171
+            // le contexte implicite qui conditionne le cache assure qu'on retombe pas sur le meme
172
+            // entre public et prive
173
+            if (test_espace_prive() or strncmp($fond, 'modeles/', 8) == 0) {
174
+                $page['entetes']['X-Spip-Cache'] = 0;
175
+            } else {
176
+                $page['entetes']['X-Spip-Cache'] = $GLOBALS['delais'] ?? 36000;
177
+            }
178
+        }
179
+
180
+        $page['contexte'] = $contexte;
181
+
182
+        // faire remonter le fichier source
183
+        static $js_inclus = false;
184
+        if (defined('_VAR_INCLURE') and _VAR_INCLURE) {
185
+            $page['sourcefile'] = $sourcefile;
186
+            $page['texte'] =
187
+                "<div class='inclure_blocs'><h6>" . $page['sourcefile'] . '</h6>' . $page['texte'] . '</div>'
188
+                . ($js_inclus ? '' : "<script type='text/javascript'>jQuery(function(){jQuery('.inclure_blocs > h6:first-child').hover(function(){jQuery(this).parent().addClass('hover')},function(){jQuery(this).parent().removeClass('hover')})});</script>");
189
+            $js_inclus = true;
190
+        }
191
+
192
+        // Si un modele contenait #SESSION, on note l'info dans $page
193
+        if (isset($GLOBALS['cache_utilise_session'])) {
194
+            $page['invalideurs']['session'] = $GLOBALS['cache_utilise_session'];
195
+            unset($GLOBALS['cache_utilise_session']);
196
+        }
197
+    }
198
+
199
+    if ($select) {
200
+        lang_select();
201
+    }
202
+
203
+    return $page;
204 204
 }
205 205
 
206 206
 /**
@@ -209,37 +209,37 @@  discard block
 block discarded – undo
209 209
  * @return string
210 210
 */
211 211
 function presenter_contexte($contexte, $profondeur_max = 1, $max_lines = 0) {
212
-	$infos = [];
213
-	$line = 0;
214
-	foreach ($contexte as $var => $val) {
215
-		$line++;
216
-		if ($max_lines and $max_lines < $line) {
217
-			$infos[] = '…';
218
-			break;
219
-		}
220
-		if ($val === null) {
221
-			$val = '';
222
-		} elseif (is_array($val)) {
223
-			if ($profondeur_max > 0) {
224
-				$val = 'array:' . count($val) . '(' . presenter_contexte($val, $profondeur_max - 1, 3) . ')';
225
-			} else {
226
-				$val = 'array:' . count($val);
227
-			}
228
-		} elseif (is_object($val)) {
229
-			$val = get_class($val);
230
-		} elseif (strlen("$val") > 30) {
231
-			$val = substr("$val", 0, 29) . '…';
232
-			if (strstr($val, ' ')) {
233
-				$val = "'$val'";
234
-			}
235
-		} elseif (strstr($val, ' ')) {
236
-			$val = "'$val'";
237
-		} elseif (!strlen($val)) {
238
-			$val = "''";
239
-		}
240
-		$infos[] = $var . '=' . $val;
241
-	}
242
-	return join(', ', $infos);
212
+    $infos = [];
213
+    $line = 0;
214
+    foreach ($contexte as $var => $val) {
215
+        $line++;
216
+        if ($max_lines and $max_lines < $line) {
217
+            $infos[] = '…';
218
+            break;
219
+        }
220
+        if ($val === null) {
221
+            $val = '';
222
+        } elseif (is_array($val)) {
223
+            if ($profondeur_max > 0) {
224
+                $val = 'array:' . count($val) . '(' . presenter_contexte($val, $profondeur_max - 1, 3) . ')';
225
+            } else {
226
+                $val = 'array:' . count($val);
227
+            }
228
+        } elseif (is_object($val)) {
229
+            $val = get_class($val);
230
+        } elseif (strlen("$val") > 30) {
231
+            $val = substr("$val", 0, 29) . '…';
232
+            if (strstr($val, ' ')) {
233
+                $val = "'$val'";
234
+            }
235
+        } elseif (strstr($val, ' ')) {
236
+            $val = "'$val'";
237
+        } elseif (!strlen($val)) {
238
+            $val = "''";
239
+        }
240
+        $infos[] = $var . '=' . $val;
241
+    }
242
+    return join(', ', $infos);
243 243
 }
244 244
 
245 245
 
@@ -256,11 +256,11 @@  discard block
 block discarded – undo
256 256
  * @return array|bool
257 257
  */
258 258
 function tester_redirection($fond, $contexte, $connect) {
259
-	static $tester_redirection = null;
260
-	if (is_null($tester_redirection)) {
261
-		$tester_redirection = charger_fonction('tester_redirection', 'public');
262
-	}
263
-	return $tester_redirection($fond, $contexte, $connect);
259
+    static $tester_redirection = null;
260
+    if (is_null($tester_redirection)) {
261
+        $tester_redirection = charger_fonction('tester_redirection', 'public');
262
+    }
263
+    return $tester_redirection($fond, $contexte, $connect);
264 264
 }
265 265
 
266 266
 
@@ -276,42 +276,42 @@  discard block
 block discarded – undo
276 276
  * @return array|bool
277 277
  */
278 278
 function public_tester_redirection_dist($fond, $contexte, $connect) {
279
-	if (
280
-		$fond == 'article'
281
-		and !empty($contexte['id_article'])
282
-		and $id_article = intval($contexte['id_article'])
283
-	) {
284
-		include_spip('public/quete'); // pour quete_virtuel et ses dependances
285
-		$m = quete_virtuel($id_article, $connect) ?? '';
286
-		if (strlen($m)) {
287
-			include_spip('inc/texte');
288
-			// les navigateurs pataugent si l'URL est vide
289
-			if ($url = virtuel_redirige($m, true)) {
290
-				// passer en url absolue car cette redirection pourra
291
-				// etre utilisee dans un contexte d'url qui change
292
-				// y compris url arbo
293
-				$status = 302;
294
-				if (defined('_STATUS_REDIRECTION_VIRTUEL')) {
295
-					$status = _STATUS_REDIRECTION_VIRTUEL;
296
-				}
297
-				if (!preg_match(',^\w+:,', $url)) {
298
-					include_spip('inc/filtres_mini');
299
-					$url = url_absolue($url);
300
-				}
301
-				$url = str_replace('&amp;', '&', $url);
302
-
303
-				return [
304
-					'texte' => '<'
305
-						. "?php include_spip('inc/headers');redirige_par_entete('"
306
-						. texte_script($url)
307
-						. "','',$status);"
308
-						. '?' . '>',
309
-					'process_ins' => 'php',
310
-					'status' => $status
311
-				];
312
-			}
313
-		}
314
-	}
315
-
316
-	return false;
279
+    if (
280
+        $fond == 'article'
281
+        and !empty($contexte['id_article'])
282
+        and $id_article = intval($contexte['id_article'])
283
+    ) {
284
+        include_spip('public/quete'); // pour quete_virtuel et ses dependances
285
+        $m = quete_virtuel($id_article, $connect) ?? '';
286
+        if (strlen($m)) {
287
+            include_spip('inc/texte');
288
+            // les navigateurs pataugent si l'URL est vide
289
+            if ($url = virtuel_redirige($m, true)) {
290
+                // passer en url absolue car cette redirection pourra
291
+                // etre utilisee dans un contexte d'url qui change
292
+                // y compris url arbo
293
+                $status = 302;
294
+                if (defined('_STATUS_REDIRECTION_VIRTUEL')) {
295
+                    $status = _STATUS_REDIRECTION_VIRTUEL;
296
+                }
297
+                if (!preg_match(',^\w+:,', $url)) {
298
+                    include_spip('inc/filtres_mini');
299
+                    $url = url_absolue($url);
300
+                }
301
+                $url = str_replace('&amp;', '&', $url);
302
+
303
+                return [
304
+                    'texte' => '<'
305
+                        . "?php include_spip('inc/headers');redirige_par_entete('"
306
+                        . texte_script($url)
307
+                        . "','',$status);"
308
+                        . '?' . '>',
309
+                    'process_ins' => 'php',
310
+                    'status' => $status
311
+                ];
312
+            }
313
+        }
314
+    }
315
+
316
+    return false;
317 317
 }
Please login to merge, or discard this patch.
ecrire/inc/queue.php 1 patch
Indentation   +476 added lines, -476 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Queue
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 define('_JQ_SCHEDULED', 1);
@@ -50,103 +50,103 @@  discard block
 block discarded – undo
50 50
  *  id of job
51 51
  */
52 52
 function queue_add_job(
53
-	$function,
54
-	$description,
55
-	$arguments = [],
56
-	$file = '',
57
-	$no_duplicate = false,
58
-	$time = 0,
59
-	$priority = 0
53
+    $function,
54
+    $description,
55
+    $arguments = [],
56
+    $file = '',
57
+    $no_duplicate = false,
58
+    $time = 0,
59
+    $priority = 0
60 60
 ) {
61
-	include_spip('base/abstract_sql');
62
-
63
-	// cas pourri de ecrire/action/editer_site avec l'option reload=oui
64
-	if (defined('_GENIE_SYNDIC_NOW')) {
65
-		$arguments['id_syndic'] = _GENIE_SYNDIC_NOW;
66
-	}
67
-
68
-	// serialiser les arguments
69
-	$arguments = serialize($arguments);
70
-	$md5args = md5($arguments);
71
-
72
-	// si pas de date programee, des que possible
73
-	$duplicate_where = 'status=' . intval(_JQ_SCHEDULED) . ' AND ';
74
-	if (!$time) {
75
-		$time = time();
76
-		$duplicate_where = ''; // ne pas dupliquer si deja le meme job en cours d'execution
77
-	}
78
-	$date = date('Y-m-d H:i:s', $time);
79
-
80
-	$set_job = [
81
-		'fonction' => $function,
82
-		'descriptif' => $description,
83
-		'args' => $arguments,
84
-		'md5args' => $md5args,
85
-		'inclure' => $file,
86
-		'priorite' => max(-10, min(10, intval($priority))),
87
-		'date' => $date,
88
-		'status' => _JQ_SCHEDULED,
89
-	];
90
-	// si option ne pas dupliquer, regarder si la fonction existe deja
91
-	// avec les memes args et file
92
-	if (
93
-		$no_duplicate
94
-		and
95
-		$id_job = sql_getfetsel(
96
-			'id_job',
97
-			'spip_jobs',
98
-			$duplicate_where =
99
-				$duplicate_where . 'fonction=' . sql_quote($function)
100
-				. (($no_duplicate === 'function_only') ? '' :
101
-			' AND md5args=' . sql_quote($md5args) . ' AND inclure=' . sql_quote($file))
102
-		)
103
-	) {
104
-		return $id_job;
105
-	}
106
-
107
-	$id_job = sql_insertq('spip_jobs', $set_job);
108
-	// en cas de concurrence, deux process peuvent arriver jusqu'ici en parallele
109
-	// avec le meme job unique a inserer. Dans ce cas, celui qui a eu l'id le plus grand
110
-	// doit s'effacer
111
-	if (
112
-		$no_duplicate
113
-		and
114
-		$id_prev = sql_getfetsel('id_job', 'spip_jobs', 'id_job<' . intval($id_job) . " AND $duplicate_where")
115
-	) {
116
-		sql_delete('spip_jobs', 'id_job=' . intval($id_job));
117
-
118
-		return $id_prev;
119
-	}
120
-
121
-	// verifier la non duplication qui peut etre problematique en cas de concurence
122
-	// il faut dans ce cas que seul le dernier ajoute se supprime !
123
-
124
-	// une option de debug pour verifier que les arguments en base sont bons
125
-	// ie cas d'un char non acceptables sur certains type de champs
126
-	// qui coupe la valeur
127
-	if (defined('_JQ_INSERT_CHECK_ARGS') and $id_job) {
128
-		$args = sql_getfetsel('args', 'spip_jobs', 'id_job=' . intval($id_job));
129
-		if ($args !== $arguments) {
130
-			spip_log('arguments job errones / longueur ' . strlen($args) . ' vs ' . strlen($arguments) . ' / valeur : ' . var_export(
131
-				$arguments,
132
-				true
133
-			), 'queue');
134
-		}
135
-	}
136
-
137
-	if ($id_job) {
138
-		queue_update_next_job_time($time);
139
-	}
140
-	// si la mise en file d'attente du job echoue,
141
-	// il ne faut pas perdre l'execution de la fonction
142
-	// on la lance immediatement, c'est un fallback
143
-	// sauf en cas d'upgrade necessaire (table spip_jobs inexistante)
144
-	elseif ($GLOBALS['meta']['version_installee'] == $GLOBALS['spip_version_base']) {
145
-		$set_job['id_job'] = 0;
146
-		queue_start_job($set_job);
147
-	}
148
-
149
-	return $id_job;
61
+    include_spip('base/abstract_sql');
62
+
63
+    // cas pourri de ecrire/action/editer_site avec l'option reload=oui
64
+    if (defined('_GENIE_SYNDIC_NOW')) {
65
+        $arguments['id_syndic'] = _GENIE_SYNDIC_NOW;
66
+    }
67
+
68
+    // serialiser les arguments
69
+    $arguments = serialize($arguments);
70
+    $md5args = md5($arguments);
71
+
72
+    // si pas de date programee, des que possible
73
+    $duplicate_where = 'status=' . intval(_JQ_SCHEDULED) . ' AND ';
74
+    if (!$time) {
75
+        $time = time();
76
+        $duplicate_where = ''; // ne pas dupliquer si deja le meme job en cours d'execution
77
+    }
78
+    $date = date('Y-m-d H:i:s', $time);
79
+
80
+    $set_job = [
81
+        'fonction' => $function,
82
+        'descriptif' => $description,
83
+        'args' => $arguments,
84
+        'md5args' => $md5args,
85
+        'inclure' => $file,
86
+        'priorite' => max(-10, min(10, intval($priority))),
87
+        'date' => $date,
88
+        'status' => _JQ_SCHEDULED,
89
+    ];
90
+    // si option ne pas dupliquer, regarder si la fonction existe deja
91
+    // avec les memes args et file
92
+    if (
93
+        $no_duplicate
94
+        and
95
+        $id_job = sql_getfetsel(
96
+            'id_job',
97
+            'spip_jobs',
98
+            $duplicate_where =
99
+                $duplicate_where . 'fonction=' . sql_quote($function)
100
+                . (($no_duplicate === 'function_only') ? '' :
101
+            ' AND md5args=' . sql_quote($md5args) . ' AND inclure=' . sql_quote($file))
102
+        )
103
+    ) {
104
+        return $id_job;
105
+    }
106
+
107
+    $id_job = sql_insertq('spip_jobs', $set_job);
108
+    // en cas de concurrence, deux process peuvent arriver jusqu'ici en parallele
109
+    // avec le meme job unique a inserer. Dans ce cas, celui qui a eu l'id le plus grand
110
+    // doit s'effacer
111
+    if (
112
+        $no_duplicate
113
+        and
114
+        $id_prev = sql_getfetsel('id_job', 'spip_jobs', 'id_job<' . intval($id_job) . " AND $duplicate_where")
115
+    ) {
116
+        sql_delete('spip_jobs', 'id_job=' . intval($id_job));
117
+
118
+        return $id_prev;
119
+    }
120
+
121
+    // verifier la non duplication qui peut etre problematique en cas de concurence
122
+    // il faut dans ce cas que seul le dernier ajoute se supprime !
123
+
124
+    // une option de debug pour verifier que les arguments en base sont bons
125
+    // ie cas d'un char non acceptables sur certains type de champs
126
+    // qui coupe la valeur
127
+    if (defined('_JQ_INSERT_CHECK_ARGS') and $id_job) {
128
+        $args = sql_getfetsel('args', 'spip_jobs', 'id_job=' . intval($id_job));
129
+        if ($args !== $arguments) {
130
+            spip_log('arguments job errones / longueur ' . strlen($args) . ' vs ' . strlen($arguments) . ' / valeur : ' . var_export(
131
+                $arguments,
132
+                true
133
+            ), 'queue');
134
+        }
135
+    }
136
+
137
+    if ($id_job) {
138
+        queue_update_next_job_time($time);
139
+    }
140
+    // si la mise en file d'attente du job echoue,
141
+    // il ne faut pas perdre l'execution de la fonction
142
+    // on la lance immediatement, c'est un fallback
143
+    // sauf en cas d'upgrade necessaire (table spip_jobs inexistante)
144
+    elseif ($GLOBALS['meta']['version_installee'] == $GLOBALS['spip_version_base']) {
145
+        $set_job['id_job'] = 0;
146
+        queue_start_job($set_job);
147
+    }
148
+
149
+    return $id_job;
150 150
 }
151 151
 
152 152
 /**
@@ -155,11 +155,11 @@  discard block
 block discarded – undo
155 155
  * @return void
156 156
  */
157 157
 function queue_purger() {
158
-	include_spip('base/abstract_sql');
159
-	sql_delete('spip_jobs');
160
-	sql_delete('spip_jobs_liens', 'id_job NOT IN (' . sql_get_select('id_job', 'spip_jobs') . ')');
161
-	include_spip('inc/genie');
162
-	genie_queue_watch_dist();
158
+    include_spip('base/abstract_sql');
159
+    sql_delete('spip_jobs');
160
+    sql_delete('spip_jobs_liens', 'id_job NOT IN (' . sql_get_select('id_job', 'spip_jobs') . ')');
161
+    include_spip('inc/genie');
162
+    genie_queue_watch_dist();
163 163
 }
164 164
 
165 165
 /**
@@ -170,25 +170,25 @@  discard block
 block discarded – undo
170 170
  * @return int|bool
171 171
  */
172 172
 function queue_remove_job($id_job) {
173
-	include_spip('base/abstract_sql');
174
-
175
-	if (
176
-		$row = sql_fetsel('fonction,inclure,date', 'spip_jobs', 'id_job=' . intval($id_job))
177
-		and $res = sql_delete('spip_jobs', 'id_job=' . intval($id_job))
178
-	) {
179
-		queue_unlink_job($id_job);
180
-		// est-ce une tache cron qu'il faut relancer ?
181
-		if ($periode = queue_is_cron_job($row['fonction'], $row['inclure'])) {
182
-			// relancer avec les nouveaux arguments de temps
183
-			include_spip('inc/genie');
184
-			// relancer avec la periode prevue
185
-			queue_genie_replan_job($row['fonction'], $periode, strtotime($row['date']));
186
-		}
187
-		queue_update_next_job_time();
188
-		return $res;
189
-	}
190
-
191
-	return false;
173
+    include_spip('base/abstract_sql');
174
+
175
+    if (
176
+        $row = sql_fetsel('fonction,inclure,date', 'spip_jobs', 'id_job=' . intval($id_job))
177
+        and $res = sql_delete('spip_jobs', 'id_job=' . intval($id_job))
178
+    ) {
179
+        queue_unlink_job($id_job);
180
+        // est-ce une tache cron qu'il faut relancer ?
181
+        if ($periode = queue_is_cron_job($row['fonction'], $row['inclure'])) {
182
+            // relancer avec les nouveaux arguments de temps
183
+            include_spip('inc/genie');
184
+            // relancer avec la periode prevue
185
+            queue_genie_replan_job($row['fonction'], $periode, strtotime($row['date']));
186
+        }
187
+        queue_update_next_job_time();
188
+        return $res;
189
+    }
190
+
191
+    return false;
192 192
 }
193 193
 
194 194
 /**
@@ -201,18 +201,18 @@  discard block
 block discarded – undo
201 201
  *  ou un tableau composé de tableaux simples pour lieur plusieurs objets en une fois
202 202
  */
203 203
 function queue_link_job($id_job, $objets) {
204
-	include_spip('base/abstract_sql');
205
-
206
-	if (is_array($objets) and count($objets)) {
207
-		if (is_array(reset($objets))) {
208
-			foreach ($objets as $k => $o) {
209
-				$objets[$k]['id_job'] = $id_job;
210
-			}
211
-			sql_insertq_multi('spip_jobs_liens', $objets);
212
-		} else {
213
-			sql_insertq('spip_jobs_liens', array_merge(['id_job' => $id_job], $objets));
214
-		}
215
-	}
204
+    include_spip('base/abstract_sql');
205
+
206
+    if (is_array($objets) and count($objets)) {
207
+        if (is_array(reset($objets))) {
208
+            foreach ($objets as $k => $o) {
209
+                $objets[$k]['id_job'] = $id_job;
210
+            }
211
+            sql_insertq_multi('spip_jobs_liens', $objets);
212
+        } else {
213
+            sql_insertq('spip_jobs_liens', array_merge(['id_job' => $id_job], $objets));
214
+        }
215
+    }
216 216
 }
217 217
 
218 218
 /**
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
  *  resultat du sql_delete
225 225
  */
226 226
 function queue_unlink_job($id_job) {
227
-	return sql_delete('spip_jobs_liens', 'id_job=' . intval($id_job));
227
+    return sql_delete('spip_jobs_liens', 'id_job=' . intval($id_job));
228 228
 }
229 229
 
230 230
 /**
@@ -237,36 +237,36 @@  discard block
 block discarded – undo
237 237
  */
238 238
 function queue_start_job($row) {
239 239
 
240
-	// deserialiser les arguments
241
-	$args = unserialize($row['args']);
242
-	if (!is_array($args)) {
243
-		spip_log('arguments job errones ' . var_export($row, true), 'queue');
244
-		$args = [];
245
-	}
246
-
247
-	$fonction = $row['fonction'];
248
-	if (strlen($inclure = trim($row['inclure']))) {
249
-		if (substr($inclure, -1) == '/') { // c'est un chemin pour charger_fonction
250
-			$f = charger_fonction($fonction, rtrim($inclure, '/'), false);
251
-			if ($f) {
252
-				$fonction = $f;
253
-			}
254
-		} else {
255
-			include_spip($inclure);
256
-		}
257
-	}
258
-
259
-	if (!function_exists($fonction)) {
260
-		spip_log("fonction $fonction ($inclure) inexistante " . var_export($row, true), 'queue');
261
-
262
-		return false;
263
-	}
264
-
265
-	spip_log('queue [' . $row['id_job'] . "]: $fonction() start", 'queue');
266
-	$res = $fonction(...$args);
267
-	spip_log('queue [' . $row['id_job'] . "]: $fonction() end", 'queue');
268
-
269
-	return $res;
240
+    // deserialiser les arguments
241
+    $args = unserialize($row['args']);
242
+    if (!is_array($args)) {
243
+        spip_log('arguments job errones ' . var_export($row, true), 'queue');
244
+        $args = [];
245
+    }
246
+
247
+    $fonction = $row['fonction'];
248
+    if (strlen($inclure = trim($row['inclure']))) {
249
+        if (substr($inclure, -1) == '/') { // c'est un chemin pour charger_fonction
250
+            $f = charger_fonction($fonction, rtrim($inclure, '/'), false);
251
+            if ($f) {
252
+                $fonction = $f;
253
+            }
254
+        } else {
255
+            include_spip($inclure);
256
+        }
257
+    }
258
+
259
+    if (!function_exists($fonction)) {
260
+        spip_log("fonction $fonction ($inclure) inexistante " . var_export($row, true), 'queue');
261
+
262
+        return false;
263
+    }
264
+
265
+    spip_log('queue [' . $row['id_job'] . "]: $fonction() start", 'queue');
266
+    $res = $fonction(...$args);
267
+    spip_log('queue [' . $row['id_job'] . "]: $fonction() end", 'queue');
268
+
269
+    return $res;
270 270
 }
271 271
 
272 272
 /**
@@ -293,89 +293,89 @@  discard block
 block discarded – undo
293 293
  *     - true : une planification a été faite.
294 294
  */
295 295
 function queue_schedule($force_jobs = null) {
296
-	$time = time();
297
-	if (defined('_DEBUG_BLOCK_QUEUE')) {
298
-		spip_log('_DEBUG_BLOCK_QUEUE : schedule stop', 'jq' . _LOG_DEBUG);
299
-
300
-		return;
301
-	}
302
-
303
-	// rien a faire si le prochain job est encore dans le futur
304
-	if (queue_sleep_time_to_next_job() > 0 and (!$force_jobs or !count($force_jobs))) {
305
-		spip_log('queue_sleep_time_to_next_job', 'jq' . _LOG_DEBUG);
306
-
307
-		return;
308
-	}
309
-
310
-	include_spip('base/abstract_sql');
311
-	// on ne peut rien faire si pas de connexion SQL
312
-	if (!spip_connect()) {
313
-		return false;
314
-	}
315
-
316
-	if (!defined('_JQ_MAX_JOBS_TIME_TO_EXECUTE')) {
317
-		$max_time = ini_get('max_execution_time') / 2;
318
-		// valeur conservatrice si on a pas reussi a lire le max_execution_time
319
-		if (!$max_time) {
320
-			$max_time = 5;
321
-		}
322
-		define('_JQ_MAX_JOBS_TIME_TO_EXECUTE', min($max_time, 15)); // une valeur maxi en temps.
323
-	}
324
-	$end_time = $time + _JQ_MAX_JOBS_TIME_TO_EXECUTE;
325
-
326
-	spip_log("JQ schedule $time / $end_time", 'jq' . _LOG_DEBUG);
327
-
328
-	if (!defined('_JQ_MAX_JOBS_EXECUTE')) {
329
-		define('_JQ_MAX_JOBS_EXECUTE', 200);
330
-	}
331
-	$nbj = 0;
332
-	// attraper les jobs
333
-	// dont la date est passee (echus en attente),
334
-	// par ordre :
335
-	//	- de priorite
336
-	//	- de date
337
-	// lorsqu'un job cron n'a pas fini, sa priorite est descendue
338
-	// pour qu'il ne bloque pas les autres jobs en attente
339
-	if (is_array($force_jobs) and count($force_jobs)) {
340
-		$cond = 'status=' . intval(_JQ_SCHEDULED) . ' AND ' . sql_in('id_job', $force_jobs);
341
-	} else {
342
-		$now = date('Y-m-d H:i:s', $time);
343
-		$cond = 'status=' . intval(_JQ_SCHEDULED) . ' AND date<=' . sql_quote($now);
344
-	}
345
-
346
-	register_shutdown_function('queue_error_handler'); // recuperer les erreurs auant que possible
347
-	$res = sql_allfetsel('*', 'spip_jobs', $cond, '', 'priorite DESC,date', '0,' . (_JQ_MAX_JOBS_EXECUTE + 1));
348
-	do {
349
-		if ($row = array_shift($res)) {
350
-			$nbj++;
351
-			// il faut un verrou, a base de sql_delete
352
-			if (sql_delete('spip_jobs', 'id_job=' . intval($row['id_job']) . ' AND status=' . intval(_JQ_SCHEDULED))) {
353
-				#spip_log("JQ schedule job ".$nbj." OK",'jq');
354
-				// on reinsert dans la base aussitot avec un status=_JQ_PENDING
355
-				$row['status'] = _JQ_PENDING;
356
-				$row['date'] = date('Y-m-d H:i:s', $time);
357
-				sql_insertq('spip_jobs', $row);
358
-
359
-				// on a la main sur le job :
360
-				// l'executer
361
-				$result = queue_start_job($row);
362
-
363
-				$time = time();
364
-				queue_close_job($row, $time, $result);
365
-			}
366
-		}
367
-		spip_log('JQ schedule job end time ' . $time, 'jq' . _LOG_DEBUG);
368
-	} while ($nbj < _JQ_MAX_JOBS_EXECUTE and $row and $time < $end_time);
369
-	spip_log('JQ schedule end time ' . time(), 'jq' . _LOG_DEBUG);
370
-
371
-	if ($row = array_shift($res)) {
372
-		queue_update_next_job_time(0); // on sait qu'il y a encore des jobs a lancer ASAP
373
-		spip_log('JQ encore !', 'jq' . _LOG_DEBUG);
374
-	} else {
375
-		queue_update_next_job_time();
376
-	}
377
-
378
-	return true;
296
+    $time = time();
297
+    if (defined('_DEBUG_BLOCK_QUEUE')) {
298
+        spip_log('_DEBUG_BLOCK_QUEUE : schedule stop', 'jq' . _LOG_DEBUG);
299
+
300
+        return;
301
+    }
302
+
303
+    // rien a faire si le prochain job est encore dans le futur
304
+    if (queue_sleep_time_to_next_job() > 0 and (!$force_jobs or !count($force_jobs))) {
305
+        spip_log('queue_sleep_time_to_next_job', 'jq' . _LOG_DEBUG);
306
+
307
+        return;
308
+    }
309
+
310
+    include_spip('base/abstract_sql');
311
+    // on ne peut rien faire si pas de connexion SQL
312
+    if (!spip_connect()) {
313
+        return false;
314
+    }
315
+
316
+    if (!defined('_JQ_MAX_JOBS_TIME_TO_EXECUTE')) {
317
+        $max_time = ini_get('max_execution_time') / 2;
318
+        // valeur conservatrice si on a pas reussi a lire le max_execution_time
319
+        if (!$max_time) {
320
+            $max_time = 5;
321
+        }
322
+        define('_JQ_MAX_JOBS_TIME_TO_EXECUTE', min($max_time, 15)); // une valeur maxi en temps.
323
+    }
324
+    $end_time = $time + _JQ_MAX_JOBS_TIME_TO_EXECUTE;
325
+
326
+    spip_log("JQ schedule $time / $end_time", 'jq' . _LOG_DEBUG);
327
+
328
+    if (!defined('_JQ_MAX_JOBS_EXECUTE')) {
329
+        define('_JQ_MAX_JOBS_EXECUTE', 200);
330
+    }
331
+    $nbj = 0;
332
+    // attraper les jobs
333
+    // dont la date est passee (echus en attente),
334
+    // par ordre :
335
+    //	- de priorite
336
+    //	- de date
337
+    // lorsqu'un job cron n'a pas fini, sa priorite est descendue
338
+    // pour qu'il ne bloque pas les autres jobs en attente
339
+    if (is_array($force_jobs) and count($force_jobs)) {
340
+        $cond = 'status=' . intval(_JQ_SCHEDULED) . ' AND ' . sql_in('id_job', $force_jobs);
341
+    } else {
342
+        $now = date('Y-m-d H:i:s', $time);
343
+        $cond = 'status=' . intval(_JQ_SCHEDULED) . ' AND date<=' . sql_quote($now);
344
+    }
345
+
346
+    register_shutdown_function('queue_error_handler'); // recuperer les erreurs auant que possible
347
+    $res = sql_allfetsel('*', 'spip_jobs', $cond, '', 'priorite DESC,date', '0,' . (_JQ_MAX_JOBS_EXECUTE + 1));
348
+    do {
349
+        if ($row = array_shift($res)) {
350
+            $nbj++;
351
+            // il faut un verrou, a base de sql_delete
352
+            if (sql_delete('spip_jobs', 'id_job=' . intval($row['id_job']) . ' AND status=' . intval(_JQ_SCHEDULED))) {
353
+                #spip_log("JQ schedule job ".$nbj." OK",'jq');
354
+                // on reinsert dans la base aussitot avec un status=_JQ_PENDING
355
+                $row['status'] = _JQ_PENDING;
356
+                $row['date'] = date('Y-m-d H:i:s', $time);
357
+                sql_insertq('spip_jobs', $row);
358
+
359
+                // on a la main sur le job :
360
+                // l'executer
361
+                $result = queue_start_job($row);
362
+
363
+                $time = time();
364
+                queue_close_job($row, $time, $result);
365
+            }
366
+        }
367
+        spip_log('JQ schedule job end time ' . $time, 'jq' . _LOG_DEBUG);
368
+    } while ($nbj < _JQ_MAX_JOBS_EXECUTE and $row and $time < $end_time);
369
+    spip_log('JQ schedule end time ' . time(), 'jq' . _LOG_DEBUG);
370
+
371
+    if ($row = array_shift($res)) {
372
+        queue_update_next_job_time(0); // on sait qu'il y a encore des jobs a lancer ASAP
373
+        spip_log('JQ encore !', 'jq' . _LOG_DEBUG);
374
+    } else {
375
+        queue_update_next_job_time();
376
+    }
377
+
378
+    return true;
379 379
 }
380 380
 
381 381
 /**
@@ -393,21 +393,21 @@  discard block
 block discarded – undo
393 393
  * @param int $result
394 394
  */
395 395
 function queue_close_job(&$row, $time, $result = 0) {
396
-	// est-ce une tache cron qu'il faut relancer ?
397
-	if ($periode = queue_is_cron_job($row['fonction'], $row['inclure'])) {
398
-		// relancer avec les nouveaux arguments de temps
399
-		include_spip('inc/genie');
400
-		if ($result < 0) { // relancer tout de suite, mais en baissant la priorite
401
-		queue_genie_replan_job($row['fonction'], $periode, 0 - $result, null, $row['priorite'] - 1);
402
-		} else // relancer avec la periode prevue
403
-		{
404
-			queue_genie_replan_job($row['fonction'], $periode, $time);
405
-		}
406
-	}
407
-	// purger ses liens eventuels avec des objets
408
-	sql_delete('spip_jobs_liens', 'id_job=' . intval($row['id_job']));
409
-	// supprimer le job fini
410
-	sql_delete('spip_jobs', 'id_job=' . intval($row['id_job']));
396
+    // est-ce une tache cron qu'il faut relancer ?
397
+    if ($periode = queue_is_cron_job($row['fonction'], $row['inclure'])) {
398
+        // relancer avec les nouveaux arguments de temps
399
+        include_spip('inc/genie');
400
+        if ($result < 0) { // relancer tout de suite, mais en baissant la priorite
401
+        queue_genie_replan_job($row['fonction'], $periode, 0 - $result, null, $row['priorite'] - 1);
402
+        } else // relancer avec la periode prevue
403
+        {
404
+            queue_genie_replan_job($row['fonction'], $periode, $time);
405
+        }
406
+    }
407
+    // purger ses liens eventuels avec des objets
408
+    sql_delete('spip_jobs_liens', 'id_job=' . intval($row['id_job']));
409
+    // supprimer le job fini
410
+    sql_delete('spip_jobs', 'id_job=' . intval($row['id_job']));
411 411
 }
412 412
 
413 413
 /**
@@ -417,10 +417,10 @@  discard block
 block discarded – undo
417 417
  * @uses queue_update_next_job_time()
418 418
  */
419 419
 function queue_error_handler() {
420
-	// se remettre dans le bon dossier, car Apache le change parfois (toujours?)
421
-	chdir(_ROOT_CWD);
420
+    // se remettre dans le bon dossier, car Apache le change parfois (toujours?)
421
+    chdir(_ROOT_CWD);
422 422
 
423
-	queue_update_next_job_time();
423
+    queue_update_next_job_time();
424 424
 }
425 425
 
426 426
 
@@ -437,18 +437,18 @@  discard block
 block discarded – undo
437 437
  *     Périodicité de la tâche en secondes, si tâche périodique, sinon false.
438 438
  */
439 439
 function queue_is_cron_job($function, $inclure) {
440
-	static $taches = null;
441
-	if (strncmp($inclure, 'genie/', 6) == 0) {
442
-		if (is_null($taches)) {
443
-			include_spip('inc/genie');
444
-			$taches = taches_generales();
445
-		}
446
-		if (isset($taches[$function])) {
447
-			return $taches[$function];
448
-		}
449
-	}
450
-
451
-	return false;
440
+    static $taches = null;
441
+    if (strncmp($inclure, 'genie/', 6) == 0) {
442
+        if (is_null($taches)) {
443
+            include_spip('inc/genie');
444
+            $taches = taches_generales();
445
+        }
446
+        if (isset($taches[$function])) {
447
+            return $taches[$function];
448
+        }
449
+    }
450
+
451
+    return false;
452 452
 }
453 453
 
454 454
 /**
@@ -462,62 +462,62 @@  discard block
 block discarded – undo
462 462
  *  temps de la tache ajoutee ou 0 pour ASAP
463 463
  */
464 464
 function queue_update_next_job_time($next_time = null) {
465
-	static $nb_jobs_scheduled = null;
466
-	static $deja_la = false;
467
-	// prendre le min des $next_time que l'on voit passer ici, en cas de reentrance
468
-	static $next = null;
469
-	// queue_close_job peut etre reentrant ici
470
-	if ($deja_la) {
471
-		return;
472
-	}
473
-	$deja_la = true;
474
-
475
-	include_spip('base/abstract_sql');
476
-	$time = time();
477
-
478
-	// traiter les jobs morts au combat (_JQ_PENDING depuis plus de 180s)
479
-	// pour cause de timeout ou autre erreur fatale
480
-	$res = sql_allfetsel(
481
-		'*',
482
-		'spip_jobs',
483
-		'status=' . intval(_JQ_PENDING) . ' AND date<' . sql_quote(date('Y-m-d H:i:s', $time - 180))
484
-	);
485
-	if (is_array($res)) {
486
-		foreach ($res as $row) {
487
-			queue_close_job($row, $time);
488
-			spip_log('queue_close_job car _JQ_PENDING depuis +180s : ' . print_r($row, 1), 'job_mort' . _LOG_ERREUR);
489
-		}
490
-	}
491
-
492
-	// chercher la date du prochain job si pas connu
493
-	if (is_null($next) or is_null(queue_sleep_time_to_next_job())) {
494
-		$date = sql_getfetsel('date', 'spip_jobs', 'status=' . intval(_JQ_SCHEDULED), '', 'date', '0,1');
495
-		$next = strtotime($date);
496
-	}
497
-	if (!is_null($next_time)) {
498
-		if (is_null($next) or $next > $next_time) {
499
-			$next = $next_time;
500
-		}
501
-	}
502
-
503
-	if ($next) {
504
-		if (is_null($nb_jobs_scheduled)) {
505
-			$nb_jobs_scheduled = sql_countsel(
506
-				'spip_jobs',
507
-				'status=' . intval(_JQ_SCHEDULED) . ' AND date<' . sql_quote(date('Y-m-d H:i:s', $time))
508
-			);
509
-		} elseif ($next <= $time) {
510
-			$nb_jobs_scheduled++;
511
-		}
512
-		// si trop de jobs en attente, on force la purge en fin de hit
513
-		// pour assurer le coup
514
-		if ($nb_jobs_scheduled > (defined('_JQ_NB_JOBS_OVERFLOW') ? _JQ_NB_JOBS_OVERFLOW : 10000)) {
515
-			define('_DIRECT_CRON_FORCE', true);
516
-		}
517
-	}
518
-
519
-	queue_set_next_job_time($next);
520
-	$deja_la = false;
465
+    static $nb_jobs_scheduled = null;
466
+    static $deja_la = false;
467
+    // prendre le min des $next_time que l'on voit passer ici, en cas de reentrance
468
+    static $next = null;
469
+    // queue_close_job peut etre reentrant ici
470
+    if ($deja_la) {
471
+        return;
472
+    }
473
+    $deja_la = true;
474
+
475
+    include_spip('base/abstract_sql');
476
+    $time = time();
477
+
478
+    // traiter les jobs morts au combat (_JQ_PENDING depuis plus de 180s)
479
+    // pour cause de timeout ou autre erreur fatale
480
+    $res = sql_allfetsel(
481
+        '*',
482
+        'spip_jobs',
483
+        'status=' . intval(_JQ_PENDING) . ' AND date<' . sql_quote(date('Y-m-d H:i:s', $time - 180))
484
+    );
485
+    if (is_array($res)) {
486
+        foreach ($res as $row) {
487
+            queue_close_job($row, $time);
488
+            spip_log('queue_close_job car _JQ_PENDING depuis +180s : ' . print_r($row, 1), 'job_mort' . _LOG_ERREUR);
489
+        }
490
+    }
491
+
492
+    // chercher la date du prochain job si pas connu
493
+    if (is_null($next) or is_null(queue_sleep_time_to_next_job())) {
494
+        $date = sql_getfetsel('date', 'spip_jobs', 'status=' . intval(_JQ_SCHEDULED), '', 'date', '0,1');
495
+        $next = strtotime($date);
496
+    }
497
+    if (!is_null($next_time)) {
498
+        if (is_null($next) or $next > $next_time) {
499
+            $next = $next_time;
500
+        }
501
+    }
502
+
503
+    if ($next) {
504
+        if (is_null($nb_jobs_scheduled)) {
505
+            $nb_jobs_scheduled = sql_countsel(
506
+                'spip_jobs',
507
+                'status=' . intval(_JQ_SCHEDULED) . ' AND date<' . sql_quote(date('Y-m-d H:i:s', $time))
508
+            );
509
+        } elseif ($next <= $time) {
510
+            $nb_jobs_scheduled++;
511
+        }
512
+        // si trop de jobs en attente, on force la purge en fin de hit
513
+        // pour assurer le coup
514
+        if ($nb_jobs_scheduled > (defined('_JQ_NB_JOBS_OVERFLOW') ? _JQ_NB_JOBS_OVERFLOW : 10000)) {
515
+            define('_DIRECT_CRON_FORCE', true);
516
+        }
517
+    }
518
+
519
+    queue_set_next_job_time($next);
520
+    $deja_la = false;
521 521
 }
522 522
 
523 523
 
@@ -528,26 +528,26 @@  discard block
 block discarded – undo
528 528
  */
529 529
 function queue_set_next_job_time($next) {
530 530
 
531
-	// utiliser le temps courant reel plutot que temps de la requete ici
532
-	$time = time();
533
-
534
-	// toujours relire la valeur pour comparer, pour tenir compte des maj concourrantes
535
-	// et ne mettre a jour que si il y a un interet a le faire
536
-	// permet ausis d'initialiser le nom de fichier a coup sur
537
-	$curr_next = $_SERVER['REQUEST_TIME'] + max(0, queue_sleep_time_to_next_job(true));
538
-	if (
539
-		($curr_next <= $time and $next > $time) // le prochain job est dans le futur mais pas la date planifiee actuelle
540
-		or $curr_next > $next // le prochain job est plus tot que la date planifiee actuelle
541
-	) {
542
-		if (function_exists('cache_set') and defined('_MEMOIZE_MEMORY') and _MEMOIZE_MEMORY) {
543
-			cache_set(_JQ_NEXT_JOB_TIME_FILENAME, intval($next));
544
-		} else {
545
-			ecrire_fichier(_JQ_NEXT_JOB_TIME_FILENAME, intval($next));
546
-		}
547
-		queue_sleep_time_to_next_job($next);
548
-	}
549
-
550
-	return queue_sleep_time_to_next_job();
531
+    // utiliser le temps courant reel plutot que temps de la requete ici
532
+    $time = time();
533
+
534
+    // toujours relire la valeur pour comparer, pour tenir compte des maj concourrantes
535
+    // et ne mettre a jour que si il y a un interet a le faire
536
+    // permet ausis d'initialiser le nom de fichier a coup sur
537
+    $curr_next = $_SERVER['REQUEST_TIME'] + max(0, queue_sleep_time_to_next_job(true));
538
+    if (
539
+        ($curr_next <= $time and $next > $time) // le prochain job est dans le futur mais pas la date planifiee actuelle
540
+        or $curr_next > $next // le prochain job est plus tot que la date planifiee actuelle
541
+    ) {
542
+        if (function_exists('cache_set') and defined('_MEMOIZE_MEMORY') and _MEMOIZE_MEMORY) {
543
+            cache_set(_JQ_NEXT_JOB_TIME_FILENAME, intval($next));
544
+        } else {
545
+            ecrire_fichier(_JQ_NEXT_JOB_TIME_FILENAME, intval($next));
546
+        }
547
+        queue_sleep_time_to_next_job($next);
548
+    }
549
+
550
+    return queue_sleep_time_to_next_job();
551 551
 }
552 552
 
553 553
 /**
@@ -564,60 +564,60 @@  discard block
 block discarded – undo
564 564
  * @return string
565 565
  */
566 566
 function queue_affichage_cron() {
567
-	$texte = '';
568
-
569
-	$time_to_next = queue_sleep_time_to_next_job();
570
-	// rien a faire si le prochain job est encore dans le futur
571
-	if ($time_to_next > 0 or defined('_DEBUG_BLOCK_QUEUE')) {
572
-		return $texte;
573
-	}
574
-
575
-	// ne pas relancer si on vient de lancer dans la meme seconde par un hit concurent
576
-	if (file_exists($lock = _DIR_TMP . 'cron.lock') and !(@filemtime($lock) < $_SERVER['REQUEST_TIME'])) {
577
-		return $texte;
578
-	}
579
-
580
-	@touch($lock);
581
-
582
-	// il y a des taches en attentes
583
-	// si depuis plus de 5min, on essaye de lancer le cron par tous les moyens pour rattraper le coup
584
-	// on est sans doute sur un site qui n'autorise pas http sortant ou avec peu de trafic
585
-	$urgent = false;
586
-	if ($time_to_next < -300) {
587
-		$urgent = true;
588
-	}
589
-
590
-	$url_cron = generer_url_action('cron', '', false, true);
591
-
592
-	if (!defined('_HTML_BG_CRON_FORCE') or !_HTML_BG_CRON_FORCE) {
593
-		if (queue_lancer_url_http_async($url_cron) and !$urgent) {
594
-			return $texte;
595
-		}
596
-	}
597
-
598
-	// si deja force, on retourne sans rien
599
-	if (defined('_DIRECT_CRON_FORCE')) {
600
-		return $texte;
601
-	}
602
-
603
-	// si c'est un bot
604
-	// inutile de faire un appel par image background,
605
-	// on force un appel direct en fin de hit
606
-	if ((defined('_IS_BOT') and _IS_BOT)) {
607
-		define('_DIRECT_CRON_FORCE', true);
608
-
609
-		return $texte;
610
-	}
611
-
612
-	if (!defined('_HTML_BG_CRON_INHIB') or !_HTML_BG_CRON_INHIB) {
613
-		// en derniere solution, on insere un appel xhr non bloquant ou une image background dans la page si pas de JS
614
-		$url_cron = generer_url_action('cron');
615
-		$texte = '<!-- SPIP-CRON -->'
616
-		  . "<script>setTimeout(function(){var xo = new XMLHttpRequest();xo.open('GET', '$url_cron', true);xo.send('');},100);</script>"
617
-		  . "<noscript><div style=\"background-image: url('$url_cron');\"></div></noscript>";
618
-	}
619
-
620
-	return $texte;
567
+    $texte = '';
568
+
569
+    $time_to_next = queue_sleep_time_to_next_job();
570
+    // rien a faire si le prochain job est encore dans le futur
571
+    if ($time_to_next > 0 or defined('_DEBUG_BLOCK_QUEUE')) {
572
+        return $texte;
573
+    }
574
+
575
+    // ne pas relancer si on vient de lancer dans la meme seconde par un hit concurent
576
+    if (file_exists($lock = _DIR_TMP . 'cron.lock') and !(@filemtime($lock) < $_SERVER['REQUEST_TIME'])) {
577
+        return $texte;
578
+    }
579
+
580
+    @touch($lock);
581
+
582
+    // il y a des taches en attentes
583
+    // si depuis plus de 5min, on essaye de lancer le cron par tous les moyens pour rattraper le coup
584
+    // on est sans doute sur un site qui n'autorise pas http sortant ou avec peu de trafic
585
+    $urgent = false;
586
+    if ($time_to_next < -300) {
587
+        $urgent = true;
588
+    }
589
+
590
+    $url_cron = generer_url_action('cron', '', false, true);
591
+
592
+    if (!defined('_HTML_BG_CRON_FORCE') or !_HTML_BG_CRON_FORCE) {
593
+        if (queue_lancer_url_http_async($url_cron) and !$urgent) {
594
+            return $texte;
595
+        }
596
+    }
597
+
598
+    // si deja force, on retourne sans rien
599
+    if (defined('_DIRECT_CRON_FORCE')) {
600
+        return $texte;
601
+    }
602
+
603
+    // si c'est un bot
604
+    // inutile de faire un appel par image background,
605
+    // on force un appel direct en fin de hit
606
+    if ((defined('_IS_BOT') and _IS_BOT)) {
607
+        define('_DIRECT_CRON_FORCE', true);
608
+
609
+        return $texte;
610
+    }
611
+
612
+    if (!defined('_HTML_BG_CRON_INHIB') or !_HTML_BG_CRON_INHIB) {
613
+        // en derniere solution, on insere un appel xhr non bloquant ou une image background dans la page si pas de JS
614
+        $url_cron = generer_url_action('cron');
615
+        $texte = '<!-- SPIP-CRON -->'
616
+            . "<script>setTimeout(function(){var xo = new XMLHttpRequest();xo.open('GET', '$url_cron', true);xo.send('');},100);</script>"
617
+            . "<noscript><div style=\"background-image: url('$url_cron');\"></div></noscript>";
618
+    }
619
+
620
+    return $texte;
621 621
 }
622 622
 
623 623
 /**
@@ -626,73 +626,73 @@  discard block
 block discarded – undo
626 626
  * @return bool : true si l'url a pu être appelée en asynchrone, false sinon
627 627
  */
628 628
 function queue_lancer_url_http_async($url_cron) {
629
-	// methode la plus rapide :
630
-	// Si fsockopen est possible, on lance le cron via un socket en asynchrone
631
-	// si fsockopen echoue (disponibilite serveur, firewall) on essaye pas cURL
632
-	// car on a toutes les chances d'echouer pareil mais sans moyen de le savoir
633
-	// mais on renvoie false direct
634
-	if (function_exists('fsockopen')) {
635
-		$parts = parse_url($url_cron);
636
-
637
-		switch ($parts['scheme']) {
638
-			case 'https':
639
-				$scheme = 'ssl://';
640
-				$port = 443;
641
-				break;
642
-			case 'http':
643
-			default:
644
-				$scheme = '';
645
-				$port = 80;
646
-		}
647
-		$fp = @fsockopen(
648
-			$scheme . $parts['host'],
649
-			$parts['port'] ?? $port,
650
-			$errno,
651
-			$errstr,
652
-			1
653
-		);
654
-
655
-		if ($fp) {
656
-			$host_sent = $parts['host'];
657
-			if (isset($parts['port']) and $parts['port'] !== $port) {
658
-				$host_sent .= ':' . $parts['port'];
659
-			}
660
-			$timeout = 200; // ms
661
-			stream_set_timeout($fp, 0, $timeout * 1000);
662
-			$query = $parts['path'] . ($parts['query'] ? '?' . $parts['query'] : '');
663
-			$out = 'GET ' . $query . " HTTP/1.1\r\n";
664
-			$out .= 'Host: ' . $host_sent . "\r\n";
665
-			$out .= "Connection: Close\r\n\r\n";
666
-			fwrite($fp, $out);
667
-			spip_timer('read');
668
-			$t = 0;
669
-			// on lit la reponse si possible pour fermer proprement la connexion
670
-			// avec un timeout total de 200ms pour ne pas se bloquer
671
-			while (!feof($fp) and $t < $timeout) {
672
-				@fgets($fp, 1024);
673
-				$t += spip_timer('read', true);
674
-				spip_timer('read');
675
-			}
676
-			fclose($fp);
677
-			return true;
678
-		}
679
-	}
680
-	// si fsockopen n'est pas dispo on essaye cURL :
681
-	// lancer le cron par un cURL asynchrone si cURL est present
682
-	elseif (function_exists('curl_init')) {
683
-		//setting the curl parameters.
684
-		$ch = curl_init($url_cron);
685
-		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
686
-		// cf bug : http://www.php.net/manual/en/function.curl-setopt.php#104597
687
-		curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
688
-		// valeur mini pour que la requete soit lancee
689
-		curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
690
-		// lancer
691
-		curl_exec($ch);
692
-		// fermer
693
-		curl_close($ch);
694
-		return true;
695
-	}
696
-
697
-	return false;
629
+    // methode la plus rapide :
630
+    // Si fsockopen est possible, on lance le cron via un socket en asynchrone
631
+    // si fsockopen echoue (disponibilite serveur, firewall) on essaye pas cURL
632
+    // car on a toutes les chances d'echouer pareil mais sans moyen de le savoir
633
+    // mais on renvoie false direct
634
+    if (function_exists('fsockopen')) {
635
+        $parts = parse_url($url_cron);
636
+
637
+        switch ($parts['scheme']) {
638
+            case 'https':
639
+                $scheme = 'ssl://';
640
+                $port = 443;
641
+                break;
642
+            case 'http':
643
+            default:
644
+                $scheme = '';
645
+                $port = 80;
646
+        }
647
+        $fp = @fsockopen(
648
+            $scheme . $parts['host'],
649
+            $parts['port'] ?? $port,
650
+            $errno,
651
+            $errstr,
652
+            1
653
+        );
654
+
655
+        if ($fp) {
656
+            $host_sent = $parts['host'];
657
+            if (isset($parts['port']) and $parts['port'] !== $port) {
658
+                $host_sent .= ':' . $parts['port'];
659
+            }
660
+            $timeout = 200; // ms
661
+            stream_set_timeout($fp, 0, $timeout * 1000);
662
+            $query = $parts['path'] . ($parts['query'] ? '?' . $parts['query'] : '');
663
+            $out = 'GET ' . $query . " HTTP/1.1\r\n";
664
+            $out .= 'Host: ' . $host_sent . "\r\n";
665
+            $out .= "Connection: Close\r\n\r\n";
666
+            fwrite($fp, $out);
667
+            spip_timer('read');
668
+            $t = 0;
669
+            // on lit la reponse si possible pour fermer proprement la connexion
670
+            // avec un timeout total de 200ms pour ne pas se bloquer
671
+            while (!feof($fp) and $t < $timeout) {
672
+                @fgets($fp, 1024);
673
+                $t += spip_timer('read', true);
674
+                spip_timer('read');
675
+            }
676
+            fclose($fp);
677
+            return true;
678
+        }
679
+    }
680
+    // si fsockopen n'est pas dispo on essaye cURL :
681
+    // lancer le cron par un cURL asynchrone si cURL est present
682
+    elseif (function_exists('curl_init')) {
683
+        //setting the curl parameters.
684
+        $ch = curl_init($url_cron);
685
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
686
+        // cf bug : http://www.php.net/manual/en/function.curl-setopt.php#104597
687
+        curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
688
+        // valeur mini pour que la requete soit lancee
689
+        curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
690
+        // lancer
691
+        curl_exec($ch);
692
+        // fermer
693
+        curl_close($ch);
694
+        return true;
695
+    }
696
+
697
+    return false;
698 698
 }
Please login to merge, or discard this patch.
ecrire/base/objets.php 1 patch
Indentation   +1257 added lines, -1257 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
 /**
@@ -32,11 +32,11 @@  discard block
 block discarded – undo
32 32
  * @return void
33 33
  **/
34 34
 function array_set_merge(&$table, $index, $valeur) {
35
-	if (!isset($table[$index])) {
36
-		$table[$index] = $valeur;
37
-	} else {
38
-		$table[$index] = array_merge($table[$index], $valeur);
39
-	}
35
+    if (!isset($table[$index])) {
36
+        $table[$index] = $valeur;
37
+    } else {
38
+        $table[$index] = array_merge($table[$index], $valeur);
39
+    }
40 40
 }
41 41
 
42 42
 /**
@@ -55,441 +55,441 @@  discard block
 block discarded – undo
55 55
  *   - string (interne) si table '::md5' retourne un hash
56 56
  */
57 57
 function lister_tables_objets_sql(?string $table_sql = null, $desc = []) {
58
-	static $deja_la = false;
59
-	static $infos_tables = null;
60
-	static $md5 = null;
61
-	static $plugin_hash = null;
62
-
63
-	// plugins hash connu ? non si _CACHE_PLUGINS_OPT est pas encore chargé.
64
-	$_PLUGINS_HASH = defined('_PLUGINS_HASH') ? _PLUGINS_HASH : '!_CACHE_PLUGINS_OPT';
65
-
66
-	// prealablement recuperer les tables_principales
67
-	if (is_null($infos_tables) or $plugin_hash !== $_PLUGINS_HASH) {
68
-		// pas de reentrance (cas base/serial)
69
-		if ($deja_la) {
70
-			spip_log('Re-entrance anormale sur lister_tables_objets_sql : '
71
-				. var_export(debug_backtrace(), true), _LOG_CRITIQUE);
72
-
73
-			return ($table_sql === '::md5' ? $md5 : []);
74
-		}
75
-		$deja_la = true;
76
-		$plugin_hash = $_PLUGINS_HASH; // avant de lancer les pipelines
77
-
78
-		// recuperer les declarations explicites ancienne mode
79
-		// qui servent a completer declarer_tables_objets_sql
80
-		base_serial($GLOBALS['tables_principales']);
81
-		base_auxiliaires($GLOBALS['tables_auxiliaires']);
82
-		$infos_tables = [
83
-			'spip_articles' => [
84
-				'page' => 'article',
85
-				'texte_retour' => 'icone_retour_article',
86
-				'texte_modifier' => 'icone_modifier_article',
87
-				'texte_creer' => 'icone_ecrire_article',
88
-				'texte_objets' => 'public:articles',
89
-				'texte_objet' => 'public:article',
90
-				'texte_signale_edition' => 'texte_travail_article',
91
-				'info_aucun_objet' => 'info_aucun_article',
92
-				'info_1_objet' => 'info_1_article',
93
-				'info_nb_objets' => 'info_nb_articles',
94
-				'texte_logo_objet' => 'logo_article',
95
-				'texte_langue_objet' => 'titre_langue_article',
96
-				'texte_definir_comme_traduction_objet' => 'trad_lier',
97
-				'titre' => 'titre, lang',
98
-				'date' => 'date',
99
-				'principale' => 'oui',
100
-				'introduction_longueur' => '500',
101
-				'champs_editables' => [
102
-					'surtitre',
103
-					'titre',
104
-					'soustitre',
105
-					'descriptif',
106
-					'nom_site',
107
-					'url_site',
108
-					'chapo',
109
-					'texte',
110
-					'ps',
111
-					'virtuel'
112
-				],
113
-				'champs_versionnes' => [
114
-					'id_rubrique',
115
-					'surtitre',
116
-					'titre',
117
-					'soustitre',
118
-					'jointure_auteurs',
119
-					'descriptif',
120
-					'nom_site',
121
-					'url_site',
122
-					'chapo',
123
-					'texte',
124
-					'ps'
125
-				],
126
-				'field' => [
127
-					'id_article' => 'bigint(21) NOT NULL',
128
-					'surtitre' => "text DEFAULT '' NOT NULL",
129
-					'titre' => "text DEFAULT '' NOT NULL",
130
-					'soustitre' => "text DEFAULT '' NOT NULL",
131
-					'id_rubrique' => "bigint(21) DEFAULT '0' NOT NULL",
132
-					'descriptif' => "text DEFAULT '' NOT NULL",
133
-					'chapo' => "mediumtext DEFAULT '' NOT NULL",
134
-					'texte' => "longtext DEFAULT '' NOT NULL",
135
-					'ps' => "mediumtext DEFAULT '' NOT NULL",
136
-					'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
137
-					'statut' => "varchar(10) DEFAULT '0' NOT NULL",
138
-					'id_secteur' => "bigint(21) DEFAULT '0' NOT NULL",
139
-					'maj' => 'TIMESTAMP',
140
-					'export' => "VARCHAR(10) DEFAULT 'oui'",
141
-					'date_redac' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
142
-					'visites' => "integer DEFAULT '0' NOT NULL",
143
-					'referers' => "integer DEFAULT '0' NOT NULL",
144
-					'popularite' => "DOUBLE DEFAULT '0' NOT NULL",
145
-					'accepter_forum' => "CHAR(3) DEFAULT '' NOT NULL",
146
-					'date_modif' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
147
-					'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
148
-					'langue_choisie' => "VARCHAR(3) DEFAULT 'non'",
149
-					'id_trad' => "bigint(21) DEFAULT '0' NOT NULL",
150
-					'nom_site' => "tinytext DEFAULT '' NOT NULL",
151
-					'url_site' => "text DEFAULT '' NOT NULL",
152
-					'virtuel' => "text DEFAULT '' NOT NULL",
153
-				],
154
-				'key' => [
155
-					'PRIMARY KEY' => 'id_article',
156
-					'KEY id_rubrique' => 'id_rubrique',
157
-					'KEY id_secteur' => 'id_secteur',
158
-					'KEY id_trad' => 'id_trad',
159
-					'KEY lang' => 'lang',
160
-					'KEY statut' => 'statut, date',
161
-				],
162
-				'join' => [
163
-					'id_article' => 'id_article',
164
-					'id_rubrique' => 'id_rubrique'
165
-				],
166
-				'parent' => [
167
-					['type' => 'rubrique', 'champ' => 'id_rubrique']
168
-				],
169
-				'rechercher_champs' => [
170
-					'surtitre' => 5,
171
-					'titre' => 8,
172
-					'soustitre' => 5,
173
-					'chapo' => 3,
174
-					'texte' => 1,
175
-					'ps' => 1,
176
-					'nom_site' => 1,
177
-					'url_site' => 1,
178
-					'descriptif' => 4
179
-				],
180
-				'rechercher_jointures' => [
181
-					'auteur' => ['nom' => 10],
182
-				],
183
-				'statut' => [
184
-					[
185
-						'champ' => 'statut',
186
-						'publie' => 'publie',
187
-						'previsu' => 'publie,prop,prepa/auteur',
188
-						'post_date' => 'date',
189
-						'exception' => ['statut', 'tout']
190
-					]
191
-				],
192
-				'statut_titres' => [
193
-					'prepa' => 'info_article_redaction',
194
-					'prop' => 'info_article_propose',
195
-					'publie' => 'info_article_publie',
196
-					'refuse' => 'info_article_refuse',
197
-					'poubelle' => 'info_article_supprime'
198
-				],
199
-				'statut_textes_instituer' => [
200
-					'prepa' => 'texte_statut_en_cours_redaction',
201
-					'prop' => 'texte_statut_propose_evaluation',
202
-					'publie' => 'texte_statut_publie',
203
-					'refuse' => 'texte_statut_refuse',
204
-					'poubelle' => 'texte_statut_poubelle',
205
-				],
206
-				'texte_changer_statut' => 'texte_article_statut',
207
-				'aide_changer_statut' => 'artstatut',
208
-				'tables_jointures' => [
209
-					'profondeur' => 'rubriques',
210
-					#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
211
-				],
212
-			],
213
-			'spip_auteurs' => [
214
-				'page' => 'auteur',
215
-				'texte_retour' => 'icone_retour',
216
-				'texte_ajouter' => 'titre_ajouter_un_auteur',
217
-				'texte_modifier' => 'admin_modifier_auteur',
218
-				'texte_objets' => 'icone_auteurs',
219
-				'texte_objet' => 'public:auteur',
220
-				'info_aucun_objet' => 'info_aucun_auteur',
221
-				'info_1_objet' => 'info_1_auteur',
222
-				'info_nb_objets' => 'info_nb_auteurs',
223
-				'texte_logo_objet' => 'logo_auteur',
224
-				'texte_creer_associer' => 'creer_et_associer_un_auteur',
225
-				'titre' => "nom AS titre, '' AS lang",
226
-				'date' => 'date',
227
-				'principale' => 'oui',
228
-				'champs_editables' => ['nom', 'email', 'bio', 'nom_site', 'url_site', 'imessage', 'pgp'],
229
-				'champs_versionnes' => ['nom', 'bio', 'email', 'nom_site', 'url_site', 'login'],
230
-				'field' => [
231
-					'id_auteur' => 'bigint(21) NOT NULL',
232
-					'nom' => "text DEFAULT '' NOT NULL",
233
-					'bio' => "text DEFAULT '' NOT NULL",
234
-					'email' => "tinytext DEFAULT '' NOT NULL",
235
-					'nom_site' => "tinytext DEFAULT '' NOT NULL",
236
-					'url_site' => "text DEFAULT '' NOT NULL",
237
-					'login' => 'VARCHAR(255) BINARY',
238
-					'pass' => "tinytext DEFAULT '' NOT NULL",
239
-					'low_sec' => "tinytext DEFAULT '' NOT NULL",
240
-					'statut' => "varchar(255)  DEFAULT '0' NOT NULL",
241
-					'webmestre' => "varchar(3)  DEFAULT 'non' NOT NULL",
242
-					'maj' => 'TIMESTAMP',
243
-					'pgp' => "TEXT DEFAULT '' NOT NULL",
244
-					'htpass' => "tinytext DEFAULT '' NOT NULL",
245
-					'en_ligne' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
246
-					'alea_actuel' => 'tinytext',
247
-					'alea_futur' => 'tinytext',
248
-					'prefs' => 'text',
249
-					'cookie_oubli' => 'tinytext',
250
-					'source' => "VARCHAR(10) DEFAULT 'spip' NOT NULL",
251
-					'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
252
-					'imessage' => "VARCHAR(3) DEFAULT '' NOT NULL",
253
-					'backup_cles' => "mediumtext DEFAULT '' NOT NULL",
254
-				],
255
-				'key' => [
256
-					'PRIMARY KEY' => 'id_auteur',
257
-					'KEY login' => 'login',
258
-					'KEY statut' => 'statut',
259
-					'KEY en_ligne' => 'en_ligne',
260
-				],
261
-				'join' => [
262
-					'id_auteur' => 'id_auteur',
263
-					'login' => 'login'
264
-				],
265
-				'rechercher_champs' => [
266
-					'nom' => 5,
267
-					'bio' => 1,
268
-					'email' => 1,
269
-					'nom_site' => 1,
270
-					'url_site' => 1,
271
-					'login' => 1
272
-				],
273
-				// 2 conditions pour les auteurs : statut!=poubelle,
274
-				// et avoir des articles publies
275
-				'statut' => [
276
-					[
277
-						'champ' => 'statut',
278
-						'publie' => '!5poubelle',
279
-						'previsu' => '!5poubelle',
280
-						'exception' => 'statut'
281
-					],
282
-					[
283
-						'champ' => [
284
-							['spip_auteurs_liens', 'id_auteur'],
285
-							[
286
-								'spip_articles',
287
-								['id_objet', 'id_article', 'objet', 'article']
288
-							],
289
-							'statut'
290
-						],
291
-						'publie' => 'publie',
292
-						'previsu' => '!',
293
-						'post_date' => 'date',
294
-						'exception' => ['statut', 'lien', 'tout']
295
-					],
296
-				],
297
-				'statut_images' => [
298
-					'auteur-6forum-16.png',
299
-					'0minirezo' => 'auteur-0minirezo-16.png',
300
-					'1comite' => 'auteur-1comite-16.png',
301
-					'6forum' => 'auteur-6forum-16.png',
302
-					'5poubelle' => 'auteur-5poubelle-16.png',
303
-					'nouveau' => ''
304
-				],
305
-				'statut_titres' => [
306
-					'titre_image_visiteur',
307
-					'0minirezo' => 'titre_image_administrateur',
308
-					'1comite' => 'titre_image_redacteur_02',
309
-					'6forum' => 'titre_image_visiteur',
310
-					'5poubelle' => 'titre_image_auteur_supprime',
311
-				],
312
-				'tables_jointures' => [#'auteurs_liens' // declaration generique plus bas
313
-				],
314
-			],
315
-			'spip_rubriques' => [
316
-				'page' => 'rubrique',
317
-				'url_voir' => 'rubrique',
318
-				'url_edit' => 'rubrique_edit',
319
-				'texte_retour' => 'icone_retour',
320
-				'texte_objets' => 'public:rubriques',
321
-				'texte_objet' => 'public:rubrique',
322
-				'texte_modifier' => 'icone_modifier_rubrique',
323
-				'texte_creer' => 'icone_creer_rubrique',
324
-				'texte_ajouter' => 'titre_ajouter_une_rubrique',
325
-				'texte_creer_associer' => 'creer_et_associer_une_rubrique',
326
-				'info_aucun_objet' => 'info_aucun_rubrique',
327
-				'info_1_objet' => 'info_1_rubrique',
328
-				'info_nb_objets' => 'info_nb_rubriques',
329
-				'texte_logo_objet' => 'logo_rubrique',
330
-				'texte_langue_objet' => 'titre_langue_rubrique',
331
-				'texte_definir_comme_traduction_objet' => 'texte_definir_comme_traduction_rubrique',
332
-				'titre' => 'titre, lang',
333
-				'date' => 'date',
334
-				'principale' => 'oui',
335
-				'introduction_longueur' => '600',
336
-				'champs_editables' => ['titre', 'texte', 'descriptif', 'extra'],
337
-				'champs_versionnes' => ['titre', 'descriptif', 'texte'],
338
-				'field' => [
339
-					'id_rubrique' => 'bigint(21) NOT NULL',
340
-					'id_parent' => "bigint(21) DEFAULT '0' NOT NULL",
341
-					'titre' => "text DEFAULT '' NOT NULL",
342
-					'descriptif' => "text DEFAULT '' NOT NULL",
343
-					'texte' => "longtext DEFAULT '' NOT NULL",
344
-					'id_secteur' => "bigint(21) DEFAULT '0' NOT NULL",
345
-					'maj' => 'TIMESTAMP',
346
-					'statut' => "varchar(10) DEFAULT '0' NOT NULL",
347
-					'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
348
-					'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
349
-					'langue_choisie' => "VARCHAR(3) DEFAULT 'non'",
350
-					'statut_tmp' => "varchar(10) DEFAULT '0' NOT NULL",
351
-					'date_tmp' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
352
-					'profondeur' => "smallint(5) DEFAULT '0' NOT NULL"
353
-				],
354
-				'key' => [
355
-					'PRIMARY KEY' => 'id_rubrique',
356
-					'KEY lang' => 'lang',
357
-					'KEY id_parent' => 'id_parent',
358
-				],
359
-				'parent' => [
360
-					['type' => 'rubrique', 'champ' => 'id_parent']
361
-				],
362
-				'rechercher_champs' => [
363
-					'titre' => 8,
364
-					'descriptif' => 5,
365
-					'texte' => 1
366
-				],
367
-				'statut' => [
368
-					[
369
-						'champ' => 'statut',
370
-						'publie' => 'publie',
371
-						'previsu' => '!',
372
-						'exception' => ['statut', 'tout']
373
-					],
374
-				],
375
-				'tables_jointures' => [#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
376
-				],
377
-			],
378
-			// toutes les tables ont le droit a une jointure sur les auteurs
379
-			['tables_jointures' => ['id_auteur' => 'auteurs_liens']]
380
-		];
381
-
382
-		// avant d'appeller les pipeline qui peuvent generer une reentrance a l'install
383
-		// initialiser la signature
384
-		$md5 = md5(serialize($infos_tables));
385
-
386
-		$GLOBALS['tables_principales'] = pipeline('declarer_tables_principales', $GLOBALS['tables_principales']);
387
-		$GLOBALS['tables_auxiliaires'] = pipeline('declarer_tables_auxiliaires', $GLOBALS['tables_auxiliaires']);
388
-		$infos_tables = pipeline('declarer_tables_objets_sql', $infos_tables);
389
-
390
-		// completer les informations manquantes ou implicites
391
-		$all = [];
392
-		foreach (array_keys($infos_tables) as $t) {
393
-			// les cles numeriques servent a declarer
394
-			// les proprietes applicables a tous les objets
395
-			// on les mets de cote
396
-			if (is_numeric($t)) {
397
-				$all = array_merge_recursive($all, $infos_tables[$t]);
398
-				unset($infos_tables[$t]);
399
-			} else {
400
-				$infos_tables[$t] = renseigner_table_objet_sql($t, $infos_tables[$t]);
401
-			}
402
-		}
403
-
404
-		// repercuter les proprietes generales communes a tous les objets
405
-		foreach (array_keys($infos_tables) as $t) {
406
-			foreach ($all as $i => $v) {
407
-				if (in_array($i, ['tables_jointures', 'champs_versionnes'])) {
408
-					$add = $all[$i];
409
-					// eviter les doublons de declaration de table jointure (ex des mots sur auteurs)
410
-					// pour les declarations generiques avec cles numeriques
411
-					if ($i == 'tables_jointures' and isset($infos_tables[$t][$i]) and is_countable($infos_tables[$t][$i]) ? count($infos_tables[$t][$i]) : 0) {
412
-						$doublons = array_intersect($infos_tables[$t][$i], $add);
413
-						foreach ($doublons as $d) {
414
-							if (
415
-								is_numeric(array_search($d, $infos_tables[$t][$i]))
416
-								and is_numeric($k = array_search($d, $add))
417
-							) {
418
-								unset($add[$k]);
419
-							}
420
-						}
421
-					}
422
-					$infos_tables[$t][$i] = array_merge($infos_tables[$t][$i] ?? [], $add);
423
-				} else {
424
-					$infos_tables[$t][$i] = array_merge_recursive(
425
-						$infos_tables[$t][$i] ?? [],
426
-						$all[$i]
427
-					);
428
-				}
429
-			}
430
-		}
431
-
432
-		// completer les tables principales et auxiliaires
433
-		// avec celles declarees uniquement dans declarer_table_objets_sql
434
-		// pour assurer la compat en transition
435
-		foreach ($infos_tables as $table => $infos) {
436
-			$principale_ou_auxiliaire = ($infos['principale'] ? 'tables_principales' : 'tables_auxiliaires');
437
-			// memoriser des champs eventuels declares par des plugins dans le pipeline tables_xxx
438
-			// qui a ete appelle avant
439
-			$mem = ($GLOBALS[$principale_ou_auxiliaire][$table] ?? []);
440
-			// l'ajouter au tableau
441
-			$GLOBALS[$principale_ou_auxiliaire][$table] = [];
442
-			if (isset($infos['field']) and isset($infos['key'])) {
443
-				foreach (['field', 'key', 'join'] as $k) {
444
-					if (isset($infos_tables[$table][$k])) {
445
-						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = &$infos_tables[$table][$k];
446
-					}
447
-				}
448
-			} else {
449
-				// ici on ne renvoie que les declarations, donc RIEN
450
-				// pour avoir la vrai description en base, il faut passer par trouver_table
451
-				$GLOBALS[$principale_ou_auxiliaire][$table] = [];
452
-			}
453
-			if (is_countable($mem) ? count($mem) : 0) {
454
-				foreach (array_keys($mem) as $k) {
455
-					if (isset($GLOBALS[$principale_ou_auxiliaire][$table][$k])) {
456
-						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = array_merge(
457
-							$GLOBALS[$principale_ou_auxiliaire][$table][$k],
458
-							$mem[$k]
459
-						);
460
-					} else {
461
-						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = $mem[$k];
462
-					}
463
-				}
464
-			}
465
-		}
466
-
467
-		// recuperer les interfaces (table_titre, table_date)
468
-		// on ne le fait que dans un second temps pour que table_objet soit fonctionnel
469
-		// dans le pipeline de declarer_tables_interfaces
470
-		include_spip('public/interfaces');
471
-		foreach (array_keys($infos_tables) as $t) {
472
-			$infos_tables[$t] = renseigner_table_objet_interfaces($t, $infos_tables[$t]);
473
-		}
474
-
475
-		$deja_la = false;
476
-		// signature
477
-		$md5 = md5(serialize($infos_tables));
478
-	}
479
-	if ($table_sql === '::md5') {
480
-		return $md5;
481
-	}
482
-	if ($table_sql and !isset($infos_tables[$table_sql])) {
483
-		#$desc = renseigner_table_objet_sql($table_sql,$desc);
484
-		$desc = renseigner_table_objet_interfaces($table_sql, $desc);
485
-
486
-		return $desc;
487
-	}
488
-	if ($table_sql) {
489
-		return $infos_tables[$table_sql] ?? [];
490
-	}
491
-
492
-	return $infos_tables;
58
+    static $deja_la = false;
59
+    static $infos_tables = null;
60
+    static $md5 = null;
61
+    static $plugin_hash = null;
62
+
63
+    // plugins hash connu ? non si _CACHE_PLUGINS_OPT est pas encore chargé.
64
+    $_PLUGINS_HASH = defined('_PLUGINS_HASH') ? _PLUGINS_HASH : '!_CACHE_PLUGINS_OPT';
65
+
66
+    // prealablement recuperer les tables_principales
67
+    if (is_null($infos_tables) or $plugin_hash !== $_PLUGINS_HASH) {
68
+        // pas de reentrance (cas base/serial)
69
+        if ($deja_la) {
70
+            spip_log('Re-entrance anormale sur lister_tables_objets_sql : '
71
+                . var_export(debug_backtrace(), true), _LOG_CRITIQUE);
72
+
73
+            return ($table_sql === '::md5' ? $md5 : []);
74
+        }
75
+        $deja_la = true;
76
+        $plugin_hash = $_PLUGINS_HASH; // avant de lancer les pipelines
77
+
78
+        // recuperer les declarations explicites ancienne mode
79
+        // qui servent a completer declarer_tables_objets_sql
80
+        base_serial($GLOBALS['tables_principales']);
81
+        base_auxiliaires($GLOBALS['tables_auxiliaires']);
82
+        $infos_tables = [
83
+            'spip_articles' => [
84
+                'page' => 'article',
85
+                'texte_retour' => 'icone_retour_article',
86
+                'texte_modifier' => 'icone_modifier_article',
87
+                'texte_creer' => 'icone_ecrire_article',
88
+                'texte_objets' => 'public:articles',
89
+                'texte_objet' => 'public:article',
90
+                'texte_signale_edition' => 'texte_travail_article',
91
+                'info_aucun_objet' => 'info_aucun_article',
92
+                'info_1_objet' => 'info_1_article',
93
+                'info_nb_objets' => 'info_nb_articles',
94
+                'texte_logo_objet' => 'logo_article',
95
+                'texte_langue_objet' => 'titre_langue_article',
96
+                'texte_definir_comme_traduction_objet' => 'trad_lier',
97
+                'titre' => 'titre, lang',
98
+                'date' => 'date',
99
+                'principale' => 'oui',
100
+                'introduction_longueur' => '500',
101
+                'champs_editables' => [
102
+                    'surtitre',
103
+                    'titre',
104
+                    'soustitre',
105
+                    'descriptif',
106
+                    'nom_site',
107
+                    'url_site',
108
+                    'chapo',
109
+                    'texte',
110
+                    'ps',
111
+                    'virtuel'
112
+                ],
113
+                'champs_versionnes' => [
114
+                    'id_rubrique',
115
+                    'surtitre',
116
+                    'titre',
117
+                    'soustitre',
118
+                    'jointure_auteurs',
119
+                    'descriptif',
120
+                    'nom_site',
121
+                    'url_site',
122
+                    'chapo',
123
+                    'texte',
124
+                    'ps'
125
+                ],
126
+                'field' => [
127
+                    'id_article' => 'bigint(21) NOT NULL',
128
+                    'surtitre' => "text DEFAULT '' NOT NULL",
129
+                    'titre' => "text DEFAULT '' NOT NULL",
130
+                    'soustitre' => "text DEFAULT '' NOT NULL",
131
+                    'id_rubrique' => "bigint(21) DEFAULT '0' NOT NULL",
132
+                    'descriptif' => "text DEFAULT '' NOT NULL",
133
+                    'chapo' => "mediumtext DEFAULT '' NOT NULL",
134
+                    'texte' => "longtext DEFAULT '' NOT NULL",
135
+                    'ps' => "mediumtext DEFAULT '' NOT NULL",
136
+                    'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
137
+                    'statut' => "varchar(10) DEFAULT '0' NOT NULL",
138
+                    'id_secteur' => "bigint(21) DEFAULT '0' NOT NULL",
139
+                    'maj' => 'TIMESTAMP',
140
+                    'export' => "VARCHAR(10) DEFAULT 'oui'",
141
+                    'date_redac' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
142
+                    'visites' => "integer DEFAULT '0' NOT NULL",
143
+                    'referers' => "integer DEFAULT '0' NOT NULL",
144
+                    'popularite' => "DOUBLE DEFAULT '0' NOT NULL",
145
+                    'accepter_forum' => "CHAR(3) DEFAULT '' NOT NULL",
146
+                    'date_modif' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
147
+                    'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
148
+                    'langue_choisie' => "VARCHAR(3) DEFAULT 'non'",
149
+                    'id_trad' => "bigint(21) DEFAULT '0' NOT NULL",
150
+                    'nom_site' => "tinytext DEFAULT '' NOT NULL",
151
+                    'url_site' => "text DEFAULT '' NOT NULL",
152
+                    'virtuel' => "text DEFAULT '' NOT NULL",
153
+                ],
154
+                'key' => [
155
+                    'PRIMARY KEY' => 'id_article',
156
+                    'KEY id_rubrique' => 'id_rubrique',
157
+                    'KEY id_secteur' => 'id_secteur',
158
+                    'KEY id_trad' => 'id_trad',
159
+                    'KEY lang' => 'lang',
160
+                    'KEY statut' => 'statut, date',
161
+                ],
162
+                'join' => [
163
+                    'id_article' => 'id_article',
164
+                    'id_rubrique' => 'id_rubrique'
165
+                ],
166
+                'parent' => [
167
+                    ['type' => 'rubrique', 'champ' => 'id_rubrique']
168
+                ],
169
+                'rechercher_champs' => [
170
+                    'surtitre' => 5,
171
+                    'titre' => 8,
172
+                    'soustitre' => 5,
173
+                    'chapo' => 3,
174
+                    'texte' => 1,
175
+                    'ps' => 1,
176
+                    'nom_site' => 1,
177
+                    'url_site' => 1,
178
+                    'descriptif' => 4
179
+                ],
180
+                'rechercher_jointures' => [
181
+                    'auteur' => ['nom' => 10],
182
+                ],
183
+                'statut' => [
184
+                    [
185
+                        'champ' => 'statut',
186
+                        'publie' => 'publie',
187
+                        'previsu' => 'publie,prop,prepa/auteur',
188
+                        'post_date' => 'date',
189
+                        'exception' => ['statut', 'tout']
190
+                    ]
191
+                ],
192
+                'statut_titres' => [
193
+                    'prepa' => 'info_article_redaction',
194
+                    'prop' => 'info_article_propose',
195
+                    'publie' => 'info_article_publie',
196
+                    'refuse' => 'info_article_refuse',
197
+                    'poubelle' => 'info_article_supprime'
198
+                ],
199
+                'statut_textes_instituer' => [
200
+                    'prepa' => 'texte_statut_en_cours_redaction',
201
+                    'prop' => 'texte_statut_propose_evaluation',
202
+                    'publie' => 'texte_statut_publie',
203
+                    'refuse' => 'texte_statut_refuse',
204
+                    'poubelle' => 'texte_statut_poubelle',
205
+                ],
206
+                'texte_changer_statut' => 'texte_article_statut',
207
+                'aide_changer_statut' => 'artstatut',
208
+                'tables_jointures' => [
209
+                    'profondeur' => 'rubriques',
210
+                    #'id_auteur' => 'auteurs_liens' // declaration generique plus bas
211
+                ],
212
+            ],
213
+            'spip_auteurs' => [
214
+                'page' => 'auteur',
215
+                'texte_retour' => 'icone_retour',
216
+                'texte_ajouter' => 'titre_ajouter_un_auteur',
217
+                'texte_modifier' => 'admin_modifier_auteur',
218
+                'texte_objets' => 'icone_auteurs',
219
+                'texte_objet' => 'public:auteur',
220
+                'info_aucun_objet' => 'info_aucun_auteur',
221
+                'info_1_objet' => 'info_1_auteur',
222
+                'info_nb_objets' => 'info_nb_auteurs',
223
+                'texte_logo_objet' => 'logo_auteur',
224
+                'texte_creer_associer' => 'creer_et_associer_un_auteur',
225
+                'titre' => "nom AS titre, '' AS lang",
226
+                'date' => 'date',
227
+                'principale' => 'oui',
228
+                'champs_editables' => ['nom', 'email', 'bio', 'nom_site', 'url_site', 'imessage', 'pgp'],
229
+                'champs_versionnes' => ['nom', 'bio', 'email', 'nom_site', 'url_site', 'login'],
230
+                'field' => [
231
+                    'id_auteur' => 'bigint(21) NOT NULL',
232
+                    'nom' => "text DEFAULT '' NOT NULL",
233
+                    'bio' => "text DEFAULT '' NOT NULL",
234
+                    'email' => "tinytext DEFAULT '' NOT NULL",
235
+                    'nom_site' => "tinytext DEFAULT '' NOT NULL",
236
+                    'url_site' => "text DEFAULT '' NOT NULL",
237
+                    'login' => 'VARCHAR(255) BINARY',
238
+                    'pass' => "tinytext DEFAULT '' NOT NULL",
239
+                    'low_sec' => "tinytext DEFAULT '' NOT NULL",
240
+                    'statut' => "varchar(255)  DEFAULT '0' NOT NULL",
241
+                    'webmestre' => "varchar(3)  DEFAULT 'non' NOT NULL",
242
+                    'maj' => 'TIMESTAMP',
243
+                    'pgp' => "TEXT DEFAULT '' NOT NULL",
244
+                    'htpass' => "tinytext DEFAULT '' NOT NULL",
245
+                    'en_ligne' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
246
+                    'alea_actuel' => 'tinytext',
247
+                    'alea_futur' => 'tinytext',
248
+                    'prefs' => 'text',
249
+                    'cookie_oubli' => 'tinytext',
250
+                    'source' => "VARCHAR(10) DEFAULT 'spip' NOT NULL",
251
+                    'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
252
+                    'imessage' => "VARCHAR(3) DEFAULT '' NOT NULL",
253
+                    'backup_cles' => "mediumtext DEFAULT '' NOT NULL",
254
+                ],
255
+                'key' => [
256
+                    'PRIMARY KEY' => 'id_auteur',
257
+                    'KEY login' => 'login',
258
+                    'KEY statut' => 'statut',
259
+                    'KEY en_ligne' => 'en_ligne',
260
+                ],
261
+                'join' => [
262
+                    'id_auteur' => 'id_auteur',
263
+                    'login' => 'login'
264
+                ],
265
+                'rechercher_champs' => [
266
+                    'nom' => 5,
267
+                    'bio' => 1,
268
+                    'email' => 1,
269
+                    'nom_site' => 1,
270
+                    'url_site' => 1,
271
+                    'login' => 1
272
+                ],
273
+                // 2 conditions pour les auteurs : statut!=poubelle,
274
+                // et avoir des articles publies
275
+                'statut' => [
276
+                    [
277
+                        'champ' => 'statut',
278
+                        'publie' => '!5poubelle',
279
+                        'previsu' => '!5poubelle',
280
+                        'exception' => 'statut'
281
+                    ],
282
+                    [
283
+                        'champ' => [
284
+                            ['spip_auteurs_liens', 'id_auteur'],
285
+                            [
286
+                                'spip_articles',
287
+                                ['id_objet', 'id_article', 'objet', 'article']
288
+                            ],
289
+                            'statut'
290
+                        ],
291
+                        'publie' => 'publie',
292
+                        'previsu' => '!',
293
+                        'post_date' => 'date',
294
+                        'exception' => ['statut', 'lien', 'tout']
295
+                    ],
296
+                ],
297
+                'statut_images' => [
298
+                    'auteur-6forum-16.png',
299
+                    '0minirezo' => 'auteur-0minirezo-16.png',
300
+                    '1comite' => 'auteur-1comite-16.png',
301
+                    '6forum' => 'auteur-6forum-16.png',
302
+                    '5poubelle' => 'auteur-5poubelle-16.png',
303
+                    'nouveau' => ''
304
+                ],
305
+                'statut_titres' => [
306
+                    'titre_image_visiteur',
307
+                    '0minirezo' => 'titre_image_administrateur',
308
+                    '1comite' => 'titre_image_redacteur_02',
309
+                    '6forum' => 'titre_image_visiteur',
310
+                    '5poubelle' => 'titre_image_auteur_supprime',
311
+                ],
312
+                'tables_jointures' => [#'auteurs_liens' // declaration generique plus bas
313
+                ],
314
+            ],
315
+            'spip_rubriques' => [
316
+                'page' => 'rubrique',
317
+                'url_voir' => 'rubrique',
318
+                'url_edit' => 'rubrique_edit',
319
+                'texte_retour' => 'icone_retour',
320
+                'texte_objets' => 'public:rubriques',
321
+                'texte_objet' => 'public:rubrique',
322
+                'texte_modifier' => 'icone_modifier_rubrique',
323
+                'texte_creer' => 'icone_creer_rubrique',
324
+                'texte_ajouter' => 'titre_ajouter_une_rubrique',
325
+                'texte_creer_associer' => 'creer_et_associer_une_rubrique',
326
+                'info_aucun_objet' => 'info_aucun_rubrique',
327
+                'info_1_objet' => 'info_1_rubrique',
328
+                'info_nb_objets' => 'info_nb_rubriques',
329
+                'texte_logo_objet' => 'logo_rubrique',
330
+                'texte_langue_objet' => 'titre_langue_rubrique',
331
+                'texte_definir_comme_traduction_objet' => 'texte_definir_comme_traduction_rubrique',
332
+                'titre' => 'titre, lang',
333
+                'date' => 'date',
334
+                'principale' => 'oui',
335
+                'introduction_longueur' => '600',
336
+                'champs_editables' => ['titre', 'texte', 'descriptif', 'extra'],
337
+                'champs_versionnes' => ['titre', 'descriptif', 'texte'],
338
+                'field' => [
339
+                    'id_rubrique' => 'bigint(21) NOT NULL',
340
+                    'id_parent' => "bigint(21) DEFAULT '0' NOT NULL",
341
+                    'titre' => "text DEFAULT '' NOT NULL",
342
+                    'descriptif' => "text DEFAULT '' NOT NULL",
343
+                    'texte' => "longtext DEFAULT '' NOT NULL",
344
+                    'id_secteur' => "bigint(21) DEFAULT '0' NOT NULL",
345
+                    'maj' => 'TIMESTAMP',
346
+                    'statut' => "varchar(10) DEFAULT '0' NOT NULL",
347
+                    'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
348
+                    'lang' => "VARCHAR(10) DEFAULT '' NOT NULL",
349
+                    'langue_choisie' => "VARCHAR(3) DEFAULT 'non'",
350
+                    'statut_tmp' => "varchar(10) DEFAULT '0' NOT NULL",
351
+                    'date_tmp' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
352
+                    'profondeur' => "smallint(5) DEFAULT '0' NOT NULL"
353
+                ],
354
+                'key' => [
355
+                    'PRIMARY KEY' => 'id_rubrique',
356
+                    'KEY lang' => 'lang',
357
+                    'KEY id_parent' => 'id_parent',
358
+                ],
359
+                'parent' => [
360
+                    ['type' => 'rubrique', 'champ' => 'id_parent']
361
+                ],
362
+                'rechercher_champs' => [
363
+                    'titre' => 8,
364
+                    'descriptif' => 5,
365
+                    'texte' => 1
366
+                ],
367
+                'statut' => [
368
+                    [
369
+                        'champ' => 'statut',
370
+                        'publie' => 'publie',
371
+                        'previsu' => '!',
372
+                        'exception' => ['statut', 'tout']
373
+                    ],
374
+                ],
375
+                'tables_jointures' => [#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
376
+                ],
377
+            ],
378
+            // toutes les tables ont le droit a une jointure sur les auteurs
379
+            ['tables_jointures' => ['id_auteur' => 'auteurs_liens']]
380
+        ];
381
+
382
+        // avant d'appeller les pipeline qui peuvent generer une reentrance a l'install
383
+        // initialiser la signature
384
+        $md5 = md5(serialize($infos_tables));
385
+
386
+        $GLOBALS['tables_principales'] = pipeline('declarer_tables_principales', $GLOBALS['tables_principales']);
387
+        $GLOBALS['tables_auxiliaires'] = pipeline('declarer_tables_auxiliaires', $GLOBALS['tables_auxiliaires']);
388
+        $infos_tables = pipeline('declarer_tables_objets_sql', $infos_tables);
389
+
390
+        // completer les informations manquantes ou implicites
391
+        $all = [];
392
+        foreach (array_keys($infos_tables) as $t) {
393
+            // les cles numeriques servent a declarer
394
+            // les proprietes applicables a tous les objets
395
+            // on les mets de cote
396
+            if (is_numeric($t)) {
397
+                $all = array_merge_recursive($all, $infos_tables[$t]);
398
+                unset($infos_tables[$t]);
399
+            } else {
400
+                $infos_tables[$t] = renseigner_table_objet_sql($t, $infos_tables[$t]);
401
+            }
402
+        }
403
+
404
+        // repercuter les proprietes generales communes a tous les objets
405
+        foreach (array_keys($infos_tables) as $t) {
406
+            foreach ($all as $i => $v) {
407
+                if (in_array($i, ['tables_jointures', 'champs_versionnes'])) {
408
+                    $add = $all[$i];
409
+                    // eviter les doublons de declaration de table jointure (ex des mots sur auteurs)
410
+                    // pour les declarations generiques avec cles numeriques
411
+                    if ($i == 'tables_jointures' and isset($infos_tables[$t][$i]) and is_countable($infos_tables[$t][$i]) ? count($infos_tables[$t][$i]) : 0) {
412
+                        $doublons = array_intersect($infos_tables[$t][$i], $add);
413
+                        foreach ($doublons as $d) {
414
+                            if (
415
+                                is_numeric(array_search($d, $infos_tables[$t][$i]))
416
+                                and is_numeric($k = array_search($d, $add))
417
+                            ) {
418
+                                unset($add[$k]);
419
+                            }
420
+                        }
421
+                    }
422
+                    $infos_tables[$t][$i] = array_merge($infos_tables[$t][$i] ?? [], $add);
423
+                } else {
424
+                    $infos_tables[$t][$i] = array_merge_recursive(
425
+                        $infos_tables[$t][$i] ?? [],
426
+                        $all[$i]
427
+                    );
428
+                }
429
+            }
430
+        }
431
+
432
+        // completer les tables principales et auxiliaires
433
+        // avec celles declarees uniquement dans declarer_table_objets_sql
434
+        // pour assurer la compat en transition
435
+        foreach ($infos_tables as $table => $infos) {
436
+            $principale_ou_auxiliaire = ($infos['principale'] ? 'tables_principales' : 'tables_auxiliaires');
437
+            // memoriser des champs eventuels declares par des plugins dans le pipeline tables_xxx
438
+            // qui a ete appelle avant
439
+            $mem = ($GLOBALS[$principale_ou_auxiliaire][$table] ?? []);
440
+            // l'ajouter au tableau
441
+            $GLOBALS[$principale_ou_auxiliaire][$table] = [];
442
+            if (isset($infos['field']) and isset($infos['key'])) {
443
+                foreach (['field', 'key', 'join'] as $k) {
444
+                    if (isset($infos_tables[$table][$k])) {
445
+                        $GLOBALS[$principale_ou_auxiliaire][$table][$k] = &$infos_tables[$table][$k];
446
+                    }
447
+                }
448
+            } else {
449
+                // ici on ne renvoie que les declarations, donc RIEN
450
+                // pour avoir la vrai description en base, il faut passer par trouver_table
451
+                $GLOBALS[$principale_ou_auxiliaire][$table] = [];
452
+            }
453
+            if (is_countable($mem) ? count($mem) : 0) {
454
+                foreach (array_keys($mem) as $k) {
455
+                    if (isset($GLOBALS[$principale_ou_auxiliaire][$table][$k])) {
456
+                        $GLOBALS[$principale_ou_auxiliaire][$table][$k] = array_merge(
457
+                            $GLOBALS[$principale_ou_auxiliaire][$table][$k],
458
+                            $mem[$k]
459
+                        );
460
+                    } else {
461
+                        $GLOBALS[$principale_ou_auxiliaire][$table][$k] = $mem[$k];
462
+                    }
463
+                }
464
+            }
465
+        }
466
+
467
+        // recuperer les interfaces (table_titre, table_date)
468
+        // on ne le fait que dans un second temps pour que table_objet soit fonctionnel
469
+        // dans le pipeline de declarer_tables_interfaces
470
+        include_spip('public/interfaces');
471
+        foreach (array_keys($infos_tables) as $t) {
472
+            $infos_tables[$t] = renseigner_table_objet_interfaces($t, $infos_tables[$t]);
473
+        }
474
+
475
+        $deja_la = false;
476
+        // signature
477
+        $md5 = md5(serialize($infos_tables));
478
+    }
479
+    if ($table_sql === '::md5') {
480
+        return $md5;
481
+    }
482
+    if ($table_sql and !isset($infos_tables[$table_sql])) {
483
+        #$desc = renseigner_table_objet_sql($table_sql,$desc);
484
+        $desc = renseigner_table_objet_interfaces($table_sql, $desc);
485
+
486
+        return $desc;
487
+    }
488
+    if ($table_sql) {
489
+        return $infos_tables[$table_sql] ?? [];
490
+    }
491
+
492
+    return $infos_tables;
493 493
 }
494 494
 
495 495
 
@@ -504,27 +504,27 @@  discard block
 block discarded – undo
504 504
  **/
505 505
 function base_serial(&$tables_principales) {
506 506
 
507
-	$spip_jobs = [
508
-		'id_job' => 'bigint(21) NOT NULL',
509
-		'descriptif' => "text DEFAULT '' NOT NULL",
510
-		'fonction' => 'varchar(255) NOT NULL', //nom de la fonction
511
-		'args' => "longblob DEFAULT '' NOT NULL", // arguments
512
-		'md5args' => "char(32) NOT NULL default ''", // signature des arguments
513
-		'inclure' => 'varchar(255) NOT NULL', // fichier a inclure ou path/ pour charger_fonction
514
-		'priorite' => 'smallint(6) NOT NULL default 0',
515
-		'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL", // date au plus tot
516
-		'status' => 'tinyint NOT NULL default 1',
517
-	];
518
-
519
-	$spip_jobs_key = [
520
-		'PRIMARY KEY' => 'id_job',
521
-		'KEY date' => 'date',
522
-		'KEY status' => 'status',
523
-	];
524
-
525
-	/// Attention: mes_fonctions peut avoir deja defini cette variable
526
-	/// il faut donc rajouter, mais pas reinitialiser
527
-	$tables_principales['spip_jobs'] = ['field' => &$spip_jobs, 'key' => &$spip_jobs_key];
507
+    $spip_jobs = [
508
+        'id_job' => 'bigint(21) NOT NULL',
509
+        'descriptif' => "text DEFAULT '' NOT NULL",
510
+        'fonction' => 'varchar(255) NOT NULL', //nom de la fonction
511
+        'args' => "longblob DEFAULT '' NOT NULL", // arguments
512
+        'md5args' => "char(32) NOT NULL default ''", // signature des arguments
513
+        'inclure' => 'varchar(255) NOT NULL', // fichier a inclure ou path/ pour charger_fonction
514
+        'priorite' => 'smallint(6) NOT NULL default 0',
515
+        'date' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL", // date au plus tot
516
+        'status' => 'tinyint NOT NULL default 1',
517
+    ];
518
+
519
+    $spip_jobs_key = [
520
+        'PRIMARY KEY' => 'id_job',
521
+        'KEY date' => 'date',
522
+        'KEY status' => 'status',
523
+    ];
524
+
525
+    /// Attention: mes_fonctions peut avoir deja defini cette variable
526
+    /// il faut donc rajouter, mais pas reinitialiser
527
+    $tables_principales['spip_jobs'] = ['field' => &$spip_jobs, 'key' => &$spip_jobs_key];
528 528
 }
529 529
 
530 530
 
@@ -536,71 +536,71 @@  discard block
 block discarded – undo
536 536
  * @return void
537 537
  **/
538 538
 function base_auxiliaires(&$tables_auxiliaires) {
539
-	$spip_resultats = [
540
-		'recherche' => "char(16) DEFAULT '' NOT NULL",
541
-		'id' => 'INT UNSIGNED NOT NULL',
542
-		'points' => "INT UNSIGNED DEFAULT '0' NOT NULL",
543
-		'table_objet' => "varchar(30) DEFAULT '' NOT NULL",
544
-		'serveur' => "char(16) DEFAULT '' NOT NULL", // hash md5 partiel du serveur de base ('' pour le serveur principal)
545
-		'maj' => 'TIMESTAMP'
546
-	];
547
-
548
-	$spip_resultats_key = [// pas de cle ni index, ca fait des insertions plus rapides et les requetes jointes utilisees en recheche ne sont pas plus lentes ...
549
-	];
550
-
551
-	$spip_auteurs_liens = [
552
-		'id_auteur' => "bigint(21) DEFAULT '0' NOT NULL",
553
-		'id_objet' => "bigint(21) DEFAULT '0' NOT NULL",
554
-		'objet' => "VARCHAR (25) DEFAULT '' NOT NULL",
555
-		'vu' => "VARCHAR(6) DEFAULT 'non' NOT NULL"
556
-	];
557
-
558
-	$spip_auteurs_liens_key = [
559
-		'PRIMARY KEY' => 'id_auteur,id_objet,objet',
560
-		'KEY id_auteur' => 'id_auteur',
561
-		'KEY id_objet' => 'id_objet',
562
-		'KEY objet' => 'objet',
563
-	];
564
-
565
-	$spip_meta = [
566
-		'nom' => 'VARCHAR (255) NOT NULL',
567
-		'valeur' => "text DEFAULT ''",
568
-		'impt' => "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL",
569
-		'maj' => 'TIMESTAMP'
570
-	];
571
-
572
-	$spip_meta_key = [
573
-		'PRIMARY KEY' => 'nom'
574
-	];
575
-
576
-	$spip_jobs_liens = [
577
-		'id_job' => "bigint(21) DEFAULT '0' NOT NULL",
578
-		'id_objet' => "bigint(21) DEFAULT '0' NOT NULL",
579
-		'objet' => "VARCHAR (25) DEFAULT '' NOT NULL",
580
-	];
581
-
582
-	$spip_jobs_liens_key = [
583
-		'PRIMARY KEY' => 'id_job,id_objet,objet',
584
-		'KEY id_job' => 'id_job'
585
-	];
586
-
587
-	$tables_auxiliaires['spip_auteurs_liens'] = [
588
-		'field' => &$spip_auteurs_liens,
589
-		'key' => &$spip_auteurs_liens_key
590
-	];
591
-
592
-	$tables_auxiliaires['spip_meta'] = [
593
-		'field' => &$spip_meta,
594
-		'key' => &$spip_meta_key
595
-	];
596
-	$tables_auxiliaires['spip_resultats'] = [
597
-		'field' => &$spip_resultats,
598
-		'key' => &$spip_resultats_key
599
-	];
600
-	$tables_auxiliaires['spip_jobs_liens'] = [
601
-		'field' => &$spip_jobs_liens,
602
-		'key' => &$spip_jobs_liens_key
603
-	];
539
+    $spip_resultats = [
540
+        'recherche' => "char(16) DEFAULT '' NOT NULL",
541
+        'id' => 'INT UNSIGNED NOT NULL',
542
+        'points' => "INT UNSIGNED DEFAULT '0' NOT NULL",
543
+        'table_objet' => "varchar(30) DEFAULT '' NOT NULL",
544
+        'serveur' => "char(16) DEFAULT '' NOT NULL", // hash md5 partiel du serveur de base ('' pour le serveur principal)
545
+        'maj' => 'TIMESTAMP'
546
+    ];
547
+
548
+    $spip_resultats_key = [// pas de cle ni index, ca fait des insertions plus rapides et les requetes jointes utilisees en recheche ne sont pas plus lentes ...
549
+    ];
550
+
551
+    $spip_auteurs_liens = [
552
+        'id_auteur' => "bigint(21) DEFAULT '0' NOT NULL",
553
+        'id_objet' => "bigint(21) DEFAULT '0' NOT NULL",
554
+        'objet' => "VARCHAR (25) DEFAULT '' NOT NULL",
555
+        'vu' => "VARCHAR(6) DEFAULT 'non' NOT NULL"
556
+    ];
557
+
558
+    $spip_auteurs_liens_key = [
559
+        'PRIMARY KEY' => 'id_auteur,id_objet,objet',
560
+        'KEY id_auteur' => 'id_auteur',
561
+        'KEY id_objet' => 'id_objet',
562
+        'KEY objet' => 'objet',
563
+    ];
564
+
565
+    $spip_meta = [
566
+        'nom' => 'VARCHAR (255) NOT NULL',
567
+        'valeur' => "text DEFAULT ''",
568
+        'impt' => "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL",
569
+        'maj' => 'TIMESTAMP'
570
+    ];
571
+
572
+    $spip_meta_key = [
573
+        'PRIMARY KEY' => 'nom'
574
+    ];
575
+
576
+    $spip_jobs_liens = [
577
+        'id_job' => "bigint(21) DEFAULT '0' NOT NULL",
578
+        'id_objet' => "bigint(21) DEFAULT '0' NOT NULL",
579
+        'objet' => "VARCHAR (25) DEFAULT '' NOT NULL",
580
+    ];
581
+
582
+    $spip_jobs_liens_key = [
583
+        'PRIMARY KEY' => 'id_job,id_objet,objet',
584
+        'KEY id_job' => 'id_job'
585
+    ];
586
+
587
+    $tables_auxiliaires['spip_auteurs_liens'] = [
588
+        'field' => &$spip_auteurs_liens,
589
+        'key' => &$spip_auteurs_liens_key
590
+    ];
591
+
592
+    $tables_auxiliaires['spip_meta'] = [
593
+        'field' => &$spip_meta,
594
+        'key' => &$spip_meta_key
595
+    ];
596
+    $tables_auxiliaires['spip_resultats'] = [
597
+        'field' => &$spip_resultats,
598
+        'key' => &$spip_resultats_key
599
+    ];
600
+    $tables_auxiliaires['spip_jobs_liens'] = [
601
+        'field' => &$spip_jobs_liens,
602
+        'key' => &$spip_jobs_liens_key
603
+    ];
604 604
 }
605 605
 
606 606
 
@@ -657,129 +657,129 @@  discard block
 block discarded – undo
657 657
  * @return array
658 658
  */
659 659
 function renseigner_table_objet_sql($table_sql, &$infos) {
660
-	if (!isset($infos['type'])) {
661
-		// si on arrive de base/trouver_table, on a la cle primaire :
662
-		// s'en servir pour extrapoler le type
663
-		if (isset($infos['key']['PRIMARY KEY'])) {
664
-			$primary = $infos['key']['PRIMARY KEY'];
665
-			$primary = explode(',', $primary);
666
-			$primary = reset($primary);
667
-			$infos['type'] = preg_replace(',^spip_|^id_|s$,', '', $primary);
668
-		} else {
669
-			$infos['type'] = preg_replace(',^spip_|s$,', '', $table_sql);
670
-		}
671
-	}
672
-	if (!isset($infos['type_surnoms'])) {
673
-		$infos['type_surnoms'] = [];
674
-	}
675
-
676
-	if (!isset($infos['table_objet'])) {
677
-		$infos['table_objet'] = preg_replace(',^spip_,', '', $table_sql);
678
-	}
679
-	if (!isset($infos['table_objet_surnoms'])) {
680
-		$infos['table_objet_surnoms'] = [];
681
-	}
682
-
683
-	if (!isset($infos['principale'])) {
684
-		$infos['principale'] = (isset($GLOBALS['tables_principales'][$table_sql]) ? 'oui' : false);
685
-	}
686
-
687
-	// normaliser pour pouvoir tester en php $infos['principale']?
688
-	// et dans une boucle {principale=oui}
689
-	$infos['principale'] = (($infos['principale'] and $infos['principale'] != 'non') ? 'oui' : false);
690
-
691
-	// declarer et normaliser pour pouvoir tester en php $infos['editable']?
692
-	// et dans une boucle {editable=oui}
693
-	if (!isset($infos['editable'])) {
694
-		$infos['editable'] = 'oui';
695
-	}
696
-
697
-	$infos['editable'] = (($infos['editable'] and $infos['editable'] != 'non') ? 'oui' : false);
698
-
699
-	// les urls publiques sont par defaut page=type pour les tables principales, et rien pour les autres
700
-	// seules les exceptions sont donc a declarer
701
-	if (!isset($infos['page'])) {
702
-		$infos['page'] = ($infos['principale'] ? $infos['type'] : '');
703
-	}
704
-
705
-	if (!isset($infos['url_voir'])) {
706
-		$infos['url_voir'] = $infos['type'];
707
-	}
708
-	if (!isset($infos['url_edit'])) {
709
-		$infos['url_edit'] = $infos['url_voir'] . ($infos['editable'] ? '_edit' : '');
710
-	}
711
-	if (!isset($infos['icone_objet'])) {
712
-		$infos['icone_objet'] = $infos['type'];
713
-	}
714
-
715
-	// chaines de langue
716
-	// par defaut : objet:icone_xxx_objet
717
-	if (!isset($infos['texte_retour'])) {
718
-		$infos['texte_retour'] = 'icone_retour';
719
-	}
720
-	if (!isset($infos['texte_modifier'])) {
721
-		$infos['texte_modifier'] = $infos['type'] . ':' . 'icone_modifier_' . $infos['type'];
722
-	}
723
-	if (!isset($infos['texte_creer'])) {
724
-		$infos['texte_creer'] = $infos['type'] . ':' . 'icone_creer_' . $infos['type'];
725
-	}
726
-	if (!isset($infos['texte_creer_associer'])) {
727
-		$infos['texte_creer_associer'] = $infos['type'] . ':' . 'texte_creer_associer_' . $infos['type'];
728
-	}
729
-	if (!isset($infos['texte_ajouter'])) {
730
-		// Ajouter un X
731
-		$infos['texte_ajouter'] = $infos['type'] . ':' . 'texte_ajouter_' . $infos['type'];
732
-	}
733
-	if (!isset($infos['texte_objets'])) {
734
-		$infos['texte_objets'] = $infos['type'] . ':' . 'titre_' . $infos['table_objet'];
735
-	}
736
-	if (!isset($infos['texte_objet'])) {
737
-		$infos['texte_objet'] = $infos['type'] . ':' . 'titre_' . $infos['type'];
738
-	}
739
-	if (!isset($infos['texte_logo_objet'])) {
740
-		// objet:titre_logo_objet "Logo de ce X"
741
-		$infos['texte_logo_objet'] = $infos['type'] . ':' . 'titre_logo_' . $infos['type'];
742
-	}
743
-	if (!isset($infos['texte_langue_objet'])) {
744
-		// objet:texte_langue_objet "Langue de ce X"
745
-		$infos['texte_langue_objet'] = $infos['type'] . ':' . 'titre_langue_' . $infos['type'];
746
-	}
747
-	if (!isset($infos['texte_definir_comme_traduction_objet'])) {
748
-		// "Ce X est une traduction du X numéro :"
749
-		$infos['texte_definir_comme_traduction_objet'] = $infos['type'] . ':' . 'texte_definir_comme_traduction_' . $infos['type'];
750
-	}
751
-
752
-	// objet:info_aucun_objet
753
-	if (!isset($infos['info_aucun_objet'])) {
754
-		$infos['info_aucun_objet'] = $infos['type'] . ':' . 'info_aucun_' . $infos['type'];
755
-	}
756
-	// objet:info_1_objet
757
-	if (!isset($infos['info_1_objet'])) {
758
-		$infos['info_1_objet'] = $infos['type'] . ':' . 'info_1_' . $infos['type'];
759
-	}
760
-	// objet:info_nb_objets
761
-	if (!isset($infos['info_nb_objets'])) {
762
-		$infos['info_nb_objets'] = $infos['type'] . ':' . 'info_nb_' . $infos['table_objet'];
763
-	}
764
-
765
-	if (!isset($infos['champs_editables'])) {
766
-		$infos['champs_editables'] = [];
767
-	}
768
-	if (!isset($infos['champs_versionnes'])) {
769
-		$infos['champs_versionnes'] = [];
770
-	}
771
-	if (!isset($infos['rechercher_champs'])) {
772
-		$infos['rechercher_champs'] = [];
773
-	}
774
-	if (!isset($infos['rechercher_jointures'])) {
775
-		$infos['rechercher_jointures'] = [];
776
-	}
777
-
778
-	if (!isset($infos['modeles'])) {
779
-		$infos['modeles'] = [$infos['type']];
780
-	}
781
-
782
-	return $infos;
660
+    if (!isset($infos['type'])) {
661
+        // si on arrive de base/trouver_table, on a la cle primaire :
662
+        // s'en servir pour extrapoler le type
663
+        if (isset($infos['key']['PRIMARY KEY'])) {
664
+            $primary = $infos['key']['PRIMARY KEY'];
665
+            $primary = explode(',', $primary);
666
+            $primary = reset($primary);
667
+            $infos['type'] = preg_replace(',^spip_|^id_|s$,', '', $primary);
668
+        } else {
669
+            $infos['type'] = preg_replace(',^spip_|s$,', '', $table_sql);
670
+        }
671
+    }
672
+    if (!isset($infos['type_surnoms'])) {
673
+        $infos['type_surnoms'] = [];
674
+    }
675
+
676
+    if (!isset($infos['table_objet'])) {
677
+        $infos['table_objet'] = preg_replace(',^spip_,', '', $table_sql);
678
+    }
679
+    if (!isset($infos['table_objet_surnoms'])) {
680
+        $infos['table_objet_surnoms'] = [];
681
+    }
682
+
683
+    if (!isset($infos['principale'])) {
684
+        $infos['principale'] = (isset($GLOBALS['tables_principales'][$table_sql]) ? 'oui' : false);
685
+    }
686
+
687
+    // normaliser pour pouvoir tester en php $infos['principale']?
688
+    // et dans une boucle {principale=oui}
689
+    $infos['principale'] = (($infos['principale'] and $infos['principale'] != 'non') ? 'oui' : false);
690
+
691
+    // declarer et normaliser pour pouvoir tester en php $infos['editable']?
692
+    // et dans une boucle {editable=oui}
693
+    if (!isset($infos['editable'])) {
694
+        $infos['editable'] = 'oui';
695
+    }
696
+
697
+    $infos['editable'] = (($infos['editable'] and $infos['editable'] != 'non') ? 'oui' : false);
698
+
699
+    // les urls publiques sont par defaut page=type pour les tables principales, et rien pour les autres
700
+    // seules les exceptions sont donc a declarer
701
+    if (!isset($infos['page'])) {
702
+        $infos['page'] = ($infos['principale'] ? $infos['type'] : '');
703
+    }
704
+
705
+    if (!isset($infos['url_voir'])) {
706
+        $infos['url_voir'] = $infos['type'];
707
+    }
708
+    if (!isset($infos['url_edit'])) {
709
+        $infos['url_edit'] = $infos['url_voir'] . ($infos['editable'] ? '_edit' : '');
710
+    }
711
+    if (!isset($infos['icone_objet'])) {
712
+        $infos['icone_objet'] = $infos['type'];
713
+    }
714
+
715
+    // chaines de langue
716
+    // par defaut : objet:icone_xxx_objet
717
+    if (!isset($infos['texte_retour'])) {
718
+        $infos['texte_retour'] = 'icone_retour';
719
+    }
720
+    if (!isset($infos['texte_modifier'])) {
721
+        $infos['texte_modifier'] = $infos['type'] . ':' . 'icone_modifier_' . $infos['type'];
722
+    }
723
+    if (!isset($infos['texte_creer'])) {
724
+        $infos['texte_creer'] = $infos['type'] . ':' . 'icone_creer_' . $infos['type'];
725
+    }
726
+    if (!isset($infos['texte_creer_associer'])) {
727
+        $infos['texte_creer_associer'] = $infos['type'] . ':' . 'texte_creer_associer_' . $infos['type'];
728
+    }
729
+    if (!isset($infos['texte_ajouter'])) {
730
+        // Ajouter un X
731
+        $infos['texte_ajouter'] = $infos['type'] . ':' . 'texte_ajouter_' . $infos['type'];
732
+    }
733
+    if (!isset($infos['texte_objets'])) {
734
+        $infos['texte_objets'] = $infos['type'] . ':' . 'titre_' . $infos['table_objet'];
735
+    }
736
+    if (!isset($infos['texte_objet'])) {
737
+        $infos['texte_objet'] = $infos['type'] . ':' . 'titre_' . $infos['type'];
738
+    }
739
+    if (!isset($infos['texte_logo_objet'])) {
740
+        // objet:titre_logo_objet "Logo de ce X"
741
+        $infos['texte_logo_objet'] = $infos['type'] . ':' . 'titre_logo_' . $infos['type'];
742
+    }
743
+    if (!isset($infos['texte_langue_objet'])) {
744
+        // objet:texte_langue_objet "Langue de ce X"
745
+        $infos['texte_langue_objet'] = $infos['type'] . ':' . 'titre_langue_' . $infos['type'];
746
+    }
747
+    if (!isset($infos['texte_definir_comme_traduction_objet'])) {
748
+        // "Ce X est une traduction du X numéro :"
749
+        $infos['texte_definir_comme_traduction_objet'] = $infos['type'] . ':' . 'texte_definir_comme_traduction_' . $infos['type'];
750
+    }
751
+
752
+    // objet:info_aucun_objet
753
+    if (!isset($infos['info_aucun_objet'])) {
754
+        $infos['info_aucun_objet'] = $infos['type'] . ':' . 'info_aucun_' . $infos['type'];
755
+    }
756
+    // objet:info_1_objet
757
+    if (!isset($infos['info_1_objet'])) {
758
+        $infos['info_1_objet'] = $infos['type'] . ':' . 'info_1_' . $infos['type'];
759
+    }
760
+    // objet:info_nb_objets
761
+    if (!isset($infos['info_nb_objets'])) {
762
+        $infos['info_nb_objets'] = $infos['type'] . ':' . 'info_nb_' . $infos['table_objet'];
763
+    }
764
+
765
+    if (!isset($infos['champs_editables'])) {
766
+        $infos['champs_editables'] = [];
767
+    }
768
+    if (!isset($infos['champs_versionnes'])) {
769
+        $infos['champs_versionnes'] = [];
770
+    }
771
+    if (!isset($infos['rechercher_champs'])) {
772
+        $infos['rechercher_champs'] = [];
773
+    }
774
+    if (!isset($infos['rechercher_jointures'])) {
775
+        $infos['rechercher_jointures'] = [];
776
+    }
777
+
778
+    if (!isset($infos['modeles'])) {
779
+        $infos['modeles'] = [$infos['type']];
780
+    }
781
+
782
+    return $infos;
783 783
 }
784 784
 
785 785
 /**
@@ -796,30 +796,30 @@  discard block
 block discarded – undo
796 796
  * @return array
797 797
  */
798 798
 function renseigner_table_objet_interfaces($table_sql, &$infos) {
799
-	if (!isset($infos['titre'])) {
800
-		if (isset($infos['table_objet']) and isset($GLOBALS['table_titre'][$infos['table_objet']])) {
801
-			$infos['titre'] = $GLOBALS['table_titre'][$infos['table_objet']];
802
-		} else {
803
-			$infos['titre'] = ((isset($infos['field']['titre'])) ? 'titre,' : "'' as titre,");
804
-			$infos['titre'] .= ((isset($infos['field']['lang'])) ? 'lang' : "'' as lang");
805
-		}
806
-	}
807
-	if (!isset($infos['date'])) {
808
-		if (isset($infos['table_objet']) and isset($GLOBALS['table_date'][$infos['table_objet']])) {
809
-			$infos['date'] = $GLOBALS['table_date'][$infos['table_objet']];
810
-		} else {
811
-			$infos['date'] = ((isset($infos['field']['date'])) ? 'date' : '');
812
-		}
813
-	}
814
-
815
-	$infos['statut'] ??= $GLOBALS['table_statut'][$table_sql] ?? '';
816
-	$infos['tables_jointures'] ??= [];
817
-
818
-	if (isset($GLOBALS['tables_jointures'][$table_sql])) {
819
-		$infos['tables_jointures'] = array_merge($infos['tables_jointures'], $GLOBALS['tables_jointures'][$table_sql]);
820
-	}
821
-
822
-	return $infos;
799
+    if (!isset($infos['titre'])) {
800
+        if (isset($infos['table_objet']) and isset($GLOBALS['table_titre'][$infos['table_objet']])) {
801
+            $infos['titre'] = $GLOBALS['table_titre'][$infos['table_objet']];
802
+        } else {
803
+            $infos['titre'] = ((isset($infos['field']['titre'])) ? 'titre,' : "'' as titre,");
804
+            $infos['titre'] .= ((isset($infos['field']['lang'])) ? 'lang' : "'' as lang");
805
+        }
806
+    }
807
+    if (!isset($infos['date'])) {
808
+        if (isset($infos['table_objet']) and isset($GLOBALS['table_date'][$infos['table_objet']])) {
809
+            $infos['date'] = $GLOBALS['table_date'][$infos['table_objet']];
810
+        } else {
811
+            $infos['date'] = ((isset($infos['field']['date'])) ? 'date' : '');
812
+        }
813
+    }
814
+
815
+    $infos['statut'] ??= $GLOBALS['table_statut'][$table_sql] ?? '';
816
+    $infos['tables_jointures'] ??= [];
817
+
818
+    if (isset($GLOBALS['tables_jointures'][$table_sql])) {
819
+        $infos['tables_jointures'] = array_merge($infos['tables_jointures'], $GLOBALS['tables_jointures'][$table_sql]);
820
+    }
821
+
822
+    return $infos;
823 823
 }
824 824
 
825 825
 /**
@@ -830,13 +830,13 @@  discard block
 block discarded – undo
830 830
  *     Liste et descriptions des tables principales
831 831
  **/
832 832
 function lister_tables_principales() {
833
-	static $done = false;
834
-	if (!$done or !(is_countable($GLOBALS['tables_principales']) ? count($GLOBALS['tables_principales']) : 0)) {
835
-		lister_tables_objets_sql();
836
-		$done = true;
837
-	}
833
+    static $done = false;
834
+    if (!$done or !(is_countable($GLOBALS['tables_principales']) ? count($GLOBALS['tables_principales']) : 0)) {
835
+        lister_tables_objets_sql();
836
+        $done = true;
837
+    }
838 838
 
839
-	return $GLOBALS['tables_principales'];
839
+    return $GLOBALS['tables_principales'];
840 840
 }
841 841
 
842 842
 /**
@@ -847,13 +847,13 @@  discard block
 block discarded – undo
847 847
  *     Liste et descriptions des tables auxiliaires
848 848
  **/
849 849
 function lister_tables_auxiliaires() {
850
-	static $done = false;
851
-	if (!$done or !(is_countable($GLOBALS['tables_auxiliaires']) ? count($GLOBALS['tables_auxiliaires']) : 0)) {
852
-		lister_tables_objets_sql();
853
-		$done = true;
854
-	}
850
+    static $done = false;
851
+    if (!$done or !(is_countable($GLOBALS['tables_auxiliaires']) ? count($GLOBALS['tables_auxiliaires']) : 0)) {
852
+        lister_tables_objets_sql();
853
+        $done = true;
854
+    }
855 855
 
856
-	return $GLOBALS['tables_auxiliaires'];
856
+    return $GLOBALS['tables_auxiliaires'];
857 857
 }
858 858
 
859 859
 /**
@@ -862,45 +862,45 @@  discard block
 block discarded – undo
862 862
  * @return array
863 863
  */
864 864
 function lister_tables_objets_surnoms() {
865
-	static $surnoms = null;
866
-	static $md5 = null;
867
-	if (
868
-		!$surnoms
869
-		or $md5 != lister_tables_objets_sql('::md5')
870
-	) {
871
-		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
872
-		// pour compatibilite, car il faut dorenavent utiliser
873
-		// declarer_table_objets_sql
874
-		$surnoms = pipeline(
875
-			'declarer_tables_objets_surnoms',
876
-			[
877
-				# pour les modeles
878
-				# a enlever ?
879
-				'doc' => 'documents',
880
-				'img' => 'documents',
881
-				'emb' => 'documents',
882
-			]
883
-		);
884
-		$infos_tables = lister_tables_objets_sql();
885
-		foreach ($infos_tables as $t => $infos) {
886
-			// cas de base type=>table
887
-			// et preg_replace(',^spip_|^id_|s$,',table)=>table
888
-			if ($infos['table_objet']) { // securite, si la fonction est appelee trop tot, c'est vide
889
-				// optimisations pour table_objet
890
-				//$surnoms[$infos['type']] = $infos['table_objet'];
891
-				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['table_objet'];
892
-				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['table_objet'];
893
-				if (is_array($infos['table_objet_surnoms']) and count($infos['table_objet_surnoms'])) {
894
-					foreach ($infos['table_objet_surnoms'] as $surnom) {
895
-						$surnoms[$surnom] = $infos['table_objet'];
896
-					}
897
-				}
898
-			}
899
-		}
900
-		$md5 = lister_tables_objets_sql('::md5');
901
-	}
902
-
903
-	return $surnoms;
865
+    static $surnoms = null;
866
+    static $md5 = null;
867
+    if (
868
+        !$surnoms
869
+        or $md5 != lister_tables_objets_sql('::md5')
870
+    ) {
871
+        // passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
872
+        // pour compatibilite, car il faut dorenavent utiliser
873
+        // declarer_table_objets_sql
874
+        $surnoms = pipeline(
875
+            'declarer_tables_objets_surnoms',
876
+            [
877
+                # pour les modeles
878
+                # a enlever ?
879
+                'doc' => 'documents',
880
+                'img' => 'documents',
881
+                'emb' => 'documents',
882
+            ]
883
+        );
884
+        $infos_tables = lister_tables_objets_sql();
885
+        foreach ($infos_tables as $t => $infos) {
886
+            // cas de base type=>table
887
+            // et preg_replace(',^spip_|^id_|s$,',table)=>table
888
+            if ($infos['table_objet']) { // securite, si la fonction est appelee trop tot, c'est vide
889
+                // optimisations pour table_objet
890
+                //$surnoms[$infos['type']] = $infos['table_objet'];
891
+                $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['table_objet'];
892
+                $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['table_objet'];
893
+                if (is_array($infos['table_objet_surnoms']) and count($infos['table_objet_surnoms'])) {
894
+                    foreach ($infos['table_objet_surnoms'] as $surnom) {
895
+                        $surnoms[$surnom] = $infos['table_objet'];
896
+                    }
897
+                }
898
+            }
899
+        }
900
+        $md5 = lister_tables_objets_sql('::md5');
901
+    }
902
+
903
+    return $surnoms;
904 904
 }
905 905
 
906 906
 /**
@@ -909,35 +909,35 @@  discard block
 block discarded – undo
909 909
  * @return array
910 910
  */
911 911
 function lister_types_surnoms() {
912
-	static $surnoms = null;
913
-	static $md5 = null;
914
-	if (
915
-		!$surnoms
916
-		or $md5 != lister_tables_objets_sql('::md5')
917
-	) {
918
-		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
919
-		// pour compatibilite, car il faut dorenavent utiliser
920
-		// declarer_table_objets_sql
921
-		$surnoms = pipeline('declarer_type_surnoms', ['racine-site' => 'site']);
922
-		$infos_tables = lister_tables_objets_sql();
923
-		foreach ($infos_tables as $t => $infos) {
924
-			if ($infos['type']) { // securite, si la fonction est appelee trop tot, c'est vide
925
-				// optimisations pour objet_type
926
-				//$surnoms[$infos['type']] = $infos['type'];
927
-				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['type'];
928
-				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['type'];
929
-				// surnoms declares
930
-				if (is_array($infos['type_surnoms']) and count($infos['type_surnoms'])) {
931
-					foreach ($infos['type_surnoms'] as $surnom) {
932
-						$surnoms[$surnom] = $infos['type'];
933
-					}
934
-				}
935
-			}
936
-		}
937
-		$md5 = lister_tables_objets_sql('::md5');
938
-	}
939
-
940
-	return $surnoms;
912
+    static $surnoms = null;
913
+    static $md5 = null;
914
+    if (
915
+        !$surnoms
916
+        or $md5 != lister_tables_objets_sql('::md5')
917
+    ) {
918
+        // passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
919
+        // pour compatibilite, car il faut dorenavent utiliser
920
+        // declarer_table_objets_sql
921
+        $surnoms = pipeline('declarer_type_surnoms', ['racine-site' => 'site']);
922
+        $infos_tables = lister_tables_objets_sql();
923
+        foreach ($infos_tables as $t => $infos) {
924
+            if ($infos['type']) { // securite, si la fonction est appelee trop tot, c'est vide
925
+                // optimisations pour objet_type
926
+                //$surnoms[$infos['type']] = $infos['type'];
927
+                $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['type'];
928
+                $surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['type'];
929
+                // surnoms declares
930
+                if (is_array($infos['type_surnoms']) and count($infos['type_surnoms'])) {
931
+                    foreach ($infos['type_surnoms'] as $surnom) {
932
+                        $surnoms[$surnom] = $infos['type'];
933
+                    }
934
+                }
935
+            }
936
+        }
937
+        $md5 = lister_tables_objets_sql('::md5');
938
+    }
939
+
940
+    return $surnoms;
941 941
 }
942 942
 
943 943
 /**
@@ -951,22 +951,22 @@  discard block
 block discarded – undo
951 951
  *     Couples (nom de la table SQL => même nom, sans 'spip_' devant)
952 952
  **/
953 953
 function lister_tables_spip($serveur = '') {
954
-	static $tables = [];
955
-	if (!isset($tables[$serveur])) {
956
-		$tables[$serveur] = [];
957
-		if (!function_exists('sql_alltable')) {
958
-			include_spip('base/abstract_sql');
959
-		}
960
-		$ts = sql_alltable(null, $serveur); // toutes les tables "spip_" (ou prefixe perso)
961
-		$connexion = $GLOBALS['connexions'][$serveur ?: 0];
962
-		$spip = $connexion['prefixe'] . '_';
963
-		foreach ($ts as $t) {
964
-			$t = substr($t, strlen($spip));
965
-			$tables[$serveur]["spip_$t"] = $t;
966
-		}
967
-	}
968
-
969
-	return $tables[$serveur];
954
+    static $tables = [];
955
+    if (!isset($tables[$serveur])) {
956
+        $tables[$serveur] = [];
957
+        if (!function_exists('sql_alltable')) {
958
+            include_spip('base/abstract_sql');
959
+        }
960
+        $ts = sql_alltable(null, $serveur); // toutes les tables "spip_" (ou prefixe perso)
961
+        $connexion = $GLOBALS['connexions'][$serveur ?: 0];
962
+        $spip = $connexion['prefixe'] . '_';
963
+        foreach ($ts as $t) {
964
+            $t = substr($t, strlen($spip));
965
+            $tables[$serveur]["spip_$t"] = $t;
966
+        }
967
+    }
968
+
969
+    return $tables[$serveur];
970 970
 }
971 971
 
972 972
 
@@ -981,18 +981,18 @@  discard block
 block discarded – undo
981 981
  *     Couples (nom de la table SQL => même nom)
982 982
  **/
983 983
 function lister_toutes_tables($serveur) {
984
-	static $tables = [];
985
-	if (!isset($tables[$serveur])) {
986
-		$tables[$serveur] = [];
987
-		if (!function_exists('sql_alltable')) {
988
-			include_spip('base/abstract_sql');
989
-		}
990
-		$ts = sql_alltable('%', $serveur); // toutes les tables
991
-		foreach ($ts as $t) {
992
-			$tables[$serveur][$t] = $t;
993
-		}
994
-	}
995
-	return $tables[$serveur];
984
+    static $tables = [];
985
+    if (!isset($tables[$serveur])) {
986
+        $tables[$serveur] = [];
987
+        if (!function_exists('sql_alltable')) {
988
+            include_spip('base/abstract_sql');
989
+        }
990
+        $ts = sql_alltable('%', $serveur); // toutes les tables
991
+        foreach ($ts as $t) {
992
+            $tables[$serveur][$t] = $t;
993
+        }
994
+    }
995
+    return $tables[$serveur];
996 996
 }
997 997
 
998 998
 /**
@@ -1013,39 +1013,39 @@  discard block
 block discarded – undo
1013 1013
  **/
1014 1014
 function table_objet(string $type, string $serveur = ''): string {
1015 1015
 
1016
-	if ($type) {
1017
-		$type = preg_replace(',^spip_|^id_|s$,', '', $type);
1018
-	}
1019
-	if (!strlen($type)) {
1020
-		return '';
1021
-	}
1022
-
1023
-	$surnoms = lister_tables_objets_surnoms();
1024
-	if (isset($surnoms[$type])) {
1025
-		return $surnoms[$type];
1026
-	}
1027
-
1028
-	if ($serveur !== false) {
1029
-		$t = lister_tables_spip($serveur);
1030
-		$trouver_table = charger_fonction('trouver_table', 'base');
1031
-		$typetrim = rtrim($type, 's') . 's';
1032
-		if (
1033
-			(isset($t[$typetrim]) or in_array($typetrim, $t))
1034
-			and ($desc = $trouver_table(rtrim($type, 's') . 's', $serveur))
1035
-		) {
1036
-			return $desc['id_table'];
1037
-		} elseif (
1038
-			(isset($t[$type]) or in_array($type, $t))
1039
-			and ($desc = $trouver_table($type, $serveur))
1040
-		) {
1041
-			return $desc['id_table'];
1042
-		}
1043
-
1044
-		spip_log('table_objet(' . $type . ') calculee sans verification');
1045
-		#spip_log(debug_backtrace(),'db');
1046
-	}
1047
-
1048
-	return rtrim($type, 's') . 's'; # cas historique ne devant plus servir, sauf si $serveur=false
1016
+    if ($type) {
1017
+        $type = preg_replace(',^spip_|^id_|s$,', '', $type);
1018
+    }
1019
+    if (!strlen($type)) {
1020
+        return '';
1021
+    }
1022
+
1023
+    $surnoms = lister_tables_objets_surnoms();
1024
+    if (isset($surnoms[$type])) {
1025
+        return $surnoms[$type];
1026
+    }
1027
+
1028
+    if ($serveur !== false) {
1029
+        $t = lister_tables_spip($serveur);
1030
+        $trouver_table = charger_fonction('trouver_table', 'base');
1031
+        $typetrim = rtrim($type, 's') . 's';
1032
+        if (
1033
+            (isset($t[$typetrim]) or in_array($typetrim, $t))
1034
+            and ($desc = $trouver_table(rtrim($type, 's') . 's', $serveur))
1035
+        ) {
1036
+            return $desc['id_table'];
1037
+        } elseif (
1038
+            (isset($t[$type]) or in_array($type, $t))
1039
+            and ($desc = $trouver_table($type, $serveur))
1040
+        ) {
1041
+            return $desc['id_table'];
1042
+        }
1043
+
1044
+        spip_log('table_objet(' . $type . ') calculee sans verification');
1045
+        #spip_log(debug_backtrace(),'db');
1046
+    }
1047
+
1048
+    return rtrim($type, 's') . 's'; # cas historique ne devant plus servir, sauf si $serveur=false
1049 1049
 }
1050 1050
 
1051 1051
 /**
@@ -1066,33 +1066,33 @@  discard block
 block discarded – undo
1066 1066
  **/
1067 1067
 function table_objet_sql(string $type, string $serveur = ''): string {
1068 1068
 
1069
-	$nom = table_objet($type, $serveur);
1070
-	if (!strlen($nom)) {
1071
-		return '';
1072
-	}
1073
-	if (!isset($GLOBALS['table_des_tables']['articles'])) {
1074
-		// eviter de multiples inclusions
1075
-		include_spip('public/interfaces');
1076
-	}
1077
-	if (isset($GLOBALS['table_des_tables'][$nom])) {
1078
-		$nom = $GLOBALS['table_des_tables'][$nom];
1079
-		$nom = "spip_$nom";
1080
-	} else {
1081
-		$infos_tables = lister_tables_objets_sql();
1082
-		if (isset($infos_tables["spip_$nom"])) {
1083
-			$nom = "spip_$nom";
1084
-		} elseif ($serveur !== false) {
1085
-			$t = lister_tables_spip($serveur);
1086
-			if (isset($t[$nom]) or in_array($nom, $t)) {
1087
-				$trouver_table = charger_fonction('trouver_table', 'base');
1088
-				if ($desc = $trouver_table($nom, $serveur)) {
1089
-					return $desc['table_sql'];
1090
-				}
1091
-			}
1092
-		}
1093
-	}
1094
-
1095
-	return $nom;
1069
+    $nom = table_objet($type, $serveur);
1070
+    if (!strlen($nom)) {
1071
+        return '';
1072
+    }
1073
+    if (!isset($GLOBALS['table_des_tables']['articles'])) {
1074
+        // eviter de multiples inclusions
1075
+        include_spip('public/interfaces');
1076
+    }
1077
+    if (isset($GLOBALS['table_des_tables'][$nom])) {
1078
+        $nom = $GLOBALS['table_des_tables'][$nom];
1079
+        $nom = "spip_$nom";
1080
+    } else {
1081
+        $infos_tables = lister_tables_objets_sql();
1082
+        if (isset($infos_tables["spip_$nom"])) {
1083
+            $nom = "spip_$nom";
1084
+        } elseif ($serveur !== false) {
1085
+            $t = lister_tables_spip($serveur);
1086
+            if (isset($t[$nom]) or in_array($nom, $t)) {
1087
+                $trouver_table = charger_fonction('trouver_table', 'base');
1088
+                if ($desc = $trouver_table($nom, $serveur)) {
1089
+                    return $desc['table_sql'];
1090
+                }
1091
+            }
1092
+        }
1093
+    }
1094
+
1095
+    return $nom;
1096 1096
 }
1097 1097
 
1098 1098
 /**
@@ -1111,35 +1111,35 @@  discard block
 block discarded – undo
1111 1111
  *     Nom de la clé primaire
1112 1112
  **/
1113 1113
 function id_table_objet(string $type, string $serveur = ''): ?string {
1114
-	static $trouver_table = null;
1115
-	$type = objet_type($type, $serveur);
1116
-	if (!$type) {
1117
-		return null;
1118
-	}
1119
-	$t = table_objet($type);
1120
-	if (!$trouver_table) {
1121
-		$trouver_table = charger_fonction('trouver_table', 'base');
1122
-	}
1123
-
1124
-	$ts = lister_tables_spip($serveur);
1125
-	if (
1126
-		in_array($t, $ts)
1127
-		or in_array($t, lister_toutes_tables($serveur))
1128
-	) {
1129
-		$desc = $trouver_table($t, $serveur);
1130
-		if (isset($desc['key']['PRIMARY KEY'])) {
1131
-			return $desc['key']['PRIMARY KEY'];
1132
-		}
1133
-		if (!$desc or isset($desc['field']["id_$type"])) {
1134
-			return "id_$type";
1135
-		}
1136
-		// sinon renvoyer le premier champ de la table...
1137
-		$keys = array_keys($desc['field']);
1138
-
1139
-		return array_shift($keys);
1140
-	}
1141
-
1142
-	return "id_$type";
1114
+    static $trouver_table = null;
1115
+    $type = objet_type($type, $serveur);
1116
+    if (!$type) {
1117
+        return null;
1118
+    }
1119
+    $t = table_objet($type);
1120
+    if (!$trouver_table) {
1121
+        $trouver_table = charger_fonction('trouver_table', 'base');
1122
+    }
1123
+
1124
+    $ts = lister_tables_spip($serveur);
1125
+    if (
1126
+        in_array($t, $ts)
1127
+        or in_array($t, lister_toutes_tables($serveur))
1128
+    ) {
1129
+        $desc = $trouver_table($t, $serveur);
1130
+        if (isset($desc['key']['PRIMARY KEY'])) {
1131
+            return $desc['key']['PRIMARY KEY'];
1132
+        }
1133
+        if (!$desc or isset($desc['field']["id_$type"])) {
1134
+            return "id_$type";
1135
+        }
1136
+        // sinon renvoyer le premier champ de la table...
1137
+        $keys = array_keys($desc['field']);
1138
+
1139
+        return array_shift($keys);
1140
+    }
1141
+
1142
+    return "id_$type";
1143 1143
 }
1144 1144
 
1145 1145
 /**
@@ -1158,60 +1158,60 @@  discard block
 block discarded – undo
1158 1158
  *     Type de l'objet
1159 1159
  **/
1160 1160
 function objet_type(string $table_objet, string $serveur = ''): ?string {
1161
-	if (!$table_objet) {
1162
-		return null;
1163
-	}
1164
-	$surnoms = lister_types_surnoms();
1165
-
1166
-	// scenario de base
1167
-	// le type est decline a partir du nom de la table en enlevant le prefixe eventuel
1168
-	// et la marque du pluriel
1169
-	// on accepte id_xx en entree aussi
1170
-	$type = preg_replace(',^spip_|^id_|s$,', '', $table_objet);
1171
-	if (isset($surnoms[$type])) {
1172
-		return $surnoms[$type];
1173
-	}
1174
-
1175
-	// securite : eliminer les caracteres non \w
1176
-	$type = preg_replace(',[^\w-],', '', $type);
1177
-
1178
-	// si le type redonne bien la table c'est bon
1179
-	// oui si table_objet ressemblait deja a un type
1180
-	if (
1181
-		$type == $table_objet
1182
-		or (table_objet($type, $serveur) == $table_objet)
1183
-		or (table_objet_sql($type, $serveur) == $table_objet)
1184
-	) {
1185
-		return $type;
1186
-	}
1187
-
1188
-	// si on ne veut pas chercher en base
1189
-	if ($serveur === false) {
1190
-		return $type;
1191
-	}
1192
-
1193
-	// sinon on passe par la cle primaire id_xx pour trouver le type
1194
-	// car le s a la fin est incertain
1195
-	// notamment en cas de pluriel derogatoire
1196
-	// id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
1197
-	// une declaration jeu => jeux, journal => journaux
1198
-	// dans le pipeline declarer_tables_objets_surnoms
1199
-	$trouver_table = charger_fonction('trouver_table', 'base');
1200
-	$ts = lister_tables_spip($serveur);
1201
-	$desc = false;
1202
-	if (in_array($table_objet, $ts)) {
1203
-		$desc = $trouver_table($table_objet);
1204
-	}
1205
-	if (!$desc and in_array($table_objet = table_objet($type, $serveur), $ts)) {
1206
-		$desc = $trouver_table($table_objet, $serveur);
1207
-	}
1208
-	// si le type est declare : bingo !
1209
-	if ($desc and isset($desc['type'])) {
1210
-		return $desc['type'];
1211
-	}
1212
-
1213
-	// on a fait ce qu'on a pu
1214
-	return $type;
1161
+    if (!$table_objet) {
1162
+        return null;
1163
+    }
1164
+    $surnoms = lister_types_surnoms();
1165
+
1166
+    // scenario de base
1167
+    // le type est decline a partir du nom de la table en enlevant le prefixe eventuel
1168
+    // et la marque du pluriel
1169
+    // on accepte id_xx en entree aussi
1170
+    $type = preg_replace(',^spip_|^id_|s$,', '', $table_objet);
1171
+    if (isset($surnoms[$type])) {
1172
+        return $surnoms[$type];
1173
+    }
1174
+
1175
+    // securite : eliminer les caracteres non \w
1176
+    $type = preg_replace(',[^\w-],', '', $type);
1177
+
1178
+    // si le type redonne bien la table c'est bon
1179
+    // oui si table_objet ressemblait deja a un type
1180
+    if (
1181
+        $type == $table_objet
1182
+        or (table_objet($type, $serveur) == $table_objet)
1183
+        or (table_objet_sql($type, $serveur) == $table_objet)
1184
+    ) {
1185
+        return $type;
1186
+    }
1187
+
1188
+    // si on ne veut pas chercher en base
1189
+    if ($serveur === false) {
1190
+        return $type;
1191
+    }
1192
+
1193
+    // sinon on passe par la cle primaire id_xx pour trouver le type
1194
+    // car le s a la fin est incertain
1195
+    // notamment en cas de pluriel derogatoire
1196
+    // id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
1197
+    // une declaration jeu => jeux, journal => journaux
1198
+    // dans le pipeline declarer_tables_objets_surnoms
1199
+    $trouver_table = charger_fonction('trouver_table', 'base');
1200
+    $ts = lister_tables_spip($serveur);
1201
+    $desc = false;
1202
+    if (in_array($table_objet, $ts)) {
1203
+        $desc = $trouver_table($table_objet);
1204
+    }
1205
+    if (!$desc and in_array($table_objet = table_objet($type, $serveur), $ts)) {
1206
+        $desc = $trouver_table($table_objet, $serveur);
1207
+    }
1208
+    // si le type est declare : bingo !
1209
+    if ($desc and isset($desc['type'])) {
1210
+        return $desc['type'];
1211
+    }
1212
+
1213
+    // on a fait ce qu'on a pu
1214
+    return $type;
1215 1215
 }
1216 1216
 
1217 1217
 /**
@@ -1227,62 +1227,62 @@  discard block
 block discarded – undo
1227 1227
  * @return bool
1228 1228
  */
1229 1229
 function objet_test_si_publie($objet, $id_objet, $serveur = '') {
1230
-	// voir si une fonction est definie pour faire le boulot
1231
-	// elle a la priorite dans ce cas
1232
-	if ($f = charger_fonction($objet . '_test_si_publie', 'base', true)) {
1233
-		return $f($objet, $id_objet, $serveur);
1234
-	}
1235
-
1236
-	// sinon on se fie a la declaration de l'objet si presente
1237
-	$id_table = $table_objet = table_objet($objet);
1238
-	$id_table_objet = id_table_objet($objet, $serveur);
1239
-	$trouver_table = charger_fonction('trouver_table', 'base');
1240
-	if (
1241
-		$desc = $trouver_table($table_objet, $serveur)
1242
-		and isset($desc['statut'])
1243
-		and $desc['statut']
1244
-	) {
1245
-		$boucle = new Boucle();
1246
-		$boucle->show = $desc;
1247
-		$boucle->nom = 'objet_test_si_publie';
1248
-		$boucle->id_boucle = $id_table;
1249
-		$boucle->id_table = $id_table;
1250
-		$boucle->primary = $desc['key']['PRIMARY KEY'] ?? '';
1251
-		$boucle->sql_serveur = $serveur;
1252
-		$boucle->select[] = $id_table_objet;
1253
-		$boucle->from[$table_objet] = table_objet_sql($objet, $serveur);
1254
-		$boucle->where[] = $id_table . '.' . $id_table_objet . '=' . intval($id_objet);
1255
-
1256
-		$boucle->descr['nom'] = 'objet_test_si_publie'; // eviter notice php
1257
-		$boucle->descr['sourcefile'] = 'internal';
1258
-		$boucle->descr['gram'] = 'html';
1259
-
1260
-		include_spip('public/compiler');
1261
-		include_spip('public/composer');
1262
-		instituer_boucle($boucle, false, true);
1263
-		$res = calculer_select(
1264
-			$boucle->select,
1265
-			$boucle->from,
1266
-			$boucle->from_type,
1267
-			$boucle->where,
1268
-			$boucle->join,
1269
-			$boucle->group,
1270
-			$boucle->order,
1271
-			$boucle->limit,
1272
-			$boucle->having,
1273
-			$table_objet,
1274
-			$id_table,
1275
-			$serveur
1276
-		);
1277
-		if (sql_fetch($res)) {
1278
-			return true;
1279
-		}
1280
-
1281
-		return false;
1282
-	}
1283
-
1284
-	// si pas d'info statut ni de fonction : l'objet est publie
1285
-	return true;
1230
+    // voir si une fonction est definie pour faire le boulot
1231
+    // elle a la priorite dans ce cas
1232
+    if ($f = charger_fonction($objet . '_test_si_publie', 'base', true)) {
1233
+        return $f($objet, $id_objet, $serveur);
1234
+    }
1235
+
1236
+    // sinon on se fie a la declaration de l'objet si presente
1237
+    $id_table = $table_objet = table_objet($objet);
1238
+    $id_table_objet = id_table_objet($objet, $serveur);
1239
+    $trouver_table = charger_fonction('trouver_table', 'base');
1240
+    if (
1241
+        $desc = $trouver_table($table_objet, $serveur)
1242
+        and isset($desc['statut'])
1243
+        and $desc['statut']
1244
+    ) {
1245
+        $boucle = new Boucle();
1246
+        $boucle->show = $desc;
1247
+        $boucle->nom = 'objet_test_si_publie';
1248
+        $boucle->id_boucle = $id_table;
1249
+        $boucle->id_table = $id_table;
1250
+        $boucle->primary = $desc['key']['PRIMARY KEY'] ?? '';
1251
+        $boucle->sql_serveur = $serveur;
1252
+        $boucle->select[] = $id_table_objet;
1253
+        $boucle->from[$table_objet] = table_objet_sql($objet, $serveur);
1254
+        $boucle->where[] = $id_table . '.' . $id_table_objet . '=' . intval($id_objet);
1255
+
1256
+        $boucle->descr['nom'] = 'objet_test_si_publie'; // eviter notice php
1257
+        $boucle->descr['sourcefile'] = 'internal';
1258
+        $boucle->descr['gram'] = 'html';
1259
+
1260
+        include_spip('public/compiler');
1261
+        include_spip('public/composer');
1262
+        instituer_boucle($boucle, false, true);
1263
+        $res = calculer_select(
1264
+            $boucle->select,
1265
+            $boucle->from,
1266
+            $boucle->from_type,
1267
+            $boucle->where,
1268
+            $boucle->join,
1269
+            $boucle->group,
1270
+            $boucle->order,
1271
+            $boucle->limit,
1272
+            $boucle->having,
1273
+            $table_objet,
1274
+            $id_table,
1275
+            $serveur
1276
+        );
1277
+        if (sql_fetch($res)) {
1278
+            return true;
1279
+        }
1280
+
1281
+        return false;
1282
+    }
1283
+
1284
+    // si pas d'info statut ni de fonction : l'objet est publie
1285
+    return true;
1286 1286
 }
1287 1287
 
1288 1288
 
@@ -1317,124 +1317,124 @@  discard block
 block discarded – undo
1317 1317
  *     Retourne un tableau décrivant les parents trouvés
1318 1318
  */
1319 1319
 function objet_lister_parents($objet, $id_objet, $parent_direct_seulement = false) {
1320
-	$parents = [];
1321
-
1322
-	// Si on trouve une ou des méthodes de parent
1323
-	if ($parent_methodes = objet_type_decrire_infos_parents($objet)) {
1324
-		// On identifie les informations sur l'objet source dont on cherche le parent.
1325
-		include_spip('base/abstract_sql');
1326
-		$table_objet = table_objet_sql($objet);
1327
-		$cle_objet = id_table_objet($objet);
1328
-		$id_objet = intval($id_objet);
1329
-
1330
-		// On teste chacun méthode dans l'ordre, et dès qu'on a trouvé un parent on s'arrête
1331
-		foreach ($parent_methodes as $parent_methode) {
1332
-			// Champ identifiant le parent (id et éventuellement le type)
1333
-			// -- cette identification ne dépend pas du fait que le parent soit stocké dans une table de différente
1334
-			//    de celle de l'objet source
1335
-			$select = [];
1336
-			if (isset($parent_methode['champ'])) {
1337
-				$select[] = $parent_methode['champ'];
1338
-			}
1339
-			if (isset($parent_methode['champ_type'])) {
1340
-				$select[] = $parent_methode['champ_type'];
1341
-			}
1342
-
1343
-			// Détermination de la table du parent et des conditions sur l'objet source et le parent.
1344
-			$condition_objet_invalide = false;
1345
-			$where = [];
1346
-			if (!isset($parent_methode['table'])) {
1347
-				// Le parent est stocké dans la même table que l'objet source :
1348
-				// -- toutes les conditions s'appliquent à la table source.
1349
-				$table = $table_objet;
1350
-				$where = ["$cle_objet = $id_objet"];
1351
-				// -- Condition supplémentaire sur la détection du parent
1352
-				if (isset($parent_methode['condition'])) {
1353
-					$where[] = $parent_methode['condition'];
1354
-				}
1355
-			} elseif (!$parent_direct_seulement) {
1356
-				// Le parent est stocké dans une table différente de l'objet source.
1357
-				// -- on vérifie d'emblée si il y a une condition sur l'objet source et si celle-ci est vérifiée
1358
-				//    Si non, on peut arrêter le traitement.
1359
-				if (isset($parent_methode['condition'])) {
1360
-					$where = [
1361
-						"$cle_objet = $id_objet",
1362
-						$parent_methode['condition']
1363
-					];
1364
-					if (!sql_countsel($table_objet, $where)) {
1365
-						$condition_objet_invalide = true;
1366
-					}
1367
-				}
1368
-
1369
-				// Si pas de condition sur l'objet source ou que la condition est vérifiée, on peut construire
1370
-				// la requête sur la table qui accueille le parent.
1371
-				if (!$condition_objet_invalide) {
1372
-					$table = $parent_methode['table'];
1373
-					// On construit les conditions en fonction de l'identification de l'objet source
1374
-					$where = [];
1375
-					// -- si le champ_source de l'id n'est pas précisé c'est qu'il est déjà connu et donc que c'est
1376
-					//    le même que celui de l'objet source.
1377
-					$where[] = isset($parent_methode['source_champ'])
1378
-						? "{$parent_methode['source_champ']} = $id_objet"
1379
-						: "${cle_objet} = $id_objet";
1380
-					if (isset($parent_methode['source_champ_type'])) {
1381
-						$where[] = "{$parent_methode['source_champ_type']} = " . sql_quote($objet);
1382
-					}
1383
-					// -- Condition supplémentaire sur la détection du parent
1384
-					if (isset($parent_methode['table_condition'])) {
1385
-						$where[] = $parent_methode['table_condition'];
1386
-					}
1387
-				}
1388
-			}
1389
-
1390
-			// On lance la requête de récupération du parent
1391
-			$is_table_lien = (strpos($table, '_liens') !== false and substr($table, -6) === '_liens');
1392
-			if (
1393
-				!$condition_objet_invalide
1394
-				and $where
1395
-				and ($lignes = sql_allfetsel($is_table_lien ? '*' : $select, $table, $where))
1396
-			) {
1397
-				foreach ($lignes as $ligne) {
1398
-					// Si le type est fixe
1399
-					if (isset($parent_methode['type'])) {
1400
-						$parent = [
1401
-							'objet' 	=> $parent_methode['type'],
1402
-							'id_objet'	=> intval($ligne[$parent_methode['champ']]),
1403
-							'champ' 	=> $parent_methode['champ'],
1404
-							'table'    => $table,
1405
-						];
1406
-					}
1407
-					elseif (isset($parent_methode['champ_type'])) {
1408
-						$parent = [
1409
-							'objet' 	 => $ligne[$parent_methode['champ_type']],
1410
-							'id_objet' 	 => intval($ligne[$parent_methode['champ']]),
1411
-							'champ' 	 => $parent_methode['champ'],
1412
-							'champ_type' => $parent_methode['champ_type'],
1413
-							'table'    => $table,
1414
-						];
1415
-					}
1416
-					if ($is_table_lien) {
1417
-						$parent['lien'] = $ligne;
1418
-					}
1419
-					$parents[] = $parent;
1420
-				}
1421
-			}
1422
-		}
1423
-	}
1424
-
1425
-	// On passe par un pipeline avant de retourner
1426
-	$parents = pipeline(
1427
-		'objet_lister_parents',
1428
-		[
1429
-			'args' => [
1430
-				'objet' => $objet,
1431
-				'id_objet' => $id_objet,
1432
-			],
1433
-			'data' => $parents,
1434
-		]
1435
-	);
1436
-
1437
-	return $parents;
1320
+    $parents = [];
1321
+
1322
+    // Si on trouve une ou des méthodes de parent
1323
+    if ($parent_methodes = objet_type_decrire_infos_parents($objet)) {
1324
+        // On identifie les informations sur l'objet source dont on cherche le parent.
1325
+        include_spip('base/abstract_sql');
1326
+        $table_objet = table_objet_sql($objet);
1327
+        $cle_objet = id_table_objet($objet);
1328
+        $id_objet = intval($id_objet);
1329
+
1330
+        // On teste chacun méthode dans l'ordre, et dès qu'on a trouvé un parent on s'arrête
1331
+        foreach ($parent_methodes as $parent_methode) {
1332
+            // Champ identifiant le parent (id et éventuellement le type)
1333
+            // -- cette identification ne dépend pas du fait que le parent soit stocké dans une table de différente
1334
+            //    de celle de l'objet source
1335
+            $select = [];
1336
+            if (isset($parent_methode['champ'])) {
1337
+                $select[] = $parent_methode['champ'];
1338
+            }
1339
+            if (isset($parent_methode['champ_type'])) {
1340
+                $select[] = $parent_methode['champ_type'];
1341
+            }
1342
+
1343
+            // Détermination de la table du parent et des conditions sur l'objet source et le parent.
1344
+            $condition_objet_invalide = false;
1345
+            $where = [];
1346
+            if (!isset($parent_methode['table'])) {
1347
+                // Le parent est stocké dans la même table que l'objet source :
1348
+                // -- toutes les conditions s'appliquent à la table source.
1349
+                $table = $table_objet;
1350
+                $where = ["$cle_objet = $id_objet"];
1351
+                // -- Condition supplémentaire sur la détection du parent
1352
+                if (isset($parent_methode['condition'])) {
1353
+                    $where[] = $parent_methode['condition'];
1354
+                }
1355
+            } elseif (!$parent_direct_seulement) {
1356
+                // Le parent est stocké dans une table différente de l'objet source.
1357
+                // -- on vérifie d'emblée si il y a une condition sur l'objet source et si celle-ci est vérifiée
1358
+                //    Si non, on peut arrêter le traitement.
1359
+                if (isset($parent_methode['condition'])) {
1360
+                    $where = [
1361
+                        "$cle_objet = $id_objet",
1362
+                        $parent_methode['condition']
1363
+                    ];
1364
+                    if (!sql_countsel($table_objet, $where)) {
1365
+                        $condition_objet_invalide = true;
1366
+                    }
1367
+                }
1368
+
1369
+                // Si pas de condition sur l'objet source ou que la condition est vérifiée, on peut construire
1370
+                // la requête sur la table qui accueille le parent.
1371
+                if (!$condition_objet_invalide) {
1372
+                    $table = $parent_methode['table'];
1373
+                    // On construit les conditions en fonction de l'identification de l'objet source
1374
+                    $where = [];
1375
+                    // -- si le champ_source de l'id n'est pas précisé c'est qu'il est déjà connu et donc que c'est
1376
+                    //    le même que celui de l'objet source.
1377
+                    $where[] = isset($parent_methode['source_champ'])
1378
+                        ? "{$parent_methode['source_champ']} = $id_objet"
1379
+                        : "${cle_objet} = $id_objet";
1380
+                    if (isset($parent_methode['source_champ_type'])) {
1381
+                        $where[] = "{$parent_methode['source_champ_type']} = " . sql_quote($objet);
1382
+                    }
1383
+                    // -- Condition supplémentaire sur la détection du parent
1384
+                    if (isset($parent_methode['table_condition'])) {
1385
+                        $where[] = $parent_methode['table_condition'];
1386
+                    }
1387
+                }
1388
+            }
1389
+
1390
+            // On lance la requête de récupération du parent
1391
+            $is_table_lien = (strpos($table, '_liens') !== false and substr($table, -6) === '_liens');
1392
+            if (
1393
+                !$condition_objet_invalide
1394
+                and $where
1395
+                and ($lignes = sql_allfetsel($is_table_lien ? '*' : $select, $table, $where))
1396
+            ) {
1397
+                foreach ($lignes as $ligne) {
1398
+                    // Si le type est fixe
1399
+                    if (isset($parent_methode['type'])) {
1400
+                        $parent = [
1401
+                            'objet' 	=> $parent_methode['type'],
1402
+                            'id_objet'	=> intval($ligne[$parent_methode['champ']]),
1403
+                            'champ' 	=> $parent_methode['champ'],
1404
+                            'table'    => $table,
1405
+                        ];
1406
+                    }
1407
+                    elseif (isset($parent_methode['champ_type'])) {
1408
+                        $parent = [
1409
+                            'objet' 	 => $ligne[$parent_methode['champ_type']],
1410
+                            'id_objet' 	 => intval($ligne[$parent_methode['champ']]),
1411
+                            'champ' 	 => $parent_methode['champ'],
1412
+                            'champ_type' => $parent_methode['champ_type'],
1413
+                            'table'    => $table,
1414
+                        ];
1415
+                    }
1416
+                    if ($is_table_lien) {
1417
+                        $parent['lien'] = $ligne;
1418
+                    }
1419
+                    $parents[] = $parent;
1420
+                }
1421
+            }
1422
+        }
1423
+    }
1424
+
1425
+    // On passe par un pipeline avant de retourner
1426
+    $parents = pipeline(
1427
+        'objet_lister_parents',
1428
+        [
1429
+            'args' => [
1430
+                'objet' => $objet,
1431
+                'id_objet' => $id_objet,
1432
+            ],
1433
+            'data' => $parents,
1434
+        ]
1435
+    );
1436
+
1437
+    return $parents;
1438 1438
 }
1439 1439
 
1440 1440
 /**
@@ -1446,17 +1446,17 @@  discard block
 block discarded – undo
1446 1446
  * @return array
1447 1447
  */
1448 1448
 function objet_lister_parents_par_type($objet, $id_objet) {
1449
-	$parents = objet_lister_parents($objet, $id_objet);
1449
+    $parents = objet_lister_parents($objet, $id_objet);
1450 1450
 
1451
-	$parents_par_type = [];
1452
-	foreach ($parents as $parent) {
1453
-		if (!isset($parents_par_type[$parent['objet']])) {
1454
-			$parents_par_type[$parent['objet']] = [];
1455
-		}
1456
-		$parents_par_type[$parent['objet']][] = $parent['id_objet'];
1457
-	}
1451
+    $parents_par_type = [];
1452
+    foreach ($parents as $parent) {
1453
+        if (!isset($parents_par_type[$parent['objet']])) {
1454
+            $parents_par_type[$parent['objet']] = [];
1455
+        }
1456
+        $parents_par_type[$parent['objet']][] = $parent['id_objet'];
1457
+    }
1458 1458
 
1459
-	return $parents_par_type;
1459
+    return $parents_par_type;
1460 1460
 }
1461 1461
 
1462 1462
 
@@ -1489,85 +1489,85 @@  discard block
 block discarded – undo
1489 1489
  *     Retourne un tableau de tableaux, avec comme clés les types des objets, et dans chacun un tableau des identifiants trouvés
1490 1490
  */
1491 1491
 function objet_lister_enfants($objet, $id_objet) {
1492
-	$enfants = [];
1493
-
1494
-	// Si on trouve des types d'enfants et leurs méthodes
1495
-	if ($enfants_methodes = objet_type_decrire_infos_enfants($objet)) {
1496
-		include_spip('base/abstract_sql');
1497
-		$id_objet = intval($id_objet);
1498
-
1499
-		// On parcourt tous les types d'enfants trouvés
1500
-		foreach ($enfants_methodes as $objet_enfant => $_methode_parent) {
1501
-			// On construit les conditions d'identification du parent
1502
-			$where = [];
1503
-			// -- L'identifiant du parent
1504
-			if (isset($_methode_parent['champ'])) {
1505
-				$where[] = $_methode_parent['champ'] . ' = ' . $id_objet;
1506
-			}
1507
-			// -- Si le parent est variable
1508
-			if (isset($_methode_parent['champ_type'])) {
1509
-				$where[] = $_methode_parent['champ_type'] . ' = ' . sql_quote($objet);
1510
-			}
1511
-
1512
-			// On détermine la table, le champ id des enfants et on complète éventuellement les conditions
1513
-			if (!isset($_methode_parent['table'])) {
1514
-				// Les enfants sont stockés dans la même table que l'objet parent :
1515
-				$table_enfant = table_objet_sql($objet_enfant);
1516
-				$cle_objet_enfant = id_table_objet($objet_enfant);
1517
-
1518
-				// S'il y a une condition supplémentaire
1519
-				if (isset($_methode_parent['condition'])) {
1520
-					$where[] = $_methode_parent['condition'];
1521
-				}
1522
-			} else {
1523
-				// Les enfants sont stockés dans une table différente de l'objet parent.
1524
-				$table_enfant = $_methode_parent['table'];
1525
-				$cle_objet_enfant = $_methode_parent['source_champ'] ?? id_table_objet($objet_enfant);
1526
-
1527
-				// S'il y a une condition supplémentaire
1528
-				if (isset($_methode_parent['table_condition'])) {
1529
-					$where[] = $_methode_parent['table_condition'];
1530
-				}
1531
-			}
1532
-
1533
-			// On lance la requête
1534
-			$is_table_lien = (strpos($table_enfant, '_liens') !== false and substr($table_enfant, -6) === '_liens');
1535
-			if ($rows = sql_allfetsel($is_table_lien ? '*' : $cle_objet_enfant, $table_enfant, $where)) {
1536
-				$enfant = [
1537
-					'objet' => $objet_enfant,
1538
-					'id_objet' => 0,
1539
-					'table' => $table_enfant
1540
-				];
1541
-				if (isset($_methode_parent['champ'])) {
1542
-					$enfant['champ'] = $_methode_parent['champ'];
1543
-				}
1544
-				if (isset($_methode_parent['champ_type'])) {
1545
-					$enfant['champ_type'] = $_methode_parent['champ_type'];
1546
-				}
1547
-				foreach ($rows as $row) {
1548
-					$enfant['id_objet'] = intval($row[$cle_objet_enfant]);
1549
-					if ($is_table_lien) {
1550
-						$enfant['lien'] = $row;
1551
-					}
1552
-					$enfants[] = $enfant;
1553
-				}
1554
-			}
1555
-		}
1556
-	}
1557
-
1558
-	// On passe par un pipeline avant de retourner
1559
-	$enfants = pipeline(
1560
-		'objet_lister_enfants',
1561
-		[
1562
-			'args' => [
1563
-				'objet' => $objet,
1564
-				'id_objet' => $id_objet,
1565
-			],
1566
-			'data' => $enfants,
1567
-		]
1568
-	);
1569
-
1570
-	return $enfants;
1492
+    $enfants = [];
1493
+
1494
+    // Si on trouve des types d'enfants et leurs méthodes
1495
+    if ($enfants_methodes = objet_type_decrire_infos_enfants($objet)) {
1496
+        include_spip('base/abstract_sql');
1497
+        $id_objet = intval($id_objet);
1498
+
1499
+        // On parcourt tous les types d'enfants trouvés
1500
+        foreach ($enfants_methodes as $objet_enfant => $_methode_parent) {
1501
+            // On construit les conditions d'identification du parent
1502
+            $where = [];
1503
+            // -- L'identifiant du parent
1504
+            if (isset($_methode_parent['champ'])) {
1505
+                $where[] = $_methode_parent['champ'] . ' = ' . $id_objet;
1506
+            }
1507
+            // -- Si le parent est variable
1508
+            if (isset($_methode_parent['champ_type'])) {
1509
+                $where[] = $_methode_parent['champ_type'] . ' = ' . sql_quote($objet);
1510
+            }
1511
+
1512
+            // On détermine la table, le champ id des enfants et on complète éventuellement les conditions
1513
+            if (!isset($_methode_parent['table'])) {
1514
+                // Les enfants sont stockés dans la même table que l'objet parent :
1515
+                $table_enfant = table_objet_sql($objet_enfant);
1516
+                $cle_objet_enfant = id_table_objet($objet_enfant);
1517
+
1518
+                // S'il y a une condition supplémentaire
1519
+                if (isset($_methode_parent['condition'])) {
1520
+                    $where[] = $_methode_parent['condition'];
1521
+                }
1522
+            } else {
1523
+                // Les enfants sont stockés dans une table différente de l'objet parent.
1524
+                $table_enfant = $_methode_parent['table'];
1525
+                $cle_objet_enfant = $_methode_parent['source_champ'] ?? id_table_objet($objet_enfant);
1526
+
1527
+                // S'il y a une condition supplémentaire
1528
+                if (isset($_methode_parent['table_condition'])) {
1529
+                    $where[] = $_methode_parent['table_condition'];
1530
+                }
1531
+            }
1532
+
1533
+            // On lance la requête
1534
+            $is_table_lien = (strpos($table_enfant, '_liens') !== false and substr($table_enfant, -6) === '_liens');
1535
+            if ($rows = sql_allfetsel($is_table_lien ? '*' : $cle_objet_enfant, $table_enfant, $where)) {
1536
+                $enfant = [
1537
+                    'objet' => $objet_enfant,
1538
+                    'id_objet' => 0,
1539
+                    'table' => $table_enfant
1540
+                ];
1541
+                if (isset($_methode_parent['champ'])) {
1542
+                    $enfant['champ'] = $_methode_parent['champ'];
1543
+                }
1544
+                if (isset($_methode_parent['champ_type'])) {
1545
+                    $enfant['champ_type'] = $_methode_parent['champ_type'];
1546
+                }
1547
+                foreach ($rows as $row) {
1548
+                    $enfant['id_objet'] = intval($row[$cle_objet_enfant]);
1549
+                    if ($is_table_lien) {
1550
+                        $enfant['lien'] = $row;
1551
+                    }
1552
+                    $enfants[] = $enfant;
1553
+                }
1554
+            }
1555
+        }
1556
+    }
1557
+
1558
+    // On passe par un pipeline avant de retourner
1559
+    $enfants = pipeline(
1560
+        'objet_lister_enfants',
1561
+        [
1562
+            'args' => [
1563
+                'objet' => $objet,
1564
+                'id_objet' => $id_objet,
1565
+            ],
1566
+            'data' => $enfants,
1567
+        ]
1568
+    );
1569
+
1570
+    return $enfants;
1571 1571
 }
1572 1572
 
1573 1573
 /**
@@ -1579,17 +1579,17 @@  discard block
 block discarded – undo
1579 1579
  * @return array
1580 1580
  */
1581 1581
 function objet_lister_enfants_par_type($objet, $id_objet) {
1582
-	$enfants = objet_lister_enfants($objet, $id_objet);
1582
+    $enfants = objet_lister_enfants($objet, $id_objet);
1583 1583
 
1584
-	$enfants_par_type = [];
1585
-	foreach ($enfants as $enfant) {
1586
-		if (!isset($enfants_par_type[$enfant['objet']])) {
1587
-			$enfants_par_type[$enfant['objet']] = [];
1588
-		}
1589
-		$enfants_par_type[$enfant['objet']][] = $enfant['id_objet'];
1590
-	}
1584
+    $enfants_par_type = [];
1585
+    foreach ($enfants as $enfant) {
1586
+        if (!isset($enfants_par_type[$enfant['objet']])) {
1587
+            $enfants_par_type[$enfant['objet']] = [];
1588
+        }
1589
+        $enfants_par_type[$enfant['objet']][] = $enfant['id_objet'];
1590
+    }
1591 1591
 
1592
-	return $enfants_par_type;
1592
+    return $enfants_par_type;
1593 1593
 }
1594 1594
 
1595 1595
 /**
@@ -1601,35 +1601,35 @@  discard block
 block discarded – undo
1601 1601
  *     Retourne un tableau de tableau contenant les informations de type et de champ pour trouver le parent ou false sinon
1602 1602
  */
1603 1603
 function objet_type_decrire_infos_parents($objet) {
1604
-	static $parents = [];
1605
-
1606
-	// Si on ne l'a pas encore cherché pour cet objet
1607
-	if (!isset($parents[$objet])) {
1608
-		$parents[$objet] = false;
1609
-		$table = table_objet_sql($objet);
1610
-
1611
-		// Si on trouve bien la description de cet objet
1612
-		if ($infos = lister_tables_objets_sql($table)) {
1613
-			if (isset($infos['parent']) and is_array($infos['parent'])) {
1614
-				// S'il y a une description explicite de parent, c'est prioritaire
1615
-				// -- on traite les cas où il y a une ou plusieurs description mais on renvoie toujours un tableau
1616
-				//    de description
1617
-				if (!isset($infos['parent'][0])) {
1618
-					$parents[$objet] = [$infos['parent']];
1619
-				} else {
1620
-					$parents[$objet] = $infos['parent'];
1621
-				}
1622
-			} elseif (isset($infos['field']['id_rubrique'])) {
1623
-				// Sinon on cherche des cas courants connus magiquement, à commencer par id_rubrique
1624
-				$parents[$objet] = [['type' => 'rubrique', 'champ' => 'id_rubrique']];
1625
-			} elseif (isset($infos['field']['id_parent'])) {
1626
-				// Sinon on cherche un champ id_parent, ce qui signifie que l'objet est parent de lui-même
1627
-				$parents[$objet] = [['type' => $objet, 'champ' => 'id_parent']];
1628
-			}
1629
-		}
1630
-	}
1631
-
1632
-	return $parents[$objet];
1604
+    static $parents = [];
1605
+
1606
+    // Si on ne l'a pas encore cherché pour cet objet
1607
+    if (!isset($parents[$objet])) {
1608
+        $parents[$objet] = false;
1609
+        $table = table_objet_sql($objet);
1610
+
1611
+        // Si on trouve bien la description de cet objet
1612
+        if ($infos = lister_tables_objets_sql($table)) {
1613
+            if (isset($infos['parent']) and is_array($infos['parent'])) {
1614
+                // S'il y a une description explicite de parent, c'est prioritaire
1615
+                // -- on traite les cas où il y a une ou plusieurs description mais on renvoie toujours un tableau
1616
+                //    de description
1617
+                if (!isset($infos['parent'][0])) {
1618
+                    $parents[$objet] = [$infos['parent']];
1619
+                } else {
1620
+                    $parents[$objet] = $infos['parent'];
1621
+                }
1622
+            } elseif (isset($infos['field']['id_rubrique'])) {
1623
+                // Sinon on cherche des cas courants connus magiquement, à commencer par id_rubrique
1624
+                $parents[$objet] = [['type' => 'rubrique', 'champ' => 'id_rubrique']];
1625
+            } elseif (isset($infos['field']['id_parent'])) {
1626
+                // Sinon on cherche un champ id_parent, ce qui signifie que l'objet est parent de lui-même
1627
+                $parents[$objet] = [['type' => $objet, 'champ' => 'id_parent']];
1628
+            }
1629
+        }
1630
+    }
1631
+
1632
+    return $parents[$objet];
1633 1633
 }
1634 1634
 
1635 1635
 /**
@@ -1641,36 +1641,36 @@  discard block
 block discarded – undo
1641 1641
  *     Retourne un tableau de tableaux contenant chacun les informations d'un type d'enfant
1642 1642
  */
1643 1643
 function objet_type_decrire_infos_enfants($objet) {
1644
-	static $enfants = [];
1645
-
1646
-	// Si on a déjà fait la recherche pour ce type d'objet
1647
-	if (!isset($enfants[$objet])) {
1648
-		$enfants[$objet] = [];
1649
-		$tables = lister_tables_objets_sql();
1650
-
1651
-		// On parcourt toutes les tables d'objet, et on cherche si chacune peut être enfant
1652
-		foreach ($tables as $table => $infos) {
1653
-			$objet_enfant = objet_type($table);
1654
-
1655
-			// On ne va pas refaire les tests des différents cas, on réutilise
1656
-			if ($parent_methodes = objet_type_decrire_infos_parents($objet_enfant)) {
1657
-				// On parcourt les différents cas possible, si certains peuvent concerner l'objet demandé
1658
-				foreach ($parent_methodes as $parent_methode) {
1659
-					// Si la méthode qu'on teste n'exclut pas le parent demandé
1660
-					if (!isset($parent_methode['exclus']) or !in_array($objet, $parent_methode['exclus'])) {
1661
-						// Si le type du parent est fixe et directement l'objet demandé
1662
-						if (isset($parent_methode['type']) and isset($parent_methode['champ']) and $parent_methode['type'] == $objet) {
1663
-							$enfants[$objet][$objet_enfant] = $parent_methode;
1664
-						}
1665
-						// Si le type est variable, alors l'objet demandé peut forcément être parent
1666
-						elseif (isset($parent_methode['champ_type']) and isset($parent_methode['champ'])) {
1667
-							$enfants[$objet][$objet_enfant] = $parent_methode;
1668
-						}
1669
-					}
1670
-				}
1671
-			}
1672
-		}
1673
-	}
1674
-
1675
-	return $enfants[$objet];
1644
+    static $enfants = [];
1645
+
1646
+    // Si on a déjà fait la recherche pour ce type d'objet
1647
+    if (!isset($enfants[$objet])) {
1648
+        $enfants[$objet] = [];
1649
+        $tables = lister_tables_objets_sql();
1650
+
1651
+        // On parcourt toutes les tables d'objet, et on cherche si chacune peut être enfant
1652
+        foreach ($tables as $table => $infos) {
1653
+            $objet_enfant = objet_type($table);
1654
+
1655
+            // On ne va pas refaire les tests des différents cas, on réutilise
1656
+            if ($parent_methodes = objet_type_decrire_infos_parents($objet_enfant)) {
1657
+                // On parcourt les différents cas possible, si certains peuvent concerner l'objet demandé
1658
+                foreach ($parent_methodes as $parent_methode) {
1659
+                    // Si la méthode qu'on teste n'exclut pas le parent demandé
1660
+                    if (!isset($parent_methode['exclus']) or !in_array($objet, $parent_methode['exclus'])) {
1661
+                        // Si le type du parent est fixe et directement l'objet demandé
1662
+                        if (isset($parent_methode['type']) and isset($parent_methode['champ']) and $parent_methode['type'] == $objet) {
1663
+                            $enfants[$objet][$objet_enfant] = $parent_methode;
1664
+                        }
1665
+                        // Si le type est variable, alors l'objet demandé peut forcément être parent
1666
+                        elseif (isset($parent_methode['champ_type']) and isset($parent_methode['champ'])) {
1667
+                            $enfants[$objet][$objet_enfant] = $parent_methode;
1668
+                        }
1669
+                    }
1670
+                }
1671
+            }
1672
+        }
1673
+    }
1674
+
1675
+    return $enfants[$objet];
1676 1676
 }
Please login to merge, or discard this patch.
ecrire/public/assembler.php 1 patch
Indentation   +633 added lines, -633 removed lines patch added patch discarded remove patch
@@ -20,178 +20,178 @@  discard block
 block discarded – undo
20 20
  **/
21 21
 
22 22
 if (!defined('_ECRIRE_INC_VERSION')) {
23
-	return;
23
+    return;
24 24
 }
25 25
 
26 26
 // En cas de modification, il faut aussi actualiser la regexp de nettoyer_uri_var() dans inc/utils.php
27 27
 if (!defined('_CONTEXTE_IGNORE_VARIABLES')) {
28
-	define('_CONTEXTE_IGNORE_VARIABLES', '/(^var_|^PHPSESSID$|^fbclid$|^utm_)/');
28
+    define('_CONTEXTE_IGNORE_VARIABLES', '/(^var_|^PHPSESSID$|^fbclid$|^utm_)/');
29 29
 }
30 30
 
31 31
 function assembler($fond, string $connect = '') {
32 32
 
33
-	$chemin_cache = null;
34
-	$lastmodified = null;
35
-	$res = null;
36
-	// flag_preserver est modifie ici, et utilise en globale
37
-	// use_cache sert a informer le bouton d'admin pr savoir s'il met un *
38
-	// contexte est utilise en globale dans le formulaire d'admin
39
-
40
-	$GLOBALS['contexte'] = calculer_contexte();
41
-	$page = ['contexte_implicite' => calculer_contexte_implicite()];
42
-	$page['contexte_implicite']['cache'] = $fond . preg_replace(
43
-		',\.[a-zA-Z0-9]*$,',
44
-		'',
45
-		preg_replace('/[?].*$/', '', $GLOBALS['REQUEST_URI'])
46
-	);
47
-	// Cette fonction est utilisee deux fois
48
-	$cacher = charger_fonction('cacher', 'public', true);
49
-	// Les quatre derniers parametres sont modifies par la fonction:
50
-	// emplacement, validite, et, s'il est valide, contenu & age
51
-	if ($cacher) {
52
-		$res = $cacher($GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, $page, $lastmodified);
53
-	} else {
54
-		$GLOBALS['use_cache'] = -1;
55
-	}
56
-	// Si un resultat est retourne, c'est un message d'impossibilite
57
-	if ($res) {
58
-		return ['texte' => $res];
59
-	}
60
-
61
-	if (!$chemin_cache || !$lastmodified) {
62
-		$lastmodified = time();
63
-	}
64
-
65
-	$headers_only = ($_SERVER['REQUEST_METHOD'] == 'HEAD');
66
-	$calculer_page = true;
67
-
68
-	// Pour les pages non-dynamiques (indiquees par #CACHE{duree,cache-client})
69
-	// une perennite valide a meme reponse qu'une requete HEAD (par defaut les
70
-	// pages sont dynamiques)
71
-	if (
72
-		isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
73
-		and (!defined('_VAR_MODE') or !_VAR_MODE)
74
-		and $chemin_cache
75
-		and isset($page['entetes'])
76
-		and isset($page['entetes']['Cache-Control'])
77
-		and strstr($page['entetes']['Cache-Control'], 'max-age=')
78
-		and !strstr($_SERVER['SERVER_SOFTWARE'], 'IIS/')
79
-	) {
80
-		$since = preg_replace(
81
-			'/;.*/',
82
-			'',
83
-			$_SERVER['HTTP_IF_MODIFIED_SINCE']
84
-		);
85
-		$since = str_replace('GMT', '', $since);
86
-		if (trim($since) == gmdate('D, d M Y H:i:s', $lastmodified)) {
87
-			$page['status'] = 304;
88
-			$headers_only = true;
89
-			$calculer_page = false;
90
-		}
91
-	}
92
-
93
-	// Si requete HEAD ou Last-modified compatible, ignorer le texte
94
-	// et pas de content-type (pour contrer le bouton admin de inc-public)
95
-	if (!$calculer_page) {
96
-		$page['texte'] = '';
97
-	} else {
98
-		// si la page est prise dans le cache
99
-		if (!$GLOBALS['use_cache']) {
100
-			// Informer les boutons d'admin du contexte
101
-			// (fourni par urls_decoder_url ci-dessous lors de la mise en cache)
102
-			$GLOBALS['contexte'] = $page['contexte'];
103
-
104
-			// vider les globales url propres qui ne doivent plus etre utilisees en cas
105
-			// d'inversion url => objet
106
-			// plus necessaire si on utilise bien la fonction urls_decoder_url
107
-			#unset($_SERVER['REDIRECT_url_propre']);
108
-			#unset($_ENV['url_propre']);
109
-		} else {
110
-			// Compat ascendante :
111
-			// 1. $contexte est global
112
-			// (a evacuer car urls_decoder_url gere ce probleme ?)
113
-			// et calculer la page
114
-			if (!test_espace_prive()) {
115
-				include_spip('inc/urls');
116
-				[$fond, $GLOBALS['contexte'], $url_redirect] = urls_decoder_url(
117
-					nettoyer_uri(),
118
-					$fond,
119
-					$GLOBALS['contexte'],
120
-					true
121
-				);
122
-			}
123
-			// squelette par defaut
124
-			if (!strlen($fond ?? '')) {
125
-				$fond = 'sommaire';
126
-			}
127
-
128
-			// produire la page : peut mettre a jour $lastmodified
129
-			$produire_page = charger_fonction('produire_page', 'public');
130
-			$page = $produire_page(
131
-				$fond,
132
-				$GLOBALS['contexte'],
133
-				$GLOBALS['use_cache'],
134
-				$chemin_cache,
135
-				null,
136
-				$page,
137
-				$lastmodified,
138
-				$connect
139
-			);
140
-			if ($page === '') {
141
-				$erreur = _T(
142
-					'info_erreur_squelette2',
143
-					['fichier' => spip_htmlspecialchars($fond) . '.' . _EXTENSION_SQUELETTES]
144
-				);
145
-				erreur_squelette($erreur);
146
-				// eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4
147
-				$page = ['texte' => '', 'erreur' => $erreur];
148
-			}
149
-		}
150
-
151
-		if ($page and $chemin_cache) {
152
-			$page['cache'] = $chemin_cache;
153
-		}
154
-
155
-		auto_content_type($page);
156
-
157
-		$GLOBALS['flag_preserver'] |= headers_sent();
158
-
159
-		// Definir les entetes si ce n'est fait
160
-		if (!$GLOBALS['flag_preserver']) {
161
-			// Si la page est vide, produire l'erreur 404 ou message d'erreur pour les inclusions
162
-			if (
163
-				trim($page['texte']) === ''
164
-				and _VAR_MODE !== 'debug'
165
-				and !isset($page['entetes']['Location']) // cette page realise une redirection, donc pas d'erreur
166
-			) {
167
-				$GLOBALS['contexte']['fond_erreur'] = $fond;
168
-				$page = message_page_indisponible($page, $GLOBALS['contexte']);
169
-			}
170
-			// pas de cache client en mode 'observation'
171
-			if (defined('_VAR_MODE') and _VAR_MODE) {
172
-				$page['entetes']['Cache-Control'] = 'no-cache,must-revalidate';
173
-				$page['entetes']['Pragma'] = 'no-cache';
174
-			}
175
-		}
176
-	}
177
-
178
-	// Entete Last-Modified:
179
-	// eviter d'etre incoherent en envoyant un lastmodified identique
180
-	// a celui qu'on a refuse d'honorer plus haut (cf. #655)
181
-	if (
182
-		$lastmodified
183
-		and !isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
184
-		and !isset($page['entetes']['Last-Modified'])
185
-	) {
186
-		$page['entetes']['Last-Modified'] = gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT';
187
-	}
188
-
189
-	// fermer la connexion apres les headers si requete HEAD
190
-	if ($headers_only) {
191
-		$page['entetes']['Connection'] = 'close';
192
-	}
193
-
194
-	return $page;
33
+    $chemin_cache = null;
34
+    $lastmodified = null;
35
+    $res = null;
36
+    // flag_preserver est modifie ici, et utilise en globale
37
+    // use_cache sert a informer le bouton d'admin pr savoir s'il met un *
38
+    // contexte est utilise en globale dans le formulaire d'admin
39
+
40
+    $GLOBALS['contexte'] = calculer_contexte();
41
+    $page = ['contexte_implicite' => calculer_contexte_implicite()];
42
+    $page['contexte_implicite']['cache'] = $fond . preg_replace(
43
+        ',\.[a-zA-Z0-9]*$,',
44
+        '',
45
+        preg_replace('/[?].*$/', '', $GLOBALS['REQUEST_URI'])
46
+    );
47
+    // Cette fonction est utilisee deux fois
48
+    $cacher = charger_fonction('cacher', 'public', true);
49
+    // Les quatre derniers parametres sont modifies par la fonction:
50
+    // emplacement, validite, et, s'il est valide, contenu & age
51
+    if ($cacher) {
52
+        $res = $cacher($GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, $page, $lastmodified);
53
+    } else {
54
+        $GLOBALS['use_cache'] = -1;
55
+    }
56
+    // Si un resultat est retourne, c'est un message d'impossibilite
57
+    if ($res) {
58
+        return ['texte' => $res];
59
+    }
60
+
61
+    if (!$chemin_cache || !$lastmodified) {
62
+        $lastmodified = time();
63
+    }
64
+
65
+    $headers_only = ($_SERVER['REQUEST_METHOD'] == 'HEAD');
66
+    $calculer_page = true;
67
+
68
+    // Pour les pages non-dynamiques (indiquees par #CACHE{duree,cache-client})
69
+    // une perennite valide a meme reponse qu'une requete HEAD (par defaut les
70
+    // pages sont dynamiques)
71
+    if (
72
+        isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
73
+        and (!defined('_VAR_MODE') or !_VAR_MODE)
74
+        and $chemin_cache
75
+        and isset($page['entetes'])
76
+        and isset($page['entetes']['Cache-Control'])
77
+        and strstr($page['entetes']['Cache-Control'], 'max-age=')
78
+        and !strstr($_SERVER['SERVER_SOFTWARE'], 'IIS/')
79
+    ) {
80
+        $since = preg_replace(
81
+            '/;.*/',
82
+            '',
83
+            $_SERVER['HTTP_IF_MODIFIED_SINCE']
84
+        );
85
+        $since = str_replace('GMT', '', $since);
86
+        if (trim($since) == gmdate('D, d M Y H:i:s', $lastmodified)) {
87
+            $page['status'] = 304;
88
+            $headers_only = true;
89
+            $calculer_page = false;
90
+        }
91
+    }
92
+
93
+    // Si requete HEAD ou Last-modified compatible, ignorer le texte
94
+    // et pas de content-type (pour contrer le bouton admin de inc-public)
95
+    if (!$calculer_page) {
96
+        $page['texte'] = '';
97
+    } else {
98
+        // si la page est prise dans le cache
99
+        if (!$GLOBALS['use_cache']) {
100
+            // Informer les boutons d'admin du contexte
101
+            // (fourni par urls_decoder_url ci-dessous lors de la mise en cache)
102
+            $GLOBALS['contexte'] = $page['contexte'];
103
+
104
+            // vider les globales url propres qui ne doivent plus etre utilisees en cas
105
+            // d'inversion url => objet
106
+            // plus necessaire si on utilise bien la fonction urls_decoder_url
107
+            #unset($_SERVER['REDIRECT_url_propre']);
108
+            #unset($_ENV['url_propre']);
109
+        } else {
110
+            // Compat ascendante :
111
+            // 1. $contexte est global
112
+            // (a evacuer car urls_decoder_url gere ce probleme ?)
113
+            // et calculer la page
114
+            if (!test_espace_prive()) {
115
+                include_spip('inc/urls');
116
+                [$fond, $GLOBALS['contexte'], $url_redirect] = urls_decoder_url(
117
+                    nettoyer_uri(),
118
+                    $fond,
119
+                    $GLOBALS['contexte'],
120
+                    true
121
+                );
122
+            }
123
+            // squelette par defaut
124
+            if (!strlen($fond ?? '')) {
125
+                $fond = 'sommaire';
126
+            }
127
+
128
+            // produire la page : peut mettre a jour $lastmodified
129
+            $produire_page = charger_fonction('produire_page', 'public');
130
+            $page = $produire_page(
131
+                $fond,
132
+                $GLOBALS['contexte'],
133
+                $GLOBALS['use_cache'],
134
+                $chemin_cache,
135
+                null,
136
+                $page,
137
+                $lastmodified,
138
+                $connect
139
+            );
140
+            if ($page === '') {
141
+                $erreur = _T(
142
+                    'info_erreur_squelette2',
143
+                    ['fichier' => spip_htmlspecialchars($fond) . '.' . _EXTENSION_SQUELETTES]
144
+                );
145
+                erreur_squelette($erreur);
146
+                // eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4
147
+                $page = ['texte' => '', 'erreur' => $erreur];
148
+            }
149
+        }
150
+
151
+        if ($page and $chemin_cache) {
152
+            $page['cache'] = $chemin_cache;
153
+        }
154
+
155
+        auto_content_type($page);
156
+
157
+        $GLOBALS['flag_preserver'] |= headers_sent();
158
+
159
+        // Definir les entetes si ce n'est fait
160
+        if (!$GLOBALS['flag_preserver']) {
161
+            // Si la page est vide, produire l'erreur 404 ou message d'erreur pour les inclusions
162
+            if (
163
+                trim($page['texte']) === ''
164
+                and _VAR_MODE !== 'debug'
165
+                and !isset($page['entetes']['Location']) // cette page realise une redirection, donc pas d'erreur
166
+            ) {
167
+                $GLOBALS['contexte']['fond_erreur'] = $fond;
168
+                $page = message_page_indisponible($page, $GLOBALS['contexte']);
169
+            }
170
+            // pas de cache client en mode 'observation'
171
+            if (defined('_VAR_MODE') and _VAR_MODE) {
172
+                $page['entetes']['Cache-Control'] = 'no-cache,must-revalidate';
173
+                $page['entetes']['Pragma'] = 'no-cache';
174
+            }
175
+        }
176
+    }
177
+
178
+    // Entete Last-Modified:
179
+    // eviter d'etre incoherent en envoyant un lastmodified identique
180
+    // a celui qu'on a refuse d'honorer plus haut (cf. #655)
181
+    if (
182
+        $lastmodified
183
+        and !isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
184
+        and !isset($page['entetes']['Last-Modified'])
185
+    ) {
186
+        $page['entetes']['Last-Modified'] = gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT';
187
+    }
188
+
189
+    // fermer la connexion apres les headers si requete HEAD
190
+    if ($headers_only) {
191
+        $page['entetes']['Connection'] = 'close';
192
+    }
193
+
194
+    return $page;
195 195
 }
196 196
 
197 197
 /**
@@ -208,19 +208,19 @@  discard block
 block discarded – undo
208 208
  */
209 209
 function calculer_contexte() {
210 210
 
211
-	$contexte = [];
212
-	foreach ($_GET as $var => $val) {
213
-		if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
214
-			$contexte[$var] = $val;
215
-		}
216
-	}
217
-	foreach ($_POST as $var => $val) {
218
-		if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
219
-			$contexte[$var] = $val;
220
-		}
221
-	}
222
-
223
-	return $contexte;
211
+    $contexte = [];
212
+    foreach ($_GET as $var => $val) {
213
+        if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
214
+            $contexte[$var] = $val;
215
+        }
216
+    }
217
+    foreach ($_POST as $var => $val) {
218
+        if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
219
+            $contexte[$var] = $val;
220
+        }
221
+    }
222
+
223
+    return $contexte;
224 224
 }
225 225
 
226 226
 /**
@@ -231,25 +231,25 @@  discard block
 block discarded – undo
231 231
  * @return array
232 232
  */
233 233
 function calculer_contexte_implicite() {
234
-	static $notes = null;
235
-	if (is_null($notes)) {
236
-		$notes = charger_fonction('notes', 'inc', true);
237
-	}
238
-	$contexte_implicite = [
239
-		'squelettes' => $GLOBALS['dossier_squelettes'], // devrait etre 'chemin' => $GLOBALS['path_sig'], ?
240
-		'host' => ($_SERVER['HTTP_HOST'] ?? null),
241
-		'https' => ($_SERVER['HTTPS'] ?? ''),
242
-		'espace' => test_espace_prive(),
243
-		'marqueur' => ($GLOBALS['marqueur'] ?? ''),
244
-		'marqueur_skel' => ($GLOBALS['marqueur_skel'] ?? ''),
245
-		'notes' => $notes ? $notes('', 'contexter_cache') : '',
246
-		'spip_version_code' => $GLOBALS['spip_version_code'],
247
-	];
248
-	if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
249
-		$contexte_implicite['host'] .= '|' . $_SERVER['HTTP_X_FORWARDED_HOST'];
250
-	}
251
-
252
-	return $contexte_implicite;
234
+    static $notes = null;
235
+    if (is_null($notes)) {
236
+        $notes = charger_fonction('notes', 'inc', true);
237
+    }
238
+    $contexte_implicite = [
239
+        'squelettes' => $GLOBALS['dossier_squelettes'], // devrait etre 'chemin' => $GLOBALS['path_sig'], ?
240
+        'host' => ($_SERVER['HTTP_HOST'] ?? null),
241
+        'https' => ($_SERVER['HTTPS'] ?? ''),
242
+        'espace' => test_espace_prive(),
243
+        'marqueur' => ($GLOBALS['marqueur'] ?? ''),
244
+        'marqueur_skel' => ($GLOBALS['marqueur_skel'] ?? ''),
245
+        'notes' => $notes ? $notes('', 'contexter_cache') : '',
246
+        'spip_version_code' => $GLOBALS['spip_version_code'],
247
+    ];
248
+    if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
249
+        $contexte_implicite['host'] .= '|' . $_SERVER['HTTP_X_FORWARDED_HOST'];
250
+    }
251
+
252
+    return $contexte_implicite;
253 253
 }
254 254
 
255 255
 //
@@ -258,55 +258,55 @@  discard block
 block discarded – undo
258 258
 
259 259
 function auto_content_type($page) {
260 260
 
261
-	if (!isset($GLOBALS['flag_preserver'])) {
262
-		$GLOBALS['flag_preserver'] = ($page && preg_match(
263
-			'/header\s*\(\s*.content\-type:/isx',
264
-			$page['texte']
265
-		) || (isset($page['entetes']['Content-Type'])));
266
-	}
261
+    if (!isset($GLOBALS['flag_preserver'])) {
262
+        $GLOBALS['flag_preserver'] = ($page && preg_match(
263
+            '/header\s*\(\s*.content\-type:/isx',
264
+            $page['texte']
265
+        ) || (isset($page['entetes']['Content-Type'])));
266
+    }
267 267
 }
268 268
 
269 269
 function inclure_page($fond, $contexte, string $connect = '') {
270
-	$use_cache = null;
271
-	$chemin_cache = null;
272
-	$lastinclude = null;
273
-	$res = null;
274
-	static $cacher, $produire_page;
275
-
276
-	// enlever le fond de contexte inclus car sinon il prend la main
277
-	// dans les sous inclusions -> boucle infinie d'inclusion identique
278
-	// (cette precaution n'est probablement plus utile)
279
-	unset($contexte['fond']);
280
-	$page = ['contexte_implicite' => calculer_contexte_implicite()];
281
-	$page['contexte_implicite']['cache'] = $fond;
282
-	if (is_null($cacher)) {
283
-		$cacher = charger_fonction('cacher', 'public', true);
284
-	}
285
-	// Les quatre derniers parametres sont modifies par la fonction:
286
-	// emplacement, validite, et, s'il est valide, contenu & age
287
-	if ($cacher) {
288
-		$res = $cacher($contexte, $use_cache, $chemin_cache, $page, $lastinclude);
289
-	} else {
290
-		$use_cache = -1;
291
-	}
292
-	// $res = message d'erreur : on sort de la
293
-	if ($res) {
294
-		return ['texte' => $res];
295
-	}
296
-
297
-	// Si use_cache ne vaut pas 0, la page doit etre calculee
298
-	// produire la page : peut mettre a jour $lastinclude
299
-	// le contexte_cache envoye a cacher() a ete conserve et est passe a produire
300
-	if ($use_cache) {
301
-		if (is_null($produire_page)) {
302
-			$produire_page = charger_fonction('produire_page', 'public');
303
-		}
304
-		$page = $produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte, $page, $lastinclude, $connect);
305
-	}
306
-	// dans tous les cas, mettre a jour $GLOBALS['lastmodified']
307
-	$GLOBALS['lastmodified'] = max(($GLOBALS['lastmodified'] ?? 0), $lastinclude);
308
-
309
-	return $page;
270
+    $use_cache = null;
271
+    $chemin_cache = null;
272
+    $lastinclude = null;
273
+    $res = null;
274
+    static $cacher, $produire_page;
275
+
276
+    // enlever le fond de contexte inclus car sinon il prend la main
277
+    // dans les sous inclusions -> boucle infinie d'inclusion identique
278
+    // (cette precaution n'est probablement plus utile)
279
+    unset($contexte['fond']);
280
+    $page = ['contexte_implicite' => calculer_contexte_implicite()];
281
+    $page['contexte_implicite']['cache'] = $fond;
282
+    if (is_null($cacher)) {
283
+        $cacher = charger_fonction('cacher', 'public', true);
284
+    }
285
+    // Les quatre derniers parametres sont modifies par la fonction:
286
+    // emplacement, validite, et, s'il est valide, contenu & age
287
+    if ($cacher) {
288
+        $res = $cacher($contexte, $use_cache, $chemin_cache, $page, $lastinclude);
289
+    } else {
290
+        $use_cache = -1;
291
+    }
292
+    // $res = message d'erreur : on sort de la
293
+    if ($res) {
294
+        return ['texte' => $res];
295
+    }
296
+
297
+    // Si use_cache ne vaut pas 0, la page doit etre calculee
298
+    // produire la page : peut mettre a jour $lastinclude
299
+    // le contexte_cache envoye a cacher() a ete conserve et est passe a produire
300
+    if ($use_cache) {
301
+        if (is_null($produire_page)) {
302
+            $produire_page = charger_fonction('produire_page', 'public');
303
+        }
304
+        $page = $produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte, $page, $lastinclude, $connect);
305
+    }
306
+    // dans tous les cas, mettre a jour $GLOBALS['lastmodified']
307
+    $GLOBALS['lastmodified'] = max(($GLOBALS['lastmodified'] ?? 0), $lastinclude);
308
+
309
+    return $page;
310 310
 }
311 311
 
312 312
 /**
@@ -324,41 +324,41 @@  discard block
 block discarded – undo
324 324
  * @return array
325 325
  */
326 326
 function public_produire_page_dist(
327
-	$fond,
328
-	$contexte,
329
-	$use_cache,
330
-	$chemin_cache,
331
-	$contexte_cache,
332
-	&$page,
333
-	&$lastinclude,
334
-	$connect = ''
327
+    $fond,
328
+    $contexte,
329
+    $use_cache,
330
+    $chemin_cache,
331
+    $contexte_cache,
332
+    &$page,
333
+    &$lastinclude,
334
+    $connect = ''
335 335
 ) {
336
-	static $parametrer, $cacher;
337
-	if (!$parametrer) {
338
-		$parametrer = charger_fonction('parametrer', 'public');
339
-	}
340
-	$page = $parametrer($fond, $contexte, $chemin_cache, $connect);
341
-	// et on l'enregistre sur le disque
342
-	if (
343
-		$chemin_cache
344
-		and $use_cache > -1
345
-		and is_array($page)
346
-		and count($page)
347
-		and isset($page['entetes']['X-Spip-Cache'])
348
-		and $page['entetes']['X-Spip-Cache'] > 0
349
-	) {
350
-		if (is_null($cacher)) {
351
-			$cacher = charger_fonction('cacher', 'public', true);
352
-		}
353
-		$lastinclude = time();
354
-		if ($cacher) {
355
-			$cacher($contexte_cache, $use_cache, $chemin_cache, $page, $lastinclude);
356
-		} else {
357
-			$use_cache = -1;
358
-		}
359
-	}
360
-
361
-	return $page;
336
+    static $parametrer, $cacher;
337
+    if (!$parametrer) {
338
+        $parametrer = charger_fonction('parametrer', 'public');
339
+    }
340
+    $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
341
+    // et on l'enregistre sur le disque
342
+    if (
343
+        $chemin_cache
344
+        and $use_cache > -1
345
+        and is_array($page)
346
+        and count($page)
347
+        and isset($page['entetes']['X-Spip-Cache'])
348
+        and $page['entetes']['X-Spip-Cache'] > 0
349
+    ) {
350
+        if (is_null($cacher)) {
351
+            $cacher = charger_fonction('cacher', 'public', true);
352
+        }
353
+        $lastinclude = time();
354
+        if ($cacher) {
355
+            $cacher($contexte_cache, $use_cache, $chemin_cache, $page, $lastinclude);
356
+        } else {
357
+            $use_cache = -1;
358
+        }
359
+    }
360
+
361
+    return $page;
362 362
 }
363 363
 
364 364
 // Fonction inseree par le compilateur dans le code compile.
@@ -372,14 +372,14 @@  discard block
 block discarded – undo
372 372
 // 4: langue
373 373
 
374 374
 function inserer_balise_dynamique($contexte_exec, $contexte_compil) {
375
-	arguments_balise_dyn_depuis_modele(null, 'reset');
376
-
377
-	if (!is_array($contexte_exec)) {
378
-		echo $contexte_exec;
379
-	} // message d'erreur etc
380
-	else {
381
-		inclure_balise_dynamique($contexte_exec, true, $contexte_compil);
382
-	}
375
+    arguments_balise_dyn_depuis_modele(null, 'reset');
376
+
377
+    if (!is_array($contexte_exec)) {
378
+        echo $contexte_exec;
379
+    } // message d'erreur etc
380
+    else {
381
+        inclure_balise_dynamique($contexte_exec, true, $contexte_compil);
382
+    }
383 383
 }
384 384
 
385 385
 /**
@@ -392,101 +392,101 @@  discard block
 block discarded – undo
392 392
  * @return string
393 393
  */
394 394
 function inclure_balise_dynamique($texte, $echo = true, $contexte_compil = []) {
395
-	if (is_array($texte)) {
396
-		[$fond, $delainc, $contexte_inclus] = $texte;
397
-
398
-		// delais a l'ancienne, c'est pratiquement mort
399
-		$d = $GLOBALS['delais'] ?? null;
400
-		$GLOBALS['delais'] = $delainc;
401
-
402
-		$page = recuperer_fond(
403
-			$fond,
404
-			$contexte_inclus,
405
-			['trim' => false, 'raw' => true, 'compil' => $contexte_compil]
406
-		);
407
-
408
-		$texte = $page['texte'];
409
-
410
-		$GLOBALS['delais'] = $d;
411
-		// Faire remonter les entetes
412
-		if (
413
-			isset($page['entetes'])
414
-			and is_array($page['entetes'])
415
-		) {
416
-			// mais pas toutes
417
-			unset($page['entetes']['X-Spip-Cache']);
418
-			unset($page['entetes']['Content-Type']);
419
-			if (isset($GLOBALS['page']) and is_array($GLOBALS['page'])) {
420
-				if (!is_array($GLOBALS['page']['entetes'])) {
421
-					$GLOBALS['page']['entetes'] = [];
422
-				}
423
-				$GLOBALS['page']['entetes'] =
424
-					array_merge($GLOBALS['page']['entetes'], $page['entetes']);
425
-			}
426
-		}
427
-		// _pipelines au pluriel array('nom_pipeline' => $args...) avec une syntaxe permettant plusieurs pipelines
428
-		if (
429
-			isset($page['contexte']['_pipelines'])
430
-			and is_array($page['contexte']['_pipelines'])
431
-			and count($page['contexte']['_pipelines'])
432
-		) {
433
-			foreach ($page['contexte']['_pipelines'] as $pipe => $args) {
434
-				$args['contexte'] = $page['contexte'];
435
-				unset($args['contexte']['_pipelines']); // par precaution, meme si le risque de boucle infinie est a priori nul
436
-				$texte = pipeline(
437
-					$pipe,
438
-					[
439
-						'data' => $texte,
440
-						'args' => $args
441
-					]
442
-				);
443
-			}
444
-		}
445
-	}
446
-
447
-	if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
448
-		// compatibilite : avant on donnait le numero de ligne ou rien.
449
-		$ligne = intval($contexte_compil[3] ?? $contexte_compil);
450
-		$GLOBALS['debug_objets']['resultat'][$ligne] = $texte;
451
-	}
452
-	if ($echo) {
453
-		echo $texte;
454
-	} else {
455
-		return $texte;
456
-	}
395
+    if (is_array($texte)) {
396
+        [$fond, $delainc, $contexte_inclus] = $texte;
397
+
398
+        // delais a l'ancienne, c'est pratiquement mort
399
+        $d = $GLOBALS['delais'] ?? null;
400
+        $GLOBALS['delais'] = $delainc;
401
+
402
+        $page = recuperer_fond(
403
+            $fond,
404
+            $contexte_inclus,
405
+            ['trim' => false, 'raw' => true, 'compil' => $contexte_compil]
406
+        );
407
+
408
+        $texte = $page['texte'];
409
+
410
+        $GLOBALS['delais'] = $d;
411
+        // Faire remonter les entetes
412
+        if (
413
+            isset($page['entetes'])
414
+            and is_array($page['entetes'])
415
+        ) {
416
+            // mais pas toutes
417
+            unset($page['entetes']['X-Spip-Cache']);
418
+            unset($page['entetes']['Content-Type']);
419
+            if (isset($GLOBALS['page']) and is_array($GLOBALS['page'])) {
420
+                if (!is_array($GLOBALS['page']['entetes'])) {
421
+                    $GLOBALS['page']['entetes'] = [];
422
+                }
423
+                $GLOBALS['page']['entetes'] =
424
+                    array_merge($GLOBALS['page']['entetes'], $page['entetes']);
425
+            }
426
+        }
427
+        // _pipelines au pluriel array('nom_pipeline' => $args...) avec une syntaxe permettant plusieurs pipelines
428
+        if (
429
+            isset($page['contexte']['_pipelines'])
430
+            and is_array($page['contexte']['_pipelines'])
431
+            and count($page['contexte']['_pipelines'])
432
+        ) {
433
+            foreach ($page['contexte']['_pipelines'] as $pipe => $args) {
434
+                $args['contexte'] = $page['contexte'];
435
+                unset($args['contexte']['_pipelines']); // par precaution, meme si le risque de boucle infinie est a priori nul
436
+                $texte = pipeline(
437
+                    $pipe,
438
+                    [
439
+                        'data' => $texte,
440
+                        'args' => $args
441
+                    ]
442
+                );
443
+            }
444
+        }
445
+    }
446
+
447
+    if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
448
+        // compatibilite : avant on donnait le numero de ligne ou rien.
449
+        $ligne = intval($contexte_compil[3] ?? $contexte_compil);
450
+        $GLOBALS['debug_objets']['resultat'][$ligne] = $texte;
451
+    }
452
+    if ($echo) {
453
+        echo $texte;
454
+    } else {
455
+        return $texte;
456
+    }
457 457
 }
458 458
 
459 459
 function message_page_indisponible($page, $contexte) {
460
-	static $deja = false;
461
-	if ($deja) {
462
-		return 'erreur';
463
-	}
464
-	$codes = [
465
-		'404' => '404 Not Found',
466
-		'503' => '503 Service Unavailable',
467
-	];
468
-
469
-	$contexte['status'] = ($page !== false) ? '404' : '503';
470
-	$contexte['code'] = $codes[$contexte['status']];
471
-	$contexte['fond'] = '404'; // gere les 2 erreurs
472
-	if (!isset($contexte['lang'])) {
473
-		include_spip('inc/lang');
474
-		$contexte['lang'] = $GLOBALS['spip_lang'];
475
-	}
476
-
477
-	$deja = true;
478
-	// passer aux plugins qui peuvent decider d'une page d'erreur plus pertinent
479
-	// ex restriction d'acces => 401
480
-	$contexte = pipeline('page_indisponible', $contexte);
481
-
482
-	// produire la page d'erreur
483
-	$page = inclure_page($contexte['fond'], $contexte);
484
-	if (!$page) {
485
-		$page = inclure_page('404', $contexte);
486
-	}
487
-	$page['status'] = $contexte['status'];
488
-
489
-	return $page;
460
+    static $deja = false;
461
+    if ($deja) {
462
+        return 'erreur';
463
+    }
464
+    $codes = [
465
+        '404' => '404 Not Found',
466
+        '503' => '503 Service Unavailable',
467
+    ];
468
+
469
+    $contexte['status'] = ($page !== false) ? '404' : '503';
470
+    $contexte['code'] = $codes[$contexte['status']];
471
+    $contexte['fond'] = '404'; // gere les 2 erreurs
472
+    if (!isset($contexte['lang'])) {
473
+        include_spip('inc/lang');
474
+        $contexte['lang'] = $GLOBALS['spip_lang'];
475
+    }
476
+
477
+    $deja = true;
478
+    // passer aux plugins qui peuvent decider d'une page d'erreur plus pertinent
479
+    // ex restriction d'acces => 401
480
+    $contexte = pipeline('page_indisponible', $contexte);
481
+
482
+    // produire la page d'erreur
483
+    $page = inclure_page($contexte['fond'], $contexte);
484
+    if (!$page) {
485
+        $page = inclure_page('404', $contexte);
486
+    }
487
+    $page['status'] = $contexte['status'];
488
+
489
+    return $page;
490 490
 }
491 491
 
492 492
 /**
@@ -498,44 +498,44 @@  discard block
 block discarded – undo
498 498
  * @return mixed
499 499
  */
500 500
 function arguments_balise_dyn_depuis_modele($arg, $operation = 'set') {
501
-	static $balise_dyn_appellee_par_modele = null;
502
-	switch ($operation) {
503
-		case 'read':
504
-			return $balise_dyn_appellee_par_modele;
505
-		case 'reset':
506
-			$balise_dyn_appellee_par_modele = null;
507
-			return null;
508
-		case 'set':
509
-		default:
510
-			$balise_dyn_appellee_par_modele = $arg;
511
-			return $arg;
512
-	}
501
+    static $balise_dyn_appellee_par_modele = null;
502
+    switch ($operation) {
503
+        case 'read':
504
+            return $balise_dyn_appellee_par_modele;
505
+        case 'reset':
506
+            $balise_dyn_appellee_par_modele = null;
507
+            return null;
508
+        case 'set':
509
+        default:
510
+            $balise_dyn_appellee_par_modele = $arg;
511
+            return $arg;
512
+    }
513 513
 }
514 514
 
515 515
 // temporairement ici : a mettre dans le futur inc/modeles
516 516
 // creer_contexte_de_modele('left', 'autostart=true', ...) renvoie un array()
517 517
 function creer_contexte_de_modele($args) {
518
-	$contexte = [];
519
-	foreach ($args as $var => $val) {
520
-		if (is_int($var)) { // argument pas formate
521
-			if (in_array($val, ['left', 'right', 'center'])) {
522
-				$var = 'align';
523
-				$contexte[$var] = $val;
524
-			} else {
525
-				$args = explode('=', $val);
526
-				if (count($args) >= 2) { // Flashvars=arg1=machin&arg2=truc genere plus de deux args
527
-				$contexte[trim($args[0])] = substr($val, strlen($args[0]) + 1);
528
-				} else // notation abregee
529
-				{
530
-					$contexte[trim($val)] = trim($val);
531
-				}
532
-			}
533
-		} else {
534
-			$contexte[$var] = $val;
535
-		}
536
-	}
537
-
538
-	return $contexte;
518
+    $contexte = [];
519
+    foreach ($args as $var => $val) {
520
+        if (is_int($var)) { // argument pas formate
521
+            if (in_array($val, ['left', 'right', 'center'])) {
522
+                $var = 'align';
523
+                $contexte[$var] = $val;
524
+            } else {
525
+                $args = explode('=', $val);
526
+                if (count($args) >= 2) { // Flashvars=arg1=machin&arg2=truc genere plus de deux args
527
+                $contexte[trim($args[0])] = substr($val, strlen($args[0]) + 1);
528
+                } else // notation abregee
529
+                {
530
+                    $contexte[trim($val)] = trim($val);
531
+                }
532
+            }
533
+        } else {
534
+            $contexte[$var] = $val;
535
+        }
536
+    }
537
+
538
+    return $contexte;
539 539
 }
540 540
 
541 541
 /**
@@ -550,43 +550,43 @@  discard block
 block discarded – undo
550 550
  * @return string
551 551
  */
552 552
 function styliser_modele($modele, $id, $contexte = null) {
553
-	static $styliseurs = null;
554
-	if (is_null($styliseurs)) {
555
-		$tables_objet = lister_tables_objets_sql();
556
-		foreach ($tables_objet as $table => $desc) {
557
-			if (
558
-				isset($desc['modeles']) and $desc['modeles']
559
-				and isset($desc['modeles_styliser']) and $desc['modeles_styliser']
560
-				and function_exists($desc['modeles_styliser'])
561
-			) {
562
-				$primary = id_table_objet($table);
563
-				foreach ($desc['modeles'] as $m) {
564
-					$styliseurs[$m] = ['primary' => $primary, 'callback' => $desc['modeles_styliser']];
565
-				}
566
-			}
567
-		}
568
-	}
569
-
570
-	if (isset($styliseurs[$modele])) {
571
-		$styliseur = $styliseurs[$modele]['callback'];
572
-		$primary = $styliseurs[$modele]['primary'];
573
-		if (is_null($id) and $contexte) {
574
-			if (isset($contexte['id'])) {
575
-				$id = $contexte['id'];
576
-			} elseif (isset($contexte[$primary])) {
577
-				$id = $contexte[$primary];
578
-			}
579
-		}
580
-		if (is_null($id)) {
581
-			$msg = "modeles/$modele : " . _T('zbug_parametres_inclus_incorrects', ['param' => "id/$primary"]);
582
-			erreur_squelette($msg);
583
-			// on passe id=0 au routeur pour tomber sur le modele par defaut et eviter une seconde erreur sur un modele inexistant
584
-			$id = 0;
585
-		}
586
-		$modele = $styliseur($modele, $id);
587
-	}
588
-
589
-	return $modele;
553
+    static $styliseurs = null;
554
+    if (is_null($styliseurs)) {
555
+        $tables_objet = lister_tables_objets_sql();
556
+        foreach ($tables_objet as $table => $desc) {
557
+            if (
558
+                isset($desc['modeles']) and $desc['modeles']
559
+                and isset($desc['modeles_styliser']) and $desc['modeles_styliser']
560
+                and function_exists($desc['modeles_styliser'])
561
+            ) {
562
+                $primary = id_table_objet($table);
563
+                foreach ($desc['modeles'] as $m) {
564
+                    $styliseurs[$m] = ['primary' => $primary, 'callback' => $desc['modeles_styliser']];
565
+                }
566
+            }
567
+        }
568
+    }
569
+
570
+    if (isset($styliseurs[$modele])) {
571
+        $styliseur = $styliseurs[$modele]['callback'];
572
+        $primary = $styliseurs[$modele]['primary'];
573
+        if (is_null($id) and $contexte) {
574
+            if (isset($contexte['id'])) {
575
+                $id = $contexte['id'];
576
+            } elseif (isset($contexte[$primary])) {
577
+                $id = $contexte[$primary];
578
+            }
579
+        }
580
+        if (is_null($id)) {
581
+            $msg = "modeles/$modele : " . _T('zbug_parametres_inclus_incorrects', ['param' => "id/$primary"]);
582
+            erreur_squelette($msg);
583
+            // on passe id=0 au routeur pour tomber sur le modele par defaut et eviter une seconde erreur sur un modele inexistant
584
+            $id = 0;
585
+        }
586
+        $modele = $styliseur($modele, $id);
587
+    }
588
+
589
+    return $modele;
590 590
 }
591 591
 
592 592
 /**
@@ -603,102 +603,102 @@  discard block
 block discarded – undo
603 603
  */
604 604
 function inclure_modele($type, $id, $params, $lien, string $connect = '', $env = []) {
605 605
 
606
-	static $compteur;
607
-	if (++$compteur > 10) {
608
-		return '';
609
-	} # ne pas boucler indefiniment
610
-
611
-	$type = strtolower($type);
612
-	$type = styliser_modele($type, $id);
613
-
614
-	$fond = $class = '';
615
-
616
-	$params = array_filter(explode('|', $params));
617
-	if ($params) {
618
-		$soustype = current($params);
619
-		$soustype = strtolower(trim($soustype));
620
-		if (in_array($soustype, ['left', 'right', 'center', 'ajax'])) {
621
-			$soustype = next($params);
622
-			$soustype = strtolower($soustype);
623
-		}
624
-
625
-		if (preg_match(',^[a-z0-9_]+$,', $soustype)) {
626
-			if (!trouve_modele($fond = ($type . '_' . $soustype))) {
627
-				$fond = '';
628
-				$class = $soustype;
629
-			}
630
-			// enlever le sous type des params
631
-			$params = array_diff($params, [$soustype]);
632
-		}
633
-	}
634
-
635
-	// Si ca marche pas en precisant le sous-type, prendre le type
636
-	if (!$fond and !trouve_modele($fond = $type)) {
637
-		spip_log("Modele $type introuvable", _LOG_INFO_IMPORTANTE);
638
-
639
-		return false;
640
-	}
641
-	$fond = 'modeles/' . $fond;
642
-	// Creer le contexte
643
-	$contexte = $env;
644
-	$contexte['dir_racine'] = _DIR_RACINE; # eviter de mixer un cache racine et un cache ecrire (meme si pour l'instant les modeles ne sont pas caches, le resultat etant different il faut que le contexte en tienne compte
645
-
646
-	// Le numero du modele est mis dans l'environnement
647
-	// d'une part sous l'identifiant "id"
648
-	// et d'autre part sous l'identifiant de la cle primaire
649
-	// par la fonction id_table_objet,
650
-	// (<article1> =>> article =>> id_article =>> id_article=1)
651
-	$_id = id_table_objet($type);
652
-	$contexte['id'] = $contexte[$_id] = $id;
653
-
654
-	if (isset($class)) {
655
-		$contexte['class'] = $class;
656
-	}
657
-
658
-	// Si un lien a ete passe en parametre, ex: [<modele1>->url] ou [<modele1|title_du_lien{hreflang}->url]
659
-	if ($lien) {
660
-		# un eventuel guillemet (") sera reechappe par #ENV
661
-		$contexte['lien'] = str_replace('&quot;', '"', $lien['href']);
662
-		$contexte['lien_class'] = $lien['class'];
663
-		$contexte['lien_mime'] = $lien['mime'];
664
-		$contexte['lien_title'] = $lien['title'];
665
-		$contexte['lien_hreflang'] = $lien['hreflang'];
666
-	}
667
-
668
-	// Traiter les parametres
669
-	// par exemple : <img1|center>, <emb12|autostart=true> ou <doc1|lang=en>
670
-	$arg_list = creer_contexte_de_modele($params);
671
-	$contexte['args'] = $arg_list; // on passe la liste des arguments du modeles dans une variable args
672
-	$contexte = array_merge($contexte, $arg_list);
673
-
674
-	// Appliquer le modele avec le contexte
675
-	$retour = recuperer_fond($fond, $contexte, [], $connect);
676
-
677
-	// Regarder si le modele tient compte des liens (il *doit* alors indiquer
678
-	// spip_lien_ok dans les classes de son conteneur de premier niveau ;
679
-	// sinon, s'il y a un lien, on l'ajoute classiquement
680
-	if (
681
-		strstr(
682
-			' ' . ($classes = extraire_attribut($retour, 'class')) . ' ',
683
-			'spip_lien_ok'
684
-		)
685
-	) {
686
-		$retour = inserer_attribut(
687
-			$retour,
688
-			'class',
689
-			trim(str_replace(' spip_lien_ok ', ' ', " $classes "))
690
-		);
691
-	} else {
692
-		if ($lien) {
693
-			$retour = "<a href='" . $lien['href'] . "' class='" . $lien['class'] . "'>" . $retour . '</a>';
694
-		}
695
-	}
696
-
697
-	$compteur--;
698
-
699
-	return (isset($arg_list['ajax']) and $arg_list['ajax'] == 'ajax')
700
-		? encoder_contexte_ajax($contexte, '', $retour)
701
-		: $retour;
606
+    static $compteur;
607
+    if (++$compteur > 10) {
608
+        return '';
609
+    } # ne pas boucler indefiniment
610
+
611
+    $type = strtolower($type);
612
+    $type = styliser_modele($type, $id);
613
+
614
+    $fond = $class = '';
615
+
616
+    $params = array_filter(explode('|', $params));
617
+    if ($params) {
618
+        $soustype = current($params);
619
+        $soustype = strtolower(trim($soustype));
620
+        if (in_array($soustype, ['left', 'right', 'center', 'ajax'])) {
621
+            $soustype = next($params);
622
+            $soustype = strtolower($soustype);
623
+        }
624
+
625
+        if (preg_match(',^[a-z0-9_]+$,', $soustype)) {
626
+            if (!trouve_modele($fond = ($type . '_' . $soustype))) {
627
+                $fond = '';
628
+                $class = $soustype;
629
+            }
630
+            // enlever le sous type des params
631
+            $params = array_diff($params, [$soustype]);
632
+        }
633
+    }
634
+
635
+    // Si ca marche pas en precisant le sous-type, prendre le type
636
+    if (!$fond and !trouve_modele($fond = $type)) {
637
+        spip_log("Modele $type introuvable", _LOG_INFO_IMPORTANTE);
638
+
639
+        return false;
640
+    }
641
+    $fond = 'modeles/' . $fond;
642
+    // Creer le contexte
643
+    $contexte = $env;
644
+    $contexte['dir_racine'] = _DIR_RACINE; # eviter de mixer un cache racine et un cache ecrire (meme si pour l'instant les modeles ne sont pas caches, le resultat etant different il faut que le contexte en tienne compte
645
+
646
+    // Le numero du modele est mis dans l'environnement
647
+    // d'une part sous l'identifiant "id"
648
+    // et d'autre part sous l'identifiant de la cle primaire
649
+    // par la fonction id_table_objet,
650
+    // (<article1> =>> article =>> id_article =>> id_article=1)
651
+    $_id = id_table_objet($type);
652
+    $contexte['id'] = $contexte[$_id] = $id;
653
+
654
+    if (isset($class)) {
655
+        $contexte['class'] = $class;
656
+    }
657
+
658
+    // Si un lien a ete passe en parametre, ex: [<modele1>->url] ou [<modele1|title_du_lien{hreflang}->url]
659
+    if ($lien) {
660
+        # un eventuel guillemet (") sera reechappe par #ENV
661
+        $contexte['lien'] = str_replace('&quot;', '"', $lien['href']);
662
+        $contexte['lien_class'] = $lien['class'];
663
+        $contexte['lien_mime'] = $lien['mime'];
664
+        $contexte['lien_title'] = $lien['title'];
665
+        $contexte['lien_hreflang'] = $lien['hreflang'];
666
+    }
667
+
668
+    // Traiter les parametres
669
+    // par exemple : <img1|center>, <emb12|autostart=true> ou <doc1|lang=en>
670
+    $arg_list = creer_contexte_de_modele($params);
671
+    $contexte['args'] = $arg_list; // on passe la liste des arguments du modeles dans une variable args
672
+    $contexte = array_merge($contexte, $arg_list);
673
+
674
+    // Appliquer le modele avec le contexte
675
+    $retour = recuperer_fond($fond, $contexte, [], $connect);
676
+
677
+    // Regarder si le modele tient compte des liens (il *doit* alors indiquer
678
+    // spip_lien_ok dans les classes de son conteneur de premier niveau ;
679
+    // sinon, s'il y a un lien, on l'ajoute classiquement
680
+    if (
681
+        strstr(
682
+            ' ' . ($classes = extraire_attribut($retour, 'class')) . ' ',
683
+            'spip_lien_ok'
684
+        )
685
+    ) {
686
+        $retour = inserer_attribut(
687
+            $retour,
688
+            'class',
689
+            trim(str_replace(' spip_lien_ok ', ' ', " $classes "))
690
+        );
691
+    } else {
692
+        if ($lien) {
693
+            $retour = "<a href='" . $lien['href'] . "' class='" . $lien['class'] . "'>" . $retour . '</a>';
694
+        }
695
+    }
696
+
697
+    $compteur--;
698
+
699
+    return (isset($arg_list['ajax']) and $arg_list['ajax'] == 'ajax')
700
+        ? encoder_contexte_ajax($contexte, '', $retour)
701
+        : $retour;
702 702
 }
703 703
 
704 704
 // Un inclure_page qui marche aussi pour l'espace prive
@@ -707,105 +707,105 @@  discard block
 block discarded – undo
707 707
 // 	recuperer_fond($fond,$contexte,array('raw'=>true))
708 708
 function evaluer_fond($fond, $contexte = [], string $connect = '') {
709 709
 
710
-	$page = inclure_page($fond, $contexte, $connect);
711
-
712
-	if (!$page) {
713
-		return $page;
714
-	}
715
-	// eval $page et affecte $res
716
-	include _ROOT_RESTREINT . 'public/evaluer_page.php';
717
-
718
-	// Lever un drapeau (global) si le fond utilise #SESSION
719
-	// a destination de public/parametrer
720
-	// pour remonter vers les inclusions appelantes
721
-	// il faut bien lever ce drapeau apres avoir evalue le fond
722
-	// pour ne pas faire descendre le flag vers les inclusions appelees
723
-	if (
724
-		isset($page['invalideurs'])
725
-		and isset($page['invalideurs']['session'])
726
-	) {
727
-		$GLOBALS['cache_utilise_session'] = $page['invalideurs']['session'];
728
-	}
729
-
730
-	return $page;
710
+    $page = inclure_page($fond, $contexte, $connect);
711
+
712
+    if (!$page) {
713
+        return $page;
714
+    }
715
+    // eval $page et affecte $res
716
+    include _ROOT_RESTREINT . 'public/evaluer_page.php';
717
+
718
+    // Lever un drapeau (global) si le fond utilise #SESSION
719
+    // a destination de public/parametrer
720
+    // pour remonter vers les inclusions appelantes
721
+    // il faut bien lever ce drapeau apres avoir evalue le fond
722
+    // pour ne pas faire descendre le flag vers les inclusions appelees
723
+    if (
724
+        isset($page['invalideurs'])
725
+        and isset($page['invalideurs']['session'])
726
+    ) {
727
+        $GLOBALS['cache_utilise_session'] = $page['invalideurs']['session'];
728
+    }
729
+
730
+    return $page;
731 731
 }
732 732
 
733 733
 
734 734
 function page_base_href(&$texte) {
735
-	static $set_html_base = null;
736
-	if (is_null($set_html_base)) {
737
-		if (!defined('_SET_HTML_BASE')) {
738
-			// si la profondeur est superieure a 1
739
-			// est que ce n'est pas une url page ni une url action
740
-			// activer par defaut
741
-		$set_html_base = ((
742
-				$GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
743
-				and _request(_SPIP_PAGE) !== 'login'
744
-				and !_request('action')) ? true : false);
745
-		} else {
746
-			$set_html_base = _SET_HTML_BASE;
747
-		}
748
-	}
749
-
750
-	if (
751
-		$set_html_base
752
-		and isset($GLOBALS['html']) and $GLOBALS['html']
753
-		and $GLOBALS['profondeur_url'] > 0
754
-		and ($poshead = strpos($texte, '</head>')) !== false
755
-	) {
756
-		$head = substr($texte, 0, $poshead);
757
-		$insert = false;
758
-		$href_base = false;
759
-		if (strpos($head, '<base') === false) {
760
-			$insert = true;
761
-		} else {
762
-			// si aucun <base ...> n'a de href il faut en inserer un
763
-			// sinon juste re-ecrire les ancres si besoin
764
-			$insert = true;
765
-			include_spip('inc/filtres');
766
-			$bases = extraire_balises($head, 'base');
767
-			foreach ($bases as $base) {
768
-				if ($href_base = extraire_attribut($base, 'href')) {
769
-					$insert = false;
770
-					break;
771
-				}
772
-			}
773
-		}
774
-
775
-		if ($insert) {
776
-			include_spip('inc/filtres_mini');
777
-			// ajouter un base qui reglera tous les liens relatifs
778
-			$href_base = url_absolue('./');
779
-			$base = "\n<base href=\"$href_base\" />";
780
-			if (($pos = strpos($head, '<head>')) !== false) {
781
-				$head = substr_replace($head, $base, $pos + 6, 0);
782
-			} elseif (preg_match(',<head[^>]*>,i', $head, $r)) {
783
-				$head = str_replace($r[0], $r[0] . $base, $head);
784
-			}
785
-			$texte = $head . substr($texte, $poshead);
786
-		}
787
-		if ($href_base) {
788
-			// gerer les ancres
789
-			$base = $_SERVER['REQUEST_URI'];
790
-			// pas de guillemets ni < dans l'URL qu'on insere dans le HTML
791
-			if (strpos($base, "'") or strpos($base, '"') or strpos($base, '<')) {
792
-				$base = str_replace(["'",'"','<'], ['%27','%22','%3C'], $base);
793
-			}
794
-			if (strpos($texte, "href='#") !== false) {
795
-				$texte = str_replace("href='#", "href='$base#", $texte);
796
-			}
797
-			if (strpos($texte, 'href="#') !== false) {
798
-				$texte = str_replace('href="#', "href=\"$base#", $texte);
799
-			}
800
-		}
801
-	}
735
+    static $set_html_base = null;
736
+    if (is_null($set_html_base)) {
737
+        if (!defined('_SET_HTML_BASE')) {
738
+            // si la profondeur est superieure a 1
739
+            // est que ce n'est pas une url page ni une url action
740
+            // activer par defaut
741
+        $set_html_base = ((
742
+                $GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
743
+                and _request(_SPIP_PAGE) !== 'login'
744
+                and !_request('action')) ? true : false);
745
+        } else {
746
+            $set_html_base = _SET_HTML_BASE;
747
+        }
748
+    }
749
+
750
+    if (
751
+        $set_html_base
752
+        and isset($GLOBALS['html']) and $GLOBALS['html']
753
+        and $GLOBALS['profondeur_url'] > 0
754
+        and ($poshead = strpos($texte, '</head>')) !== false
755
+    ) {
756
+        $head = substr($texte, 0, $poshead);
757
+        $insert = false;
758
+        $href_base = false;
759
+        if (strpos($head, '<base') === false) {
760
+            $insert = true;
761
+        } else {
762
+            // si aucun <base ...> n'a de href il faut en inserer un
763
+            // sinon juste re-ecrire les ancres si besoin
764
+            $insert = true;
765
+            include_spip('inc/filtres');
766
+            $bases = extraire_balises($head, 'base');
767
+            foreach ($bases as $base) {
768
+                if ($href_base = extraire_attribut($base, 'href')) {
769
+                    $insert = false;
770
+                    break;
771
+                }
772
+            }
773
+        }
774
+
775
+        if ($insert) {
776
+            include_spip('inc/filtres_mini');
777
+            // ajouter un base qui reglera tous les liens relatifs
778
+            $href_base = url_absolue('./');
779
+            $base = "\n<base href=\"$href_base\" />";
780
+            if (($pos = strpos($head, '<head>')) !== false) {
781
+                $head = substr_replace($head, $base, $pos + 6, 0);
782
+            } elseif (preg_match(',<head[^>]*>,i', $head, $r)) {
783
+                $head = str_replace($r[0], $r[0] . $base, $head);
784
+            }
785
+            $texte = $head . substr($texte, $poshead);
786
+        }
787
+        if ($href_base) {
788
+            // gerer les ancres
789
+            $base = $_SERVER['REQUEST_URI'];
790
+            // pas de guillemets ni < dans l'URL qu'on insere dans le HTML
791
+            if (strpos($base, "'") or strpos($base, '"') or strpos($base, '<')) {
792
+                $base = str_replace(["'",'"','<'], ['%27','%22','%3C'], $base);
793
+            }
794
+            if (strpos($texte, "href='#") !== false) {
795
+                $texte = str_replace("href='#", "href='$base#", $texte);
796
+            }
797
+            if (strpos($texte, 'href="#') !== false) {
798
+                $texte = str_replace('href="#', "href=\"$base#", $texte);
799
+            }
800
+        }
801
+    }
802 802
 }
803 803
 
804 804
 
805 805
 // Envoyer les entetes, en retenant ceux qui sont a usage interne
806 806
 // et demarrent par X-Spip-...
807 807
 function envoyer_entetes($entetes) {
808
-	foreach ($entetes as $k => $v) { #	if (strncmp($k, 'X-Spip-', 7))
809
-	@header(strlen($v) ? "$k: $v" : $k);
810
-	}
808
+    foreach ($entetes as $k => $v) { #	if (strncmp($k, 'X-Spip-', 7))
809
+    @header(strlen($v) ? "$k: $v" : $k);
810
+    }
811 811
 }
Please login to merge, or discard this patch.