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

compiler.php ➔ compile_cas()   F

Complexity

Conditions 39
Paths 2528

Size

Total Lines 171
Code Lines 134

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 39
eloc 134
c 0
b 0
f 0
nc 2528
nop 4
dl 0
loc 171
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
14
/**
15
 * Fichier principal du compilateur de squelettes
16
 *
17
 * @package SPIP\Compilateur\Compilation
18
**/
19
20
if (!defined('_ECRIRE_INC_VERSION')) return;
21
22
/** Repérer un code ne calculant rien, meme avec commentaire */
23
define('CODE_MONOTONE', ",^(\n//[^\n]*\n)?\(?'([^'])*'\)?$,");
24
/** Indique s'il faut commenter le code produit */
25
define('CODE_COMMENTE', true);
26
27
// definition des structures de donnees
28
include_spip('public/interfaces');
29
30
// Definition de la structure $p, et fonctions de recherche et de reservation
31
// dans l'arborescence des boucles
32
include_spip('public/references');
33
34
// production du code qui peut etre securisee
35
include_spip('public/sandbox');
36
37
// definition des boucles
38
include_spip('public/boucles');
39
40
// definition des criteres
41
include_spip('public/criteres');
42
43
// definition des balises
44
include_spip('public/balises');
45
46
// Gestion des jointures
47
include_spip('public/jointures');
48
49
// Les 2 ecritures INCLURE{A1,A2,A3...} et INCLURE(A1){A2}{A3}... sont admises
50
// Preferer la premiere.
51
// Les Ai sont de la forme Vi=Ei ou bien Vi qui veut alors dire Vi=Vi
52
// Le resultat est un tableau indexe par les Vi
53
// Toutefois, si le premier argument n'est pas de la forme Vi=Ei
54
// il est conventionnellement la valeur de l'index 1.
55
// pour la balise #INCLURE
56
// mais pas pour <INCLURE> dont le fond est defini explicitement.
57
58
59
// http://doc.spip.org/@argumenter_inclure
60
function argumenter_inclure($params, $rejet_filtres, $p, &$boucles, $id_boucle, $echap=true, $lang = '', $fond1=false){
0 ignored issues
show
Unused Code introduced by
The parameter $rejet_filtres 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...
61
	$l = array();
62
	$erreur_p_i_i = '';
63
	if (!is_array($params)) return $l;
64
	foreach($params as $k => $couple) {
65
	// la liste d'arguments d'inclusion peut se terminer par un filtre
66
		$filtre = array_shift($couple);
67
		if ($filtre) break;
68
		foreach($couple as $n => $val) {
69
			$var = $val[0];
70
			if ($var->type != 'texte') {
71
			  if ($n OR $k OR $fond1) {
72
				$erreur_p_i_i = array('zbug_parametres_inclus_incorrects',
73
					 array('param' => $var->nom_champ));
74
				erreur_squelette($erreur_p_i_i, $p);
75
				  break;
76
			  }
77
			  else $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle);
78
			} else {
79
				preg_match(",^([^=]*)(=?)(.*)$,m", $var->texte,$m);
80
				$var = $m[1];
81
				$auto = false;;
82
				if ($m[2]) {
83
				  $v = $m[3];
84
				  if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) $v = $m[1];
85
				  $val[0] = new Texte;
86
				  $val[0]->texte = $v;
87
				} elseif ($k OR $n OR $fond1) {
88
				  $auto = true;
89
				} else $var = 1;
90
91
				if ($var == 'lang') {
92
				  $lang = !$auto 
93
				    ? calculer_liste($val, $p->descr, $boucles, $id_boucle)
94
				    : '$GLOBALS["spip_lang"]';
95
				} else {
96
				  $val = $auto
97
				    ? index_pile($id_boucle, $var, $boucles)
98
				    : calculer_liste($val, $p->descr, $boucles, $id_boucle);
99
				  if ($var !== 1)
100
				    $val = ($echap?"\'$var\' => ' . argumenter_squelette(":"'$var' => ")
101
				    . $val . ($echap? ") . '":" ");
102
				  else $val = $echap ? "'.$val.'" : $val;
103
				  $l[$var] = $val;
104
				}
105
			}
106
		}
107
	}
108
	if ($erreur_p_i_i) return false;
109
	// Cas particulier de la langue : si {lang=xx} est definie, on
110
	// la passe, sinon on passe la langue courante au moment du calcul
111
	// sauf si on n'en veut pas 
112
	if ($lang === false) return $l;
113
	if (!$lang) $lang = '$GLOBALS["spip_lang"]';
114
	$l['lang'] = ($echap?"\'lang\' => ' . argumenter_squelette(":"'lang' => ")  . $lang . ($echap?") . '":" ");
115
116
	return $l;
117
}
118
119
/**
120
 * Code d'appel à un <INCLURE()>
121
 *
122
 * Code PHP pour un squelette (aussi pour #INCLURE, #MODELE #LES_AUTEURS)
123
 */
124
define('CODE_RECUPERER_FOND', 'recuperer_fond(%s, %s, array(%s), %s)');
125
126
/**
127
 * Compile une inclusion <INCLURE> ou #INCLURE
128
 *
129
 * @param Inclure $p
130
 *     Description de l'inclusion (AST au niveau de l'inclure)
131
 * @param array $boucles
132
 *     AST du squelette
133
 * @param string $id_boucle
134
 *     Identifiant de la boucle contenant l'inclure
135
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be false|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...
136
 *     Code PHP appelant l'inclusion
137
**/
138
function calculer_inclure($p, &$boucles, $id_boucle) {
139
140
	$_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true);
141
	if (is_string($p->texte)) {
142
		$fichier = $p->texte;
143
		$code = "\"$fichier\"";
144
145
	} else {
146
		$code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle);
0 ignored issues
show
Bug introduced by
The property descr does not seem to exist in Inclure.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
147
		if ($code AND preg_match("/^'([^']*)'/s", $code, $r))
148
			$fichier = $r[1];
149
		else $fichier = '';
150
	}
151
	if (!$code OR $code === '""') {
152
		$erreur_p_i_i = array('zbug_parametres_inclus_incorrects',
153
					 array('param' => $code));
154
		erreur_squelette($erreur_p_i_i, $p);
155
		return false;
156
	}
157
	$compil = texte_script(memoriser_contexte_compil($p));
158
159
	if (is_array($_contexte)) {
160
		// Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
161
		if ($env = (isset($_contexte['env'])|| isset($_contexte['self']))) {
162
			unset($_contexte['env']);
163
		}
164
165
		// noter les doublons dans l'appel a public.php
166
		if (isset($_contexte['doublons'])) {
167
			$_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
168
		}
169
170 View Code Duplication
		if ($ajax = isset($_contexte['ajax'])){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
171
			$ajax = preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
172
			unset($_contexte['ajax']);
173
		}
174
175
		$_contexte = join(",\n\t", $_contexte);
176
	}
177
	else
178
		return false; // j'aurais voulu toucher le fond ...
179
		
180
	$contexte = 'array(' . $_contexte  .')';
181
182
	if ($env) {
183
		$contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)";
184
	}
185
186
	// s'il y a une extension .php, ce n'est pas un squelette
187
	if (preg_match('/^.+[.]php$/s', $fichier)) {
188
		$code = sandbox_composer_inclure_php($fichier, $p, $contexte);
189
	} else 	{
190
		$_options[] = "\"compil\"=>array($compil)";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$_options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $_options = 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...
191
		if ($ajax)
192
			$_options[] = $ajax;
193
		$code = " ' . argumenter_squelette($code) . '"; 
194
		$code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',',$_options), "_request(\"connect\")") . ';';
195
	}
196
197
	return	"\n'<'.'".	"?php ". $code . "\n?'." . "'>'";
198
}
199
200
201
/**
202
 * Gérer les statuts declarés pour cette table
203
 *
204
 * S'il existe des statuts sur cette table, déclarés dans la description
205
 * d'un objet éditorial, applique leurs contraintes
206
 *
207
 * @param Boucle $boucle
208
 *     Descrition de la boucle
209
 * @param bool $echapper
210
 *     true pour échapper le code créé
211
 * @param bool $ignore_previsu
212
 *     true pour ne tester que le cas publie et ignorer l'eventuel var_mode=preview de la page
213
 */
214
function instituer_boucle(&$boucle, $echapper=true, $ignore_previsu=false){
215
	/*
216
	$show['statut'][] = array(
217
		'champ'=>'statut',  // champ de la table sur lequel porte le filtrage par le statut
218
		'publie'=>'publie', // valeur ou liste de valeurs, qui definissent l'objet comme publie.
219
		'previsu'=>'publie,prop', // valeur ou liste de valeurs qui sont visibles en previsu
220
		'post_date'=>'date', // un champ de date pour la prise en compte des post_dates, ou rien sinon
221
	  'exception'=>'statut', // liste des modificateurs qui annulent le filtrage par statut
222
	                         // si plusieurs valeurs : array('statut','tout','lien')
223
	);
224
225
	Pour 'publier' ou 'previsu', si la chaine commence par un "!" on exclu au lieu de filtrer sur les valeurs donnees
226
	si la chaine est vide, on ne garde rien si elle est seulement "!" on n'exclu rien
227
228
	Si le statut repose sur une jointure, 'champ' est alors un tableau du format suivant :
229
	'champ'=>array(
230
	    array(table1, cle1),
231
	    ...
232
	    array(tablen, clen),
233
	    champstatut
234
	 )
235
236
	champstatut est alors le champ statut sur la tablen
237
	dans les jointures, clen peut etre un tableau pour une jointure complexe : array('id_objet','id_article','objet','article')
238
*/
239
	$id_table = $boucle->id_table;
240
	$show = $boucle->show;
241
	if (isset($show['statut']) AND $show['statut']){
242
		foreach($show['statut'] as $k=>$s){
243
			// Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
244
			$filtrer = true;
245
			if (isset($s['exception'])) {
246
				foreach(is_array($s['exception'])?$s['exception']:array($s['exception']) as $m) {
247
					if (isset($boucle->modificateur[$m]) OR isset($boucle->modificateur['criteres'][$m])) {
248
						$filtrer = false;
249
						break;
250
					}
251
				}
252
			}
253
254
			if ($filtrer) {
255
				if (is_array($s['champ'])){
256
					$statut = preg_replace(',\W,','',array_pop($s['champ'])); // securite
257
					$jointures = array();
258
					// indiquer la description de chaque table dans le tableau de jointures,
259
					// ce qui permet d'eviter certains GROUP BY inutiles.
260
					$trouver_table = charger_fonction('trouver_table', 'base');
261
					foreach($s['champ'] as $j) {
262
						$id = reset($j);
263
						$def = $trouver_table($id);
264
						$jointures[] = array('',array($id,$def),end($j));
265
					}
266
					$jointures[0][0] = $id_table;
267
					if (!array_search($id, $boucle->from)){
0 ignored issues
show
Bug introduced by
The variable $id 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...
268
						include_spip('public/jointures');
269
						fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper);
270
					}
271
					// trouver l'alias de la table d'arrivee qui porte le statut
272
					$id = array_search($id, $boucle->from);
273
				}
274
				else {
275
					$id = $id_table;
276
					$statut = preg_replace(',\W,','',$s['champ']); // securite
277
				}
278
				$mstatut = $id .'.'.$statut;
279
280
				$arg_ignore_previsu=($ignore_previsu?",true":'');
281
				include_spip('public/quete');
282
				if (isset($s['post_date']) AND $s['post_date']
283
					AND $GLOBALS['meta']["post_dates"] == 'non'){
284
					$date = $id.'.'.preg_replace(',\W,','',$s['post_date']); // securite
285
					array_unshift($boucle->where,
286
						$echapper ?
287
							"\nquete_condition_postdates('$date',"._q($boucle->sql_serveur)."$arg_ignore_previsu)"
288
						:
289
							quete_condition_postdates($date,$boucle->sql_serveur,$ignore_previsu)
290
					);
291
				}
292
				array_unshift($boucle->where,
293
					$echapper ?
294
						"\nquete_condition_statut('$mstatut',"
295
							. _q($s['previsu']).","
296
							._q($s['publie']).","
297
							._q($boucle->sql_serveur)."$arg_ignore_previsu)"
298
					:
299
						quete_condition_statut($mstatut,$s['previsu'],$s['publie'],$boucle->sql_serveur,$ignore_previsu)
300
				);
301
			}
302
		}
303
	}
304
}
305
306
/**
307
 * Produit le corps PHP d'une boucle Spip.
308
 * 
309
 * Ce corps remplit une variable $t0 retournée en valeur.
310
 * Ici on distingue boucles recursives et boucle à requête SQL
311
 * et on insère le code d'envoi au debusqueur du resultat de la fonction.
312
 *
313
 * @param string $id_boucle
314
 * 		Identifiant de la boucle
315
 * @param array $boucles
316
 * 		AST du squelette
317
 * @return string
318
 * 		Code PHP compilé de la boucle
319
 */
320
function calculer_boucle($id_boucle, &$boucles) {
321
322
	$boucle = &$boucles[$id_boucle];
323
	instituer_boucle($boucle);
324
	$boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
325
326
	// en mode debug memoriser les premiers passages dans la boucle,
327
	// mais pas tous, sinon ca pete.
328
	if  (_request('var_mode_affiche') != 'resultat') 
329
		$trace = '';
330
	else {
331
		$trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle;
332
		$trace = "if (count(@\$GLOBALS['debug_objets']['resultat']['$trace'])<3)
333
	    \$GLOBALS['debug_objets']['resultat']['$trace'][] = \$t0;";
334
	}
335
	return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF)
336
	? calculer_boucle_rec($id_boucle, $boucles, $trace) 
337
	: calculer_boucle_nonrec($id_boucle, $boucles, $trace);
338
}
339
340
341
/**
342
 * Compilation d'une boucle recursive. 
343
 *
344
 * @internal
345
 * 		Il suffit (ET IL FAUT) sauvegarder les valeurs des arguments passes par
346
 * 		reference, car par definition un tel passage ne les sauvegarde pas
347
 * 
348
 * @param string $id_boucle
349
 * 		Identifiant de la boucle
350
 * @param array $boucles
351
 * 		AST du squelette
352
 * @param string $trace
353
 * 		Code PHP (en mode debug uniquement) servant à conserver une
354
 * 		trace des premières valeurs de la boucle afin de pouvoir
355
 * 		les afficher dans le débugueur ultérieurement
356
 * @return string
357
 * 		Code PHP compilé de la boucle récursive
358
**/
359
function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
360
	$nom = $boucles[$id_boucle]->param[0];
361
	return
362
	  // Numrows[$nom] peut ne pas être encore defini
363
	  "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());"
364
	. "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";"
365
	. "\n\t\$Numrows['$nom'] = (\$save_numrows);"
366
	. $trace
367
	. "\n\treturn \$t0;";
368
}
369
370
/**
371
 * Compilation d'une boucle non recursive.
372
 * 
373
 * La constante donne le cadre systématique du code:
374
 * %s1: initialisation des arguments de calculer_select
375
 * %s2: appel de calculer_select en donnant un contexte pour les cas d'erreur
376
 * %s3: initialisation du sous-tableau Numrows[id_boucle]
377
 * %s4: sauvegarde de la langue et calcul des invariants de boucle sur elle
378
 * %s5: boucle while sql_fetch ou str_repeat si corps monotone
379
 * %s6: restauration de la langue
380
 * %s7: liberation de la ressource, en tenant compte du serveur SQL 
381
 * %s8: code de trace eventuel avant le retour
382
**/
383
define('CODE_CORPS_BOUCLE', '%s
384
	if (defined("_BOUCLE_PROFILER")) $timer = time()+microtime();
385
	$t0 = "";
386
	// REQUETE
387
	$iter = IterFactory::create(
388
		"%s",
389
		%s,
390
		array(%s)
391
	);
392
	if (!$iter->err()) {
393
	%s%s$SP++;
394
	// RESULTATS
395
	%s
396
	%s$iter->free();
397
	}%s
398
	if (defined("_BOUCLE_PROFILER")
399
	AND 1000*($timer = (time()+microtime())-$timer) > _BOUCLE_PROFILER)
400
		spip_log(intval(1000*$timer)."ms %s","profiler"._LOG_AVERTISSEMENT);
401
	return $t0;'
402
);
403
404
/**
405
 * Compilation d'une boucle (non recursive). 
406
 *
407
 * @param string $id_boucle
408
 * 		Identifiant de la boucle
409
 * @param array $boucles
410
 * 		AST du squelette
411
 * @param string $trace
412
 * 		Code PHP (en mode debug uniquement) servant à conserver une
413
 * 		trace des premières valeurs de la boucle afin de pouvoir
414
 * 		les afficher dans le débugueur ultérieurement
415
 * @return string
416
 * 		Code PHP compilé de la boucle récursive
417
**/
418
function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
419
420
	$boucle = &$boucles[$id_boucle];
421
	$return = $boucle->return;
422
	$type_boucle = $boucle->type_requete;
423
	$primary = $boucle->primary;
424
	$constant = preg_match(CODE_MONOTONE, str_replace("\\'",'', $return));
425
	$flag_cpt = $boucle->mode_partie ||$boucle->cptrows;
426
	$corps = '';
427
428
	// faudrait expanser le foreach a la compil, car y en a souvent qu'un 
429
	// et puis faire un [] plutot qu'un "','."
430
	if ($boucle->doublons)
431
		$corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' .
432
		index_pile($id_boucle, $primary, $boucles)
433
		. "; // doublons\n";
434
435
	// La boucle doit-elle selectionner la langue ?
436
	// - par defaut, les boucles suivantes le font
437
	//    (sauf si forcer_lang==true ou si le titre contient <multi>).
438
	// - a moins d'une demande explicite via {!lang_select}
439
	if (!$constant && $boucle->lang_select != 'non' &&
440
	    (($boucle->lang_select == 'oui')  ||
441
		    in_array($type_boucle, array(
442
		    	'articles', 'rubriques', 'hierarchie', 'breves'
443
			)))
444
	) {
445
		// Memoriser la langue avant la boucle et la restituer apres
446
		// afin que le corps de boucle affecte la globale directement
447
		$init_lang = "lang_select(\$GLOBALS['spip_lang']);\n\t";
448
		$fin_lang = "lang_select();\n\t";
449
		$fin_lang_select_public = "\n\t\tlang_select();";
450
451
		$corps .= 
452
			"\n\t\tlang_select_public("
453
			. index_pile($id_boucle, 'lang', $boucles)
0 ignored issues
show
Bug introduced by
It seems like $boucles defined by parameter $boucles on line 418 can also be of type array; however, index_pile() does only seem to accept object, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
454
			. ", '".$boucle->lang_select."'"
455
			. (in_array($type_boucle, array(
456
				'articles', 'rubriques', 'hierarchie', 'breves'
457
				)) ? ', '.index_pile($id_boucle, 'titre', $boucles) : '')
458
			. ');';
459
	}
460
	else {
461
		$init_lang = '';
462
		$fin_lang = '';
463
		$fin_lang_select_public = '';
464
		// sortir les appels au traducteur (invariants de boucle)
465
		if (strpos($return, '?php') === false
466
		AND preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)) {
467
			$i = 1;
468
			foreach($r[1] as $t) {
469
				$init_lang .= "\n\t\$l$i = $t;";
470
				$return = str_replace($t, "\$l$i", $return);
471
				$i++;
472
			}
473
		}
474
	}
475
476
	// gestion optimale des separateurs et des boucles constantes
477
	if (count($boucle->separateur))
478
	  $code_sep = ("'" . str_replace("'","\'",join('',$boucle->separateur)) . "'");
479
480
	$corps .= 
481
		((!$boucle->separateur) ? 
482
			(($constant && !$corps && !$flag_cpt) ? $return :
483
			 (($return==="''") ? '' :
484
			  ("\n\t\t" . '$t0 .= ' . $return . ";"))) :
485
		 ("\n\t\t\$t1 " .
486
			((strpos($return, '$t1.') === 0) ? 
487
			 (".=" . substr($return,4)) :
488
			 ('= ' . $return)) .
489
		  ";\n\t\t" .
490
		  '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;"));
0 ignored issues
show
Bug introduced by
The variable $code_sep 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...
491
     
492
	// Calculer les invalideurs si c'est une boucle non constante et si on
493
	// souhaite invalider ces elements
494
	if (!$constant AND $primary) {
495
		include_spip('inc/invalideur');
496
		if (function_exists($i = 'calcul_invalideurs'))
497
			$corps = $i($corps, $primary, $boucles, $id_boucle);
498
	}
499
500
	// gerer le compteur de boucle 
501
	// avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}...
502
503
	if ($boucle->partie OR $boucle->cptrows)
504
		$corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;"
505
		. $boucle->partie 
506
		. $corps;
507
508
	// depiler la lang de la boucle si besoin
509
	$corps .= $fin_lang_select_public;
510
511
	// si le corps est une constante, ne pas appeler le serveur N fois!
512
513
	if (preg_match(CODE_MONOTONE,str_replace("\\'",'',$corps), $r)) {
514
		if (!isset($r[2]) OR (!$r[2])) {
515
			if (!$boucle->numrows)
516
				return "\n\t\$t0 = '';";
517
			else
518
				$corps = "";
519
		} else {
520
			$boucle->numrows = true;
521
			$corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
522
		}
523
	} else $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n	}"; 
524
525
	$count = '';
0 ignored issues
show
Unused Code introduced by
$count 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...
526
	if (!$boucle->select) {
527
		if (!$boucle->numrows OR $boucle->limit OR $boucle->mode_partie OR $boucle->group)
528
			$count = '1';
529
		else $count = 'count(*)';
530
		$boucles[$id_boucle]->select[]= $count; 
531
	}
532
533
	if ($flag_cpt)
534
		$nums = "\n\t// COMPTEUR\n\t"
535
		. "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t";
536
	else $nums = '';
537
538
	if ($boucle->numrows OR $boucle->mode_partie) {
539
		$nums .= "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());"
540
		. $boucle->mode_partie
541
		. "\n\t";
542
	}
543
544
	// Ne calculer la requete que maintenant
545
	// car ce qui precede appelle index_pile qui influe dessus
546
547
	$init = (($init = $boucles[$id_boucle]->doublons)
548
			 ? ("\n\t$init = array();") : '')
549
	. calculer_requete_sql($boucles[$id_boucle]);
550
551
	$contexte = memoriser_contexte_compil($boucle);
552
553
	$a = sprintf(CODE_CORPS_BOUCLE,
554
		$init,
555
		$boucle->iterateur,
556
		"\$command",
557
		$contexte,
558
		$nums,
559
		$init_lang,
560
		$corps,
561
		$fin_lang,
562
		$trace,
563
		'BOUCLE'.$id_boucle .' @ '.($boucle->descr['sourcefile'])
564
	);
565
566
#	var_dump($a);exit;
567
	return $a;
568
}
569
570
571
/**
572
 * Calcule le code PHP d'une boucle contenant les informations qui produiront une requête SQL
573
 *
574
 * Le code produit est un tableau associatif $command contenant les informations
575
 * pour que la boucle produise ensuite sa requête, tel que $command['from'] = 'spip_articles';
576
 *
577
 * @param Boucle $boucle
578
 * 		AST de la boucle 
579
 * @return string
580
 * 		Code PHP compilé définissant les informations de requête
581
**/
582
function calculer_requete_sql($boucle)
583
{
584
	$init = array();
585
	$init[] = calculer_dec('table',  "'" . $boucle->id_table ."'");
586
	$init[] = calculer_dec('id', "'" . $boucle->id_boucle ."'");
587
	# En absence de champ c'est un decompte :
588
	$init[] = calculer_dec('from',  calculer_from($boucle));
589
	$init[] = calculer_dec('type', calculer_from_type($boucle));
590
	$init[] = calculer_dec('groupby', 'array(' . (($g=join("\",\n\t\t\"",$boucle->group))?'"'.$g.'"':'') . ")");
591
	$init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select).  "\")");
592
	$init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) .	")");
593
	$init[] = calculer_dec('where', calculer_dump_array($boucle->where));
594
	$init[] = calculer_dec('join', calculer_dump_join($boucle->join));
595
	$init[] = calculer_dec('limit',
596
			(strpos($boucle->limit, 'intval') === false ?
597
				  "'".$boucle->limit."'"
598
				:
599
				  $boucle->limit));
600
	$init[] = calculer_dec('having', calculer_dump_array($boucle->having));
601
	$s = $d = "";
602
	foreach ($init as $i){
603
		if (reset($i))
604
			$s .= "\n\t\t".end($i);
605
		else
606
			$d .= "\n\t".end($i);
607
	}
608
609
	return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '')
610
	  . $boucle->in 
611
	  . $boucle->hash
612
		. "\n\t".'if (!isset($command[\'table\'])) {'
613
		. $s
614
		. "\n\t}"
615
		. $d;
616
}
617
618
/**
619
 * Retourne une chaîne des informations du contexte de compilation
620
 *
621
 * Retourne la source, le nom, l'identifiant de boucle, la ligne, la langue
622
 * de l'élément dans une chaîne.
623
 *
624
 * @see reconstruire_contexte_compil()
625
 * 
626
 * @param Object $p
627
 *     Objet de l'AST dont on mémorise le contexte
628
 * @return string
629
 *     Informations du contexte séparés par des virgules,
630
 *     qui peut être utilisé pour la production d'un tableau array()
631
**/
632
function memoriser_contexte_compil($p) {
633
	return join(',', array(
634
		_q($p->descr['sourcefile']),
635
		_q($p->descr['nom']),
636
		@_q($p->id_boucle),
637
		intval($p->ligne),
638
		'$GLOBALS[\'spip_lang\']'));
639
}
640
641
/**
642
 * Reconstruit un contexte de compilation 
643
 *
644
 * Pour un tableau d'information de contexte donné,
645
 * retourne un objet Contexte (objet générique de l'AST)
646
 * avec ces informations
647
 *
648
 * @see memoriser_contexte_compil()
649
 * 
650
 * @param array $context_compil
651
 *     Tableau des informations du contexte
652
 * @return Contexte
653
 *     Objet Contexte
654
**/
655
function reconstruire_contexte_compil($context_compil)
656
{
657
	if (!is_array($context_compil)) return $context_compil;
658
	$p = new Contexte;
659
	$p->descr = array('sourcefile' => $context_compil[0],
660
				  'nom' => $context_compil[1]);
661
	$p->id_boucle = $context_compil[2];
662
	$p->ligne = $context_compil[3];
663
	$p->lang = $context_compil[4];
664
	return $p;
665
}
666
667
// http://doc.spip.org/@calculer_dec
668
function calculer_dec($nom, $val)
669
{
670
	$static = 'if (!isset($command[\''.$nom.'\'])) ';
671
	// si une variable apparait dans le calcul de la clause
672
	// il faut la re-evaluer a chaque passage
673
	if (
674
		strpos($val, '$') !== false
675
		/*
676
		OR strpos($val, 'sql_') !== false
677
		OR (
678
			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
679
			AND strpos($test,"(")!==FALSE // si pas de parenthese ouvrante, pas de fonction, on peut sortir
680
			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
681
			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
682
		)*/
683
	)
684
		$static = "";
685
686
	return array($static,'$command[\''.$nom.'\'] = ' . $val . ';');
687
}
688
689
// http://doc.spip.org/@calculer_dump_array
690
function calculer_dump_array($a)
691
{
692
  if (!is_array($a)) return $a ;
693
  $res = "";
694
  if ($a AND $a[0] == "'?'") 
695
    return ("(" . calculer_dump_array($a[1]) .
696
	    " ? " . calculer_dump_array($a[2]) .
697
	    " : " . calculer_dump_array($a[3]) .
698
	    ")");
699
  else {
700
    foreach($a as $v) $res .= ", " . calculer_dump_array($v);
701
    return "\n\t\t\tarray(" . substr($res,2) . ')';
702
  }
703
}
704
705
// http://doc.spip.org/@calculer_dump_join
706
function calculer_dump_join($a)
707
{
708
  $res = "";
709
  foreach($a as $k => $v) 
710
		$res .= ", '$k' => array(".implode(',',$v).")";
711
  return 'array(' . substr($res,2) . ')';
712
}
713
714
// http://doc.spip.org/@calculer_from
715
function calculer_from(&$boucle)
716
{
717
  $res = "";
718
  foreach($boucle->from as $k => $v) $res .= ",'$k' => '$v'";
719
  return 'array(' . substr($res,1) . ')';
720
}
721
722
// http://doc.spip.org/@calculer_from_type
723
function calculer_from_type(&$boucle)
724
{
725
  $res = "";
726
  foreach($boucle->from_type as $k => $v) $res .= ",'$k' => '$v'";
727
  return 'array(' . substr($res,1) . ')';
728
}
729
730
// http://doc.spip.org/@calculer_order
731
function calculer_order(&$boucle)
732
{
733
	if (!$order = $boucle->order
734
	AND !$order = $boucle->default_order)
735
		$order = array();
736
737
	/*if (isset($boucle->modificateur['collate'])){
738
		$col = "." . $boucle->modificateur['collate'];
739
		foreach($order as $k=>$o)
740
			if (strpos($order[$k],'COLLATE')===false)
741
				$order[$k].= $col;
742
	}*/
743
	return join(', ', $order);
744
}
745
746
// Production du code PHP a partir de la sequence livree par le phraseur
747
// $boucles est passe par reference pour affectation par index_pile.
748
// Retourne une expression PHP,
749
// (qui sera argument d'un Return ou la partie droite d'une affectation).
750
751
// http://doc.spip.org/@calculer_liste
752
function calculer_liste($tableau, $descr, &$boucles, $id_boucle='') {
753
	if (!$tableau) return "''";
754
	if (!isset($descr['niv'])) $descr['niv'] = 0;
755
	$codes = compile_cas($tableau, $descr, $boucles, $id_boucle);
756
	if ($codes === false) return false;
757
	$n = count($codes);
758
	if (!$n) return "''";
759
	$tab = str_repeat("\t", $descr['niv']);
760
	if (_request('var_mode_affiche') != 'validation') {
761
		if ($n==1) 
762
			return $codes[0];
763
		else {
764
			$res = '';
765
			foreach($codes as $code) {
766
				if (!preg_match("/^'[^']*'$/", $code)
767
				OR substr($res,-1,1)!=="'")
768
				  $res .=  " .\n$tab$code";
769
				else {
770
				  $res = substr($res,0,-1) . substr($code,1);
771
				}
772
			}
773
			return '(' . substr($res,2+$descr['niv']) . ')';
774
		}
775
	} else {
776
	  $nom = $descr['nom'] . $id_boucle .  ($descr['niv']?$descr['niv']:'');
777
	  return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" .  join(" ,\n$tab", $codes) . ")))";
778
	}
779
}
780
781
define('_REGEXP_COND_VIDE_NONVIDE',"/^[(](.*)[?]\s*''\s*:\s*('[^']+')\s*[)]$/");
782
define('_REGEXP_COND_NONVIDE_VIDE',"/^[(](.*)[?]\s*('[^']+')\s*:\s*''\s*[)]$/");
783
define('_REGEXP_CONCAT_NON_VIDE', "/^(.*)[.]\s*'[^']+'\s*$/");
784
785
// http://doc.spip.org/@compile_cas
786
function compile_cas($tableau, $descr, &$boucles, $id_boucle) {
787
788
        $codes = array();
789
	// cas de la boucle recursive
790
	if (is_array($id_boucle)) 
791
	  $id_boucle = $id_boucle[0];
792
	$type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete;
793
	$tab = str_repeat("\t", ++$descr['niv']);
794
	$mode = _request('var_mode_affiche');
795
	$err_e_c = '';
796
	// chaque commentaire introduit dans le code doit commencer
797
	// par un caractere distinguant le cas, pour exploitation par debug.
798
	foreach ($tableau as $p) {
799
800
		switch($p->type) {
801
		// texte seul
802
		case 'texte':
803
			$code = sandbox_composer_texte($p->texte, $p);
804
			$commentaire= strlen($p->texte) . " signes";
805
			$avant='';
806
			$apres='';
807
			$altern = "''";
808
			break;
809
810
		case 'polyglotte':
811
			$code = "";
812
			foreach($p->traductions as $k => $v) {
813
			  $code .= ",'" .
814
			    str_replace(array("\\","'"),array("\\\\","\\'"), $k) .
815
			    "' => '" .
816
			    str_replace(array("\\","'"),array("\\\\","\\'"), $v) .
817
			    "'";
818
			}
819
			$code = "choisir_traduction(array(" .
820
 			  substr($code,1) .
821
			  "))";
822
			$commentaire= '&';
823
			$avant='';
824
			$apres='';
825
			$altern = "''";
826
			break;
827
828
		// inclure
829
		case 'include':
830
			$p->descr = $descr;
831
			$code = calculer_inclure($p, $boucles, $id_boucle);
832
			if ($code === false) {
833
				$err_e_c = true;
834
				$code = "''";
835
			} else {
836
				$commentaire = '<INCLURE ' . addslashes(str_replace("\n", ' ', $code)) . '>';
837
				$avant='';
838
				$apres='';
839
				$altern = "''";
840
			}
841
			break;
842
843
		// boucle
844
		case TYPE_RECURSIF:
845
			$nom = $p->id_boucle;
846
			$newdescr = $descr;
847
			$newdescr['id_mere'] = $nom;
848
			$newdescr['niv']++;
849
			$avant = calculer_liste($p->avant,
850
				$newdescr, $boucles, $id_boucle);
851
			$apres = calculer_liste($p->apres,
852
				$newdescr, $boucles, $id_boucle);
853
			$newdescr['niv']--;
854
			$altern = calculer_liste($p->altern,
855
				$newdescr, $boucles, $id_boucle);
856
			if (($avant === false) OR ($apres === false) OR ($altern === false)) {
857
				$err_e_c = true;
858
				$code = "''";
859
			} else {
860
				$code = 'BOUCLE' .
861
				  str_replace("-","_", $nom) . $descr['nom'] .
862
				  '($Cache, $Pile, $doublons, $Numrows, $SP)';
863
				$commentaire= "?$nom";
864
				if (!$boucles[$nom]->milieu
865
				AND $boucles[$nom]->type_requete <> TYPE_RECURSIF) {
866
					if ($altern != "''") $code .= "\n. $altern";
867
					if ($avant<>"''" OR $apres<>"''")
868
					  spip_log("boucle $nom toujours vide, code superflu dans $id");
0 ignored issues
show
Bug introduced by
The variable $id does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
869
					$avant = $apres = $altern = "''";
870
				} else if ($altern != "''") $altern = "($altern)";
871
			}
872
			break;
873
874
		case 'idiome':
875
			$l = array();
876
			$code = '';
877
			foreach ($p->arg as $k => $v) {
878
			  	$_v = calculer_liste($v, $descr, $boucles, $id_boucle);
879
				if ($k) {
880
					$l[] = _q($k) . ' => ' . $_v;
881
				} else {
882
					$code = $_v;
883
				}
884
			}
885
			// Si le module n'est pas fourni, l'expliciter sauf si calculé
886
			if ($p->module) {
887
				$m = $p->module .':'.$p->nom_champ;
888
			} elseif ($p->nom_champ) {
889
				$m = MODULES_IDIOMES .':'.$p->nom_champ;
890
			} else {
891
				$m = '';
892
			}
893
			$code = (!$code ? "'$m'" :
894
						($m ? "'$m' . $code" :
895
							("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))")))
896
					. (!$l ? '' : (", array(" . implode(",\n", $l) . ")"));
897
			$code = "_T($code)";
898
			if ($p->param) {
899
				$p->id_boucle = $id_boucle;
900
				$p->boucles = &$boucles;
901
				$code = compose_filtres($p, $code);
902
			}
903
			$commentaire = ":";
904
			$avant='';
905
			$apres='';
906
			$altern = "''";
907
			break;
908
909
		case 'champ':
910
911
			// cette structure pourrait etre completee des le phrase' (a faire)
912
			$p->id_boucle = $id_boucle;
913
			$p->boucles = &$boucles;
914
			$p->descr = $descr;
915
			#$p->interdire_scripts = true;
916
			$p->type_requete = $type;
917
918
			$code = calculer_champ($p);
919
			$commentaire = '#' . $p->nom_champ . $p->etoile;
920
			$avant = calculer_liste($p->avant,
921
				$descr, $boucles, $id_boucle);
922
			$apres = calculer_liste($p->apres,
923
				$descr, $boucles, $id_boucle);
924
			$altern = "''";
925
			// Si la valeur est destinee a une comparaison a ''
926
			// forcer la conversion en une chaine par strval
927
			// si ca peut etre autre chose qu'une chaine
928
			if (($avant != "''" OR $apres != "''")
929
			AND $code[0]!= "'"
930
#			AND (strpos($code,'interdire_scripts') !== 0)
931
			AND !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code)
932
			AND !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code)
933
			AND !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) 
934
				$code = "strval($code)";
935
			break;
936
937
		default: 
938
		  // Erreur de construction de l'arbre de syntaxe abstraite
939
			$code = "''";
940
			$p->descr = $descr;
941
			$err_e_c = _T('zbug_erreur_compilation');
942
			erreur_squelette($err_e_c, $p);
943
		} // switch
944
945
		if ($code != "''") {
946
			$code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']);
0 ignored issues
show
Bug introduced by
The variable $avant 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...
Bug introduced by
The variable $apres 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...
Bug introduced by
The variable $altern 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...
947
			$codes[]= (($mode == 'validation') ?
948
				"array($code, '$commentaire', " . $p->ligne . ")"
0 ignored issues
show
Bug introduced by
The variable $commentaire 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...
949
				: (($mode == 'code') ?
950
				"\n// $commentaire\n$code" :
951
				$code));
952
		}
953
	} // foreach
954
955
	return $err_e_c ? false : $codes;
956
}
957
958
// production d'une expression conditionnelle ((v=EXP) ? (p . v .s) : a)
959
// mais si EXP est de la forme (t ? 'C' : '') on produit (t ? (p . C . s) : a)
960
// de meme si EXP est de la forme (t ? '' : 'C')
961
962
// http://doc.spip.org/@compile_retour
963
function compile_retour($code, $avant, $apres, $altern, $tab, $n)
964
{
965
	if ($avant == "''") $avant = '';
966
	if ($apres == "''") $apres = '';
967
	if (!$avant AND !$apres AND ($altern==="''")) return $code;
968
969
	if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) {
970
		$t = $code;
971
		$cond = '';
972
	} elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE,$code, $r)) {
973
		$t = $r[2];
974
		$cond =  '!' . $r[1];
975
	} else if  (preg_match(_REGEXP_COND_NONVIDE_VIDE,$code, $r)) {
976
		$t = $r[2];
977
		$cond = $r[1];
978
	} else {
979
		$t = '$t' . $n;
980
		$cond = "($t = $code)!==''";
981
	}
982
983
	$res = (!$avant ? "" : "$avant . ") . 
984
		$t .
985
		(!$apres ? "" : " . $apres");
986
987
	if ($res !== $t) $res = "($res)";
988
	return !$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)";
989
}
990
991
992
function compile_inclure_doublons($lexemes)
993
{
994
	foreach($lexemes as $v)
995
	  if($v->type === 'include' AND $v->param) 
996
	    foreach($v->param as $r) 
997
	      if (trim($r[0]) === 'doublons') 
998
		return true;
999
	return false;
1000
}
1001
1002
// Prend en argument le texte d'un squelette, le nom de son fichier d'origine,
1003
// sa grammaire et un nom. Retourne False en cas d'erreur,
1004
// sinon retourne un tableau de fonctions PHP compilees a evaluer,
1005
// notamment une fonction portant ce nom et calculant une page.
1006
// Pour appeler la fonction produite, lui fournir 2 tableaux de 1 e'le'ment:
1007
// - 1er: element 'cache' => nom (du fichier ou` mettre la page)
1008
// - 2e: element 0 contenant un environnement ('id_article => $id_article, etc)
1009
// Elle retournera alors un tableau de 5 e'le'ments:
1010
// - 'texte' => page HTML, application du squelette a` l'environnement;
1011
// - 'squelette' => le nom du squelette
1012
// - 'process_ins' => 'html' ou 'php' selon la pre'sence de PHP dynamique
1013
// - 'invalideurs' =>  de'pendances de cette page, pour invalider son cache.
1014
// - 'entetes' => tableau des entetes http
1015
// En cas d'erreur, elle retournera un tableau des 2 premiers elements seulement
1016
1017
// http://doc.spip.org/@public_compiler_dist
1018
function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect=''){
1019
	// Pre-traitement : reperer le charset du squelette, et le convertir
1020
	// Bonus : supprime le BOM
1021
	include_spip('inc/charsets');
1022
	$squelette = transcoder_page($squelette);
1023
1024
	// rendre inertes les echappements de #[](){}<>
1025
	$i = 0;
1026
	while(false !== strpos($squelette, $inerte = '-INERTE'.$i)) $i++;
1027
	$squelette = preg_replace_callback(',\\\\([#[()\]{}<>]),',
1028
		create_function('$a', "return '$inerte-'.ord(\$a[1]).'-';"), $squelette, -1, $esc);
1029
1030
	$descr = array('nom' => $nom,
1031
			'gram' => $gram,
1032
			'sourcefile' => $sourcefile,
1033
			'squelette' => $squelette);
1034
1035
	// Phraser le squelette, selon sa grammaire
1036
1037
	$boucles = array();
1038
	$f = charger_fonction('phraser_' . $gram, 'public');
1039
1040
	$squelette = $f($squelette, '', $boucles, $descr);
1041
	$boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect);
1042
1043
	// restituer les echappements
1044
	if ($esc)
0 ignored issues
show
Bug Best Practice introduced by
The expression $esc of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1045
		foreach($boucles as $i=>$boucle) {
0 ignored issues
show
Bug introduced by
The expression $boucles of type false|array<string,objec...,{"":"object<Boucle>"}> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1046
			$boucles[$i]->return = preg_replace_callback(",$inerte-(\d+)-,", create_function('$a', 'return chr($a[1]);'),
1047
				$boucle->return);
1048
			$boucles[$i]->descr['squelette'] = preg_replace_callback(",$inerte-(\d+)-,", create_function('$a', 'return "\\\\".chr($a[1]);'),
1049
				$boucle->descr['squelette']);
1050
		}
1051
	
1052
	$debug = ($boucles AND defined('_VAR_MODE') AND _VAR_MODE == 'debug');
1053
	if ($debug) {
1054
		include_spip('public/decompiler');
1055
		foreach($boucles as $id => $boucle) {
1056
			if ($id)
1057
			  $decomp = "\n/* BOUCLE " .
1058
			    $boucle->type_requete .
1059
			    " " .
1060
			    str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) .
1061
			    " */\n";
1062
			else $decomp = ("\n/*\n" . 
1063
				 str_replace('*/', '* /', public_decompiler($squelette, $gram)) 
1064
				 . "\n*/");
1065
			$boucles[$id]->return = $decomp .$boucle->return; 
1066
			$GLOBALS['debug_objets']['code'][$nom.$id] = $boucle->return;
1067
		}
1068
	}
1069
1070
	return $boucles;
1071
}
1072
1073
// Point d'entree pour arbre de syntaxe abstraite fourni en premier argument
1074
// Autres specifications comme ci-dessus
1075
1076
function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect=''){
1077
	static $trouver_table;
1078
	spip_timer('calcul_skel');
1079
1080
	if (defined('_VAR_MODE') AND _VAR_MODE == 'debug') {
1081
		$GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette'];
1082
		$GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile;
1083
1084
		if (!isset($GLOBALS['debug_objets']['principal']))
1085
			$GLOBALS['debug_objets']['principal'] = $nom;
1086
	}
1087
	foreach ($boucles as $id => $boucle) {
1088
		$GLOBALS['debug_objets']['boucle'][$nom.$id] = $boucle;
1089
	}
1090
	$descr['documents'] = compile_inclure_doublons($squelette);
1091
1092
	// Demander la description des tables une fois pour toutes
1093
	// et reperer si les doublons sont demandes
1094
	// pour un inclure ou une boucle document
1095
	// c'est utile a la fonction champs_traitements
1096
	if (!$trouver_table)
1097
		$trouver_table = charger_fonction('trouver_table', 'base');
1098
1099
	foreach($boucles as $id => $boucle) {
1100
		if (!($type = $boucle->type_requete)) continue;
1101
		if (!$descr['documents'] AND (
1102
			(($type == 'documents') AND $boucle->doublons) OR
1103
				compile_inclure_doublons($boucle->avant) OR
1104
				compile_inclure_doublons($boucle->apres) OR
1105
				compile_inclure_doublons($boucle->milieu) OR
1106
				compile_inclure_doublons($boucle->altern)))
1107
			$descr['documents'] = true;  
1108
		if ($type != TYPE_RECURSIF) {
1109
			if (!$boucles[$id]->sql_serveur AND $connect)
1110
				$boucles[$id]->sql_serveur = $connect;
1111
1112
			// chercher dans les iterateurs du repertoire iterateur/
1113
			if ($g = charger_fonction(
1114
			preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true)) {
1115
				$boucles[$id] = $g($boucle);
1116
1117
			// sinon, en cas de requeteur d'un type predefini,
1118
			// utiliser les informations donnees par le requeteur
1119
			// cas "php:xx" et "data:xx".
1120
			} else if ($boucle->sql_serveur AND $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) {
1121
				$requeteur($boucles, $boucle, $id);
1122
1123
			// utiliser la description des champs transmis
1124
			} else {
1125
				$show = $trouver_table($type, $boucles[$id]->sql_serveur);
1126
				// si la table n'existe pas avec le connecteur par defaut,
1127
				// c'est peut etre une table qui necessite son connecteur dedie fourni
1128
				// permet une ecriture allegee (GEO) -> (geo:GEO)
1129
				if (!$show
1130
				AND $show=$trouver_table($type, strtolower($type))) {
1131
					$boucles[$id]->sql_serveur = strtolower($type);
1132
				}
1133
				if ($show) {
1134
					$boucles[$id]->show = $show;
1135
					// recopie les infos les plus importantes
1136
					$boucles[$id]->primary = $show['key']["PRIMARY KEY"];
1137
					$boucles[$id]->id_table = $x = preg_replace(",^spip_,","",$show['id_table']);
1138
					$boucles[$id]->from[$x] = $nom_table = $show['table'];
0 ignored issues
show
Unused Code introduced by
$nom_table 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...
1139
					$boucles[$id]->iterateur = 'SQL';
1140
1141
					$boucles[$id]->descr = &$descr;
1142
					if ((!$boucles[$id]->jointures)
1143
					    AND is_array($show['tables_jointures'])
1144
					        AND count($x = $show['tables_jointures']))
1145
						$boucles[$id]->jointures = $x;
1146
					if ($boucles[$id]->jointures_explicites){
1147
						$jointures = preg_split("/\s+/",$boucles[$id]->jointures_explicites);
1148
						while ($j=array_pop($jointures))
1149
							array_unshift($boucles[$id]->jointures,$j);
1150
					}
1151
				} else {
1152
					// Pas une erreur si la table est optionnelle
1153
					if ($boucles[$id]->table_optionnelle)
1154
						$boucles[$id]->type_requete = '';
1155
					else  {
1156
						$boucles[$id]->type_requete = false;
1157
						$boucle = $boucles[$id];
1158
						$x = (!$boucle->sql_serveur ? '' :
1159
							($boucle->sql_serveur . ":")) .
1160
						     $type;
1161
						$msg = array('zbug_table_inconnue',
1162
						             array('table' => $x));
1163
						erreur_squelette($msg, $boucle);
1164
					}
1165
				}
1166
			}
1167
		}
1168
	}
1169
1170
	// Commencer par reperer les boucles appelees explicitement 
1171
	// car elles indexent les arguments de maniere derogatoire
1172
	foreach($boucles as $id => $boucle) {
1173
		if ($boucle->type_requete == TYPE_RECURSIF AND $boucle->param) {
1174
			$boucles[$id]->descr = &$descr;
1175
			$rec = &$boucles[$boucle->param[0]];
1176
			if (!$rec) {
1177
				$msg = array('zbug_boucle_recursive_undef',
1178
					array('nom' => $boucle->param[0]));
1179
				erreur_squelette($msg, $boucle);
1180
				$boucles[$id]->type_requete = false;
1181
			} else {
1182
				$rec->externe = $id;
1183
				$descr['id_mere'] = $id;
1184
				$boucles[$id]->return =
1185
						calculer_liste(array($rec),
1186
							 $descr,
1187
							 $boucles,
1188
							 $boucle->param);
1189
			}
1190
		}
1191
	}
1192
	foreach($boucles as $id => $boucle) { 
1193
		$id = strval($id); // attention au type dans index_pile
1194
		$type = $boucle->type_requete;
1195
		if ($type AND $type != TYPE_RECURSIF) {
1196
			$res = '';
1197
			if ($boucle->param) {
1198
				// retourne un tableau en cas d'erreur
1199
				$res = calculer_criteres($id, $boucles);
1200
			}
1201
			$descr['id_mere'] = $id;
1202
			$boucles[$id]->return =
1203
			  calculer_liste($boucle->milieu,
1204
					 $descr,
1205
					 $boucles,
1206
					 $id);
1207
			// Si les criteres se sont mal compiles
1208
			// ne pas tenter d'assembler le code final
1209
			// (mais compiler le corps pour detection d'erreurs)
1210
			if (is_array($res)) {
1211
				$boucles[$id]->type_requete = false;
1212
			}
1213
		}
1214
	}
1215
1216
	// idem pour la racine
1217
	$descr['id_mere'] = '';
1218
	$corps = calculer_liste($squelette, $descr, $boucles);
1219
1220
1221
1222
	// Calcul du corps de toutes les fonctions PHP,
1223
	// en particulier les requetes SQL et TOTAL_BOUCLE
1224
	// de'terminables seulement maintenant
1225
1226
	foreach($boucles as $id => $boucle) {
1227
		$boucle = $boucles[$id] = pipeline('pre_boucle', $boucle);
1228
		if ($boucle->return === false) {$corps = false; continue;}
1229
		// appeler la fonction de definition de la boucle
1230
1231
		if ($req = $boucle->type_requete) {
0 ignored issues
show
Unused Code introduced by
$req 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...
1232
			// boucle personnalisée ?
1233
			$table = strtoupper($boucle->type_requete);
1234
			$serveur = strtolower($boucle->sql_serveur);
1235
			if (
1236
				// fonction de boucle avec serveur & table
1237
				(!$serveur OR
1238
				 ((!function_exists($f = "boucle_".$serveur."_".$table))
1239
				  AND (!function_exists($f = $f."_dist"))
1240
				 )
1241
				)
1242
				// fonction de boucle avec table
1243
				AND (!function_exists($f = "boucle_".$table))
1244
					AND (!function_exists($f = $f."_dist"))
1245
			){
1246
				// fonction de boucle standard 
1247
				if (!function_exists($f = 'boucle_DEFAUT')) {
1248
					$f = 'boucle_DEFAUT_dist';
1249
				}
1250
			}
1251
1252
			$req = "\n\n\tstatic \$command = array();\n\t" .
1253
					"static \$connect;\n\t" .
1254
					"\$command['connect'] = \$connect = " .
1255
				_q($boucle->sql_serveur) .
1256
				";" .
1257
				$f($id, $boucles);
1258
		} else $req = ("\n\treturn '';");
1259
1260
		$boucles[$id]->return = 
1261
			"\n\nfunction BOUCLE" . strtr($id,"-","_") . $nom .
1262
			'(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' .
1263
			$req .
1264
			"\n}\n";
1265
	}
1266
1267
	// Au final, si le corps ou un critere au moins s'est mal compile
1268
	// retourner False, sinon inserer leur decompilation
1269
	if (is_bool($corps)) return false;
1270
1271
	$principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons=array(), $Numrows=array(), $SP=0) {
1272
'
1273
	// reporter de maniere securisee les doublons inclus
1274
.'
1275
	if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"]))
1276
		$doublons = nettoyer_env_doublons($Pile[0]["doublons"]);
1277
1278
	$connect = ' .
1279
	_q($connect) . ';
1280
	$page = ' .
1281
	// ATTENTION, le calcul de l'expression $corps affectera $Cache
1282
	// c'est pourquoi on l'affecte a la variable auxiliaire $page. 
1283
	// avant de referencer $Cache
1284
	$corps . ";
1285
1286
	return analyse_resultat_skel(".var_export($nom,true)
1287
		.", \$Cache, \$page, ".var_export($sourcefile,true).");
1288
}";
1289
1290
	$secondes = spip_timer('calcul_skel');
1291
	spip_log("COMPIL ($secondes) [$sourcefile] $nom.php");
1292
	// $connect n'est pas sûr : on nettoie
1293
	$connect = preg_replace(',[^\w],', '', $connect);
1294
1295
	// Assimiler la fct principale a une boucle anonyme, pour retourner un resultat simple
1296
	$code = new Boucle;
1297
	$code->descr = $descr;
1298
	$code->return = '
1299
//
1300
// Fonction principale du squelette ' . 
1301
	$sourcefile . 
1302
	($connect ? " pour $connect" : '') . 
1303
	(!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") .
1304
	"\n//\n" .
1305
	$principal;
1306
1307
	$boucles[''] = $code;
1308
	return $boucles;
1309
}
1310
1311
1312
/**
1313
 * Requeteur pour les boucles (php:nom_iterateur)
1314
 * 
1315
 * Analyse si le nom d'iterateur correspond bien a une classe PHP existante
1316
 * et dans ce cas charge la boucle avec cet iterateur.
1317
 * Affichera une erreur dans le cas contraire.
1318
 *
1319
 * @param $boucles Liste des boucles
1320
 * @param $boucle  La boucle parcourue
1321
 * @param $id      L'identifiant de la boucle parcourue
1322
 * 
1323
**/
1324
function requeteur_php_dist(&$boucles, &$boucle, &$id) {
1325
	if (class_exists($boucle->type_requete)) {
1326
		$g = charger_fonction('php', 'iterateur');
1327
		$boucles[$id] = $g($boucle, $boucle->type_requete);
1328 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...
1329
		$x = $boucle->type_requete;
1330
		$boucle->type_requete = false;
1331
		$msg = array('zbug_iterateur_inconnu',
1332
				array('iterateur' => $x));
1333
		erreur_squelette($msg, $boucle);
1334
	}
1335
}
1336
1337
1338
/**
1339
 * Requeteur pour les boucles (data:type de donnee)
1340
 * note: (DATA) tout court ne passe pas par ici.
1341
 * 
1342
 * Analyse si le type de donnee peut etre traite
1343
 * et dans ce cas charge la boucle avec cet iterateur.
1344
 * Affichera une erreur dans le cas contraire.
1345
 *
1346
 * @param $boucles Liste des boucles
1347
 * @param $boucle  La boucle parcourue
1348
 * @param $id      L'identifiant de la boucle parcourue
1349
 * 
1350
**/
1351
function requeteur_data_dist(&$boucles, &$boucle, &$id) {
1352
	include_spip('iterateur/data');
1353
	if ($h = charger_fonction($boucle->type_requete . '_to_array' , 'inc', true)) {
0 ignored issues
show
Unused Code introduced by
$h 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...
1354
		$g = charger_fonction('data', 'iterateur');
1355
		$boucles[$id] = $g($boucle);
1356
		// from[0] stocke le type de data (rss, yql, ...)
1357
		$boucles[$id]->from[] = $boucle->type_requete;
1358
		
1359 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...
1360
		$x = $boucle->type_requete;
1361
		$boucle->type_requete = false;
1362
		$msg = array('zbug_requeteur_inconnu',
1363
				array(
1364
				'requeteur' => 'data',
1365
				'type' => $x
1366
		));
1367
		erreur_squelette($msg, $boucle);
1368
	}
1369
}
1370
1371
?>
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...
1372