Completed
Push — master ( 47aeae...d8d4cc )
by cam
07:22
created

balises.php ➔ balise_CONST_dist()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2017                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
/**
14
 * Ce fichier regroupe la quasi totalité des définitions de `#BALISES` de SPIP.
15
 *
16
 * Pour chaque balise, il est possible de surcharger, dans son fichier
17
 * mes_fonctions.php, la fonction `balise_TOTO_dist()` par une fonction
18
 * `balise_TOTO()` respectant la même API : elle reçoit en entrée un objet
19
 * de classe `Champ`, le modifie et le retourne. Cette classe est définie
20
 * dans public/interfaces.
21
 *
22
 * Des balises dites «dynamiques» sont également déclarées dans le
23
 * répertoire ecrire/balise/
24
 *
25
 * @package SPIP\Core\Compilateur\Balises
26
 **/
27
28
if (!defined('_ECRIRE_INC_VERSION')) {
29
	return;
30
}
31
32
/**
33
 * Retourne le code PHP d'un argument de balise s'il est présent
34
 *
35
 * @uses calculer_liste()
36
 * @example
37
 *     ```
38
 *     // Retourne le premier argument de la balise
39
 *     // #BALISE{premier,deuxieme}
40
 *     $arg = interprete_argument_balise(1,$p);
41
 *     ```
42
 *
43
 * @param int $n
44
 *     Numéro de l'argument
45
 * @param Champ $p
46
 *     Pile au niveau de la balise
47
 * @return string|null
48
 *     Code PHP si cet argument est présent, sinon null
49
 **/
50
function interprete_argument_balise($n, $p) {
51
	if (($p->param) && (!$p->param[0][0]) && (count($p->param[0]) > $n)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->param of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
52
		return calculer_liste($p->param[0][$n],
53
			$p->descr,
54
			$p->boucles,
55
			$p->id_boucle);
56
	} else {
57
		return null;
58
	}
59
}
60
61
62
//
63
// Définition des balises
64
//
65
66
/**
67
 * Compile la balise `#NOM_SITE_SPIP` retournant le nom du site
68
 *
69
 * @balise
70
 * @link http://www.spip.net/4622
71
 *
72
 * @param Champ $p
73
 *     Pile au niveau de la balise
74
 * @return Champ
75
 *     Pile complétée par le code à générer
76
 **/
77
function balise_NOM_SITE_SPIP_dist($p) {
78
	$p->code = "\$GLOBALS['meta']['nom_site']";
79
80
	#$p->interdire_scripts = true;
81
	return $p;
82
}
83
84
/**
85
 * Compile la balise `#EMAIL_WEBMASTER` retournant l'adresse courriel
86
 * du webmestre
87
 *
88
 * @balise
89
 * @link http://www.spip.net/4586
90
 *
91
 * @param Champ $p
92
 *     Pile au niveau de la balise
93
 * @return Champ
94
 *     Pile complétée par le code à générer
95
 **/
96
function balise_EMAIL_WEBMASTER_dist($p) {
97
	$p->code = "\$GLOBALS['meta']['email_webmaster']";
98
99
	#$p->interdire_scripts = true;
100
	return $p;
101
}
102
103
/**
104
 * Compile la balise `#DESCRIPTIF_SITE_SPIP` qui retourne le descriptif
105
 * du site !
106
 *
107
 * @balise
108
 * @link http://www.spip.net/4338
109
 *
110
 * @param Champ $p
111
 *     Pile au niveau de la balise
112
 * @return Champ
113
 *     Pile complétée par le code à générer
114
 **/
115
function balise_DESCRIPTIF_SITE_SPIP_dist($p) {
116
	$p->code = "\$GLOBALS['meta']['descriptif_site']";
117
118
	#$p->interdire_scripts = true;
119
	return $p;
120
}
121
122
123
/**
124
 * Compile la balise `#CHARSET` qui retourne le nom du jeu de caractères
125
 * utilisé par le site tel que `utf-8`
126
 *
127
 * @balise
128
 * @link http://www.spip.net/4331
129
 * @example
130
 *     ```
131
 *     <meta http-equiv="Content-Type" content="text/html; charset=#CHARSET" />
132
 *     ```
133
 *
134
 * @param Champ $p
135
 *     Pile au niveau de la balise
136
 * @return Champ
137
 *     Pile complétée par le code à générer
138
 **/
139
function balise_CHARSET_dist($p) {
140
	$p->code = "\$GLOBALS['meta']['charset']";
141
142
	#$p->interdire_scripts = true;
143
	return $p;
144
}
145
146
/**
147
 * Compile la balise `#LANG_LEFT` retournant 'left' si la langue s'écrit
148
 * de gauche à droite, sinon 'right'
149
 *
150
 * @note
151
 *     Peut servir à l'écriture de code CSS dans un squelette, mais
152
 *     pour inclure un fichier css, il vaut mieux utiliser le filtre
153
 *     `direction_css` si on le souhaite sensible à la langue utilisé.
154
 *
155
 * @balise
156
 * @link http://www.spip.net/4625
157
 * @see lang_dir()
158
 * @see balise_LANG_RIGHT_dist()
159
 * @see balise_LANG_DIR_dist()
160
 * @see direction_css()
161
 *
162
 * @param Champ $p
163
 *     Pile au niveau de la balise
164
 * @return Champ
165
 *     Pile complétée par le code à générer
166
 **/
167 View Code Duplication
function balise_LANG_LEFT_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
168
	$_lang = champ_sql('lang', $p);
169
	$p->code = "lang_dir($_lang, 'left','right')";
170
	$p->interdire_scripts = false;
171
172
	return $p;
173
}
174
175
/**
176
 * Compile la balise `#LANG_RIGHT` retournant 'right' si la langue s'écrit
177
 * de gauche à droite, sinon 'left'
178
 *
179
 * @balise
180
 * @link http://www.spip.net/4625
181
 * @see lang_dir()
182
 * @see balise_LANG_LEFT_dist()
183
 * @see balise_LANG_DIR_dist()
184
 * @see direction_css()
185
 *
186
 * @param Champ $p
187
 *     Pile au niveau de la balise
188
 * @return Champ
189
 *     Pile complétée par le code à générer
190
 **/
191 View Code Duplication
function balise_LANG_RIGHT_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
	$_lang = champ_sql('lang', $p);
193
	$p->code = "lang_dir($_lang, 'right','left')";
194
	$p->interdire_scripts = false;
195
196
	return $p;
197
}
198
199
/**
200
 * Compile la balise `#LANG_DIR` retournant 'ltr' si la langue s'écrit
201
 * de gauche à droite, sinon 'rtl'
202
 *
203
 * @balise
204
 * @link http://www.spip.net/4625
205
 * @see lang_dir()
206
 * @see balise_LANG_LEFT_dist()
207
 * @see balise_LANG_RIGHT_dist()
208
 * @example
209
 *     ```
210
 *     <html dir="#LANG_DIR" lang="#LANG"
211
 *         xmlns="http://www.w3.org/1999/xhtml"
212
 *         xml:lang="#LANG" class="[(#LANG_DIR)][ (#LANG)] no-js">
213
 *     ```
214
 *
215
 * @param Champ $p
216
 *     Pile au niveau de la balise
217
 * @return Champ
218
 *     Pile complétée par le code à générer
219
 **/
220 View Code Duplication
function balise_LANG_DIR_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
	$_lang = champ_sql('lang', $p);
222
	$p->code = "lang_dir($_lang, 'ltr','rtl')";
223
	$p->interdire_scripts = false;
224
225
	return $p;
226
}
227
228
229
/**
230
 * Compile la balise `#PUCE` affichant une puce
231
 *
232
 * @balise
233
 * @link http://www.spip.net/4628
234
 * @see definir_puce()
235
 *
236
 * @param Champ $p
237
 *     Pile au niveau de la balise
238
 * @return Champ
239
 *     Pile complétée par le code à générer
240
 **/
241
function balise_PUCE_dist($p) {
242
	$p->code = "definir_puce()";
243
	$p->interdire_scripts = false;
244
245
	return $p;
246
}
247
248
249
/**
250
 * Compile la balise `#DATE` qui retourne la date de mise en ligne
251
 *
252
 * Cette balise retourne soit le champ `date` d'une table si elle est
253
 * utilisée dans une boucle, sinon la date de calcul du squelette.
254
 *
255
 * @balise
256
 * @link http://www.spip.net/4336 Balise DATE
257
 * @link http://www.spip.net/1971 La gestion des dates
258
 * @example
259
 *     ```
260
 *     <td>[(#DATE|affdate_jourcourt)]</td>
261
 *     ```
262
 *
263
 * @param Champ $p
264
 *     Pile au niveau de la balise.
265
 * @return Champ
266
 *     Pile completée du code PHP d'exécution de la balise
267
 */
268
function balise_DATE_dist($p) {
269
	$d = champ_sql('date', $p);
270
#	if ($d === "@\$Pile[0]['date']")
271
#		$d = "isset(\$Pile[0]['date']) ? $d : time()";
272
	$p->code = $d;
273
274
	return $p;
275
}
276
277
278
/**
279
 * Compile la balise `#DATE_REDAC` qui retourne la date de première publication
280
 *
281
 * Cette balise retourne le champ `date_redac` d'une table
282
 *
283
 * @balise
284
 * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC
285
 * @link http://www.spip.net/1971 La gestion des dates
286
 * @see balise_DATE_MODIF_dist()
287
 *
288
 * @param Champ $p
289
 *     Pile au niveau de la balise.
290
 * @return Champ
291
 *     Pile completée du code PHP d'exécution de la balise
292
 */
293
function balise_DATE_REDAC_dist($p) {
294
	$d = champ_sql('date_redac', $p);
295
#	if ($d === "@\$Pile[0]['date_redac']")
296
#		$d = "isset(\$Pile[0]['date_redac']) ? $d : time()";
297
	$p->code = $d;
298
	$p->interdire_scripts = false;
299
300
	return $p;
301
}
302
303
/**
304
 * Compile la balise `#DATE_MODIF` qui retourne la date de dernière modification
305
 *
306
 * Cette balise retourne le champ `date_modif` d'une table
307
 *
308
 * @balise
309
 * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC
310
 * @link http://www.spip.net/1971 La gestion des dates
311
 * @see balise_DATE_REDAC_dist()
312
 *
313
 * @param Champ $p
314
 *     Pile au niveau de la balise.
315
 * @return Champ
316
 *     Pile completée du code PHP d'exécution de la balise
317
 */
318
function balise_DATE_MODIF_dist($p) {
319
	$p->code = champ_sql('date_modif', $p);
320
	$p->interdire_scripts = false;
321
322
	return $p;
323
}
324
325
/**
326
 * Compile la balise `#DATE_NOUVEAUTES` indiquant la date de dernier envoi
327
 * du mail de nouveautés
328
 *
329
 * @balise
330
 * @link http://www.spip.net/4337 Balise DATE_NOUVEAUTES
331
 * @link http://www.spip.net/1971 La gestion des dates
332
 * @see balise_DATE_REDAC_dist()
333
 *
334
 * @param Champ $p
335
 *     Pile au niveau de la balise.
336
 * @return Champ
337
 *     Pile completée du code PHP d'exécution de la balise
338
 */
339
function balise_DATE_NOUVEAUTES_dist($p) {
340
	$p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui'
341
	AND isset(\$GLOBALS['meta']['dernier_envoi_neuf'])) ?
342
	\$GLOBALS['meta']['dernier_envoi_neuf'] :
343
	\"'0000-00-00'\")";
344
	$p->interdire_scripts = false;
345
346
	return $p;
347
}
348
349
350
/**
351
 * Compile la balise `#DOSSIER_SQUELETTE` retournant le chemin vers le
352
 * répertoire de squelettes actuellement utilisé
353
 *
354
 * @balise
355
 * @deprecated Utiliser `#CHEMIN`
356
 * @link http://www.spip.net/4627
357
 * @see balise_CHEMIN_dist()
358
 *
359
 * @param Champ $p
360
 *     Pile au niveau de la balise.
361
 * @return Champ
362
 *     Pile completée du code PHP d'exécution de la balise
363
 */
364
function balise_DOSSIER_SQUELETTE_dist($p) {
365
	$code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE));
366
	$p->code = "_DIR_RACINE . '$code'" .
367
		$p->interdire_scripts = false;
368
369
	return $p;
370
}
371
372
/**
373
 * Compile la balise `#SQUELETTE` retournant le chemin du squelette courant
374
 *
375
 * @balise
376
 * @link http://www.spip.net/4027
377
 *
378
 * @param Champ $p
379
 *     Pile au niveau de la balise.
380
 * @return Champ
381
 *     Pile completée du code PHP d'exécution de la balise
382
 */
383
function balise_SQUELETTE_dist($p) {
384
	$code = addslashes($p->descr['sourcefile']);
385
	$p->code = "'$code'" .
386
		$p->interdire_scripts = false;
387
388
	return $p;
389
}
390
391
/**
392
 * Compile la balise `#SPIP_VERSION` qui affiche la version de SPIP
393
 *
394
 * @balise
395
 * @see spip_version()
396
 * @example
397
 *     ```
398
 *     <meta name="generator" content="SPIP[ (#SPIP_VERSION)]" />
399
 *     ```
400
 *
401
 * @param Champ $p
402
 *     Pile au niveau de la balise.
403
 * @return Champ
404
 *     Pile completée du code PHP d'exécution de la balise
405
 */
406
function balise_SPIP_VERSION_dist($p) {
407
	$p->code = "spip_version()";
408
	$p->interdire_scripts = false;
409
410
	return $p;
411
}
412
413
414
/**
415
 * Compile la balise `#NOM_SITE` qui affiche le nom du site.
416
 *
417
 * Affiche le nom du site ou sinon l'URL ou le titre de l'objet
418
 * Utiliser `#NOM_SITE*` pour avoir le nom du site ou rien.
419
 *
420
 * Cette balise interroge les colonnes `nom_site` ou `url_site`
421
 * dans la boucle la plus proche.
422
 *
423
 * @balise
424
 * @see calculer_url()
425
 * @example
426
 *     ```
427
 *     <a href="#URL_SITE">#NOM_SITE</a>
428
 *     ```
429
 *
430
 * @param Champ $p
431
 *     Pile au niveau de la balise
432
 * @return Champ
433
 *     Pile complétée par le code à générer
434
 **/
435
function balise_NOM_SITE_dist($p) {
436
	if (!$p->etoile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->etoile of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
437
		$p->code = "supprimer_numero(calculer_url(" .
438
			champ_sql('url_site', $p) . "," .
439
			champ_sql('nom_site', $p) .
440
			", 'titre', \$connect, false))";
441
	} else {
442
		$p->code = champ_sql('nom_site', $p);
443
	}
444
445
	$p->interdire_scripts = true;
446
447
	return $p;
448
}
449
450
451
/**
452
 * Compile la balise `#NOTE` qui affiche les notes de bas de page
453
 *
454
 * @balise
455
 * @link http://www.spip.net/3964
456
 * @see calculer_notes()
457
 *
458
 * @param Champ $p
459
 *     Pile au niveau de la balise
460
 * @return Champ
461
 *     Pile complétée par le code à générer
462
 **/
463
function balise_NOTES_dist($p) {
464
	// Recuperer les notes
465
	$p->code = 'calculer_notes()';
466
467
	#$p->interdire_scripts = true;
468
	return $p;
469
}
470
471
472
/**
473
 * Compile la balise `#RECHERCHE` qui retourne le terme de recherche demandé
474
 *
475
 * Retourne un terme demandé en recherche, en le prenant dans _request()
476
 * sous la clé `recherche`.
477
 *
478
 * @balise
479
 * @example
480
 *     ```
481
 *     <h3>Recherche de : #RECHERCHE</h3>
482
 *     ```
483
 *
484
 * @param Champ $p
485
 *     Pile au niveau de la balise
486
 * @return Champ
487
 *     Pile complétée par le code à générer
488
 **/
489
function balise_RECHERCHE_dist($p) {
490
	$p->code = 'entites_html(_request("recherche"))';
491
	$p->interdire_scripts = false;
492
493
	return $p;
494
}
495
496
497
/**
498
 * Compile la balise `#COMPTEUR_BOUCLE` qui retourne le numéro de l’itération
499
 * actuelle de la boucle
500
 *
501
 * @balise
502
 * @link http://www.spip.net/4333
503
 * @see balise_TOTAL_BOUCLE_dist()
504
 *
505
 * @param Champ $p
506
 *     Pile au niveau de la balise
507
 * @return Champ
0 ignored issues
show
Documentation introduced by
Should the return type not be Champ|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
508
 *     Pile complétée par le code à générer
509
 **/
510
function balise_COMPTEUR_BOUCLE_dist($p) {
511
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
512
	if ($b === '') {
513
		$msg = array(
514
			'zbug_champ_hors_boucle',
515
			array('champ' => '#COMPTEUR_BOUCLE')
516
		);
517
		erreur_squelette($msg, $p);
518
	} else {
519
		$p->code = "\$Numrows['$b']['compteur_boucle']";
520
		$p->boucles[$b]->cptrows = true;
521
		$p->interdire_scripts = false;
522
523
		return $p;
524
	}
525
}
526
527
/**
528
 * Compile la balise `#TOTAL_BOUCLE` qui retourne le nombre de résultats
529
 * affichés par la boucle
530
 *
531
 * @balise
532
 * @link http://www.spip.net/4334
533
 * @see balise_COMPTEUR_BOUCLE_dist()
534
 * @see balise_GRAND_TOTAL_dist()
535
 *
536
 * @param Champ $p
537
 *     Pile au niveau de la balise
538
 * @return Champ
539
 *     Pile complétée par le code à générer
540
 **/
541 View Code Duplication
function balise_TOTAL_BOUCLE_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
542
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
543
	if ($b === '' || !isset($p->boucles[$b])) {
544
		$msg = array(
545
			'zbug_champ_hors_boucle',
546
			array('champ' => "#$b" . 'TOTAL_BOUCLE')
547
		);
548
		erreur_squelette($msg, $p);
549
	} else {
550
		$p->code = "\$Numrows['$b']['total']";
551
		$p->boucles[$b]->numrows = true;
552
		$p->interdire_scripts = false;
553
	}
554
555
	return $p;
556
}
557
558
559
/**
560
 * Compile la balise `#POINTS` qui affiche la pertinence des résultats
561
 *
562
 * Retourne le calcul `points` réalisé par le critère `recherche`.
563
 * Cette balise nécessite donc la présence de ce critère.
564
 *
565
 * @balise
566
 * @link http://www.spip.net/903 Boucles et balises de recherche
567
 * @see critere_recherche_dist()
568
 *
569
 * @param Champ $p
570
 *     Pile au niveau de la balise
571
 * @return Champ
572
 *     Pile complétée par le code à générer
573
 **/
574
function balise_POINTS_dist($p) {
575
	return rindex_pile($p, 'points', 'recherche');
576
}
577
578
579
/**
580
 * Compile la balise `#POPULARITE_ABSOLUE` qui affiche la popularité absolue
581
 *
582
 * Cela correspond à la popularité quotidienne de l'article
583
 *
584
 * @balise
585
 * @link http://www.spip.net/1846 La popularité
586
 * @see balise_POPULARITE_dist()
587
 * @see balise_POPULARITE_MAX_dist()
588
 * @see balise_POPULARITE_SITE_dist()
589
 *
590
 * @param Champ $p
591
 *     Pile au niveau de la balise
592
 * @return Champ
593
 *     Pile complétée par le code à générer
594
 **/
595
function balise_POPULARITE_ABSOLUE_dist($p) {
596
	$p->code = 'ceil(' .
597
		champ_sql('popularite', $p) .
598
		')';
599
	$p->interdire_scripts = false;
600
601
	return $p;
602
}
603
604
/**
605
 * Compile la balise `#POPULARITE_SITE` qui affiche la popularité du site
606
 *
607
 * La popularité du site est la somme de toutes les popularités absolues.
608
 *
609
 * @balise
610
 * @link http://www.spip.net/1846 La popularité
611
 * @see balise_POPULARITE_ABSOLUE_dist()
612
 * @see balise_POPULARITE_dist()
613
 * @see balise_POPULARITE_MAX_dist()
614
 *
615
 * @param Champ $p
616
 *     Pile au niveau de la balise
617
 * @return Champ
618
 *     Pile complétée par le code à générer
619
 **/
620
function balise_POPULARITE_SITE_dist($p) {
621
	$p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])';
622
	$p->interdire_scripts = false;
623
624
	return $p;
625
}
626
627
/**
628
 * Compile la balise `#POPULARITE_MAX` qui affiche la popularité maximum
629
 * parmis les popularités des articles
630
 *
631
 * Cela correspond à la popularité quotidienne de l'article
632
 *
633
 * @balise
634
 * @link http://www.spip.net/1846 La popularité
635
 * @see balise_POPULARITE_ABSOLUE_dist()
636
 * @see balise_POPULARITE_dist()
637
 * @see balise_POPULARITE_SITE_dist()
638
 *
639
 * @param Champ $p
640
 *     Pile au niveau de la balise
641
 * @return Champ
642
 *     Pile complétée par le code à générer
643
 **/
644
function balise_POPULARITE_MAX_dist($p) {
645
	$p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])';
646
	$p->interdire_scripts = false;
647
648
	return $p;
649
}
650
651
652
/**
653
 * Compile la balise `#VALEUR` retournant le champ `valeur`
654
 *
655
 * Utile dans une boucle DATA pour retourner une valeur.
656
 *
657
 * @balise
658
 * @link http://www.spip.net/5546 #CLE et #VALEUR
659
 * @see table_valeur()
660
 * @example
661
 *     ```
662
 *     #VALEUR renvoie le champ valeur
663
 *     #VALEUR{x} renvoie #VALEUR|table_valeur{x},
664
 *        équivalent à #X (si X n'est pas une balise spécifique à SPIP)
665
 *     #VALEUR{a/b} renvoie #VALEUR|table_valeur{a/b}
666
 *     ```
667
 *
668
 * @param Champ $p
669
 *     Pile au niveau de la balise
670
 * @return Champ
671
 *     Pile complétée par le code à générer
672
 **/
673
function balise_VALEUR_dist($p) {
674
	$b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
675
	$p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);;
676
	if (($v = interprete_argument_balise(1, $p)) !== null) {
677
		$p->code = 'table_valeur(' . $p->code . ', ' . $v . ')';
678
	}
679
	$p->interdire_scripts = true;
680
681
	return $p;
682
}
683
684
/**
685
 * Compile la balise `#EXPOSE` qui met en évidence l'élément sur lequel
686
 * la page se trouve
687
 *
688
 * Expose dans une boucle l'élément de la page sur laquelle on se trouve,
689
 * en retournant `on` si l'élément correspond à la page, une chaîne vide sinon.
690
 *
691
 * On peut passer les paramètres à faire retourner par la balise.
692
 *
693
 * @example
694
 *     ```
695
 *     <a href="#URL_ARTICLE"[ class="(#EXPOSE)"]>
696
 *     <a href="#URL_ARTICLE"[ class="(#EXPOSE{actif})"]>
697
 *     <a href="#URL_ARTICLE"[ class="(#EXPOSE{on,off})"]>
698
 *     ```
699
 *
700
 * @balise
701
 * @link http://www.spip.net/2319 Exposer un article
702
 * @uses calculer_balise_expose()
703
 *
704
 * @param Champ $p
705
 *     Pile au niveau de la balise
706
 * @return Champ
707
 *     Pile complétée par le code à générer
708
 **/
709
function balise_EXPOSE_dist($p) {
710
	$on = "'on'";
711
	$off = "''";
712
	if (($v = interprete_argument_balise(1, $p)) !== null) {
713
		$on = $v;
714
		if (($v = interprete_argument_balise(2, $p)) !== null) {
715
			$off = $v;
716
		}
717
718
	}
719
720
	return calculer_balise_expose($p, $on, $off);
721
}
722
723
/**
724
 * Calcul de la balise expose
725
 *
726
 * @see calcul_exposer()
727
 *
728
 * @param Champ $p
729
 *     Pile au niveau de la balise
730
 * @param string $on
731
 *     Texte à afficher si l'élément est exposé (code à écrire tel que "'on'")
732
 * @param string $off
733
 *     Texte à afficher si l'élément n'est pas exposé (code à écrire tel que "''")
734
 * @return Champ
735
 *     Pile complétée par le code à générer
736
 **/
737
function calculer_balise_expose($p, $on, $off) {
738
	$b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
739
	if (empty($p->boucles[$b]->primary)) {
740
		$msg = array('zbug_champ_hors_boucle', array('champ' => '#EXPOSER'));
741
		erreur_squelette($msg, $p);
742
	} else {
743
744
		$key = $p->boucles[$b]->primary;
745
		$type = $p->boucles[$p->id_boucle]->primary;
746
		$desc = $p->boucles[$b]->show;
747
		$connect = sql_quote($p->boucles[$b]->sql_serveur);
748
749
		// Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
750
		$c = index_pile($p->id_boucle, $type, $p->boucles);
751
752
		if (isset($desc['field']['id_parent'])) {
753
			$parent = 0; // pour if (!$parent) dans calculer_expose
754
		} elseif (isset($desc['field']['id_rubrique'])) {
755
			$parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
756
		} elseif (isset($desc['field']['id_groupe'])) {
757
			$parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
758
		} else {
759
			$parent = "''";
760
		}
761
762
		$p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";
763
	}
764
765
	$p->interdire_scripts = false;
766
767
	return $p;
768
}
769
770
771
/**
772
 * Compile la balise `#DEBUT_SURLIGNE` qui permettait le surlignage
773
 * des mots d'une recherche
774
 *
775
 * @note
776
 *     Cette balise n'a plus d'effet depuis r9343
777
 *
778
 * @balise
779
 * @see balise_FIN_SURLIGNE_dist()
780
 * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable`
781
 *
782
 * @param Champ $p
783
 *     Pile au niveau de la balise
784
 * @return Champ
785
 *     Pile complétée par le code à générer
786
 **/
787
function balise_DEBUT_SURLIGNE_dist($p) {
788
	include_spip('inc/surligne');
789
	$p->code = "'<!-- " . MARQUEUR_SURLIGNE . " -->'";
0 ignored issues
show
Deprecated Code introduced by
The constant MARQUEUR_SURLIGNE has been deprecated with message: N'a plus d'effet

This class constant has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
790
791
	return $p;
792
}
793
794
795
/**
796
 * Compile la balise `#FIN_SURLIGNE` qui arrêtait le surlignage
797
 * des mots d'une recherche
798
 *
799
 * @note
800
 *     Cette balise n'a plus d'effet depuis r9343
801
 *
802
 * @balise
803
 * @see balise_DEBUT_SURLIGNE_dist()
804
 * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable`
805
 *
806
 * @param Champ $p
807
 *     Pile au niveau de la balise
808
 * @return Champ
809
 *     Pile complétée par le code à générer
810
 **/
811
function balise_FIN_SURLIGNE_dist($p) {
812
	include_spip('inc/surligne');
813
	$p->code = "'<!-- " . MARQUEUR_FSURLIGNE . "-->'";
0 ignored issues
show
Deprecated Code introduced by
The constant MARQUEUR_FSURLIGNE has been deprecated with message: N'a plus d'effet

This class constant has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
814
815
	return $p;
816
}
817
818
819
/**
820
 * Compile la balise `#INTRODUCTION`
821
 *
822
 * Retourne une introduction d'un objet éditorial, c'est à dire les 600
823
 * premiers caractères environ du champ 'texte' de l'objet ou le contenu
824
 * indiqué entre `<intro>` et `</intro>` de ce même champ.
825
 *
826
 * Pour les articles, l'introduction utilisée est celle du champ `descriptif`
827
 * s'il est renseigné, sinon il est pris dans les champs `chapo` et `texte` et
828
 * est par défaut limité à 500 caractères.
829
 *
830
 * Pour les rubriques, l'introduction utilisée est celle du champ `descriptif`
831
 * s'il est renseigné, sinon du champ texte.
832
 *
833
 * La balise accèpte 1 paramètre indiquant la longueur en nombre de caractères
834
 * de l'introduction.
835
 *
836
 * @see filtre_introduction_dist()
837
 * @example
838
 *     ```
839
 *     #INTRODUCTION
840
 *     #INTRODUCTION{300}
841
 *     ```
842
 *
843
 * @balise
844
 * @link http://www.spip.net/@introduction
845
 *
846
 * @param Champ $p
847
 *     Pile au niveau de la balise
848
 * @return Champ
849
 *     Pile complétée par le code à générer
850
 **/
851
function balise_INTRODUCTION_dist($p) {
852
853
	$type = $p->type_requete;
854
855
	$_texte = champ_sql('texte', $p);
856
	$_descriptif = ($type == 'articles' or $type == 'rubriques') ? champ_sql('descriptif', $p) : "''";
857
858
	if ($type == 'articles') {
859
		$_chapo = champ_sql('chapo', $p);
860
		$_texte = "(strlen($_descriptif))
861
		? ''
862
		: $_chapo . \"\\n\\n\" . $_texte";
863
	}
864
865
	// longueur en parametre, ou valeur par defaut
866
	$longueur_defaut = objet_info($type, 'introduction_longueur');
867
	if (!$longueur_defaut) {
868
		$longueur_defaut = 600;
869
	}
870
871
	$_suite = 'null';
872
	$_longueur = $longueur_defaut;
873
	if (($v = interprete_argument_balise(1, $p)) !== null) {
874
		$_longueur = 'is_numeric(' . $v . ')?intval(' . $v . '):' . $longueur_defaut;
875
		$_suite = '!is_numeric(' . $v . ')?' . $v . ':null';
876
	}
877
	if (($v2 = interprete_argument_balise(2, $p)) !== null) {
878
		$_suite = $v2;
879
	}
880
881
	$f = chercher_filtre('introduction');
882
	$p->code = "$f($_descriptif, $_texte, $_longueur, \$connect, $_suite)";
883
884
	#$p->interdire_scripts = true;
885
	$p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
886
	return $p;
887
}
888
889
890
/**
891
 * Compile la balise `#LANG` qui affiche la langue de l'objet (ou d'une boucle supérieure),
892
 * et à defaut la langue courante
893
 *
894
 * La langue courante est celle du site ou celle qui a été passée dans l'URL par le visiteur.
895
 * L'étoile `#LANG*` n'affiche rien si aucune langue n'est trouvée dans le SQL ou le contexte.
896
 *
897
 * @balise
898
 * @link http://www.spip.net/3864
899
 *
900
 * @param Champ $p
901
 *     Pile au niveau de la balise
902
 * @return Champ
903
 *     Pile complétée par le code à générer
904
 **/
905
function balise_LANG_dist($p) {
906
	$_lang = champ_sql('lang', $p);
907
	if (!$p->etoile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->etoile of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
908
		$p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
909
	} else {
910
		$p->code = "spip_htmlentities($_lang)";
911
	}
912
	$p->interdire_scripts = false;
913
914
	return $p;
915
}
916
917
/**
918
 * Compile la balise `#LESAUTEURS` chargée d'afficher la liste des auteurs d'un objet
919
 *
920
 * - Soit le champ `lesauteurs` existe dans la table et à ce moment là,
921
 *   la balise retourne son contenu,
922
 * - soit la balise appelle le modele `lesauteurs.html` en lui passant
923
 *   le couple `objet` et `id_objet` dans son environnement.
924
 *
925
 * @balise
926
 * @link http://www.spip.net/3966 Description de la balise
927
 * @link http://www.spip.net/902 Description de la boucle ARTICLES
928
 * @link http://www.spip.net/911 Description de la boucle SYNDIC_ARTICLES
929
 *
930
 * @param Champ $p
931
 *     Pile au niveau de la balise
932
 * @return Champ
933
 *     Pile complétée par le code à générer
934
 */
935
function balise_LESAUTEURS_dist($p) {
936
	// Cherche le champ 'lesauteurs' dans la pile
937
	$_lesauteurs = champ_sql('lesauteurs', $p, false);
938
939
	// Si le champ n'existe pas (cas de spip_articles), on applique
940
	// le modele lesauteurs.html en passant id_article dans le contexte;
941
	// dans le cas contraire on prend le champ 'lesauteurs'
942
	// (cf extension sites/)
943
	if ($_lesauteurs
944
		and $_lesauteurs != '@$Pile[0][\'lesauteurs\']'
945
	) {
946
		$p->code = "safehtml($_lesauteurs)";
947
		// $p->interdire_scripts = true;
948
	} else {
949
		if (!$p->id_boucle) {
950
			$connect = '';
951
			$objet = 'article';
952
			$id_table_objet = 'id_article';
953
		} else {
954
			$b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
955
			$connect = $p->boucles[$b]->sql_serveur;
956
			$type_boucle = $p->boucles[$b]->type_requete;
957
			$objet = objet_type($type_boucle);
958
			$id_table_objet = id_table_objet($type_boucle);
959
		}
960
		$c = memoriser_contexte_compil($p);
961
962
		$p->code = sprintf(CODE_RECUPERER_FOND, "'modeles/lesauteurs'",
963
			"array('objet'=>'" . $objet .
964
			"','id_objet' => " . champ_sql($id_table_objet, $p) .
965
			",'$id_table_objet' => " . champ_sql($id_table_objet, $p) .
966
			($objet == 'article' ? "" : ",'id_article' => " . champ_sql('id_article', $p)) .
967
			")",
968
			"'trim'=>true, 'compil'=>array($c)",
969
			_q($connect));
970
		$p->interdire_scripts = false; // securite apposee par recuperer_fond()
971
	}
972
973
	return $p;
974
}
975
976
977
/**
978
 * Compile la balise `#RANG` chargée d'afficher le numéro de l'objet
979
 *
980
 * Affiche le « numero de l'objet ». Soit `1` quand on a un titre `1. Premier article`.
981
 *
982
 * Ceci est transitoire afin de préparer une migration vers un vrai système de
983
 * tri des articles dans une rubrique (et plus si affinités).
984
 * La balise permet d'extraire le numero masqué par le filtre `supprimer_numero`.
985
 *
986
 * La balise recupère le champ declaré dans la définition `table_titre`
987
 * de l'objet, ou à defaut du champ `titre`
988
 *
989
 * Si un champ `rang` existe, il est pris en priorité.
990
 *
991
 * @balise
992
 * @link http://www.spip.net/5495
993
 *
994
 * @param Champ $p
995
 *     Pile au niveau de la balise
996
 * @return Champ
997
 *     Pile complétée par le code à générer
998
 */
999
function balise_RANG_dist($p) {
1000
	$b = index_boucle($p);
1001
	if ($b === '') {
1002
		$msg = array(
1003
			'zbug_champ_hors_boucle',
1004
			array('champ' => '#RANG')
1005
		);
1006
		erreur_squelette($msg, $p);
1007
	} else {
1008
		// chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql)
1009
		// dans la boucle immediatement englobante uniquement
1010
		// sinon on compose le champ calcule
1011
		$_rang = champ_sql('rang', $p, '', false);
1012
1013
		// si pas trouve de champ sql rang :
1014
		if (!$_rang or $_rang == "''") {
1015
			$boucle = &$p->boucles[$b];
1016
			$trouver_table = charger_fonction('trouver_table', 'base');
1017
			$desc = $trouver_table($boucle->id_table);
1018
			$_titre = ''; # où extraire le numero ?
1019
			
1020
			if (isset($desc['titre'])) {
1021
				$t = $desc['titre'];
1022
				if (
1023
					// Soit on trouve avec la déclaration de la lang AVANT
1024
					preg_match(';(?:lang\s*,)\s*(.*?titre)\s*(,|$);', $t, $m)
1025
					// Soit on prend depuis le début
1026
					or preg_match(';^(.*?titre)\s*(,|$);', $t, $m)
1027
				) {
1028
					$m = preg_replace(',as\s+titre$,i', '', $m[1]);
1029
					$m = trim($m);
1030
					if ($m != "''") {
1031
						if (!preg_match(",\W,", $m)) {
1032
							$m = $boucle->id_table . ".$m";
1033
						}
1034
						
1035
						$m .= " AS titre_rang";
1036
1037
						$boucle->select[] = $m;
1038
						$_titre = '$Pile[$SP][\'titre_rang\']';
1039
					}
1040
				}
1041
			}
1042
			
1043
			// si on n'a rien trouvé, on utilise le champ titre classique
1044
			if (!$_titre) {
1045
				$_titre = champ_sql('titre', $p);
1046
			}
1047
			
1048
			$_rang = "recuperer_numero($_titre)";
1049
		}
1050
		
1051
		$p->code = $_rang;
1052
		$p->interdire_scripts = false;
1053
	}
1054
	
1055
	return $p;
1056
}
1057
1058
1059
/**
1060
 * Compile la balise `#POPULARITE` qui affiche la popularité relative.
1061
 *
1062
 * C'est à dire le pourcentage de la fréquentation de l'article
1063
 * (la popularité absolue) par rapport à la popularité maximum.
1064
 *
1065
 * @balise
1066
 * @link http://www.spip.net/1846 La popularité
1067
 * @see balise_POPULARITE_ABSOLUE_dist()
1068
 * @see balise_POPULARITE_MAX_dist()
1069
 * @see balise_POPULARITE_SITE_dist()
1070
 *
1071
 * @param Champ $p
1072
 *     Pile au niveau de la balise
1073
 * @return Champ
1074
 *     Pile complétée par le code à générer
1075
 **/
1076
function balise_POPULARITE_dist($p) {
1077
	$_popularite = champ_sql('popularite', $p);
1078
	$p->code = "(ceil(min(100, 100 * $_popularite
1079
	/ max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))";
1080
	$p->interdire_scripts = false;
1081
1082
	return $p;
1083
}
1084
1085
/**
1086
 * Code de compilation pour la balise `#PAGINATION`
1087
 *
1088
 * Le code produit est trompeur, car les modèles ne fournissent pas Pile[0].
1089
 * On produit un appel à `_request` si on ne l'a pas, mais c'est inexact:
1090
 * l'absence peut-être due à une faute de frappe dans le contexte inclus.
1091
 */
1092
define('CODE_PAGINATION',
1093
'%s($Numrows["%s"]["grand_total"],
1094
 		%s,
1095
		isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)),
1096
		%5$s, %6$s, %7$s, %8$s, array(%9$s))');
1097
1098
/**
1099
 * Compile la balise `#PAGINATION` chargée d'afficher une pagination
1100
 *
1101
 * Elle charge le modèle `pagination.html` (par défaut), mais un paramètre
1102
 * permet d'indiquer d'autres modèles. `#PAGINATION{nom}` utilisera le
1103
 * modèle `pagination_nom.html`.
1104
 *
1105
 * Cette balise nécessite le critère `pagination` sur la boucle où elle
1106
 * est utilisée.
1107
 *
1108
 * @balise
1109
 * @link http://www.spip.net/3367 Le système de pagination
1110
 * @see filtre_pagination_dist()
1111
 * @see critere_pagination_dist()
1112
 * @see balise_ANCRE_PAGINATION_dist()
1113
 * @example
1114
 *    ```
1115
 *    [<p class="pagination">(#PAGINATION{prive})</p>]
1116
 *    ```
1117
 *
1118
 * @param Champ $p
1119
 *     Pile au niveau de la balise
1120
 * @param string $liste
1121
 *     Afficher ou non les liens de pagination (variable de type `string`
1122
 *     car code à faire écrire au compilateur) :
1123
 *     - `true` pour les afficher
1124
 *     - `false` pour afficher uniquement l'ancre.
1125
 * @return Champ
1126
 *     Pile complétée par le code à générer
1127
 */
1128
function balise_PAGINATION_dist($p, $liste = 'true') {
1129
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
1130
1131
	// s'il n'y a pas de nom de boucle, on ne peut pas paginer
1132
	if ($b === '') {
1133
		$msg = array(
1134
			'zbug_champ_hors_boucle',
1135
			array('champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION')
1136
		);
1137
		erreur_squelette($msg, $p);
1138
1139
		return $p;
1140
	}
1141
1142
	// s'il n'y a pas de mode_partie, c'est qu'on se trouve
1143
	// dans un boucle recursive ou qu'on a oublie le critere {pagination}
1144
	if (!$p->boucles[$b]->mode_partie) {
1145
		if (!$p->boucles[$b]->table_optionnelle) {
1146
			$msg = array(
1147
				'zbug_pagination_sans_critere',
1148
				array('champ' => '#PAGINATION')
1149
			);
1150
			erreur_squelette($msg, $p);
1151
		}
1152
1153
		return $p;
1154
	}
1155
1156
	// a priori true
1157
	// si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
1158
	// si true, les arguments simples (sans truc=chose) vont degager
1159
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
1160
	if (count($_contexte)) {
1161
		list($key, $val) = each($_contexte);
0 ignored issues
show
Unused Code introduced by
The assignment to $val is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1162
		if (is_numeric($key)) {
1163
			array_shift($_contexte);
1164
			$__modele = interprete_argument_balise(1, $p);
1165
		}
1166
	}
1167
1168
	if (count($_contexte)) {
1169
		$code_contexte = implode(',', $_contexte);
1170
	} else {
1171
		$code_contexte = '';
1172
	}
1173
1174
	$connect = $p->boucles[$b]->sql_serveur;
1175
	$pas = $p->boucles[$b]->total_parties;
1176
	$f_pagination = chercher_filtre('pagination');
1177
	$type = $p->boucles[$b]->modificateur['debut_nom'];
1178
	$modif = ($type[0] !== "'") ? "'debut'.$type"
1179
		: ("'debut" . substr($type, 1));
1180
1181
	$p->code = sprintf(CODE_PAGINATION, $f_pagination, $b, $type, $modif, $pas, $liste,
1182
		((isset($__modele) and $__modele) ? $__modele : "''"), _q($connect), $code_contexte);
1183
1184
	$p->boucles[$b]->numrows = true;
1185
	$p->interdire_scripts = false;
1186
1187
	return $p;
1188
}
1189
1190
1191
/**
1192
 * Compile la balise `#ANCRE_PAGINATION` chargée d'afficher l'ancre
1193
 * de la pagination
1194
 *
1195
 * Cette ancre peut ainsi être placée au-dessus la liste des éléments
1196
 * de la boucle alors qu'on mettra les liens de pagination en-dessous de
1197
 * cette liste paginée.
1198
 *
1199
 * Cette balise nécessite le critère `pagination` sur la boucle où elle
1200
 * est utilisée.
1201
 *
1202
 * @balise
1203
 * @link http://www.spip.net/3367 Le système de pagination
1204
 * @link http://www.spip.net/4328 Balise ANCRE_PAGINATION
1205
 * @see critere_pagination_dist()
1206
 * @see balise_PAGINATION_dist()
1207
 *
1208
 * @param Champ $p
1209
 *     Pile au niveau de la balise
1210
 * @return Champ
1211
 *     Pile complétée par le code à générer
1212
 **/
1213
function balise_ANCRE_PAGINATION_dist($p) {
1214
	if ($f = charger_fonction('PAGINATION', 'balise', true)) {
1215
		return $f($p, $liste = 'false');
1216
	} else {
1217
		return null;
1218
	} // ou une erreur ?
1219
}
1220
1221
1222
/**
1223
 * Compile la balise `#GRAND_TOTAL` qui retourne le nombre total de résultats
1224
 * d'une boucle
1225
 *
1226
 * Cette balise set équivalente à `#TOTAL_BOUCLE` sauf pour les boucles paginées.
1227
 * Dans ce cas elle indique le nombre total d'éléments répondant aux critères
1228
 * hors pagination.
1229
 *
1230
 * @balise
1231
 * @see balise_GRAND_TOTAL_dist()
1232
 *
1233
 * @param Champ $p
1234
 *     Pile au niveau de la balise
1235
 * @return Champ
1236
 *     Pile complétée par le code à générer
1237
 **/
1238 View Code Duplication
function balise_GRAND_TOTAL_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1239
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
1240
	if ($b === '' || !isset($p->boucles[$b])) {
1241
		$msg = array(
1242
			'zbug_champ_hors_boucle',
1243
			array('champ' => "#$b" . 'TOTAL_BOUCLE')
1244
		);
1245
		erreur_squelette($msg, $p);
1246
	} else {
1247
		$p->code = "(isset(\$Numrows['$b']['grand_total'])
1248
			? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])";
1249
		$p->boucles[$b]->numrows = true;
1250
		$p->interdire_scripts = false;
1251
	}
1252
1253
	return $p;
1254
}
1255
1256
1257
/**
1258
 * Compile la balise `#SELF` qui retourne l’URL de la page appelée.
1259
 *
1260
 * Cette URL est nettoyée des variables propres à l’exécution de SPIP
1261
 * tel que `var_mode`.
1262
 *
1263
 * @note
1264
 *     Attention dans un `INCLURE()` ou une balise dynamique, on n'a pas le droit de
1265
 *     mettre en cache `#SELF` car il peut correspondre à une autre page (attaque XSS)
1266
 *     (Dans ce cas faire <INCLURE{self=#SELF}> pour différencier les caches.)
1267
 *
1268
 * @balise
1269
 * @link http://www.spip.net/4574
1270
 * @example
1271
 *     ```
1272
 *     <a href="[(#SELF|parametre_url{id_mot,#ID_MOT})]">...
1273
 *     ```
1274
 *
1275
 * @param Champ $p
1276
 *     Pile au niveau de la balise
1277
 * @return Champ
1278
 *     Pile complétée par le code à générer
1279
 **/
1280
function balise_SELF_dist($p) {
1281
	$p->code = 'self()';
1282
	$p->interdire_scripts = false;
1283
1284
	return $p;
1285
}
1286
1287
1288
/**
1289
 * Compile la balise `#CHEMIN` qui cherche un fichier dans les chemins
1290
 * connus de SPIP et retourne son chemin complet depuis la racine
1291
 *
1292
 * Signature : `#CHEMIN{chemin/vers/fichier.ext}`
1293
 *
1294
 * Retourne une chaîne vide si le fichier n'est pas trouvé.
1295
 *
1296
 * @balise
1297
 * @link http://www.spip.net/4332
1298
 * @see find_in_path() Recherche de chemin
1299
 * @example
1300
 *     ```
1301
 *     [<script type="text/javascript" src="(#CHEMIN{javascript/jquery.flot.js})"></script>]
1302
 *     [<link rel="stylesheet" href="(#CHEMIN{css/perso.css}|direction_css)" type="text/css" />]
1303
 *     ```
1304
 *
1305
 * @param Champ $p
1306
 *     Pile au niveau de la balise
1307
 * @return Champ
1308
 *     Pile complétée par le code à générer
1309
 **/
1310 View Code Duplication
function balise_CHEMIN_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1311
	$arg = interprete_argument_balise(1, $p);
1312
	if (!$arg) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $arg of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1313
		$msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN'));
1314
		erreur_squelette($msg, $p);
1315
	} else {
1316
		$p->code = 'find_in_path(' . $arg . ')';
1317
	}
1318
1319
	$p->interdire_scripts = false;
1320
1321
	return $p;
1322
}
1323
1324
/**
1325
 * Compile la balise `#CHEMIN_IMAGE` qui cherche une image dans le thème
1326
 * de l'espace privé utilisé par SPIP et retourne son chemin complet depuis
1327
 * la racine
1328
 *
1329
 * Signature : `#CHEMIN_IMAGE{image.png}`
1330
 *
1331
 * Retourne une chaîne vide si le fichier n'est pas trouvé.
1332
 *
1333
 * @balise
1334
 * @see chemin_image()
1335
 * @example
1336
 *     ```
1337
 *     #CHEMIN_IMAGE{article-24.png}
1338
 *     ```
1339
 *
1340
 * @param Champ $p
1341
 *     Pile au niveau de la balise
1342
 * @return Champ
1343
 *     Pile complétée par le code à générer
1344
 **/
1345 View Code Duplication
function balise_CHEMIN_IMAGE_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1346
	$arg = interprete_argument_balise(1, $p);
1347
	if (!$arg) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $arg of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1348
		$msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN_IMAGE'));
1349
		erreur_squelette($msg, $p);
1350
	} else {
1351
		$p->code = 'chemin_image(' . $arg . ')';
1352
	}
1353
1354
	#$p->interdire_scripts = true;
1355
	return $p;
1356
}
1357
1358
1359
/**
1360
 * Compile la balise `#ENV` qui permet de récupérer le contexte d'environnement
1361
 * transmis à un squelette.
1362
 *
1363
 * La syntaxe `#ENV{toto, valeur par defaut}`
1364
 * renverra `valeur par defaut` si `$toto` est vide.
1365
 *
1366
 * La recherche de la clé s'appuyant sur la fonction `table_valeur`
1367
 * il est possible de demander un sous élément d'un tableau :
1368
 * `#ENV{toto/sous/element, valeur par defaut}` retournera l'équivalent de
1369
 * `#ENV{toto}|table_valeur{sous/element}` c'est-à-dire en quelque sorte
1370
 * `$env['toto']['sous']['element']` s'il existe, sinon la valeur par défaut.
1371
 *
1372
 * Si le tableau est vide on renvoie `''` (utile pour `#SESSION`)
1373
 *
1374
 * Enfin, la balise utilisée seule `#ENV` retourne le tableau complet
1375
 * de l'environnement. À noter que ce tableau est retourné sérialisé.
1376
 *
1377
 * En standard est appliqué le filtre `entites_html`, mais si l'étoile est
1378
 * utilisée pour désactiver les filtres par défaut, par exemple avec
1379
 * `[(#ENV*{toto})]` , il *faut* s'assurer de la sécurité
1380
 * anti-javascript, par exemple en filtrant avec `safehtml` : `[(#ENV*{toto}|safehtml)]`
1381
 *
1382
 *
1383
 * @param Champ $p
1384
 *     Pile ; arbre de syntaxe abstrait positionné au niveau de la balise.
1385
 * @param array $src
0 ignored issues
show
Documentation introduced by
Should the type for parameter $src not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1386
 *     Tableau dans lequel chercher la clé demandée en paramètre de la balise.
1387
 *     Par defaut prend dans le contexte du squelette.
1388
 * @return Champ
1389
 *     Pile completée du code PHP d'exécution de la balise
1390
 **/
1391
function balise_ENV_dist($p, $src = null) {
1392
1393
	// cle du tableau desiree
1394
	$_nom = interprete_argument_balise(1, $p);
1395
	// valeur par defaut
1396
	$_sinon = interprete_argument_balise(2, $p);
1397
1398
	// $src est un tableau de donnees sources eventuellement transmis
1399
	// en absence, on utilise l'environnement du squelette $Pile[0]
1400
1401
	if (!$_nom) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_nom of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1402
		// cas de #ENV sans argument : on retourne le serialize() du tableau
1403
		// une belle fonction [(#ENV|affiche_env)] serait pratique
1404
		if ($src) {
1405
			$p->code = '(is_array($a = (' . $src . ')) ? serialize($a) : "")';
1406
		} else {
1407
			$p->code = '@serialize($Pile[0])';
1408
		}
1409
	} else {
1410
		if (!$src) {
1411
			$src = '@$Pile[0]';
1412
		}
1413
		if ($_sinon) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_sinon of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1414
			$p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)";
1415
		} else {
1416
			$p->code = "table_valeur($src, (string)$_nom, null)";
1417
		}
1418
	}
1419
1420
	#$p->interdire_scripts = true;
1421
1422
	return $p;
1423
}
1424
1425
/**
1426
 * Compile la balise `#CONFIG` qui retourne une valeur de configuration
1427
 *
1428
 * Cette balise appelle la fonction `lire_config()` pour obtenir les
1429
 * configurations du site.
1430
 *
1431
 * Par exemple `#CONFIG{gerer_trad}` donne 'oui ou 'non' selon le réglage.
1432
 *
1433
 * Le 3ème argument permet de contrôler la sérialisation du résultat
1434
 * (mais ne sert que pour le dépot `meta`) qui doit parfois désérialiser,
1435
 * par exemple avec `|in_array{#CONFIG{toto,#ARRAY,1}}`. Ceci n'affecte
1436
 * pas d'autres dépots et `|in_array{#CONFIG{toto/,#ARRAY}}` sera
1437
 * équivalent.
1438
 *
1439
 * Òn peut appeler d'autres tables que `spip_meta` avec un
1440
 * `#CONFIG{/infos/champ,defaut}` qui lit la valeur de `champ`
1441
 * dans une table des meta qui serait `spip_infos`
1442
 *
1443
 * @balise
1444
 * @link http://www.spip.net/4335
1445
 *
1446
 * @param Champ $p
1447
 *     Pile au niveau de la balise.
1448
 * @return Champ
1449
 *     Pile completée du code PHP d'exécution de la balise
1450
 */
1451
function balise_CONFIG_dist($p) {
1452
	if (!$arg = interprete_argument_balise(1, $p)) {
1453
		$arg = "''";
1454
	}
1455
	$_sinon = interprete_argument_balise(2, $p);
1456
	$_unserialize = sinon(interprete_argument_balise(3, $p), "false");
1457
1458
	$p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' .
1459
		($_sinon && $_sinon != "''" ? $_sinon : 'null') . ',' . $_unserialize . "):'')";
0 ignored issues
show
Bug Best Practice introduced by
The expression $_sinon of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1460
1461
	return $p;
1462
}
1463
1464
1465
/**
1466
 * Compile la balise `#CONNECT` qui retourne le nom du connecteur
1467
 * de base de données
1468
 *
1469
 * Retourne le nom du connecteur de base de données utilisé (le nom
1470
 * du fichier `config/xx.php` sans l'extension, utilisé pour calculer
1471
 * les données du squelette).
1472
 *
1473
 * Retourne `NULL` si le connecteur utilisé est celui par défaut de SPIP
1474
 * (connect.php), sinon retourne son nom.
1475
 *
1476
 * @balise
1477
 *
1478
 * @param Champ $p
1479
 *     Pile au niveau de la balise.
1480
 * @return Champ
1481
 *     Pile completée du code PHP d'exécution de la balise
1482
 */
1483
function balise_CONNECT_dist($p) {
1484
	$p->code = '($connect ? $connect : NULL)';
1485
	$p->interdire_scripts = false;
1486
1487
	return $p;
1488
}
1489
1490
1491
/**
1492
 * Compile la balise `#SESSION` qui permet d’accéder aux informations
1493
 * liées au visiteur authentifié et de différencier automatiquement
1494
 * le cache en fonction du visiteur.
1495
 *
1496
 * Cette balise est un tableau des données du visiteur (nom, email etc).
1497
 * Si elle est invoquée, elle lève un drapeau dans le fichier cache, qui
1498
 * permet à public/cacher de créer un cache différent par visiteur
1499
 *
1500
 * @balise
1501
 * @link http://www.spip.net/3979
1502
 * @see balise_AUTORISER_dist()
1503
 * @see balise_SESSION_SET_dist()
1504
 * @example
1505
 *     ```
1506
 *     #SESSION{nom}
1507
 *     ```
1508
 *
1509
 * @param Champ $p
1510
 *     Pile au niveau de la balise.
1511
 * @return Champ
1512
 *     Pile completée du code PHP d'exécution de la balise
1513
 **/
1514
function balise_SESSION_dist($p) {
1515
	$p->descr['session'] = true;
1516
1517
	$f = function_exists('balise_ENV')
1518
		? 'balise_ENV'
1519
		: 'balise_ENV_dist';
1520
1521
	$p = $f($p, '$GLOBALS["visiteur_session"]');
1522
1523
	return $p;
1524
}
1525
1526
1527
/**
1528
 * Compile la balise `#SESSION_SET` qui d’insérer dans la session
1529
 * des données supplémentaires
1530
 *
1531
 * @balise
1532
 * @link http://www.spip.net/3984
1533
 * @see balise_AUTORISER_dist()
1534
 * @see balise_SESSION_SET_dist()
1535
 * @example
1536
 *     ```
1537
 *     #SESSION_SET{x,y} ajoute x=y dans la session du visiteur
1538
 *     ```
1539
 *
1540
 * @param Champ $p
1541
 *     Pile au niveau de la balise.
1542
 * @return Champ
1543
 *     Pile completée du code PHP d'exécution de la balise
1544
 **/
1545
function balise_SESSION_SET_dist($p) {
1546
	$_nom = interprete_argument_balise(1, $p);
1547
	$_val = interprete_argument_balise(2, $p);
1548
	if (!$_nom or !$_val) {
1549
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SESSION_SET'));
1550
		erreur_squelette($err_b_s_a, $p);
1551
	} else {
1552
		$p->code = '(include_spip("inc/session") AND session_set(' . $_nom . ',' . $_val . '))';
1553
	}
1554
1555
	$p->interdire_scripts = false;
1556
1557
	return $p;
1558
}
1559
1560
1561
/**
1562
 * Compile la balise `#EVAL` qui évalue un code PHP
1563
 *
1564
 * À utiliser avec précautions !
1565
 *
1566
 * @balise
1567
 * @link http://www.spip.net/4587
1568
 * @example
1569
 *     ```
1570
 *     #EVAL{6+9}
1571
 *     #EVAL{_DIR_IMG_PACK}
1572
 *     #EVAL{'date("Y-m-d")'}
1573
 *     #EVAL{$_SERVER['REQUEST_URI']}
1574
 *     #EVAL{'str_replace("r","z", "roger")'}  (attention les "'" sont interdits)
1575
 *     ```
1576
 *
1577
 * @note
1578
 *     `#EVAL{code}` produit `eval('return code;')`
1579
 *      mais si le code est une expression sans balise, on se dispense
1580
 *      de passer par une construction si compliquée, et le code est
1581
 *      passé tel quel (entre parenthèses, et protégé par interdire_scripts)
1582
 *
1583
 * @param Champ $p
1584
 *     Pile au niveau de la balise.
1585
 * @return Champ
1586
 *     Pile completée du code PHP d'exécution de la balise
1587
 **/
1588
function balise_EVAL_dist($p) {
1589
	$php = interprete_argument_balise(1, $p);
1590
	if ($php) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $php of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1591
		# optimisation sur les #EVAL{une expression sans #BALISE}
1592
		# attention au commentaire "// x signes" qui precede
1593 View Code Duplication
		if (preg_match(",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms",
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1594
			$php, $r)) {
1595
			$p->code = /* $r[1]. */
1596
				'(' . $r[2] . ')';
1597
		} else {
1598
			$p->code = "eval('return '.$php.';')";
1599
		}
1600
	} else {
1601
		$msg = array('zbug_balise_sans_argument', array('balise' => ' EVAL'));
1602
		erreur_squelette($msg, $p);
1603
	}
1604
1605
	#$p->interdire_scripts = true;
1606
1607
	return $p;
1608
}
1609
1610
1611
/**
1612
 * Compile la balise `#CHAMP_SQL` qui renvoie la valeur d'un champ SQL
1613
 *
1614
 * Signature : `#CHAMP_SQL{champ}`
1615
 *
1616
 * Cette balise permet de récupérer par exemple un champ `notes` dans une table
1617
 * SQL externe (impossible avec la balise `#NOTES` qui est une balise calculée).
1618
 *
1619
 * Ne permet pas de passer une expression comme argument, qui ne peut
1620
 * être qu'un texte statique !
1621
 *
1622
 * @balise
1623
 * @link http://www.spip.net/4041
1624
 * @see champ_sql()
1625
 * @example
1626
 *     ```
1627
 *     #CHAMP_SQL{notes}
1628
 *     ```
1629
 *
1630
 * @param Champ $p
1631
 *     Pile au niveau de la balise
1632
 * @return Champ
1633
 *     Pile complétée par le code à générer
1634
 **/
1635
function balise_CHAMP_SQL_dist($p) {
1636
1637
	if ($p->param
1638
		and isset($p->param[0][1][0])
1639
		and $champ = ($p->param[0][1][0]->texte)
1640
	) {
1641
		$p->code = champ_sql($champ, $p);
1642
	} else {
1643
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => ' CHAMP_SQL'));
1644
		erreur_squelette($err_b_s_a, $p);
1645
	}
1646
1647
	#$p->interdire_scripts = true;
1648
	return $p;
1649
}
1650
1651
/**
1652
 * Compile la balise `#VAL` qui retourne simplement le premier argument
1653
 * qui lui est transmis
1654
 *
1655
 * Cela permet d'appliquer un filtre à une chaîne de caractère
1656
 *
1657
 * @balise
1658
 * @link http://www.spip.net/4026
1659
 * @example
1660
 *     ```
1661
 *     #VAL retourne ''
1662
 *     #VAL{x} retourne 'x'
1663
 *     #VAL{1,2} renvoie '1' (2 est considéré comme un autre paramètre)
1664
 *     #VAL{'1,2'} renvoie '1,2'
1665
 *     [(#VAL{a_suivre}|bouton_spip_rss)]
1666
 *     ```
1667
 *
1668
 * @param Champ $p
1669
 *     Pile au niveau de la balise
1670
 * @return Champ
1671
 *     Pile complétée par le code à générer
1672
 **/
1673
function balise_VAL_dist($p) {
1674
	$p->code = interprete_argument_balise(1, $p);
1675
	if (!strlen($p->code)) {
1676
		$p->code = "''";
1677
	}
1678
	$p->interdire_scripts = false;
1679
1680
	return $p;
1681
}
1682
1683
/**
1684
 * Compile la balise `#NOOP`, alias (déprécié) de `#VAL`
1685
 *
1686
 * Alias pour regler #948. Ne plus utiliser.
1687
 *
1688
 * @balise
1689
 * @see balise_VAL_dist()
1690
 * @deprecated Utiliser #VAL
1691
 *
1692
 * @param Champ $p
1693
 *     Pile au niveau de la balise
1694
 * @return Champ
1695
 *     Pile complétée par le code à générer
1696
 **/
1697
function balise_NOOP_dist($p) { return balise_VAL_dist($p); }
1698
1699
1700
/**
1701
 * Compile la balise `#REM` servant à commenter du texte
1702
 *
1703
 * Retourne toujours une chaîne vide.
1704
 *
1705
 * @balise
1706
 * @link http://www.spip.net/4578
1707
 * @example
1708
 *     ```
1709
 *     [(#REM)
1710
 *       Ceci est une remarque ou un commentaire,
1711
 *       non affiché dans le code généré
1712
 *     ]
1713
 *     ```
1714
 *
1715
 * @note
1716
 *     La balise `#REM` n'empêche pas l'exécution des balises SPIP contenues
1717
 *     dedans (elle ne sert pas à commenter du code pour empêcher son
1718
 *     exécution).
1719
 *
1720
 * @param Champ $p
1721
 *     Pile au niveau de la balise
1722
 * @return Champ
1723
 *     Pile complétée par le code à générer
1724
 **/
1725
function balise_REM_dist($p) {
1726
	$p->code = "''";
1727
	$p->interdire_scripts = false;
1728
1729
	return $p;
1730
}
1731
1732
1733
/**
1734
 * Compile la balise `#HTTP_HEADER` envoyant des entêtes de retour HTTP
1735
 *
1736
 * Doit être placée en tête de fichier et ne fonctionne pas dans une
1737
 * inclusion.
1738
 *
1739
 * @balise
1740
 * @link http://www.spip.net/4631
1741
 * @example
1742
 *     ```
1743
 *     #HTTP_HEADER{Content-Type: text/csv; charset=#CHARSET}
1744
 *     ```
1745
 *
1746
 * @param Champ $p
1747
 *     Pile au niveau de la balise
1748
 * @return Champ
1749
 *     Pile complétée par le code à générer
1750
 **/
1751 View Code Duplication
function balise_HTTP_HEADER_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1752
1753
	$header = interprete_argument_balise(1, $p);
1754
	if (!$header) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $header of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1755
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'HTTP_HEADER'));
1756
		erreur_squelette($err_b_s_a, $p);
1757
	} else {
1758
		$p->code = "'<'.'?php header(' . _q("
1759
			. $header
1760
			. ") . '); ?'.'>'";
1761
	}
1762
	$p->interdire_scripts = false;
1763
1764
	return $p;
1765
}
1766
1767
1768
/**
1769
 * Compile la balise `#FILTRE` qui exécute un filtre à l'ensemble du squelette
1770
 * une fois calculé.
1771
 *
1772
 * Le filtrage se fait au niveau du squelette, sans s'appliquer aux `<INCLURE>`.
1773
 * Plusieurs filtres peuvent être indiqués, séparés par des barres verticales `|`
1774
 *
1775
 * @balise
1776
 * @link http://www.spip.net/4894
1777
 * @example
1778
 *     ```
1779
 *     #FILTRE{compacte_head}
1780
 *     #FILTRE{supprimer_tags|filtrer_entites|trim}
1781
 *     ```
1782
 *
1783
 * @param Champ $p
1784
 *     Pile au niveau de la balise
1785
 * @return Champ
0 ignored issues
show
Documentation introduced by
Should the return type not be Champ|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1786
 *     Pile complétée par le code à générer
1787
 **/
1788
function balise_FILTRE_dist($p) {
1789
	if ($p->param) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->param of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1790
		$args = array();
1791
		foreach ($p->param as $i => $ignore) {
1792
			$args[] = interprete_argument_balise($i + 1, $p);
1793
		}
1794
		$p->code = "'<' . '"
1795
			. '?php header("X-Spip-Filtre: \'.'
1796
			. join('.\'|\'.', $args)
1797
			. " . '\"); ?'.'>'";
1798
1799
		$p->interdire_scripts = false;
1800
1801
		return $p;
1802
	}
1803
}
1804
1805
1806
/**
1807
 * Compile la balise `#CACHE` definissant la durée de validité du cache du squelette
1808
 *
1809
 * Signature : `#CACHE{duree[,type]}`
1810
 *
1811
 * Le premier argument est la durée en seconde du cache. Le second
1812
 * (par défaut `statique`) indique le type de cache :
1813
 *
1814
 * - `cache-client` autorise gestion du IF_MODIFIED_SINCE
1815
 * - `statique` ne respecte pas l'invalidation par modif de la base
1816
 *   (mais s'invalide tout de même à l'expiration du delai)
1817
 *
1818
 * @balise
1819
 * @see ecrire/public/cacher.php
1820
 * @link http://www.spip.net/4330
1821
 * @example
1822
 *     ```
1823
 *     #CACHE{24*3600}
1824
 *     #CACHE{24*3600, cache-client}
1825
 *     #CACHE{0} pas de cache
1826
 *     ```
1827
 * @note
1828
 *   En absence de cette balise la durée est du cache est donné
1829
 *   par la constante `_DUREE_CACHE_DEFAUT`
1830
 *
1831
 * @param Champ $p
1832
 *     Pile au niveau de la balise
1833
 * @return Champ
1834
 *     Pile complétée par le code à générer
1835
 **/
1836
function balise_CACHE_dist($p) {
1837
1838
	if ($p->param) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->param of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1839
		$duree = valeur_numerique($p->param[0][1][0]->texte);
1840
1841
		// noter la duree du cache dans un entete proprietaire
1842
1843
		$code = "'<'.'" . '?php header("X-Spip-Cache: '
1844
			. $duree
1845
			. '"); ?' . "'.'>'";
1846
1847
		// Remplir le header Cache-Control
1848
		// cas #CACHE{0}
1849
		if ($duree == 0) {
1850
			$code .= ".'<'.'"
1851
				. '?php header("Cache-Control: no-cache, must-revalidate"); ?'
1852
				. "'.'><'.'"
1853
				. '?php header("Pragma: no-cache"); ?'
1854
				. "'.'>'";
1855
		}
1856
1857
		// recuperer les parametres suivants
1858
		$i = 1;
1859
		while (isset($p->param[0][++$i])) {
1860
			$pa = ($p->param[0][$i][0]->texte);
1861
1862
			if ($pa == 'cache-client'
1863
				and $duree > 0
1864
			) {
1865
				$code .= ".'<'.'" . '?php header("Cache-Control: max-age='
1866
					. $duree
1867
					. '"); ?' . "'.'>'";
1868
				// il semble logique, si on cache-client, de ne pas invalider
1869
				$pa = 'statique';
1870
			}
1871
1872
			if ($pa == 'statique'
1873
				and $duree > 0
1874
			) {
1875
				$code .= ".'<'.'" . '?php header("X-Spip-Statique: oui"); ?' . "'.'>'";
1876
			}
1877
		}
1878
	} else {
1879
		$code = "''";
1880
	}
1881
	$p->code = $code;
1882
	$p->interdire_scripts = false;
1883
1884
	return $p;
1885
}
1886
1887
1888
/**
1889
 * Compile la balise `#INSERT_HEAD` permettant d'insérer du contenu dans
1890
 * le `<head>` d'une page HTML
1891
 *
1892
 * La balise permet aux plugins d'insérer des styles, js ou autre
1893
 * dans l'entête sans modification du squelette.
1894
 * Les css doivent être inserées de préférence par `#INSERT_HEAD_CSS`
1895
 * pour en faciliter la surcharge.
1896
 *
1897
 * On insère ici aussi un morceau de PHP qui verifiera à l'exécution
1898
 * que le pipeline `insert_head_css` a bien été vu
1899
 * et dans le cas contraire l'appelera. Ceal permet de ne pas oublier
1900
 * les css de `#INSERT_HEAD_CSS` même si cette balise n'est pas presente.
1901
 *
1902
 * Il faut mettre ce php avant le `insert_head` car le compresseur y mets
1903
 * ensuite un php du meme type pour collecter
1904
 * CSS et JS, et on ne veut pas qu'il rate les css insérées en fallback
1905
 * par `insert_head_css_conditionnel`.
1906
 *
1907
 * @link http://www.spip.net/4629
1908
 * @see balise_INSERT_HEAD_CSS_dist()
1909
 *
1910
 * @param Champ $p
1911
 *     Pile au niveau de la balise
1912
 * @return Champ
1913
 *     Pile complétée par le code à générer
1914
 */
1915
function balise_INSERT_HEAD_dist($p) {
1916
	$p->code = "'<'.'"
1917
		. '?php header("X-Spip-Filtre: insert_head_css_conditionnel"); ?'
1918
		. "'.'>'";
1919
	$p->code .= ". pipeline('insert_head','<!-- insert_head -->')";
1920
	$p->interdire_scripts = false;
1921
1922
	return $p;
1923
}
1924
1925
/**
1926
 * Compile la balise `#INSERT_HEAD_CSS` homologue de `#INSERT_HEAD` pour les CSS
1927
 *
1928
 * Et par extension pour le JS inline qui doit préférentiellement
1929
 * être inséré avant les CSS car bloquant sinon.
1930
 *
1931
 * @link http://www.spip.net/4605
1932
 * @see balise_INSERT_HEAD_dist()
1933
 *
1934
 * @param Champ $p
1935
 *     Pile au niveau de la balise
1936
 * @return Champ
1937
 *     Pile complétée par le code à générer
1938
 */
1939
function balise_INSERT_HEAD_CSS_dist($p) {
1940
	$p->code = "pipeline('insert_head_css','<!-- insert_head_css -->')";
1941
	$p->interdire_scripts = false;
1942
1943
	return $p;
1944
}
1945
1946
/**
1947
 * Compile la balise `#INCLUDE` alias de `#INCLURE`
1948
 *
1949
 * @balise
1950
 * @see balise_INCLURE_dist()
1951
 *
1952
 * @param Champ $p
1953
 *     Pile au niveau de la balise
1954
 * @return Champ
1955
 *     Pile complétée par le code à générer
1956
 **/
1957
function balise_INCLUDE_dist($p) {
1958
	if (function_exists('balise_INCLURE')) {
1959
		return balise_INCLURE($p);
1960
	} else {
1961
		return balise_INCLURE_dist($p);
1962
	}
1963
}
1964
1965
/**
1966
 * Compile la balise `#INCLURE` qui inclut un résultat de squelette
1967
 *
1968
 * Signature : `[(#INCLURE{fond=nom_du_squelette, argument, argument=xx})]`
1969
 *
1970
 * L'argument `env` permet de transmettre tout l'environnement du squelette
1971
 * en cours au squelette inclus.
1972
 *
1973
 * On parle d’inclusion « statique » car le résultat de compilation est
1974
 * ajouté au squelette en cours, dans le même fichier de cache.
1975
 * Cette balise est donc différente d’une inclusion « dynamique » avec
1976
 * `<INCLURE.../>` qui, elle, crée un fichier de cache séparé
1977
 * (avec une durée de cache qui lui est propre).
1978
 *
1979
 * L'inclusion est realisée au calcul du squelette, pas au service
1980
 * ainsi le produit du squelette peut être utilisé en entrée de filtres
1981
 * à suivre. On peut faire un `#INCLURE{fichier}` sans squelette
1982
 * (Incompatible avec les balises dynamiques).
1983
 *
1984
 * @balise
1985
 * @example
1986
 *     ```
1987
 *     [(#INCLURE{fond=inclure/documents,id_article, env})]
1988
 *     ```
1989
 *
1990
 * @param Champ $p
1991
 *     Pile au niveau de la balise
1992
 * @return Champ
1993
 *     Pile complétée par le code à générer
1994
 **/
1995
function balise_INCLURE_dist($p) {
1996
	$id_boucle = $p->id_boucle;
1997
	// la lang n'est pas passe de facon automatique par argumenter
1998
	// mais le sera pas recuperer_fond, sauf si etoile=>true est passe
1999
	// en option
2000
2001
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
2002
2003
	// erreur de syntaxe = fond absent
2004
	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
2005
	if (!$_contexte) {
2006
		$contexte = array();
0 ignored issues
show
Unused Code introduced by
$contexte is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2007
	}
2008
2009
	if (isset($_contexte['fond'])) {
2010
2011
		$f = $_contexte['fond'];
2012
		// toujours vrai :
2013
		if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
2014
			$f = $r[1];
2015
			unset($_contexte['fond']);
2016
		} else {
2017
			spip_log("compilation de #INCLURE a revoir");
2018
		}
2019
2020
		// #INCLURE{doublons}
2021
		if (isset($_contexte['doublons'])) {
2022
			$_contexte['doublons'] = "'doublons' => \$doublons";
2023
		}
2024
2025
		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
2026
		$flag_env = false;
2027 View Code Duplication
		if (isset($_contexte['env']) or isset($_contexte['self'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2028
			$flag_env = true;
2029
			unset($_contexte['env']);
2030
		}
2031
2032
		$_options = array();
2033 View Code Duplication
		if (isset($_contexte['ajax'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2034
			$_options[] = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2035
			unset($_contexte['ajax']);
2036
		}
2037
		if ($p->etoile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->etoile of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2038
			$_options[] = "'etoile'=>true";
2039
		}
2040
		$_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) . ")";
2041
2042
		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
2043
		if ($flag_env) {
2044
			$_l = "array_merge(\$Pile[0],$_l)";
2045
		}
2046
2047
		$p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',', $_options), "_request('connect')");
2048
2049
	} elseif (!isset($_contexte[1])) {
2050
		$msg = array('zbug_balise_sans_argument', array('balise' => ' INCLURE'));
2051
		erreur_squelette($msg, $p);
2052
	} else {
2053
		$p->code = 'charge_scripts(' . $_contexte[1] . ',false)';
2054
	}
2055
2056
	$p->interdire_scripts = false; // la securite est assuree par recuperer_fond
2057
	return $p;
2058
}
2059
2060
2061
/**
2062
 * Compile la balise `#MODELE` qui inclut un résultat de squelette de modèle
2063
 *
2064
 * `#MODELE{nom}` insère le résultat d’un squelette contenu dans le
2065
 * répertoire `modeles/`. L’identifiant de la boucle parente est transmis
2066
 * par défaut avec le paramètre `id` à cette inclusion.
2067
 *
2068
 * Des arguments supplémentaires peuvent être transmis :
2069
 * `[(#MODELE{nom, argument=xx, argument})]`
2070
 *
2071
 * @balise
2072
 * @see balise_INCLURE_dist()
2073
 * @example
2074
 *     ```
2075
 *     #MODELE{article_traductions}
2076
 *     ```
2077
 *
2078
 * @param Champ $p
2079
 *     Pile au niveau de la balise
2080
 * @return Champ
2081
 *     Pile complétée par le code à générer
2082
 **/
2083
function balise_MODELE_dist($p) {
2084
2085
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
2086
2087
	// erreur de syntaxe = fond absent
2088
	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
2089
	if (!$_contexte) {
2090
		$contexte = array();
0 ignored issues
show
Unused Code introduced by
$contexte is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2091
	}
2092
2093
	if (!isset($_contexte[1])) {
2094
		$msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
2095
		erreur_squelette($msg, $p);
2096
	} else {
2097
		$nom = $_contexte[1];
2098
		unset($_contexte[1]);
2099
2100
		if (preg_match("/^\s*'[^']*'/s", $nom)) {
2101
			$nom = "'modeles/" . substr($nom, 1);
2102
		} else {
2103
			$nom = "'modeles/' . $nom";
2104
		}
2105
2106
		$flag_env = false;
2107
		if (isset($_contexte['env'])) {
2108
			$flag_env = true;
2109
			unset($_contexte['env']);
2110
		}
2111
2112
		// Incoherence dans la syntaxe du contexte. A revoir.
2113
		// Reserver la cle primaire de la boucle courante si elle existe
2114
		if (isset($p->boucles[$p->id_boucle]->primary)) {
2115
			$primary = $p->boucles[$p->id_boucle]->primary;
2116
			if (!strpos($primary, ',')) {
2117
				$id = champ_sql($primary, $p);
2118
				$_contexte[] = "'$primary'=>" . $id;
2119
				$_contexte[] = "'id'=>" . $id;
2120
			}
2121
		}
2122
		$_contexte[] = "'recurs'=>(++\$recurs)";
2123
		$connect = '';
2124
		if (isset($p->boucles[$p->id_boucle])) {
2125
			$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2126
		}
2127
2128
		$_options = memoriser_contexte_compil($p);
2129
		$_options = "'compil'=>array($_options), 'trim'=>true";
2130 View Code Duplication
		if (isset($_contexte['ajax'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2131
			$_options .= ", " . preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2132
			unset($_contexte['ajax']);
2133
		}
2134
2135
		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
2136
		if ($flag_env) {
2137
			$_l = "array_merge(\$Pile[0],$_l)";
2138
		}
2139
2140
		$page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect));
2141
2142
		$p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
2143
2144
		$p->interdire_scripts = false; // securite assuree par le squelette
2145
	}
2146
2147
	return $p;
2148
}
2149
2150
2151
/**
2152
 * Compile la balise `#SET` qui affecte une variable locale au squelette
2153
 *
2154
 * Signature : `#SET{cle,valeur}`
2155
 *
2156
 * @balise
2157
 * @link http://www.spip.net/3990 Balises #SET et #GET
2158
 * @see balise_GET_dist()
2159
 * @example
2160
 *     ```
2161
 *     #SET{nb,5}
2162
 *     #GET{nb} // affiche 5
2163
 *     ```
2164
 *
2165
 * @param Champ $p
2166
 *     Pile au niveau de la balise
2167
 * @return Champ
2168
 *     Pile complétée par le code à générer
2169
 **/
2170 View Code Duplication
function balise_SET_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2171
	$_nom = interprete_argument_balise(1, $p);
2172
	$_val = interprete_argument_balise(2, $p);
2173
2174
	if (!$_nom or !$_val) {
2175
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SET'));
2176
		erreur_squelette($err_b_s_a, $p);
2177
	}
2178
	// affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4
2179
	// cf https://bugs.php.net/bug.php?id=65845
2180
	else {
2181
		$p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)";
2182
	}
2183
2184
	$p->interdire_scripts = false; // la balise ne renvoie rien
2185
	return $p;
2186
}
2187
2188
2189
/**
2190
 * Compile la balise `#GET` qui récupère une variable locale au squelette
2191
 *
2192
 * Signature : `#GET{cle[,defaut]}`
2193
 *
2194
 * La clé peut obtenir des sous clés séparés par des `/`
2195
 *
2196
 * @balise
2197
 * @link http://www.spip.net/3990 Balises #SET et #GET
2198
 * @see balise_SET_dist()
2199
 * @example
2200
 *     ```
2201
 *     #SET{nb,5}
2202
 *     #GET{nb} affiche 5
2203
 *     #GET{nb,3} affiche la valeur de nb, sinon 3
2204
 *
2205
 *     #SET{nb,#ARRAY{boucles,3}}
2206
 *     #GET{nb/boucles} affiche 3, équivalent à #GET{nb}|table_valeur{boucles}
2207
 *     ```
2208
 *
2209
 * @param Champ $p
2210
 *     Pile au niveau de la balise
2211
 * @return Champ
2212
 *     Pile complétée par le code à générer
2213
 **/
2214
function balise_GET_dist($p) {
2215
	$p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
2216
	if (function_exists('balise_ENV')) {
2217
		return balise_ENV($p, '$Pile["vars"]');
2218
	} else {
2219
		return balise_ENV_dist($p, '$Pile["vars"]');
2220
	}
2221
}
2222
2223
2224
/**
2225
 * Compile la balise `#DOUBLONS` qui redonne les doublons enregistrés
2226
 *
2227
 * - `#DOUBLONS{mots}` ou `#DOUBLONS{mots,famille}`
2228
 *   donne l'état des doublons `(MOTS)` à cet endroit
2229
 *   sous forme de tableau d'id_mot comme `array(1,2,3,...)`
2230
 * - `#DOUBLONS` tout seul donne la liste brute de tous les doublons
2231
 * - `#DOUBLONS*{mots}` donne la chaine brute `,1,2,3,...`
2232
 *   (changera si la gestion des doublons evolue)
2233
 *
2234
 * @balise
2235
 * @link http://www.spip.net/4123
2236
 *
2237
 * @param Champ $p
2238
 *     Pile au niveau de la balise
2239
 * @return Champ
2240
 *     Pile complétée par le code à générer
2241
 **/
2242
function balise_DOUBLONS_dist($p) {
2243
	if ($type = interprete_argument_balise(1, $p)) {
2244
		if ($famille = interprete_argument_balise(2, $p)) {
2245
			$type .= '.' . $famille;
2246
		}
2247
		$p->code = '(isset($doublons[' . $type . ']) ? $doublons[' . $type . '] : "")';
2248
		if (!$p->etoile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $p->etoile of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2249
			$p->code = 'array_filter(array_map("intval",explode(",",'
2250
				. $p->code . ')))';
2251
		}
2252
	} else {
2253
		$p->code = '$doublons';
2254
	}
2255
2256
	$p->interdire_scripts = false;
2257
2258
	return $p;
2259
}
2260
2261
2262
/**
2263
 * Compile la balise `#PIPELINE` pour permettre d'insérer des sorties de
2264
 * pipeline dans un squelette
2265
 *
2266
 * @balise
2267
 * @see pipeline()
2268
 * @example
2269
 *     ```
2270
 *     #PIPELINE{nom}
2271
 *     #PIPELINE{nom,données}
2272
 *     #PIPELINE{boite_infos,#ARRAY{data,'',args,#ARRAY{type,rubrique,id,#ENV{id_rubrique}}}}
2273
 *     ```
2274
 *
2275
 * @param Champ $p
2276
 *     Pile au niveau de la balise
2277
 * @return Champ
2278
 *     Pile complétée par le code à générer
2279
 **/
2280 View Code Duplication
function balise_PIPELINE_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2281
	$_pipe = interprete_argument_balise(1, $p);
2282
	if (!$_pipe) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_pipe of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2283
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'PIPELINE'));
2284
		erreur_squelette($err_b_s_a, $p);
2285
	} else {
2286
		$_flux = interprete_argument_balise(2, $p);
2287
		$_flux = $_flux ? $_flux : "''";
2288
		$p->code = "pipeline( $_pipe , $_flux )";
2289
		$p->interdire_scripts = false;
2290
	}
2291
2292
	return $p;
2293
}
2294
2295
2296
/**
2297
 * Compile la balise `#EDIT` qui ne fait rien dans SPIP
2298
 *
2299
 * Cette balise ne retourne rien mais permet d'indiquer, pour certains plugins
2300
 * qui redéfinissent cette balise, le nom du champ SQL (ou le nom d'un contrôleur)
2301
 * correspondant à ce qui est édité. Cela sert particulièrement au plugin Crayons.
2302
 * Ainsi en absence du plugin, la balise est toujours reconnue (mais n'a aucune action).
2303
 *
2304
 * @balise
2305
 * @link http://www.spip.net/4584
2306
 * @example
2307
 *     ```
2308
 *     [<div class="#EDIT{texte} texte">(#TEXTE)</div>]
2309
 *     ```
2310
 *
2311
 * @param Champ $p
2312
 *     Pile au niveau de la balise
2313
 * @return Champ
2314
 *     Pile complétée par le code à générer
2315
 **/
2316
function balise_EDIT_dist($p) {
2317
	$p->code = "''";
2318
	$p->interdire_scripts = false;
2319
2320
	return $p;
2321
}
2322
2323
2324
/**
2325
 * Compile la balise `#TOTAL_UNIQUE` qui récupère le nombre d'éléments
2326
 * différents affichés par le filtre `unique`
2327
 *
2328
 * @balise
2329
 * @link http://www.spip.net/4374
2330
 * @see unique()
2331
 * @example
2332
 *     ```
2333
 *     #TOTAL_UNIQUE affiche le nombre de #BALISE|unique
2334
 *     #TOTAL_UNIQUE{famille} afiche le nombre de #BALISE|unique{famille}
2335
 *     ```
2336
 *
2337
 * @param Champ $p
2338
 *     Pile au niveau de la balise
2339
 * @return Champ
2340
 *     Pile complétée par le code à générer
2341
 **/
2342
function balise_TOTAL_UNIQUE_dist($p) {
2343
	$_famille = interprete_argument_balise(1, $p);
2344
	$_famille = $_famille ? $_famille : "''";
2345
	$p->code = "unique('', $_famille, true)";
2346
2347
	return $p;
2348
}
2349
2350
/**
2351
 * Compile la balise `#ARRAY` créant un tableau PHP associatif
2352
 *
2353
 * Crée un `array` PHP à partir d'arguments calculés.
2354
 * Chaque paire d'arguments représente la clé et la valeur du tableau.
2355
 *
2356
 * @balise
2357
 * @link http://www.spip.net/4009
2358
 * @example
2359
 *     ```
2360
 *     #ARRAY{key1,val1,key2,val2 ...} retourne
2361
 *     array( key1 => val1, key2 => val2, ...)
2362
 *     ```
2363
 *
2364
 * @param Champ $p
2365
 *     Pile au niveau de la balise
2366
 * @return Champ
2367
 *     Pile complétée par le code à générer
2368
 **/
2369
function balise_ARRAY_dist($p) {
2370
	$_code = array();
2371
	$n = 1;
2372
	do {
2373
		$_key = interprete_argument_balise($n++, $p);
2374
		$_val = interprete_argument_balise($n++, $p);
2375
		if ($_key and $_val) {
2376
			$_code[] = "$_key => $_val";
2377
		}
2378
	} while ($_key && $_val);
0 ignored issues
show
Bug Best Practice introduced by
The expression $_key of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $_val of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2379
	$p->code = 'array(' . join(', ', $_code) . ')';
2380
	$p->interdire_scripts = false;
2381
2382
	return $p;
2383
}
2384
2385
/**
2386
 * Compile la balise `#LISTE` qui crée un tableau PHP avec les valeurs, sans préciser les clés
2387
 *
2388
 * @balise
2389
 * @link http://www.spip.net/5547
2390
 * @example
2391
 *    ```
2392
 *    #LISTE{a,b,c,d,e}
2393
 *    ```
2394
 *
2395
 * @param Champ $p
2396
 *     Pile au niveau de la balise
2397
 * @return Champ
2398
 *     Pile complétée par le code à générer
2399
 */
2400 View Code Duplication
function balise_LISTE_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2401
	$_code = array();
2402
	$n = 1;
2403
	while ($_val = interprete_argument_balise($n++, $p)) {
2404
		$_code[] = $_val;
2405
	}
2406
	$p->code = 'array(' . join(', ', $_code) . ')';
2407
	$p->interdire_scripts = false;
2408
2409
	return $p;
2410
}
2411
2412
2413
/**
2414
 * Compile la balise `#AUTORISER` qui teste une autorisation
2415
 *
2416
 * Appelle la fonction `autoriser()` avec les mêmes arguments,
2417
 * et renvoie un espace ' ' si OK (l'action est autorisée),
2418
 * sinon une chaine vide '' (l'action n'est pas autorisée).
2419
 *
2420
 * Cette balise créée un cache par session.
2421
 *
2422
 * Signature : `#AUTORISER{faire[,type[,id[,auteur[,options]]]}`
2423
 *
2424
 * @note
2425
 *     La priorité des opérateurs exige && plutot que AND
2426
 *
2427
 * @balise
2428
 * @link http://www.spip.net/3896
2429
 * @see autoriser()
2430
 * @see sinon_interdire_acces()
2431
 * @example
2432
 *    ```
2433
 *    [(#AUTORISER{modifier,rubrique,#ID_RUBRIQUE}) ... ]
2434
 *    [(#AUTORISER{voir,rubrique,#ID_RUBRIQUE}|sinon_interdire_acces)]
2435
 *    ```
2436
 *
2437
 * @param Champ $p
2438
 *     Pile au niveau de la balise
2439
 * @return Champ
2440
 *     Pile complétée par le code à générer
2441
 **/
2442 View Code Duplication
function balise_AUTORISER_dist($p) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2443
	$_code = array();
2444
	$p->descr['session'] = true; // faire un cache par session
2445
2446
	$n = 1;
2447
	while ($_v = interprete_argument_balise($n++, $p)) {
2448
		$_code[] = $_v;
2449
	}
2450
2451
	$p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(', ',
2452
			$_code) . ')?" ":"")';
2453
	$p->interdire_scripts = false;
2454
2455
	return $p;
2456
}
2457
2458
2459
/**
2460
 * Compile la balise `#PLUGIN` qui permet d’afficher les informations d'un plugin actif
2461
 *
2462
 * @balise
2463
 * @see filtre_info_plugin_dist()
2464
 * @link http://www.spip.net/4591
2465
 * @example
2466
 *     ```
2467
 *     #PLUGIN Retourne la liste sérialisée des préfixes de plugins actifs
2468
 *     #PLUGIN{prefixe} Renvoie true si le plugin avec ce préfixe est actif
2469
 *     #PLUGIN{prefixe, x} Renvoie l'information x du plugin (s'il est actif)
2470
 *     #PLUGIN{prefixe, tout} Renvoie toutes les informations du plugin (s'il est actif)
2471
 *     ```
2472
 *
2473
 * @param Champ $p
2474
 *     Pile au niveau de la balise
2475
 * @return Champ
2476
 *     Pile complétée par le code à générer
2477
 **/
2478
function balise_PLUGIN_dist($p) {
2479
	$plugin = interprete_argument_balise(1, $p);
2480
	$plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
2481
	$type_info = interprete_argument_balise(2, $p);
2482
	$type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
2483
2484
	$f = chercher_filtre('info_plugin');
2485
	$p->code = $f . '(' . $plugin . ', ' . $type_info . ')';
2486
2487
	return $p;
2488
}
2489
2490
/**
2491
 * Compile la balise `#AIDER` qui permet d’afficher l’icone de l’aide
2492
 * au sein des squelettes.
2493
 *
2494
 * @balise
2495
 * @see inc_aide_dist()
2496
 * @link http://www.spip.net/4733
2497
 * @example
2498
 *     ```
2499
 *     #AIDER{titre}
2500
 *     ```
2501
 *
2502
 * @param Champ $p
2503
 *     Pile au niveau de la balise
2504
 * @return Champ
2505
 *     Pile complétée par le code à générer
2506
 **/
2507
function balise_AIDER_dist($p) {
2508
	$_motif = interprete_argument_balise(1, $p);
2509
	$s = "'" . addslashes($p->descr['sourcefile']) . "'";
2510
	$p->code = "((\$aider=charger_fonction('aide','inc',true))?\$aider($_motif,$s, \$Pile[0]):'')";
2511
2512
	return $p;
2513
}
2514
2515
/**
2516
 * Compile la balise `#ACTION_FORMULAIRE` qui insère le contexte
2517
 * des formulaires charger / vérifier / traiter avec les hidden de
2518
 * l'URL d'action
2519
 *
2520
 * Accèpte 2 arguments optionnels :
2521
 * - L'url de l'action (par défaut `#ENV{action}`
2522
 * - Le nom du formulaire (par défaut `#ENV{form}`
2523
 *
2524
 * @balise
2525
 * @see form_hidden()
2526
 * @example
2527
 *     ```
2528
 *     <form method='post' action='#ENV{action}'><div>
2529
 *     #ACTION_FORMULAIRE
2530
 *     ```
2531
 *
2532
 * @param Champ $p
2533
 *     Pile au niveau de la balise
2534
 * @return Champ
2535
 *     Pile complétée par le code à générer
2536
 **/
2537
function balise_ACTION_FORMULAIRE($p) {
2538
	if (!$_url = interprete_argument_balise(1, $p)) {
2539
		$_url = "@\$Pile[0]['action']";
2540
	}
2541
	if (!$_form = interprete_argument_balise(2, $p)) {
2542
		$_form = "@\$Pile[0]['form']";
2543
	}
2544
2545
	// envoyer le nom du formulaire que l'on traite
2546
	// transmettre les eventuels args de la balise formulaire
2547
	$p->code = "	'<div>' .
2548
	form_hidden($_url) .
2549
	'<input name=\'formulaire_action\' type=\'hidden\'
2550
		value=\'' . $_form . '\' />' .
2551
	'<input name=\'formulaire_action_args\' type=\'hidden\'
2552
		value=\'' . @\$Pile[0]['formulaire_args']. '\' />' .
2553
	(!empty(\$Pile[0]['_hidden']) ? @\$Pile[0]['_hidden'] : '') .
2554
	'</div>'";
2555
2556
	$p->interdire_scripts = false;
2557
2558
	return $p;
2559
}
2560
2561
2562
/**
2563
 * Compile la balise `#BOUTON_ACTION` qui génère un bouton d'action en post, ajaxable
2564
 *
2565
 * Cette balise s'utilise à la place des liens `action_auteur`, sous la forme
2566
 *
2567
 * - `#BOUTON_ACTION{libelle,url}`
2568
 * - ou `#BOUTON_ACTION{libelle,url,ajax}` pour que l'action soit ajax comme un lien `class='ajax'`
2569
 * - ou `#BOUTON_ACTION{libelle,url,ajax,message_confirmation}` pour utiliser un message de confirmation
2570
 * - ou encore `#BOUTON_ACTION{libelle[,url[,ajax[,message_confirmation[,title[,callback]]]]]}`
2571
 *
2572
 * @balise
2573
 * @link http://www.spip.net/4583
2574
 * @example
2575
 *     ```
2576
 *     [(#AUTORISER{reparer,base})
2577
 *        [(#BOUTON_ACTION{<:bouton_tenter_recuperation:>,#URL_ECRIRE{base_repair}})]
2578
 *     ]
2579
 *     ```
2580
 *
2581
 * @param Champ $p
2582
 *     Pile au niveau de la balise
2583
 * @return Champ
2584
 *     Pile complétée par le code à générer
2585
 */
2586
function balise_BOUTON_ACTION_dist($p) {
2587
2588
	$args = array();
2589
	for ($k = 1; $k <= 6; $k++) {
2590
		$_a = interprete_argument_balise($k, $p);
2591
		if (!$_a) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_a of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2592
			$_a = "''";
2593
		}
2594
		$args[] = $_a;
2595
	}
2596
	// supprimer les args vides
2597
	while (end($args) == "''" and count($args) > 2) {
2598
		array_pop($args);
2599
	}
2600
	$args = implode(",", $args);
2601
2602
	$bouton_action = chercher_filtre("bouton_action");
2603
	$p->code = "$bouton_action($args)";
2604
	$p->interdire_scripts = false;
2605
2606
	return $p;
2607
}
2608
2609
2610
/**
2611
 * Compile la balise `#SLOGAN_SITE_SPIP` qui retourne le slogan du site
2612
 *
2613
 * @balise
2614
 * @example
2615
 *     ```
2616
 *     [<p id="slogan">(#SLOGAN_SITE_SPIP)</p>]
2617
 *     ```
2618
 *
2619
 * @param Champ $p
2620
 *     Pile au niveau de la balise
2621
 * @return Champ
2622
 *     Pile complétée par le code à générer
2623
 */
2624
function balise_SLOGAN_SITE_SPIP_dist($p) {
2625
	$p->code = "\$GLOBALS['meta']['slogan_site']";
2626
2627
	#$p->interdire_scripts = true;
2628
	return $p;
2629
}
2630
2631
2632
/**
2633
 * Compile la balise `#HTML5` indiquant si l'espace public peut utiliser du HTML5
2634
 *
2635
 * Renvoie `' '` si le webmestre souhaite que SPIP génère du code (X)HTML5 sur
2636
 * le site public, et `''` si le code doit être strictement compatible HTML4
2637
 *
2638
 * @balise
2639
 * @uses html5_permis()
2640
 * @example
2641
 *     ```
2642
 *     [(#HTML5) required="required"]
2643
 *     <input[ (#HTML5|?{type="email",type="text"})] ... />
2644
 *     ```
2645
 *
2646
 * @param Champ $p
2647
 *     Pile au niveau de la balise
2648
 * @return Champ
2649
 *     Pile complétée par le code à générer
2650
 */
2651
function balise_HTML5_dist($p) {
2652
	$p->code = html5_permis() ? "' '" : "''";
2653
	$p->interdire_scripts = false;
2654
2655
	return $p;
2656
}
2657
2658
2659
/**
2660
 * Compile la balise `#TRI` permettant d'afficher un lien de changement d'ordre de tri
2661
 * d'une colonne de la boucle
2662
 *
2663
 * La balise `#TRI{champ[,libelle]}` champ prend `>` ou `<` pour afficher
2664
 * le lien de changement de sens croissant ou decroissant (`>` `<` indiquent
2665
 * un sens par une flèche)
2666
 *
2667
 * @balise
2668
 * @example
2669
 *     ```
2670
 *     <th>[(#TRI{titre,<:info_titre:>,ajax})]</th>
2671
 *     ```
2672
 *
2673
 * @param Champ $p
2674
 *     Pile au niveau de la balise
2675
 * @param string $liste
2676
 *     Inutilisé
2677
 * @return Champ
2678
 *     Pile complétée par le code à générer
2679
 */
2680
function balise_TRI_dist($p, $liste = 'true') {
0 ignored issues
show
Unused Code introduced by
The parameter $liste is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2681
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
2682
2683
	// s'il n'y a pas de nom de boucle, on ne peut pas trier
2684 View Code Duplication
	if ($b === '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2685
		erreur_squelette(
2686
			_T('zbug_champ_hors_boucle',
2687
				array('champ' => '#TRI')
2688
			), $p->id_boucle);
2689
		$p->code = "''";
2690
2691
		return $p;
2692
	}
2693
	$boucle = $p->boucles[$b];
2694
2695
	// s'il n'y a pas de tri_champ, c'est qu'on se trouve
2696
	// dans un boucle recursive ou qu'on a oublie le critere {tri}
2697 View Code Duplication
	if (!isset($boucle->modificateur['tri_champ'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2698
		erreur_squelette(
2699
			_T('zbug_tri_sans_critere',
2700
				array('champ' => '#TRI')
2701
			), $p->id_boucle);
2702
		$p->code = "''";
2703
2704
		return $p;
2705
	}
2706
2707
	$_champ = interprete_argument_balise(1, $p);
2708
	// si pas de champ, renvoyer le critere de tri utilise
2709
	if (!$_champ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_champ of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2710
		$p->code = $boucle->modificateur['tri_champ'];
2711
2712
		return $p;
2713
	}
2714
	// forcer la jointure si besoin, et si le champ est statique
2715
	if (preg_match(",^'([\w.]+)'$,i", $_champ, $m)) {
2716
		index_pile($b, $m[1], $p->boucles, '', null, true, false);
2717
	}
2718
2719
	$_libelle = interprete_argument_balise(2, $p);
2720
	$_libelle = $_libelle ? $_libelle : $_champ;
2721
2722
	$_class = interprete_argument_balise(3, $p);
2723
	// si champ = ">" c'est un lien vers le tri croissant : de gauche a droite ==> 1
2724
	// si champ = "<" c'est un lien vers le tri decroissant : (sens inverse) == -1
2725
	$_issens = "in_array($_champ,array('>','<'))";
2726
	$_sens = "(strpos('< >',$_champ)-1)";
2727
2728
	$_variable = "((\$s=$_issens)?'sens':'tri')." . $boucle->modificateur['tri_nom'];
2729
	$_url = "parametre_url(self(),$_variable,\$s?$_sens:$_champ)";
2730
	$_url = "parametre_url($_url,'var_memotri',strncmp(" . $boucle->modificateur['tri_nom'] . ",'session',7)==0?$_variable:'')";
2731
	$_on = "\$s?(" . $boucle->modificateur['tri_sens'] . "==$_sens" . '):(' . $boucle->modificateur['tri_champ'] . "==$_champ)";
2732
2733
	$p->code = "lien_ou_expose($_url,$_libelle,$_on" . ($_class ? ",$_class" : "") . ")";
2734
	//$p->code = "''";
2735
	$p->interdire_scripts = false;
2736
2737
	return $p;
2738
}
2739
2740
2741
/**
2742
 * Compile la balise `#SAUTER{n}` qui permet de sauter en avant n resultats dans une boucle
2743
 *
2744
 * La balise modifie le compteur courant de la boucle, mais pas les autres
2745
 * champs qui restent les valeurs de la boucle avant le saut. Il est donc
2746
 * preferable d'utiliser la balise juste avant la fermeture `</BOUCLE>`
2747
 *
2748
 * L'argument `n` doit être supérieur à zéro sinon la balise ne fait rien
2749
 *
2750
 * @balise
2751
 *
2752
 * @param Champ $p
2753
 *     Pile au niveau de la balise
2754
 * @return Champ
2755
 *     Pile complétée par le code à générer
2756
 */
2757
function balise_SAUTER_dist($p) {
2758
	$id_boucle = $p->id_boucle;
2759
2760
	if (empty($p->boucles[$id_boucle])) {
2761
		$msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER'));
2762
		erreur_squelette($msg, $p);
2763
	} else {
2764
		$boucle = $p->boucles[$id_boucle];
0 ignored issues
show
Unused Code introduced by
$boucle is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2765
		$_saut = interprete_argument_balise(1, $p);
2766
		$_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
2767
		$_total = "\$Numrows['$id_boucle']['total']";
2768
2769
		$p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
2770
	}
2771
	$p->interdire_scripts = false;
2772
2773
	return $p;
2774
}
2775
2776
2777
/**
2778
 * Compile la balise `#PUBLIE` qui indique si un objet est publié ou non
2779
 *
2780
 * @balise
2781
 * @link http://www.spip.net/5545
2782
 * @see objet_test_si_publie()
2783
 * @example
2784
 *     ```
2785
 *     #PUBLIE : porte sur la boucle en cours
2786
 *     [(#PUBLIE{article, 3}|oui) ... ] : pour l'objet indiqué
2787
 *     ```
2788
 *
2789
 * @param Champ $p
2790
 *     Pile au niveau de la balise
2791
 * @return Champ
2792
 *     Pile complétée par le code à générer
2793
 */
2794
function balise_PUBLIE_dist($p) {
2795
	if (!$_type = interprete_argument_balise(1, $p)) {
2796
		$_type = _q($p->type_requete);
2797
		$_id = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
2798
	} else {
2799
		$_id = interprete_argument_balise(2, $p);
2800
	}
2801
2802
	$connect = '';
2803
	if (isset($p->boucles[$p->id_boucle])) {
2804
		$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2805
	}
2806
2807
	$p->code = "(objet_test_si_publie(" . $_type . ",intval(" . $_id . ")," . _q($connect) . ")?' ':'')";
2808
	$p->interdire_scripts = false;
2809
2810
	return $p;
2811
}
2812
2813
/**
2814
 * Compile la balise `#PRODUIRE` qui génère un fichier statique à partir
2815
 * d'un squelette SPIP
2816
 *
2817
 * Le format du fichier sera extrait de la pre-extension du squelette
2818
 * (typo.css.html, messcripts.js.html)
2819
 * ou par l'argument `format=css` ou `format=js` passé en argument.
2820
 *
2821
 * S'il n'y a pas de format détectable, on utilise `.html`, comme pour les squelettes.
2822
 *
2823
 * La syntaxe de la balise est la même que celle de `#INCLURE`.
2824
 *
2825
 * @balise
2826
 * @see balise_INCLURE_dist()
2827
 * @link http://www.spip.net/5505
2828
 * @example
2829
 *     ```
2830
 *     <link rel="stylesheet" type="text/css" href="#PRODUIRE{fond=css/macss.css,couleur=ffffff}" />
2831
 *     ```
2832
 *
2833
 * @param Champ $p
2834
 *     Pile au niveau de la balise
2835
 * @return Champ
2836
 *     Pile complétée par le code à générer
2837
 */
2838
function balise_PRODUIRE_dist($p) {
2839
	$balise_inclure = charger_fonction('INCLURE', 'balise');
2840
	$p = $balise_inclure($p);
2841
2842
	$p->code = str_replace('recuperer_fond(', 'produire_fond_statique(', $p->code);
2843
2844
	return $p;
2845
}
2846
2847
/**
2848
 * Compile la balise `#LARGEUR_ECRAN` qui définit la largeur d'écran
2849
 * dans l'espace privé
2850
 *
2851
 * @balise
2852
 * @example
2853
 *     ```
2854
 *     #LARGEUR_ECRAN{pleine_largeur}
2855
 *     ```
2856
 *
2857
 * @param Champ $p
2858
 *     Pile au niveau de la balise
2859
 * @return Champ
2860
 *     Pile complétée par le code à générer
2861
 */
2862
function balise_LARGEUR_ECRAN_dist($p) {
2863
	$_class = interprete_argument_balise(1, $p);
2864
	if (!$_class) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $_class of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2865
		$_class = 'null';
2866
	}
2867
	$p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))";
2868
2869
	return $p;
2870
}
2871
2872
2873
/**
2874
 * Compile la balise `#CONST` qui retourne la valeur de la constante passee en argument
2875
 * #CONST{_DIR_IMG}
2876
 *
2877
 * @balise
2878
 * @param Champ $p
2879
 *     Pile au niveau de la balise
2880
 * @return Champ
2881
 *     Pile complétée par le code à générer
2882
 **/
2883
function balise_CONST_dist($p) {
2884
	$_const = interprete_argument_balise(1, $p);
2885
	if (!strlen($_const)) {
2886
		$p->code = "''";
2887
	}
2888
	else {
2889
		$p->code = "(defined($_const)?constant($_const):'')";
2890
	}
2891
	$p->interdire_scripts = false;
2892
2893
	return $p;
2894
}
2895