Completed
Push — spip-2.1 ( b6b097 )
by cam
42:28 queued 30:44
created

composer.php ➔ calculer_select()   F

Complexity

Conditions 48
Paths > 20000

Size

Total Lines 179
Code Lines 121

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 48
eloc 121
nc 48180
nop 13
dl 0
loc 179
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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/texte');
16
include_spip('inc/documents');
17
include_spip('inc/distant');
18
include_spip('inc/rubriques'); # pour calcul_branche (cf critere branche)
19
include_spip('inc/acces'); // Gestion des acces pour ical
20
include_spip('public/interfaces');
21
include_spip('public/quete');
22
23
# Charge et retourne un composeur ou '' s'il est inconnu. Le compile au besoin
24
# Charge egalement un fichier homonyme de celui du squelette
25
# mais de suffixe '_fonctions.php' pouvant contenir:
26
# 1. des filtres
27
# 2. des fonctions de traduction de balise, de critere et de boucle
28
# 3. des declaration de tables SQL supplementaires
29
# Toutefois pour 2. et 3. preferer la technique de la surcharge
30
31
// http://doc.spip.org/@public_composer_dist
32
function public_composer_dist($squelette, $mime_type, $gram, $source, $connect='') {
33
34
	$nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
35
36
	//  si deja en memoire (INCLURE  a repetition) c'est bon.
37
38
	if (function_exists($nom)) return array($nom);
39
40
	if (isset($GLOBALS['var_mode']) && ($GLOBALS['var_mode'] == 'debug'))
41
		$GLOBALS['debug_objets']['courant'] = $nom;
42
43
	$phpfile = sous_repertoire(_DIR_SKELS,'',false,true) . $nom . '.php';
44
45
	// si squelette est deja compile et perenne, le charger
46
	if (!squelette_obsolete($phpfile, $source)
47
	AND lire_fichier ($phpfile, $skel_code,
48
	array('critique' => 'oui', 'phpcheck' => 'oui')))
49
		eval('?'.'>'.$skel_code);
50
#	spip_log($skel_code, 'comp')
51
	if (@file_exists($lib = $squelette . '_fonctions'.'.php'))
52
		include_once $lib;
53
54
	// tester si le eval ci-dessus a mis le squelette en memoire
55
56
	if (function_exists($nom)) return array($nom, $skel_code);
0 ignored issues
show
Bug introduced by
The variable $skel_code 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...
57
58
	// charger le source, si possible, et compiler 
59
	if (lire_fichier ($source, $skel)) {
60
		$compiler = charger_fonction('compiler', 'public');
61
		$skel_code = $compiler($skel, $nom, $gram, $source, $connect);
62
	}
63
64
	// Ne plus rien faire si le compilateur n'a pas pu operer.
65
	if (!$skel_code) return false;
66
67
	foreach($skel_code as $id => $boucle) {
68
		$f = $boucle->return;
69
		if (@eval("return true; $f ;") ===  false) {
70
		// Code syntaxiquement faux (critere etc mal programme')
71
			$msg = array('zbug_erreur_compilation');
72
			erreur_squelette($msg, $boucle);
73
			// continuer pour trouver d'autres fautes eventuelles
74
			// mais prevenir que c'est mort
75
			$nom = '';
76
		} 
77
		// Contexte de compil inutile a present
78
		// (mais la derniere valeur de $boucle est utilisee ci-dessous)
79
		$skel_code[$id] = $f;
80
	}
81
82
	if ($nom) {
83
		// Si le code est bon, concatener et mettre en cache
84
		if (function_exists($nom))
85
			$code = squelette_traduit($skel, $source, $phpfile, $skel_code);
86
		else {
87
		// code semantiquement faux: bug du compilateur
88
		// $boucle est en fait ici la fct principale du squelette
89
			$msg = array('zbug_erreur_compilation');
90
			erreur_squelette($msg, $boucle);
0 ignored issues
show
Bug introduced by
The variable $boucle seems to be defined by a foreach iteration on line 67. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
91
			$nom = '';
92
		}
93
	}
94
95
	if (isset($GLOBALS['var_mode']) AND $GLOBALS['var_mode'] == 'debug') {
96
97
		// Tracer ce qui vient d'etre compile
98
		$GLOBALS['debug_objets']['code'][$nom . 'tout'] = $code;
0 ignored issues
show
Bug introduced by
The variable $code 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...
99
100
		// si c'est ce que demande le debusqueur, lui passer la main
101 View Code Duplication
		if ($GLOBALS['debug_objets']['sourcefile']
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...
102
		AND (_request('var_mode_objet') == $nom)
103
		AND (_request('var_mode_affiche') == 'code')  )
104
			erreur_squelette();
105
	}
106
	return $nom ? array($nom, $code) : false;
107
}
108
109
function squelette_traduit($squelette, $sourcefile, $phpfile, $boucles)
0 ignored issues
show
Unused Code introduced by
The parameter $squelette 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...
110
{
111
112
	// Le dernier index est '' (fonction principale)
113
	$noms = substr(join (', ', array_keys($boucles)), 0, -2);
114
	if (CODE_COMMENTE)
115
	$code = "
116
/*
117
 * Squelette : $sourcefile
118
 * Date :      ".gmdate("D, d M Y H:i:s", @filemtime($sourcefile))." GMT
119
 * Compile :   ".gmdate("D, d M Y H:i:s", time())." GMT
120
 * " . (!$boucles ?  "Pas de boucle" :	("Boucles :   " . $noms)) ."
121
 */ " ;
122
123
	$code = '<'. "?php\n" . $code . join('', $boucles)  . "\n?" .'>';
0 ignored issues
show
Bug introduced by
The variable $code 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...
124
	if (!isset($GLOBALS['var_nocache']) OR !$GLOBALS['var_nocache'])
125
		ecrire_fichier($phpfile, $code);
126
	return $code;
127
}
128
129
// Le squelette compile est-il trop vieux ?
130
// http://doc.spip.org/@squelette_obsolete
131
function squelette_obsolete($skel, $squelette) {
132
	static $date_change = null;
133
	// ne verifier la date de mes_fonctions et mes_options qu'une seule fois
134
	// par hit
135
	if (is_null($date_change)){
136
		if (@file_exists($fonc = 'mes_fonctions.php')
137
			OR @file_exists($fonc = 'mes_fonctions.php3'))
138
			$date_change = @filemtime($fonc); # compatibilite
139
		if (defined('_FILE_OPTIONS'))
140
			$date_change = max($date_change,@filemtime(_FILE_OPTIONS));
141
	}
142
	return (
143
		(isset($GLOBALS['var_mode']) AND in_array($GLOBALS['var_mode'], array('recalcul','preview','debug')))
144
		OR !@file_exists($skel)
145
		OR ((@file_exists($squelette)?@filemtime($squelette):0)
146
			> ($date = @filemtime($skel)))
147
		OR ($date_change > $date)
148
	);
149
}
150
151
// Activer l'invalideur de session
152
// http://doc.spip.org/@invalideur_session
153
function invalideur_session(&$Cache, $code=NULL) {
154
	$Cache['session']=spip_session();
155
	return $code;
156
}
157
158
159
//
160
// Des fonctions diverses utilisees lors du calcul d'une page ; ces fonctions
161
// bien pratiques n'ont guere de logique organisationnelle ; elles sont
162
// appelees par certaines balises au moment du calcul des pages. (Peut-on
163
// trouver un modele de donnees qui les associe physiquement au fichier
164
// definissant leur balise ???
165
//
166
167
// http://doc.spip.org/@echapper_php_callback
168
function echapper_php_callback($r) {
169
	static $src = array();
170
	static $dst = array();
171
172
	// si on recoit un tableau, on est en mode echappement
173
	// on enregistre le code a echapper dans dst, et le code echappe dans src
174
	if (is_array($r)) {
175
		$dst[] = $r[0];
176
		return $src[] = '___'.md5($r[0]).'___';
177
	}
178
179
	// si on recoit une chaine, on est en mode remplacement
180
	$r = str_replace($src, $dst, $r);
181
	$src = $dst = array(); // raz de la memoire
182
	return $r;
183
}
184
185
// http://doc.spip.org/@analyse_resultat_skel
186
function analyse_resultat_skel($nom, $cache, $corps, $source='') {
187
	$headers = array();
188
189
	// Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
190
	// note: on essaie d'attrapper aussi certains de ces entetes codes
191
	// "a la main" dans les squelettes, mais evidemment sans exhaustivite
192
	if (preg_match_all(
193
	'/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
194
	$corps, $regs, PREG_SET_ORDER)){
195
		foreach ($regs as $r) {
196
			$corps = str_replace($r[0], '', $corps);
197
			# $j = Content-Type, et pas content-TYPE.
198
			$j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
199
200
			if ($j=='X-Spip-Filtre' AND isset($headers[$j]))
201
				$headers[$j].="|".$r[3];
202
			else
203
				$headers[$j] = $r[3];
204
		}
205
	}
206
	// S'agit-il d'un resultat constant ou contenant du code php
207
	$process_ins = (
208
		strpos($corps,'<'.'?') === false
209
		OR strpos(str_replace('<'.'?xml', '', $corps),'<'.'?') === false
210
	)
211
		? 'html'
212
		: 'php';
213
214
	// traiter #FILTRE{} ?
215
	if (isset($headers['X-Spip-Filtre'])
216
	AND strlen($headers['X-Spip-Filtre'])) {
217
		// proteger les <INCLUDE> et tous les morceaux de php
218
		if ($process_ins == 'php')
219
			$corps = preg_replace_callback(',<[?](\s|php|=).*[?]>,UimsS',
220
				'echapper_php_callback', $corps);
221
		foreach (explode('|', $headers['X-Spip-Filtre']) as $filtre) {
222
			if ($f = chercher_filtre($filtre))
223
				$corps = $f($corps);
224
		}
225
		// restaurer les echappements
226
		$corps = echapper_php_callback($corps);
227
		unset($headers['X-Spip-Filtre']);
228
	}
229
230
	return array('texte' => $corps,
231
		'squelette' => $nom,
232
		'source' => $source,
233
		'process_ins' => $process_ins,
234
		'invalideurs' => $cache,
235
		'entetes' => $headers,
236
		'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0 
237
	);
238
}
239
240
241
//
242
// fonction standard de calcul de la balise #INTRODUCTION
243
// on peut la surcharger en definissant dans mes_fonctions :
244
// function filtre_introduction()
245
//
246
// http://doc.spip.org/@filtre_introduction_dist
247
function filtre_introduction_dist($descriptif, $texte, $longueur, $connect) {
248
	// Si un descriptif est envoye, on l'utilise directement
249
	if (strlen($descriptif))
250
		return propre($descriptif,$connect);
251
252
	// De preference ce qui est marque <intro>...</intro>
253
	$intro = '';
254
	$texte = preg_replace(",(</?)intro>,i", "\\1intro>", $texte); // minuscules
255
	while ($fin = strpos($texte, "</intro>")) {
256
		$zone = substr($texte, 0, $fin);
257
		$texte = substr($texte, $fin + strlen("</intro>"));
258
		if ($deb = strpos($zone, "<intro>") OR substr($zone, 0, 7) == "<intro>")
259
			$zone = substr($zone, $deb + 7);
260
		$intro .= $zone;
261
	}
262
263
	// [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut,
264
	// qui inclus raccourcis et modeles
265
	// un simple <articlexx> peut etre ensuite transforme en 1000 lignes ...
266
	// par ailleurs le nettoyage des raccourcis ne tient pas compte
267
	// des surcharges et enrichissement de propre
268
	// couper doit se faire apres propre
269
	//$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect);
270
271
	// Cependant pour des questions de perfs on coupe quand meme, en prenant
272
	// large et en se mefiant des tableaux #1323
273
274
	if (strlen($intro))
275
		$texte = $intro;
276
277
	else
278
	if (strpos("\n".$texte, "\n|")===false
279
	AND strlen($texte) > 2.5*$longueur)
280
		$texte = couper($texte, 2*$longueur);
281
282
	// ne pas tenir compte des notes
283
	$notes = charger_fonction('notes', 'inc');
284
	$notes('','empiler');
285
	// Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable
286
	// dans l'introduction.
287
	$texte = supprime_img($texte, '');
288
	$texte = propre($texte,$connect);
289
	$notes('','depiler');
290
291
	if (!defined('_INTRODUCTION_SUITE')) define('_INTRODUCTION_SUITE', '&nbsp;(...)');
292
	$texte = couper($texte, $longueur, _INTRODUCTION_SUITE);
293
294
	return $texte;
295
}
296
297
//
298
// Balises dynamiques
299
//
300
301
// elles sont traitees comme des inclusions
302
// http://doc.spip.org/@synthetiser_balise_dynamique
303
304
define('CODE_INCLURE_BALISE', '<' . '?php 
305
include_once("./" . _DIR_RACINE . "%s");
306
if ($lang_select = "%s") $lang_select = lang_select($lang_select);
307
inserer_balise_dynamique(balise_%s_dyn(%s), array(%s));
308
if ($lang_select) lang_select();
309
?'
310
       .'>');
311
312
313
function synthetiser_balise_dynamique($nom, $args, $file, $context_compil) {
314
	$r = sprintf(CODE_INCLURE_BALISE,
315
	       $file,
316
	       $context_compil[4]?$context_compil[4]:'',
317
	       $nom,
318
	       join(', ', array_map('argumenter_squelette', $args)),
319
	       join(', ', array_map('_q', $context_compil)));
320
	return $r;
321
}
322
323
// http://doc.spip.org/@argumenter_squelette
324
function argumenter_squelette($v) {
325
326
	if (!is_array($v))
327
		return "'" . texte_script($v) . "'";
328
	else {
329
		$out = array();
330
		foreach($v as $k=>$val) 
331
			$out [] = argumenter_squelette($k) . '=>' . argumenter_squelette($val);
332
	  return 'array(' . join(", ", $out) . ')';
333
	}
334
}
335
336
// verifier leurs arguments et filtres, et calculer le code a inclure
337
// http://doc.spip.org/@executer_balise_dynamique
338
function executer_balise_dynamique($nom, $args, $context_compil) {
339
	$p = strpos($nom,"_");
340
	$nomfonction = $nom;
341
	$nomfonction_generique = substr($nom,0,$p+1);
342
	if (!$file = include_spip("balise/". strtolower($nomfonction))) {
343
		// pas de fichier associe, passer au traitement generique
344
		$file = include_spip("balise/" .strtolower($nomfonction_generique));
345
		if ($file) {
346
			// et injecter en premier arg le nom de la balise 
347
			array_unshift($args,$nom);
348
			// et passer sur la fonction generique pour la suite
349
			$nomfonction = $nomfonction_generique;
350
		}
351 View Code Duplication
		else {
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...
352
			$msg = array('zbug_balise_inexistante',array('from'=>'CVT','balise'=>$nom));
353
			erreur_squelette($msg, $context_compil);
354
			return '';
355
		}
356
	}
357
	// Y a-t-il une fonction de traitement des arguments ?
358
	$f = 'balise_' . $nomfonction . '_stat';
359
360
	$r = !function_exists($f) ? $args : $f($args, $context_compil); 
361
362
	if (!is_array($r)) return $r;
363
364
	// verifier que la fonction dyn est la, 
365
	// sinon se replier sur la generique si elle existe
366
	if (!function_exists('balise_' . $nomfonction . '_dyn')) {
367
		$file = include_spip("balise/" .strtolower($nomfonction_generique));
368
		if (function_exists('balise_' . $nomfonction_generique . '_dyn')) {
369
			// et lui injecter en premier arg le nom de la balise 
370
			array_unshift($r,$nom);
371
			$nomfonction = $nomfonction_generique;
372 View Code Duplication
		} else {
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...
373
			$msg = array('zbug_balise_inexistante',array('from'=>'CVT','balise'=>$nom));
374
			erreur_squelette($msg, $context_compil);
375
			return '';
376
		}
377
	}
378
379
	if (!_DIR_RESTREINT) 
380
		$file = _DIR_RESTREINT_ABS . $file;
381
	return synthetiser_balise_dynamique($nomfonction, $r, $file, $context_compil);
382
}
383
384
// http://doc.spip.org/@lister_objets_avec_logos
385
function lister_objets_avec_logos ($type) {
386
	global $formats_logos;
387
	$logos = array();
388
	$chercher_logo = charger_fonction('chercher_logo', 'inc');
0 ignored issues
show
Unused Code introduced by
$chercher_logo 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...
389
	$type = '/'
390
	. type_du_logo($type)
391
	. "on(\d+)\.("
392
	. join('|',$formats_logos)
393
	. ")$/";
394
395
	if ($d = @opendir(_DIR_LOGOS)) {
396 View Code Duplication
		while($f = readdir($d)) {
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...
397
			if (preg_match($type, $f, $r))
398
				$logos[] = $r[1];
399
		}
400
	}
401
	@closedir($d);
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...
402
	return join(',',$logos);
403
}
404
405
// fonction appelee par la balise #NOTES
406
// Renvoyer l'etat courant des notes, le purger et en preparer un nouveau
407
// http://doc.spip.org/@calculer_notes
408
function calculer_notes() {
409
	$notes = charger_fonction('notes', 'inc');
410
	$r = $notes(array());
411
	$notes('','depiler');
412
	$notes('','empiler');
413
	return $r;
414
}
415
416
// Selectionner la langue de l'objet dans la boucle, sauf dans les
417
// cas ou il ne le faut pas :-)
418
function lang_select_public($lang, $lang_select, $titre=null) {
419
	// Cas 1. forcer_lang = true et pas de critere {lang_select}
420
	if (isset($GLOBALS['forcer_lang']) AND $GLOBALS['forcer_lang']
421
	AND $lang_select !== 'oui')
422
		return;
423
424
	// Cas 2. l'objet n'a pas de langue definie (ou definie a '')
425
	if (!strlen($lang))
426
		return;
427
428
	// Cas 3. l'objet est multilingue !
429
	if ($lang_select !== 'oui'
430
	AND strlen($titre) > 10
431
	AND strpos($titre, '<multi>') !== false
432
	AND strpos(echappe_html($titre), '<multi>') !== false)
433
		return;
434
435
	// Tous les cas ayant ete elimines, faire le job
436
	$GLOBALS['spip_lang'] = $lang;
437
	return;
438
}
439
440
441
// Si un tableau &doublons[articles] est passe en parametre,
442
// il faut le nettoyer car il pourrait etre injecte en SQL
443
// http://doc.spip.org/@nettoyer_env_doublons
444
function nettoyer_env_doublons($envd) {
445
	foreach ($envd as $table => $liste) {
446
		$n = '';
447
		foreach(explode(',',$liste) as $val) {
448
			if ($a = intval($val) AND $val === strval($a))
449
				$n.= ','.$val;
450
		}
451
		if (strlen($n))
452
			$envd[$table] = $n;
453
		else
454
			unset($envd[$table]);
455
	}
456
	return $envd;
457
}
458
459
// http://doc.spip.org/@match_self
460
function match_self($w){
461
	if (is_string($w)) return false;
462 View Code Duplication
	if (is_array($w)) {
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...
463
		if (in_array(reset($w),array("SELF","SUBSELECT"))) return $w;
464
		foreach($w as $sw)
465
			if ($m=match_self($sw)) return $m;
466
	}
467
	return false;
468
}
469
// http://doc.spip.org/@remplace_sous_requete
470
function remplace_sous_requete($w,$sousrequete){
471 View Code Duplication
	if (is_array($w)) {
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...
472
		if (in_array(reset($w),array("SELF","SUBSELECT"))) return $sousrequete;
473
		foreach($w as $k=>$sw)
474
			$w[$k] = remplace_sous_requete($sw,$sousrequete);
475
	}
476
	return $w;
477
}
478
// http://doc.spip.org/@trouver_sous_requetes
479
function trouver_sous_requetes($where){
480
	$where_simples = array();
481
	$where_sous = array();
482
	foreach($where as $k=>$w){
483
		if (match_self($w)) $where_sous[$k] = $w;
484
		else $where_simples[$k] = $w;
485
	}
486
	return array($where_simples,$where_sous);
487
}
488
489
// La fonction presente dans les squelettes compiles
490
491
// http://doc.spip.org/@calculer_select
492
function calculer_select ($select = array(), $from = array(), 
493
			$from_type = array(),
494
      $where = array(), $join=array(),
495
			$groupby = array(), $orderby = array(), $limit = '',
496
			$having=array(), $table = '', $id = '', $serveur='', $requeter=true) {
497
498
// retirer les criteres vides:
499
// {X ?} avec X absent de l'URL
500
// {par #ENV{X}} avec X absent de l'URL
501
// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
502
503
	$menage = false;
504
	foreach($where as $k => $v) { 
505
		if (is_array($v)){
506
			if ((count($v)>=2) && ($v[0]=='REGEXP') && ($v[2]=="'.*'")) $op= false;
507
			elseif ((count($v)>=2) && ($v[0]=='LIKE') && ($v[2]=="'%'")) $op= false;
508
			else $op = $v[0] ? $v[0] : $v;
509
		} else $op = $v;
510
		if ((!$op) OR ($op==1) OR ($op=='0=0')) {
511
			unset($where[$k]);
512
			$menage = true;
513
		}
514
	}
515
516
	// evacuer les eventuels groupby vide issus d'un calcul dynamique
517
	$groupby = array_diff($groupby,array(''));
518
519
	// remplacer les sous requetes recursives au calcul
520
	list($where_simples,$where_sous) = trouver_sous_requetes($where);
521
	//var_dump($where_sous);
522
	foreach($where_sous as $k=>$w) {
523
		$menage = true;
524
		// on recupere la sous requete 
525
		$sous = match_self($w);
526
		if ($sous[0]=='SELF') {
527
			// c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
528
			array_push($where_simples,$sous[2]);
529
			$where[$k] = remplace_sous_requete($w,"(".calculer_select(
530
			$sous[1],
531
			$from,
532
			$from_type,
533
			array($sous[2],'0=0'), // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
534
			$join,
535
			array(),array(),'',
536
			$having,$table,$id,$serveur,false).")");
537
		}
538
		if ($sous[0]=='SUBSELECT') {
539
			// c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
540
			array_push($where_simples,$sous[3]); // est-ce utile dans ce cas ?
541
			$where[$k] = remplace_sous_requete($w,"(".calculer_select(
542
			$sous[1], # select
543
			$sous[2], #from
544
			array(), #from_type
545
			$sous[3]?(is_array($sous[3])?$sous[3]:array($sous[3])):array(), #where, qui peut etre de la forme string comme dans sql_select
546
			array(), #join
547
			$sous[4]?$sous[4]:array(), #groupby
548
			$sous[5]?$sous[5]:array(), #orderby
549
			$sous[6], #limit
550
			$sous[7]?$sous[7]:array(), #having
551
			$table,$id,$serveur,false
552
			).")");
553
		}
554
		array_pop($where_simples);
555
	}
556
557
	foreach($having as $k => $v) { 
558
		if ((!$v) OR ($v==1) OR ($v=='0=0')) {
559
			unset($having[$k]);
560
		}
561
	}
562
563
// Installer les jointures.
564
// Retirer celles seulement utiles aux criteres finalement absents mais
565
// parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
566
// si elle est seulement utile a Ln+1 elle meme inutile
567
	
568
	$afrom = array();
569
	$equiv = array();
570
	$k = count($join);
571
	foreach(array_reverse($join,true) as $cledef=>$j) {
572
		$cle = $cledef;
573
		// le format de join est :
574
		// array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
575
		if (count($join[$cle])==2) $join[$cle][] = $join[$cle][1];
576
		if (count($join[$cle])==3) $join[$cle][] = '';
577
		list($t,$c,$carr,$and) = $join[$cle];
578
		// si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
579
		// pour compat avec ancienne convention
580
		if (is_numeric($cle))
581
			$cle = "L$k";
582
		if (!$menage
583
		OR isset($afrom[$cle])
584
		OR calculer_jointnul($cle, $select)
585
		OR calculer_jointnul($cle, array_diff($join,array($cle=>$join[$cle])))
586
		OR calculer_jointnul($cle, $having)
587
		OR calculer_jointnul($cle, $where_simples)) {
588
			// on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
589
			// sans recours a preg_match
590
			// un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
591
			$afrom[$t][$cle] = array("\n" .
592
				(isset($from_type[$cle])?$from_type[$cle]:"INNER")." JOIN",
593
				$from[$cle],
594
				"AS $cle",
595
				"ON (",
596
				"$cle.$c",
597
				"=",
598
				"$t.$carr",
599
				($and ? "AND ". $and:"") .
600
				")");
601
			if (isset($afrom[$cle])){
602
				$afrom[$t] = $afrom[$t] + $afrom[$cle];
603
				unset($afrom[$cle]);
604
			}
605
			$equiv[]= $carr;
606
		} else { unset($join[$cledef]);}
607
		unset($from[$cle]);
608
		$k--;
609
	}
610
611
	if (count($afrom)) {
612
		// Regarder si la table principale ne sert finalement a rien comme dans
613
		//<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
614
		//<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
615
		//<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
616
		// ou dans
617
		//<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
618
		// qui comporte plusieurs jointures
619
		// ou dans
620
		// <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
621
		// <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
622
		// penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
623
		// <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
624
		// penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
625
		// <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
626
		
627
	  list($t,$c) = each($from);
0 ignored issues
show
Unused Code introduced by
The assignment to $c 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...
628
	  reset($from);
629
	  $e = '/\b(' . "$t\\." . join("|" . $t . '\.', $equiv) . ')\b/';
630
	  if (!(strpos($t, ' ') OR // jointure des le depart cf boucle_doc
631
		 calculer_jointnul($t, $select, $e) OR
632
		 calculer_jointnul($t, $join, $e) OR
633
		 calculer_jointnul($t, $where, $e) OR
634
		 calculer_jointnul($t, $orderby, $e) OR
635
		 calculer_jointnul($t, $groupby, $e) OR
636
		 calculer_jointnul($t, $having, $e))
637
		 && count($afrom[$t])) {
638
		 	reset($afrom[$t]);
639
		 	list($nt,$nfrom) = each($afrom[$t]);
640
	    unset($from[$t]);
641
	    $from[$nt] = $nfrom[1];
642
	    unset($afrom[$t][$nt]);
643
	    $afrom[$nt] = $afrom[$t];
644
	    unset($afrom[$t]);
645
	    $e = '/\b'.preg_quote($nfrom[6]).'\b/';
646
	    $t = $nfrom[4];
647
	    $alias = "";
648
	    // verifier que les deux cles sont homonymes, sinon installer un alias dans le select
649
	    $oldcle = explode('.',$nfrom[6]);
650
	    $oldcle = end($oldcle);
651
	    $newcle = explode('.',$nfrom[4]);
652
	    $newcle = end($newcle);
653
	    if ($newcle!=$oldcle){
654
	    	$alias = ", ".$nfrom[4]." AS $oldcle";
655
	    }
656
	    $select = remplacer_jointnul($t . $alias, $select, $e);
657
	    $join = remplacer_jointnul($t, $join, $e);
0 ignored issues
show
Unused Code introduced by
$join 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...
658
	    $where = remplacer_jointnul($t, $where, $e);
659
	    $having = remplacer_jointnul($t, $having, $e);
660
	    $groupby = remplacer_jointnul($t, $groupby, $e);
661
	    $orderby = remplacer_jointnul($t, $orderby, $e);
662
	  }
663
	  $from = reinjecte_joint($afrom, $from);
664
	}
665
	$GLOBALS['debug']['aucasou'] = array ($table, $id, $serveur, $requeter);
666
	$r = sql_select($select, $from, $where,
667
		$groupby, array_filter($orderby), $limit, $having, $serveur, $requeter);
668
	unset($GLOBALS['debug']['aucasou']);
669
	return $r;
670
}
671
672
//condition suffisante (mais non necessaire) pour qu'une table soit utile
673
674
// http://doc.spip.org/@calculer_jointnul
675
function calculer_jointnul($cle, $exp, $equiv='')
676
{
677
	if (!is_array($exp)) {
678
		if ($equiv) $exp = preg_replace($equiv, '', $exp);
679
		return preg_match("/\\b$cle\\./", $exp);
680
	} else {
681
		foreach($exp as $v) {
682
			if (calculer_jointnul($cle, $v, $equiv)) return true;
683
		}
684
		return false;
685
	}
686
}
687
688
// http://doc.spip.org/@reinjecte_joint
689
function reinjecte_joint($afrom, $from)
690
{
691
	  $from_synth = array();
692
	  foreach($from as $k=>$v){
693
	  	$from_synth[$k]=$from[$k];
694
	  	if (isset($afrom[$k])) {
695
	  		foreach($afrom[$k] as $kk=>$vv) $afrom[$k][$kk] = implode(' ',$afrom[$k][$kk]);
696
	  		$from_synth["$k@"]= implode(' ',$afrom[$k]);
697
	  		unset($afrom[$k]);
698
	  	}
699
	  }
700
	  return $from_synth;
701
}
702
703
// http://doc.spip.org/@remplacer_jointnul
704
function remplacer_jointnul($cle, $exp, $equiv='')
705
{
706
	if (!is_array($exp)) {
707
		return preg_replace($equiv, $cle, $exp);
708
	} else {
709
		foreach($exp as $k => $v) {
710
		  $exp[$k] = remplacer_jointnul($cle, $v, $equiv);
711
		}
712
		return $exp;
713
	}
714
}
715
716
// calcul du nom du squelette
717
// http://doc.spip.org/@calculer_nom_fonction_squel
718
function calculer_nom_fonction_squel($skel, $mime_type='html', $connect='')
719
{
720
	// ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
721
	if (strlen(_DIR_RACINE) AND substr($skel,0,strlen(_DIR_RACINE))==_DIR_RACINE)
722
		$skel = substr($skel,strlen(_DIR_RACINE));
723
	return $mime_type
724
	. (!$connect ?  '' : preg_replace('/\W/',"_", $connect)) . '_'
725
	. md5($GLOBALS['spip_version_code'] . ' * ' . $skel);
726
}
727
728
?>
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...
729