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

composer.php ➔ calculer_select()   F

Complexity

Conditions 58
Paths > 20000

Size

Total Lines 220
Code Lines 147

Duplication

Lines 9
Ratio 4.09 %

Importance

Changes 0
Metric Value
cc 58
eloc 147
c 0
b 0
f 0
nc 675675
nop 13
dl 9
loc 220
rs 2

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('inc/actions');
21
include_spip('public/iterateur');
22
include_spip('public/interfaces');
23
include_spip('public/quete');
24
25
# Charge et retourne un composeur ou '' s'il est inconnu. Le compile au besoin
26
# Charge egalement un fichier homonyme de celui du squelette
27
# mais de suffixe '_fonctions.php' pouvant contenir:
28
# 1. des filtres
29
# 2. des fonctions de traduction de balise, de critere et de boucle
30
# 3. des declaration de tables SQL supplementaires
31
# Toutefois pour 2. et 3. preferer la technique de la surcharge
32
33
// http://doc.spip.org/@public_composer_dist
34
function public_composer_dist($squelette, $mime_type, $gram, $source, $connect='') {
35
36
	$nom = calculer_nom_fonction_squel($squelette, $mime_type, $connect);
37
38
	//  si deja en memoire (INCLURE  a repetition) c'est bon.
39
	if (function_exists($nom)) return $nom;
40
41
	if (defined('_VAR_MODE') AND _VAR_MODE == 'debug')
42
		$GLOBALS['debug_objets']['courant'] = $nom;
43
44
	$phpfile = sous_repertoire(_DIR_SKELS,'',false,true) . $nom . '.php';
45
46
	// si squelette est deja compile et perenne, le charger
47
	if (!squelette_obsolete($phpfile, $source)){
48
		include_once $phpfile;
49
		#if (!squelette_obsolete($phpfile, $source)
50
		#  AND lire_fichier ($phpfile, $skel_code,
51
		#  array('critique' => 'oui', 'phpcheck' => 'oui'))){
52
		## eval('?'.'>'.$skel_code);
53
		#	 spip_log($skel_code, 'comp')
54
		#}
55
	}
56
57
	if (file_exists($lib = $squelette . '_fonctions'.'.php')){
58
		include_once $lib;
59
	}
60
61
	// tester si le eval ci-dessus a mis le squelette en memoire
62
63
	if (function_exists($nom)) return $nom;
64
65
	// charger le source, si possible, et compiler 
66
	if (lire_fichier ($source, $skel)) {
67
		$compiler = charger_fonction('compiler', 'public');
68
		$skel_code = $compiler($skel, $nom, $gram, $source, $connect);
69
	}
70
71
	// Ne plus rien faire si le compilateur n'a pas pu operer.
72
	if (!$skel_code) return false;
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...
73
74
	foreach($skel_code as $id => $boucle) {
75
		$f = $boucle->return;
76
		if (@eval("return true; $f ;") ===  false) {
77
		// Code syntaxiquement faux (critere etc mal programme')
78
			$msg = _T('zbug_erreur_compilation');
79
			erreur_squelette($msg, $boucle);
80
			// continuer pour trouver d'autres fautes eventuelles
81
			// mais prevenir que c'est mort
82
			$nom = '';
83
		} 
84
		// Contexte de compil inutile a present
85
		// (mais la derniere valeur de $boucle est utilisee ci-dessous)
86
		$skel_code[$id] = $f;
87
	}
88
89
	if ($nom) {
90
		// Si le code est bon, concatener et mettre en cache
91
		if (function_exists($nom))
92
			$code = squelette_traduit($skel, $source, $phpfile, $skel_code);
93
		else {
94
		// code semantiquement faux: bug du compilateur
95
		// $boucle est en fait ici la fct principale du squelette
96
			$msg = _T('zbug_erreur_compilation');
97
			erreur_squelette($msg, $boucle);
0 ignored issues
show
Bug introduced by
The variable $boucle seems to be defined by a foreach iteration on line 74. 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...
98
			$nom = '';
99
		}
100
	}
101
102
	if (defined('_VAR_MODE') AND _VAR_MODE == 'debug') {
103
104
		// Tracer ce qui vient d'etre compile
105
		$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...
106
107
		// si c'est ce que demande le debusqueur, lui passer la main
108 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...
109
		AND (_request('var_mode_objet') == $nom)
110
		AND (_request('var_mode_affiche') == 'code')  )
111
			erreur_squelette();
112
	}
113
	return $nom ? $nom : false;
114
}
115
116
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...
117
{
118
119
	// Le dernier index est '' (fonction principale)
120
	$noms = substr(join (', ', array_keys($boucles)), 0, -2);
121
	if (CODE_COMMENTE)
122
	$code = "
123
/*
124
 * Squelette : $sourcefile
125
 * Date :      ".gmdate("D, d M Y H:i:s", @filemtime($sourcefile))." GMT
126
 * Compile :   ".gmdate("D, d M Y H:i:s", time())." GMT
127
 * " . (!$boucles ?  "Pas de boucle" :	("Boucles :   " . $noms)) ."
128
 */ " ;
129
130
	$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...
131
	if (!defined('_VAR_NOCACHE') OR !_VAR_NOCACHE)
132
		ecrire_fichier($phpfile, $code);
133
	return $code;
134
}
135
136
// Le squelette compile est-il trop vieux ?
137
// http://doc.spip.org/@squelette_obsolete
138
function squelette_obsolete($skel, $squelette) {
139
	static $date_change = null;
140
	// ne verifier la date de mes_fonctions et mes_options qu'une seule fois
141
	// par hit
142
	if (is_null($date_change)){
143
		if (@file_exists($fonc = 'mes_fonctions.php'))
144
			$date_change = @filemtime($fonc); # compatibilite
145
		if (defined('_FILE_OPTIONS'))
146
			$date_change = max($date_change,@filemtime(_FILE_OPTIONS));
147
	}
148
	return (
149
		(defined('_VAR_MODE') AND in_array(_VAR_MODE, array('recalcul','preview','debug')))
150
		OR !@file_exists($skel)
151
		OR ((@file_exists($squelette)?@filemtime($squelette):0)
152
			> ($date = @filemtime($skel)))
153
		OR ($date_change > $date)
154
	);
155
}
156
157
// Activer l'invalideur de session
158
// http://doc.spip.org/@invalideur_session
159
function invalideur_session(&$Cache, $code=NULL) {
160
	$Cache['session']=spip_session();
161
	return $code;
162
}
163
164
165
// http://doc.spip.org/@analyse_resultat_skel
166
function analyse_resultat_skel($nom, $cache, $corps, $source='') {
167
	static $filtres = array();
168
	$headers = array();
169
170
	// Recupere les < ?php header('Xx: y'); ? > pour $page['headers']
171
	// note: on essaie d'attrapper aussi certains de ces entetes codes
172
	// "a la main" dans les squelettes, mais evidemment sans exhaustivite
173
	if (stripos($corps,'header')!==false
174
		AND preg_match_all(
175
	'/(<[?]php\s+)@?header\s*\(\s*.([^:\'"]*):?\s*([^)]*)[^)]\s*\)\s*[;]?\s*[?]>/ims',
176
	$corps, $regs, PREG_SET_ORDER)){
177
		foreach ($regs as $r) {
178
			$corps = str_replace($r[0], '', $corps);
179
			# $j = Content-Type, et pas content-TYPE.
180
			$j = join('-', array_map('ucwords', explode('-', strtolower($r[2]))));
181
182
			if ($j=='X-Spip-Filtre' AND isset($headers[$j]))
183
				$headers[$j].="|".$r[3];
184
			else
185
				$headers[$j] = $r[3];
186
		}
187
	}
188
	// S'agit-il d'un resultat constant ou contenant du code php
189
	$process_ins = (
190
		strpos($corps,'<'.'?') === false
191
		OR
192
		 (strpos($corps,'<'.'?xml')!==false AND
193
		  strpos(str_replace('<'.'?xml', '', $corps),'<'.'?') === false)
194
	)
195
		? 'html'
196
		: 'php';
197
198
	$skel = array(
199
		'squelette' => $nom,
200
		'source' => $source,
201
		'process_ins' => $process_ins,
202
		'invalideurs' => $cache,
203
		'entetes' => $headers,
204
		'duree' => isset($headers['X-Spip-Cache']) ? intval($headers['X-Spip-Cache']) : 0
205
	);
206
207
	// traiter #FILTRE{} et filtres
208
  if (!isset($filtres[$nom])) {
209
	  $filtres[$nom] = pipeline('declarer_filtres_squelettes',array('args'=>$skel,'data'=>array()));
210
  }
211
	if (count($filtres[$nom]) OR (isset($headers['X-Spip-Filtre']) AND strlen($headers['X-Spip-Filtre']))) {
212
		include_spip('public/sandbox');
213
		$corps = sandbox_filtrer_squelette($skel,$corps,strlen($headers['X-Spip-Filtre'])?explode('|', $headers['X-Spip-Filtre']):array(),$filtres[$nom]);
214
		unset($headers['X-Spip-Filtre']);
215
	}
216
217
	$skel['entetes'] = $headers;
218
	$skel['texte'] = $corps;
219
220
	return $skel;
221
}
222
223
//
224
// Des fonctions diverses utilisees lors du calcul d'une page ; ces fonctions
225
// bien pratiques n'ont guere de logique organisationnelle ; elles sont
226
// appelees par certaines balises au moment du calcul des pages. (Peut-on
227
// trouver un modele de donnees qui les associe physiquement au fichier
228
// definissant leur balise ???
229
//
230
231
232
//
233
// fonction standard de calcul de la balise #INTRODUCTION
234
// on peut la surcharger en definissant dans mes_fonctions :
235
// function filtre_introduction()
236
//
237
// http://doc.spip.org/@filtre_introduction_dist
238
function filtre_introduction_dist($descriptif, $texte, $longueur, $connect) {
239
	// Si un descriptif est envoye, on l'utilise directement
240
	if (strlen($descriptif))
241
		return propre($descriptif,$connect);
242
243
	// De preference ce qui est marque <intro>...</intro>
244
	$intro = '';
245
	$texte = preg_replace(",(</?)intro>,i", "\\1intro>", $texte); // minuscules
246
	while ($fin = strpos($texte, "</intro>")) {
247
		$zone = substr($texte, 0, $fin);
248
		$texte = substr($texte, $fin + strlen("</intro>"));
249
		if ($deb = strpos($zone, "<intro>") OR substr($zone, 0, 7) == "<intro>")
250
			$zone = substr($zone, $deb + 7);
251
		$intro .= $zone;
252
	}
253
254
	// [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut,
255
	// qui inclus raccourcis et modeles
256
	// un simple <articlexx> peut etre ensuite transforme en 1000 lignes ...
257
	// par ailleurs le nettoyage des raccourcis ne tient pas compte
258
	// des surcharges et enrichissement de propre
259
	// couper doit se faire apres propre
260
	//$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect);
261
262
	// Cependant pour des questions de perfs on coupe quand meme, en prenant
263
	// large et en se mefiant des tableaux #1323
264
265
	if (strlen($intro))
266
		$texte = $intro;
267
268
	else
269
	if (strpos("\n".$texte, "\n|")===false
270
	  AND strlen($texte) > 2.5*$longueur){
271
		if (strpos($texte,"<multi")!==false)
272
			$texte = extraire_multi($texte);
273
		$texte = couper($texte, 2*$longueur);
274
	}
275
276
	// ne pas tenir compte des notes
277
	if ($notes = charger_fonction('notes', 'inc', true))
278
		$notes('','empiler');
279
	// Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable
280
	// dans l'introduction.
281
	$texte = supprime_img($texte, '');
282
	$texte = propre($texte,$connect);
283
	if ($notes)
284
		$notes('','depiler');
285
286
	if (!defined('_INTRODUCTION_SUITE')) define('_INTRODUCTION_SUITE', '&nbsp;(...)');
287
	$texte = couper($texte, $longueur, _INTRODUCTION_SUITE);
288
289
	// et reparagrapher si necessaire (coherence avec le cas descriptif)
290
	if ($GLOBALS['toujours_paragrapher'])
291
		// Fermer les paragraphes
292
		$texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']);
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
	$r='';
410
	if ($notes = charger_fonction('notes', 'inc', true)) {
411
		$r = $notes(array());
412
		$notes('','depiler');
413
		$notes('','empiler');
414
	}
415
	return $r;
416
}
417
418
// Selectionner la langue de l'objet dans la boucle, sauf dans les
419
// cas ou il ne le faut pas :-)
420
function lang_select_public($lang, $lang_select, $titre=null) {
421
	// Cas 1. forcer_lang = true et pas de critere {lang_select}
422
	if (isset($GLOBALS['forcer_lang']) AND $GLOBALS['forcer_lang']
423
	AND $lang_select !== 'oui')
424
		$lang = $GLOBALS['spip_lang'];
425
426
	// Cas 2. l'objet n'a pas de langue definie (ou definie a '')
427
	elseif (!strlen($lang))
428
		$lang = $GLOBALS['spip_lang'];
429
430
	// Cas 3. l'objet est multilingue !
431
	elseif ($lang_select !== 'oui'
432
	  AND strlen($titre) > 10
433
	  AND strpos($titre, '<multi>') !== false
434
	  AND strpos(echappe_html($titre), '<multi>') !== false)
435
		$lang = $GLOBALS['spip_lang'];
436
437
	// faire un lang_select() eventuellement sur la langue inchangee
438
	lang_select($lang);
439
440
	return;
441
}
442
443
444
// Si un tableau &doublons[articles] est passe en parametre,
445
// il faut le nettoyer car il pourrait etre injecte en SQL
446
// http://doc.spip.org/@nettoyer_env_doublons
447
function nettoyer_env_doublons($envd) {
448
	foreach ($envd as $table => $liste) {
449
		$n = '';
450
		foreach(explode(',',$liste) as $val) {
451
			if ($a = intval($val) AND $val === strval($a))
452
				$n.= ','.$val;
453
		}
454
		if (strlen($n))
455
			$envd[$table] = $n;
456
		else
457
			unset($envd[$table]);
458
	}
459
	return $envd;
460
}
461
462
// http://doc.spip.org/@match_self
463
function match_self($w){
464
	if (is_string($w)) return false;
465
	if (is_array($w)) {
466
		if (in_array(reset($w),array("SELF","SUBSELECT"))) return $w;
467
		foreach(array_filter($w,'is_array') as $sw)
468
			if ($m=match_self($sw)) return $m;
469
	}
470
	return false;
471
}
472
// http://doc.spip.org/@remplace_sous_requete
473
function remplace_sous_requete($w,$sousrequete){
474
	if (is_array($w)) {
475
		if (in_array(reset($w),array("SELF","SUBSELECT"))) return $sousrequete;
476
		foreach($w as $k=>$sw)
477
			$w[$k] = remplace_sous_requete($sw,$sousrequete);
478
	}
479
	return $w;
480
}
481
// http://doc.spip.org/@trouver_sous_requetes
482
function trouver_sous_requetes($where){
483
	$where_simples = array();
484
	$where_sous = array();
485
	foreach($where as $k=>$w){
486
		if (match_self($w)) $where_sous[$k] = $w;
487
		else $where_simples[$k] = $w;
488
	}
489
	return array($where_simples,$where_sous);
490
}
491
492
493
/**
494
 * La fonction presente dans les squelettes compiles
495
 *
496
 * http://doc.spip.org/@calculer_select
497
 *
498
 * @param array $select
499
 * @param array $from
500
 * @param array $from_type
501
 * @param array $where
502
 * @param array $join
503
 * @param array $groupby
504
 * @param array $orderby
505
 * @param string $limit
506
 * @param array $having
507
 * @param string $table
508
 * @param string $id
509
 * @param string $serveur
510
 * @param bool $requeter
511
 * @return resource
512
 */
513
function calculer_select ($select = array(), $from = array(), 
514
			$from_type = array(),
515
      $where = array(), $join=array(),
516
			$groupby = array(), $orderby = array(), $limit = '',
517
			$having=array(), $table = '', $id = '', $serveur='', $requeter=true) {
518
519
	// retirer les criteres vides:
520
	// {X ?} avec X absent de l'URL
521
	// {par #ENV{X}} avec X absent de l'URL
522
	// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
523
	$menage = false;
524
	foreach($where as $k => $v) { 
525 View Code Duplication
		if (is_array($v)){
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...
526
			if ((count($v)>=2) && ($v[0]=='REGEXP') && ($v[2]=="'.*'")) $op= false;
527
			elseif ((count($v)>=2) && ($v[0]=='LIKE') && ($v[2]=="'%'")) $op= false;
528
			else $op = $v[0] ? $v[0] : $v;
529
		} else $op = $v;
530 View Code Duplication
		if ((!$op) OR ($op==1) OR ($op=='0=0')) {
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...
531
			unset($where[$k]);
532
			$menage = true;
533
		}
534
	}
535
536
	// evacuer les eventuels groupby vide issus d'un calcul dynamique
537
	$groupby = array_diff($groupby,array(''));
538
539
	// remplacer les sous requetes recursives au calcul
540
	list($where_simples,$where_sous) = trouver_sous_requetes($where);
541
	foreach($where_sous as $k=>$w) {
542
		$menage = true;
543
		// on recupere la sous requete 
544
		$sous = match_self($w);
545
		if ($sous[0]=='SELF') {
546
			// c'est une sous requete identique a elle meme sous la forme (SELF,$select,$where)
547
			array_push($where_simples,$sous[2]);
548
			$wheresub = array($sous[2],'0=0'); // pour accepter une string et forcer a faire le menage car on a surement simplifie select et where
549
			$jsub = $join;
550
			// trouver les jointures utiles a
551
			// reinjecter dans le where de la sous requete les conditions supplementaires des jointures qui y sont mentionnees
552
			// ie L1.objet='article'
553
			// on construit le where une fois, puis on ajoute les where complentaires si besoin, et on reconstruit le where en fonction
554
			$i = 0;
555
			do {
556
				$where[$k] = remplace_sous_requete($w,"(".calculer_select(
557
				array($sous[1]." AS id"),
558
				$from,
559
				$from_type,
560
				$wheresub,
561
				$jsub,
562
				array(),array(),'',
563
				$having,$table,$id,$serveur,false).")");
564
				if (!$i){
565
					$i = 1;
566
					$wherestring = calculer_where_to_string($where[$k]);
567
					foreach ($join as $cle=>$wj){
568
						if (count($wj)==4
569
							AND strpos($wherestring,"{$cle}.")!==FALSE
570
						){
571
							$i = 0;
572
							$wheresub[] = $wj[3];
573
							unset($jsub[$cle][3]);
574
						}
575
					}
576
				}
577
			} while ($i++<1);
578
		}
579
		if ($sous[0]=='SUBSELECT') {
580
			// c'est une sous requete explicite sous la forme identique a sql_select : (SUBSELECT,$select,$from,$where,$groupby,$orderby,$limit,$having)
581
			array_push($where_simples,$sous[3]); // est-ce utile dans ce cas ?
582
			$where[$k] = remplace_sous_requete($w,"(".calculer_select(
583
			$sous[1], # select
584
			$sous[2], #from
585
			array(), #from_type
586
			$sous[3]?(is_array($sous[3])?$sous[3]:array($sous[3])):array(), #where, qui peut etre de la forme string comme dans sql_select
587
			array(), #join
588
			$sous[4]?$sous[4]:array(), #groupby
589
			$sous[5]?$sous[5]:array(), #orderby
590
			$sous[6], #limit
591
			$sous[7]?$sous[7]:array(), #having
592
			$table,$id,$serveur,false
593
			).")");
594
		}
595
		array_pop($where_simples);
596
	}
597
598
	foreach($having as $k => $v) { 
599
		if ((!$v) OR ($v==1) OR ($v=='0=0')) {
600
			unset($having[$k]);
601
		}
602
	}
603
604
	// Installer les jointures.
605
	// Retirer celles seulement utiles aux criteres finalement absents mais
606
	// parcourir de la plus recente a la moins recente pour pouvoir eliminer Ln
607
	// si elle est seulement utile a Ln+1 elle meme inutile
608
	
609
	$afrom = array();
610
	$equiv = array();
611
	$k = count($join);
612
	foreach(array_reverse($join,true) as $cledef=>$j) {
613
		$cle = $cledef;
614
		// le format de join est :
615
		// array(table depart, cle depart [,cle arrivee[,condition optionnelle and ...]])
616
		if (count($join[$cle])==2) $join[$cle][] = $join[$cle][1];
617
		if (count($join[$cle])==3) $join[$cle][] = '';
618
		list($t,$c,$carr,$and) = $join[$cle];
619
		// si le nom de la jointure n'a pas ete specifiee, on prend Lx avec x sont rang dans la liste
620
		// pour compat avec ancienne convention
621
		if (is_numeric($cle))
622
			$cle = "L$k";
623
		if (!$menage
624
		OR isset($afrom[$cle])
625
		OR calculer_jointnul($cle, $select)
626
		OR calculer_jointnul($cle, array_diff_key($join, array($cle=>$join[$cle])))
627
		OR calculer_jointnul($cle, $having)
628
		OR calculer_jointnul($cle, $where_simples)) {
629
			// corriger les references non explicites dans select
630
			// ou groupby
631
			foreach($select as $i=>$s) {
632
				if ($s == $c) {
633
					$select[$i] = "$cle.$c AS $c";
634
					break;
635
				}
636
			}
637
			foreach($groupby as $i=>$g) {
638
				if ($g == $c) {
639
					$groupby[$i] = "$cle.$c";
640
					break;
641
				}
642
			}
643
			// on garde une ecriture decomposee pour permettre une simplification ulterieure si besoin
644
			// sans recours a preg_match
645
			// un implode(' ',..) est fait dans reinjecte_joint un peu plus bas
646
			$afrom[$t][$cle] = array("\n" .
647
				(isset($from_type[$cle])?$from_type[$cle]:"INNER")." JOIN",
648
				$from[$cle],
649
				"AS $cle",
650
				"ON (",
651
				"$cle.$c",
652
				"=",
653
				"$t.$carr",
654
				($and ? "AND ". $and:"") .
655
				")");
656
			if (isset($afrom[$cle])){
657
				$afrom[$t] = $afrom[$t] + $afrom[$cle];
658
				unset($afrom[$cle]);
659
			}
660
			$equiv[]= $carr;
661
		} else { unset($join[$cledef]);}
662
		unset($from[$cle]);
663
		$k--;
664
	}
665
666
	if (count($afrom)) {
667
		// Regarder si la table principale ne sert finalement a rien comme dans
668
		//<BOUCLE3(MOTS){id_article}{id_mot}> class='on'</BOUCLE3>
669
		//<BOUCLE2(MOTS){id_article} />#TOTAL_BOUCLE<//B2>
670
		//<BOUCLE5(RUBRIQUES){id_mot}{tout} />#TOTAL_BOUCLE<//B5>
671
		// ou dans
672
		//<BOUCLE8(HIERARCHIE){id_rubrique}{tout}{type='Squelette'}{inverse}{0,1}{lang_select=non} />#TOTAL_BOUCLE<//B8>
673
		// qui comporte plusieurs jointures
674
		// ou dans
675
		// <BOUCLE6(ARTICLES){id_mot=2}{statut==.*} />#TOTAL_BOUCLE<//B6>
676
		// <BOUCLE7(ARTICLES){id_mot>0}{statut?} />#TOTAL_BOUCLE<//B7>
677
		// penser a regarder aussi la clause orderby pour ne pas simplifier abusivement
678
		// <BOUCLE9(ARTICLES){recherche truc}{par titre}>#ID_ARTICLE</BOUCLE9>
679
		// penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
680
		// <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
681
		
682
	  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...
683
	  reset($from);
684
	  $e = '/\b(' . "$t\\." . join("|" . $t . '\.', $equiv) . ')\b/';
685
	  if (!(strpos($t, ' ') OR // jointure des le depart cf boucle_doc
686
		 calculer_jointnul($t, $select, $e) OR
687
		 calculer_jointnul($t, $join, $e) OR
688
		 calculer_jointnul($t, $where, $e) OR
689
		 calculer_jointnul($t, $orderby, $e) OR
690
		 calculer_jointnul($t, $groupby, $e) OR
691
		 calculer_jointnul($t, $having, $e))
692
		 && count($afrom[$t])) {
693
		 	reset($afrom[$t]);
694
		 	list($nt,$nfrom) = each($afrom[$t]);
695
	    unset($from[$t]);
696
	    $from[$nt] = $nfrom[1];
697
	    unset($afrom[$t][$nt]);
698
	    $afrom[$nt] = $afrom[$t];
699
	    unset($afrom[$t]);
700
	    $e = '/\b'.preg_quote($nfrom[6]).'\b/';
701
	    $t = $nfrom[4];
702
	    $alias = "";
703
	    // verifier que les deux cles sont homonymes, sinon installer un alias dans le select
704
	    $oldcle = explode('.',$nfrom[6]);
705
	    $oldcle = end($oldcle);
706
	    $newcle = explode('.',$nfrom[4]);
707
	    $newcle = end($newcle);
708
	    if ($newcle!=$oldcle){
709
		    // si l'ancienne cle etait deja dans le select avec un AS
710
		    // reprendre simplement ce AS
711
		    $as = '/\b'.preg_quote($nfrom[6]).'\s+(AS\s+\w+)\b/';
712
		    if (preg_match($as,implode(',',$select),$m)){
713
			    $alias = "";
714
		    }
715
		    else
716
					$alias = ", ".$nfrom[4]." AS $oldcle";
717
	    }
718
	    $select = remplacer_jointnul($t . $alias, $select, $e);
719
	    $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...
720
	    $where = remplacer_jointnul($t, $where, $e);
721
	    $having = remplacer_jointnul($t, $having, $e);
722
	    $groupby = remplacer_jointnul($t, $groupby, $e);
723
	    $orderby = remplacer_jointnul($t, $orderby, $e);
724
	  }
725
	  $from = reinjecte_joint($afrom, $from);
726
	}
727
	$GLOBALS['debug']['aucasou'] = array ($table, $id, $serveur, $requeter);
728
	$r = sql_select($select, $from, $where,
729
		$groupby, array_filter($orderby), $limit, $having, $serveur, $requeter);
730
	unset($GLOBALS['debug']['aucasou']);
731
	return $r;
732
}
733
734
/**
735
 * Analogue a calculer_mysql_expression et autre (a unifier ?)
736
 * @param string|array $v
737
 * @param string $join
738
 * @return string
739
 */
740 View Code Duplication
function calculer_where_to_string($v, $join = 'AND'){
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...
741
	if (empty($v))
742
		return '';
743
744
	if (!is_array($v)) {
745
		return $v;
746
	} else {
747
		$exp = "";
748
		if (strtoupper($join) === 'AND')
749
			return $exp . join(" $join ", array_map('calculer_where_to_string', $v));
750
		else
751
			return $exp . join($join, $v);
752
	}
753
}
754
755
756
//condition suffisante (mais non necessaire) pour qu'une table soit utile
757
758
// http://doc.spip.org/@calculer_jointnul
759
function calculer_jointnul($cle, $exp, $equiv='')
760
{
761
	if (!is_array($exp)) {
762
		if ($equiv) $exp = preg_replace($equiv, '', $exp);
763
		return preg_match("/\\b$cle\\./", $exp);
764
	} else {
765
		foreach($exp as $v) {
766
			if (calculer_jointnul($cle, $v, $equiv)) return true;
767
		}
768
		return false;
769
	}
770
}
771
772
// http://doc.spip.org/@reinjecte_joint
773
function reinjecte_joint($afrom, $from)
774
{
775
	  $from_synth = array();
776
	  foreach($from as $k=>$v){
777
	  	$from_synth[$k]=$from[$k];
778
	  	if (isset($afrom[$k])) {
779
	  		foreach($afrom[$k] as $kk=>$vv) $afrom[$k][$kk] = implode(' ',$afrom[$k][$kk]);
780
	  		$from_synth["$k@"]= implode(' ',$afrom[$k]);
781
	  		unset($afrom[$k]);
782
	  	}
783
	  }
784
	  return $from_synth;
785
}
786
787
// http://doc.spip.org/@remplacer_jointnul
788
function remplacer_jointnul($cle, $exp, $equiv='')
789
{
790
	if (!is_array($exp)) {
791
		return preg_replace($equiv, $cle, $exp);
792
	} else {
793
		foreach($exp as $k => $v) {
794
		  $exp[$k] = remplacer_jointnul($cle, $v, $equiv);
795
		}
796
		return $exp;
797
	}
798
}
799
800
// calcul du nom du squelette
801
// http://doc.spip.org/@calculer_nom_fonction_squel
802
function calculer_nom_fonction_squel($skel, $mime_type='html', $connect='')
803
{
804
	// ne pas doublonner les squelette selon qu'ils sont calcules depuis ecrire/ ou depuis la racine
805 View Code Duplication
	if ($l=strlen(_DIR_RACINE) AND strncmp($skel,_DIR_RACINE,$l)==0)
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...
806
		$skel = substr($skel,strlen(_DIR_RACINE));
807
	return $mime_type
808
	. (!$connect ?  '' : preg_replace('/\W/',"_", $connect)) . '_'
809
	. md5($GLOBALS['spip_version_code'] . ' * ' . $skel . (isset($GLOBALS['marqueur_skel'])?'*'.$GLOBALS['marqueur_skel']:''));
810
}
811
812
?>
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...
813