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

phraser_html.php ➔ public_phraser_html_dist()   F

Complexity

Conditions 21
Paths 18436

Size

Total Lines 177
Code Lines 118

Duplication

Lines 9
Ratio 5.08 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 21
eloc 118
c 2
b 0
f 0
nc 18436
nop 5
dl 9
loc 177
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
if (!defined('_ECRIRE_INC_VERSION')) return;
15
16
# Ce fichier transforme un squelette en un tableau d'objets de classe Boucle
17
# il est charge par un include calcule 
18
# pour permettre differentes syntaxes en entree
19
20
define('BALISE_BOUCLE', '<BOUCLE');
21
define('BALISE_FIN_BOUCLE', '</BOUCLE');
22
define('BALISE_PRE_BOUCLE', '<B');
23
define('BALISE_POST_BOUCLE', '</B');
24
define('BALISE_ALT_BOUCLE', '<//B');
25
26
define('TYPE_RECURSIF', 'boucle');
27
define('SPEC_BOUCLE','/\s*\(\s*([^\s?)]+)(\s*[^)?]*)([?]?)\)/');
28
define('NOM_DE_BOUCLE', "[0-9]+|[-_][-_.a-zA-Z0-9]*");
29
# ecriture alambiquee pour rester compatible avec les hexadecimaux des vieux squelettes
30
define('NOM_DE_CHAMP', "#((" . NOM_DE_BOUCLE . "):)?(([A-F]*[G-Z_][A-Z_0-9]*)|[A-Z_]+)(\*{0,2})");
31
define('CHAMP_ETENDU', '/\[([^]\[]*)\(' . NOM_DE_CHAMP . '([^[)]*\)[^]\[]*)\]/S');
32
33
define('BALISE_INCLURE','/<INCLU[DR]E[[:space:]]*(\(([^)]*)\))?/S');
34
define('BALISE_POLYGLOTTE',',<multi>(.*)</multi>,Uims');
35
define('BALISE_IDIOMES',',<:(([a-z0-9_]+):)?([a-z0-9_]*)({([^\|=>]*=[^>]*)})?((\|[^>]*)?:>),iS');
36
define('BALISE_IDIOMES_ARGS', '@^\s*([^= ]*)\s*=\s*((' . NOM_DE_CHAMP . '[{][^}]*})?[^,]*)\s*,?\s*@s');
37
38
define('SQL_ARGS', '(\([^)]*\))');
39
define('CHAMP_SQL_PLUS_FONC', '`?([A-Z_][A-Z_0-9.]*)' . SQL_ARGS . '?`?');
40
41
// http://doc.spip.org/@phraser_inclure
42
function phraser_inclure($texte, $ligne, $result) {
43
44
	while (preg_match(BALISE_INCLURE, $texte, $match)) {
45
		$p = strpos($texte,$match[0]);
46
		$debut = substr($texte, 0, $p);
47
		if ($p) $result = phraser_idiomes($debut, $ligne, $result);
48
		$ligne +=  substr_count($debut, "\n");
49
		$champ = new Inclure;
50
		$champ->ligne = $ligne;
51
		$ligne += substr_count($match[0], "\n");
52
		$fichier = @$match[2];
53
		# assurer ici la migration .php3 => .php
54
		# et de l'ancienne syntaxe INCLURE(page.php3) devenue surperflue
55
		if (preg_match(',^(.*[.]php)3$,', $fichier, $r)) {
56
			$fichier = $r[1];
57
		}
58
		$champ->texte = ($fichier !== 'page.php') ? $fichier : '';
59
		$texte = substr($texte, $p+strlen($match[0]));
60
		// on assimile {var=val} a une liste de un argument sans fonction
61
		phraser_args($texte,"/>","",$result,$champ);
62
		if (!$champ->texte OR count($champ->param) > 1) {
63
			include_spip('public/normaliser');
64
			normaliser_inclure($champ);
65
		}
66
		$texte = substr($champ->apres, strpos($champ->apres, '>')+1);
67
		$champ->apres = "";
68
		$texte = preg_replace(',^</INCLU[DR]E>,', '', $texte);
69
		$result[] = $champ;
70
	}
71
	return (($texte==="") ? $result : phraser_idiomes($texte, $ligne, $result));
72
}
73
74
// http://doc.spip.org/@phraser_polyglotte
75
function phraser_polyglotte($texte,$ligne, $result) {
76
77
	if (preg_match_all(BALISE_POLYGLOTTE, $texte, $m, PREG_SET_ORDER))
78
	foreach ($m as $match) {
79
		$p = strpos($texte, $match[0]);
80
		$debut = substr($texte, 0, $p);
81
		if ($p) {
82
			$champ = new Texte;
83
			$champ->texte = $debut;
84
			$champ->ligne = $ligne;
85
			$result[] = $champ;
86
			$ligne += substr_count($champ->texte, "\n");
87
		}
88
89
		$champ = new Polyglotte;
90
		$champ->ligne = $ligne;
91
		$ligne += substr_count($match[0], "\n");
92
		$lang = '';
93
		$bloc = $match[1];
94
		$texte = substr($texte,$p+strlen($match[0]));
95
		while (preg_match("/^[[:space:]]*([^[{]*)[[:space:]]*[[{]([a-z_]+)[]}](.*)$/si", $bloc, $regs)) {
96
		  $trad = $regs[1];
97
		  if ($trad OR $lang) 
98
			$champ->traductions[$lang] = $trad;
99
		  $lang = $regs[2];
100
		  $bloc = $regs[3];
101
		}
102
		$champ->traductions[$lang] = $bloc;
103
		$result[] = $champ;
104
	}
105
	if ($texte!=="") {
106
			$champ = new Texte;
107
			$champ->texte = $texte;
108
			$champ->ligne = $ligne;
109
			$result[] = $champ;
110
	}
111
	return $result;
112
}
113
114
115
116
/// Reperer les balises de traduction
117
/// <:module:chaine{arg1=texte1,arg2=#BALISE}|filtre1{texte2,#BALISE}|filtre2:>
118
/// chaine peut etre vide si =texte1 est present et arg1 est vide
119
/// sinon ce n'est pas un idiome
120
function phraser_idiomes($texte,$ligne,$result) {
121
	while (preg_match(BALISE_IDIOMES, $texte, $match)) {
122
		$p = strpos($texte, $match[0]);
123
		$ko = (!$match[3] && ($match[5][0]!=='='));
124
		$debut = substr($texte, 0, $p + ($ko ? strlen($match[0]) : 0));
125
		if ($debut) $result = phraser_champs($debut, $ligne, $result);
126
		$texte = substr($texte,$p+strlen($match[0]));
127
		$ligne += substr_count($debut, "\n");	
128
		if ($ko) continue; // faux idiome
129
		$champ = new Idiome;
130
		$champ->ligne = $ligne;
131
		$ligne += substr_count($match[0], "\n");
132
		// Stocker les arguments de la balise de traduction
133
		$args = array();
134
		$largs = $match[5];
135
		while (preg_match(BALISE_IDIOMES_ARGS, $largs, $r)) {
136
			$args[$r[1]] = phraser_champs($r[2], 0, array(), true);
137
			$largs = substr($largs, strlen($r[0]));
138
		}
139
		$champ->arg = $args;
140
		$champ->nom_champ = strtolower($match[3]);
141
		$champ->module = $match[2];
142
		// pas d'imbrication pour les filtres sur langue
143
		phraser_args(@$match[7], ":", '', array(), $champ);
144
		$result[] = $champ;
145
	}
146
	if ($texte!=="")  $result = phraser_champs($texte,$ligne,$result);
147
	return $result;
148
}
149
150
// http://doc.spip.org/@phraser_champs
151
function phraser_champs($texte,$ligne,$result, $filtre=false) {
152
	while (preg_match("/".NOM_DE_CHAMP."/S", $texte, $match)) {
153
	  $p = strpos($texte, $match[0]);
154
	  $suite = substr($texte,$p+strlen($match[0]));
155
	  if ($match[5] || (strpos($suite[0], "[0-9]") === false)) {
156
		$debut = substr($texte, 0, $p);
157
		if ($p)	$result = phraser_polyglotte($debut, $ligne, $result);
158
		$ligne += substr_count($debut, "\n");
159
		$champ = new Champ;
160
		$champ->ligne = $ligne;
161
		$ligne += substr_count($match[0], "\n");
162
		$champ->nom_boucle = $match[2];
163
		$champ->nom_champ = $match[3];
164
		$champ->etoile = $match[5];
165
166
		if ($suite[0] == '{') {
167
			phraser_arg($suite, '', array(), $champ);
168
		// ce ltrim est une ereur de conception
169
		// mais on le conserve par souci de compatibilite
170
			$texte = ltrim($suite);
171
		// Il faudrait le normaliser dans l'arbre de syntaxe abstraite
172
		// pour faire sauter ce cas particulier a la decompilation.
173
		/* Ce qui suit est malheureusement incomplet pour cela:
174
			if ($n = (strlen($suite) - strlen($texte))) {
175
				$champ->apres = array(new Texte);
176
				$champ->apres[0]->texte = substr($suite,0,$n);
177
			}
178
		*/
179
		} else $texte = $suite;
180
		if ($filtre) while ($texte[0]=='|') {
181
			$result = phraser_args($texte, '', '', $result, $champ);
182
			$args = $champ->apres ;
183
			$champ->apres = '';
184
			$texte = $args[0];
185
		  }
186
		phraser_vieux($champ);
187
		$result[] = $champ;
188
	  } else {
189
	    // faux champ
190
	    $result = phraser_polyglotte (substr($texte, 0, $p+1), $ligne, $result);
191
	    $texte = (substr($texte, $p+1));
192
	  }
193
	}
194
	if ($texte!=="") $result = phraser_polyglotte($texte, $ligne, $result);
195
	return $result;
196
}
197
198
// Gestion des imbrications:
199
// on cherche les [..] les plus internes et on les remplace par une chaine
200
// %###N@ ou N indexe un tableau comportant le resultat de leur analyse
201
// on recommence tant qu'il y a des [...] en substituant a l'appel suivant
202
203
// http://doc.spip.org/@phraser_champs_etendus
204
function phraser_champs_etendus($texte, $ligne,$result) {
205
	if ($texte==="") return $result;
206
	$sep = '##';
207
	while (strpos($texte,$sep)!== false)
208
		$sep .= '#';
209
	return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, array()));
210
}
211
212
//  Analyse les filtres d'un champ etendu et affecte le resultat
213
// renvoie la liste des lexemes d'origine augmentee
214
// de ceux trouves dans les arguments des filtres (rare)
215
// sert aussi aux arguments des includes et aux criteres de boucles
216
// Tres chevelu
217
218
// http://doc.spip.org/@phraser_args
219
function phraser_args($texte, $fin, $sep, $result, &$pointeur_champ) {
220
  $texte = ltrim($texte);
221
  while (($texte!=="") && strpos($fin, $texte[0]) === false) {
222
	$result = phraser_arg($texte, $sep, $result, $pointeur_champ);
223
	$texte = ltrim($texte);
224
  }
225
# mettre ici la suite du texte, 
226
# notamment pour que l'appelant vire le caractere fermant si besoin
227
  $pointeur_champ->apres = $texte;
228
  return $result;
229
}
230
231
// http://doc.spip.org/@phraser_arg
232
function phraser_arg(&$texte, $sep, $result, &$pointeur_champ) {
233
	preg_match(",^(\|?[^}{)|]*)(.*)$,ms", $texte, $match);
234
	$suite = ltrim($match[2]);
235
	$fonc = trim($match[1]);
236 View Code Duplication
	if ($fonc && $fonc[0] == "|") $fonc = ltrim(substr($fonc,1));
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...
237
	$res = array($fonc);
238
	$err_f = '';
239
	// cas du filtre sans argument ou du critere /
240
	if (($suite && ($suite[0] != '{')) || ($fonc  && $fonc[0] == '/')) {
241
		// si pas d'argument, alors il faut une fonction ou un double |
242 View Code Duplication
		if (!$match[1]) {
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...
243
			$err_f = array('zbug_erreur_filtre', array('filtre' => $texte));
244
			erreur_squelette($err_f, $pointeur_champ);
245
			$texte = '';
246
		} else 	$texte = $suite;
247 View Code Duplication
		if ($err_f) $pointeur_champ->param = false;
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
248
		elseif ($fonc!=='') $pointeur_champ->param[] = $res;
249
		// pour les balises avec faux filtres qui boudent ce dur larbeur
250
		$pointeur_champ->fonctions[] = array($fonc, '');
251
		return $result;
252
	}
253
	$args = ltrim(substr($suite,1)); // virer le '(' initial
254
	$collecte = array();
255
	while ($args && $args[0] != '}') {
256
        $f1 = $f2 = 0;
257
		if ($args[0] == '"')
258
			$f1 = preg_match ('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
259
		else if ($args[0] == "'")
260
			$f2 = preg_match ("/^(')([^']*)(')(.*)$/ms", $args, $regs);
261
        if (!($f1 OR $f2)) {
262
            preg_match("/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^,}]*)([,}].*)$/ms", $args, $regs);
263 View Code Duplication
		  if (!strlen($regs[2]))
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...
264
		    {
265
			$err_f = array('zbug_erreur_filtre', array('filtre' => $args));
266
			erreur_squelette($err_f, $pointeur_champ);
267
			$args = "";
268
			break;
269
		      }   
270
		}
271
		$arg = $regs[2];
0 ignored issues
show
Bug introduced by
The variable $regs 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...
272
		if (trim($regs[1])) {
273
			$champ = new Texte;
274
			$champ->texte = $arg;
275
			$champ->apres = $champ->avant = $regs[1];
276
			$result[] = $champ;
277
			$collecte[] = $champ;
278
			$args = ltrim($regs[count($regs)-1]);
279
		} else {
280
			if (!preg_match("/".NOM_DE_CHAMP ."([{|])/", $arg, $r)) {
281
				// 0 est un aveu d'impuissance. A completer
282
				$arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
283
284
				$args = ltrim($regs[count($regs)-1]);
285
				$collecte = array_merge($collecte, $arg);
286
				$result = array_merge($result, $arg);
287
			}
288
			else {
289
				$n = strpos($args,$r[0]);
290
				$pred = substr($args, 0, $n);
291
				$par = ',}';
292
				if (preg_match('/^(.*)\($/', $pred, $m))
293
					{$pred = $m[1]; $par =')';}
294
				if ($pred) {
295
					$r2 = phraser_idiomes($pred, 0, array());
296
					$result = array_merge($result, $r2);
297
					$collecte =  array_merge($collecte, $r2);
298
				}
299
				$rec = substr($args, $n + strlen($r[0]) -1);
300
				$champ = new Champ;
301
				$champ->nom_boucle = $r[2];
302
				$champ->nom_champ = $r[3];
303
				$champ->etoile = $r[5];
304
				$next = $r[6];
305
				while ($next=='{') {
306
					phraser_arg($rec, $sep, array(), $champ);
307
					$args = ltrim($rec) ;
308
					$next = $args[0];
309
				}
310
				while ($next=='|') {
311
					phraser_args($rec, $par, $sep, array(), $champ);
312
					$args = $champ->apres ;
313
					$champ->apres = '';
314
					$next = $args[0];
315
				}
316
				// Si erreur de syntaxe dans un sous-argument, propager.
317
				if ($champ->param === false)
318
					$err_f = true;
319
				else phraser_vieux($champ);
320
				if ($par==')') $args = substr($args,1);
321
				$collecte[] = $champ;
322
				$result[] = $champ;
323
			}
324
		}
325
		if ($args[0] == ',') {
326
			$args = ltrim(substr($args,1));
327
			if ($collecte) {$res[] = $collecte; $collecte = array();}
0 ignored issues
show
Bug Best Practice introduced by
The expression $collecte 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...
328
		}
329
	}
330
	if ($collecte) {$res[] = $collecte; $collecte = array();}
0 ignored issues
show
Bug Best Practice introduced by
The expression $collecte 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...
Unused Code introduced by
$collecte 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...
331
	$texte = substr($args,1);
332
	$source = substr($suite, 0, strlen($suite) - strlen($texte));
333
	// propager les erreurs, et ignorer les param vides
334
	if ($pointeur_champ->param !== false) {
335 View Code Duplication
		if ($err_f)
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...
336
			$pointeur_champ->param = false;
337
		elseif ($fonc!=='' || count($res) > 1)
338
			$pointeur_champ->param[] = $res;
339
	}
340
	// pour les balises avec faux filtres qui boudent ce dur larbeur
341
	$pointeur_champ->fonctions[] = array($fonc, $source);
342
	return $result;
343
}
344
345
346
// http://doc.spip.org/@phraser_champs_exterieurs
347
function phraser_champs_exterieurs($texte, $ligne, $sep, $nested) {
348
	$res = array();
349
	while (($p=strpos($texte, "%$sep"))!==false) {
350
		if (!preg_match(',^%'.preg_quote($sep).'([0-9]+)@,', substr($texte,$p), $m))
351
			break;
352
		$debut = substr($texte,0,$p);
353
		$texte = substr($texte, $p+strlen($m[0]));
354
		if ($p)
355
			$res = phraser_inclure($debut, $ligne, $res);
356
		$ligne += substr_count($debut, "\n");
357
		$res[]= $nested[$m[1]];
358
	}
359
	return (($texte==='') ? $res : phraser_inclure($texte, $ligne, $res));
360
}
361
362
// http://doc.spip.org/@phraser_champs_interieurs
363
function phraser_champs_interieurs($texte, $ligne, $sep, $result) {
364
	$i = 0; // en fait count($result)
365
	$x = "";
366
367
	while (true) {
368
		$j=$i;
369
		$n = $ligne;
370
		while (preg_match(CHAMP_ETENDU, $texte, $match)) {
371
			$p = strpos($texte, $match[0]);
372
			$debut = substr($texte, 0, $p);
373
			if ($p) {
374
				$result[$i] = $debut;
375
				$i++;
376
			}
377
			$nom = $match[4];
378
			$champ = new Champ;
379
			// ca ne marche pas encore en cas de champ imbrique
380
			$champ->ligne = $x ? 0 :($n+substr_count($debut, "\n"));
381
			$champ->nom_boucle = $match[3];
382
			$champ->nom_champ = $nom;
383
			$champ->etoile = $match[6];
384
			// phraser_args indiquera ou commence apres
385
			$result = phraser_args($match[7], ")", $sep, $result, $champ);
386
			phraser_vieux($champ);
387
			$champ->avant =
388
				phraser_champs_exterieurs($match[1],$n,$sep,$result);
389
			$debut = substr($champ->apres,1);
390 View Code Duplication
            if (!empty($debut))
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...
391
                $n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
392
			$champ->apres = phraser_champs_exterieurs($debut,$n,$sep,$result);
393
394
			$result[$i] = $champ;
395
			$i++;
396
			$texte = substr($texte,$p+strlen($match[0]));
397
		}
398
		if ($texte!=="") {$result[$i] = $texte; $i++;}
399
		$x ='';
400
401
		while($j < $i) {
402
			$z= $result[$j]; 
403
			// j'aurais besoin de connaitre le nombre de lignes...
404
			if (is_object($z))
405
				$x .= "%$sep$j@";
406
			else
407
				$x.=$z;
408
			$j++;
409
		}
410
		if (preg_match(CHAMP_ETENDU, $x))
411
			$texte = $x;
412
		else
413
			return phraser_champs_exterieurs($x, $ligne, $sep, $result);
414
	}
415
}
416
417
function phraser_vieux(&$champ)
418
{
419
	$nom = $champ->nom_champ;
420
	if ($nom == 'EMBED_DOCUMENT') {
421
		include_spip('public/normaliser');
422
		phraser_vieux_emb($champ);
423
	} elseif ($nom == 'EXPOSER') {
424
		include_spip('public/normaliser');
425
		phraser_vieux_exposer($champ);
426
	} elseif ($champ->param) {
427
		if ($nom == 'FORMULAIRE_RECHERCHE') {
428
			include_spip('public/normaliser');
429
			phraser_vieux_recherche($champ);
430
		} elseif (preg_match(",^LOGO_[A-Z]+,", $nom)) {
431
			include_spip('public/normaliser');
432
			phraser_vieux_logos($champ);
433
		} elseif ($nom == 'MODELE') {
434
			include_spip('public/normaliser');
435
			phraser_vieux_modele($champ);
436
		} elseif ($nom == 'INCLURE' OR $nom == 'INCLUDE') {
437
			include_spip('public/normaliser');
438
			phraser_vieux_inclu($champ);
439
		}
440
	}
441
}
442
443
// analyse des criteres de boucle, 
444
445
// http://doc.spip.org/@phraser_criteres
446
function phraser_criteres($params, &$result) {
447
448
	$err_ci = ''; // indiquera s'il y a eu une erreur
449
	$args = array();
450
	$type = $result->type_requete;
451
	$doublons = array();
452
	foreach($params as $v) {
453
		$var = $v[1][0];
454
		$param = ($var->type != 'texte') ? "" : $var->texte;
455
		if ((count($v) > 2) && (!preg_match(",[^A-Za-z]IN[^A-Za-z],i",$param)))
456
		  {
457
// plus d'un argument et pas le critere IN:
458
// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
459
460
			if (($var->type != 'texte') ||
461
			    (strpos("0123456789-", $param[strlen($param)-1])
462
			     !== false)) {
463
			  $op = ',';
464
			  $not = "";
465
			} else {
466
			  // Le debut du premier argument est l'operateur
467
			  preg_match("/^([!]?)([a-zA-Z][a-zA-Z0-9]*)[[:space:]]*(.*)$/ms", $param, $m);
468
			  $op = $m[2];
469
			  $not = $m[1];
470
			  // virer le premier argument,
471
			  // et mettre son reliquat eventuel
472
			  // Recopier pour ne pas alterer le texte source
473
			  // utile au debusqueur
474
475
			  if ($m[3]) {
476
			    $texte = new Texte;
477
			    $texte->texte = $m[3]; 
478
			    $v[1][0]= $texte;
479
			  } else array_shift($v[1]);
480
			}
481
			array_shift($v); // $v[O] est vide
482
			$crit = new Critere;
483
			$crit->op = $op;
484
			$crit->not = $not;
485
			$crit->exclus ="";
486
			$crit->param = $v;
487
			$args[] = $crit;
488
		  } else {
489
		  if ($var->type != 'texte') {
490
		    // cas 1 seul arg ne commencant pas par du texte brut: 
491
		    // erreur ou critere infixe "/"
492
		    if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) !='/')) {
493
			$err_ci = array('zbug_critere_inconnu', 
494
					array('critere' => $var->nom_champ));
495
			erreur_squelette($err_ci, $result);
496
		    } else {
497
		      $crit = new Critere;
498
		      $crit->op = '/';
499
		      $crit->not = "";
500
		      $crit->exclus ="";
501
		      $crit->param = array(array($v[1][0]),array($v[1][2]));
502
		      $args[] = $crit;
503
		    }
504
		  } else {
505
	// traiter qq lexemes particuliers pour faciliter la suite
506
	// les separateurs
507
			if ($var->apres)
508
				$result->separateur[] = $param;
509
			elseif (($param == 'tout') OR ($param == 'tous'))
510
				$result->modificateur['tout'] = true;
511
			elseif ($param == 'plat') 
512
				$result->modificateur['plat'] = true;
513
514
	// Boucle hierarchie, analyser le critere id_article - id_rubrique
515
	// - id_syndic, afin, dans les cas autres que {id_rubrique}, de
516
	// forcer {tout} pour avoir la rubrique mere...
517
518
			elseif (!strcasecmp($type, 'hierarchie') AND
519
				($param == 'id_article' OR $param == 'id_syndic'))
520
				$result->modificateur['tout'] = true;
521
			elseif (!strcasecmp($type, 'hierarchie') AND ($param == 'id_rubrique'))
522
				{;}
523
			else {
524
			  // pas d'emplacement statique, faut un dynamique
525
			  /// mais il y a 2 cas qui ont les 2 !
526
			  if (($param == 'unique') || (preg_match(',^!?doublons *,', $param)))
527
			    {
528
			      // cette variable sera inseree dans le code
529
			      // et son nom sert d'indicateur des maintenant
530
			      $result->doublons = '$doublons_index';
531
			      if ($param == 'unique') $param = 'doublons';
532
			    }
533
			  elseif ($param == 'recherche')
534
			    // meme chose (a cause de #nom_de_boucle:URL_*)
535
			      $result->hash = ' ';
536
			  if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
537
			    $crit = phraser_critere_infixe($m[1], $m[3],$v, '/', '', '');
538
			  } elseif (preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC . 
539
					 ')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)) {
540
			    $a2 = trim($m[8]);
541
			    if ($a2 AND ($a2[0]=="'" OR $a2[0]=='"') AND ($a2[0]==substr($a2,-1)))
542
			      $a2 = substr($a2,1,-1);
543
			    $crit = phraser_critere_infixe($m[2], $a2, $v,
544
							   (($m[2] == 'lang_select') ? $m[2] : $m[7]),
545
							   $m[6], $m[5]);
546
					$crit->exclus = $m[1];
547
			  } elseif (preg_match("/^([!]?)\s*(" .
548
					       CHAMP_SQL_PLUS_FONC .
549
					       ")\s*(\??)(.*)$/is", $param, $m)) {
550
		  // contient aussi les comparaisons implicites !
551
			    // Comme ci-dessus: 
552
			    // le premier arg contient l'operateur
553
			    array_shift($v);
554
			    if ($m[6]) {
555
			      $v[0][0] = new Texte;
556
			      $v[0][0]->texte = $m[6];
557
			    } else {
558
			      array_shift($v[0]);
559
			      if (!$v[0]) array_shift($v);
560
			    }
561
			    $crit = new Critere;
562
			    $crit->op = $m[2];
563
			    $crit->param = $v;
564
			    $crit->not = $m[1];
565
			    $crit->cond = $m[5];
0 ignored issues
show
Bug introduced by
The property cond does not seem to exist in Critere.

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...
566
			  }
567
			  else {
568
			 	$err_ci = array('zbug_critere_inconnu', 
569
					array('critere' => $param));
570
				erreur_squelette($err_ci, $result);
571
			  }
572
			  if ((!preg_match(',^!?doublons *,', $param)) || $crit->not)
573
			    $args[] = $crit;
0 ignored issues
show
Bug introduced by
The variable $crit 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...
574
			  else 
575
			    $doublons[] = $crit;
576
			}
577
		  }
578
		}
579
	}
580
	// les doublons non nies doivent etre le dernier critere
581
	// pour que la variable $doublon_index ait la bonne valeur
582
	// cf critere_doublon
583
	if ($doublons) $args= array_merge($args, $doublons);
0 ignored issues
show
Bug Best Practice introduced by
The expression $doublons 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...
584
	// Si erreur, laisser la chaine dans ce champ pour le HTTP 503
585
	if (!$err_ci) $result->criteres = $args;
586
}
587
588
// http://doc.spip.org/@phraser_critere_infixe
589
function phraser_critere_infixe($arg1, $arg2, $args, $op, $not, $cond)
590
{
591
	$args[0] = new Texte;
592
	$args[0]->texte = $arg1;
593
	$args[0] = array($args[0]);
594
	$args[1][0] = new Texte;
595
	$args[1][0]->texte  = $arg2;
596
	$crit = new Critere;
597
	$crit->op = $op;
598
	$crit->not = $not;
599
	$crit->cond = $cond;
0 ignored issues
show
Bug introduced by
The property cond does not seem to exist in Critere.

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...
600
	$crit->param = $args;
601
	return $crit;
602
}
603
604
function public_phraser_html_dist($texte, $id_parent, &$boucles, $descr, $ligne=1) {
605
606
	$all_res = array();
607
608
	while (($pos_boucle = strpos($texte, BALISE_BOUCLE)) !== false) {
609
610
		$err_b = ''; // indiquera s'il y a eu une erreur
611
		$result = new Boucle;
612
		$result->id_parent = $id_parent;
613
		$result->descr = $descr;
614
# attention: reperer la premiere des 2 balises: pre_boucle ou boucle
615
616
		if (!preg_match(",".BALISE_PRE_BOUCLE . '[0-9_],', $texte, $r)
617
			OR ($n = strpos($texte, $r[0]))===false
618
			OR ($n > $pos_boucle) ) {
619
		  $debut = substr($texte, 0, $pos_boucle);
620
		  $milieu = substr($texte, $pos_boucle);
621
		  $n = strpos($milieu, '(');
622
		  $id_boucle = trim(substr($milieu,
623
					   strlen(BALISE_BOUCLE),
624
					   $n - strlen(BALISE_BOUCLE)));
625
		  $milieu = substr($milieu, $n);
626
		} else {
627
            $debut = substr($texte, 0, $n);
628
            $milieu = substr($texte, $n);
629
            $k = strpos($milieu, '>');
630
            $id_boucle = substr($milieu,
631
				       strlen(BALISE_PRE_BOUCLE),
632
				       $k - strlen(BALISE_PRE_BOUCLE));
633
634
            if (!preg_match(",".BALISE_BOUCLE . $id_boucle . "[[:space:]]*\(,", $milieu, $r)) {
635
                $err_b = array('zbug_erreur_boucle_syntaxe', array('id' => $id_boucle));
636
                erreur_squelette($err_b, $result);
637
                $texte = substr($texte, $n+1);
638
                continue;
639
		  } else {
640
                $pos_boucle = $n;
0 ignored issues
show
Unused Code introduced by
$pos_boucle 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...
641
                $n = strpos($milieu, $r[0]);
642
                $result->avant = substr($milieu, $k+1, $n-$k-1);
643
                $milieu = substr($milieu, $n+strlen($id_boucle)+strlen(BALISE_BOUCLE));
644
            }
645
		}
646
        if (!preg_match('#^' . NOM_DE_BOUCLE . '$#', $id_boucle)) {
647
            $err_b = array('zbug_erreur_boucle_syntaxe', array('id' => $id_boucle));
648
            erreur_squelette($err_b, $result);
649
            $texte = substr($texte, $n);
650
            continue;
651
        }
652
653
		$result->id_boucle = $id_boucle;
654
655
		preg_match(SPEC_BOUCLE, $milieu, $match);
656
		$result->type_requete = $match[0];
657
                $milieu = substr($milieu, strlen($match[0]));
658
		$type = $match[1];
659
		$jointures = trim($match[2]);
660
		$table_optionnelle = ($match[3]);
661
		if ($jointures) {
662
			// on affecte pas ici les jointures explicites, mais dans la compilation
663
			// ou elles seront completees des jointures declarees
664
			$result->jointures_explicites = $jointures;
0 ignored issues
show
Documentation Bug introduced by
The property $jointures_explicites was declared of type boolean, but $jointures is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
665
		}
666
		
667
		if ($table_optionnelle){
668
			$result->table_optionnelle = $type;
0 ignored issues
show
Documentation Bug introduced by
The property $table_optionnelle was declared of type boolean, but $type is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
669
		}
670
		
671
		// 1ere passe sur les criteres, vu comme des arguments sans fct
672
		// Resultat mis dans result->param
673
		phraser_args($milieu,"/>","",$all_res,$result);
674
675
		// En 2e passe result->criteres contiendra un tableau
676
		// pour l'instant on met le source (chaine) :
677
		// si elle reste ici au final, c'est qu'elle contient une erreur
678
		$result->criteres =  substr($milieu,0,@strpos($milieu,$result->apres));
679
		$milieu = $result->apres;
680
		$result->apres = "";
681
682
		//
683
		// Recuperer la fin :
684
		//
685
		if ($milieu[0] === '/') {
686
			$suite = substr($milieu,2);
687
			$milieu = '';
688
		} else {
689
			$milieu = substr($milieu,1);
690
			$s = BALISE_FIN_BOUCLE . $id_boucle . ">";
691
			$p = strpos($milieu, $s);
692
			if ($p === false) {
693
				$err_b = array('zbug_erreur_boucle_fermant',
694
					array('id' => $id_boucle));
695
				erreur_squelette($err_b, $result);
696
			}
697
698
			$suite = substr($milieu, $p + strlen($s));
699
			$milieu = substr($milieu, 0, $p);
700
		}
701
702
		$result->milieu = $milieu;
703
704
		//
705
		// 1. Recuperer la partie conditionnelle apres
706
		//
707
		$s = BALISE_POST_BOUCLE . $id_boucle . ">";
708
		$p = strpos($suite, $s);
709 View Code Duplication
		if ($p !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
710
			$result->apres = substr($suite, 0, $p);
711
			$suite = substr($suite, $p + strlen($s));
712
		}
713
714
		//
715
		// 2. Recuperer la partie alternative
716
		//
717
		$s = BALISE_ALT_BOUCLE . $id_boucle . ">";
718
		$p = strpos($suite, $s);
719 View Code Duplication
		if ($p !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
720
			$result->altern = substr($suite, 0, $p);
721
			$suite = substr($suite, $p + strlen($s));
722
		}
723
		$result->ligne = $ligne + substr_count($debut, "\n");
724
		$m = substr_count($milieu, "\n");
725
		$b = substr_count($result->avant, "\n");
726
		$a = substr_count($result->apres, "\n");
727
728
		if ($p = strpos($type, ':')) {
729
			$result->sql_serveur = substr($type,0,$p);
730
			$type = substr($type,$p+1);
731
		}
732
		$soustype = strtolower($type);
733
		if ($soustype == 'sites') $soustype = 'syndication' ; # alias
734
735
		if (!isset($GLOBALS["table_des_tables"][$soustype]))
736
			$soustype = $type;
737
738
		$result->type_requete = $soustype;
739
		// Lancer la 2e passe sur les criteres si la 1ere etait bonne
740
		if (!is_array($result->param))
741
			$err_b = true;
742
		else {
743
			phraser_criteres($result->param, $result);
744
			if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
745
				$result->type_requete = TYPE_RECURSIF;
746
				$args = $result->param;
747
				array_unshift($args,
748
					substr($type, strlen(TYPE_RECURSIF)));
749
				$result->param = $args;
750
			}
751
		}
752
753
		$result->avant = public_phraser_html_dist($result->avant, $id_parent,$boucles, $descr, $result->ligne);
754
		$result->apres = public_phraser_html_dist($result->apres, $id_parent,$boucles, $descr, $result->ligne+$b+$m);
755
		$result->altern = public_phraser_html_dist($result->altern,$id_parent,$boucles, $descr, $result->ligne+$a+$m+$b);
756
		$result->milieu = public_phraser_html_dist($milieu, $id_boucle,$boucles, $descr, $result->ligne+$b);
757
758
		// Prevenir le generateur de code que le squelette est faux
759
		if ($err_b) $result->type_requete = false;
760
761
		// Verifier qu'il n'y a pas double definition
762
		// apres analyse des sous-parties (pas avant).
763
		
764
		if (isset($boucles[$id_boucle])) {
765
			$err_b_d = array('zbug_erreur_boucle_double',
766
				 	array('id'=>$id_boucle));
767
			erreur_squelette($err_b_d, $result);
768
		// Prevenir le generateur de code que le squelette est faux
769
			$boucles[$id_boucle]->type_requete = false;
770
		} else
771
			$boucles[$id_boucle] = $result;
772
		$all_res = phraser_champs_etendus($debut, $ligne, $all_res);
773
		$all_res[] = &$boucles[$id_boucle];
774 View Code Duplication
        if (!empty($suite))
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...
775
            $ligne += substr_count(substr($texte, 0, strpos($texte, $suite)), "\n");
776
		$texte = $suite;
777
	}
778
779
	return phraser_champs_etendus($texte, $ligne, $all_res);
780
}
781
?>
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...
782