source: spip-zone/_plugins_/iterateurs/public/phraser_html.php @ 68178

Last change on this file since 68178 was 68178, checked in by esj@…, 7 years ago

iterateurs: ne redéfinir que les fonctions qui changent afin d'hériter de toute modif dans le phraseur standard.

File size: 11.3 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2011                                                *
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
14if (!defined('_ECRIRE_INC_VERSION')) return;
15
16include(_DIR_RESTREINT . 'public/phraser_html.php');
17
18define('CHAMP_SQL_PLUS_FONC', '`?([A-Z_\/][A-Z_\/0-9.]*)' . SQL_ARGS . '?`?');
19
20// analyse des criteres de boucle,
21
22// http://doc.spip.org/@phraser_criteres
23function phraser_criteres_iterateurs($params, &$result) {
24
25        $err_ci = ''; // indiquera s'il y a eu une erreur
26        $args = array();
27        $type = $result->type_requete;
28        $doublons = array();
29        foreach($params as $v) {
30                $var = $v[1][0];
31                $param = ($var->type != 'texte') ? "" : $var->texte;
32                if ((count($v) > 2) && (!preg_match(",[^A-Za-z]IN[^A-Za-z],i",$param)))
33                  {
34// plus d'un argument et pas le critere IN:
35// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
36
37                        if ($var->type != 'texte'
38                        OR preg_match("/^(n|(n-)?\d+)$/S", $param)) {
39                          $op = ',';
40                          $not = "";
41                        } else {
42                          // Le debut du premier argument est l'operateur
43                          preg_match("/^([!]?)([a-zA-Z][a-zA-Z0-9]*)[[:space:]]*(.*)$/ms", $param, $m);
44                          $op = $m[2];
45                          $not = $m[1];
46                          // virer le premier argument,
47                          // et mettre son reliquat eventuel
48                          // Recopier pour ne pas alterer le texte source
49                          // utile au debusqueur
50                          if ($m[3]) {
51                            // une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
52                            if (preg_match(',^(["\'])(.*)\1$,', $m[3])) {
53                                $c = null;
54                                eval ('$c = '.$m[3].';');
55                                if (isset($c))
56                                        $m[3] = $c;
57                            }
58                            $texte = new Texte;
59                            $texte->texte = $m[3]; 
60                            $v[1][0]= $texte;
61                          } else array_shift($v[1]);
62                        }
63                        array_shift($v); // $v[O] est vide
64                        $crit = new Critere;
65                        $crit->op = $op;
66                        $crit->not = $not;
67                        $crit->exclus ="";
68                        $crit->param = $v;
69                        $args[] = $crit;
70                  } else {
71                  if ($var->type != 'texte') {
72                    // cas 1 seul arg ne commencant pas par du texte brut:
73                    // erreur ou critere infixe "/"
74                    if (($v[1][1]->type != 'texte') || (trim($v[1][1]->texte) !='/')) {
75                        $err_ci = array('zbug_critere_inconnu', 
76                                        array('critere' => $var->nom_champ));
77                        erreur_squelette($err_ci, $result);
78                    } else {
79                      $crit = new Critere;
80                      $crit->op = '/';
81                      $crit->not = "";
82                      $crit->exclus ="";
83                      $crit->param = array(array($v[1][0]),array($v[1][2]));
84                      $args[] = $crit;
85                    }
86                  } else {
87        // traiter qq lexemes particuliers pour faciliter la suite
88        // les separateurs
89                        if ($var->apres)
90                                $result->separateur[] = $param;
91                        elseif (($param == 'tout') OR ($param == 'tous'))
92                                $result->modificateur['tout'] = true;
93                        elseif ($param == 'plat') 
94                                $result->modificateur['plat'] = true;
95
96        // Boucle hierarchie, analyser le critere id_article - id_rubrique
97        // - id_syndic, afin, dans les cas autres que {id_rubrique}, de
98        // forcer {tout} pour avoir la rubrique mere...
99
100                        elseif (!strcasecmp($type, 'hierarchie') AND
101                                ($param == 'id_article' OR $param == 'id_syndic'))
102                                $result->modificateur['tout'] = true;
103                        elseif (!strcasecmp($type, 'hierarchie') AND ($param == 'id_rubrique'))
104                                {;}
105                        else {
106                          // pas d'emplacement statique, faut un dynamique
107                          /// mais il y a 2 cas qui ont les 2 !
108                          if (($param == 'unique') || (preg_match(',^!?doublons *,', $param)))
109                            {
110                              // cette variable sera inseree dans le code
111                              // et son nom sert d'indicateur des maintenant
112                              $result->doublons = '$doublons_index';
113                              if ($param == 'unique') $param = 'doublons';
114                            }
115                          elseif ($param == 'recherche')
116                            // meme chose (a cause de #nom_de_boucle:URL_*)
117                              $result->hash = ' ';
118                          if (preg_match(',^ *([0-9-]+) *(/) *(.+) *$,', $param, $m)) {
119                            $crit = phraser_critere_infixe($m[1], $m[3],$v, '/', '', '');
120                          } elseif (preg_match(',^([!]?)(' . CHAMP_SQL_PLUS_FONC . 
121                                         ')[[:space:]]*(\??)(!?)(<=?|>=?|==?|\b(?:IN|LIKE)\b)(.*)$,is', $param, $m)) {
122                            $a2 = trim($m[8]);
123                            if ($a2 AND ($a2[0]=="'" OR $a2[0]=='"') AND ($a2[0]==substr($a2,-1)))
124                              $a2 = substr($a2,1,-1);
125                            $crit = phraser_critere_infixe($m[2], $a2, $v,
126                                                           (($m[2] == 'lang_select') ? $m[2] : $m[7]),
127                                                           $m[6], $m[5]);
128                                        $crit->exclus = $m[1];
129                          } elseif (preg_match("/^([!]?)\s*(" .
130                                               CHAMP_SQL_PLUS_FONC .
131                                               ")\s*(\??)(.*)$/is", $param, $m)) {
132                  // contient aussi les comparaisons implicites !
133                            // Comme ci-dessus:
134                            // le premier arg contient l'operateur
135                            array_shift($v);
136                            if ($m[6]) {
137                              $v[0][0] = new Texte;
138                              $v[0][0]->texte = $m[6];
139                            } else {
140                              array_shift($v[0]);
141                              if (!$v[0]) array_shift($v);
142                            }
143                            $crit = new Critere;
144                            $crit->op = $m[2];
145                            $crit->param = $v;
146                            $crit->not = $m[1];
147                            $crit->cond = $m[5];
148                          }
149                          else {
150                                $err_ci = array('zbug_critere_inconnu', 
151                                        array('critere' => $param));
152                                erreur_squelette($err_ci, $result);
153                          }
154                          if ((!preg_match(',^!?doublons *,', $param)) || $crit->not)
155                            $args[] = $crit;
156                          else 
157                            $doublons[] = $crit;
158                        }
159                  }
160                }
161        }
162        // les doublons non nies doivent etre le dernier critere
163        // pour que la variable $doublon_index ait la bonne valeur
164        // cf critere_doublon
165        if ($doublons) $args= array_merge($args, $doublons);
166        // Si erreur, laisser la chaine dans ce champ pour le HTTP 503
167        if (!$err_ci) $result->criteres = $args;
168}
169
170function public_phraser_html($texte, $id_parent, &$boucles, $descr, $ligne=1) {
171
172        $all_res = array();
173
174        while (($pos_boucle = strpos($texte, BALISE_BOUCLE)) !== false) {
175
176                $err_b = ''; // indiquera s'il y a eu une erreur
177                $result = new Boucle;
178                $result->id_parent = $id_parent;
179                $result->descr = $descr;
180# attention: reperer la premiere des 2 balises: pre_boucle ou boucle
181
182                if (!preg_match(",".BALISE_PRE_BOUCLE . '[0-9_],', $texte, $r)
183                        OR ($n = strpos($texte, $r[0]))===false
184                        OR ($n > $pos_boucle) ) {
185                  $debut = substr($texte, 0, $pos_boucle);
186                  $milieu = substr($texte, $pos_boucle);
187                  $k = strpos($milieu, '(');
188                  $id_boucle = trim(substr($milieu,
189                                           strlen(BALISE_BOUCLE),
190                                           $k - strlen(BALISE_BOUCLE)));
191                  $milieu = substr($milieu, $k);
192
193                } else {
194                  $debut = substr($texte, 0, $n);
195                  $milieu = substr($texte, $n);
196                  $k = strpos($milieu, '>');
197                  $id_boucle = substr($milieu,
198                                       strlen(BALISE_PRE_BOUCLE),
199                                       $k - strlen(BALISE_PRE_BOUCLE));
200
201                  if (!preg_match(",".BALISE_BOUCLE . $id_boucle . "[[:space:]]*\(,", $milieu, $r)) {
202                        $err_b = array('zbug_erreur_boucle_syntaxe', array('id' => $id_boucle));
203                        erreur_squelette($err_b, $result);
204                  }
205                  $pos_boucle = $n;
206                  $n = strpos($milieu, $r[0]);
207                  $result->avant = substr($milieu, $k+1, $n-$k-1);
208                  $milieu = substr($milieu, $n+strlen($id_boucle)+strlen(BALISE_BOUCLE));
209                }
210                $result->id_boucle = $id_boucle;
211
212                preg_match(SPEC_BOUCLE, $milieu, $match);
213                $result->type_requete = $match[0];
214                $milieu = substr($milieu, strlen($match[0]));
215                $type = $match[1];
216                $jointures = trim($match[2]);
217                $table_optionnelle = ($match[3]);
218                if ($jointures) {
219                        // on affecte pas ici les jointures explicites, mais dans la compilation
220                        // ou elles seront completees des jointures declarees
221                        $result->jointures_explicites = $jointures;
222                }
223               
224                if ($table_optionnelle){
225                        $result->table_optionnelle = $type;
226                }
227               
228                // 1ere passe sur les criteres, vu comme des arguments sans fct
229                // Resultat mis dans result->param
230                phraser_args($milieu,"/>","",$all_res,$result);
231
232                // En 2e passe result->criteres contiendra un tableau
233                // pour l'instant on met le source (chaine) :
234                // si elle reste ici au final, c'est qu'elle contient une erreur
235                $result->criteres =  substr($milieu,0,@strpos($milieu,$result->apres));
236                $milieu = $result->apres;
237                $result->apres = "";
238
239                //
240                // Recuperer la fin :
241                //
242                if ($milieu[0] === '/') {
243                        $suite = substr($milieu,2);
244                        $milieu = '';
245                } else {
246                        $milieu = substr($milieu,1);
247                        $s = BALISE_FIN_BOUCLE . $id_boucle . ">";
248                        $p = strpos($milieu, $s);
249                        if ($p === false) {
250                                $err_b = array('zbug_erreur_boucle_fermant',
251                                        array('id' => $id_boucle));
252                                erreur_squelette($err_b, $result);
253                        }
254
255                        $suite = substr($milieu, $p + strlen($s));
256                        $milieu = substr($milieu, 0, $p);
257                }
258
259                $result->milieu = $milieu;
260
261                //
262                // 1. Recuperer la partie conditionnelle apres
263                //
264                $s = BALISE_POST_BOUCLE . $id_boucle . ">";
265                $p = strpos($suite, $s);
266                if ($p !== false) {
267                        $result->apres = substr($suite, 0, $p);
268                        $suite = substr($suite, $p + strlen($s));
269                }
270
271                //
272                // 2. Recuperer la partie alternative
273                //
274                $s = BALISE_ALT_BOUCLE . $id_boucle . ">";
275                $p = strpos($suite, $s);
276                if ($p !== false) {
277                        $result->altern = substr($suite, 0, $p);
278                        $suite = substr($suite, $p + strlen($s));
279                }
280                $result->ligne = $ligne + substr_count($debut, "\n");
281                $m = substr_count($milieu, "\n");
282                $b = substr_count($result->avant, "\n");
283                $a = substr_count($result->apres, "\n");
284
285                if ($p = strpos($type, ':')) {
286                        $result->sql_serveur = substr($type,0,$p);
287                        $type = substr($type,$p+1);
288                }
289                $soustype = strtolower($type);
290                if ($soustype == 'sites') $soustype = 'syndication' ; # alias
291
292                if (!isset($GLOBALS["table_des_tables"][$soustype]))
293                        $soustype = $type;
294
295                $result->type_requete = $soustype;
296                // Lancer la 2e passe sur les criteres si la 1ere etait bonne
297                if (!is_array($result->param))
298                        $err_b = true;
299                else {
300                        phraser_criteres_iterateurs($result->param, $result);
301                        if (strncasecmp($soustype, TYPE_RECURSIF, strlen(TYPE_RECURSIF)) == 0) {
302                                $result->type_requete = TYPE_RECURSIF;
303                                $args = $result->param;
304                                array_unshift($args,
305                                        substr($type, strlen(TYPE_RECURSIF)));
306                                $result->param = $args;
307                        }
308                }
309
310                $result->avant = public_phraser_html_dist($result->avant, $id_parent,$boucles, $descr, $result->ligne);
311                $result->apres = public_phraser_html_dist($result->apres, $id_parent,$boucles, $descr, $result->ligne+$b+$m);
312                $result->altern = public_phraser_html_dist($result->altern,$id_parent,$boucles, $descr, $result->ligne+$a+$m+$b);
313                $result->milieu = public_phraser_html_dist($milieu, $id_boucle,$boucles, $descr, $result->ligne+$b);
314
315                // Prevenir le generateur de code que le squelette est faux
316                if ($err_b) $result->type_requete = false;
317
318                // Verifier qu'il n'y a pas double definition
319                // apres analyse des sous-parties (pas avant).
320               
321                if (isset($boucles[$id_boucle])) {
322                        $err_b_d = array('zbug_erreur_boucle_double',
323                                        array('id'=>$id_boucle));
324                        erreur_squelette($err_b_d, $result);
325                // Prevenir le generateur de code que le squelette est faux
326                        $boucles[$id_boucle]->type_requete = false;
327                } else
328                        $boucles[$id_boucle] = $result;
329                $all_res = phraser_champs_etendus($debut, $ligne, $all_res);
330                $all_res[] = &$boucles[$id_boucle];
331                $ligne += substr_count(substr($texte, 0, strpos($texte, $suite)), "\n");
332                $texte = $suite;
333        }
334
335        return phraser_champs_etendus($texte, $ligne, $all_res);
336}
337?>
Note: See TracBrowser for help on using the repository browser.