Completed
Push — master ( 11f960...65d759 )
by cam
07:32
created

balises.php ➔ balise_FIN_SURLIGNE_dist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
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 `#INTRODUCTION`
773
 *
774
 * Retourne une introduction d'un objet éditorial, c'est à dire les 600
775
 * premiers caractères environ du champ 'texte' de l'objet ou le contenu
776
 * indiqué entre `<intro>` et `</intro>` de ce même champ.
777
 *
778
 * Pour les articles, l'introduction utilisée est celle du champ `descriptif`
779
 * s'il est renseigné, sinon il est pris dans les champs `chapo` et `texte` et
780
 * est par défaut limité à 500 caractères.
781
 *
782
 * Pour les rubriques, l'introduction utilisée est celle du champ `descriptif`
783
 * s'il est renseigné, sinon du champ texte.
784
 *
785
 * La balise accèpte 1 paramètre indiquant la longueur en nombre de caractères
786
 * de l'introduction.
787
 *
788
 * @see filtre_introduction_dist()
789
 * @example
790
 *     ```
791
 *     #INTRODUCTION
792
 *     #INTRODUCTION{300}
793
 *     ```
794
 *
795
 * @balise
796
 * @link http://www.spip.net/@introduction
797
 *
798
 * @param Champ $p
799
 *     Pile au niveau de la balise
800
 * @return Champ
801
 *     Pile complétée par le code à générer
802
 **/
803
function balise_INTRODUCTION_dist($p) {
804
805
	$type = $p->type_requete;
806
807
	$_texte = champ_sql('texte', $p);
808
	$_descriptif = ($type == 'articles' or $type == 'rubriques') ? champ_sql('descriptif', $p) : "''";
809
810
	if ($type == 'articles') {
811
		$_chapo = champ_sql('chapo', $p);
812
		$_texte = "(strlen($_descriptif))
813
		? ''
814
		: $_chapo . \"\\n\\n\" . $_texte";
815
	}
816
817
	// longueur en parametre, ou valeur par defaut
818
	$longueur_defaut = objet_info($type, 'introduction_longueur');
819
	if (!$longueur_defaut) {
820
		$longueur_defaut = 600;
821
	}
822
823
	$_suite = 'null';
824
	$_longueur = $longueur_defaut;
825
	if (($v = interprete_argument_balise(1, $p)) !== null) {
826
		$_longueur = 'is_numeric(' . $v . ')?intval(' . $v . '):' . $longueur_defaut;
827
		$_suite = '!is_numeric(' . $v . ')?' . $v . ':null';
828
	}
829
	if (($v2 = interprete_argument_balise(2, $p)) !== null) {
830
		$_suite = $v2;
831
	}
832
833
	$f = chercher_filtre('introduction');
834
	$p->code = "$f($_descriptif, $_texte, $_longueur, \$connect, $_suite)";
835
836
	#$p->interdire_scripts = true;
837
	$p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
838
	return $p;
839
}
840
841
842
/**
843
 * Compile la balise `#LANG` qui affiche la langue de l'objet (ou d'une boucle supérieure),
844
 * et à defaut la langue courante
845
 *
846
 * La langue courante est celle du site ou celle qui a été passée dans l'URL par le visiteur.
847
 * L'étoile `#LANG*` n'affiche rien si aucune langue n'est trouvée dans le SQL ou le contexte.
848
 *
849
 * @balise
850
 * @link http://www.spip.net/3864
851
 *
852
 * @param Champ $p
853
 *     Pile au niveau de la balise
854
 * @return Champ
855
 *     Pile complétée par le code à générer
856
 **/
857
function balise_LANG_dist($p) {
858
	$_lang = champ_sql('lang', $p);
859
	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...
860
		$p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
861
	} else {
862
		$p->code = "spip_htmlentities($_lang)";
863
	}
864
	$p->interdire_scripts = false;
865
866
	return $p;
867
}
868
869
/**
870
 * Compile la balise `#LESAUTEURS` chargée d'afficher la liste des auteurs d'un objet
871
 *
872
 * - Soit le champ `lesauteurs` existe dans la table et à ce moment là,
873
 *   la balise retourne son contenu,
874
 * - soit la balise appelle le modele `lesauteurs.html` en lui passant
875
 *   le couple `objet` et `id_objet` dans son environnement.
876
 *
877
 * @balise
878
 * @link http://www.spip.net/3966 Description de la balise
879
 * @link http://www.spip.net/902 Description de la boucle ARTICLES
880
 * @link http://www.spip.net/911 Description de la boucle SYNDIC_ARTICLES
881
 *
882
 * @param Champ $p
883
 *     Pile au niveau de la balise
884
 * @return Champ
885
 *     Pile complétée par le code à générer
886
 */
887
function balise_LESAUTEURS_dist($p) {
888
	// Cherche le champ 'lesauteurs' dans la pile
889
	$_lesauteurs = champ_sql('lesauteurs', $p, false);
890
891
	// Si le champ n'existe pas (cas de spip_articles), on applique
892
	// le modele lesauteurs.html en passant id_article dans le contexte;
893
	// dans le cas contraire on prend le champ 'lesauteurs'
894
	// (cf extension sites/)
895
	if ($_lesauteurs
896
		and $_lesauteurs != '@$Pile[0][\'lesauteurs\']'
897
	) {
898
		$p->code = "safehtml($_lesauteurs)";
899
		// $p->interdire_scripts = true;
900
	} else {
901
		if (!$p->id_boucle) {
902
			$connect = '';
903
			$objet = 'article';
904
			$id_table_objet = 'id_article';
905
		} else {
906
			$b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
907
			$connect = $p->boucles[$b]->sql_serveur;
908
			$type_boucle = $p->boucles[$b]->type_requete;
909
			$objet = objet_type($type_boucle);
910
			$id_table_objet = id_table_objet($type_boucle);
911
		}
912
		$c = memoriser_contexte_compil($p);
913
914
		$p->code = sprintf(CODE_RECUPERER_FOND, "'modeles/lesauteurs'",
915
			"array('objet'=>'" . $objet .
916
			"','id_objet' => " . champ_sql($id_table_objet, $p) .
917
			",'$id_table_objet' => " . champ_sql($id_table_objet, $p) .
918
			($objet == 'article' ? "" : ",'id_article' => " . champ_sql('id_article', $p)) .
919
			")",
920
			"'trim'=>true, 'compil'=>array($c)",
921
			_q($connect));
922
		$p->interdire_scripts = false; // securite apposee par recuperer_fond()
923
	}
924
925
	return $p;
926
}
927
928
929
/**
930
 * Compile la balise `#RANG` chargée d'afficher le numéro de l'objet
931
 *
932
 * Affiche le « numero de l'objet ». Soit `1` quand on a un titre `1. Premier article`.
933
 *
934
 * Ceci est transitoire afin de préparer une migration vers un vrai système de
935
 * tri des articles dans une rubrique (et plus si affinités).
936
 * La balise permet d'extraire le numero masqué par le filtre `supprimer_numero`.
937
 *
938
 * La balise recupère le champ declaré dans la définition `table_titre`
939
 * de l'objet, ou à defaut du champ `titre`
940
 *
941
 * Si un champ `rang` existe, il est pris en priorité.
942
 *
943
 * @balise
944
 * @link http://www.spip.net/5495
945
 *
946
 * @param Champ $p
947
 *     Pile au niveau de la balise
948
 * @return Champ
949
 *     Pile complétée par le code à générer
950
 */
951
function balise_RANG_dist($p) {
952
	$b = index_boucle($p);
953
	if ($b === '') {
954
		$msg = array(
955
			'zbug_champ_hors_boucle',
956
			array('champ' => '#RANG')
957
		);
958
		erreur_squelette($msg, $p);
959
	} else {
960
		// chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql)
961
		// dans la boucle immediatement englobante uniquement
962
		// sinon on compose le champ calcule
963
		$_rang = champ_sql('rang', $p, '', false);
964
965
		// si pas trouve de champ sql rang :
966
		if (!$_rang or $_rang == "''") {
967
			$boucle = &$p->boucles[$b];
968
			$trouver_table = charger_fonction('trouver_table', 'base');
969
			$desc = $trouver_table($boucle->id_table);
970
			$_titre = ''; # où extraire le numero ?
971
			
972
			if (isset($desc['titre'])) {
973
				$t = $desc['titre'];
974
				if (
975
					// Soit on trouve avec la déclaration de la lang AVANT
976
					preg_match(';(?:lang\s*,)\s*(.*?titre)\s*(,|$);', $t, $m)
977
					// Soit on prend depuis le début
978
					or preg_match(';^(.*?titre)\s*(,|$);', $t, $m)
979
				) {
980
					$m = preg_replace(',as\s+titre$,i', '', $m[1]);
981
					$m = trim($m);
982
					if ($m != "''") {
983
						if (!preg_match(",\W,", $m)) {
984
							$m = $boucle->id_table . ".$m";
985
						}
986
						
987
						$m .= " AS titre_rang";
988
989
						$boucle->select[] = $m;
990
						$_titre = '$Pile[$SP][\'titre_rang\']';
991
					}
992
				}
993
			}
994
			
995
			// si on n'a rien trouvé, on utilise le champ titre classique
996
			if (!$_titre) {
997
				$_titre = champ_sql('titre', $p);
998
			}
999
			
1000
			$_rang = "recuperer_numero($_titre)";
1001
		}
1002
		
1003
		$p->code = $_rang;
1004
		$p->interdire_scripts = false;
1005
	}
1006
	
1007
	return $p;
1008
}
1009
1010
1011
/**
1012
 * Compile la balise `#POPULARITE` qui affiche la popularité relative.
1013
 *
1014
 * C'est à dire le pourcentage de la fréquentation de l'article
1015
 * (la popularité absolue) par rapport à la popularité maximum.
1016
 *
1017
 * @balise
1018
 * @link http://www.spip.net/1846 La popularité
1019
 * @see balise_POPULARITE_ABSOLUE_dist()
1020
 * @see balise_POPULARITE_MAX_dist()
1021
 * @see balise_POPULARITE_SITE_dist()
1022
 *
1023
 * @param Champ $p
1024
 *     Pile au niveau de la balise
1025
 * @return Champ
1026
 *     Pile complétée par le code à générer
1027
 **/
1028
function balise_POPULARITE_dist($p) {
1029
	$_popularite = champ_sql('popularite', $p);
1030
	$p->code = "(ceil(min(100, 100 * $_popularite
1031
	/ max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))";
1032
	$p->interdire_scripts = false;
1033
1034
	return $p;
1035
}
1036
1037
/**
1038
 * Code de compilation pour la balise `#PAGINATION`
1039
 *
1040
 * Le code produit est trompeur, car les modèles ne fournissent pas Pile[0].
1041
 * On produit un appel à `_request` si on ne l'a pas, mais c'est inexact:
1042
 * l'absence peut-être due à une faute de frappe dans le contexte inclus.
1043
 */
1044
define('CODE_PAGINATION',
1045
'%s($Numrows["%s"]["grand_total"],
1046
 		%s,
1047
		isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)),
1048
		%5$s, %6$s, %7$s, %8$s, array(%9$s))');
1049
1050
/**
1051
 * Compile la balise `#PAGINATION` chargée d'afficher une pagination
1052
 *
1053
 * Elle charge le modèle `pagination.html` (par défaut), mais un paramètre
1054
 * permet d'indiquer d'autres modèles. `#PAGINATION{nom}` utilisera le
1055
 * modèle `pagination_nom.html`.
1056
 *
1057
 * Cette balise nécessite le critère `pagination` sur la boucle où elle
1058
 * est utilisée.
1059
 *
1060
 * @balise
1061
 * @link http://www.spip.net/3367 Le système de pagination
1062
 * @see filtre_pagination_dist()
1063
 * @see critere_pagination_dist()
1064
 * @see balise_ANCRE_PAGINATION_dist()
1065
 * @example
1066
 *    ```
1067
 *    [<p class="pagination">(#PAGINATION{prive})</p>]
1068
 *    ```
1069
 *
1070
 * @param Champ $p
1071
 *     Pile au niveau de la balise
1072
 * @param string $liste
1073
 *     Afficher ou non les liens de pagination (variable de type `string`
1074
 *     car code à faire écrire au compilateur) :
1075
 *     - `true` pour les afficher
1076
 *     - `false` pour afficher uniquement l'ancre.
1077
 * @return Champ
1078
 *     Pile complétée par le code à générer
1079
 */
1080
function balise_PAGINATION_dist($p, $liste = 'true') {
1081
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
1082
1083
	// s'il n'y a pas de nom de boucle, on ne peut pas paginer
1084
	if ($b === '') {
1085
		$msg = array(
1086
			'zbug_champ_hors_boucle',
1087
			array('champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION')
1088
		);
1089
		erreur_squelette($msg, $p);
1090
1091
		return $p;
1092
	}
1093
1094
	// s'il n'y a pas de mode_partie, c'est qu'on se trouve
1095
	// dans un boucle recursive ou qu'on a oublie le critere {pagination}
1096
	if (!$p->boucles[$b]->mode_partie) {
1097
		if (!$p->boucles[$b]->table_optionnelle) {
1098
			$msg = array(
1099
				'zbug_pagination_sans_critere',
1100
				array('champ' => '#PAGINATION')
1101
			);
1102
			erreur_squelette($msg, $p);
1103
		}
1104
1105
		return $p;
1106
	}
1107
1108
	// a priori true
1109
	// si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
1110
	// si true, les arguments simples (sans truc=chose) vont degager
1111
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
1112
	if (count($_contexte)) {
1113
		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...
1114
		if (is_numeric($key)) {
1115
			array_shift($_contexte);
1116
			$__modele = interprete_argument_balise(1, $p);
1117
		}
1118
	}
1119
1120
	if (count($_contexte)) {
1121
		$code_contexte = implode(',', $_contexte);
1122
	} else {
1123
		$code_contexte = '';
1124
	}
1125
1126
	$connect = $p->boucles[$b]->sql_serveur;
1127
	$pas = $p->boucles[$b]->total_parties;
1128
	$f_pagination = chercher_filtre('pagination');
1129
	$type = $p->boucles[$b]->modificateur['debut_nom'];
1130
	$modif = ($type[0] !== "'") ? "'debut'.$type"
1131
		: ("'debut" . substr($type, 1));
1132
1133
	$p->code = sprintf(CODE_PAGINATION, $f_pagination, $b, $type, $modif, $pas, $liste,
1134
		((isset($__modele) and $__modele) ? $__modele : "''"), _q($connect), $code_contexte);
1135
1136
	$p->boucles[$b]->numrows = true;
1137
	$p->interdire_scripts = false;
1138
1139
	return $p;
1140
}
1141
1142
1143
/**
1144
 * Compile la balise `#ANCRE_PAGINATION` chargée d'afficher l'ancre
1145
 * de la pagination
1146
 *
1147
 * Cette ancre peut ainsi être placée au-dessus la liste des éléments
1148
 * de la boucle alors qu'on mettra les liens de pagination en-dessous de
1149
 * cette liste paginée.
1150
 *
1151
 * Cette balise nécessite le critère `pagination` sur la boucle où elle
1152
 * est utilisée.
1153
 *
1154
 * @balise
1155
 * @link http://www.spip.net/3367 Le système de pagination
1156
 * @link http://www.spip.net/4328 Balise ANCRE_PAGINATION
1157
 * @see critere_pagination_dist()
1158
 * @see balise_PAGINATION_dist()
1159
 *
1160
 * @param Champ $p
1161
 *     Pile au niveau de la balise
1162
 * @return Champ
1163
 *     Pile complétée par le code à générer
1164
 **/
1165
function balise_ANCRE_PAGINATION_dist($p) {
1166
	if ($f = charger_fonction('PAGINATION', 'balise', true)) {
1167
		return $f($p, $liste = 'false');
1168
	} else {
1169
		return null;
1170
	} // ou une erreur ?
1171
}
1172
1173
1174
/**
1175
 * Compile la balise `#GRAND_TOTAL` qui retourne le nombre total de résultats
1176
 * d'une boucle
1177
 *
1178
 * Cette balise set équivalente à `#TOTAL_BOUCLE` sauf pour les boucles paginées.
1179
 * Dans ce cas elle indique le nombre total d'éléments répondant aux critères
1180
 * hors pagination.
1181
 *
1182
 * @balise
1183
 * @see balise_GRAND_TOTAL_dist()
1184
 *
1185
 * @param Champ $p
1186
 *     Pile au niveau de la balise
1187
 * @return Champ
1188
 *     Pile complétée par le code à générer
1189
 **/
1190 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...
1191
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
1192
	if ($b === '' || !isset($p->boucles[$b])) {
1193
		$msg = array(
1194
			'zbug_champ_hors_boucle',
1195
			array('champ' => "#$b" . 'TOTAL_BOUCLE')
1196
		);
1197
		erreur_squelette($msg, $p);
1198
	} else {
1199
		$p->code = "(isset(\$Numrows['$b']['grand_total'])
1200
			? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])";
1201
		$p->boucles[$b]->numrows = true;
1202
		$p->interdire_scripts = false;
1203
	}
1204
1205
	return $p;
1206
}
1207
1208
1209
/**
1210
 * Compile la balise `#SELF` qui retourne l’URL de la page appelée.
1211
 *
1212
 * Cette URL est nettoyée des variables propres à l’exécution de SPIP
1213
 * tel que `var_mode`.
1214
 *
1215
 * @note
1216
 *     Attention dans un `INCLURE()` ou une balise dynamique, on n'a pas le droit de
1217
 *     mettre en cache `#SELF` car il peut correspondre à une autre page (attaque XSS)
1218
 *     (Dans ce cas faire <INCLURE{self=#SELF}> pour différencier les caches.)
1219
 *
1220
 * @balise
1221
 * @link http://www.spip.net/4574
1222
 * @example
1223
 *     ```
1224
 *     <a href="[(#SELF|parametre_url{id_mot,#ID_MOT})]">...
1225
 *     ```
1226
 *
1227
 * @param Champ $p
1228
 *     Pile au niveau de la balise
1229
 * @return Champ
1230
 *     Pile complétée par le code à générer
1231
 **/
1232
function balise_SELF_dist($p) {
1233
	$p->code = 'self()';
1234
	$p->interdire_scripts = false;
1235
1236
	return $p;
1237
}
1238
1239
1240
/**
1241
 * Compile la balise `#CHEMIN` qui cherche un fichier dans les chemins
1242
 * connus de SPIP et retourne son chemin complet depuis la racine
1243
 *
1244
 * Signature : `#CHEMIN{chemin/vers/fichier.ext}`
1245
 *
1246
 * Retourne une chaîne vide si le fichier n'est pas trouvé.
1247
 *
1248
 * @balise
1249
 * @link http://www.spip.net/4332
1250
 * @see find_in_path() Recherche de chemin
1251
 * @example
1252
 *     ```
1253
 *     [<script type="text/javascript" src="(#CHEMIN{javascript/jquery.flot.js})"></script>]
1254
 *     [<link rel="stylesheet" href="(#CHEMIN{css/perso.css}|direction_css)" type="text/css" />]
1255
 *     ```
1256
 *
1257
 * @param Champ $p
1258
 *     Pile au niveau de la balise
1259
 * @return Champ
1260
 *     Pile complétée par le code à générer
1261
 **/
1262 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...
1263
	$arg = interprete_argument_balise(1, $p);
1264
	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...
1265
		$msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN'));
1266
		erreur_squelette($msg, $p);
1267
	} else {
1268
		$p->code = 'find_in_path(' . $arg . ')';
1269
	}
1270
1271
	$p->interdire_scripts = false;
1272
1273
	return $p;
1274
}
1275
1276
/**
1277
 * Compile la balise `#CHEMIN_IMAGE` qui cherche une image dans le thème
1278
 * de l'espace privé utilisé par SPIP et retourne son chemin complet depuis
1279
 * la racine
1280
 *
1281
 * Signature : `#CHEMIN_IMAGE{image.png}`
1282
 *
1283
 * Retourne une chaîne vide si le fichier n'est pas trouvé.
1284
 *
1285
 * @balise
1286
 * @see chemin_image()
1287
 * @example
1288
 *     ```
1289
 *     #CHEMIN_IMAGE{article-24.png}
1290
 *     ```
1291
 *
1292
 * @param Champ $p
1293
 *     Pile au niveau de la balise
1294
 * @return Champ
1295
 *     Pile complétée par le code à générer
1296
 **/
1297 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...
1298
	$arg = interprete_argument_balise(1, $p);
1299
	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...
1300
		$msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN_IMAGE'));
1301
		erreur_squelette($msg, $p);
1302
	} else {
1303
		$p->code = 'chemin_image(' . $arg . ')';
1304
	}
1305
1306
	#$p->interdire_scripts = true;
1307
	return $p;
1308
}
1309
1310
1311
/**
1312
 * Compile la balise `#ENV` qui permet de récupérer le contexte d'environnement
1313
 * transmis à un squelette.
1314
 *
1315
 * La syntaxe `#ENV{toto, valeur par defaut}`
1316
 * renverra `valeur par defaut` si `$toto` est vide.
1317
 *
1318
 * La recherche de la clé s'appuyant sur la fonction `table_valeur`
1319
 * il est possible de demander un sous élément d'un tableau :
1320
 * `#ENV{toto/sous/element, valeur par defaut}` retournera l'équivalent de
1321
 * `#ENV{toto}|table_valeur{sous/element}` c'est-à-dire en quelque sorte
1322
 * `$env['toto']['sous']['element']` s'il existe, sinon la valeur par défaut.
1323
 *
1324
 * Si le tableau est vide on renvoie `''` (utile pour `#SESSION`)
1325
 *
1326
 * Enfin, la balise utilisée seule `#ENV` retourne le tableau complet
1327
 * de l'environnement. À noter que ce tableau est retourné sérialisé.
1328
 *
1329
 * En standard est appliqué le filtre `entites_html`, mais si l'étoile est
1330
 * utilisée pour désactiver les filtres par défaut, par exemple avec
1331
 * `[(#ENV*{toto})]` , il *faut* s'assurer de la sécurité
1332
 * anti-javascript, par exemple en filtrant avec `safehtml` : `[(#ENV*{toto}|safehtml)]`
1333
 *
1334
 *
1335
 * @param Champ $p
1336
 *     Pile ; arbre de syntaxe abstrait positionné au niveau de la balise.
1337
 * @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...
1338
 *     Tableau dans lequel chercher la clé demandée en paramètre de la balise.
1339
 *     Par defaut prend dans le contexte du squelette.
1340
 * @return Champ
1341
 *     Pile completée du code PHP d'exécution de la balise
1342
 **/
1343
function balise_ENV_dist($p, $src = null) {
1344
1345
	// cle du tableau desiree
1346
	$_nom = interprete_argument_balise(1, $p);
1347
	// valeur par defaut
1348
	$_sinon = interprete_argument_balise(2, $p);
1349
1350
	// $src est un tableau de donnees sources eventuellement transmis
1351
	// en absence, on utilise l'environnement du squelette $Pile[0]
1352
1353
	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...
1354
		// cas de #ENV sans argument : on retourne le serialize() du tableau
1355
		// une belle fonction [(#ENV|affiche_env)] serait pratique
1356
		if ($src) {
1357
			$p->code = '(is_array($a = (' . $src . ')) ? serialize($a) : "")';
1358
		} else {
1359
			$p->code = '@serialize($Pile[0])';
1360
		}
1361
	} else {
1362
		if (!$src) {
1363
			$src = '@$Pile[0]';
1364
		}
1365
		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...
1366
			$p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)";
1367
		} else {
1368
			$p->code = "table_valeur($src, (string)$_nom, null)";
1369
		}
1370
	}
1371
1372
	#$p->interdire_scripts = true;
1373
1374
	return $p;
1375
}
1376
1377
/**
1378
 * Compile la balise `#CONFIG` qui retourne une valeur de configuration
1379
 *
1380
 * Cette balise appelle la fonction `lire_config()` pour obtenir les
1381
 * configurations du site.
1382
 *
1383
 * Par exemple `#CONFIG{gerer_trad}` donne 'oui ou 'non' selon le réglage.
1384
 *
1385
 * Le 3ème argument permet de contrôler la sérialisation du résultat
1386
 * (mais ne sert que pour le dépot `meta`) qui doit parfois désérialiser,
1387
 * par exemple avec `|in_array{#CONFIG{toto,#ARRAY,1}}`. Ceci n'affecte
1388
 * pas d'autres dépots et `|in_array{#CONFIG{toto/,#ARRAY}}` sera
1389
 * équivalent.
1390
 *
1391
 * Òn peut appeler d'autres tables que `spip_meta` avec un
1392
 * `#CONFIG{/infos/champ,defaut}` qui lit la valeur de `champ`
1393
 * dans une table des meta qui serait `spip_infos`
1394
 *
1395
 * @balise
1396
 * @link http://www.spip.net/4335
1397
 *
1398
 * @param Champ $p
1399
 *     Pile au niveau de la balise.
1400
 * @return Champ
1401
 *     Pile completée du code PHP d'exécution de la balise
1402
 */
1403
function balise_CONFIG_dist($p) {
1404
	if (!$arg = interprete_argument_balise(1, $p)) {
1405
		$arg = "''";
1406
	}
1407
	$_sinon = interprete_argument_balise(2, $p);
1408
	$_unserialize = sinon(interprete_argument_balise(3, $p), "false");
1409
1410
	$p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' .
1411
		($_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...
1412
1413
	return $p;
1414
}
1415
1416
1417
/**
1418
 * Compile la balise `#CONNECT` qui retourne le nom du connecteur
1419
 * de base de données
1420
 *
1421
 * Retourne le nom du connecteur de base de données utilisé (le nom
1422
 * du fichier `config/xx.php` sans l'extension, utilisé pour calculer
1423
 * les données du squelette).
1424
 *
1425
 * Retourne `NULL` si le connecteur utilisé est celui par défaut de SPIP
1426
 * (connect.php), sinon retourne son nom.
1427
 *
1428
 * @balise
1429
 *
1430
 * @param Champ $p
1431
 *     Pile au niveau de la balise.
1432
 * @return Champ
1433
 *     Pile completée du code PHP d'exécution de la balise
1434
 */
1435
function balise_CONNECT_dist($p) {
1436
	$p->code = '($connect ? $connect : NULL)';
1437
	$p->interdire_scripts = false;
1438
1439
	return $p;
1440
}
1441
1442
1443
/**
1444
 * Compile la balise `#SESSION` qui permet d’accéder aux informations
1445
 * liées au visiteur authentifié et de différencier automatiquement
1446
 * le cache en fonction du visiteur.
1447
 *
1448
 * Cette balise est un tableau des données du visiteur (nom, email etc).
1449
 * Si elle est invoquée, elle lève un drapeau dans le fichier cache, qui
1450
 * permet à public/cacher de créer un cache différent par visiteur
1451
 *
1452
 * @balise
1453
 * @link http://www.spip.net/3979
1454
 * @see balise_AUTORISER_dist()
1455
 * @see balise_SESSION_SET_dist()
1456
 * @example
1457
 *     ```
1458
 *     #SESSION{nom}
1459
 *     ```
1460
 *
1461
 * @param Champ $p
1462
 *     Pile au niveau de la balise.
1463
 * @return Champ
1464
 *     Pile completée du code PHP d'exécution de la balise
1465
 **/
1466
function balise_SESSION_dist($p) {
1467
	$p->descr['session'] = true;
1468
1469
	$f = function_exists('balise_ENV')
1470
		? 'balise_ENV'
1471
		: 'balise_ENV_dist';
1472
1473
	$p = $f($p, '$GLOBALS["visiteur_session"]');
1474
1475
	return $p;
1476
}
1477
1478
1479
/**
1480
 * Compile la balise `#SESSION_SET` qui d’insérer dans la session
1481
 * des données supplémentaires
1482
 *
1483
 * @balise
1484
 * @link http://www.spip.net/3984
1485
 * @see balise_AUTORISER_dist()
1486
 * @see balise_SESSION_SET_dist()
1487
 * @example
1488
 *     ```
1489
 *     #SESSION_SET{x,y} ajoute x=y dans la session du visiteur
1490
 *     ```
1491
 *
1492
 * @param Champ $p
1493
 *     Pile au niveau de la balise.
1494
 * @return Champ
1495
 *     Pile completée du code PHP d'exécution de la balise
1496
 **/
1497
function balise_SESSION_SET_dist($p) {
1498
	$_nom = interprete_argument_balise(1, $p);
1499
	$_val = interprete_argument_balise(2, $p);
1500
	if (!$_nom or !$_val) {
1501
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SESSION_SET'));
1502
		erreur_squelette($err_b_s_a, $p);
1503
	} else {
1504
		$p->code = '(include_spip("inc/session") AND session_set(' . $_nom . ',' . $_val . '))';
1505
	}
1506
1507
	$p->interdire_scripts = false;
1508
1509
	return $p;
1510
}
1511
1512
1513
/**
1514
 * Compile la balise `#EVAL` qui évalue un code PHP
1515
 *
1516
 * À utiliser avec précautions !
1517
 *
1518
 * @balise
1519
 * @link http://www.spip.net/4587
1520
 * @example
1521
 *     ```
1522
 *     #EVAL{6+9}
1523
 *     #EVAL{'date("Y-m-d")'}
1524
 *     #EVAL{$_SERVER['REQUEST_URI']}
1525
 *     #EVAL{'str_replace("r","z", "roger")'}  (attention les "'" sont interdits)
1526
 *     ```
1527
 *
1528
 * @note
1529
 *     `#EVAL{code}` produit `eval('return code;')`
1530
 *      mais si le code est une expression sans balise, on se dispense
1531
 *      de passer par une construction si compliquée, et le code est
1532
 *      passé tel quel (entre parenthèses, et protégé par interdire_scripts)
1533
 *
1534
 * @param Champ $p
1535
 *     Pile au niveau de la balise.
1536
 * @return Champ
1537
 *     Pile completée du code PHP d'exécution de la balise
1538
 **/
1539
function balise_EVAL_dist($p) {
1540
	$php = interprete_argument_balise(1, $p);
1541
	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...
1542
		# optimisation sur les #EVAL{une expression sans #BALISE}
1543
		# attention au commentaire "// x signes" qui precede
1544 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...
1545
			$php, $r)) {
1546
			$p->code = /* $r[1]. */
1547
				'(' . $r[2] . ')';
1548
		} else {
1549
			$p->code = "eval('return '.$php.';')";
1550
		}
1551
	} else {
1552
		$msg = array('zbug_balise_sans_argument', array('balise' => ' EVAL'));
1553
		erreur_squelette($msg, $p);
1554
	}
1555
1556
	#$p->interdire_scripts = true;
1557
1558
	return $p;
1559
}
1560
1561
1562
/**
1563
 * Compile la balise `#CHAMP_SQL` qui renvoie la valeur d'un champ SQL
1564
 *
1565
 * Signature : `#CHAMP_SQL{champ}`
1566
 *
1567
 * Cette balise permet de récupérer par exemple un champ `notes` dans une table
1568
 * SQL externe (impossible avec la balise `#NOTES` qui est une balise calculée).
1569
 *
1570
 * Ne permet pas de passer une expression comme argument, qui ne peut
1571
 * être qu'un texte statique !
1572
 *
1573
 * @balise
1574
 * @link http://www.spip.net/4041
1575
 * @see champ_sql()
1576
 * @example
1577
 *     ```
1578
 *     #CHAMP_SQL{notes}
1579
 *     ```
1580
 *
1581
 * @param Champ $p
1582
 *     Pile au niveau de la balise
1583
 * @return Champ
1584
 *     Pile complétée par le code à générer
1585
 **/
1586
function balise_CHAMP_SQL_dist($p) {
1587
1588
	if ($p->param
1589
		and isset($p->param[0][1][0])
1590
		and $champ = ($p->param[0][1][0]->texte)
1591
	) {
1592
		$p->code = champ_sql($champ, $p);
1593
	} else {
1594
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => ' CHAMP_SQL'));
1595
		erreur_squelette($err_b_s_a, $p);
1596
	}
1597
1598
	#$p->interdire_scripts = true;
1599
	return $p;
1600
}
1601
1602
/**
1603
 * Compile la balise `#VAL` qui retourne simplement le premier argument
1604
 * qui lui est transmis
1605
 *
1606
 * Cela permet d'appliquer un filtre à une chaîne de caractère
1607
 *
1608
 * @balise
1609
 * @link http://www.spip.net/4026
1610
 * @example
1611
 *     ```
1612
 *     #VAL retourne ''
1613
 *     #VAL{x} retourne 'x'
1614
 *     #VAL{1,2} renvoie '1' (2 est considéré comme un autre paramètre)
1615
 *     #VAL{'1,2'} renvoie '1,2'
1616
 *     [(#VAL{a_suivre}|bouton_spip_rss)]
1617
 *     ```
1618
 *
1619
 * @param Champ $p
1620
 *     Pile au niveau de la balise
1621
 * @return Champ
1622
 *     Pile complétée par le code à générer
1623
 **/
1624
function balise_VAL_dist($p) {
1625
	$p->code = interprete_argument_balise(1, $p);
1626
	if (!strlen($p->code)) {
1627
		$p->code = "''";
1628
	}
1629
	$p->interdire_scripts = false;
1630
1631
	return $p;
1632
}
1633
1634
/**
1635
 * Compile la balise `#NOOP`, alias (déprécié) de `#VAL`
1636
 *
1637
 * Alias pour regler #948. Ne plus utiliser.
1638
 *
1639
 * @balise
1640
 * @see balise_VAL_dist()
1641
 * @deprecated Utiliser #VAL
1642
 *
1643
 * @param Champ $p
1644
 *     Pile au niveau de la balise
1645
 * @return Champ
1646
 *     Pile complétée par le code à générer
1647
 **/
1648
function balise_NOOP_dist($p) { return balise_VAL_dist($p); }
1649
1650
1651
/**
1652
 * Compile la balise `#REM` servant à commenter du texte
1653
 *
1654
 * Retourne toujours une chaîne vide.
1655
 *
1656
 * @balise
1657
 * @link http://www.spip.net/4578
1658
 * @example
1659
 *     ```
1660
 *     [(#REM)
1661
 *       Ceci est une remarque ou un commentaire,
1662
 *       non affiché dans le code généré
1663
 *     ]
1664
 *     ```
1665
 *
1666
 * @note
1667
 *     La balise `#REM` n'empêche pas l'exécution des balises SPIP contenues
1668
 *     dedans (elle ne sert pas à commenter du code pour empêcher son
1669
 *     exécution).
1670
 *
1671
 * @param Champ $p
1672
 *     Pile au niveau de la balise
1673
 * @return Champ
1674
 *     Pile complétée par le code à générer
1675
 **/
1676
function balise_REM_dist($p) {
1677
	$p->code = "''";
1678
	$p->interdire_scripts = false;
1679
1680
	return $p;
1681
}
1682
1683
1684
/**
1685
 * Compile la balise `#HTTP_HEADER` envoyant des entêtes de retour HTTP
1686
 *
1687
 * Doit être placée en tête de fichier et ne fonctionne pas dans une
1688
 * inclusion.
1689
 *
1690
 * @balise
1691
 * @link http://www.spip.net/4631
1692
 * @example
1693
 *     ```
1694
 *     #HTTP_HEADER{Content-Type: text/csv; charset=#CHARSET}
1695
 *     ```
1696
 *
1697
 * @param Champ $p
1698
 *     Pile au niveau de la balise
1699
 * @return Champ
1700
 *     Pile complétée par le code à générer
1701
 **/
1702 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...
1703
1704
	$header = interprete_argument_balise(1, $p);
1705
	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...
1706
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'HTTP_HEADER'));
1707
		erreur_squelette($err_b_s_a, $p);
1708
	} else {
1709
		$p->code = "'<'.'?php header(' . _q("
1710
			. $header
1711
			. ") . '); ?'.'>'";
1712
	}
1713
	$p->interdire_scripts = false;
1714
1715
	return $p;
1716
}
1717
1718
1719
/**
1720
 * Compile la balise `#FILTRE` qui exécute un filtre à l'ensemble du squelette
1721
 * une fois calculé.
1722
 *
1723
 * Le filtrage se fait au niveau du squelette, sans s'appliquer aux `<INCLURE>`.
1724
 * Plusieurs filtres peuvent être indiqués, séparés par des barres verticales `|`
1725
 *
1726
 * @balise
1727
 * @link http://www.spip.net/4894
1728
 * @example
1729
 *     ```
1730
 *     #FILTRE{compacte_head}
1731
 *     #FILTRE{supprimer_tags|filtrer_entites|trim}
1732
 *     ```
1733
 *
1734
 * @param Champ $p
1735
 *     Pile au niveau de la balise
1736
 * @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...
1737
 *     Pile complétée par le code à générer
1738
 **/
1739
function balise_FILTRE_dist($p) {
1740
	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...
1741
		$args = array();
1742
		foreach ($p->param as $i => $ignore) {
1743
			$args[] = interprete_argument_balise($i + 1, $p);
1744
		}
1745
		$p->code = "'<' . '"
1746
			. '?php header("X-Spip-Filtre: \'.'
1747
			. join('.\'|\'.', $args)
1748
			. " . '\"); ?'.'>'";
1749
1750
		$p->interdire_scripts = false;
1751
1752
		return $p;
1753
	}
1754
}
1755
1756
1757
/**
1758
 * Compile la balise `#CACHE` definissant la durée de validité du cache du squelette
1759
 *
1760
 * Signature : `#CACHE{duree[,type]}`
1761
 *
1762
 * Le premier argument est la durée en seconde du cache. Le second
1763
 * (par défaut `statique`) indique le type de cache :
1764
 *
1765
 * - `cache-client` autorise gestion du IF_MODIFIED_SINCE
1766
 * - `statique` ne respecte pas l'invalidation par modif de la base
1767
 *   (mais s'invalide tout de même à l'expiration du delai)
1768
 *
1769
 * @balise
1770
 * @see ecrire/public/cacher.php
1771
 * @link http://www.spip.net/4330
1772
 * @example
1773
 *     ```
1774
 *     #CACHE{24*3600}
1775
 *     #CACHE{24*3600, cache-client}
1776
 *     #CACHE{0} pas de cache
1777
 *     ```
1778
 * @note
1779
 *   En absence de cette balise la durée est du cache est donné
1780
 *   par la constante `_DUREE_CACHE_DEFAUT`
1781
 *
1782
 * @param Champ $p
1783
 *     Pile au niveau de la balise
1784
 * @return Champ
1785
 *     Pile complétée par le code à générer
1786
 **/
1787
function balise_CACHE_dist($p) {
1788
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
		$duree = valeur_numerique($p->param[0][1][0]->texte);
1791
1792
		// noter la duree du cache dans un entete proprietaire
1793
1794
		$code = "'<'.'" . '?php header("X-Spip-Cache: '
1795
			. $duree
1796
			. '"); ?' . "'.'>'";
1797
1798
		// Remplir le header Cache-Control
1799
		// cas #CACHE{0}
1800
		if ($duree == 0) {
1801
			$code .= ".'<'.'"
1802
				. '?php header("Cache-Control: no-cache, must-revalidate"); ?'
1803
				. "'.'><'.'"
1804
				. '?php header("Pragma: no-cache"); ?'
1805
				. "'.'>'";
1806
		}
1807
1808
		// recuperer les parametres suivants
1809
		$i = 1;
1810
		while (isset($p->param[0][++$i])) {
1811
			$pa = ($p->param[0][$i][0]->texte);
1812
1813
			if ($pa == 'cache-client'
1814
				and $duree > 0
1815
			) {
1816
				$code .= ".'<'.'" . '?php header("Cache-Control: max-age='
1817
					. $duree
1818
					. '"); ?' . "'.'>'";
1819
				// il semble logique, si on cache-client, de ne pas invalider
1820
				$pa = 'statique';
1821
			}
1822
1823
			if ($pa == 'statique'
1824
				and $duree > 0
1825
			) {
1826
				$code .= ".'<'.'" . '?php header("X-Spip-Statique: oui"); ?' . "'.'>'";
1827
			}
1828
		}
1829
	} else {
1830
		$code = "''";
1831
	}
1832
	$p->code = $code;
1833
	$p->interdire_scripts = false;
1834
1835
	return $p;
1836
}
1837
1838
1839
/**
1840
 * Compile la balise `#INSERT_HEAD` permettant d'insérer du contenu dans
1841
 * le `<head>` d'une page HTML
1842
 *
1843
 * La balise permet aux plugins d'insérer des styles, js ou autre
1844
 * dans l'entête sans modification du squelette.
1845
 * Les css doivent être inserées de préférence par `#INSERT_HEAD_CSS`
1846
 * pour en faciliter la surcharge.
1847
 *
1848
 * On insère ici aussi un morceau de PHP qui verifiera à l'exécution
1849
 * que le pipeline `insert_head_css` a bien été vu
1850
 * et dans le cas contraire l'appelera. Ceal permet de ne pas oublier
1851
 * les css de `#INSERT_HEAD_CSS` même si cette balise n'est pas presente.
1852
 *
1853
 * Il faut mettre ce php avant le `insert_head` car le compresseur y mets
1854
 * ensuite un php du meme type pour collecter
1855
 * CSS et JS, et on ne veut pas qu'il rate les css insérées en fallback
1856
 * par `insert_head_css_conditionnel`.
1857
 *
1858
 * @link http://www.spip.net/4629
1859
 * @see balise_INSERT_HEAD_CSS_dist()
1860
 *
1861
 * @param Champ $p
1862
 *     Pile au niveau de la balise
1863
 * @return Champ
1864
 *     Pile complétée par le code à générer
1865
 */
1866
function balise_INSERT_HEAD_dist($p) {
1867
	$p->code = "'<'.'"
1868
		. '?php header("X-Spip-Filtre: insert_head_css_conditionnel"); ?'
1869
		. "'.'>'";
1870
	$p->code .= ". pipeline('insert_head','<!-- insert_head -->')";
1871
	$p->interdire_scripts = false;
1872
1873
	return $p;
1874
}
1875
1876
/**
1877
 * Compile la balise `#INSERT_HEAD_CSS` homologue de `#INSERT_HEAD` pour les CSS
1878
 *
1879
 * Et par extension pour le JS inline qui doit préférentiellement
1880
 * être inséré avant les CSS car bloquant sinon.
1881
 *
1882
 * @link http://www.spip.net/4605
1883
 * @see balise_INSERT_HEAD_dist()
1884
 *
1885
 * @param Champ $p
1886
 *     Pile au niveau de la balise
1887
 * @return Champ
1888
 *     Pile complétée par le code à générer
1889
 */
1890
function balise_INSERT_HEAD_CSS_dist($p) {
1891
	$p->code = "pipeline('insert_head_css','<!-- insert_head_css -->')";
1892
	$p->interdire_scripts = false;
1893
1894
	return $p;
1895
}
1896
1897
/**
1898
 * Compile la balise `#INCLUDE` alias de `#INCLURE`
1899
 *
1900
 * @balise
1901
 * @see balise_INCLURE_dist()
1902
 *
1903
 * @param Champ $p
1904
 *     Pile au niveau de la balise
1905
 * @return Champ
1906
 *     Pile complétée par le code à générer
1907
 **/
1908
function balise_INCLUDE_dist($p) {
1909
	if (function_exists('balise_INCLURE')) {
1910
		return balise_INCLURE($p);
1911
	} else {
1912
		return balise_INCLURE_dist($p);
1913
	}
1914
}
1915
1916
/**
1917
 * Compile la balise `#INCLURE` qui inclut un résultat de squelette
1918
 *
1919
 * Signature : `[(#INCLURE{fond=nom_du_squelette, argument, argument=xx})]`
1920
 *
1921
 * L'argument `env` permet de transmettre tout l'environnement du squelette
1922
 * en cours au squelette inclus.
1923
 *
1924
 * On parle d’inclusion « statique » car le résultat de compilation est
1925
 * ajouté au squelette en cours, dans le même fichier de cache.
1926
 * Cette balise est donc différente d’une inclusion « dynamique » avec
1927
 * `<INCLURE.../>` qui, elle, crée un fichier de cache séparé
1928
 * (avec une durée de cache qui lui est propre).
1929
 *
1930
 * L'inclusion est realisée au calcul du squelette, pas au service
1931
 * ainsi le produit du squelette peut être utilisé en entrée de filtres
1932
 * à suivre. On peut faire un `#INCLURE{fichier}` sans squelette
1933
 * (Incompatible avec les balises dynamiques).
1934
 *
1935
 * @balise
1936
 * @example
1937
 *     ```
1938
 *     [(#INCLURE{fond=inclure/documents,id_article, env})]
1939
 *     ```
1940
 *
1941
 * @param Champ $p
1942
 *     Pile au niveau de la balise
1943
 * @return Champ
1944
 *     Pile complétée par le code à générer
1945
 **/
1946
function balise_INCLURE_dist($p) {
1947
	$id_boucle = $p->id_boucle;
1948
	// la lang n'est pas passe de facon automatique par argumenter
1949
	// mais le sera pas recuperer_fond, sauf si etoile=>true est passe
1950
	// en option
1951
1952
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
1953
1954
	// erreur de syntaxe = fond absent
1955
	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
1956
	if (!$_contexte) {
1957
		$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...
1958
	}
1959
1960
	if (isset($_contexte['fond'])) {
1961
1962
		$f = $_contexte['fond'];
1963
		// toujours vrai :
1964
		if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
1965
			$f = $r[1];
1966
			unset($_contexte['fond']);
1967
		} else {
1968
			spip_log("compilation de #INCLURE a revoir");
1969
		}
1970
1971
		// #INCLURE{doublons}
1972
		if (isset($_contexte['doublons'])) {
1973
			$_contexte['doublons'] = "'doublons' => \$doublons";
1974
		}
1975
1976
		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
1977
		$flag_env = false;
1978 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...
1979
			$flag_env = true;
1980
			unset($_contexte['env']);
1981
		}
1982
1983
		$_options = array();
1984 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...
1985
			$_options[] = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
1986
			unset($_contexte['ajax']);
1987
		}
1988
		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...
1989
			$_options[] = "'etoile'=>true";
1990
		}
1991
		$_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) . ")";
1992
1993
		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
1994
		if ($flag_env) {
1995
			$_l = "array_merge(\$Pile[0],$_l)";
1996
		}
1997
1998
		$p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',', $_options), "_request('connect')");
1999
2000
	} elseif (!isset($_contexte[1])) {
2001
		$msg = array('zbug_balise_sans_argument', array('balise' => ' INCLURE'));
2002
		erreur_squelette($msg, $p);
2003
	} else {
2004
		$p->code = 'charge_scripts(' . $_contexte[1] . ',false)';
2005
	}
2006
2007
	$p->interdire_scripts = false; // la securite est assuree par recuperer_fond
2008
	return $p;
2009
}
2010
2011
2012
/**
2013
 * Compile la balise `#MODELE` qui inclut un résultat de squelette de modèle
2014
 *
2015
 * `#MODELE{nom}` insère le résultat d’un squelette contenu dans le
2016
 * répertoire `modeles/`. L’identifiant de la boucle parente est transmis
2017
 * par défaut avec le paramètre `id` à cette inclusion.
2018
 *
2019
 * Des arguments supplémentaires peuvent être transmis :
2020
 * `[(#MODELE{nom, argument=xx, argument})]`
2021
 *
2022
 * @balise
2023
 * @see balise_INCLURE_dist()
2024
 * @example
2025
 *     ```
2026
 *     #MODELE{article_traductions}
2027
 *     ```
2028
 *
2029
 * @param Champ $p
2030
 *     Pile au niveau de la balise
2031
 * @return Champ
2032
 *     Pile complétée par le code à générer
2033
 **/
2034
function balise_MODELE_dist($p) {
2035
2036
	$_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
2037
2038
	// erreur de syntaxe = fond absent
2039
	// (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
2040
	if (!$_contexte) {
2041
		$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...
2042
	}
2043
2044
	if (!isset($_contexte[1])) {
2045
		$msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
2046
		erreur_squelette($msg, $p);
2047
	} else {
2048
		$nom = $_contexte[1];
2049
		unset($_contexte[1]);
2050
2051
		if (preg_match("/^\s*'[^']*'/s", $nom)) {
2052
			$nom = "'modeles/" . substr($nom, 1);
2053
		} else {
2054
			$nom = "'modeles/' . $nom";
2055
		}
2056
2057
		$flag_env = false;
2058
		if (isset($_contexte['env'])) {
2059
			$flag_env = true;
2060
			unset($_contexte['env']);
2061
		}
2062
2063
		// Incoherence dans la syntaxe du contexte. A revoir.
2064
		// Reserver la cle primaire de la boucle courante si elle existe
2065
		if (isset($p->boucles[$p->id_boucle]->primary)) {
2066
			$primary = $p->boucles[$p->id_boucle]->primary;
2067
			if (!strpos($primary, ',')) {
2068
				$id = champ_sql($primary, $p);
2069
				$_contexte[] = "'$primary'=>" . $id;
2070
				$_contexte[] = "'id'=>" . $id;
2071
			}
2072
		}
2073
		$_contexte[] = "'recurs'=>(++\$recurs)";
2074
		$connect = '';
2075
		if (isset($p->boucles[$p->id_boucle])) {
2076
			$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2077
		}
2078
2079
		$_options = memoriser_contexte_compil($p);
2080
		$_options = "'compil'=>array($_options), 'trim'=>true";
2081 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...
2082
			$_options .= ", " . preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']);
2083
			unset($_contexte['ajax']);
2084
		}
2085
2086
		$_l = 'array(' . join(",\n\t", $_contexte) . ')';
2087
		if ($flag_env) {
2088
			$_l = "array_merge(\$Pile[0],$_l)";
2089
		}
2090
2091
		$page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect));
2092
2093
		$p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
2094
2095
		$p->interdire_scripts = false; // securite assuree par le squelette
2096
	}
2097
2098
	return $p;
2099
}
2100
2101
2102
/**
2103
 * Compile la balise `#SET` qui affecte une variable locale au squelette
2104
 *
2105
 * Signature : `#SET{cle,valeur}`
2106
 *
2107
 * @balise
2108
 * @link http://www.spip.net/3990 Balises #SET et #GET
2109
 * @see balise_GET_dist()
2110
 * @example
2111
 *     ```
2112
 *     #SET{nb,5}
2113
 *     #GET{nb} // affiche 5
2114
 *     ```
2115
 *
2116
 * @param Champ $p
2117
 *     Pile au niveau de la balise
2118
 * @return Champ
2119
 *     Pile complétée par le code à générer
2120
 **/
2121 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...
2122
	$_nom = interprete_argument_balise(1, $p);
2123
	$_val = interprete_argument_balise(2, $p);
2124
2125
	if (!$_nom or !$_val) {
2126
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SET'));
2127
		erreur_squelette($err_b_s_a, $p);
2128
	}
2129
	// affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4
2130
	// cf https://bugs.php.net/bug.php?id=65845
2131
	else {
2132
		$p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)";
2133
	}
2134
2135
	$p->interdire_scripts = false; // la balise ne renvoie rien
2136
	return $p;
2137
}
2138
2139
2140
/**
2141
 * Compile la balise `#GET` qui récupère une variable locale au squelette
2142
 *
2143
 * Signature : `#GET{cle[,defaut]}`
2144
 *
2145
 * La clé peut obtenir des sous clés séparés par des `/`
2146
 *
2147
 * @balise
2148
 * @link http://www.spip.net/3990 Balises #SET et #GET
2149
 * @see balise_SET_dist()
2150
 * @example
2151
 *     ```
2152
 *     #SET{nb,5}
2153
 *     #GET{nb} affiche 5
2154
 *     #GET{nb,3} affiche la valeur de nb, sinon 3
2155
 *
2156
 *     #SET{nb,#ARRAY{boucles,3}}
2157
 *     #GET{nb/boucles} affiche 3, équivalent à #GET{nb}|table_valeur{boucles}
2158
 *     ```
2159
 *
2160
 * @param Champ $p
2161
 *     Pile au niveau de la balise
2162
 * @return Champ
2163
 *     Pile complétée par le code à générer
2164
 **/
2165
function balise_GET_dist($p) {
2166
	$p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
2167
	if (function_exists('balise_ENV')) {
2168
		return balise_ENV($p, '$Pile["vars"]');
2169
	} else {
2170
		return balise_ENV_dist($p, '$Pile["vars"]');
2171
	}
2172
}
2173
2174
2175
/**
2176
 * Compile la balise `#DOUBLONS` qui redonne les doublons enregistrés
2177
 *
2178
 * - `#DOUBLONS{mots}` ou `#DOUBLONS{mots,famille}`
2179
 *   donne l'état des doublons `(MOTS)` à cet endroit
2180
 *   sous forme de tableau d'id_mot comme `array(1,2,3,...)`
2181
 * - `#DOUBLONS` tout seul donne la liste brute de tous les doublons
2182
 * - `#DOUBLONS*{mots}` donne la chaine brute `,1,2,3,...`
2183
 *   (changera si la gestion des doublons evolue)
2184
 *
2185
 * @balise
2186
 * @link http://www.spip.net/4123
2187
 *
2188
 * @param Champ $p
2189
 *     Pile au niveau de la balise
2190
 * @return Champ
2191
 *     Pile complétée par le code à générer
2192
 **/
2193
function balise_DOUBLONS_dist($p) {
2194
	if ($type = interprete_argument_balise(1, $p)) {
2195
		if ($famille = interprete_argument_balise(2, $p)) {
2196
			$type .= '.' . $famille;
2197
		}
2198
		$p->code = '(isset($doublons[' . $type . ']) ? $doublons[' . $type . '] : "")';
2199
		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...
2200
			$p->code = 'array_filter(array_map("intval",explode(",",'
2201
				. $p->code . ')))';
2202
		}
2203
	} else {
2204
		$p->code = '$doublons';
2205
	}
2206
2207
	$p->interdire_scripts = false;
2208
2209
	return $p;
2210
}
2211
2212
2213
/**
2214
 * Compile la balise `#PIPELINE` pour permettre d'insérer des sorties de
2215
 * pipeline dans un squelette
2216
 *
2217
 * @balise
2218
 * @see pipeline()
2219
 * @example
2220
 *     ```
2221
 *     #PIPELINE{nom}
2222
 *     #PIPELINE{nom,données}
2223
 *     #PIPELINE{boite_infos,#ARRAY{data,'',args,#ARRAY{type,rubrique,id,#ENV{id_rubrique}}}}
2224
 *     ```
2225
 *
2226
 * @param Champ $p
2227
 *     Pile au niveau de la balise
2228
 * @return Champ
2229
 *     Pile complétée par le code à générer
2230
 **/
2231 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...
2232
	$_pipe = interprete_argument_balise(1, $p);
2233
	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...
2234
		$err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'PIPELINE'));
2235
		erreur_squelette($err_b_s_a, $p);
2236
	} else {
2237
		$_flux = interprete_argument_balise(2, $p);
2238
		$_flux = $_flux ? $_flux : "''";
2239
		$p->code = "pipeline( $_pipe , $_flux )";
2240
		$p->interdire_scripts = false;
2241
	}
2242
2243
	return $p;
2244
}
2245
2246
2247
/**
2248
 * Compile la balise `#EDIT` qui ne fait rien dans SPIP
2249
 *
2250
 * Cette balise ne retourne rien mais permet d'indiquer, pour certains plugins
2251
 * qui redéfinissent cette balise, le nom du champ SQL (ou le nom d'un contrôleur)
2252
 * correspondant à ce qui est édité. Cela sert particulièrement au plugin Crayons.
2253
 * Ainsi en absence du plugin, la balise est toujours reconnue (mais n'a aucune action).
2254
 *
2255
 * @balise
2256
 * @link http://www.spip.net/4584
2257
 * @example
2258
 *     ```
2259
 *     [<div class="#EDIT{texte} texte">(#TEXTE)</div>]
2260
 *     ```
2261
 *
2262
 * @param Champ $p
2263
 *     Pile au niveau de la balise
2264
 * @return Champ
2265
 *     Pile complétée par le code à générer
2266
 **/
2267
function balise_EDIT_dist($p) {
2268
	$p->code = "''";
2269
	$p->interdire_scripts = false;
2270
2271
	return $p;
2272
}
2273
2274
2275
/**
2276
 * Compile la balise `#TOTAL_UNIQUE` qui récupère le nombre d'éléments
2277
 * différents affichés par le filtre `unique`
2278
 *
2279
 * @balise
2280
 * @link http://www.spip.net/4374
2281
 * @see unique()
2282
 * @example
2283
 *     ```
2284
 *     #TOTAL_UNIQUE affiche le nombre de #BALISE|unique
2285
 *     #TOTAL_UNIQUE{famille} afiche le nombre de #BALISE|unique{famille}
2286
 *     ```
2287
 *
2288
 * @param Champ $p
2289
 *     Pile au niveau de la balise
2290
 * @return Champ
2291
 *     Pile complétée par le code à générer
2292
 **/
2293
function balise_TOTAL_UNIQUE_dist($p) {
2294
	$_famille = interprete_argument_balise(1, $p);
2295
	$_famille = $_famille ? $_famille : "''";
2296
	$p->code = "unique('', $_famille, true)";
2297
2298
	return $p;
2299
}
2300
2301
/**
2302
 * Compile la balise `#ARRAY` créant un tableau PHP associatif
2303
 *
2304
 * Crée un `array` PHP à partir d'arguments calculés.
2305
 * Chaque paire d'arguments représente la clé et la valeur du tableau.
2306
 *
2307
 * @balise
2308
 * @link http://www.spip.net/4009
2309
 * @example
2310
 *     ```
2311
 *     #ARRAY{key1,val1,key2,val2 ...} retourne
2312
 *     array( key1 => val1, key2 => val2, ...)
2313
 *     ```
2314
 *
2315
 * @param Champ $p
2316
 *     Pile au niveau de la balise
2317
 * @return Champ
2318
 *     Pile complétée par le code à générer
2319
 **/
2320
function balise_ARRAY_dist($p) {
2321
	$_code = array();
2322
	$n = 1;
2323
	do {
2324
		$_key = interprete_argument_balise($n++, $p);
2325
		$_val = interprete_argument_balise($n++, $p);
2326
		if ($_key and $_val) {
2327
			$_code[] = "$_key => $_val";
2328
		}
2329
	} 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...
2330
	$p->code = 'array(' . join(', ', $_code) . ')';
2331
	$p->interdire_scripts = false;
2332
2333
	return $p;
2334
}
2335
2336
/**
2337
 * Compile la balise `#LISTE` qui crée un tableau PHP avec les valeurs, sans préciser les clés
2338
 *
2339
 * @balise
2340
 * @link http://www.spip.net/5547
2341
 * @example
2342
 *    ```
2343
 *    #LISTE{a,b,c,d,e}
2344
 *    ```
2345
 *
2346
 * @param Champ $p
2347
 *     Pile au niveau de la balise
2348
 * @return Champ
2349
 *     Pile complétée par le code à générer
2350
 */
2351 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...
2352
	$_code = array();
2353
	$n = 1;
2354
	while ($_val = interprete_argument_balise($n++, $p)) {
2355
		$_code[] = $_val;
2356
	}
2357
	$p->code = 'array(' . join(', ', $_code) . ')';
2358
	$p->interdire_scripts = false;
2359
2360
	return $p;
2361
}
2362
2363
2364
/**
2365
 * Compile la balise `#AUTORISER` qui teste une autorisation
2366
 *
2367
 * Appelle la fonction `autoriser()` avec les mêmes arguments,
2368
 * et renvoie un espace ' ' si OK (l'action est autorisée),
2369
 * sinon une chaine vide '' (l'action n'est pas autorisée).
2370
 *
2371
 * Cette balise créée un cache par session.
2372
 *
2373
 * Signature : `#AUTORISER{faire[,type[,id[,auteur[,options]]]}`
2374
 *
2375
 * @note
2376
 *     La priorité des opérateurs exige && plutot que AND
2377
 *
2378
 * @balise
2379
 * @link http://www.spip.net/3896
2380
 * @see autoriser()
2381
 * @see sinon_interdire_acces()
2382
 * @example
2383
 *    ```
2384
 *    [(#AUTORISER{modifier,rubrique,#ID_RUBRIQUE}) ... ]
2385
 *    [(#AUTORISER{voir,rubrique,#ID_RUBRIQUE}|sinon_interdire_acces)]
2386
 *    ```
2387
 *
2388
 * @param Champ $p
2389
 *     Pile au niveau de la balise
2390
 * @return Champ
2391
 *     Pile complétée par le code à générer
2392
 **/
2393 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...
2394
	$_code = array();
2395
	$p->descr['session'] = true; // faire un cache par session
2396
2397
	$n = 1;
2398
	while ($_v = interprete_argument_balise($n++, $p)) {
2399
		$_code[] = $_v;
2400
	}
2401
2402
	$p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(', ',
2403
			$_code) . ')?" ":"")';
2404
	$p->interdire_scripts = false;
2405
2406
	return $p;
2407
}
2408
2409
2410
/**
2411
 * Compile la balise `#PLUGIN` qui permet d’afficher les informations d'un plugin actif
2412
 *
2413
 * @balise
2414
 * @see filtre_info_plugin_dist()
2415
 * @link http://www.spip.net/4591
2416
 * @example
2417
 *     ```
2418
 *     #PLUGIN Retourne la liste sérialisée des préfixes de plugins actifs
2419
 *     #PLUGIN{prefixe} Renvoie true si le plugin avec ce préfixe est actif
2420
 *     #PLUGIN{prefixe, x} Renvoie l'information x du plugin (s'il est actif)
2421
 *     #PLUGIN{prefixe, tout} Renvoie toutes les informations du plugin (s'il est actif)
2422
 *     ```
2423
 *
2424
 * @param Champ $p
2425
 *     Pile au niveau de la balise
2426
 * @return Champ
2427
 *     Pile complétée par le code à générer
2428
 **/
2429
function balise_PLUGIN_dist($p) {
2430
	$plugin = interprete_argument_balise(1, $p);
2431
	$plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
2432
	$type_info = interprete_argument_balise(2, $p);
2433
	$type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
2434
2435
	$f = chercher_filtre('info_plugin');
2436
	$p->code = $f . '(' . $plugin . ', ' . $type_info . ')';
2437
2438
	return $p;
2439
}
2440
2441
/**
2442
 * Compile la balise `#AIDER` qui permet d’afficher l’icone de l’aide
2443
 * au sein des squelettes.
2444
 *
2445
 * @balise
2446
 * @see inc_aide_dist()
2447
 * @link http://www.spip.net/4733
2448
 * @example
2449
 *     ```
2450
 *     #AIDER{titre}
2451
 *     ```
2452
 *
2453
 * @param Champ $p
2454
 *     Pile au niveau de la balise
2455
 * @return Champ
2456
 *     Pile complétée par le code à générer
2457
 **/
2458
function balise_AIDER_dist($p) {
2459
	$_motif = interprete_argument_balise(1, $p);
2460
	$s = "'" . addslashes($p->descr['sourcefile']) . "'";
2461
	$p->code = "((\$aider=charger_fonction('aide','inc',true))?\$aider($_motif,$s, \$Pile[0]):'')";
2462
2463
	return $p;
2464
}
2465
2466
/**
2467
 * Compile la balise `#ACTION_FORMULAIRE` qui insère le contexte
2468
 * des formulaires charger / vérifier / traiter avec les hidden de
2469
 * l'URL d'action
2470
 *
2471
 * Accèpte 2 arguments optionnels :
2472
 * - L'url de l'action (par défaut `#ENV{action}`
2473
 * - Le nom du formulaire (par défaut `#ENV{form}`
2474
 *
2475
 * @balise
2476
 * @see form_hidden()
2477
 * @example
2478
 *     ```
2479
 *     <form method='post' action='#ENV{action}'><div>
2480
 *     #ACTION_FORMULAIRE
2481
 *     ```
2482
 *
2483
 * @param Champ $p
2484
 *     Pile au niveau de la balise
2485
 * @return Champ
2486
 *     Pile complétée par le code à générer
2487
 **/
2488
function balise_ACTION_FORMULAIRE($p) {
2489
	if (!$_url = interprete_argument_balise(1, $p)) {
2490
		$_url = "@\$Pile[0]['action']";
2491
	}
2492
	if (!$_form = interprete_argument_balise(2, $p)) {
2493
		$_form = "@\$Pile[0]['form']";
2494
	}
2495
2496
	// envoyer le nom du formulaire que l'on traite
2497
	// transmettre les eventuels args de la balise formulaire
2498
	$p->code = "	'<div>' .
2499
	form_hidden($_url) .
2500
	'<input name=\'formulaire_action\' type=\'hidden\'
2501
		value=\'' . $_form . '\' />' .
2502
	'<input name=\'formulaire_action_args\' type=\'hidden\'
2503
		value=\'' . @\$Pile[0]['formulaire_args']. '\' />' .
2504
	(!empty(\$Pile[0]['_hidden']) ? @\$Pile[0]['_hidden'] : '') .
2505
	'</div>'";
2506
2507
	$p->interdire_scripts = false;
2508
2509
	return $p;
2510
}
2511
2512
2513
/**
2514
 * Compile la balise `#BOUTON_ACTION` qui génère un bouton d'action en post, ajaxable
2515
 *
2516
 * Cette balise s'utilise à la place des liens `action_auteur`, sous la forme
2517
 *
2518
 * - `#BOUTON_ACTION{libelle,url}`
2519
 * - ou `#BOUTON_ACTION{libelle,url,ajax}` pour que l'action soit ajax comme un lien `class='ajax'`
2520
 * - ou `#BOUTON_ACTION{libelle,url,ajax,message_confirmation}` pour utiliser un message de confirmation
2521
 * - ou encore `#BOUTON_ACTION{libelle[,url[,ajax[,message_confirmation[,title[,callback]]]]]}`
2522
 *
2523
 * @balise
2524
 * @link http://www.spip.net/4583
2525
 * @example
2526
 *     ```
2527
 *     [(#AUTORISER{reparer,base})
2528
 *        [(#BOUTON_ACTION{<:bouton_tenter_recuperation:>,#URL_ECRIRE{base_repair}})]
2529
 *     ]
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_BOUTON_ACTION_dist($p) {
2538
2539
	$args = array();
2540
	for ($k = 1; $k <= 6; $k++) {
2541
		$_a = interprete_argument_balise($k, $p);
2542
		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...
2543
			$_a = "''";
2544
		}
2545
		$args[] = $_a;
2546
	}
2547
	// supprimer les args vides
2548
	while (end($args) == "''" and count($args) > 2) {
2549
		array_pop($args);
2550
	}
2551
	$args = implode(",", $args);
2552
2553
	$bouton_action = chercher_filtre("bouton_action");
2554
	$p->code = "$bouton_action($args)";
2555
	$p->interdire_scripts = false;
2556
2557
	return $p;
2558
}
2559
2560
2561
/**
2562
 * Compile la balise `#SLOGAN_SITE_SPIP` qui retourne le slogan du site
2563
 *
2564
 * @balise
2565
 * @example
2566
 *     ```
2567
 *     [<p id="slogan">(#SLOGAN_SITE_SPIP)</p>]
2568
 *     ```
2569
 *
2570
 * @param Champ $p
2571
 *     Pile au niveau de la balise
2572
 * @return Champ
2573
 *     Pile complétée par le code à générer
2574
 */
2575
function balise_SLOGAN_SITE_SPIP_dist($p) {
2576
	$p->code = "\$GLOBALS['meta']['slogan_site']";
2577
2578
	#$p->interdire_scripts = true;
2579
	return $p;
2580
}
2581
2582
2583
/**
2584
 * Compile la balise `#HTML5` indiquant si l'espace public peut utiliser du HTML5
2585
 *
2586
 * Renvoie `' '` si le webmestre souhaite que SPIP génère du code (X)HTML5 sur
2587
 * le site public, et `''` si le code doit être strictement compatible HTML4
2588
 *
2589
 * @balise
2590
 * @uses html5_permis()
2591
 * @example
2592
 *     ```
2593
 *     [(#HTML5) required="required"]
2594
 *     <input[ (#HTML5|?{type="email",type="text"})] ... />
2595
 *     ```
2596
 *
2597
 * @param Champ $p
2598
 *     Pile au niveau de la balise
2599
 * @return Champ
2600
 *     Pile complétée par le code à générer
2601
 */
2602
function balise_HTML5_dist($p) {
2603
	$p->code = html5_permis() ? "' '" : "''";
2604
	$p->interdire_scripts = false;
2605
2606
	return $p;
2607
}
2608
2609
2610
/**
2611
 * Compile la balise `#TRI` permettant d'afficher un lien de changement d'ordre de tri
2612
 * d'une colonne de la boucle
2613
 *
2614
 * La balise `#TRI{champ[,libelle]}` champ prend `>` ou `<` pour afficher
2615
 * le lien de changement de sens croissant ou decroissant (`>` `<` indiquent
2616
 * un sens par une flèche)
2617
 *
2618
 * @balise
2619
 * @example
2620
 *     ```
2621
 *     <th>[(#TRI{titre,<:info_titre:>,ajax})]</th>
2622
 *     ```
2623
 *
2624
 * @param Champ $p
2625
 *     Pile au niveau de la balise
2626
 * @param string $liste
2627
 *     Inutilisé
2628
 * @return Champ
2629
 *     Pile complétée par le code à générer
2630
 */
2631
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...
2632
	$b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
2633
2634
	// s'il n'y a pas de nom de boucle, on ne peut pas trier
2635 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...
2636
		erreur_squelette(
2637
			_T('zbug_champ_hors_boucle',
2638
				array('champ' => '#TRI')
2639
			), $p->id_boucle);
2640
		$p->code = "''";
2641
2642
		return $p;
2643
	}
2644
	$boucle = $p->boucles[$b];
2645
2646
	// s'il n'y a pas de tri_champ, c'est qu'on se trouve
2647
	// dans un boucle recursive ou qu'on a oublie le critere {tri}
2648 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...
2649
		erreur_squelette(
2650
			_T('zbug_tri_sans_critere',
2651
				array('champ' => '#TRI')
2652
			), $p->id_boucle);
2653
		$p->code = "''";
2654
2655
		return $p;
2656
	}
2657
2658
	$_champ = interprete_argument_balise(1, $p);
2659
	// si pas de champ, renvoyer le critere de tri utilise
2660
	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...
2661
		$p->code = $boucle->modificateur['tri_champ'];
2662
2663
		return $p;
2664
	}
2665
	// forcer la jointure si besoin, et si le champ est statique
2666
	if (preg_match(",^'([\w.]+)'$,i", $_champ, $m)) {
2667
		index_pile($b, $m[1], $p->boucles, '', null, true, false);
2668
	}
2669
2670
	$_libelle = interprete_argument_balise(2, $p);
2671
	$_libelle = $_libelle ? $_libelle : $_champ;
2672
2673
	$_class = interprete_argument_balise(3, $p);
2674
	// si champ = ">" c'est un lien vers le tri croissant : de gauche a droite ==> 1
2675
	// si champ = "<" c'est un lien vers le tri decroissant : (sens inverse) == -1
2676
	$_issens = "in_array($_champ,array('>','<'))";
2677
	$_sens = "(strpos('< >',$_champ)-1)";
2678
2679
	$_variable = "((\$s=$_issens)?'sens':'tri')." . $boucle->modificateur['tri_nom'];
2680
	$_url = "parametre_url(self(),$_variable,\$s?$_sens:$_champ)";
2681
	$_url = "parametre_url($_url,'var_memotri',strncmp(" . $boucle->modificateur['tri_nom'] . ",'session',7)==0?$_variable:'')";
2682
	$_on = "\$s?(" . $boucle->modificateur['tri_sens'] . "==$_sens" . '):(' . $boucle->modificateur['tri_champ'] . "==$_champ)";
2683
2684
	$p->code = "lien_ou_expose($_url,$_libelle,$_on" . ($_class ? ",$_class" : "") . ")";
2685
	//$p->code = "''";
2686
	$p->interdire_scripts = false;
2687
2688
	return $p;
2689
}
2690
2691
2692
/**
2693
 * Compile la balise `#SAUTER{n}` qui permet de sauter en avant n resultats dans une boucle
2694
 *
2695
 * La balise modifie le compteur courant de la boucle, mais pas les autres
2696
 * champs qui restent les valeurs de la boucle avant le saut. Il est donc
2697
 * preferable d'utiliser la balise juste avant la fermeture `</BOUCLE>`
2698
 *
2699
 * L'argument `n` doit être supérieur à zéro sinon la balise ne fait rien
2700
 *
2701
 * @balise
2702
 *
2703
 * @param Champ $p
2704
 *     Pile au niveau de la balise
2705
 * @return Champ
2706
 *     Pile complétée par le code à générer
2707
 */
2708
function balise_SAUTER_dist($p) {
2709
	$id_boucle = $p->id_boucle;
2710
2711
	if (empty($p->boucles[$id_boucle])) {
2712
		$msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER'));
2713
		erreur_squelette($msg, $p);
2714
	} else {
2715
		$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...
2716
		$_saut = interprete_argument_balise(1, $p);
2717
		$_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
2718
		$_total = "\$Numrows['$id_boucle']['total']";
2719
2720
		$p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
2721
	}
2722
	$p->interdire_scripts = false;
2723
2724
	return $p;
2725
}
2726
2727
2728
/**
2729
 * Compile la balise `#PUBLIE` qui indique si un objet est publié ou non
2730
 *
2731
 * @balise
2732
 * @link http://www.spip.net/5545
2733
 * @see objet_test_si_publie()
2734
 * @example
2735
 *     ```
2736
 *     #PUBLIE : porte sur la boucle en cours
2737
 *     [(#PUBLIE{article, 3}|oui) ... ] : pour l'objet indiqué
2738
 *     ```
2739
 *
2740
 * @param Champ $p
2741
 *     Pile au niveau de la balise
2742
 * @return Champ
2743
 *     Pile complétée par le code à générer
2744
 */
2745
function balise_PUBLIE_dist($p) {
2746
	if (!$_type = interprete_argument_balise(1, $p)) {
2747
		$_type = _q($p->type_requete);
2748
		$_id = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
2749
	} else {
2750
		$_id = interprete_argument_balise(2, $p);
2751
	}
2752
2753
	$connect = '';
2754
	if (isset($p->boucles[$p->id_boucle])) {
2755
		$connect = $p->boucles[$p->id_boucle]->sql_serveur;
2756
	}
2757
2758
	$p->code = "(objet_test_si_publie(" . $_type . ",intval(" . $_id . ")," . _q($connect) . ")?' ':'')";
2759
	$p->interdire_scripts = false;
2760
2761
	return $p;
2762
}
2763
2764
/**
2765
 * Compile la balise `#PRODUIRE` qui génère un fichier statique à partir
2766
 * d'un squelette SPIP
2767
 *
2768
 * Le format du fichier sera extrait de la pre-extension du squelette
2769
 * (typo.css.html, messcripts.js.html)
2770
 * ou par l'argument `format=css` ou `format=js` passé en argument.
2771
 *
2772
 * S'il n'y a pas de format détectable, on utilise `.html`, comme pour les squelettes.
2773
 *
2774
 * La syntaxe de la balise est la même que celle de `#INCLURE`.
2775
 *
2776
 * @balise
2777
 * @see balise_INCLURE_dist()
2778
 * @link http://www.spip.net/5505
2779
 * @example
2780
 *     ```
2781
 *     <link rel="stylesheet" type="text/css" href="#PRODUIRE{fond=css/macss.css,couleur=ffffff}" />
2782
 *     ```
2783
 *
2784
 * @param Champ $p
2785
 *     Pile au niveau de la balise
2786
 * @return Champ
2787
 *     Pile complétée par le code à générer
2788
 */
2789
function balise_PRODUIRE_dist($p) {
2790
	$balise_inclure = charger_fonction('INCLURE', 'balise');
2791
	$p = $balise_inclure($p);
2792
2793
	$p->code = str_replace('recuperer_fond(', 'produire_fond_statique(', $p->code);
2794
2795
	return $p;
2796
}
2797
2798
/**
2799
 * Compile la balise `#LARGEUR_ECRAN` qui définit la largeur d'écran
2800
 * dans l'espace privé
2801
 *
2802
 * @balise
2803
 * @example
2804
 *     ```
2805
 *     #LARGEUR_ECRAN{pleine_largeur}
2806
 *     ```
2807
 *
2808
 * @param Champ $p
2809
 *     Pile au niveau de la balise
2810
 * @return Champ
2811
 *     Pile complétée par le code à générer
2812
 */
2813
function balise_LARGEUR_ECRAN_dist($p) {
2814
	$_class = interprete_argument_balise(1, $p);
2815
	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...
2816
		$_class = 'null';
2817
	}
2818
	$p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))";
2819
2820
	return $p;
2821
}
2822
2823
2824
/**
2825
 * Compile la balise `#CONST` qui retourne la valeur de la constante passée en argument
2826
 *
2827
 * @balise
2828
 * @example `#CONST{_DIR_IMG}`
2829
 *
2830
 * @param Champ $p
2831
 *     Pile au niveau de la balise
2832
 * @return Champ
2833
 *     Pile complétée par le code à générer
2834
 **/
2835
function balise_CONST_dist($p) {
2836
	$_const = interprete_argument_balise(1, $p);
2837
	if (!strlen($_const)) {
2838
		$p->code = "''";
2839
	}
2840
	else {
2841
		$p->code = "(defined($_const)?constant($_const):'')";
2842
	}
2843
	$p->interdire_scripts = false;
2844
2845
	return $p;
2846
}
2847