Completed
Push — master ( 518dfb...07a5e0 )
by cam
04:05
created

debusquer.php ➔ debusquer_contexte()   C

Complexity

Conditions 12
Paths 14

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
nc 14
nop 1
dl 0
loc 39
rs 6.9666
c 0
b 0
f 0

How to fix   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-2019                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
if (!defined('_ECRIRE_INC_VERSION')) {
14
	return;
15
}
16
17
include_spip('public/decompiler');
18
include_spip('inc/filtres_mini');
19
20
// Le debusqueur repose sur la globale debug_objets,
21
// affectee par le compilateur et le code produit par celui-ci.
22
// Cette globale est un tableau avec comme index:
23
// 'boucle' : tableau des arbres de syntaxe abstraite des boucles
24
// 'contexte' : tableau des contextes des squelettes assembles
25
// 'principal' : nom du squelette principal
26
// 'profile' : tableau des temps de calcul des squelettes
27
// 'resultat' : tableau des resultats envoyes (tableau de tableaux pour les boucles)
28
// 'sequence' : tableau de sous-tableaux resultat/source/numero-de-ligne
29
// 'sourcefile' : tableau des noms des squelettes inclus
30
// 'squelette' : tableau des sources de squelettes
31
// 'validation' : resultat final a passer a l'analyseur XML au besoin
32
33
/**
34
 * Definir le nombre maximal d'erreur possible dans les squelettes
35
 * au dela, l'affichage est arrete et les erreurs sont affichees.
36
 * Definir a zero permet de ne jamais bloquer,
37
 * mais il faut etre tres prudent avec cette utilisation
38
 *
39
 * Sert pour les tests unitaires
40
 */
41
defined('_DEBUG_MAX_SQUELETTE_ERREURS') || define('_DEBUG_MAX_SQUELETTE_ERREURS', 9);
42
43
44
/**
45
 * Point d'entrée pour les erreurs de compilation
46
 *
47
 * Point d'entrée pour les appels involontaires ($message non vide => erreur)
48
 *  et volontaires (var_mode et var_profile)
49
 *
50
 * Si pas d'autorisation, les erreurs ne sont pas affichées
51
 * (mais seront dans les logs)
52
 *
53
 * Si l'erreur vient de SPIP,  en parler sur `[email protected]`
54
 *
55
 * @param bool|string|array $message
56
 *     - Message d'erreur (string|array)
57
 *     - false pour retourner le texte des messages d'erreurs
58
 *     - vide pour afficher les messages d'erreurs
59
 * @param string|Contexte $lieu
60
 *     Contexte : lieu d'origine de l'erreur
61
 * @param array $opt
62
 *     Options pour debug ou tests unitaires
63
 *     - 'erreurs' = 'get' : Retourne le tableau des erreurs
64
 *     - 'erreurs' = 'reset' : Efface le tableau des erreurs
65
 * @return null|string
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean|null|string? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

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

Loading history...
66
 *     - string si $message à false.
67
 **/
68
function public_debusquer_dist($message = '', $lieu = '', $opt = array()) {
69
	static $tableau_des_erreurs = array();
70
71
	// Pour des tests unitaires, pouvoir récupérer les erreurs générées
72
	if (isset($opt['erreurs'])) {
73
		if ($opt['erreurs'] == 'get') {
74
			return $tableau_des_erreurs;
75
		}
76
		if ($opt['erreurs'] == 'reset') {
77
			$tableau_des_erreurs = array();
78
79
			return true;
80
		}
81
	}
82
83
	// Erreur ou appel final ?
84
	if ($message) {
85
		$message = debusquer_compose_message($message);
86
		$tableau_des_erreurs[] = array($message, $lieu);
87
		set_request('var_mode', 'debug');
88
		$GLOBALS['bouton_admin_debug'] = true;
89
		// Permettre a la compil de continuer
90
		if (is_object($lieu) and (!isset($lieu->code) or !$lieu->code)) {
91
			$lieu->code = "''";
92
		}
93
		// forcer l'appel au debusqueur en cas de boucles infernales
94
		$urgence = (_DEBUG_MAX_SQUELETTE_ERREURS and count($tableau_des_erreurs) > _DEBUG_MAX_SQUELETTE_ERREURS);
95
		if (!$urgence) {
96
			return;
97
		}
98
	}
99
	if (empty($GLOBALS['debug_objets']['principal'])) {
100
		// espace public ?
101
		if (isset($GLOBALS['fond'])) {
102
			$GLOBALS['debug_objets']['principal'] = $GLOBALS['fond'];
103
		}
104
	}
105
106
	include_spip('inc/autoriser');
107
	if (!autoriser('debug')) {
108
		return;
109
	}
110
	include_spip('inc/headers');
111
	include_spip('inc/filtres');
112
113
	// en cas de squelette inclus,  virer le code de l'incluant:
114
	// - il contient souvent une Div restreignant la largeur a 3 fois rien
115
	// - ca fait 2 headers !
116
	// sauf si l'on se trouve deja dans un flux compresse (plugin compresseur
117
	// actif par exemple)
118
	if (ob_get_length()
119
		and
120
		!in_array('ob_gzhandler', ob_get_status())
121
	) {
122
		ob_end_clean();
123
	}
124
125
	lang_select($GLOBALS['visiteur_session']['lang']);
126
	$fonc = _request('var_mode_objet');
127
	$mode = _request('var_mode_affiche');
128
	$self = str_replace("\\'", '&#39;', self());
129
	$self = parametre_url($self, 'var_mode', 'debug');
130
131
	$res = debusquer_bandeau($tableau_des_erreurs)
132
		. '<br />'
133
		. debusquer_squelette($fonc, $mode, $self);
134
135
	if (!_DIR_RESTREINT or headers_sent()) {
136
		return $res;
137
	}
138
	if ($tableau_des_erreurs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tableau_des_erreurs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
139
		http_status(503);
140
	}
141
142
	http_no_cache();
143
	if (isset($_GET['var_profile'])) {
144
		$titre = parametre_url($GLOBALS['REQUEST_URI'], 'var_profile', '');
145
		$titre = parametre_url($titre, 'var_mode', '');
146
	} else {
147
		if (!$fonc) {
148
			$fonc = $GLOBALS['debug_objets']['principal'];
149
		}
150
		$titre = !$mode ? $fonc : ($mode . (isset($GLOBALS['debug_objets']['sourcefile'][$fonc]) ? " " . $GLOBALS['debug_objets']['sourcefile'][$fonc] : ""));
151
	}
152
	if ($message === false) {
153
		lang_select();
154
155
		return debusquer_entete($titre, $res);
156
	} else {
157
		echo debusquer_entete($titre, $res);
158
	}
159
	exit;
160
}
161
162
function debusquer_compose_message($msg) {
163
	if (is_array($msg)) {
164
		// si c'est un texte, c'est une traduction a faire, mais
165
		// sqlite renvoit aussi des erreurs alpha num (mais avec 3 arguments)
166
		if (!is_numeric($msg[0]) and count($msg) == 2) {
167
			// message avec argument: instancier
168
			$msg = _T($msg[0], $msg[1], 'spip-debug-arg');
169
		} else {
170
			// message SQL: interpreter
171
			$msg = debusquer_requete($msg);
172
		}
173
	}
174
	// FIXME: le fond n'est pas la si on n'est pas dans un squelette
175
	// cela dit, ca serait bien d'indiquer tout de meme d'ou vient l'erreur
176
	$fond = isset($GLOBALS['fond']) ? $GLOBALS['fond'] : "";
177
	// une erreur critique sort $message en array
178
	$debug = is_array($msg) ? $msg[1] : $msg;
179
	spip_log("Debug: " . $debug . " (" . $fond . ")");
180
181
	return $msg;
182
}
183
184
function debusquer_bandeau($erreurs) {
185
186
	if (!empty($erreurs)) {
187
		$n = array(count($erreurs) . ' ' . _T('zbug_erreur_squelette'));
188
189
		return debusquer_navigation($erreurs, $n);
190
	} elseif (!empty($GLOBALS['tableau_des_temps'])) {
191
		include_spip('public/tracer');
192
		list($temps, $nav) = chrono_requete($GLOBALS['tableau_des_temps']);
193
194
		return debusquer_navigation($temps, $nav, 'debug-profile');
195
	} else {
196
		return '';
197
	}
198
}
199
200
/**
201
 * Affiche proprement dans un tableau le contexte d'environnement
202
 *
203
 * @param array|string $env
204
 * @return string Code HTML
205
 **/
206
function debusquer_contexte($env) {
207
208
	if (is_array($env_tab = @unserialize($env))) {
209
		$env = $env_tab;
210
	}
211
212
	if (!$env) {
213
		return '';
214
	}
215
	$res = "";
216
	foreach ($env as $nom => $valeur) {
0 ignored issues
show
Bug introduced by
The expression $env of type array|string 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...
217
		if (is_array($valeur)) {
218
			$valeur_simple = array();
219
			foreach ($valeur as $v) {
220
				if (is_array($v)) {
221
					$valeur_simple[] = 'array:' . count($v);
222
				} elseif (is_object($v)) {
223
					$valeur_simple[] = get_class($v);
224
				} elseif (is_string($v)) {
225
					$valeur_simple[] = "'" . $v . "'";
226
				} else {
227
					$valeur_simple[] = $v;
228
				}
229
			}
230
			$n = count($valeur);
231
			$valeur = (($n > 3) ? 'array:' . $n . ' ' : '');
232
			$valeur .= '[' . join(', ', $valeur_simple) . ']';
233
		} elseif (is_object($valeur)) {
234
			$valeur = get_class($valeur);
235
		} elseif (is_string($valeur)) {
236
			$valeur = "'" . $valeur . "'";
237
		}
238
		$res .= "\n<tr><td><strong>" . nl2br(entites_html($nom))
239
			. "</strong></td><td>:&nbsp;" . nl2br(entites_html($valeur))
240
			. "</td></tr>\n";
241
	}
242
243
	return "<div class='spip-env'><fieldset><legend>#ENV</legend>\n<div><table>$res</table></div></fieldset></div>\n";
244
}
245
246
// Affichage du tableau des erreurs ou des temps de calcul
247
// Cliquer sur les numeros en premiere colonne permet de voir le code
248
249
function debusquer_navigation($tableau, $caption = array(), $id = 'debug-nav') {
250
251
	if (_request('exec') == 'valider_xml') {
252
		return '';
253
	}
254
	$GLOBALS['bouton_admin_debug'] = true;
255
	$res = '';
256
	$href = quote_amp(parametre_url($GLOBALS['REQUEST_URI'], 'var_mode', 'debug'));
0 ignored issues
show
Bug introduced by
It seems like parametre_url($GLOBALS['...], 'var_mode', 'debug') targeting parametre_url() can also be of type array<integer,string> or null; however, quote_amp() does only seem to accept string, maybe add an additional type check?

This check looks at variables that 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...
257
	foreach ($tableau as $i => $err) {
258
		$boucle = $ligne = $skel = '';
259
		list($msg, $lieu) = $err;
260
		if (is_object($lieu)) {
261
			$ligne = $lieu->ligne;
262
			$boucle = $lieu->id_boucle ? $lieu->id_boucle : '';
263
			if (isset($lieu->descr['nom'])) {
264
				$nom_code = $lieu->descr['nom'];
265
				$skel = $lieu->descr['sourcefile'];
266
				$h2 = parametre_url($href, 'var_mode_objet', $nom_code);
267
				$h3 = parametre_url($h2, 'var_mode_affiche', 'squelette') . '#L' . $ligne;
268
				$skel = "<a href='$h3'><b>$skel</b></a>";
269
				if ($boucle) {
270
					$h3 = parametre_url($h2 . $boucle, 'var_mode_affiche', 'boucle');
271
					$boucle = "<a href='$h3'><b>$boucle</b></a>";
272
				}
273
			}
274
		}
275
276
		$j = ($i + 1);
277
		$res .= "<tr id='req$j'><td style='text-align: right'>"
278
			. $j
279
			. "&nbsp;</td><td style='text-align: left'>"
280
			. (is_array($msg) ? implode('', $msg) : $msg)
281
			. "</td><td style='text-align: left'>"
282
			. ($skel ? $skel : "&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;")
283
			. "</td><td class='spip-debug-arg' style='text-align: left'>"
284
			. ($boucle ? $boucle : "&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;")
285
			. "</td><td style='text-align: right'>"
286
			. $ligne
287
			. "</td></tr>\n";
288
289
	}
290
291
	return "\n<table id='$id'>"
292
	. "<caption onclick=\"x = document.getElementById('$id'); (x.style.display == '' ? x.style.display = 'none' : x.style.display = '');\">"
293
	. $caption[0]
294
## aide locale courte a ecrire, avec lien vers une grosse page de documentation
295
#		aider('erreur_compilation'),
296
	. "</caption>"
297
	//  fausse caption du chrono (mais vraie nav)
298
	. (!empty($caption[1]) ? $caption[1] : '')
299
	. "<tr><th>"
300
	. _T('numero')
301
	. "</th><th>"
302
	. _T('public:message')
303
	. "</th><th>"
304
	. _T('squelette')
305
	. "</th><th>"
306
	. _T('zbug_boucle')
307
	. "</th><th>"
308
	. _T('ligne')
309
	. "</th></tr>"
310
	. $res
311
	. "</table>";
312
}
313
314
315
/**
316
 * Retourne le texte d'un message d'erreur de requête
317
 *
318
 * Si une boucle cree des soucis, on peut afficher la requete fautive
319
 * avec son code d'erreur
320
 *
321
 * @param array $message
322
 *    Description du message en 3 éléments :
323
 *    - numéro d'erreur
324
 *    - texte de l'erreur
325
 *    - requête en erreur
326
 * @return string|array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[]|string.

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

Loading history...
327
 *    Retourne le texte de l'erreur a afficher
328
 *    ou un tableau si l'erreur est critique
329
 **/
330
function debusquer_requete($message) {
331
	list($errno, $msg, $query) = $message;
332
333
	// FIXME: ces écritures mélangent divers syntaxe des moteurs SQL
334
	// il serait plus prudent certainement d'avoir une fonction d'analyse par moteur
335
	if (preg_match(',err(no|code):?[[:space:]]*([0-9]+),i', $msg, $regs)) {
336
		$errno = $regs[2];
337
	} elseif (is_numeric($errno) and ($errno == 1030 or $errno <= 1026)
338
		and preg_match(',[^[:alnum:]]([0-9]+)[^[:alnum:]],', $msg, $regs)
339
	) {
340
		$errno = $regs[1];
341
	}
342
343
	// Erreur systeme
344
	if (is_numeric($errno) and $errno > 0 and $errno < 200) {
345
		$retour = "<tt><br /><br /><blink>"
346
			. _T('info_erreur_systeme', array('errsys' => $errno))
347
			. "</blink><br />\n<b>"
348
			. _T('info_erreur_systeme2',
349
				array('script' => generer_url_ecrire('base_repair')))
350
			. '</b><br />';
351
		spip_log("Erreur systeme $errno");
352
353
		return array($retour, '');
354
	}
355
356
	// Requete erronee
357
	$err = "<b>" . _T('avis_erreur_mysql') . " $errno</b><br /><tt>\n"
358
		. spip_htmlspecialchars($msg)
359
		. "\n<br /><span style='color: red'><b>"
360
		. spip_htmlspecialchars($query)
361
		. "</b></span></tt><br />";
362
363
	//. aider('erreur_mysql');
364
365
	return $err;
366
}
367
368
369
// http://code.spip.net/@trouve_boucle_debug
370
function trouve_boucle_debug($n, $nom, $debut = 0, $boucle = "") {
371
372
	$id = $nom . $boucle;
373
	if (is_array($GLOBALS['debug_objets']['sequence'][$id])) {
374
		foreach ($GLOBALS['debug_objets']['sequence'][$id] as $v) {
375
376
			if (!preg_match('/^(.*)(<\?.*\?>)(.*)$/s', $v[0], $r)) {
377
				$y = substr_count($v[0], "\n");
378
			} else {
379
				if ($v[1][0] == '#') // balise dynamique
380
				{
381
					$incl = $GLOBALS['debug_objets']['resultat'][$v[2]];
382
				} else // inclusion
383
				{
384
					$incl = $GLOBALS['debug_objets']['squelette'][trouve_squelette_inclus($v[0])];
385
				}
386
				$y = substr_count($incl, "\n")
387
					+ substr_count($r[1], "\n")
388
					+ substr_count($r[3], "\n");
389
			}
390
			if ($n <= ($y + $debut)) {
391
				if ($v[1][0] == '?') {
392
					return trouve_boucle_debug($n, $nom, $debut, substr($v[1], 1));
393
				} elseif ($v[1][0] == '!') {
394
					if ($incl = trouve_squelette_inclus($v[1])) {
395
						return trouve_boucle_debug($n, $incl, $debut);
396
					}
397
				}
398
399
				return array($nom, $boucle, $v[2] - 1 + $n - $debut);
400
			}
401
			$debut += $y;
402
		}
403
	}
404
405
	return array($nom, $boucle, $n - $debut);
406
}
407
408
// http://code.spip.net/@trouve_squelette_inclus
409
function trouve_squelette_inclus($script) {
410
411
	preg_match('/include\(.(.*).php3?.\);/', $script, $reg);
412
	// si le script X.php n'est pas ecrire/public.php
413
	// on suppose qu'il prend le squelette X.html (pas sur, mais y a pas mieux)
414
	if ($reg[1] == 'ecrire/public') // si c'est bien ecrire/public on cherche le param 'fond'
415
	{
416
		if (!preg_match("/'fond' => '([^']*)'/", $script, $reg)) // a defaut on cherche le param 'page'
417
		{
418
			if (!preg_match("/'param' => '([^']*)'/", $script, $reg)) {
419
				$reg[1] = "inconnu";
420
			}
421
		}
422
	}
423
	$incl = ',' . $reg[1] . '[.]\w$,';
424
425
	foreach ($GLOBALS['debug_objets']['sourcefile'] as $k => $v) {
426
		if (preg_match($incl, $v)) {
427
			return $k;
428
		}
429
	}
430
431
	return "";
432
}
433
434
// http://code.spip.net/@reference_boucle_debug
435
function reference_boucle_debug($n, $nom, $self) {
436
	list($skel, $boucle, $ligne) = trouve_boucle_debug($n, $nom);
437
438
	if (!$boucle) {
439
		return !$ligne ? "" :
440
			(" (" .
441
				(($nom != $skel) ? _T('squelette_inclus_ligne') :
442
					_T('squelette_ligne')) .
443
				" <a href='$self&amp;var_mode_objet=$skel&amp;var_mode_affiche=squelette&amp;var_mode_ligne=$ligne#L$ligne'>$ligne</a>)");
444
	} else {
445
		$self .= "&amp;var_mode_objet=$skel$boucle&amp;var_mode_affiche=boucle";
446
447
		return !$ligne ? " (boucle\n<a href='$self#$skel$boucle'>$boucle</a>)" :
448
			" (boucle $boucle ligne\n<a href='$self&amp;var_mode_ligne=$ligne#L$ligne'>$ligne</a>)";
449
	}
450
}
451
452
// affiche un texte avec numero de ligne et ancre.
453
454
// http://code.spip.net/@ancre_texte
455
function ancre_texte($texte, $fautifs = array(), $nocpt = false) {
456
457
	$var_mode_ligne = _request('var_mode_ligne');
458
	if ($var_mode_ligne) {
459
		$fautifs[] = array($var_mode_ligne);
460
	}
461
	$res = '';
462
463
	$s = highlight_string($texte, true);
464
	if (substr($s, 0, 6) == '<code>') {
465
		$s = substr($s, 6);
466
		$res = '<code>';
467
	}
468
469
	$s = preg_replace(',<(\w[^<>]*)>([^<]*)<br />([^<]*)</\1>,',
470
		'<\1>\2</\1><br />' . "\n" . '<\1>\3</\1>',
471
		$s);
472
473
474
	$tableau = explode("<br />", $s);
475
476
	$format = "<span style='float:left;display:block;width:50px;height:1px'><a id='L%d' style='background-color: white; visibility: " . ($nocpt ? 'hidden' : 'visible') . ";%s' href='#T%s' title=\"%s\">%0" . strval(@strlen(count($tableau))) . "d</a></span> %s<br />\n";
477
478
	$format10 = str_replace('white', 'lightgrey', $format);
479
	$formaterr = "color: red;";
480
	$i = 1;
481
	$flignes = array();
482
	$loc = array(0, 0);
483
	foreach ($fautifs as $lc) {
484
		if (is_array($lc)) {
485
			$l = array_shift($lc);
486
			$flignes[$l] = $lc;
487
		} else {
488
			$flignes[$lc] = $loc;
489
		}
490
	}
491
492
	$ancre = md5($texte);
493
	foreach ($tableau as $ligne) {
494
		if (isset($flignes[$i])) {
495
			$ligne = str_replace('&nbsp;', ' ', $ligne);
496
			$indexmesg = $flignes[$i][1];
497
			$err = textebrut($flignes[$i][2]);
498
			// tentative de pointer sur la colonne fautive;
499
			// marche pas car highlight_string rajoute des entites. A revoir.
500
			// $m = $flignes[$i][0];
501
			// $ligne = substr($ligne, 0, $m-1) .
502
			// sprintf($formaterr, substr($ligne,$m));
503
			$bg = $formaterr;
504
		} else {
505
			$indexmesg = $ancre;
506
			$err = $bg = '';
507
		}
508
		$res .= sprintf((($i % 10) ? $format : $format10), $i, $bg, $indexmesg, $err, $i, $ligne);
509
		$i++;
510
	}
511
512
	return "<div id='T$ancre'>"
513
	. '<div onclick="'
514
	. "jQuery(this).parent().find('a').toggle();"
515
	. '" title="'
516
	. _T('masquer_colonne')
517
	. '" style="cursor: pointer;">'
518
	. ($nocpt ? '' : _T('info_numero_abbreviation'))
519
	. "</div>
520
	" . $res . "</div>\n";
521
}
522
523
// l'environnement graphique du debuggueur 
524
525
function debusquer_squelette($fonc, $mode, $self) {
526
	$texte = '';
527
528
	if ($mode !== 'validation') {
529
		if (isset($GLOBALS['debug_objets']['sourcefile']) and $GLOBALS['debug_objets']['sourcefile']) {
530
			$res = "<div id='spip-boucles'>\n"
531
				. debusquer_navigation_squelettes($self)
532
				. "</div>";
533
		} else {
534
			$res = '';
535
		}
536
		if ($fonc) {
537
			$id = " id='$fonc'";
538
			if (!empty($GLOBALS['debug_objets'][$mode][$fonc])) {
539
				list($legend, $texte, $res2) = debusquer_source($fonc, $mode);
540
				$texte .= $res2;
541
			} elseif (!empty($GLOBALS['debug_objets'][$mode][$fonc . 'tout'])) {
542
				$legend = _T('zbug_' . $mode);
543
				$texte = $GLOBALS['debug_objets'][$mode][$fonc . 'tout'];
544
				$texte = ancre_texte($texte, array('', ''));
545
			}
546
		} else {
547
			if (strlen(trim($res))) {
548
				return "<img src='" . chemin_image('compat-16.png') . "' alt='afficher-masquer le debug' id='spip-debug-toggle' onclick=\"var x = document.getElementById('spip-debug'); (x.style.display == '' ? x.style.display = 'none' : x.style.display = '');\" /><div id='spip-debug'>$res</div>";
549
			} else {
550
				// cas de l'appel sur erreur: montre la page
551
				return isset($GLOBALS['debug_objets']['resultat']['tout'])
552
					? $GLOBALS['debug_objets']['resultat']['tout']
553
					: '';
554
			}
555
		}
556
	} else {
557
		$valider = charger_fonction('valider', 'xml');
558
		$val = $valider($GLOBALS['debug_objets']['validation'][$fonc . 'tout']);
559
		// Si erreur, signaler leur nombre dans le formulaire admin
560
		$GLOBALS['debug_objets']['validation'] = $val->err ? count($val->err) : '';
561
		list($texte, $err) = emboite_texte($val, $fonc, $self);
562
		if ($err === false) {
563
			$err = _T('impossible');
564
		} elseif ($err === true) {
565
			$err = _T('correcte');
566
		} else {
567
			$err = ": $err";
568
		}
569
		$legend = _T('validation') . ' ' . $err;
570
		$res = $id = '';
571
	}
572
573
	return !trim($texte) ? '' : (
574
		"<img src='" . chemin_image('compat-16.png') . "' alt='afficher-masquer le debug' id='spip-debug-toggle' onclick=\"var x = document.getElementById('spip-debug'); (x.style.display == '' ? x.style.display = 'none' : x.style.display = '');\" /><div id='spip-debug'>$res"
575
		. "<div id='debug_boucle'><fieldset$id><legend>"
576
		. "<a href='" . $self . "#f_" . substr($fonc, 0, 37) . "'> &#8593; "
577
		. ($legend ? $legend : $mode)
0 ignored issues
show
Bug introduced by
The variable $legend 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...
578
		. "</a></legend>"
579
		. $texte
580
		. "</fieldset></div>"
581
		. "</div>");
582
}
583
584
585
// http://code.spip.net/@emboite_texte
586
function emboite_texte($res, $fonc = '', $self = '') {
587
	$errs = $res->err;
588
	$texte = $res->entete . ($errs ? '' : $res->page);
589
590 View Code Duplication
	if (!$texte and !$errs) {
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...
591
		return array(ancre_texte('', array('', '')), false);
592
	}
593 View Code Duplication
	if (!$errs) {
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...
594
		return array(ancre_texte($texte, array('', '')), true);
595
	}
596
597
	if (!isset($GLOBALS['debug_objets'])) {
598
599
		$colors = array('#e0e0f0', '#f8f8ff');
600
		$encore = count_occ($errs);
601
		$encore2 = array();
602
		$fautifs = array();
603
604
		$err = '<tr><th>'
605
			. _T('numero')
606
			. "</th><th>"
607
			. _T('occurence')
608
			. "</th><th>"
609
			. _T('ligne')
610
			. "</th><th>"
611
			. _T('colonne')
612
			. "</th><th>"
613
			. _T('erreur')
614
			. "</th></tr>";
615
616
		$i = 0;
617
		$style = "style='text-align: right; padding-right: 5px'";
618
		foreach ($errs as $r) {
619
			$i++;
620
			list($msg, $ligne, $col) = $r;
621
			#spip_log("$r = list($msg, $ligne, $col");
622
			if (isset($encore2[$msg])) {
623
				$ref = ++$encore2[$msg];
624
			} else {
625
				$encore2[$msg] = $ref = 1;
626
			}
627
			$err .= "<tr  style='background-color: "
628
				. $colors[$i % 2]
629
				. "'><td $style><a href='#debut_err'>"
630
				. $i
631
				. "</a></td><td $style>"
632
				. "$ref/$encore[$msg]</td>"
633
				. "<td $style><a href='#L"
634
				. $ligne
635
				. "' id='T$i'>"
636
				. $ligne
637
				. "</a></td><td $style>"
638
				. $col
639
				. "</td><td>$msg</td></tr>\n";
640
			$fautifs[] = array($ligne, $col, $i, $msg);
641
		}
642
		$err = "<h2 style='text-align: center'>"
643
			. $i
644
			. "<a href='#fin_err'>"
645
			. " " . _T('erreur_texte')
646
			. "</a></h2><table id='debut_err' style='width: 100%'>"
647
			. $err
648
			. " </table><a id='fin_err'></a>";
649
650
		return array(ancre_texte($texte, $fautifs), $err);
651
	} else {
652
		list($msg, $fermant, $ouvrant) = $errs[0];
653
		$rf = reference_boucle_debug($fermant, $fonc, $self);
654
		$ro = reference_boucle_debug($ouvrant, $fonc, $self);
655
		$err = $msg .
656
			"<a href='#L" . $fermant . "'>$fermant</a>$rf<br />" .
657
			"<a href='#L" . $ouvrant . "'>$ouvrant</a>$ro";
658
659
		return array(ancre_texte($texte, array(array($ouvrant), array($fermant))), $err);
660
	}
661
}
662
663
// http://code.spip.net/@count_occ
664
function count_occ($regs) {
665
	$encore = array();
666
	foreach ($regs as $r) {
667
		if (isset($encore[$r[0]])) {
668
			$encore[$r[0]]++;
669
		} else {
670
			$encore[$r[0]] = 1;
671
		}
672
	}
673
674
	return $encore;
675
}
676
677
function debusquer_navigation_squelettes($self) {
678
679
	$res = '';
680
	$boucles = !empty($GLOBALS['debug_objets']['boucle']) ? $GLOBALS['debug_objets']['boucle'] : '';
681
	$contexte = $GLOBALS['debug_objets']['contexte'];
682
	$t_skel = _T('squelette');
683
	foreach ($GLOBALS['debug_objets']['sourcefile'] as $nom => $sourcefile) {
684
		$self2 = parametre_url($self, 'var_mode_objet', $nom);
685
		$nav = !$boucles ? '' : debusquer_navigation_boucles($boucles, $nom, $self, $sourcefile);
686
		$temps = !isset($GLOBALS['debug_objets']['profile'][$sourcefile]) ? '' : _T('zbug_profile',
687
			array('time' => $GLOBALS['debug_objets']['profile'][$sourcefile]));
688
689
		$res .= "<fieldset id='f_" . $nom . "'><legend>"
690
			. $t_skel
691
			. ' '
692
			. $sourcefile
693
			. "&nbsp;:\n<a href='$self2&amp;var_mode_affiche=squelette#f_$nom'>"
694
			. $t_skel
695
			. "</a>\n<a href='$self2&amp;var_mode_affiche=resultat#f_$nom'>"
696
			. _T('zbug_resultat')
697
			. "</a>\n<a href='$self2&amp;var_mode_affiche=code#f_$nom'>"
698
			. _T('zbug_code')
699
			. "</a>\n<a href='"
700
			. str_replace('var_mode=debug', 'var_profile=1&amp;var_mode=recalcul', $self)
701
			. "'>"
702
			. _T('zbug_calcul')
703
			. "</a></legend>"
704
			. (!$temps ? '' : ("\n<span style='display:block;float:" . $GLOBALS['spip_lang_right'] . "'>$temps</span><br />"))
705
			. debusquer_contexte($contexte[$sourcefile])
706
		. (!$nav ? '' : ("<table width='100%'>\n$nav</table>\n"))
707
		. "</fieldset>\n";
708
	}
709
710
	return $res;
711
}
712
713
function debusquer_navigation_boucles($boucles, $nom_skel, $self, $nom_source) {
714
	$i = 0;
715
	$res = '';
716
	$var_mode_objet = _request('var_mode_objet');
717
	$gram = preg_match('/[.](\w+)$/', $nom_source, $r) ? $r[1] : '';
718
719
	foreach ($boucles as $objet => $boucle) {
720
		if (substr($objet, 0, strlen($nom_skel)) == $nom_skel) {
721
			$i++;
722
			$nom = $boucle->id_boucle;
723
			$req = $boucle->type_requete;
724
			$crit = public_decompiler($boucle, $gram, 0, 'criteres');
725
			$self2 = $self . "&amp;var_mode_objet=" . $objet;
726
727
			$res .= "\n<tr style='background-color: " .
728
				($i % 2 ? '#e0e0f0' : '#f8f8ff') .
729
				"'><td  align='right'>$i</td><td>\n" .
730
				"<a  class='debug_link_boucle' href='" .
731
				$self2 .
732
				"&amp;var_mode_affiche=boucle#f_$nom_skel'>" .
733
				_T('zbug_boucle') .
734
				"</a></td><td>\n<a class='debug_link_boucle' href='" .
735
				$self2 .
736
				"&amp;var_mode_affiche=resultat#f_$nom_skel'>" .
737
				_T('zbug_resultat') .
738
				"</a></td><td>\n<a class='debug_link_resultat' href='" .
739
				$self2 .
740
				"&amp;var_mode_affiche=code#f_$nom_skel'>" .
741
				_T('zbug_code') .
742
				"</a></td><td>\n<a class='debug_link_resultat' href='" .
743
				str_replace('var_mode=', 'var_profile=', $self2) .
744
				"'>" .
745
				_T('zbug_calcul') .
746
				"</a></td><td>\n" .
747
				(($var_mode_objet == $objet) ? "<b>$nom</b>" : $nom) .
748
				"</td><td>\n" .
749
				$req .
750
				"</td><td>\n" .
751
				spip_htmlspecialchars($crit) .
752
				"</td></tr>";
753
		}
754
	}
755
756
	return $res;
757
}
758
759
function debusquer_source($objet, $affiche) {
760
	$quoi = $GLOBALS['debug_objets'][$affiche][$objet];
761
	if (!empty($GLOBALS['debug_objets']['boucle'][$objet]->id_boucle)) {
762
		$nom = $GLOBALS['debug_objets']['boucle'][$objet]->id_boucle;
763
	} else {
764
		$nom = $GLOBALS['debug_objets']['sourcefile'][$objet];
765
	}
766
	$res2 = "";
767
768
	if ($affiche == 'resultat') {
769
		$legend = $nom;
770
		$req = $GLOBALS['debug_objets']['requete'][$objet];
771
		if (function_exists('_mysql_traite_query')) {
772
			$c = strtolower(_request('connect'));
773
			$c = $GLOBALS['connexions'][$c ? $c : 0]['prefixe'];
774
			$req = _mysql_traite_query($req, '', $c);
775
		}
776
		//  permettre le copier/coller facile
777
		// $res = ancre_texte($req, array(), true);
778
		$res = "<div id='T" . md5($req) . "'>\n<pre>\n" . $req . "</pre>\n</div>\n";
779
		//  formatage et affichage des resultats bruts de la requete
780
		$ress_req = spip_query($req);
0 ignored issues
show
Deprecated Code introduced by
The function spip_query() has been deprecated with message: Pour compatibilité. Utiliser `sql_query()` ou l'API `sql_*`.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
781
		$brut_sql = '';
782
		$num = 1;
783
		//  eviter l'affichage de milliers de lignes
784
		//  personnalisation possible dans mes_options
785
		$max_aff = defined('_MAX_DEBUG_AFF') ? _MAX_DEBUG_AFF : 50;
786
		while ($retours_sql = sql_fetch($ress_req)) {
787
			if ($num <= $max_aff) {
788
				$brut_sql .= "<h3>" . ($num == 1 ? $num . " sur " . sql_count($ress_req) : $num) . "</h3>";
789
				$brut_sql .= "<p>";
790
				foreach ($retours_sql as $key => $val) {
791
					$brut_sql .= "<strong>" . $key . "</strong> => " . spip_htmlspecialchars(couper($val, 150)) . "<br />\n";
792
				}
793
				$brut_sql .= "</p>";
794
			}
795
			$num++;
796
		}
797
		$res2 = interdire_scripts($brut_sql);
798
		foreach ($quoi as $view) {
799
			//  ne pas afficher les $contexte_inclus
800
			$view = preg_replace(",<\?php.+\?[>],Uims", "", $view);
801
			if ($view) {
802
				$res2 .= "\n<br /><fieldset>" . interdire_scripts($view) . "</fieldset>";
803
			}
804
		}
805
806
	} elseif ($affiche == 'code') {
807
		$legend = $nom;
808
		$res = ancre_texte("<" . "?php\n" . $quoi . "\n?" . ">");
809
	} elseif ($affiche == 'boucle') {
810
		$legend = _T('zbug_boucle') . ' ' . $nom;
811
		// Le compilateur prefixe le nom des boucles par l'extension du fichier source.
812
		$gram = preg_match('/^([^_]+)_/', $objet, $r) ? $r[1] : '';
813
		$res = ancre_texte(public_decompiler($quoi, $gram, 0, 'boucle'));
814
	} elseif ($affiche == 'squelette') {
815
		$legend = $GLOBALS['debug_objets']['sourcefile'][$objet];
816
		$res = ancre_texte($GLOBALS['debug_objets']['squelette'][$objet]);
817
	}
818
819
	return array($legend, $res, $res2);
0 ignored issues
show
Bug introduced by
The variable $legend 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 $res 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...
820
}
821
822
// http://code.spip.net/@debusquer_entete
823
function debusquer_entete($titre, $corps) {
824
825
	include_spip('balise/formulaire_admin');
826
	include_spip('public/assembler'); // pour inclure_balise_dynamique
827
	include_spip('inc/texte'); // pour corriger_typo
828
829
	return _DOCTYPE_ECRIRE .
830
	html_lang_attributes() .
831
	"<head>\n<title>" .
832
	('SPIP ' . $GLOBALS['spip_version_affichee'] . ' ' .
833
		_T('admin_debug') . ' ' . $titre . ' (' .
834
		supprimer_tags(corriger_typo($GLOBALS['meta']['nom_site']))) .
835
	")</title>\n" .
836
	"<meta http-equiv='Content-Type' content='text/html" .
837
	(($c = $GLOBALS['meta']['charset']) ? "; charset=$c" : '') .
838
	"' />\n" .
839
	http_script('', 'jquery.js')
840
	. "<link rel='stylesheet' href='" . url_absolue(find_in_path('spip_admin.css'))
0 ignored issues
show
Bug introduced by
It seems like find_in_path('spip_admin.css') targeting find_in_path() can also be of type boolean; however, url_absolue() does only seem to accept string, maybe add an additional type check?

This check looks at variables that 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...
841
	. "' type='text/css' />" .
842
	"</head>\n" .
843
	"<body style='margin:0 10px;'>\n" .
844
	"<div id='spip-debug-header'>" .
845
	$corps .
846
	inclure_balise_dynamique(balise_FORMULAIRE_ADMIN_dyn('spip-admin-float', $GLOBALS['debug_objets']), false) .
847
	'</div></body></html>';
848
}
849