4 |
david |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
/***************************************************************************\
|
|
|
4 |
* SPIP, Systeme de publication pour l'internet *
|
|
|
5 |
* *
|
|
|
6 |
* Copyright (c) 2001-2005 *
|
|
|
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 |
// Ce fichier ne sera execute qu'une fois
|
|
|
15 |
if (defined("_INC_HTML_SQUEL")) return;
|
|
|
16 |
define("_INC_HTML_SQUEL", "1");
|
|
|
17 |
|
|
|
18 |
# Ce fichier doit IMPERATIVEMENT contenir la fonction "phraser"
|
|
|
19 |
# qui transforme un squelette en un tableau d'objets de classe Boucle
|
|
|
20 |
# il est charge par un include calcule dans inc-calcul-squel
|
|
|
21 |
# pour permettre differentes syntaxes en entree
|
|
|
22 |
|
|
|
23 |
define('BALISE_BOUCLE', '<BOUCLE');
|
|
|
24 |
define('BALISE_FIN_BOUCLE', '</BOUCLE');
|
|
|
25 |
define('BALISE_PRE_BOUCLE', '<B');
|
|
|
26 |
define('BALISE_POST_BOUCLE', '</B');
|
|
|
27 |
define('BALISE_ALT_BOUCLE', '<//B');
|
|
|
28 |
|
|
|
29 |
define('TYPE_RECURSIF', 'boucle');
|
|
|
30 |
define('SPEC_BOUCLE','[[:space:]]*\(([^)]*)\)');
|
|
|
31 |
define('NOM_DE_BOUCLE', "[0-9]+|[-_][-_.a-zA-Z0-9]*");
|
|
|
32 |
# ecriture alambiquee pour rester compatible avec les hexadecimaux des vieux squelettes
|
|
|
33 |
define('NOM_DE_CHAMP', "#((" . NOM_DE_BOUCLE . "):)?(([A-F]*[G-Z_][A-Z_0-9]*)|[A-Z_]+)(\*?)");
|
|
|
34 |
define('CHAMP_ETENDU', '\[([^]\[]*)\(' . NOM_DE_CHAMP . '([^[)]*\)[^]\[]*)\]');
|
|
|
35 |
|
|
|
36 |
define('BALISE_INCLURE','<INCLU[DR]E[[:space:]]*\(([^)]*)\)');
|
|
|
37 |
|
|
|
38 |
function phraser_inclure($texte, $ligne, $result) {
|
|
|
39 |
|
|
|
40 |
while (ereg(BALISE_INCLURE, $texte, $match)) {
|
|
|
41 |
$p = strpos($texte,$match[0]);
|
|
|
42 |
$debut = substr($texte, 0, $p);
|
|
|
43 |
if ($p) $result = phraser_idiomes($debut, $ligne, $result);
|
|
|
44 |
$ligne += substr_count($debut, "\n");
|
|
|
45 |
$champ = new Inclure;
|
|
|
46 |
$champ->ligne = $ligne;
|
|
|
47 |
$ligne += substr_count($match[0], "\n");
|
|
|
48 |
$champ->texte = $match[1];
|
|
|
49 |
$texte = substr($texte, $p+strlen($match[0]));
|
|
|
50 |
// on assimile {var=val} a une liste de un argument sans fonction
|
|
|
51 |
phraser_args($texte,">","",$result,$champ);
|
|
|
52 |
foreach ($champ->param as $k => $v) {
|
|
|
53 |
$var = $v[1][0];
|
|
|
54 |
if ($var->type != 'texte')
|
|
|
55 |
erreur_squelette(_T('zbug_parametres_inclus_incorrects'),
|
|
|
56 |
$match[0]);
|
|
|
57 |
else {
|
|
|
58 |
ereg("^([^=]*)(=)?(.*)$", $var->texte,$m);
|
|
|
59 |
if ($m[2]) {
|
|
|
60 |
$champ->param[$k][0] = $m[1];
|
|
|
61 |
$val = $m[3];
|
|
|
62 |
if (ereg('^[\'"](.*)[\'"]$', $val, $m)) $val = $m[1];
|
|
|
63 |
$champ->param[$k][1][0]->texte = $val;
|
|
|
64 |
}
|
|
|
65 |
else
|
|
|
66 |
$champ->param[$k] = array($m[1]);
|
|
|
67 |
}
|
|
|
68 |
}
|
|
|
69 |
$texte = substr($champ->apres,1);
|
|
|
70 |
$champ->apres = "";
|
|
|
71 |
$result[] = $champ;
|
|
|
72 |
}
|
|
|
73 |
return (($texte==="") ? $result : phraser_idiomes($texte, $ligne, $result));
|
|
|
74 |
}
|
|
|
75 |
|
|
|
76 |
function phraser_polyglotte($texte,$ligne, $result) {
|
|
|
77 |
|
|
|
78 |
while (eregi('<multi>([^<]*)</multi>', $texte, $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 |
}
|
|
|
87 |
|
|
|
88 |
$champ = new Polyglotte;
|
|
|
89 |
$ligne += substr_count($champ->texte, "\n");
|
|
|
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 |
function phraser_idiomes($texte,$ligne,$result) {
|
|
|
116 |
|
|
|
117 |
// Reperer les balises de traduction <:toto:>
|
|
|
118 |
while (eregi("<:(([a-z0-9_]+):)?([a-z0-9_]+)((\|[^:>]*)?:>)", $texte, $match)) {
|
|
|
119 |
$p = strpos($texte, $match[0]);
|
|
|
120 |
$debut = substr($texte, 0, $p);
|
|
|
121 |
if ($p) $result = phraser_champs($debut, $ligne, $result);
|
|
|
122 |
$champ = new Idiome;
|
|
|
123 |
$ligne += substr_count($debut, "\n");
|
|
|
124 |
$champ->ligne = $ligne;
|
|
|
125 |
$ligne += substr_count($match[0], "\n");
|
|
|
126 |
$texte = substr($texte,$p+strlen($match[0]));
|
|
|
127 |
$champ->nom_champ = strtolower($match[3]);
|
|
|
128 |
$champ->module = $match[2] ? $match[2] : 'public/spip/ecrire';
|
|
|
129 |
// pas d'imbrication pour les filtres sur langue
|
|
|
130 |
phraser_args($match[5], ":", '', array(), $champ);
|
|
|
131 |
$result[] = $champ;
|
|
|
132 |
}
|
|
|
133 |
if ($texte!=="") $result = phraser_champs($texte,$ligne,$result);
|
|
|
134 |
return $result;
|
|
|
135 |
}
|
|
|
136 |
|
|
|
137 |
function phraser_champs($texte,$ligne,$result) {
|
|
|
138 |
while (ereg(NOM_DE_CHAMP, $texte, $match)) {
|
|
|
139 |
$p = strpos($texte, $match[0]);
|
|
|
140 |
$suite = substr($texte,$p+strlen($match[0]));
|
|
|
141 |
if ($match[5] || (strpos($suite[0], "[0-9]") === false)) {
|
|
|
142 |
$debut = substr($texte, 0, $p);
|
|
|
143 |
if ($p) $result = phraser_polyglotte($debut, $ligne, $result);
|
|
|
144 |
$ligne += substr_count($debut, "\n");
|
|
|
145 |
$champ = new Champ;
|
|
|
146 |
$champ->ligne = $ligne;
|
|
|
147 |
$ligne += substr_count($match[0], "\n");
|
|
|
148 |
$champ->nom_boucle = $match[2];
|
|
|
149 |
$champ->nom_champ = $match[3];
|
|
|
150 |
$champ->etoile = $match[5];
|
|
|
151 |
$texte = $suite;
|
|
|
152 |
$result[] = $champ;
|
|
|
153 |
} else {
|
|
|
154 |
// faux champ
|
|
|
155 |
$result = phraser_polyglotte (substr($texte, 0, $p+1), $ligne, $result);
|
|
|
156 |
$texte = (substr($texte, $p+1));
|
|
|
157 |
}
|
|
|
158 |
}
|
|
|
159 |
if ($texte!=="") $result = phraser_polyglotte($texte, $ligne, $result);
|
|
|
160 |
return $result;
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
// Gestion des imbrications:
|
|
|
164 |
// on cherche les [..] les plus internes et on les remplace par une chaine
|
|
|
165 |
// %###N@ ou N indexe un tableau comportant le resultat de leur analyse
|
|
|
166 |
// on recommence tant qu'il y a des [...] en substituant a l'appel suivant
|
|
|
167 |
|
|
|
168 |
function phraser_champs_etendus($texte, $ligne,$result) {
|
|
|
169 |
if ($texte==="") return $result;
|
|
|
170 |
$sep = '##';
|
|
|
171 |
while (strpos($texte,$sep)!== false)
|
|
|
172 |
$sep .= '#';
|
|
|
173 |
return array_merge($result, phraser_champs_interieurs($texte, $ligne, $sep, array()));
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
// Analyse les filtres d'un champ etendu et affecte le resultat
|
|
|
177 |
// renvoie la liste des lexemes d'origine augmentee
|
|
|
178 |
// de ceux trouves dans les arguments des filtres (rare)
|
|
|
179 |
// sert aussi aux arguments des includes et aux criteres de boucles
|
|
|
180 |
// Tres chevelu
|
|
|
181 |
|
|
|
182 |
function phraser_args($texte, $fin, $sep, $result, &$pointeur_champ) {
|
|
|
183 |
$texte = ltrim($texte);
|
|
|
184 |
while (($texte!=="") && strpos($fin, $texte[0]) === false) {
|
|
|
185 |
preg_match(",^(\|?[^{)|]*)(.*)$,ms", $texte, $match);
|
|
|
186 |
$suite = ltrim($match[2]);
|
|
|
187 |
$fonc = trim($match[1]);
|
|
|
188 |
if ($fonc[0] == "|") $fonc = ltrim(substr($fonc,1));
|
|
|
189 |
$res = array($fonc);
|
|
|
190 |
$args = $suite ;
|
|
|
191 |
// cas du filtre sans argument ou du critere /
|
|
|
192 |
if (($suite[0] != '{') || ($fonc && $fonc[0] == '/'))
|
|
|
193 |
{
|
|
|
194 |
// si pas d'argument, alors il faut une fonction ou un double |
|
|
|
195 |
if (!$match[1])
|
|
|
196 |
erreur_squelette(_T('zbug_info_erreur_squelette'), $texte);
|
|
|
197 |
// pas d'arg et pas d'autres filtres ==> critere infixe comme "/"
|
|
|
198 |
if (($fin != ':') &&
|
|
|
199 |
((!$suite) || strpos(")|", $suite[0]) === false)) break;
|
|
|
200 |
} else {
|
|
|
201 |
$args = ltrim(substr($suite,1));
|
|
|
202 |
$collecte = array();
|
|
|
203 |
while ($args && $args[0] != '}') {
|
|
|
204 |
if ($args[0] == '"')
|
|
|
205 |
preg_match ('/^(")([^"]*)(")(.*)$/ms', $args, $regs);
|
|
|
206 |
else if ($args[0] == "'")
|
|
|
207 |
preg_match ("/^(')([^']*)(')(.*)$/ms", $args, $regs);
|
|
|
208 |
else {
|
|
|
209 |
preg_match("/^([[:space:]]*)([^,([{}]*([(\[{][^])}]*[])}])?[^$fin,}]*)([,}$fin].*)$/ms", $args, $regs);
|
|
|
210 |
if (!strlen($regs[2]))
|
|
|
211 |
{
|
|
|
212 |
erreur_squelette(_T('zbug_info_erreur_squelette'), $args);
|
|
|
213 |
$args = '';
|
|
|
214 |
exit;
|
|
|
215 |
}
|
|
|
216 |
}
|
|
|
217 |
$arg = $regs[2];
|
|
|
218 |
if (trim($regs[1])) {
|
|
|
219 |
$champ = new Texte;
|
|
|
220 |
$champ->texte = $arg;
|
|
|
221 |
$champ->apres = $champ->avant = $regs[1];
|
|
|
222 |
$result[] = $champ;
|
|
|
223 |
$collecte[] = $champ;
|
|
|
224 |
$args = ltrim($regs[count($regs)-1]);
|
|
|
225 |
} else {
|
|
|
226 |
if (!ereg(NOM_DE_CHAMP ."[{|]", $arg, $r)) {
|
|
|
227 |
// 0 est un aveu d'impuissance. A completer
|
|
|
228 |
$arg = phraser_champs_exterieurs($arg, 0, $sep, $result);
|
|
|
229 |
$args = ltrim($regs[count($regs)-1]);
|
|
|
230 |
$collecte = array_merge($collecte, $arg);
|
|
|
231 |
$result = array_merge($result, $arg);
|
|
|
232 |
}
|
|
|
233 |
else {
|
|
|
234 |
$n = strpos($args,$r[0]);
|
|
|
235 |
$pred = substr($args, 0, $n);
|
|
|
236 |
$par = ',}';
|
|
|
237 |
if (ereg('^(.*)\($', $pred, $m))
|
|
|
238 |
{$pred = $m[1]; $par =')';}
|
|
|
239 |
if ($pred) {
|
|
|
240 |
$champ = new Texte;
|
|
|
241 |
$champ->texte = $pred;
|
|
|
242 |
$champ->apres = $champ->avant = "";
|
|
|
243 |
$result[] = $champ;
|
|
|
244 |
$collecte[] = $champ;
|
|
|
245 |
}
|
|
|
246 |
$rec = substr($args, $n + strlen($r[0]) -1);
|
|
|
247 |
$champ = new Champ;
|
|
|
248 |
$champ->nom_boucle = $r[2];
|
|
|
249 |
$champ->nom_champ = $r[3];
|
|
|
250 |
$champ->etoile = $r[5];
|
|
|
251 |
phraser_args($rec, $par, $sep, array(), $champ);
|
|
|
252 |
$args = $champ->apres ;
|
|
|
253 |
$champ->apres = '';
|
|
|
254 |
if ($par==')') $args = substr($args,1);
|
|
|
255 |
$collecte[] = $champ;
|
|
|
256 |
$result[] = $champ;
|
|
|
257 |
}
|
|
|
258 |
}
|
|
|
259 |
if ($args[0] == ',') {
|
|
|
260 |
$args = ltrim(substr($args,1));
|
|
|
261 |
if ($collecte)
|
|
|
262 |
{$res[] = $collecte; $collecte = array();}
|
|
|
263 |
}
|
|
|
264 |
|
|
|
265 |
}
|
|
|
266 |
if ($collecte) {$res[] = $collecte; $collecte = array();}
|
|
|
267 |
$args = substr($args,1);
|
|
|
268 |
}
|
|
|
269 |
$n = strlen($suite) - strlen($args);
|
|
|
270 |
$pointeur_champ->param[] = $res;
|
|
|
271 |
// pour les balises avec faux filtres qui boudent ce dur larbeur
|
|
|
272 |
$pointeur_champ->fonctions[] = array($fonc, substr($suite, 0, $n));
|
|
|
273 |
$texte = ltrim($args);
|
|
|
274 |
}
|
|
|
275 |
# laisser l'appelant virer le caractere fermant
|
|
|
276 |
$pointeur_champ->apres = $texte;
|
|
|
277 |
return $result;
|
|
|
278 |
}
|
|
|
279 |
|
|
|
280 |
function phraser_champs_exterieurs($texte, $ligne, $sep, $nested) {
|
|
|
281 |
$res = array();
|
|
|
282 |
while (($p=strpos($texte, "%$sep"))!==false) {
|
|
|
283 |
$debut = substr($texte,0,$p);
|
|
|
284 |
if ($p) $res = phraser_inclure($debut, $ligne, $res);
|
|
|
285 |
$ligne += substr_count($debut, "\n");
|
|
|
286 |
ereg("^%$sep([0-9]+)@(.*)$", substr($texte,$p),$m);
|
|
|
287 |
$res[]= $nested[$m[1]];
|
|
|
288 |
$texte = $m[2];
|
|
|
289 |
}
|
|
|
290 |
return (($texte==="") ? $res : phraser_inclure($texte, $ligne, $res));
|
|
|
291 |
}
|
|
|
292 |
|
|
|
293 |
function phraser_champs_interieurs($texte, $ligne, $sep, $result) {
|
|
|
294 |
$i = 0; // en fait count($result)
|
|
|
295 |
$x = "";
|
|
|
296 |
while (true) { $j=$i; $n = $ligne;
|
|
|
297 |
while (ereg(CHAMP_ETENDU, $texte, $match)) {
|
|
|
298 |
$p = strpos($texte, $match[0]);
|
|
|
299 |
$debut = substr($texte, 0, $p);
|
|
|
300 |
if ($p) {$result[$i] = $debut;$i++; }
|
|
|
301 |
$champ = new Champ;
|
|
|
302 |
// ca ne marche pas encore en cas de champ imbrique
|
|
|
303 |
$champ->ligne = $x ? 0 :($n+substr_count($debut, "\n"));
|
|
|
304 |
$champ->nom_boucle = $match[3];
|
|
|
305 |
$champ->nom_champ = $match[4];
|
|
|
306 |
$champ->etoile = $match[6];
|
|
|
307 |
// phraser_args indiquera ou commence apres
|
|
|
308 |
$result = phraser_args($match[7], ")", $sep, $result, $champ);
|
|
|
309 |
$champ->avant = phraser_champs_exterieurs($match[1],$n,$sep,$result);
|
|
|
310 |
$debut = substr($champ->apres,1);
|
|
|
311 |
$n += substr_count(substr($texte, 0, strpos($texte, $debut)), "\n");
|
|
|
312 |
$champ->apres = phraser_champs_exterieurs($debut,$n,$sep,$result);
|
|
|
313 |
|
|
|
314 |
$result[$i] = $champ;
|
|
|
315 |
$i++;
|
|
|
316 |
$texte = substr($texte,$p+strlen($match[0]));
|
|
|
317 |
}
|
|
|
318 |
if ($texte!=="") {$result[$i] = $texte; $i++;}
|
|
|
319 |
$x ='';
|
|
|
320 |
|
|
|
321 |
while($j < $i)
|
|
|
322 |
{ $z= $result[$j];
|
|
|
323 |
// j'aurais besoin de connaitre le nombre de lignes...
|
|
|
324 |
if (is_object($z)) $x .= "%$sep$j@" ; else $x.=$z ;
|
|
|
325 |
$j++;}
|
|
|
326 |
if (ereg(CHAMP_ETENDU, $x)) $texte = $x;
|
|
|
327 |
else return phraser_champs_exterieurs($x, $ligne, $sep, $result);}
|
|
|
328 |
}
|
|
|
329 |
|
|
|
330 |
// analyse des criteres de boucle,
|
|
|
331 |
|
|
|
332 |
function phraser_criteres($params, &$result) {
|
|
|
333 |
|
|
|
334 |
$args = array();
|
|
|
335 |
$type = $result->type_requete;
|
|
|
336 |
|
|
|
337 |
foreach($params as $v) {
|
|
|
338 |
$var = $v[1][0];
|
|
|
339 |
$param = ($var->type != 'texte') ? "" : $var->texte;
|
|
|
340 |
if ((count($v) > 2) && (!eregi("[^A-Za-z]IN[^A-Za-z]",$param)))
|
|
|
341 |
{
|
|
|
342 |
// plus d'un argument et pas le critere IN:
|
|
|
343 |
// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
|
|
|
344 |
|
|
|
345 |
if (($var->type != 'texte') ||
|
|
|
346 |
(strpos("0123456789-", $param[strlen($param)-1])
|
|
|
347 |
!== false)) {
|
|
|
348 |
$op = ',';
|
|
|
349 |
$not = "";
|
|
|
350 |
} else {
|
|
|
351 |
preg_match("/^([!]?)([a-zA-Z][a-zA-Z0-9]*)[[:space:]]*(.*)$/ms", $param, $m);
|
|
|
352 |
$op = $m[2];
|
|
|
353 |
$not = $m[1];
|
|
|
354 |
if ($m[3]) $v[1][0]->texte = $m[3]; else array_shift($v[1]);
|
|
|
355 |
}
|
|
|
356 |
array_shift($v);
|
|
|
357 |
$crit = new Critere;
|
|
|
358 |
$crit->op = $op;
|
|
|
359 |
$crit->not = $not;
|
|
|
360 |
$crit->param = $v;
|
|
|
361 |
$args[] = $crit;
|
|
|
362 |
} else {
|
|
|
363 |
if ($var->type != 'texte') {
|
|
|
364 |
// cas 1 seul arg ne commencant pas par du texte brut:
|
|
|
365 |
// erreur ou critere infixe "/"
|
|
|
366 |
if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) !='/'))
|
|
|
367 |
erreur_squelette('criteres',$var->nom_champ);
|
|
|
368 |
else {
|
|
|
369 |
$crit = new Critere;
|
|
|
370 |
$crit->op = '/';
|
|
|
371 |
$crit->not = "";
|
|
|
372 |
$crit->param = array(array($v[1][0]),array($v[1][2]));
|
|
|
373 |
$args[] = $crit;
|
|
|
374 |
}
|
|
|
375 |
} else {
|
|
|
376 |
// traiter qq lexemes particuliers pour faciliter la suite
|
|
|
377 |
|
|
|
378 |
// les separateurs
|
|
|
379 |
if ($var->apres)
|
|
|
380 |
$result->separateur[] = $param;
|
|
|
381 |
elseif (($param == 'tout') OR ($param == 'tous'))
|
|
|
382 |
$result->tout = true;
|
|
|
383 |
elseif ($param == 'plat')
|
|
|
384 |
$result->plat = true;
|
|
|
385 |
|
|
|
386 |
// Boucle hierarchie, analyser le critere id_article - id_rubrique
|
|
|
387 |
// - id_syndic, afin, dans les cas autres que {id_rubrique}, de
|
|
|
388 |
// forcer {tout} pour avoir la rubrique mere...
|
|
|
389 |
|
|
|
390 |
elseif (($type == 'hierarchie') &&
|
|
|
391 |
($param == 'id_article' OR $param == 'id_syndic'))
|
|
|
392 |
$result->tout = true;
|
|
|
393 |
elseif (($type == 'hierarchie') && ($param == 'id_rubrique'))
|
|
|
394 |
{;}
|
|
|
395 |
else {
|
|
|
396 |
// pas d'emplacement statique, faut un dynamique
|
|
|
397 |
/// mais il y a 2 cas qui ont les 2 !
|
|
|
398 |
if (($param == 'unique') || (ereg('^!?doublons *', $param)))
|
|
|
399 |
{
|
|
|
400 |
// cette variable sera inseree dans le code
|
|
|
401 |
// et son nom sert d'indicateur des maintenant
|
|
|
402 |
$result->doublons = '$doublons_index';
|
|
|
403 |
if ($param == 'unique') $param = 'doublons';
|
|
|
404 |
}
|
|
|
405 |
elseif ($param == 'recherche')
|
|
|
406 |
// meme chose (a cause de #nom_de_boucle:URL_*)
|
|
|
407 |
$result->hash = true;
|
|
|
408 |
if (ereg('^ *([0-9-]+) *(/) *(.+) *$', $param, $m)) {
|
|
|
409 |
$crit = phraser_critere_infixe($m[1], $m[3],$v, '/', '', '');
|
|
|
410 |
} elseif (ereg('^(`?[A-Za-z_][A-Za-z_0-9]*\(?[A-Za-z_]*\)?`?)[[:space:]]*(\??)(!?)(<=?|>=?|==?|IN)[[:space:]]*"?([^<>=!"]*)"?$', $param, $m)) {
|
|
|
411 |
$crit = phraser_critere_infixe($m[1], $m[5],$v,
|
|
|
412 |
(($m[1] == 'lang_select') ? $m[1] : trim($m[4])),
|
|
|
413 |
$m[3], $m[2]);
|
|
|
414 |
} elseif (preg_match("/^([!]?)[[:space:]]*([A-Za-z_][A-Za-z_0-9]*)[[:space:]]*(\??)(.*)$/ism", $param, $m)) {
|
|
|
415 |
// contient aussi les comparaisons implicites !
|
|
|
416 |
array_shift($v);
|
|
|
417 |
if ($m[4])
|
|
|
418 |
$v[0][0]->texte = $m[4];
|
|
|
419 |
else {
|
|
|
420 |
array_shift($v[0]);
|
|
|
421 |
if (!$v[0]) array_shift($v);
|
|
|
422 |
}
|
|
|
423 |
$crit = new Critere;
|
|
|
424 |
$crit->op = $m[2];
|
|
|
425 |
$crit->param = $v;
|
|
|
426 |
$crit->not = $m[1];
|
|
|
427 |
$crit->cond = $m[3];
|
|
|
428 |
}
|
|
|
429 |
else {
|
|
|
430 |
erreur_squelette(_T('zbug_critere_inconnu',
|
|
|
431 |
array('critere' => $param)));
|
|
|
432 |
}
|
|
|
433 |
$args[] = $crit;
|
|
|
434 |
}
|
|
|
435 |
}
|
|
|
436 |
}
|
|
|
437 |
}
|
|
|
438 |
|
|
|
439 |
$result->criteres = $args;
|
|
|
440 |
}
|
|
|
441 |
|
|
|
442 |
function phraser_critere_infixe($arg1, $arg2, $args, $op, $not, $cond)
|
|
|
443 |
{
|
|
|
444 |
$args[0] = new Texte;
|
|
|
445 |
$args[0]->texte = $arg1;
|
|
|
446 |
$args[0] = array($args[0]);
|
|
|
447 |
$args[1][0]->texte = $arg2;
|
|
|
448 |
$crit = new Critere;
|
|
|
449 |
$crit->op = $op;
|
|
|
450 |
$crit->not = $not;
|
|
|
451 |
$crit->cond = $cond;
|
|
|
452 |
$crit->param = $args;
|
|
|
453 |
return $crit;
|
|
|
454 |
}
|
|
|
455 |
|
|
|
456 |
function phraser($texte, $id_parent, &$boucles, $nom, $ligne=1) {
|
|
|
457 |
|
|
|
458 |
$all_res = array();
|
|
|
459 |
|
|
|
460 |
while (($p = strpos($texte, BALISE_BOUCLE)) !== false) {
|
|
|
461 |
|
|
|
462 |
$result = new Boucle;
|
|
|
463 |
$result->id_parent = $id_parent;
|
|
|
464 |
|
|
|
465 |
# attention: reperer la premiere des 2 balises: pre_boucle ou boucle
|
|
|
466 |
|
|
|
467 |
$n = ereg(BALISE_PRE_BOUCLE . '[0-9_]', $texte, $r);
|
|
|
468 |
if ($n) $n = strpos($texte, $r[0]);
|
|
|
469 |
if (($n === false) || ($n > $p)) {
|
|
|
470 |
$debut = substr($texte, 0, $p);
|
|
|
471 |
$milieu = substr($texte, $p);
|
|
|
472 |
$k = strpos($milieu, '(');
|
|
|
473 |
$id_boucle = trim(substr($milieu,
|
|
|
474 |
strlen(BALISE_BOUCLE),
|
|
|
475 |
$k - strlen(BALISE_BOUCLE)));
|
|
|
476 |
$milieu = substr($milieu, $k);
|
|
|
477 |
|
|
|
478 |
/* a adapter: si $n pointe sur $id_boucle ...
|
|
|
479 |
if (strpos($milieu, $s)) {
|
|
|
480 |
erreur_squelette(_T('zbug_erreur_boucle_syntaxe'),
|
|
|
481 |
$id_boucle .
|
|
|
482 |
_T('zbug_balise_b_aval'));
|
|
|
483 |
}
|
|
|
484 |
*/
|
|
|
485 |
} else {
|
|
|
486 |
$debut = substr($texte, 0, $n);
|
|
|
487 |
$milieu = substr($texte, $n);
|
|
|
488 |
$k = strpos($milieu, '>');
|
|
|
489 |
$id_boucle = substr($milieu,
|
|
|
490 |
strlen(BALISE_PRE_BOUCLE),
|
|
|
491 |
$k - strlen(BALISE_PRE_BOUCLE));
|
|
|
492 |
|
|
|
493 |
if (!ereg(BALISE_BOUCLE . $id_boucle . "[[:space:]]*\(", $milieu, $r))
|
|
|
494 |
erreur_squelette((_T('zbug_erreur_boucle_syntaxe')), $id_boucle);
|
|
|
495 |
$p = strpos($milieu, $r[0]);
|
|
|
496 |
$result->avant = substr($milieu, $k+1, $p-$k-1);
|
|
|
497 |
$milieu = substr($milieu, $p+strlen($id_boucle)+strlen(BALISE_BOUCLE));
|
|
|
498 |
}
|
|
|
499 |
$result->id_boucle = $id_boucle;
|
|
|
500 |
|
|
|
501 |
ereg(SPEC_BOUCLE, $milieu, $match);
|
|
|
502 |
$milieu = substr($milieu, strlen($match[0]));
|
|
|
503 |
$type = $match[1];
|
|
|
504 |
|
|
|
505 |
if ($p = strpos($type, ':'))
|
|
|
506 |
{
|
|
|
507 |
$result->sql_serveur = substr($type,0,$p);
|
|
|
508 |
$soustype = strtolower(substr($type,$p+1));
|
|
|
509 |
}
|
|
|
510 |
else
|
|
|
511 |
$soustype = strtolower($type);
|
|
|
512 |
|
|
|
513 |
if ($soustype == 'sites') $soustype = 'syndication' ; # alias
|
|
|
514 |
|
|
|
515 |
//
|
|
|
516 |
// analyser les criteres et distinguer la boucle recursive
|
|
|
517 |
//
|
|
|
518 |
if (substr($soustype, 0, 6) == TYPE_RECURSIF) {
|
|
|
519 |
$result->type_requete = TYPE_RECURSIF;
|
|
|
520 |
$result->param[0] = substr($type, strlen(TYPE_RECURSIF));
|
|
|
521 |
$milieu = substr($milieu, strpos($milieu, '>')+1);
|
|
|
522 |
$params = "";
|
|
|
523 |
} else {
|
|
|
524 |
$result->type_requete = $soustype;
|
|
|
525 |
phraser_args($milieu,">","",$all_res,$result);
|
|
|
526 |
$params = substr($milieu,0,strpos($milieu,$result->apres));
|
|
|
527 |
$milieu = substr($result->apres,1);
|
|
|
528 |
$result->apres = "";
|
|
|
529 |
phraser_criteres($result->param, $result);
|
|
|
530 |
}
|
|
|
531 |
|
|
|
532 |
//
|
|
|
533 |
// Recuperer la fin :
|
|
|
534 |
//
|
|
|
535 |
$s = BALISE_FIN_BOUCLE . $id_boucle . ">";
|
|
|
536 |
$p = strpos($milieu, $s);
|
|
|
537 |
if ($p === false) {
|
|
|
538 |
erreur_squelette(_T('zbug_erreur_boucle_syntaxe'),
|
|
|
539 |
_T('zbug_erreur_boucle_fermant',
|
|
|
540 |
array('id'=>$id_boucle)));
|
|
|
541 |
}
|
|
|
542 |
|
|
|
543 |
$suite = substr($milieu, $p + strlen($s));
|
|
|
544 |
$milieu = substr($milieu, 0, $p);
|
|
|
545 |
//
|
|
|
546 |
// 1. Recuperer la partie conditionnelle apres
|
|
|
547 |
//
|
|
|
548 |
$s = BALISE_POST_BOUCLE . $id_boucle . ">";
|
|
|
549 |
$p = strpos($suite, $s);
|
|
|
550 |
if ($p !== false) {
|
|
|
551 |
$result->apres = substr($suite, 0, $p);
|
|
|
552 |
$suite = substr($suite, $p + strlen($s));
|
|
|
553 |
}
|
|
|
554 |
|
|
|
555 |
//
|
|
|
556 |
// 2. Recuperer la partie alternative
|
|
|
557 |
//
|
|
|
558 |
$s = BALISE_ALT_BOUCLE . $id_boucle . ">";
|
|
|
559 |
$p = strpos($suite, $s);
|
|
|
560 |
if ($p !== false) {
|
|
|
561 |
$result->altern = substr($suite, 0, $p);
|
|
|
562 |
$suite = substr($suite, $p + strlen($s));
|
|
|
563 |
}
|
|
|
564 |
$result->ligne = $ligne + substr_count($debut, "\n");
|
|
|
565 |
$m = substr_count($milieu, "\n");
|
|
|
566 |
$b = substr_count($result->avant, "\n");
|
|
|
567 |
$a = substr_count($result->apres, "\n");
|
|
|
568 |
|
|
|
569 |
// envoyer la boucle au debugueur
|
|
|
570 |
if ($GLOBALS['var_mode']== 'debug') {
|
|
|
571 |
boucle_debug ($nom, $id_parent, $id_boucle,
|
|
|
572 |
$type,
|
|
|
573 |
$params,
|
|
|
574 |
$result->avant,
|
|
|
575 |
$milieu,
|
|
|
576 |
$result->apres,
|
|
|
577 |
$result->altern);
|
|
|
578 |
}
|
|
|
579 |
|
|
|
580 |
$result->avant = phraser($result->avant, $id_parent,$boucles, $nom, $result->ligne);
|
|
|
581 |
$result->apres = phraser($result->apres, $id_parent,$boucles, $nom, $result->ligne+$b+$m);
|
|
|
582 |
$result->altern = phraser($result->altern,$id_parent,$boucles, $nom, $result->ligne+$a+$m+$b);
|
|
|
583 |
$result->milieu = phraser($milieu, $id_boucle,$boucles, $nom, $result->ligne+$b);
|
|
|
584 |
|
|
|
585 |
if ($boucles[$id_boucle]) {
|
|
|
586 |
erreur_squelette(_T('zbug_erreur_boucle_syntaxe'),
|
|
|
587 |
_T('zbug_erreur_boucle_double',
|
|
|
588 |
array('id'=>$id_boucle)));
|
|
|
589 |
} else
|
|
|
590 |
$boucles[$id_boucle] = $result;
|
|
|
591 |
$all_res = phraser_champs_etendus($debut, $ligne, $all_res);
|
|
|
592 |
$all_res[] = $result;
|
|
|
593 |
$ligne += substr_count(substr($texte, 0, strpos($texte, $suite)), "\n");
|
|
|
594 |
$texte = $suite;
|
|
|
595 |
}
|
|
|
596 |
return phraser_champs_etendus($texte, $ligne, $all_res);
|
|
|
597 |
}
|
|
|
598 |
?>
|