Completed
Push — spip-3.0 ( 5d8b58 )
by cam
53:01 queued 42:30
created

filtres.php ➔ affdate_base()   F

Complexity

Conditions 61
Paths 6698

Size

Total Lines 109
Code Lines 84

Duplication

Lines 3
Ratio 2.75 %

Importance

Changes 0
Metric Value
cc 61
eloc 84
c 0
b 0
f 0
nc 6698
nop 3
dl 3
loc 109
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2016                                                *
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
if (!defined('_ECRIRE_INC_VERSION')) return;
14
15
include_spip('inc/charsets');
16
include_spip('inc/filtres_mini');
17
include_spip('base/objets');
18
include_spip('public/parametrer'); // charger les fichiers fonctions
19
20
/**
21
 * Charger un filtre depuis le php :
22
 * - on inclue tous les fichiers fonctions des plugins et du skel
23
 * - on appelle chercher_filtre
24
 *
25
 * @param string $fonc
26
 * @param string $default
27
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

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...
28
 */
29
function charger_filtre($fonc, $default='filtre_identite_dist') {
30
	include_spip('public/parametrer'); // inclure les fichiers fonctions
31
	return chercher_filtre($fonc, $default);
32
}
33
34
function filtre_identite_dist($texte){return $texte;}
35
36
/**
37
 * http://doc.spip.org/@chercher_filtre
38
 *
39
 * @param string $fonc
40
 * @param null $default
41
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

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...
42
 */
43
function chercher_filtre($fonc, $default=NULL) {
44
	if (!$fonc) return $default;
45
	// Cas des types mime, sans confondre avec les appels de fonction de classe
46
	// Foo::Bar
47
	// qui peuvent etre avec un namespace : space\Foo::Bar
48
	if (preg_match(',^[\w]+/,',$fonc)){
49
		$nom = preg_replace(',\W,','_', $fonc);
50
		$f = chercher_filtre($nom);
51
		// cas du sous-type MIME sans filtre associe, passer au type:
52
		// si filtre_text_plain pas defini, passe a filtre_text
53
		if (!$f AND $nom!==$fonc)
54
			$f = chercher_filtre(preg_replace(',\W.*$,','', $fonc));
55
		return $f;
56
	}
57
	foreach (
58
	array('filtre_'.$fonc, 'filtre_'.$fonc.'_dist', $fonc) as $f){
59
		if (isset( $GLOBALS['spip_matrice'][$f]) AND is_string($g = $GLOBALS['spip_matrice'][$f]))
60
			find_in_path($g,'', true);
61
		if (function_exists($f)
62
		OR (preg_match("/^(\w*)::(\w*)$/", $f, $regs)
63
			AND is_callable(array($regs[1], $regs[2]))
64
		)) {
65
			return $f;
66
		}
67
	}
68
	return $default;
69
}
70
71
/**
72
 * Applique un filtre
73
 * 
74
 * Fonction générique qui prend en argument l’objet (texte, etc) à modifier
75
 * et le nom du filtre. Retrouve les arguments du filtre demandé dans les arguments
76
 * transmis à cette fonction, via func_get_args().
77
 *
78
 * @see filtrer() Assez proche
79
 * 
80
 * @param string $arg
81
 *     Texte sur lequel appliquer le filtre
82
 * @param string $filtre
83
 *     Nom du filtre a appliquer
84
 * @param string $force
0 ignored issues
show
Documentation introduced by
Should the type for parameter $force not be string|null?

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.

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

Loading history...
85
 *     La fonction doit-elle retourner le texte ou rien ?
86
 * @return string
87
 *     Texte avec le filtre appliqué s'il a été trouvé,
88
 *     Texte sans le filtre appliqué s'il n'a pas été trouvé et que $force n'a
89
 *       pas été fourni,
90
 *     Chaîne vide si le filtre n'a pas été trouvé et que $force a été fourni.
91
**/
92
function appliquer_filtre($arg, $filtre, $force=NULL) {
93
	$f = chercher_filtre($filtre);
94
	if (!$f) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $f 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...
95
		if (!$force) return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression $force 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...
96
		else return $arg;
97
	}
98
99
	$args = func_get_args();
100
	array_shift($args); // enlever $arg
101
	array_shift($args); // enlever $filtre
102
	array_unshift($args, $arg); // remettre $arg
103
	return call_user_func_array($f,$args);
104
}
105
106
// http://doc.spip.org/@spip_version
107
function spip_version() {
108
	$version = $GLOBALS['spip_version_affichee'];
109 View Code Duplication
	if ($svn_revision = version_svn_courante(_DIR_RACINE))
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...
110
		$version .= ($svn_revision<0 ? ' SVN':'').' ['.abs($svn_revision).']';
111
	return $version;
112
}
113
114
115
//
116
// Mention de la revision SVN courante de l'espace restreint standard
117
// (numero non garanti pour l'espace public et en cas de mutualisation)
118
// on est negatif si on est sur .svn, et positif si on utilise svn.revision
119
// http://doc.spip.org/@version_svn_courante
120
function version_svn_courante($dir) {
121
	if (!$dir) $dir = '.';
122
123
	// version installee par paquet ZIP
124
	if (lire_fichier($dir.'/svn.revision', $c)
125
	AND preg_match(',Revision: (\d+),', $c, $d))
126
		return intval($d[1]);
127
128
	// version installee par SVN
129
	if (lire_fichier($dir . '/.svn/entries', $c)
130
	AND (
131
	(preg_match_all(
132
	',committed-rev="([0-9]+)",', $c, $r1, PREG_PATTERN_ORDER)
133
	AND $v = max($r1[1])
134
	)
135
	OR
136
	(preg_match(',^\d.*dir[\r\n]+(\d+),ms', $c, $r1) # svn >= 1.4
137
	AND $v = $r1[1]
138
	)))
139
		return -$v;
140
141
	// Bug ou paquet fait main
142
	return 0;
143
}
144
145
// La matrice est necessaire pour ne filtrer _que_ des fonctions definies dans filtres_images
146
// et laisser passer les fonctions personnelles baptisees image_...
147
$GLOBALS['spip_matrice']['image_graver'] = true;//'inc/filtres_images_mini.php';
148
$GLOBALS['spip_matrice']['image_select'] = true;//'inc/filtres_images_mini.php';
149
$GLOBALS['spip_matrice']['image_reduire'] = true;//'inc/filtres_images_mini.php';
150
$GLOBALS['spip_matrice']['image_reduire_par'] = true;//'inc/filtres_images_mini.php';
151
$GLOBALS['spip_matrice']['image_passe_partout'] = true;//'inc/filtres_images_mini.php';
152
153
$GLOBALS['spip_matrice']['couleur_html_to_hex'] = 'inc/filtres_images_mini.php';
154
$GLOBALS['spip_matrice']['couleur_foncer'] = 'inc/filtres_images_mini.php';
155
$GLOBALS['spip_matrice']['couleur_eclaircir'] = 'inc/filtres_images_mini.php';
156
157
// ou pour inclure un script au moment ou l'on cherche le filtre
158
$GLOBALS['spip_matrice']['filtre_image_dist'] = 'inc/filtres_mime.php';
159
$GLOBALS['spip_matrice']['filtre_audio_dist'] = 'inc/filtres_mime.php';
160
$GLOBALS['spip_matrice']['filtre_video_dist'] = 'inc/filtres_mime.php';
161
$GLOBALS['spip_matrice']['filtre_application_dist'] = 'inc/filtres_mime.php';
162
$GLOBALS['spip_matrice']['filtre_message_dist'] = 'inc/filtres_mime.php';
163
$GLOBALS['spip_matrice']['filtre_multipart_dist'] = 'inc/filtres_mime.php';
164
$GLOBALS['spip_matrice']['filtre_text_dist'] = 'inc/filtres_mime.php';
165
$GLOBALS['spip_matrice']['filtre_text_csv_dist'] = 'inc/filtres_mime.php';
166
$GLOBALS['spip_matrice']['filtre_text_html_dist'] = 'inc/filtres_mime.php';
167
$GLOBALS['spip_matrice']['filtre_audio_x_pn_realaudio'] = 'inc/filtres_mime.php';
168
169
170
// charge les fonctions graphiques et applique celle demandee
171
// http://doc.spip.org/@filtrer
172
function filtrer($filtre) {
173
	if (isset($GLOBALS['spip_matrice'][$filtre]) and is_string($f = $GLOBALS['spip_matrice'][$filtre])){
174
		find_in_path($f,'', true);
175
		$GLOBALS['spip_matrice'][$filtre] = true;
176
	}
177
	$tous = func_get_args();
178
	if (substr($filtre,0,6)=='image_' && $GLOBALS['spip_matrice'][$filtre])
179
		return image_filtrer($tous);
180
	elseif($f = chercher_filtre($filtre)) {
181
		array_shift($tous);
182
		return call_user_func_array($f, $tous);
183
	}
184
	else {
185
		// le filtre n'existe pas, on provoque une erreur
186
		$msg = array('zbug_erreur_filtre', array('filtre'=>texte_script($filtre)));
187
		erreur_squelette($msg);
188
		return '';
189
	}
190
}
191
192
/*
193
 *
194
 * [(#CALCUL|set{toto})] enregistre le résultat de #CALCUL
195
 *           dans la variable toto et renvoie vide
196
 *
197
 * [(#CALCUL|set{toto,1})] enregistre le résultat de #CALCUL
198
 *           dans la variable toto et renvoie la valeur
199
 *
200
 */
201
function filtre_set(&$Pile, $val, $key, $continue = null) {
202
	$Pile['vars'][$key] = $val;
203
	return $continue ? $val : '';
204
}
205
206
/*
207
 * [(#TRUC|debug{avant}|calcul|debug{apres}|etc)] affiche
208
 *   la valeur de #TRUC avant et après le calcul
209
 */
210
function filtre_debug($val, $key=null) {
211
	$debug = (
212
		is_null($key) ? '' :  (var_export($key,true)." = ")
213
	) . var_export($val, true);
214
215
	include_spip('inc/autoriser');
216
	if (autoriser('webmestre'))
217
		echo "<div class='spip_debug'>\n",$debug,"</div>\n";
218
219
	spip_log($debug, 'debug');
220
221
	return $val;
222
}
223
224
225
// fonction generique d'entree des filtres images
226
// accepte en entree un texte complet, un img-log (produit par #LOGO_XX),
227
// un tag <img ...> complet, ou encore un nom de fichier *local* (passer
228
// le filtre |copie_locale si on veut l'appliquer a un document)
229
// applique le filtre demande a chacune des occurrences
230
231
// http://doc.spip.org/@image_filtrer
232
function image_filtrer($args){
233
	$filtre = array_shift($args); # enlever $filtre
234
	$texte = array_shift($args);
235
	if (!strlen($texte)) return;
236
	find_in_path('filtres_images_mini.php','inc/', true);
237
	statut_effacer_images_temporaires(true); // activer la suppression des images temporaires car le compilo finit la chaine par un image_graver
0 ignored issues
show
Unused Code introduced by
The call to the function statut_effacer_images_temporaires() seems unnecessary as the function has no side-effects.
Loading history...
238
	// Cas du nom de fichier local
239
	if ( strpos(substr($texte,strlen(_DIR_RACINE)),'..')===FALSE
240
	AND !preg_match(',^/|[<>]|\s,S', $texte)
241
	AND (
242
		file_exists(preg_replace(',[?].*$,','',$texte))
243
		OR preg_match(';^(\w{3,7}://);', $texte) 
244
		)) {
245
		array_unshift($args,"<img src='$texte' />");
246
		$res = call_user_func_array($filtre, $args);
247
		statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
0 ignored issues
show
Unused Code introduced by
The call to the function statut_effacer_images_temporaires() seems unnecessary as the function has no side-effects.
Loading history...
248
		return $res;
249
	}
250
251
	// Cas general : trier toutes les images, avec eventuellement leur <span>
252
	if (preg_match_all(
253
		',(<([a-z]+) [^<>]*spip_documents[^<>]*>)?\s*(<img\s.*>),UimsS',
254
		$texte, $tags, PREG_SET_ORDER)) {
255
		foreach ($tags as $tag) {
256
			$class = extraire_attribut($tag[3],'class');
257
			if (!$class || (strpos($class,'no_image_filtrer')===FALSE)){
258
				array_unshift($args,$tag[3]);
259
				if ($reduit = call_user_func_array($filtre, $args)) {
260
					// En cas de span spip_documents, modifier le style=...width:
261
					if($tag[1]){
262
						$w = extraire_attribut($reduit, 'width');
263
						if (!$w AND preg_match(",width:\s*(\d+)px,S",extraire_attribut($reduit,'style'),$regs))
264
							$w = $regs[1];
265
						if ($w AND ($style = extraire_attribut($tag[1], 'style'))){
266
							$style = preg_replace(",width:\s*\d+px,S", "width:${w}px", $style);
267
							$replace = inserer_attribut($tag[1], 'style', $style);
268
							$texte = str_replace($tag[1], $replace, $texte);
269
						}
270
					}
271
					// traiter aussi un eventuel mouseover
272
					if ($mouseover = extraire_attribut($reduit,'onmouseover')){
273
						if (preg_match(",this[.]src=['\"]([^'\"]+)['\"],ims", $mouseover, $match)){
274
							$srcover = $match[1];
275
							array_shift($args);
276
							array_unshift($args,"<img src='".$match[1]."' />");
277
							$srcover_filter = call_user_func_array($filtre, $args);
278
							$srcover_filter = extraire_attribut($srcover_filter,'src');
279
							$reduit = str_replace($srcover,$srcover_filter,$reduit);
280
						}
281
					}
282
					$texte = str_replace($tag[3], $reduit, $texte);
283
				}
284
				array_shift($args);
285
			}
286
		}
287
	}
288
	statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
0 ignored issues
show
Unused Code introduced by
The call to the function statut_effacer_images_temporaires() seems unnecessary as the function has no side-effects.
Loading history...
289
	return $texte;
290
}
291
292
//
293
// Retourner taille d'une image
294
// pour les filtres |largeur et |hauteur
295
//
296
// http://doc.spip.org/@taille_image
297
function taille_image($img) {
298
299
	static $largeur_img =array(), $hauteur_img= array();
300
	$srcWidth = 0;
301
	$srcHeight = 0;
302
303
	$logo = extraire_attribut($img,'src');
304
305
	if (!$logo) $logo = $img;
306
	else {
307
		$srcWidth = extraire_attribut($img,'width');
308
		$srcHeight = extraire_attribut($img,'height');
309
	}
310
311
	// ne jamais operer directement sur une image distante pour des raisons de perfo
312
	// la copie locale a toutes les chances d'etre la ou de resservir
313
	if (preg_match(';^(\w{3,7}://);', $logo)){
314
		include_spip('inc/distant');
315
		$fichier = copie_locale($logo);
316
		$logo = $fichier ? _DIR_RACINE . $fichier : $logo;
317
	}
318 View Code Duplication
	if (($p=strpos($logo,'?'))!==FALSE)
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...
319
		$logo=substr($logo,0,$p);
320
321
	$srcsize = false;
0 ignored issues
show
Unused Code introduced by
$srcsize 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...
322
	if (isset($largeur_img[$logo]))
323
		$srcWidth = $largeur_img[$logo];
324
	if (isset($hauteur_img[$logo]))
325
		$srcHeight = $hauteur_img[$logo];
326
	if (!$srcWidth OR !$srcHeight){
327
		if (file_exists($logo)
328
			AND $srcsize = @getimagesize($logo)){
329
			if (!$srcWidth)	$largeur_img[$logo] = $srcWidth = $srcsize[0];
330
			if (!$srcHeight)	$hauteur_img[$logo] = $srcHeight = $srcsize[1];
331
		}
332
		// $logo peut etre une reference a une image temporaire dont a n'a que le log .src
333
		// on s'y refere, l'image sera reconstruite en temps utile si necessaire
334
		elseif(@file_exists($f = "$logo.src")
335
		  AND lire_fichier($f,$valeurs)
336
		  AND $valeurs=unserialize($valeurs)) {
337
			if (!$srcWidth)	$largeur_img[$logo] = $srcWidth = $valeurs["largeur_dest"];
338
			if (!$srcHeight)	$hauteur_img[$logo] = $srcHeight = $valeurs["hauteur_dest"];
339
	  }
340
	}
341
	return array($srcHeight, $srcWidth);
342
}
343
// http://doc.spip.org/@largeur
344
function largeur($img) {
345
	if (!$img) return;
346
	list ($h,$l) = taille_image($img);
0 ignored issues
show
Unused Code introduced by
The assignment to $h is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
347
	return $l;
348
}
349
// http://doc.spip.org/@hauteur
350
function hauteur($img) {
351
	if (!$img) return;
352
	list ($h,$l) = taille_image($img);
0 ignored issues
show
Unused Code introduced by
The assignment to $l is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
353
	return $h;
354
}
355
356
357
// Echappement des entites HTML avec correction des entites "brutes"
358
// (generees par les butineurs lorsqu'on rentre des caracteres n'appartenant
359
// pas au charset de la page [iso-8859-1 par defaut])
360
//
361
// Attention on limite cette correction aux caracteres "hauts" (en fait > 99
362
// pour aller plus vite que le > 127 qui serait logique), de maniere a
363
// preserver des echappements de caracteres "bas" (par exemple [ ou ")
364
// et au cas particulier de &amp; qui devient &amp;amp; dans les url
365
// http://doc.spip.org/@corriger_entites_html
366
function corriger_entites_html($texte) {
367
	if (strpos($texte,'&amp;') === false) return $texte;
368
	return preg_replace(',&amp;(#[0-9][0-9][0-9]+;|amp;),iS', '&\1', $texte);
369
}
370
// idem mais corriger aussi les &amp;eacute; en &eacute;
371
// http://doc.spip.org/@corriger_toutes_entites_html
372
function corriger_toutes_entites_html($texte) {
373
	if (strpos($texte,'&amp;') === false) return $texte;
374
	return preg_replace(',&amp;(#?[a-z0-9]+;),iS', '&\1', $texte);
375
}
376
377
// http://doc.spip.org/@proteger_amp
378
function proteger_amp($texte){
379
	return str_replace('&','&amp;',$texte);
380
}
381
382
//
383
/**
384
 * http://doc.spip.org/@entites_html
385
 *
386
 * @param string $texte
387
 *   chaine a echapper
388
 * @param bool $tout
389
 *   corriger toutes les &amp;xx; en &xx;
390
 * @param bool $quote
391
 *   echapper aussi les simples quotes en &#039;
392
 * @return mixed|string
393
 */
394
function entites_html($texte, $tout=false, $quote=true) {
395 View Code Duplication
	if (!is_string($texte) OR !$texte
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...
396
	OR strpbrk($texte, "&\"'<>")==false
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing strpbrk($texte, '&"\'<>') of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
397
	) return $texte;
398
	include_spip('inc/texte');
399
	$flags = !defined('PHP_VERSION_ID') OR PHP_VERSION_ID < 50400 ? ENT_COMPAT : ENT_COMPAT|ENT_HTML401;
400
	$texte = spip_htmlspecialchars(echappe_retour(echappe_html($texte, '', true), '', 'proteger_amp'), $quote?ENT_QUOTES:$flags);
0 ignored issues
show
Bug introduced by
It seems like $quote ? ENT_QUOTES : $flags can also be of type boolean; however, spip_htmlspecialchars() does only seem to accept integer|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
401
	if ($tout)
402
		return corriger_toutes_entites_html($texte);
403
	else
404
		return corriger_entites_html($texte);
405
}
406
407
// Transformer les &eacute; dans le charset local
408
// http://doc.spip.org/@filtrer_entites
409
function filtrer_entites($texte) {
410
	if (strpos($texte,'&') === false) return $texte;
411
	// filtrer
412
	$texte = html2unicode($texte);
413
	// remettre le tout dans le charset cible
414
	$texte = unicode2charset($texte);
415
	// cas particulier des " et ' qu'il faut filtrer aussi
416
	// (on le faisait deja avec un &quot;)
417 View Code Duplication
	if (strpos($texte,"&#")!==false)
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...
418
		$texte = str_replace(array("&#039;","&#39;","&#034;","&#34;"), array("'","'",'"','"'), $texte);
419
	return $texte;
420
}
421
422
/**
423
 * Version securisee de filtrer_entites
424
 * @param string $t
425
 * @return string
426
 */
427
if (!function_exists('filtre_filtrer_entites_dist')) {
428
	function filtre_filtrer_entites_dist($t) {
0 ignored issues
show
Best Practice introduced by
The function filtre_filtrer_entites_dist() has been defined more than once; this definition is ignored, only the first definition in config/ecran_securite.php (L305-308) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
429
		include_spip('inc/texte');
430
		return interdire_scripts(filtrer_entites($t));
431
	}
432
}
433
434
435
// caracteres de controle - http://www.w3.org/TR/REC-xml/#charsets
436
// http://doc.spip.org/@supprimer_caracteres_illegaux
437
function supprimer_caracteres_illegaux($texte) {
438
	static $from = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\xB\xC\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
439
	static $to = null;
440
	
441
	if (is_array($texte)) {
442
		return array_map('supprimer_caracteres_illegaux', $texte);
443
	}
444
	
445
	if (!$to) $to = str_repeat('-', strlen($from));
446
	return strtr($texte, $from, $to);
447
}
448
449
// Supprimer caracteres windows et les caracteres de controle ILLEGAUX
450
// http://doc.spip.org/@corriger_caracteres
451
function corriger_caracteres ($texte) {
452
	$texte = corriger_caracteres_windows($texte);
453
	$texte = supprimer_caracteres_illegaux($texte);
454
	return $texte;
455
}
456
457
/**
458
 * Encode du HTML pour transmission XML
459
 * notamment dans les flux RSS
460
 *
461
 * http://doc.spip.org/@texte_backend
462
 *
463
 * @param $texte
464
 * @return mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
465
 */
466
function texte_backend($texte) {
467
468
	static $apostrophe = array("&#8217;", "'"); # n'allouer qu'une fois
469
470
	// si on a des liens ou des images, les passer en absolu
471
	$texte = liens_absolus($texte);
472
473
	// echapper les tags &gt; &lt;
474
	$texte = preg_replace(',&(gt|lt);,S', '&amp;\1;', $texte);
475
476
	// importer les &eacute;
477
	$texte = filtrer_entites($texte);
478
479
	// " -> &quot; et tout ce genre de choses
480
	$u = $GLOBALS['meta']['pcre_u'];
481
	$texte = str_replace("&nbsp;", " ", $texte);
482
	$texte = preg_replace('/\s{2,}/S'.$u, " ", $texte);
483
	// ne pas echapper les sinqle quotes car certains outils de syndication gerent mal
484
	$texte = entites_html($texte, false, false);
485
	// mais bien echapper les double quotes !
486
	$texte = str_replace('"','&#034;',$texte);
487
488
	// verifier le charset
489
	$texte = charset2unicode($texte);
490
491
	// Caracteres problematiques en iso-latin 1
492
	if ($GLOBALS['meta']['charset'] == 'iso-8859-1') {
493
		$texte = str_replace(chr(156), '&#156;', $texte);
494
		$texte = str_replace(chr(140), '&#140;', $texte);
495
		$texte = str_replace(chr(159), '&#159;', $texte);
496
	}
497
498
	// l'apostrophe curly pose probleme a certains lecteure de RSS
499
	// et le caractere apostrophe alourdit les squelettes avec PHP
500
	// ==> on les remplace par l'entite HTML
501
	return str_replace($apostrophe, "'", $texte);
502
}
503
504
// Comme ci-dessus, mais avec addslashes final pour squelettes avec PHP (rss)
505
506
function texte_backendq($texte) {
507
	return addslashes(texte_backend($texte));
508
}
509
510
// Enleve le numero des titres numerotes ("1. Titre" -> "Titre")
511
// http://doc.spip.org/@supprimer_numero
512
function supprimer_numero($texte) {
513
	return preg_replace(
514
	",^[[:space:]]*([0-9]+)([.)]|".chr(194).'?'.chr(176).")[[:space:]]+,S",
515
	"", $texte);
516
}
517
518
// et la fonction inverse
519
// http://doc.spip.org/@recuperer_numero
520
function recuperer_numero($texte) {
521
	if (preg_match(
522
	",^[[:space:]]*([0-9]+)([.)]|".chr(194).'?'.chr(176).")[[:space:]]+,S",
523
	$texte, $regs))
524
		return strval($regs[1]);
525
	else
526
		return '';
527
}
528
529
// Suppression basique et brutale de tous les <...>
530
// http://doc.spip.org/@supprimer_tags
531
function supprimer_tags($texte, $rempl = "") {
532
	$texte = preg_replace(",<[^>]*>,US", $rempl, $texte);
533
	// ne pas oublier un < final non ferme
534
	// mais qui peut aussi etre un simple signe plus petit que
535
	$texte = str_replace('<', ' ', $texte);
536
	return $texte;
537
}
538
539
// Convertit les <...> en la version lisible en HTML
540
// http://doc.spip.org/@echapper_tags
541
function echapper_tags($texte, $rempl = "") {
0 ignored issues
show
Unused Code introduced by
The parameter $rempl 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...
542
	$texte = preg_replace("/<([^>]*)>/", "&lt;\\1&gt;", $texte);
543
	return $texte;
544
}
545
546
// Convertit un texte HTML en texte brut
547
// http://doc.spip.org/@textebrut
548
function textebrut($texte) {
549
	$u = $GLOBALS['meta']['pcre_u'];
550
	$texte = preg_replace('/\s+/S'.$u, " ", $texte);
551
	$texte = preg_replace("/<(p|br)( [^>]*)?".">/iS", "\n\n", $texte);
552
	$texte = preg_replace("/^\n+/", "", $texte);
553
	$texte = preg_replace("/\n+$/", "", $texte);
554
	$texte = preg_replace("/\n +/", "\n", $texte);
555
	$texte = supprimer_tags($texte);
556
	$texte = preg_replace("/(&nbsp;| )+/S", " ", $texte);
557
	// nettoyer l'apostrophe curly qui pose probleme a certains rss-readers, lecteurs de mail...
558
	$texte = str_replace("&#8217;","'",$texte);
559
	return $texte;
560
}
561
562
// Remplace les liens SPIP en liens ouvrant dans une nouvelle fenetre (target=blank)
563
// http://doc.spip.org/@liens_ouvrants
564
function liens_ouvrants ($texte) {
565
	return preg_replace(",<a\s+([^>]*https?://[^>]*class=[\"']spip_(out|url)\b[^>]+)>,",
566
		"<a \\1 target=\"_blank\">", $texte);
567
}
568
569
/**
570
 * Ajouter un attribut rel="nofollow" sur tous les liens d'un texte
571
 * @param string $texte
572
 * @return string
573
 */
574
function liens_nofollow($texte) {
575
	if (stripos($texte,"<a")===false)
576
		return $texte;
577
578
	if (preg_match_all(",<a\b[^>]*>,UimsS",$texte, $regs, PREG_PATTERN_ORDER)){
579
		foreach($regs[0] as $a){
580
			$rel = extraire_attribut($a,"rel");
581
			if (strpos($rel,"nofollow")===false){
582
				$rel = "nofollow" . ($rel?" $rel":"");
583
				$anofollow = inserer_attribut($a,"rel",$rel);
584
				$texte = str_replace($a,$anofollow,$texte);
585
			}
586
		}
587
	}
588
589
	return $texte;
590
}
591
592
// Transformer les sauts de paragraphe en simples passages a la ligne
593
// http://doc.spip.org/@PtoBR
594
function PtoBR($texte){
595
	$u = $GLOBALS['meta']['pcre_u'];
596
	$texte = preg_replace("@</p>@iS", "\n", $texte);
597
	$texte = preg_replace("@<p\b.*>@UiS", "<br />", $texte);
598
	$texte = preg_replace("@^\s*<br />@S".$u, "", $texte);
599
	return $texte;
600
}
601
602
603
/**
604
 * lignes_longues assure qu'un texte ne vas pas deborder d'un bloc
605
 * par la faute d'un mot trop long (souvent des URLs)
606
 * Ne devrait plus etre utilise et fait directement en CSS par un style
607
 * word-wrap:break-word;
608
 * cf http://www.alsacreations.com/tuto/lire/1038-gerer-debordement-contenu-css.html
609
 *
610
 * Pour assurer la compatibilite du filtre, on encapsule le contenu par
611
 * un div ou span portant ce style inline.
612
 *
613
 * http://doc.spip.org/@lignes_longues
614
 *
615
 * @param string $texte
616
 * @return string
617
 */
618
function lignes_longues($texte) {
619
	if (!strlen(trim($texte))) return $texte;
620
	include_spip('inc/texte');
621
	$tag = preg_match(',</?('._BALISES_BLOCS.')[>[:space:]],iS', $texte) ?
622
		'div' : 'span';
623
624
	return "<$tag style='word-wrap:break-word;'>$texte</$tag>";
625
}
626
627
// Majuscules y compris accents, en HTML
628
// http://doc.spip.org/@majuscules
629
function majuscules($texte) {
630
	if (!strlen($texte)) return '';
631
632
	// Cas du turc
633
	if ($GLOBALS['spip_lang'] == 'tr') {
634
		# remplacer hors des tags et des entites
635 View Code Duplication
		if (preg_match_all(',<[^<>]+>|&[^;]+;,S', $texte, $regs, PREG_SET_ORDER))
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...
636
			foreach ($regs as $n => $match)
637
				$texte = str_replace($match[0], "@@SPIP_TURC$n@@", $texte);
638
639
		$texte = str_replace('i', '&#304;', $texte);
640
641 View Code Duplication
		if ($regs)
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...
642
			foreach ($regs as $n => $match)
643
				$texte = str_replace("@@SPIP_TURC$n@@", $match[0], $texte);
644
	}
645
646
	// Cas general
647
	return "<span style='text-transform: uppercase;'>$texte</span>";
648
}
649
650
// "127.4 ko" ou "3.1 Mo"
651
// http://doc.spip.org/@taille_en_octets
652
function taille_en_octets ($taille) {
653
	if ($taille < 1) return '';
654
	if ($taille < 1024) {$taille = _T('taille_octets', array('taille' => $taille));}
655
	else if ($taille < 1024*1024) {
656
		$taille = _T('taille_ko', array('taille' => round($taille/1024, 1)));
657
	} else if ($taille < 1024*1024*1024) {
658
		$taille = _T('taille_mo', array('taille' => round($taille/1024/1024, 1)));
659
	} else {
660
		$taille = _T('taille_go', array('taille' => round($taille/1024/1024/1024, 2)));
661
	}
662
	return $taille;
663
}
664
665
666
// Rend une chaine utilisable sans dommage comme attribut HTML
667
// http://doc.spip.org/@attribut_html
668
function attribut_html($texte,$textebrut = true) {
669
	$u = $GLOBALS['meta']['pcre_u'];
670
	if ($textebrut)
671
		$texte = preg_replace(array(",\n,",",\s(?=\s),msS".$u),array(" ",""),textebrut($texte));
672
	$texte = texte_backend($texte);
673
	$texte = str_replace(array("'",'"'),array('&#039;', '&#034;'), $texte);
674
	
675
	return preg_replace(array("/&(amp;|#38;)/","/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/"),array("&","&#38;") , $texte);
676
}
677
678
// Vider les url nulles comme 'http://' ou 'mailto:'
679
// et leur appliquer un htmlspecialchars() + gerer les &amp;
680
// http://doc.spip.org/@vider_url
681
function vider_url($url, $entites = true) {
682
	# un message pour abs_url
683
	$GLOBALS['mode_abs_url'] = 'url';
684
	$url = trim($url);
685
	$r = ",^(?:" . _PROTOCOLES_STD . '):?/?/?$,iS';
686
	return preg_match($r, $url) ? '': ($entites ? entites_html($url) : $url);
687
}
688
689
// Extraire une date de n'importe quel champ (a completer...)
690
// http://doc.spip.org/@extraire_date
691
function extraire_date($texte) {
692
	// format = 2001-08
693
	if (preg_match(",([1-2][0-9]{3})[^0-9]*(1[0-2]|0?[1-9]),",$texte,$regs))
694
		return $regs[1]."-".sprintf("%02d", $regs[2])."-01";
695
}
696
697
// Maquiller une adresse e-mail
698
// http://doc.spip.org/@antispam
699
function antispam($texte) {
700
	include_spip('inc/acces');
701
	$masque = creer_pass_aleatoire(3);
702
	return preg_replace("/@/", " $masque ", $texte);
703
}
704
705
// http://doc.spip.org/@securiser_acces
706
function securiser_acces($id_auteur, $cle, $dir, $op='', $args='')
707
{
708
	include_spip('inc/acces');
709
	if ($op) $dir .= " $op $args";
710
	return verifier_low_sec($id_auteur, $cle, $dir);
711
}
712
713
/**
714
 * La fonction sinon retourne le second parametre lorsque
715
 * le premier est considere vide, sinon retourne le premier parametre.
716
 *
717
 * En php sinon($a, 'rien') retourne $a ou 'rien' si $a est vide.
718
 * En filtre spip |sinon{#TEXTE, rien} : affiche #TEXTE ou "rien" si #TEXTE est vide,
719
 *
720
 * Note : l'utilisation de |sinon en tant que filtre de squelette
721
 * est directement compile dans public/references par la fonction filtre_logique()
722
 * 
723
 * @param mixed $texte
724
 * 		Contenu de reference a tester
725
 * @param mixed $sinon
726
 * 		Contenu a retourner si le contenu de reference est vide
727
 * @return mixed
728
 * 		Retourne $texte, sinon $sinon.
729
**/
730
function sinon ($texte, $sinon='') {
731
	if ($texte OR (!is_array($texte) AND strlen($texte)))
732
		return $texte;
733
	else
734
		return $sinon;
735
}
736
737
// |choixsivide{vide,pasvide} affiche pasvide si la chaine n'est pas vide...
738
// http://doc.spip.org/@choixsivide
739
function choixsivide($a, $vide, $pasvide) {
740
	return $a ? $pasvide : $vide;
741
}
742
743
// |choixsiegal{aquoi,oui,non} affiche oui si la chaine est egal a aquoi ...
744
// http://doc.spip.org/@choixsiegal
745
function choixsiegal($a1,$a2,$v,$f) {
746
	return ($a1 == $a2) ? $v : $f;
747
}
748
749
750
//
751
// Date, heure, saisons
752
//
753
754
// on normalise la date, si elle vient du contexte (public/parametrer.php), on force le jour
755
// http://doc.spip.org/@normaliser_date
756
function normaliser_date($date, $forcer_jour = false) {
757
	$date = vider_date($date);
758
	if ($date) {
759
		if (preg_match("/^[0-9]{8,10}$/", $date))
760
			$date = date("Y-m-d H:i:s", $date);
761
		if (preg_match("#^([12][0-9]{3})([-/]00)?( [-0-9:]+)?$#", $date, $regs))
762
			$date = $regs[1]."-00-00".$regs[3];
763
		else if (preg_match("#^([12][0-9]{3}[-/][01]?[0-9])([-/]00)?( [-0-9:]+)?$#", $date, $regs))
764
			$date = preg_replace("@/@","-",$regs[1])."-00".$regs[3];
765
		else
766
			$date = date("Y-m-d H:i:s", strtotime($date));
767
768
		if ($forcer_jour)
769
			$date = str_replace('-00', '-01', $date);
770
	}
771
	return $date;
772
}
773
774
// http://doc.spip.org/@vider_date
775
function vider_date($letexte) {
776
	if (strncmp("0000-00-00", $letexte,10)==0) return '';
777
	if (strncmp("0001-01-01", $letexte,10)==0) return '';
778
	if (strncmp("1970-01-01", $letexte,10)==0) return '';	// eviter le bug GMT-1
779
	return $letexte;
780
}
781
782
// http://doc.spip.org/@recup_heure
783
function recup_heure($date){
784
785
	static $d = array(0,0,0);
786
	if (!preg_match('#([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $date, $r)) 
787
		return $d;
788
	
789
	array_shift($r);
790
	return $r;
791
}
792
793
// http://doc.spip.org/@heures
794
function heures($numdate) {
795
	$date_array = recup_heure($numdate);
796
	if ($date_array)
0 ignored issues
show
Bug Best Practice introduced by
The expression $date_array 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...
797
		list($heures, $minutes, $secondes) = $date_array;
0 ignored issues
show
Unused Code introduced by
The assignment to $minutes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $secondes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
798
	return $heures;
0 ignored issues
show
Bug introduced by
The variable $heures does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
799
}
800
801
// http://doc.spip.org/@minutes
802
function minutes($numdate) {
803
	$date_array = recup_heure($numdate);
804
	if ($date_array)
0 ignored issues
show
Bug Best Practice introduced by
The expression $date_array 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...
805
		list($heures, $minutes, $secondes) = $date_array;
0 ignored issues
show
Unused Code introduced by
The assignment to $heures is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $secondes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
806
	return $minutes;
0 ignored issues
show
Bug introduced by
The variable $minutes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
807
}
808
809
// http://doc.spip.org/@secondes
810
function secondes($numdate) {
811
	$date_array = recup_heure($numdate);
812
	if ($date_array)
0 ignored issues
show
Bug Best Practice introduced by
The expression $date_array 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...
813
		list($heures,$minutes,$secondes) = $date_array;
0 ignored issues
show
Unused Code introduced by
The assignment to $heures is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $minutes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
814
	return $secondes;
0 ignored issues
show
Bug introduced by
The variable $secondes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
815
}
816
817
// http://doc.spip.org/@heures_minutes
818
function heures_minutes($numdate) {
819
	return _T('date_fmt_heures_minutes', array('h'=> heures($numdate), 'm'=> minutes($numdate)));
820
}
821
822
// http://doc.spip.org/@recup_date
823
function recup_date($numdate, $forcer_jour = true){
824
	if (!$numdate) return '';
825
	$heures = $minutes = $secondes = 0;
826
	if (preg_match('#([0-9]{1,2})/([0-9]{1,2})/([0-9]{4}|[0-9]{1,2})#', $numdate, $regs)) {
827
		$jour = $regs[1];
828
		$mois = $regs[2];
829
		$annee = $regs[3];
830
		if ($annee < 90){
831
			$annee = 2000 + $annee;
832
		} elseif ($annee<100) {
833
			$annee = 1900 + $annee ;
834
		}
835
		list($heures, $minutes, $secondes) = recup_heure($numdate);
836
837
	}
838 View Code Duplication
	elseif (preg_match('#([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})#',$numdate, $regs)) {
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...
839
		$annee = $regs[1];
840
		$mois = $regs[2];
841
		$jour = $regs[3];
842
		list($heures, $minutes, $secondes) = recup_heure($numdate);
843
	}
844 View Code Duplication
	elseif (preg_match('#([0-9]{4})-([0-9]{2})#', $numdate, $regs)){
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...
845
		$annee = $regs[1];
846
		$mois = $regs[2];
847
		$jour ='';
848
		list($heures, $minutes, $secondes) = recup_heure($numdate);
849
	}
850
	elseif (preg_match('#^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$#', $numdate, $regs)){
851
		$annee = $regs[1];
852
		$mois = $regs[2];
853
		$jour = $regs[3];
854
		$heures = $regs[4];
855
		$minutes = $regs[5];
856
		$secondes = $regs[6];
857
	} else $annee = $mois =  $jour =''; 
858
	if ($annee > 4000) $annee -= 9000;
859
	if (substr($jour, 0, 1) == '0') $jour = substr($jour, 1);
860
861
	if ($forcer_jour AND $jour == '0') $jour = '1';
862
	if ($forcer_jour AND $mois == '0') $mois = '1';
863
	if ($annee OR $mois OR $jour OR $heures OR $minutes OR $secondes)
864
		return array($annee, $mois, $jour, $heures, $minutes, $secondes);
865
}
866
867
// une date pour l'interface : utilise date_relative si le decalage
868
// avec time() est de moins de douze heures, sinon la date complete
869
// http://doc.spip.org/@date_interface
870
function date_interface($date, $decalage_maxi = 43200/* 12*3600 */) {
871
	return sinon(
872
		date_relative($date, $decalage_maxi),
873
		affdate_heure($date)
874
	);
875
}
876
877
// http://doc.spip.org/@date_relative
878
function date_relative($date, $decalage_maxi=0,$ref_date=null) {
879
	
880
	if (is_null($ref_date))
881
		$ref_time = time();
882
	else
883
		$ref_time = strtotime($ref_date);
884
	
885
	if (!$date) return;
886
	$decal = date("U",$ref_time) - date("U", strtotime($date));
887
888
	if ($decalage_maxi AND ($decal > $decalage_maxi OR $decal < 0))
889
		return '';
890
891
	if ($decal < 0) {
892
		$il_y_a = "date_dans";
893
		$decal = -1 * $decal;
894
	} else {
895
		$il_y_a = "date_il_y_a";
896
	}
897
898
	if ($decal > 3600 * 24 * 30 * 6)
899
		return affdate_court($date);
900
901
	if ($decal > 3600 * 24 * 30) {
902
		$mois = floor ($decal / (3600 * 24 * 30));
903
		if ($mois < 2)
904
			$delai = "$mois "._T("date_un_mois");
905
		else
906
			$delai = "$mois "._T("date_mois");
907
	}
908
	else if ($decal > 3600 * 24 * 7) {
909
		$semaines = floor ($decal / (3600 * 24 * 7));
910
		if ($semaines < 2)
911
			$delai = "$semaines "._T("date_une_semaine");
912
		else
913
			$delai = "$semaines "._T("date_semaines");
914
	}
915
	else if ($decal > 3600 * 24) {
916
		$jours = floor ($decal / (3600 * 24));
917
		if ($jours < 2)
918
			return $il_y_a=="date_dans"?_T("date_demain"):_T("date_hier");
919
		else
920
			$delai = "$jours "._T("date_jours");
921
	}
922
	else if ($decal >= 3600) {
923
		$heures = floor ($decal / 3600);
924
		if ($heures < 2)
925
			$delai = "$heures "._T("date_une_heure");
926
		else
927
			$delai = "$heures "._T("date_heures");
928
	}
929
	else if ($decal >= 60) {
930
		$minutes = floor($decal / 60);
931
		if ($minutes < 2)
932
			$delai = "$minutes "._T("date_une_minute");
933
		else
934
			$delai = "$minutes "._T("date_minutes");
935
	} else {
936
		$secondes = ceil($decal);
937
		if ($secondes < 2)
938
			$delai = "$secondes "._T("date_une_seconde");
939
		else
940
			$delai = "$secondes "._T("date_secondes");
941
	}
942
943
	return _T($il_y_a, array("delai"=> $delai));
944
}
945
946
947
// http://doc.spip.org/@date_relativecourt
948
function date_relativecourt($date, $decalage_maxi=0) {
949
	
950
	if (!$date) return;
951
	$decal = date("U",strtotime(date('Y-m-d'))-strtotime(date('Y-m-d',strtotime($date))));
952
953
	if ($decalage_maxi AND ($decal > $decalage_maxi OR $decal < 0))
954
		return '';
955
956
	if ($decal < -24*3600) {
957
		$retour = date_relative($date, $decalage_maxi);
958
	}
959
	elseif ($decal < 0) {
960
		$retour = _T("date_demain");
961
	}
962
	else if ($decal < (3600 * 24) ) {
963
		$retour = _T("date_aujourdhui");
964
	}
965
	else if ($decal < (3600 * 24 *2) ) {
966
		$retour = _T("date_hier");
967
	}
968
	else {
969
		$retour = date_relative($date, $decalage_maxi);
970
	}
971
972
973
974
	return $retour;
975
}
976
977
/**
978
 * Formatage humain de la date $numdate selon le format $vue
979
 * http://doc.spip.org/@affdate_base
980
 *
981
 * @param $numdate
982
 * @param $vue
983
 * @param array $options
984
 *   param : 'abbr' ou 'initiale' permet d'afficher les jours au format court ou initiale
985
 *   annee_courante : permet de definir l'annee de reference pour l'affichage des dates courtes
986
 * @return mixed|string
987
 */
988
function affdate_base($numdate, $vue, $options = array()) {
989
	if (is_string($options))
990
		$options = array('param'=>$options);
991
	$date_array = recup_date($numdate, false);
992
	if (!$date_array) return;
993
	list($annee, $mois, $jour, $heures, $minutes, $secondes)= $date_array;
0 ignored issues
show
Unused Code introduced by
The assignment to $heures is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $minutes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $secondes is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
994
995
	// 1er, 21st, etc.
996
	$journum = $jour;
997
998
	if ($jour == 0) {
999
		$jour = '';
1000
	} else {
1001
		$njour = intval($jour);
1002
		if ($jourth = _T('date_jnum'.$jour))
1003
			$jour = $jourth;
1004
	}
1005
1006
	$mois = intval($mois);
1007
	if ($mois > 0 AND $mois < 13) {
1008
		$nommois = _T('date_mois_'.$mois);
1009
		if ($jour)
1010
			$jourmois = _T('date_de_mois_'.$mois, array('j'=>$jour, 'nommois'=>$nommois));
1011
		else
1012
			$jourmois = $nommois;
1013
	} else $nommois = '';
1014
1015
	if ($annee < 0) {
1016
		$annee = -$annee." "._T('date_avant_jc');
1017
		$avjc = true;
1018
	}
1019
	else $avjc = false;
1020
1021
	switch ($vue) {
1022
	case 'saison':
1023
	case 'saison_annee':
1024
		$saison = '';
1025
		if ($mois > 0){
1026
			$saison = 1;
1027
			if (($mois == 3 AND $jour >= 21) OR $mois > 3) $saison = 2;
1028
			if (($mois == 6 AND $jour >= 21) OR $mois > 6) $saison = 3;
1029
			if (($mois == 9 AND $jour >= 21) OR $mois > 9) $saison = 4;
1030
			if (($mois == 12 AND $jour >= 21) OR $mois > 12) $saison = 1;
1031
		}
1032
		if($vue == 'saison')
1033
			return $saison?_T('date_saison_'.$saison):'';
1034
		else
1035
			return $saison?trim(_T('date_fmt_saison_annee', array('saison'=>_T('date_saison_'.$saison), 'annee'=>$annee))) :'';
1036
1037
	case 'court':
1038
		if ($avjc) return $annee;
1039
		$a = ((isset($options['annee_courante']) AND $options['annee_courante'])?$options['annee_courante']:date('Y'));
1040
		if ($annee < ($a - 100) OR $annee > ($a + 100)) return $annee;
1041 View Code Duplication
		if ($annee != $a) return _T('date_fmt_mois_annee', array ('mois'=>$mois, 'nommois'=>spip_ucfirst($nommois), 'annee'=>$annee));
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...
1042
		return _T('date_fmt_jour_mois', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
0 ignored issues
show
Bug introduced by
The variable $jourmois does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1043
1044
	case 'jourcourt':
1045
		if ($avjc) return $annee;
1046
		$a = ((isset($options['annee_courante']) AND $options['annee_courante'])?$options['annee_courante']:date('Y'));
1047
		if ($annee < ($a - 100) OR $annee > ($a + 100)) return $annee;
1048
		if ($annee != $a) return _T('date_fmt_jour_mois_annee', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
1049
		return _T('date_fmt_jour_mois', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
1050
1051
	case 'entier':
1052
		if ($avjc) return $annee;
1053
		if ($jour)
1054
			return _T('date_fmt_jour_mois_annee', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
1055 View Code Duplication
		elseif ($mois)
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...
1056
			return trim(_T('date_fmt_mois_annee', array ('mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee)));
1057
		else
1058
			return $annee;
1059
1060
	case 'nom_mois':
1061
		$param = ((isset($options['param']) AND $options['param']) ? '_'.$options['param'] : '');
1062
		if ($param and $mois) {
1063
			return _T('date_mois_'.$mois.$param);
1064
		}
1065
		return $nommois;
1066
1067
	case 'mois':
1068
		return sprintf("%02s",$mois);
1069
1070
	case 'jour':
1071
		return $jour;
1072
1073
	case 'journum':
1074
		return $journum;
1075
1076
	case 'nom_jour':
1077
		if (!$mois OR !$njour)
0 ignored issues
show
Bug introduced by
The variable $njour does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1078
			return '';
1079
		$nom = mktime(1,1,1,$mois,$njour,$annee);
1080
		$nom = 1+date('w',$nom);
1081
		$param = ((isset($options['param']) AND $options['param']) ? '_'.$options['param'] : '');
1082
		return _T('date_jour_'.$nom.$param);
1083
1084
	case 'mois_annee':
1085
		if ($avjc) return $annee;
1086
		return trim(_T('date_fmt_mois_annee', array('mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee)));
1087
1088
	case 'annee':
1089
		return $annee;
1090
1091
	// Cas d'une vue non definie : retomber sur le format
1092
	// de date propose par http://www.php.net/date
1093
	default:
1094
		return date($vue, strtotime($numdate));
1095
	}
1096
}
1097
1098
// http://doc.spip.org/@nom_jour
1099
function nom_jour($numdate, $forme = '') {
1100
	if(!($forme == 'abbr' OR $forme == 'initiale')) $forme = '';
1101
	return affdate_base($numdate, 'nom_jour', $forme);
1102
}
1103
1104
// http://doc.spip.org/@jour
1105
function jour($numdate) {
1106
	return affdate_base($numdate, 'jour');
1107
}
1108
1109
// http://doc.spip.org/@journum
1110
function journum($numdate) {
1111
	return affdate_base($numdate, 'journum');
1112
}
1113
1114
// http://doc.spip.org/@mois
1115
function mois($numdate) {
1116
	return affdate_base($numdate, 'mois');
1117
}
1118
1119
// http://doc.spip.org/@nom_mois
1120
function nom_mois($numdate, $forme='') {
1121
	if(!($forme == 'abbr')) $forme = '';
1122
	return affdate_base($numdate, 'nom_mois', $forme);
1123
}
1124
1125
// http://doc.spip.org/@annee
1126
function annee($numdate) {
1127
	return affdate_base($numdate, 'annee');
1128
}
1129
1130
// http://doc.spip.org/@saison
1131
function saison($numdate) {
1132
	return affdate_base($numdate, 'saison');
1133
}
1134
1135
// http://doc.spip.org/@saison_annee
1136
function saison_annee($numdate) {
1137
	return affdate_base($numdate, 'saison_annee');
1138
}
1139
1140
// http://doc.spip.org/@affdate
1141
function affdate($numdate, $format='entier') {
1142
	return affdate_base($numdate, $format);
1143
}
1144
1145
// http://doc.spip.org/@affdate_court
1146
function affdate_court($numdate, $annee_courante=null) {
1147
	return affdate_base($numdate, 'court', array('annee_courante'=>$annee_courante));
1148
}
1149
1150
// http://doc.spip.org/@affdate_jourcourt
1151
function affdate_jourcourt($numdate, $annee_courante=null) {
1152
	return affdate_base($numdate, 'jourcourt', array('annee_courante'=>$annee_courante));
1153
}
1154
1155
// http://doc.spip.org/@affdate_mois_annee
1156
function affdate_mois_annee($numdate) {
1157
	return affdate_base($numdate, 'mois_annee');
1158
}
1159
1160
// http://doc.spip.org/@affdate_heure
1161
function affdate_heure($numdate) {
1162
	$date_array = recup_date($numdate);
1163
	if (!$date_array) return;
1164
	list($annee, $mois, $jour, $heures, $minutes, $sec)= $date_array;
0 ignored issues
show
Unused Code introduced by
The assignment to $annee is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $mois is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $jour is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $sec is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1165
	return _T('date_fmt_jour_heure', array('jour' => affdate($numdate), 'heure' =>  _T('date_fmt_heures_minutes', array('h'=> $heures, 'm'=> $minutes))));
1166
}
1167
1168
/**
1169
 * Afficher de facon textuelle les dates de debut et fin en fonction des cas
1170
 * - Lundi 20 fevrier a 18h
1171
 * - Le 20 fevrier de 18h a 20h
1172
 * - Du 20 au 23 fevrier
1173
 * - Du 20 fevrier au 30 mars
1174
 * - Du 20 fevrier 2007 au 30 mars 2008
1175
 * $horaire='oui' ou true permet d'afficher l'horaire, toute autre valeur n'indique que le jour
1176
 * $forme peut contenir une ou plusieurs valeurs parmi
1177
 *  - abbr (afficher le nom des jours en abrege)
1178
 *  - hcal (generer une date au format hcal)
1179
 *  - jour (forcer l'affichage des jours)
1180
 *  - annee (forcer l'affichage de l'annee)
1181
 *
1182
 * @param string $date_debut
1183
 * @param string $date_fin
1184
 * @param string $horaire
1185
 * @param string $forme
1186
 *   abbr pour afficher le nom du jour en abrege (Dim. au lieu de Dimanche)
1187
 *   annee pour forcer l'affichage de l'annee courante
1188
 *   jour pour forcer l'affichage du nom du jour
1189
 *   hcal pour avoir un markup microformat abbr
1190
 * @return string
1191
 */
1192
function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme=''){
1193
	$abbr = $jour = '';
1194
	$affdate = "affdate_jourcourt";
1195
	if (strpos($forme,'abbr') !==false) $abbr = 'abbr';
1196
	if (strpos($forme,'annee')!==false) $affdate = 'affdate';
1197
	if (strpos($forme,'jour') !==false) $jour = 'jour';
1198
	
1199
	$dtstart = $dtend = $dtabbr = "";
1200
	if (strpos($forme,'hcal')!==false) {
1201
		$dtstart = "<abbr class='dtstart' title='".date_iso($date_debut)."'>";
1202
		$dtend = "<abbr class='dtend' title='".date_iso($date_fin)."'>";
1203
		$dtabbr = "</abbr>";
1204
	}
1205
1206
	$date_debut = strtotime($date_debut);
1207
	$date_fin = strtotime($date_fin);
1208
	$d = date("Y-m-d", $date_debut);
1209
	$f = date("Y-m-d", $date_fin);
1210
	$h = ($horaire==='oui' OR $horaire===true);
1211
	$hd = _T('date_fmt_heures_minutes_court', array('h'=> date("H",$date_debut), 'm'=> date("i",$date_debut)));
1212
	$hf = _T('date_fmt_heures_minutes_court', array('h'=> date("H",$date_fin), 'm'=> date("i",$date_fin)));
1213
1214
	if ($d==$f)
1215
	{ // meme jour
1216
		$nomjour = nom_jour($d,$abbr);
1217
		$s = $affdate($d);
1218
		$s = _T('date_fmt_jour',array('nomjour'=>$nomjour,'jour' => $s));
1219
		if ($h){
1220
			if ($hd==$hf){
1221
				// Lundi 20 fevrier a 18h25
1222
				$s = spip_ucfirst(_T('date_fmt_jour_heure',array('jour'=>$s,'heure'=>$hd)));
1223
				$s = "$dtstart$s$dtabbr";
1224
			}else{
1225
				// Le <abbr...>lundi 20 fevrier de 18h00</abbr> a <abbr...>20h00</abbr>
1226
				if($dtabbr && $dtstart && $dtend)
1227
					$s = _T('date_fmt_jour_heure_debut_fin_abbr',array('jour'=>spip_ucfirst($s),'heure_debut'=>$hd,'heure_fin'=>$hf,'dtstart'=>$dtstart,'dtend'=>$dtend,'dtabbr'=>$dtabbr));
1228
				// Le lundi 20 fevrier de 18h00 a 20h00
1229
				else
1230
					$s = spip_ucfirst(_T('date_fmt_jour_heure_debut_fin',array('jour'=>$s,'heure_debut'=>$hd,'heure_fin'=>$hf)));
1231
			}
1232
		}else{
1233
			if($dtabbr && $dtstart)
1234
				$s = $dtstart.spip_ucfirst($s).$dtabbr;
1235
			else
1236
				$s = spip_ucfirst($s);
1237
		}
1238
	}
1239
	else if ((date("Y-m",$date_debut))==date("Y-m",$date_fin))
1240
	{ // meme annee et mois, jours differents
1241
		if(!$h)
1242
			$date_debut = jour($d);
1243
		else
1244
			$date_debut = affdate_jourcourt($d,date("Y",$date_fin));
1245
		$date_fin = $affdate($f);
1246 View Code Duplication
		if($jour){
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...
1247
			$nomjour_debut = nom_jour($d,$abbr);
1248
			$date_debut = _T('date_fmt_jour',array('nomjour'=>$nomjour_debut,'jour' => $date_debut));
1249
			$nomjour_fin = nom_jour($f,$abbr);
1250
			$date_fin = _T('date_fmt_jour',array('nomjour'=>$nomjour_fin,'jour' => $date_fin));
1251
		}
1252 View Code Duplication
		if ($h){
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...
1253
			$date_debut = _T('date_fmt_jour_heure',array('jour'=>$date_debut,'heure'=>$hd));
1254
			$date_fin = _T('date_fmt_jour_heure',array('jour'=>$date_fin,'heure'=>$hf));
1255
		}
1256
		$date_debut = $dtstart.$date_debut.$dtabbr;
1257
		$date_fin = $dtend.$date_fin.$dtabbr;
1258
		
1259
		$s = _T('date_fmt_periode',array('date_debut' => $date_debut,'date_fin'=>$date_fin));
1260
	}
1261
	else {
1262
		$date_debut = affdate_jourcourt($d,date("Y",$date_fin));
1263
		$date_fin = $affdate($f);
1264 View Code Duplication
		if($jour){
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...
1265
			$nomjour_debut = nom_jour($d,$abbr);
1266
			$date_debut = _T('date_fmt_jour',array('nomjour'=>$nomjour_debut,'jour' => $date_debut));
1267
			$nomjour_fin = nom_jour($f,$abbr);
1268
			$date_fin = _T('date_fmt_jour',array('nomjour'=>$nomjour_fin,'jour' => $date_fin));
1269
		}
1270 View Code Duplication
		if ($h){
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...
1271
			$date_debut = _T('date_fmt_jour_heure',array('jour'=>$date_debut,'heure'=>$hd)); 
1272
			$date_fin = _T('date_fmt_jour_heure',array('jour'=>$date_fin,'heure'=>$hf));
1273
		}
1274
		
1275
		$date_debut = $dtstart.$date_debut.$dtabbr;
1276
		$date_fin=$dtend.$date_fin.$dtabbr;
1277
		$s = _T('date_fmt_periode',array('date_debut' => $date_debut,'date_fin'=>$date_fin));
1278
		
1279
	}
1280
	return $s;
1281
}
1282
1283
/**
1284
 * Alignements en HTML (Old-style, preferer CSS)
1285
 * Cette fonction ne cree pas de paragraphe
1286
 *
1287
 * http://doc.spip.org/@aligner
1288
 *
1289
 * @param  $letexte
1290
 * @param string $justif
1291
 * @return string
1292
 */
1293
function aligner($letexte, $justif='') {
1294
	$letexte = trim($letexte);
1295
	if (!strlen($letexte)) return '';
1296
1297
	// Paragrapher rapidement
1298
	$letexte = "<div style='text-align:$justif'>"
1299
		. $letexte
1300
	  ."</div>";
1301
1302
	return $letexte;
1303
}
1304
// http://doc.spip.org/@justifier
1305
function justifier($letexte) { return aligner($letexte,'justify');}
1306
// http://doc.spip.org/@aligner_droite
1307
function aligner_droite($letexte) { return aligner($letexte,'right');}
1308
// http://doc.spip.org/@aligner_gauche
1309
function aligner_gauche($letexte) {return aligner($letexte,'left');}
1310
// http://doc.spip.org/@centrer
1311
function centrer($letexte) {return aligner($letexte,'center');}
1312
1313
// http://doc.spip.org/@style_align
1314
function style_align($bof) {
0 ignored issues
show
Unused Code introduced by
The parameter $bof 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...
1315
	global $spip_lang_left;
1316
	return "text-align: $spip_lang_left";
1317
}
1318
1319
//
1320
// Export iCal
1321
//
1322
1323
// http://doc.spip.org/@filtrer_ical
1324
function filtrer_ical($texte) {
1325
	#include_spip('inc/charsets');
1326
	$texte = html2unicode($texte);
1327
	$texte = unicode2charset(charset2unicode($texte, $GLOBALS['meta']['charset'], 1), 'utf-8');
0 ignored issues
show
Unused Code introduced by
The call to charset2unicode() has too many arguments starting with 1.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1328
	$texte = preg_replace("/\n/", " ", $texte);
1329
	$texte = preg_replace("/,/", "\,", $texte);
1330
1331
	return $texte;
1332
}
1333
1334
// http://doc.spip.org/@date_ical
1335
function date_ical($date, $addminutes = 0) {
1336
	list($heures, $minutes, $secondes) = recup_heure($date);
1337
	list($annee, $mois, $jour) = recup_date($date);
1338
	return date("Ymd\THis", 
1339
		    mktime($heures, $minutes+$addminutes,$secondes,$mois,$jour,$annee));
1340
}
1341
1342
// date_iso retourne la date au format "RFC 3339" / "ISO 8601"
1343
// voir http://www.php.net/manual/fr/ref.datetime.php#datetime.constants
1344
// http://doc.spip.org/@date_iso
1345 View Code Duplication
function date_iso($date_heure) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
1346
	list($annee, $mois, $jour) = recup_date($date_heure);
1347
	list($heures, $minutes, $secondes) = recup_heure($date_heure);
1348
	$time = @mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
1349
	return gmdate('Y-m-d\TH:i:s\Z', $time);
1350
}
1351
1352
// date_822 retourne la date au format "RFC 822"
1353
// utilise pour <pubdate> dans certains feeds RSS
1354
// http://doc.spip.org/@date_822
1355 View Code Duplication
function date_822($date_heure) {
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...
1356
	list($annee, $mois, $jour) = recup_date($date_heure);
1357
	list($heures, $minutes, $secondes) = recup_heure($date_heure);
1358
	$time = mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
1359
	return date('r', $time);
1360
}
1361
1362
// http://doc.spip.org/@date_anneemoisjour
1363
function date_anneemoisjour($d)  {
1364
	if (!$d) $d = date("Y-m-d");
1365
	return  substr($d, 0, 4) . substr($d, 5, 2) .substr($d, 8, 2);
1366
}
1367
1368
// http://doc.spip.org/@date_anneemois
1369
function date_anneemois($d)  {
1370
	if (!$d) $d = date("Y-m-d");
1371
	return  substr($d, 0, 4) . substr($d, 5, 2);
1372
}
1373
1374
// http://doc.spip.org/@date_debut_semaine
1375 View Code Duplication
function date_debut_semaine($annee, $mois, $jour) {
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...
1376
  $w_day = date("w", mktime(0,0,0,$mois, $jour, $annee));
1377
  if ($w_day == 0) $w_day = 7; // Gaffe: le dimanche est zero
1378
  $debut = $jour-$w_day+1;
1379
  return date("Ymd", mktime(0,0,0,$mois,$debut,$annee));
1380
}
1381
1382
// http://doc.spip.org/@date_fin_semaine
1383 View Code Duplication
function date_fin_semaine($annee, $mois, $jour) {
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...
1384
  $w_day = date("w", mktime(0,0,0,$mois, $jour, $annee));
1385
  if ($w_day == 0) $w_day = 7; // Gaffe: le dimanche est zero
1386
  $debut = $jour-$w_day+1;
1387
  return date("Ymd", mktime(0,0,0,$mois,$debut+6,$annee));
1388
}
1389
1390
1391
//
1392
// Recuperation de donnees dans le champ extra
1393
// Ce filtre n'a de sens qu'avec la balise #EXTRA
1394
//
1395
// http://doc.spip.org/@extra
1396
function extra($letexte, $champ) {
1397
	$champs = unserialize($letexte);
1398
	return $champs[$champ];
1399
}
1400
1401
// postautobr : transforme les sauts de ligne en _
1402
// http://doc.spip.org/@post_autobr
1403
function post_autobr($texte, $delim="\n_ ") {
1404
	if (!function_exists('echappe_html'))
1405
		include_spip('inc/texte_mini');
1406
	$texte = str_replace("\r\n", "\r", $texte);
1407
	$texte = str_replace("\r", "\n", $texte);
1408
1409 View Code Duplication
	if (preg_match(",\n+$,", $texte, $fin))
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...
1410
		$texte = substr($texte, 0, -strlen($fin = $fin[0]));
1411
	else
1412
		$fin = '';
1413
1414
	$texte = echappe_html($texte, '', true);
1415
1416
	// echapper les modeles
1417
	if (strpos($texte,"<")!==false){
1418
		include_spip('inc/lien');
1419
		if (defined('_PREG_MODELE')){
1420
			$preg_modeles = "@"._PREG_MODELE."@imsS";
1421
			$texte = echappe_html($texte, '', true, $preg_modeles);
1422
		}
1423
	}
1424
1425
	$debut = '';
1426
	$suite = $texte;
1427
	while ($t = strpos('-'.$suite, "\n", 1)) {
1428
		$debut .= substr($suite, 0, $t-1);
1429
		$suite = substr($suite, $t);
1430
		$car = substr($suite, 0, 1);
1431
		if (($car<>'-') AND ($car<>'_') AND ($car<>"\n") AND ($car<>"|") AND ($car<>"}")
1432
		AND !preg_match(',^\s*(\n|</?(quote|div|dl|dt|dd)|$),S',($suite))
1433
		AND !preg_match(',</?(quote|div|dl|dt|dd)> *$,iS', $debut)) {
1434
			$debut .= $delim;
1435
		} else
1436
			$debut .= "\n";
1437 View Code Duplication
		if (preg_match(",^\n+,", $suite, $regs)) {
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...
1438
			$debut.=$regs[0];
1439
			$suite = substr($suite, strlen($regs[0]));
1440
		}
1441
	}
1442
	$texte = $debut.$suite;
1443
1444
	$texte = echappe_retour($texte);
1445
	return $texte.$fin;
1446
}
1447
1448
1449
define('_EXTRAIRE_MULTI', "@<multi>(.*?)</multi>@sS");
1450
1451
// Extraire et transformer les blocs multi ; on indique la langue courante
1452
// pour ne pas mettre de span@lang=fr si on est deja en fr
1453
// http://doc.spip.org/@extraire_multi
1454
function extraire_multi($letexte, $lang=null, $echappe_span=false) {
1455
	if (preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)) {
1456
		if (!$lang) $lang = $GLOBALS['spip_lang'];
1457
1458
		foreach ($regs as $reg) {
1459
			// chercher la version de la langue courante
1460
			$trads = extraire_trads($reg[1]);
1461
			if ($l = approcher_langue($trads, $lang)) {
1462
				$trad = $trads[$l];
1463
			} else {
1464
				include_spip('inc/texte');
1465
				// langue absente, prendre la premiere dispo
1466
				// mais typographier le texte selon les regles de celle-ci
1467
				// Attention aux blocs multi sur plusieurs lignes
1468
				$l = key($trads);
1469
				$trad = $trads[$l];
1470
				$typographie = charger_fonction(lang_typo($l), 'typographie');
1471
				$trad = $typographie($trad);
1472
				include_spip('inc/texte');
1473
				// Tester si on echappe en span ou en div
1474
				// il ne faut pas echapper en div si propre produit un seul paragraphe
1475
				$trad_propre = preg_replace(",(^<p[^>]*>|</p>$),Uims","",propre($trad));
1476
				$mode = preg_match(',</?('._BALISES_BLOCS.')[>[:space:]],iS', $trad_propre) ? 'div' : 'span';
1477
				$trad = code_echappement($trad, 'multi', false, $mode);
1478
				$trad = str_replace("'", '"', inserer_attribut($trad, 'lang', $l));
1479
				if (lang_dir($l) !== lang_dir($lang))
1480
					$trad = str_replace("'", '"', inserer_attribut($trad, 'dir', lang_dir($l)));
1481
				if (!$echappe_span)
1482
					$trad = echappe_retour($trad, 'multi');
1483
			}
1484
			$letexte = str_replace($reg[0], $trad, $letexte);
1485
		}
1486
	}
1487
1488
	return $letexte;
1489
}
1490
1491
// convertit le contenu d'une balise multi en un tableau
1492
// http://doc.spip.org/@extraire_trad
1493
function extraire_trads($bloc) {
1494
	$lang = '';
1495
// ce reg fait planter l'analyse multi s'il y a de l'{italique} dans le champ
1496
//	while (preg_match("/^(.*?)[{\[]([a-z_]+)[}\]]/siS", $bloc, $regs)) {
1497
	while (preg_match("/^(.*?)[\[]([a-z_]+)[\]]/siS", $bloc, $regs)) {
1498
		$texte = trim($regs[1]);
1499
		if ($texte OR $lang)
1500
			$trads[$lang] = $texte;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$trads was never initialized. Although not strictly required by PHP, it is generally a good practice to add $trads = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1501
		$bloc = substr($bloc, strlen($regs[0]));
1502
		$lang = $regs[2];
1503
	}
1504
	$trads[$lang] = $bloc;
0 ignored issues
show
Bug introduced by
The variable $trads does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1505
1506
	return $trads;
1507
}
1508
1509
// Calculer l'initiale d'un nom
1510
function initiale($nom){
1511
	return spip_substr(trim(strtoupper(extraire_multi($nom))),0,1);
1512
}
1513
1514
//
1515
// Ce filtre retourne la donnee si c'est la premiere fois qu'il la voit ;
1516
// possibilite de gerer differentes "familles" de donnees |unique{famille}
1517
# |unique{famille,1} affiche le nombre d'elements affiches (preferer toutefois #TOTAL_UNIQUE)
1518
# ameliorations possibles :
1519
# 1) si la donnee est grosse, mettre son md5 comme cle
1520
# 2) purger $mem quand on change de squelette (sinon bug inclusions)
1521
//
1522
// http://www.spip.net/@unique
1523
// http://doc.spip.org/@unique
1524
function unique($donnee, $famille='', $cpt = false) {
1525
	static $mem = array();
1526
	// permettre de vider la pile et de la restaurer
1527
	// pour le calcul de introduction...
1528
	if ($famille=='_spip_raz_'){
1529
		$tmp = $mem;
1530
		$mem = array();
1531
		return $tmp;
1532
	} elseif ($famille=='_spip_set_'){
1533
		$mem = $donnee;
1534
		return;
1535
	}
1536
	// eviter une notice
1537
	if (!isset($mem[$famille])) {
1538
		$mem[$famille] = array();
1539
	}
1540
	if ($cpt) {
1541
		return count($mem[$famille]);
1542
	}
1543
	// eviter une notice
1544
	if (!isset($mem[$famille][$donnee])) {
1545
		$mem[$famille][$donnee] = 0;
1546
	}
1547
	if (!($mem[$famille][$donnee]++)) {
1548
		return $donnee;
1549
	}
1550
}
1551
1552
//
1553
// Filtre |alterner
1554
//
1555
// Exemple [(#COMPTEUR_BOUCLE|alterner{'bleu','vert','rouge'})]
1556
//
1557
// http://doc.spip.org/@alterner
1558
function alterner($i) {
1559
	// recuperer les arguments (attention fonctions un peu space)
1560
	$num = func_num_args();
1561
	$args = func_get_args();
1562
1563
	if($num == 2 && is_array($args[1])) {
1564
    $args = $args[1];
1565
    array_unshift($args,'');
1566
    $num = count($args);
1567
  }
1568
1569
	// renvoyer le i-ieme argument, modulo le nombre d'arguments
1570
	return $args[(intval($i)-1)%($num-1)+1];
1571
}
1572
1573
// recuperer un attribut d'une balise html
1574
// ($complet demande de retourner $r)
1575
// la regexp est mortelle : cf. tests/filtres/extraire_attribut.php
1576
// Si on a passe un tableau de balises, renvoyer un tableau de resultats
1577
// (dans ce cas l'option $complet n'est pas disponible)
1578
// http://doc.spip.org/@extraire_attribut
1579
function extraire_attribut($balise, $attribut, $complet = false) {
1580
	if (is_array($balise)) {
1581
		array_walk($balise,
1582
			create_function('&$a,$key,$t',
1583
				'$a = extraire_attribut($a,$t);'
1584
			),
1585
			$attribut);
1586
		return $balise;
1587
	}
1588
	if (preg_match(
1589
	',(^.*?<(?:(?>\s*)(?>[\w:.-]+)(?>(?:=(?:"[^"]*"|\'[^\']*\'|[^\'"]\S*))?))*?)(\s+'
1590
	.$attribut
1591
	.'(?:=\s*("[^"]*"|\'[^\']*\'|[^\'"]\S*))?)()([^>]*>.*),isS',
1592
1593
	$balise, $r)) {
1594
		if ($r[3][0] == '"' || $r[3][0] == "'") {
1595
			$r[4] = substr($r[3], 1, -1);
1596
			$r[3] = $r[3][0];
1597
		} elseif ($r[3]!=='') {
1598
			$r[4] = $r[3]; 
1599
			$r[3] = '';
1600
		} else {
1601
			$r[4] = trim($r[2]); 
1602
		}
1603
		$att = $r[4];
1604 View Code Duplication
		if (strpos($att,"&#")!==false)
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...
1605
			$att = str_replace(array("&#039;","&#39;","&#034;","&#34;"), array("'","'",'"','"'), $att);
1606
		$att = filtrer_entites($att);
1607
	}
1608
	else
1609
		$att = NULL;
1610
1611
	if ($complet)
1612
		return array($att, $r);
1613
	else
1614
		return $att;
1615
}
1616
1617
/**
1618
 * modifier (ou inserer) un attribut html dans une balise
1619
 *
1620
 * http://doc.spip.org/@inserer_attribut
1621
 *
1622
 * @param string $balise
1623
 * @param string $attribut
1624
 * @param string $val
1625
 * @param bool $proteger
1626
 * @param bool $vider
1627
 * @return string
1628
 */
1629
function inserer_attribut($balise, $attribut, $val, $proteger=true, $vider=false) {
1630
	// preparer l'attribut
1631
	// supprimer les &nbsp; etc mais pas les balises html
1632
	// qui ont un sens dans un attribut value d'un input
1633
	if ($proteger) $val = attribut_html($val,false);
1634
1635
	// echapper les ' pour eviter tout bug
1636
	$val = str_replace("'", "&#039;", $val);
1637
	if ($vider AND strlen($val)==0)
1638
		$insert = '';
1639
	else
1640
		$insert = " $attribut='$val'";
1641
1642
	list($old, $r) = extraire_attribut($balise, $attribut, true);
1643
1644
	if ($old !== NULL) {
1645
		// Remplacer l'ancien attribut du meme nom
1646
		$balise = $r[1].$insert.$r[5];
1647
	}
1648
	else {
1649
		// preferer une balise " />" (comme <img />)
1650
		if (preg_match(',/>,', $balise))
1651
			$balise = preg_replace(",\s?/>,S", $insert." />", $balise, 1);
1652
		// sinon une balise <a ...> ... </a>
1653
		else
1654
			$balise = preg_replace(",\s?>,S", $insert.">", $balise, 1);
1655
	}
1656
1657
	return $balise;
1658
}
1659
1660
// http://doc.spip.org/@vider_attribut
1661
function vider_attribut ($balise, $attribut) {
1662
	return inserer_attribut($balise, $attribut, '', false, true);
1663
}
1664
1665
1666
/**
1667
 * Un filtre pour determiner le nom du satut des inscrits
1668
 *
1669
 * @param void|int $id
1670
 * @param string $mode
1671
 * @return string
1672
 */
1673
function tester_config($id, $mode='') {
1674
	include_spip('action/inscrire_auteur');
1675
	return tester_statut_inscription($mode, $id);
1676
}
1677
1678
//
1679
// Quelques fonctions de calcul arithmetique
1680
//
1681
// http://doc.spip.org/@plus
1682
function plus($a,$b) {
1683
	return $a+$b;
1684
}
1685
// http://doc.spip.org/@moins
1686
function moins($a,$b) {
1687
	return $a-$b;
1688
}
1689
// http://doc.spip.org/@mult
1690
function mult($a,$b) {
1691
	return $a*$b;
1692
}
1693
// http://doc.spip.org/@div
1694
function div($a,$b) {
1695
	return $b?$a/$b:0;
1696
}
1697
// http://doc.spip.org/@modulo
1698
function modulo($nb, $mod, $add=0) {
1699
	return ($mod?$nb%$mod:0)+$add;
1700
}
1701
1702
1703
/**
1704
 * Vérifie qu'un nom (d'auteur) ne comporte pas d'autres tags que <multi>
1705
 * et ceux volontairement spécifiés dans la constante
1706
 *
1707
 * @param string $nom
1708
 *      Nom (signature) proposé
1709
 * @return bool
1710
 *      - false si pas conforme,
1711
 *      - true sinon
1712
**/
1713
function nom_acceptable($nom) {
1714
	if (!is_string($nom)) {
1715
		return false;
1716
	}
1717
	if (!defined('_TAGS_NOM_AUTEUR')) define('_TAGS_NOM_AUTEUR','');
1718
	$tags_acceptes = array_unique(explode(',', 'multi,' . _TAGS_NOM_AUTEUR));
1719
	foreach($tags_acceptes as $tag) {
1720
		if (strlen($tag)) {
1721
			$remp1[] = '<'.trim($tag).'>';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$remp1 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $remp1 = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1722
			$remp1[] = '</'.trim($tag).'>';
0 ignored issues
show
Bug introduced by
The variable $remp1 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1723
			$remp2[] = '\x60'.trim($tag).'\x61';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$remp2 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $remp2 = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1724
			$remp2[] = '\x60/'.trim($tag).'\x61';
1725
		}
1726
	}	
1727
	$v_nom = str_replace($remp2, $remp1, supprimer_tags(str_replace($remp1, $remp2, $nom)));
0 ignored issues
show
Bug introduced by
The variable $remp2 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1728
	return str_replace('&lt;', '<', $v_nom) == $nom;
1729
}
1730
1731
// Verifier la conformite d'une ou plusieurs adresses email
1732
//  retourne false ou la  normalisation de la derniere adresse donnee
1733
// http://doc.spip.org/@email_valide
1734
function email_valide($adresses) {
1735
	// eviter d'injecter n'importe quoi dans preg_match
1736
	if (!is_string($adresses))
1737
		return false;
1738
1739
	// Si c'est un spammeur autant arreter tout de suite
1740
	if (preg_match(",[\n\r].*(MIME|multipart|Content-),i", $adresses)) {
1741
		spip_log("Tentative d'injection de mail : $adresses");
1742
		return false;
1743
	}
1744
1745
	foreach (explode(',', $adresses) as $v) {
1746
		// nettoyer certains formats
1747
		// "Marie Toto <[email protected]>"
1748
		$adresse = trim(preg_replace(",^[^<>\"]*<([^<>\"]+)>$,i", "\\1", $v));
1749
		// RFC 822
1750
		if (!preg_match('#^[^()<>@,;:\\"/[:space:]]+(@([-_0-9a-z]+\.)*[-_0-9a-z]+)$#i', $adresse))
1751
			return false;
1752
	}
1753
	return $adresse;
0 ignored issues
show
Bug introduced by
The variable $adresse does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1754
}
1755
1756
// http://doc.spip.org/@afficher_enclosures
1757
function afficher_enclosures($tags) {
1758
	$s = array();
1759
	foreach (extraire_balises($tags, 'a') as $tag) {
1760
		if (extraire_attribut($tag, 'rel') == 'enclosure'
1761
		AND $t = extraire_attribut($tag, 'href')) {
1762
			$s[] = preg_replace(',>[^<]+</a>,S', 
1763
				'>'
1764
				.http_img_pack('attachment-16.png', $t,
1765
					'title="'.attribut_html($t).'"')
1766
				.'</a>', $tag);
1767
		}
1768
	}
1769
	return join('&nbsp;', $s);
1770
}
1771
// http://doc.spip.org/@afficher_tags
1772
function afficher_tags($tags, $rels='tag,directory') {
1773
	$s = array();
1774
	foreach (extraire_balises($tags, 'a') as $tag) {
1775
		$rel = extraire_attribut($tag, 'rel');
1776
		if (strstr(",$rels,", ",$rel,"))
1777
			$s[] = $tag;
1778
	}
1779
	return join(', ', $s);
1780
}
1781
1782
// Passe un <enclosure url="fichier" length="5588242" type="audio/mpeg"/>
1783
// au format microformat <a rel="enclosure" href="fichier" ...>fichier</a>
1784
// attention length="zz" devient title="zz", pour rester conforme
1785
// http://doc.spip.org/@enclosure2microformat
1786
function enclosure2microformat($e) {
1787
	if (!$url = filtrer_entites(extraire_attribut($e, 'url')))
1788
		$url = filtrer_entites(extraire_attribut($e, 'href'));
1789
	$type = extraire_attribut($e, 'type');
1790
	if (!$length = extraire_attribut($e, 'length')) {
1791
		# <media:content : longeur dans fileSize. On tente.
1792
		$length = extraire_attribut($e, 'fileSize');
1793
	}
1794
	$fichier = basename($url);
1795
	return '<a rel="enclosure"'
1796
		. ($url? ' href="'.spip_htmlspecialchars($url).'"' : '')
1797
		. ($type? ' type="'.spip_htmlspecialchars($type).'"' : '')
1798
		. ($length? ' title="'.spip_htmlspecialchars($length).'"' : '')
1799
		. '>'.$fichier.'</a>';
1800
}
1801
// La fonction inverse
1802
// http://doc.spip.org/@microformat2enclosure
1803
function microformat2enclosure($tags) {
1804
	$enclosures = array();
1805
	foreach (extraire_balises($tags, 'a') as $e)
1806
	if (extraire_attribut($e, 'rel') == 'enclosure') {
1807
		$url = filtrer_entites(extraire_attribut($e, 'href'));
1808
		$type = extraire_attribut($e, 'type');
1809
		if (!$length = intval(extraire_attribut($e, 'title')))
1810
			$length = intval(extraire_attribut($e, 'length')); # vieux data
1811
		$fichier = basename($url);
0 ignored issues
show
Unused Code introduced by
$fichier 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...
1812
		$enclosures[] = '<enclosure'
1813
			. ($url? ' url="'.spip_htmlspecialchars($url).'"' : '')
1814
			. ($type? ' type="'.spip_htmlspecialchars($type).'"' : '')
1815
			. ($length? ' length="'.$length.'"' : '')
1816
			. ' />';
1817
	}
1818
	return join("\n", $enclosures);
1819
}
1820
// Creer les elements ATOM <dc:subject> a partir des tags
1821
// http://doc.spip.org/@tags2dcsubject
1822
function tags2dcsubject($tags) {
1823
	$subjects = '';
1824
	foreach (extraire_balises($tags, 'a') as $e) {
1825
		if (extraire_attribut($e, rel) == 'tag') {
1826
			$subjects .= '<dc:subject>'
1827
				. texte_backend(textebrut($e))
1828
				. '</dc:subject>'."\n";
1829
		}
1830
	}
1831
	return $subjects;
1832
}
1833
1834
// retourne la premiere balise du type demande
1835
// ex: [(#DESCRIPTIF|extraire_balise{img})]
1836
// Si on a passe un tableau de textes, renvoyer un tableau de resultats
1837
// http://doc.spip.org/@extraire_balise
1838
function extraire_balise($texte, $tag='a') {
1839
	if (is_array($texte)) {
1840
		array_walk($texte,
1841
			create_function('&$a,$key,$t', '$a = extraire_balise($a,$t);'),
1842
			$tag);
1843
		return $texte;
1844
	}
1845
1846
	if (preg_match(
1847
	",<$tag\b[^>]*(/>|>.*</$tag\b[^>]*>|>),UimsS",
1848
	$texte, $regs))
1849
		return $regs[0];
1850
}
1851
1852
// extraire toutes les balises du type demande, sous forme de tableau
1853
// Si on a passe un tableau de textes, renvoyer un tableau de resultats
1854
// http://doc.spip.org/@extraire_balises
1855
function extraire_balises($texte, $tag='a') {
1856
	if (is_array($texte)) {
1857
		array_walk($texte,
1858
			create_function('&$a,$key,$t', '$a = extraire_balises($a,$t);'),
1859
			$tag);
1860
		return $texte;
1861
	}
1862
1863
	if (preg_match_all(
1864
	",<${tag}\b[^>]*(/>|>.*</${tag}\b[^>]*>|>),UimsS",
1865
	$texte, $regs, PREG_PATTERN_ORDER))
1866
		return $regs[0];
1867
	else
1868
		return array();
1869
}
1870
1871
// comme in_array mais renvoie son 3e arg si le 2er arg n'est pas un tableau
1872
// prend ' ' comme representant de vrai et '' de faux
1873
1874
// http://doc.spip.org/@in_any
1875
function in_any($val, $vals, $def='') {
1876
	if (!is_array($vals) AND $v=unserialize($vals)) $vals = $v;
1877
  return (!is_array($vals) ? $def : (in_array($val, $vals) ? ' ' : ''));
1878
}
1879
1880
// valeur_numerique("3*2") => 6
1881
// n'accepte que les *, + et - (a ameliorer si on l'utilise vraiment)
1882
// http://doc.spip.org/@valeur_numerique
1883
function valeur_numerique($expr) {
1884
	$a = 0;
1885
	if (preg_match(',^[0-9]+(\s*[+*-]\s*[0-9]+)*$,S', trim($expr)))
1886
		eval("\$a = $expr;");
1887
	return intval($a);
1888
}
1889
1890
// http://doc.spip.org/@regledetrois
1891
function regledetrois($a,$b,$c)
1892
{
1893
  return round($a*$b/$c);
1894
}
1895
1896
// Fournit la suite de Input-Hidden correspondant aux parametres de
1897
// l'URL donnee en argument, compatible avec les types_urls depuis [14447].
1898
// cf. tests/filtres/form_hidden.html
1899
// http://doc.spip.org/@form_hidden
1900
function form_hidden($action) {
1901
1902
	$contexte = array();
1903
	include_spip('inc/urls');
1904
	if ($p = urls_decoder_url($action, '')
1905
		AND reset($p)) {
1906
		$fond = array_shift($p);
1907
		if ($fond!='404'){
1908
			$contexte = array_shift($p);
1909
			$contexte['page'] = $fond;
1910
			$action = preg_replace('/([?]'.preg_quote($fond).'[^&=]*[0-9]+)(&|$)/', '?&', $action);
1911
		}
1912
	}
1913
	// defaire ce qu'a injecte urls_decoder_url : a revoir en modifiant la signature de urls_decoder_url
1914
	if (defined('_DEFINIR_CONTEXTE_TYPE') AND _DEFINIR_CONTEXTE_TYPE)
1915
		unset($contexte['type']);
1916
	if (defined('_DEFINIR_CONTEXTE_TYPE_PAGE') AND _DEFINIR_CONTEXTE_TYPE_PAGE)
1917
		unset($contexte['type-page']);
1918
1919
	// on va remplir un tableau de valeurs en prenant bien soin de ne pas
1920
	// ecraser les elements de la forme mots[]=1&mots[]=2
1921
	$values = array();
1922
1923
	// d'abord avec celles de l'url
1924
	if (false !== ($p = strpos($action, '?'))) {
1925
		foreach(preg_split('/&(amp;)?/S',substr($action,$p+1)) as $c){
1926
			list($var,$val) = explode('=', $c, 2);
1927
			if ($var) {
1928
				$val =  rawurldecode($val);
1929
				$var =  rawurldecode($var); // decoder les [] eventuels
1930 View Code Duplication
				if (preg_match(',\[\]$,S', $var))
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...
1931
					$values[] = array($var, $val);
1932
				else if (!isset($values[$var]))
1933
					$values[$var] = array($var, $val);
1934
			}
1935
		}
1936
	}
1937
1938
	// ensuite avec celles du contexte, sans doublonner !
1939
	foreach($contexte as $var=>$val)
1940 View Code Duplication
		if (preg_match(',\[\]$,S', $var))
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...
1941
			$values[] = array($var, $val);
1942
		else if (!isset($values[$var]))
1943
			$values[$var] = array($var, $val);
1944
1945
	// puis on rassemble le tout
1946
	$hidden = array();
1947
	foreach($values as $value) {
1948
		list($var,$val) = $value;
1949
		$hidden[] = '<input name="'
1950
			. entites_html($var)
1951
			.'"'
1952
			. (is_null($val)
1953
				? ''
1954
				: ' value="'.entites_html($val).'"'
1955
				)
1956
			. ' type="hidden"'."\n/>";
1957
	}
1958
	return join("", $hidden);
1959
}
1960
1961
// http://doc.spip.org/@filtre_bornes_pagination_dist
1962
function filtre_bornes_pagination_dist($courante, $nombre, $max = 10) {
1963
	if($max<=0 OR $max>=$nombre)
1964
		return array(1, $nombre);
1965
1966
	$premiere = max(1, $courante-floor(($max-1)/2));
1967
	$derniere = min($nombre, $premiere+$max-2);
1968
	$premiere = $derniere == $nombre ? $derniere-$max+1 : $premiere;
1969
	return array($premiere, $derniere);
1970
}
1971
1972
1973
// Ces trois fonctions permettent de simuler les filtres |reset et |end
1974
// pour extraire la premiere ou la derniere valeur d'un tableau ; utile
1975
// pour la pagination (mais peut-etre a refaire plus simplement)
1976
// http://doc.spip.org/@filtre_valeur_tableau
1977
function filtre_valeur_tableau($array, $index) {
1978
	if (!is_array($array)
1979
	OR !isset($array[$index]))
1980
		return null;
1981
	return $array[$index];
1982
}
1983
// http://doc.spip.org/@filtre_reset
1984
function filtre_reset($array) {
1985
	return !is_array($array) ? null : reset($array);
1986
}
1987
// http://doc.spip.org/@filtre_end
1988
function filtre_end($array) {
1989
	return !is_array($array) ? null : end($array);
1990
}
1991
1992
// http://doc.spip.org/@filtre_push
1993
function filtre_push($array, $val) {
1994
	if($array == '' OR !array_push($array, $val)) return '';
1995
	return $array;
1996
}
1997
1998
// http://doc.spip.org/@filtre_find
1999
function filtre_find($array, $val) {
2000
	return (is_array($array) AND in_array($val, $array));
2001
}
2002
2003
2004
//
2005
// fonction standard de calcul de la balise #PAGINATION
2006
// on peut la surcharger en definissant filtre_pagination dans mes_fonctions
2007
//
2008
2009
// http://doc.spip.org/@filtre_pagination_dist
2010
function filtre_pagination_dist($total, $nom, $position, $pas, $liste = true, $modele='', $connect='', $env=array()) {
2011
	static $ancres = array();
2012
	if ($pas<1) return '';
2013
	$ancre = 'pagination'.$nom; // #pagination_articles
2014
	$debut = 'debut'.$nom; // 'debut_articles'
2015
2016
	// n'afficher l'ancre qu'une fois
2017
	if (!isset($ancres[$ancre]))
2018
		$bloc_ancre = $ancres[$ancre] = "<a name='".$ancre."' id='".$ancre."'></a>";
2019
	else $bloc_ancre = '';
2020
	// liste = false : on ne veut que l'ancre
2021
	if (!$liste)
2022
		return $ancres[$ancre];
2023
2024
	$pagination = array(
2025
		'debut' => $debut,
2026
		'url' => parametre_url(self(),'fragment',''), // nettoyer l'id ahah eventuel
2027
		'total' => $total,
2028
		'position' => intval($position),
2029
		'pas' => $pas,
2030
		'nombre_pages' => floor(($total-1)/$pas)+1,
2031
		'page_courante' => floor(intval($position)/$pas)+1,
2032
		'ancre' => $ancre,
2033
		'bloc_ancre' => $bloc_ancre
2034
	);
2035
	if (is_array($env))
2036
		$pagination = array_merge($env,$pagination);
2037
2038
	// Pas de pagination
2039
	if ($pagination['nombre_pages']<=1)
2040
		return '';
2041
2042
	if ($modele) $modele = '_'.$modele;
2043
2044
	return recuperer_fond("modeles/pagination$modele", $pagination, array('trim'=>true), $connect);
2045
}
2046
2047
// passer les url relatives a la css d'origine en url absolues
2048
// http://doc.spip.org/@urls_absolues_css
2049
function urls_absolues_css($contenu, $source) {
2050
	$path = suivre_lien(url_absolue($source),'./');
2051
2052
	return preg_replace_callback(
2053
		",url\s*\(\s*['\"]?([^'\"/][^:]*)['\"]?\s*\),Uims",
2054
		create_function('$x',
2055
			'return "url(\"".suivre_lien("'.$path.'",$x[1])."\")";'
2056
		), $contenu);
2057
}
2058
2059
// recuperere le chemin d'une css existante et :
2060
// 1. regarde si une css inversee droite-gauche existe dans le meme repertoire
2061
// 2. sinon la cree (ou la recree) dans _DIR_VAR/cache_css/
2062
// SI on lui donne a manger une feuille nommee _rtl.css il va faire l'inverse
2063
// http://doc.spip.org/@direction_css
2064
function direction_css ($css, $voulue='') {
2065
	if (!preg_match(',(_rtl)?\.css$,i', $css, $r)) return $css;
2066
2067
	// si on a precise le sens voulu en argument, le prendre en compte
2068
	if ($voulue = strtolower($voulue)) {
2069
		if ($voulue != 'rtl' AND $voulue != 'ltr')
2070
			$voulue = lang_dir($voulue);
2071
	}
2072
	else
2073
		$voulue =  lang_dir();
2074
2075
	$r = count($r) > 1;
2076
	$right = $r ? 'left' : 'right'; // 'right' de la css lue en entree
0 ignored issues
show
Unused Code introduced by
$right 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...
2077
	$dir = $r ? 'rtl' : 'ltr';
2078
	$ndir = $r ? 'ltr' : 'rtl';
2079
2080
	if ($voulue == $dir)
2081
		return $css;
2082
2083
	if (
2084
		// url absolue
2085
		preg_match(",^http:,i",$css)
2086
		// ou qui contient un ?
2087
		OR (($p=strpos($css,'?'))!==FALSE)) {
2088
		$distant = true;
2089
		$cssf = parse_url($css);
2090
		$cssf = $cssf['path'].($cssf['query']?"?".$cssf['query']:"");
2091
		$cssf = preg_replace(',[?:&=],', "_", $cssf);
2092
	}
2093
	else {
2094
		$distant = false;
2095
		$cssf = $css;
2096
		// 1. regarder d'abord si un fichier avec la bonne direction n'est pas aussi
2097
		//propose (rien a faire dans ce cas)
2098
		$f = preg_replace(',(_rtl)?\.css$,i', '_'.$ndir.'.css', $css);
2099
		if (@file_exists($f))
2100
			return $f;
2101
	}
2102
2103
	// 2.
2104
	$dir_var = sous_repertoire (_DIR_VAR, 'cache-css');
2105
	$f = $dir_var
2106
		. preg_replace(',.*/(.*?)(_rtl)?\.css,', '\1', $cssf)
2107
		. '.' . substr(md5($cssf), 0,4) . '_' . $ndir . '.css';
2108
2109
	// la css peut etre distante (url absolue !)
2110
	if ($distant){
2111
		include_spip('inc/distant');
2112
		$contenu = recuperer_page($css);
2113
		if (!$contenu) return $css;
2114
	}
2115
	else {
2116 View Code Duplication
		if ((@filemtime($f) > @filemtime($css))
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...
2117
			AND (_VAR_MODE != 'recalcul'))
2118
			return $f;
2119
		if (!lire_fichier($css, $contenu))
2120
			return $css;
2121
	}
2122
2123
	$contenu = str_replace(
2124
		array('right', 'left', '@@@@L E F T@@@@'),
2125
		array('@@@@L E F T@@@@', 'right', 'left'),
2126
		$contenu);
2127
	
2128
	// reperer les @import auxquels il faut propager le direction_css
2129
	preg_match_all(",\@import\s*url\s*\(\s*['\"]?([^'\"/][^:]*)['\"]?\s*\),Uims",$contenu,$regs);
2130
	$src = array();$src_direction_css = array();$src_faux_abs=array();
2131
	$d = dirname($css);
2132
	foreach($regs[1] as $k=>$import_css){
2133
		$css_direction = direction_css("$d/$import_css",$voulue);
2134
		// si la css_direction est dans le meme path que la css d'origine, on tronque le path, elle sera passee en absolue
2135
		if (substr($css_direction,0,strlen($d)+1)=="$d/") $css_direction = substr($css_direction,strlen($d)+1);
2136
		// si la css_direction commence par $dir_var on la fait passer pour une absolue
2137
		elseif (substr($css_direction,0,strlen($dir_var))==$dir_var) {
2138
			$css_direction = substr($css_direction,strlen($dir_var));
2139
			$src_faux_abs["/@@@@@@/".$css_direction] = $css_direction;
2140
			$css_direction = "/@@@@@@/".$css_direction;
2141
		}
2142
		$src[] = $regs[0][$k];
2143
		$src_direction_css[] = str_replace($import_css,$css_direction,$regs[0][$k]);
2144
	}
2145
	$contenu = str_replace($src,$src_direction_css,$contenu);
2146
2147
	$contenu = urls_absolues_css($contenu, $css);
2148
2149
	// virer les fausses url absolues que l'on a mis dans les import
2150
	if (count($src_faux_abs))
2151
		$contenu = str_replace(array_keys($src_faux_abs),$src_faux_abs,$contenu);
2152
2153
	if (!ecrire_fichier($f, $contenu))
2154
		return $css;
2155
2156
	return $f;
2157
}
2158
2159
// recuperere le chemin d'une css existante et :
2160
// cree (ou recree) dans _DIR_VAR/cache_css/ une css dont les url relatives sont passees en url absolues
2161
// http://doc.spip.org/@url_absolue_css
2162
function url_absolue_css ($css) {
2163
	if (!preg_match(',\.css$,i', $css, $r)) return $css;
2164
2165
	$url_absolue_css = url_absolue($css);
2166
2167
	$f = basename($css,'.css');
2168
	$f = sous_repertoire (_DIR_VAR, 'cache-css') 
2169
		. preg_replace(",(.*?)(_rtl|_ltr)?$,","\\1-urlabs-" . substr(md5("$css-urlabs"), 0,4) . "\\2",$f) 
2170
		. '.css';
2171
2172 View Code Duplication
	if ((@filemtime($f) > @filemtime($css))
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...
2173
	AND (_VAR_MODE != 'recalcul'))
2174
		return $f;
2175
2176
	if ($url_absolue_css==$css){
2177
		if (strncmp($GLOBALS['meta']['adresse_site'],$css,$l=strlen($GLOBALS['meta']['adresse_site']))!=0
2178
		 OR !lire_fichier(_DIR_RACINE . substr($css,$l), $contenu)){
2179
		 		include_spip('inc/distant');
2180
		 		if (!$contenu = recuperer_page($css))
2181
					return $css;
2182
		}
2183
	}
2184
	elseif (!lire_fichier($css, $contenu))
2185
		return $css;
2186
2187
	// passer les url relatives a la css d'origine en url absolues
2188
	$contenu = urls_absolues_css($contenu, $css);
2189
2190
	// ecrire la css
2191
	if (!ecrire_fichier($f, $contenu))
2192
		return $css;
2193
2194
	return $f;
2195
}
2196
2197
2198
2199
/**
2200
 * Le filtre table_valeur
2201
 * permet de recuperer la valeur d'une cle donnee
2202
 * dans un tableau (ou un objet).
2203
 * 
2204
 * @param mixed $table
2205
 * 		Tableau ou objet
2206
 * 		(ou chaine serialisee de tableau, ce qui permet d'enchainer le filtre)
2207
 * 		
2208
 * @param string $cle
2209
 * 		Cle du tableau (ou parametre public de l'objet)
2210
 * 		Cette cle peut contenir des caracteres / pour selectionner
2211
 * 		des sous elements dans le tableau, tel que "sous/element/ici"
2212
 * 		pour obtenir la valeur de $tableau['sous']['element']['ici']
2213
 *
2214
 * @param mixed $defaut
2215
 * 		Valeur par defaut retournee si la cle demandee n'existe pas
2216
 * 
2217
 * @return mixed Valeur trouvee ou valeur par defaut.
2218
**/
2219
function table_valeur($table, $cle, $defaut='') {
2220
	foreach (explode('/', $cle) as $k) {
2221
2222
		$table = is_string($table) ? @unserialize($table) : $table;
2223
2224
		if (is_object($table)) {
2225
			$table =  (($k !== "") and isset($table->$k)) ? $table->$k : $defaut;
2226
		} elseif (is_array($table)) {
2227
			$table = isset($table[$k]) ? $table[$k] : $defaut;
2228
		} else {
2229
			$table = $defaut;
2230
		}
2231
	}
2232
	return $table;
2233
}
2234
2235
// filtre match pour faire des tests avec expression reguliere
2236
// [(#TEXTE|match{^ceci$,Uims})]
2237
// retourne le fragment de chaine qui "matche"
2238
// il est possible de passer en 3eme argument optionnel le numero de parenthese capturante
2239
// accepte egalement la syntaxe #TRUC|match{truc(...)$,1} ou le modificateur n'est pas passe en second argument
2240
// http://doc.spip.org/@match
2241
function match($texte, $expression, $modif="UimsS",$capte=0) {
2242
	if (intval($modif) AND $capte==0){
2243
		$capte = $modif;
2244
		$modif = "UimsS";
2245
	}
2246
	$expression=str_replace("\/","/",$expression);
2247
	$expression=str_replace("/","\/",$expression);
2248
2249
	if (preg_match('/' . $expression . '/' . $modif,$texte, $r)) {
2250
		if (isset($r[$capte]))
2251
			return $r[$capte];
2252
		else
2253
			return true;
2254
	}
2255
	return false;
2256
}
2257
2258
// filtre replace pour faire des operations avec expression reguliere
2259
// [(#TEXTE|replace{^ceci$,cela,UimsS})]
2260
// http://doc.spip.org/@replace
2261
function replace($texte, $expression, $replace='', $modif="UimsS") {
2262
	$expression=str_replace("\/","/", $expression);
2263
	$expression=str_replace("/","\/",$expression);
2264
	return preg_replace('/' . $expression . '/' . $modif, $replace, $texte);
2265
}
2266
2267
2268
// cherche les documents numerotes dans un texte traite par propre()
2269
// et affecte les doublons['documents']
2270
// http://doc.spip.org/@traiter_doublons_documents
2271
// http://doc.spip.org/@traiter_doublons_documents
2272
function traiter_doublons_documents(&$doublons, $letexte) {
2273
2274
	// Verifier dans le texte & les notes (pas beau, helas)
2275
	$t = $letexte.$GLOBALS['les_notes'];
2276
2277
	if (strstr($t, 'spip_document_') // evite le preg_match_all si inutile
2278
	AND preg_match_all(
2279
	',<[^>]+\sclass=["\']spip_document_([0-9]+)[\s"\'],imsS',
2280
	$t, $matches, PREG_PATTERN_ORDER))
2281
		$doublons['documents'] .= "," . join(',', $matches[1]);
2282
2283
	return $letexte;
2284
}
2285
2286
// filtre vide qui ne renvoie rien
2287
// http://doc.spip.org/@vide
2288
function vide($texte){
0 ignored issues
show
Unused Code introduced by
The parameter $texte 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...
2289
	return "";
2290
}
2291
2292
//
2293
// Filtres pour le modele/emb (embed document)
2294
//
2295
2296
// A partir d'un #ENV, retourne des <param ...>
2297
// http://doc.spip.org/@env_to_params
2298 View Code Duplication
function env_to_params ($texte, $ignore_params=array()) {
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...
2299
	$ignore_params = array_merge (
2300
		array('id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'),
2301
	$ignore_params);
2302
	$tableau = unserialize($texte);
2303
	$texte = "";
2304
	foreach ($tableau as $i => $j)
2305
		if (is_string($j) AND !in_array($i,$ignore_params))
2306
			$texte .= "<param name='".$i."'\n\tvalue='".$j."' />";
2307
	return $texte;
2308
}
2309
// A partir d'un #ENV, retourne des attributs
2310
// http://doc.spip.org/@env_to_attributs
2311 View Code Duplication
function env_to_attributs ($texte, $ignore_params=array()) {
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...
2312
	$ignore_params = array_merge (
2313
		array('id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'),
2314
	$ignore_params);
2315
	$tableau = unserialize($texte);
2316
	$texte = "";
2317
	foreach ($tableau as $i => $j)
2318
		if (is_string($j) AND !in_array($i,$ignore_params))
2319
			$texte .= $i."='".$j."' ";
2320
	return $texte;
2321
}
2322
2323
// Concatener des chaines
2324
// #TEXTE|concat{texte1,texte2,...}
2325
// http://doc.spip.org/@concat
2326
function concat(){
2327
	$args = func_get_args();
2328
	return join('', $args);
2329
}
2330
2331
2332
// http://doc.spip.org/@charge_scripts
2333
// http://doc.spip.org/@charge_scripts
2334
function charge_scripts($files, $script = true) {
2335
	$flux = "";
2336
	foreach(is_array($files)?$files:explode("|",$files) as $file) {
2337
		if (!is_string($file)) continue;
2338
		if ($script)
2339
			$file = preg_match(",^\w+$,",$file) ? "javascript/$file.js" : '';
2340
		if ($file) $path = find_in_path($file);
2341
		if ($path) $flux .= spip_file_get_contents($path);
0 ignored issues
show
Bug introduced by
The variable $path does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2342
	}
2343
	return $flux;
2344
}
2345
2346
2347
2348
/**
2349
 * produit une balise img avec un champ alt d'office si vide
2350
 * attention le htmlentities et la traduction doivent etre appliques avant.
2351
 *
2352
 * http://doc.spip.org/@http_img_pack
2353
 *
2354
 * @param $img
2355
 * @param $alt
2356
 * @param string $atts
2357
 * @param string $title
2358
 * @param array $options
2359
 *   chemin_image : utiliser chemin_image sur $img fourni, ou non (oui par dafaut)
2360
 *   utiliser_suffixe_size : utiliser ou non le suffixe de taille dans le nom de fichier de l'image
2361
 *   sous forme -xx.png (pour les icones essentiellement) (oui par defaut)
2362
 * @return string
2363
 */
2364
function http_img_pack($img, $alt, $atts='', $title='', $options = array()) {
2365
	if (!isset($options['chemin_image']) OR $options['chemin_image']==true)
2366
		$img = chemin_image($img);
2367
	if (stripos($atts, 'width')===false){
2368
		// utiliser directement l'info de taille presente dans le nom
2369
		if ((!isset($options['utiliser_suffixe_size']) OR $options['utiliser_suffixe_size']==true)
2370
		    AND preg_match(',-([0-9]+)[.](png|gif)$,',$img,$regs)){
2371
			$largeur = $hauteur = intval($regs[1]);
2372
		}
2373
		else{
2374
			$taille = taille_image($img);
2375
			list($hauteur,$largeur) = $taille;
2376
			if (!$hauteur OR !$largeur)
2377
				return "";
2378
		}
2379
		$atts.=" width='".$largeur."' height='".$hauteur."'";
2380
	}
2381
	return  "<img src='$img' alt='" . attribut_html($alt ? $alt : $title) . "'"
2382
	  . ($title ? ' title="'.attribut_html($title).'"' : '')
2383
	  . " ".ltrim($atts)
2384
	  . " />";
2385
}
2386
2387
/**
2388
 * generer une directive style='background:url()' a partir d'un fichier image
2389
 * 
2390
 * http://doc.spip.org/@http_style_background
2391
 *
2392
 * @param string $img
2393
 * @param string $att
2394
 * @return string
2395
 */
2396
function http_style_background($img, $att=''){
2397
  return " style='background".($att?"":"-image").": url(\"".chemin_image($img)."\")" . ($att ? (' ' . $att) : '') . ";'";
2398
}
2399
2400
/**
2401
 * une fonction pour generer une balise img a partir d'un nom de fichier
2402
 *
2403
 * @param string $img
2404
 * @param string $alt
2405
 * @param string $class
2406
 * @return string
2407
 */
2408
function filtre_balise_img_dist($img,$alt="",$class=""){
2409
	return http_img_pack($img, $alt, $class?" class='".attribut_html($class)."'":'', '', array('chemin_image'=>false,'utiliser_suffixe_size'=>false));
2410
}
2411
2412
2413
//[(#ENV*|unserialize|foreach)]
2414
// http://doc.spip.org/@filtre_foreach_dist
2415
function filtre_foreach_dist($balise_deserializee, $modele = 'foreach') {
2416
	$texte = '';
2417
	if(is_array($balise_deserializee))
2418
		foreach($balise_deserializee as $k => $v) {
2419
			$res = recuperer_fond('modeles/'.$modele,
2420
				array_merge(array('cle' => $k), (is_array($v) ? $v : array('valeur' => $v)))
2421
			);
2422
			$texte .= $res;
2423
		}
2424
	return $texte;
2425
}
2426
2427
// renvoie la liste des plugins actifs du site
2428
// si le premier parametre est un prefix de cette liste, renvoie vrai, faux sinon
2429
// la valeur du second parametre si celui-ci renvoie a une information connue
2430
// cf liste_plugin_actifs() pour connaitre les informations affichables
2431
// appelee par la balise #PLUGIN
2432
// http://doc.spip.org/@filtre_info_plugin_dist
2433
function filtre_info_plugin_dist($plugin, $type_info) {
2434
	include_spip('inc/plugin');
2435
	$plugin = strtoupper($plugin);
2436
	$plugins_actifs = liste_plugin_actifs();
2437
2438
	if (!$plugin)
2439
		return serialize(array_keys($plugins_actifs));
2440
	elseif (empty($plugins_actifs[$plugin]))
2441
		return '';
2442
	elseif ($type_info == 'est_actif')
2443
		return $plugins_actifs[$plugin] ? 1 : 0;
2444
	elseif (isset($plugins_actifs[$plugin][$type_info]))
2445
		return $plugins_actifs[$plugin][$type_info];
2446
	else {
2447
		$get_infos = charger_fonction('get_infos','plugins');
2448
		// On prend en compte les extensions
2449
		if (!is_dir($plugins_actifs[$plugin]['dir_type']))
2450
			$dir_plugins = constant($plugins_actifs[$plugin]['dir_type']);
2451
		else
2452
			$dir_plugins = $plugins_actifs[$plugin]['dir_type'];
2453
		if (!$infos = $get_infos($plugins_actifs[$plugin]['dir'], false, $dir_plugins))
2454
			return '';
2455
		if ($type_info == 'tout')
2456
			return $infos;
2457
		else
2458
			return strval($infos[$type_info]);
2459
	}
2460
}
2461
2462
2463
// http://doc.spip.org/@puce_changement_statut
2464
function puce_changement_statut($id_objet, $statut, $id_rubrique, $type, $ajax=false){
2465
	$puce_statut = charger_fonction('puce_statut','inc');
2466
	return $puce_statut($id_objet, $statut, $id_rubrique, $type, $ajax);
2467
}
2468
2469
/**
2470
 * [(#STATUT|puce_statut{article})] affiche une puce passive
2471
 * [(#STATUT|puce_statut{article,#ID_ARTICLE,#ID_RUBRIQUE})] affiche une puce avec changement rapide
2472
 *
2473
 * utilisable sur tout objet qui a declare
2474
 * @param string $statut
2475
 * @param string $objet
2476
 * @param int $id_objet
2477
 * @param int $id_parent
2478
 * @return string
2479
 */
2480
function filtre_puce_statut_dist($statut,$objet,$id_objet=0,$id_parent=0){
2481
	static $puce_statut = null;
2482
	if (!$puce_statut)
2483
		$puce_statut = charger_fonction('puce_statut','inc');
2484
	return $puce_statut($id_objet, $statut, $id_parent, $objet, false, objet_info($objet,'editable')?_ACTIVER_PUCE_RAPIDE:false);
2485
}
2486
2487
2488
/**
2489
 * Encoder un contexte pour l'ajax, le signer avec une cle, le crypter
2490
 * avec le secret du site, le gziper si possible...
2491
 * l'entree peut etre serialisee (le #ENV** des fonds ajax et ajax_stat)
2492
 *
2493
 * http://doc.spip.org/@encoder_contexte_ajax
2494
 *
2495
 * @param string|array $c
2496
 *   contexte, peut etre un tableau serialize
2497
 * @param string $form
2498
 *   nom du formulaire eventuel
2499
 * @param string $emboite
0 ignored issues
show
Documentation introduced by
Should the type for parameter $emboite not be string|null?

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.

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

Loading history...
2500
 *   contenu a emboiter dans le conteneur ajax
2501
 * @param string $ajaxid
2502
 *   ajaxid pour cibler le bloc et forcer sa mise a jour
2503
 * @return string
2504
 */
2505
function encoder_contexte_ajax($c,$form='', $emboite=NULL, $ajaxid='') {
2506
	if (is_string($c)
2507
	AND !is_null(@unserialize($c))) {
2508
		$c = unserialize($c);
2509
	}
2510
2511
	// supprimer les parametres debut_x
2512
	// pour que la pagination ajax ne soit pas plantee
2513
	// si on charge la page &debut_x=1 : car alors en cliquant sur l'item 0,
2514
	// le debut_x=0 n'existe pas, et on resterait sur 1
2515
	foreach ($c as $k => $v) {
2516
		if (strpos($k,'debut_') === 0) {
2517
			unset($c[$k]);
2518
		}
2519
	}
2520
	
2521
	if (!function_exists('calculer_cle_action'))
2522
		include_spip("inc/securiser_action");
2523
2524
	$c = serialize($c);
2525
	$cle = calculer_cle_action($form . $c);
2526
	$c = "$cle:$c";
2527
2528
	// on ne stocke pas les contextes dans des fichiers caches
2529
	// par defaut, sauf si cette configuration a ete forcee
2530
	// OU que la longueur de l''argument generee est plus long
2531
	// que ce que telere Suhosin.
2532
	$cache_contextes_ajax = (defined('_CACHE_CONTEXTES_AJAX') AND _CACHE_CONTEXTES_AJAX);
2533
	if (!$cache_contextes_ajax) {
2534
		$env = $c;
2535
		if (function_exists('gzdeflate') && function_exists('gzinflate')) {
2536
			$env = gzdeflate($env);
2537
			// http://core.spip.org/issues/2667 | https://bugs.php.net/bug.php?id=61287
2538
			if (substr(phpversion(),0,5) == '5.4.0' AND !@gzinflate($env)) {
2539
				$cache_contextes_ajax = true;
2540
				spip_log("Contextes AJAX forces en fichiers ! Erreur PHP 5.4.0", _LOG_AVERTISSEMENT);
2541
			}
2542
		}
2543
		$env = _xor($env);
2544
		$env = base64_encode($env);
2545
		// tester Suhosin et la valeur maximale des variables en GET...
2546
		if ($max_len = @ini_get('suhosin.get.max_value_length')
2547
		and $max_len < ($len = strlen($env))) {
2548
			$cache_contextes_ajax = true;
2549
			spip_log("Contextes AJAX forces en fichiers !"
2550
				. " Cela arrive lorsque la valeur du contexte"
2551
				. " depasse la longueur maximale autorisee par Suhosin"
2552
				. " ($max_len) dans 'suhosin.get.max_value_length'. Ici : $len."
2553
				. " Vous devriez modifier les parametres de Suhosin"
2554
				. " pour accepter au moins 1024 caracteres.", _LOG_AVERTISSEMENT);
2555
		}
2556
	}
2557
	
2558
	if ($cache_contextes_ajax) {
2559
		$dir = sous_repertoire(_DIR_CACHE, 'contextes');
2560
		// stocker les contextes sur disque et ne passer qu'un hash dans l'url
2561
		$md5 = md5($c);
2562
		ecrire_fichier("$dir/c$md5",$c);
2563
		$env = $md5;
2564
	} 
2565
	
2566
	if ($emboite === NULL) return $env;
0 ignored issues
show
Bug introduced by
The variable $env does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2567
	if (!trim($emboite)) return "";
2568
	// toujours encoder l'url source dans le bloc ajax
2569
	$r = self();
2570
	$r = ' data-origin="'.$r.'"';
2571
	$class = 'ajaxbloc';
2572
	if ($ajaxid and is_string($ajaxid)) {
2573
		// ajaxid est normalement conforme a un nom de classe css
2574
		// on ne verifie pas la conformite, mais on passe entites_html par dessus par precaution
2575
		$class .= ' ajax-id-' . entites_html($ajaxid);
2576
	}
2577
	return "<div class='$class' "."data-ajax-env='$env'$r>\n$emboite</div><!--ajaxbloc-->\n";
2578
}
2579
2580
// la procedure inverse de encoder_contexte_ajax()
2581
// http://doc.spip.org/@decoder_contexte_ajax
2582
function decoder_contexte_ajax($c,$form='') {
2583
	if (!function_exists('calculer_cle_action'))
2584
		include_spip("inc/securiser_action");
2585
	if (( (defined('_CACHE_CONTEXTES_AJAX') AND _CACHE_CONTEXTES_AJAX) OR strlen($c)==32)
2586
		AND $dir = sous_repertoire(_DIR_CACHE, 'contextes')
2587
		AND lire_fichier("$dir/c$c",$contexte)) {
2588
			$c = $contexte;
2589
	} else {
2590
		$c = @base64_decode($c);
2591
		$c = _xor($c);
2592
		if (function_exists('gzdeflate') && function_exists('gzinflate'))
2593
			$c = @gzinflate($c);
2594
	}
2595
2596
	// extraire la signature en debut de contexte
2597
	// et la verifier avant de deserializer
2598
	// format : signature:donneesserializees
2599 View Code Duplication
	if ($p = strpos($c,":")){
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...
2600
		$cle = substr($c,0,$p);
2601
		$c = substr($c,$p+1);
2602
2603
		if ($cle == calculer_cle_action($form . $c)) {
2604
			$env = @unserialize($c);
2605
			return $env;
2606
		}
2607
	}
2608
2609
	return false;
2610
}
2611
2612
// encrypter/decrypter un message
2613
// http://www.php.net/manual/fr/language.operators.bitwise.php#81358
2614
// http://doc.spip.org/@_xor
2615
function _xor($message, $key=null){
2616
	if (is_null($key)) {
2617
		if (!function_exists('calculer_cle_action'))
2618
			include_spip("inc/securiser_action");
2619
		$key = pack("H*", calculer_cle_action('_xor'));
2620
	}
2621
2622
	$keylen = strlen($key);
2623
	$messagelen = strlen($message);
2624
	for($i=0; $i<$messagelen; $i++)
2625
		$message[$i] = ~($message[$i]^$key[$i%$keylen]);
2626
2627
	return $message;
2628
}
2629
2630
// Les vrai fonctions sont dans le plugin forum, mais on evite ici une erreur du compilateur
2631
// en absence du plugin
2632
function url_reponse_forum($texte){return $texte;}
2633
function url_rss_forum($texte){return $texte;}
2634
2635
2636
/**
2637
 * une fonction pour generer des menus avec liens
2638
 * ou un <strong class='on'> non clicable lorsque l'item est selectionne
2639
 *
2640
 * @param string $url
2641
 * @param string $libelle
0 ignored issues
show
Documentation introduced by
Should the type for parameter $libelle not be string|null?

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.

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

Loading history...
2642
 *   le texte du lien
2643
 * @param bool $on
2644
 *   etat expose (genere un strong) ou non (genere un lien)
2645
 * @param string $class
2646
 * @param string $title
2647
 * @param string $rel
2648
 * @param string $evt
2649
 *   complement a la balise a pour gerer un evenement javascript, de la forme " onclick='...'"
2650
 * @return string
2651
 */
2652
function lien_ou_expose($url,$libelle=NULL,$on=false,$class="",$title="",$rel="", $evt=''){
2653
	if ($on) {
2654
		$bal = "strong";
2655
		$att = "class='on'";
2656
	} else {
2657
		$bal = 'a';
2658
		$att = "href='$url'"
2659
	  	.($title?" title='".attribut_html($title)."'":'')
2660
	  	.($class?" class='".attribut_html($class)."'":'')
2661
	  	.($rel?" rel='".attribut_html($rel)."'":'')
2662
		.$evt;
2663
	}
2664
	if ($libelle === NULL)
2665
		$libelle = $url;
2666
	return "<$bal $att>$libelle</$bal>";
2667
}
2668
2669
2670
/**
2671
 * Afficher un message "un truc"/"N trucs"
2672
 * Les items sont à indiquer comme pour la fonction _T() sous la forme :
2673
 * "module:chaine"
2674
 *
2675
 * @param int $nb : le nombre
2676
 * @param string $chaine_un : l'item de langue si $nb vaut un 
2677
 * @param string $chaine_plusieurs : l'item de lanque si $nb > 1 
2678
 * @param string $var : La variable à remplacer par $nb dans l'item de langue (facultatif, défaut "nb")
2679
 * @param array $vars : Les autres variables nécessaires aux chaines de langues (facultatif)
2680
 * @return string : la chaine de langue finale en utilisant la fonction _T()
2681
 */
2682
function singulier_ou_pluriel($nb,$chaine_un,$chaine_plusieurs,$var='nb',$vars=array()){
2683
	if (!$nb=intval($nb)) return "";
2684
	if (!is_array($vars)) return "";
2685
	$vars[$var] = $nb;
2686
	if ($nb>1) return _T($chaine_plusieurs, $vars);
2687
	else return _T($chaine_un,$vars);
2688
}
2689
2690
2691
/**
2692
 * Fonction de base pour une icone dans un squelette
2693
 * structure html : <span><a><img><b>texte</b></span>
2694
 *
2695
 * @param string $type
2696
 *  'lien' ou 'bouton'
2697
 * @param string $lien
2698
 *  url
2699
 * @param string $texte
2700
 *  texte du lien / alt de l'image
2701
 * @param string $fond
2702
 *  objet avec ou sans son extension et sa taille (article, article-24, article-24.png)
2703
 * @param string $fonction
2704
 *  new/del/edit
2705
 * @param string $class
2706
 *  classe supplementaire (horizontale, verticale, ajax ...)
2707
 * @param string $javascript
2708
 *  "onclick='...'" par exemple
2709
 * @return string 
2710
 */
2711
function prepare_icone_base($type, $lien, $texte, $fond, $fonction="", $class="",$javascript=""){
2712
	if (in_array($fonction,array("del","supprimer.gif")))
2713
		$class .= ' danger';
2714
	elseif ($fonction == "rien.gif")
2715
		$fonction = "";
2716
	elseif ($fonction == "delsafe")
2717
		$fonction = "del";
2718
2719
	// remappage des icone : article-24.png+new => article-new-24.png
2720 View Code Duplication
	if ($icone_renommer = charger_fonction('icone_renommer','inc',true))
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...
2721
		list($fond,$fonction) = $icone_renommer($fond,$fonction);
2722
2723
	// ajouter le type d'objet dans la class de l'icone
2724
	$class .= " " . substr(basename($fond),0,-4);
2725
2726
	$alt = attribut_html($texte);
2727
	$title = " title=\"$alt\""; // est-ce pertinent de doubler le alt par un title ?
2728
2729
	$ajax = "";
2730
	if (strpos($class,"ajax")!==false) {
2731
			$ajax="ajax";
2732
		if (strpos($class,"preload")!==false)
2733
			$ajax.=" preload";
2734
		if (strpos($class,"nocache")!==false)
2735
			$ajax.=" nocache";
2736
		$ajax=" class='$ajax'";
2737
	}
2738
2739
	$size = 24;
2740
	if (preg_match("/-([0-9]{1,3})[.](gif|png)$/i",$fond,$match))
2741
		$size = $match[1];
2742
2743
	if ($fonction){
2744
		// 2 images pour composer l'icone : le fond (article) en background,
2745
		// la fonction (new) en image
2746
		$icone = http_img_pack($fonction, $alt, "width='$size' height='$size'\n" .
2747
					http_style_background($fond));
2748
	}
2749
	else {
2750
		$icone = http_img_pack($fond, $alt, "width='$size' height='$size'");
2751
	}
2752
2753
	if ($type=='lien')
2754
		return "<span class='icone s$size $class'>"
2755
		. "<a href='$lien'$title$ajax$javascript>"
2756
		. $icone
2757
		. "<b>$texte</b>"
2758
		. "</a></span>\n";
2759
2760
	else
2761
		return bouton_action("$icone<b>$texte</b>",$lien,"icone s$size $class",$javascript,$alt);
2762
}
2763
2764
function icone_base($lien, $texte, $fond, $fonction="", $class="",$javascript=""){
2765
	return prepare_icone_base('lien', $lien, $texte, $fond, $fonction, $class, $javascript);
2766
}
2767
function filtre_icone_verticale_dist($lien, $texte, $fond, $fonction="", $class="",$javascript=""){
2768
	return icone_base($lien,$texte,$fond,$fonction,"verticale $class",$javascript);
2769
}
2770
function filtre_icone_horizontale_dist($lien, $texte, $fond, $fonction="", $class="",$javascript=""){
2771
	return icone_base($lien,$texte,$fond,$fonction,"horizontale $class",$javascript);
2772
}
2773
2774
function filtre_bouton_action_horizontal_dist($lien, $texte, $fond, $fonction="", $class="",$confirm=""){
2775
	return prepare_icone_base('bouton', $lien, $texte, $fond, $fonction, "horizontale $class", $confirm);
2776
}
2777
/*
2778
 * Filtre icone pour compatibilite
2779
 * mappe sur icone_base
2780
 */
2781
function filtre_icone_dist($lien, $texte, $fond, $align="", $fonction="", $class="",$javascript=""){
2782
	return icone_base($lien,$texte,$fond,$fonction,"verticale $align $class",$javascript);
2783
}
2784
2785
2786
/**
2787
 * filtre explode pour les squelettes permettant d'ecrire
2788
 * #GET{truc}|explode{-}
2789
 *
2790
 * @param strong $a
2791
 * @param string $b
2792
 * @return array
2793
 */
2794
function filtre_explode_dist($a,$b){return explode($b,$a);}
2795
2796
/**
2797
 * filtre implode pour les squelettes permettant d'ecrire
2798
 * #GET{truc}|implode{-}
2799
 *
2800
 * @param array $a
2801
 * @param string $b
2802
 * @return string
2803
 */
2804
function filtre_implode_dist($a,$b){return is_array($a)?implode($b,$a):$a;}
2805
2806
/**
2807
 * Produire les styles prives qui associent item de menu avec icone en background
2808
 * @return string
2809
 */
2810
function bando_images_background(){
2811
	include_spip('inc/bandeau');
2812
	// recuperer tous les boutons et leurs images
2813
	$boutons = definir_barre_boutons(definir_barre_contexte(),true,false);
2814
2815
	$res = "";
2816
	foreach($boutons as $page => $detail){
2817
		if ($detail->icone AND strlen(trim($detail->icone)))
2818
			$res .="\n.navigation_avec_icones #bando1_$page {background-image:url(".$detail->icone.");}";
2819
		$selecteur = (in_array($page,array('outils_rapides','outils_collaboratifs'))?"":".navigation_avec_icones ");
2820
		if (is_array($detail->sousmenu))
2821
			foreach($detail->sousmenu as $souspage=>$sousdetail)
2822
				if ($sousdetail->icone AND strlen(trim($sousdetail->icone)))
2823
					$res .="\n$selecteur.bando2_$souspage {background-image:url(".$sousdetail->icone.");}";
2824
	}
2825
	return $res;
2826
}
2827
2828
/**
2829
 * Generer un bouton_action
2830
 * utilise par #BOUTON_ACTION
2831
 *
2832
 * @param string $libelle
2833
 * @param string $url
2834
 * @param string $class
2835
 * @param string $confirm
2836
 *   message de confirmation oui/non avant l'action
2837
 * @param string $title
2838
 * @param string $callback
2839
 *   callback js a appeler lors de l'evenement action (apres confirmation eventuelle si $confirm est non vide)
2840
 *   et avant execution de l'action. Si la callback renvoie false, elle annule le declenchement de l'action
2841
 * @return string
2842
 */
2843
function bouton_action($libelle, $url, $class="", $confirm="", $title="", $callback=""){
2844
	if ($confirm) {
2845
		$confirm = "confirm(\"" . attribut_html($confirm) . "\")";
2846
	  if ($callback)
2847
		  $callback = "$confirm?($callback):false";
2848
	  else
2849
		  $callback = $confirm;
2850
	}
2851
	$onclick = $callback?" onclick='return ".addcslashes($callback,"'")."'":"";
2852
	$title = $title ? " title='$title'" : "";
2853
	return "<form class='bouton_action_post $class' method='post' action='$url'><div>".form_hidden($url)
2854
		."<button type='submit' class='submit'$title$onclick>$libelle</button></div></form>";
2855
}
2856
2857
2858
/**
2859
 * Proteger les champs passes dans l'url et utiliser dans {tri ...}
2860
 * preserver l'espace pour interpreter ensuite num xxx et multi xxx
2861
 * @param string $t
2862
 * @return string
2863
 */
2864
function tri_protege_champ($t){
2865
	return preg_replace(',[^\s\w.+],','',$t);
2866
}
2867
2868
/**
2869
 * Interpreter les multi xxx et num xxx utilise comme tri
2870
 * pour la clause order
2871
 * 'multi xxx' devient simplement 'multi' qui est calcule dans le select
2872
 * @param string $t
2873
 * @param array $from
0 ignored issues
show
Documentation introduced by
Should the type for parameter $from 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...
2874
 * @return string
2875
 */
2876
function tri_champ_order($t, $from=null){
2877
	if(strncmp($t,'multi ',6)==0){
2878
		return "multi";
2879
	}
2880
2881
	$champ = $t;
2882
2883
	if (strncmp($t,'num ',4)==0)
2884
		$champ = substr($t,4);
2885
	// enlever les autres espaces non evacues par tri_protege_champ
2886
	$champ = preg_replace(',\s,','',$champ);
2887
2888
	if (is_array($from)){
2889
		$trouver_table = charger_fonction('trouver_table','base');
2890
		foreach($from as $idt=>$table_sql){
2891
			if ($desc = $trouver_table($table_sql)
2892
				AND isset($desc['field'][$champ])){
2893
				$champ = "$idt.$champ";
2894
				break;
2895
			}
2896
		}
2897
	}
2898
	if (strncmp($t,'num ',4)==0)
2899
		return "0+$champ";
2900
	else
2901
		return $champ;
2902
}
2903
2904
/**
2905
 * Interpreter les multi xxx et num xxx utilise comme tri
2906
 * pour la clause select
2907
 * 'multi xxx' devient select "...." as multi
2908
 * les autres cas ne produisent qu'une chaine vide '' en select
2909
 * 'hasard' devient 'rand() AS hasard' dans le select
2910
 *
2911
 * @param string $t
2912
 * @return string
2913
 */
2914
function tri_champ_select($t){
2915
	if(strncmp($t,'multi ',6)==0){
2916
		$t = substr($t,6);
2917
		$t = preg_replace(',\s,','',$t);
2918
		$t = sql_multi($t,$GLOBALS['spip_lang']);
2919
		return $t;
2920
	}
2921
	if(trim($t)=='hasard'){
2922
		return 'rand() AS hasard';
2923
	}
2924
	return "''";
2925
}
2926
2927
2928
/**
2929
 * Donner n'importe quelle information sur un objet de maniere generique.
2930
 *
2931
 * La fonction va gerer en interne deux cas particuliers les plus utilises :
2932
 * l'URL et le titre (qui n'est pas forcemment le champ SQL "titre").
2933
 *
2934
 * On peut ensuite personnaliser les autres infos en creant une fonction
2935
 * generer_<nom_info>_entite($id_objet, $type_objet, $ligne).
2936
 * $ligne correspond a la ligne SQL de tous les champs de l'objet, les fonctions
2937
 * de personnalisation n'ont donc pas a refaire de requete.
2938
 *
2939
 * @param int $id_objet
2940
 * @param string $type_objet
2941
 * @param string $info
2942
 * @param string $etoile
2943
 * @return string
2944
 */
2945
function generer_info_entite($id_objet, $type_objet, $info, $etoile=""){
2946
	global $table_des_traitements;
2947
	static $trouver_table=null;
2948
	static $objets;
2949
2950
	// On verifie qu'on a tout ce qu'il faut
2951
	$id_objet = intval($id_objet);
2952
	if (!($id_objet and $type_objet and $info))
2953
		return '';
2954
2955
	// si on a deja note que l'objet n'existe pas, ne pas aller plus loin
2956
	if (isset($objets[$type_objet]) AND $objets[$type_objet]===false)
2957
		return '';
2958
2959
	// Si on demande l'url, on retourne direct la fonction
2960
	if ($info == 'url')
2961
		return generer_url_entite($id_objet, $type_objet);
2962
2963
	// Sinon on va tout chercher dans la table et on garde en memoire
2964
	$demande_titre = ($info == 'titre');
2965
2966
	// On ne fait la requete que si on a pas deja l'objet ou si on demande le titre mais qu'on ne l'a pas encore
2967
	if (!isset($objets[$type_objet][$id_objet])
2968
	  OR
2969
	  ($demande_titre AND !isset($objets[$type_objet][$id_objet]['titre']))
2970
	  ){
2971
		if (!$trouver_table)
2972
			$trouver_table = charger_fonction('trouver_table','base');
2973
		$desc = $trouver_table(table_objet_sql($type_objet));
2974
		if (!$desc)
2975
			return $objets[$type_objet] = false;
2976
2977
		// Si on demande le titre, on le gere en interne
2978
		$champ_titre = "";
2979
		if ($demande_titre){
2980
			// si pas de titre declare mais champ titre, il sera peuple par le select *
2981
			$champ_titre = (!empty($desc['titre'])) ? ', ' . $desc['titre']:'';
2982
		}
2983
		include_spip('base/abstract_sql');
2984
		include_spip('base/connect_sql');
2985
		$objets[$type_objet][$id_objet] = sql_fetsel(
2986
			'*'.$champ_titre,
2987
			$desc['table_sql'],
2988
			id_table_objet($type_objet).' = '.intval($id_objet)
2989
		);
2990
	}
2991
2992
	// Si la fonction generer_TRUC_TYPE existe, on l'utilise pour formater $info_generee
2993
	if ($generer = charger_fonction("generer_${info}_${type_objet}", '', true))
2994
		$info_generee = $generer($id_objet, $objets[$type_objet][$id_objet]);
2995
	// Si la fonction generer_TRUC_entite existe, on l'utilise pour formater $info_generee
2996
	else if ($generer = charger_fonction("generer_${info}_entite", '', true))
2997
		$info_generee = $generer($id_objet, $type_objet, $objets[$type_objet][$id_objet]);
2998
	// Sinon on prend directement le champ SQL tel quel
2999
	else
3000
		$info_generee = (isset($objets[$type_objet][$id_objet][$info])?$objets[$type_objet][$id_objet][$info]:'');
3001
3002
	// On va ensuite chercher les traitements automatiques a faire
3003
	$champ = strtoupper($info);
3004
	$traitement = isset($table_des_traitements[$champ]) ? $table_des_traitements[$champ] : false;
3005
	$table_sql = table_objet_sql($type_objet);
3006
3007
	if (!$etoile
3008
		AND is_array($traitement)
3009
	  AND (isset($traitement[$table_sql]) OR isset($traitement[0]))){
3010
	  	include_spip('inc/texte');
3011
		$traitement = $traitement[isset($traitement[$table_sql]) ? $table_sql : 0];
3012
		$traitement = str_replace('%s', "'".texte_script($info_generee)."'", $traitement);
3013
		// FIXME: $connect et $Pile[0] font souvent partie des traitements.
3014
		// on les definit pour eviter des notices, mais ce fonctionnement est a ameliorer !
3015
		$connect = ""; $Pile = array(0 => array('id_objet'=>$id_objet,'objet'=>$type_objet));
0 ignored issues
show
Unused Code introduced by
$connect 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...
Unused Code introduced by
$Pile 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...
3016
		eval("\$info_generee = $traitement;");
3017
	}
3018
3019
	return $info_generee;
3020
}
3021
3022
/**
3023
 * Wrap un texte avec des balises
3024
 * wrap('mot','<b>') => '<b>mot</b>'
3025
 * @param string $texte
3026
 * @param string $wrap
3027
 * @return string
3028
 */
3029
function wrap($texte,$wrap) {
3030
	$balises = extraire_balises($wrap);
0 ignored issues
show
Unused Code introduced by
$balises 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...
3031
	if (preg_match_all(",<([a-z]\w*)\b[^>]*>,UimsS",$wrap, $regs, PREG_PATTERN_ORDER)) {
3032
		$texte = $wrap . $texte;
3033
		$regs = array_reverse($regs[1]);
3034
		$wrap = "</".implode("></",$regs).">";
3035
		$texte = $texte . $wrap;
3036
	}
3037
	return $texte;
3038
}
3039
3040
3041
/**
3042
 * afficher proprement n'importe quoi
3043
 * On affiche in fine un pseudo-yaml qui premet de lire humainement les tableaux et de s'y reperer
3044
 *
3045
 * Les textes sont retournes avec simplement mise en forme typo
3046
 *
3047
 * le $join sert a separer les items d'un tableau, c'est en general un \n ou <br /> selon si on fait du html ou du texte
3048
 * les tableaux-listes (qui n'ont que des cles numeriques), sont affiches sous forme de liste separee par des virgules :
3049
 * c'est VOULU !
3050
 *
3051
 * @param $u
3052
 * @param string $join
3053
 * @param int $indent
3054
 * @return array|mixed|string
3055
 */
3056
function filtre_print_dist($u, $join="<br />", $indent=0) {
3057
	if (is_string($u)){
3058
		$u = typo($u);
3059
		return $u;
3060
	}
3061
3062
	// caster $u en array si besoin
3063
	if (is_object($u))
3064
		$u = (array) $u;
3065
3066
	if (is_array($u)){
3067
		$out = "";
3068
		// toutes les cles sont numeriques ?
3069
		// et aucun enfant n'est un tableau
3070
		// liste simple separee par des virgules
3071
		$numeric_keys = array_map('is_numeric',array_keys($u));
3072
		$array_values = array_map('is_array',$u);
3073
		$object_values = array_map('is_object',$u);
3074
		if (array_sum($numeric_keys)==count($numeric_keys)
3075
		  AND !array_sum($array_values)
3076
		  AND !array_sum($object_values)){
3077
			return join(", ", array_map('filtre_print_dist', $u));
3078
		}
3079
3080
		// sinon on passe a la ligne et on indente
3081
		$i_str = str_pad("",$indent," ");
3082
		foreach($u as $k => $v){
3083
			$out .= $join . $i_str . "$k: " . filtre_print_dist($v,$join,$indent+2);
3084
		}
3085
		return $out;
3086
	}
3087
3088
	// on sait pas quoi faire...
3089
	return $u;
3090
}
3091
3092
3093
/**
3094
 * Renvoyer l'info d'un objet
3095
 * telles que definies dans declarer_tables_objets_sql
3096
 *
3097
 * @param string $objet
3098
 * @param string $info
3099
 * @return string
3100
 */
3101
function objet_info($objet,$info){
3102
	$table = table_objet_sql($objet);
3103
	$infos = lister_tables_objets_sql($table);
3104
	return (isset($infos[$info])?$infos[$info]:'');
3105
}
3106
3107
/**
3108
 * Filtre pour afficher 'Aucun truc' ou '1 truc' ou 'N trucs'
3109
 * avec la bonne chaine de langue en fonction de l'objet utilise
3110
 * @param  $nb
3111
 * @param  $objet
3112
 * @return mixed|string
3113
 */
3114
function objet_afficher_nb($nb, $objet){
3115
	if (!$nb)
3116
		return _T(objet_info($objet,'info_aucun_objet'));
3117
	else
3118
		return _T(objet_info($objet,$nb==1?'info_1_objet':'info_nb_objets'),array('nb'=>$nb));
3119
}
3120
3121
/**
3122
 * Filtre pour afficher l'img icone d'un objet
3123
 *
3124
 * @param string $objet
3125
 * @param int $taille
3126
 * @return string
3127
 */
3128
function objet_icone($objet,$taille=24){
3129
	$icone = objet_info($objet,'icone_objet')."-".$taille.".png";
3130
	$icone = chemin_image($icone);
3131
	$balise_img = charger_filtre('balise_img');
3132
	return $icone?$balise_img($icone,_T(objet_info($objet,'texte_objet'))):'';
3133
}
3134
3135
/**
3136
 * Fonction de secours pour inserer le head_css de facon conditionnelle
3137
 * 
3138
 * Appelée en filtre sur le squelette qui contient #INSERT_HEAD,
3139
 * elle vérifie l'absence éventuelle de #INSERT_HEAD_CSS et y suplée si besoin
3140
 * pour assurer la compat avec les squelettes qui n'utilisent pas.
3141
 * 
3142
 * @param string $flux Code HTML
3143
 * @return string      Code HTML
3144
 */
3145
function insert_head_css_conditionnel($flux){
3146
	if (strpos($flux,'<!-- insert_head_css -->')===false
3147
		AND $p=strpos($flux,'<!-- insert_head -->')){
3148
		// plutot avant le premier js externe (jquery) pour etre non bloquant
3149
		if ($p1 = stripos($flux,'<script src=') AND $p1<$p)
3150
			$p = $p1;
3151
		$flux = substr_replace($flux,pipeline('insert_head_css','<!-- insert_head_css -->'),$p,0);
3152
	}
3153
	return $flux;
3154
}
3155
3156
/**
3157
 * Produire un fichier statique a partir d'un squelette dynamique
3158
 * Permet ensuite a apache de le servir en statique sans repasser
3159
 * par spip.php a chaque hit sur le fichier
3160
 * si le format (css ou js) est passe dans contexte['format'], on l'utilise
3161
 * sinon on regarde si le fond finit par .css ou .js
3162
 * sinon on utilie "html"
3163
 *
3164
 * @param string $fond
3165
 * @param array $contexte
3166
 * @param array $options
3167
 * @param string $connect
3168
 * @return string
3169
 */
3170
function produire_fond_statique($fond, $contexte=array(), $options = array(), $connect=''){
3171
	if (isset($contexte['format'])){
3172
		$extension = $contexte['format'];
3173
		unset($contexte['format']);
3174
	}
3175
	else {
3176
		$extension = "html";
3177
		if (preg_match(',[.](css|js|json)$,',$fond,$m))
3178
			$extension = $m[1];
3179
	}
3180
	// recuperer le contenu produit par le squelette
3181
	$options['raw'] = true;
3182
	$cache = recuperer_fond($fond,$contexte,$options,$connect);
3183
	
3184
	// calculer le nom de la css
3185
	$dir_var = sous_repertoire (_DIR_VAR, 'cache-'.$extension);
3186
	$nom_safe = preg_replace(",\W,",'_',str_replace('.','_',$fond));
3187
	$filename = $dir_var . $extension."dyn-$nom_safe-".substr(md5($fond.serialize($contexte).$connect),0,8) .".$extension";
3188
3189
	// mettre a jour le fichier si il n'existe pas
3190
	// ou trop ancien
3191
	// le dernier fichier produit est toujours suffixe par .last
3192
	// et recopie sur le fichier cible uniquement si il change
3193
	if (!file_exists($filename)
3194
		OR !file_exists($filename.".last")
3195
		OR (isset($cache['lastmodified']) AND $cache['lastmodified'] AND filemtime($filename.".last")<$cache['lastmodified'])
3196
		OR (defined('_VAR_MODE') AND _VAR_MODE=='recalcul')) {
3197
		$contenu = $cache['texte'];
3198
		// passer les urls en absolu si c'est une css
3199
		if ($extension=="css")
3200
			$contenu = urls_absolues_css($contenu, test_espace_prive()?generer_url_ecrire('accueil'):generer_url_public($fond));
3201
		
3202
		// ne pas insérer de commentaire si c'est du json
3203
		if ($extension!="json") {
3204
			$comment = "/* #PRODUIRE{fond=$fond";
3205
			foreach($contexte as $k=>$v)
3206
				$comment .= ",$k=$v";
3207
			// pas de date dans le commentaire car sinon ca invalide le md5 et force la maj
3208
			// mais on peut mettre un md5 du contenu, ce qui donne un aperu rapide si la feuille a change ou non
3209
			$comment .="}\n   md5:".md5($contenu)." */\n";
3210
		}
3211
		// et ecrire le fichier
3212
		ecrire_fichier($filename.".last",$comment.$contenu);
0 ignored issues
show
Bug introduced by
The variable $comment does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
3213
		// regarder si on recopie
3214
		if (!file_exists($filename)
3215
		  OR md5_file($filename)!==md5_file($filename.".last")){
3216
			@copy($filename.".last",$filename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3217
			spip_clearstatcache(true,$filename); // eviter que PHP ne reserve le vieux timestamp
3218
		}
3219
	}
3220
	
3221
	return $filename;
3222
}
3223
3224
/**
3225
 * Ajouter un timestamp a une url de fichier
3226
 * [(#CHEMIN{monfichier}|timestamp)]
3227
 *
3228
 * @param string $fichier
3229
 * @return string
3230
 */
3231
function timestamp($fichier){
3232
	if (!$fichier OR !file_exists($fichier)) return $fichier;
3233
	$m = filemtime($fichier);
3234
	return "$fichier?$m";
3235
}
3236
3237
/**
3238
 * Nettoyer le titre d'un email
3239
 * eviter une erreur lorsqu'on utilise |nettoyer_titre_email dans un squelette de mail
3240
 * @param  $titre
3241
 * @return mixed
3242
 */
3243
function filtre_nettoyer_titre_email_dist($titre){
3244
	include_spip('inc/envoyer_mail');
3245
	return nettoyer_titre_email($titre);
3246
}
3247
3248
/**
3249
 * Afficher le sélecteur de rubrique
3250
 *
3251
 * Il permet de placer un objet dans la hiérarchie des rubriques de SPIP
3252
 *
3253
 * @param string $titre
3254
 * @param int $id_objet
3255
 * @param int $id_parent
3256
 * @param string $objet
3257
 * @param int $id_secteur
3258
 * @param bool $restreint
3259
 * @param bool $actionable
3260
 *   true : fournit le selecteur dans un form directement postable
3261
 * @param bool $retour_sans_cadre
3262
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
3263
 */
3264
function filtre_chercher_rubrique_dist($titre,$id_objet, $id_parent, $objet, $id_secteur, $restreint,$actionable = false, $retour_sans_cadre=false){
3265
	include_spip('inc/filtres_ecrire');
3266
	return chercher_rubrique($titre,$id_objet, $id_parent, $objet, $id_secteur, $restreint,$actionable, $retour_sans_cadre);
3267
}
3268
3269
/**
3270
 * Rediriger une page suivant une autorisation,
3271
 * et ce, n'importe où dans un squelette, même dans les inclusions.
3272
 * Exemple :
3273
 * [(#AUTORISER{non}|sinon_interdire_acces)]
3274
 * [(#AUTORISER{non}|sinon_interdire_acces{#URL_PAGE{login}, 401})]
3275
 *
3276
 * @param bool $ok Indique si l'on doit rediriger ou pas
3277
 * @param string $url Adresse vers laquelle rediriger
3278
 * @param int $statut Statut HTML avec lequel on redirigera
3279
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|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...
3280
 */
3281
function sinon_interdire_acces($ok=false, $url='', $statut=0){
3282
	if ($ok) return '';
3283
	
3284
	// Vider tous les tampons
3285
	$level = @ob_get_level();
3286
	while ($level--)
3287
		@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3288
	
3289
	include_spip('inc/headers');
3290
	$statut = intval($statut);
3291
	
3292
	// Si aucun argument on essaye de deviner quoi faire par défaut
3293
	if (!$url and !$statut){
3294
		// Si on est dans l'espace privé, on génère du 403 Forbidden
3295
		if (test_espace_prive()){
3296
			http_status(403);
3297
			$echec = charger_fonction('403','exec');
3298
			$echec();
3299
		}
3300
		// Sinon dans l'espace public on redirige vers une 404 par défaut, car elle toujours présente normalement
3301
		else{
3302
			$statut = 404;
3303
		}
3304
	}
3305
	
3306
	// On suit les directives indiquées dans les deux arguments
3307
	
3308
	// S'il y a un statut
3309
	if ($statut){
3310
		// Dans tous les cas on modifie l'entité avec ce qui est demandé
3311
		http_status($statut);
3312
		// Si le statut est une erreur et qu'il n'y a pas de redirection on va chercher le squelette du même nom
3313
		if ($statut >= 400 and !$url)
3314
			echo recuperer_fond("$statut");
3315
	}
3316
	
3317
	// S'il y a une URL, on redirige (si pas de statut, la fonction mettra 302 par défaut)
3318
	if ($url) redirige_par_entete($url, '', $statut);
3319
	
3320
	exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function sinon_interdire_acces() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
3321
}
3322
3323
/**
3324
 * Assurer le fonctionnement de |compacte meme sans l'extension compresseur
3325
 * @param string $source
3326
 * @param null|string $format
3327
 * @return string
3328
 */
3329
function filtre_compacte_dist($source, $format = null){
3330
	if (function_exists('compacte'))
3331
		return compacte($source, $format);
3332
	return $source;
3333
}
3334
3335
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
3336