Completed
Push — master ( 2a0f4b...be3b46 )
by cam
05:37
created

balises.php ➔ balise_NULL_dist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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