Changeset 43155 in spip-zone


Ignore:
Timestamp:
Dec 26, 2010, 10:27:26 PM (10 years ago)
Author:
fil@…
Message:

backport des modifs dev pour les iterateurs

Location:
_plugins_/iterateurs/public
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/iterateurs/public/compiler.php

    r43154 r43155  
    190190}
    191191
    192 //
    193 // calculer_boucle() produit le corps PHP d'une boucle Spip.
    194 // ce corps remplit une variable $t0 retournee en valeur.
    195 // Ici on distingue boucles recursives et boucle a requete SQL
    196 // et on insere le code d'envoi au debusqueur du resultat de la fonction.
    197 
    198 // http://doc.spip.org/@calculer_boucle
     192
     193/**
     194 * Calculer la clause where pour filtrer les status,
     195 *
     196 * @param string $mstatut
     197 *  le champ de la table sur lequel porte la condition
     198 * @param string $liste
     199 *  statut ou liste des statuts separes par une virgule
     200 * @return array
     201 */
     202function calculer_where_statut($mstatut,$liste){
     203        $not = false;
     204        if (strncmp($liste,'!',1)==0){
     205                $not = true;
     206          $liste = substr($liste,1);
     207        }
     208        // '' => ne rien afficher, '!'=> ne rien filtrer
     209        if (!strlen($liste))
     210                return ($not?"'1=1'":"'0=1'");
     211
     212        $liste = explode(',',$liste);
     213        foreach($liste as $k=>$v) {
     214                $liste[$k] = "\\'".preg_replace(",\W,","",$v)."\\'";
     215        }
     216  if (count($liste)==1){
     217                return array($not?"'<>'":"'='", "'$mstatut'", "'".reset($liste)."'");
     218  }
     219  else {
     220          return array($not?"'NOT IN'":"'IN'", "'$mstatut'", "'(".implode(',',$liste).")'");
     221  }
     222}
     223
     224/**
     225 * calculer_boucle() produit le corps PHP d'une boucle Spip.
     226 * ce corps remplit une variable $t0 retournee en valeur.
     227 * Ici on distingue boucles recursives et boucle a requete SQL
     228 * et on insere le code d'envoi au debusqueur du resultat de la fonction.
     229 *
     230 * http://doc.spip.org/@calculer_boucle
     231 *
     232 * @param  $id_boucle
     233 * @param  $boucles
     234 * @return string
     235 */
    199236function calculer_boucle($id_boucle, &$boucles) {
     237
     238        // gerer les statuts si declares pour cette table
     239        /*
     240        $table_statut[nom_table][] = array(
     241                'champ'=>'statut',  // champ de la table sur lequel porte le filtrage par le statut
     242                'publie'=>'publie', // valeur ou liste de valeurs, qui definissent l'objet comme publie.
     243                'previsu'=>'publie,prop', // valeur ou liste de valeurs qui sont visibles en previsu
     244                'post_date'=>'date', // un champ de date pour la prise en compte des post_dates, ou rien sinon
     245          'exception'=>'statut', // liste des modificateurs qui annulent le filtrage par statut
     246                                 // si plusieurs valeurs : array('statut','tout','lien')
     247        );
     248
     249        Pour 'publier' ou 'previsu', si la chaine commence par un "!" on exclu au lieu de filtrer sur les valeurs donnees
     250        si la chaine est vide, on ne garde rien si elle est seulement "!" on n'exclu rien
     251
     252        Si le statut repose sur une jointure, 'champ' est alors un tableau du format suivant :
     253        'champ'=>array(
     254            array(table1, cle1),
     255            ...
     256            array(tablen, clen),
     257            champstatut
     258         )
     259
     260        champstatut est alors le champ statut sur la tablen
     261        dans les jointures, clen peut etre un tableau pour une jointure complexe : array('id_objet','id_article','objet','article')     
     262        */
     263
     264        $boucle = &$boucles[$id_boucle];
     265        $id_table = $boucle->id_table;
     266        $table_sql = $boucle->from[$id_table];
     267        if (isset($GLOBALS['table_statut'][$table_sql])){
     268                foreach($GLOBALS['table_statut'][$table_sql] as $s){
     269                        // Restreindre aux elements publies si pas de {statut} ou autre dans les criteres
     270                        $filtrer = true;
     271                        if (isset($s['exception'])) {
     272                                foreach(is_array($s['exception'])?$s['exception']:array($s['exception']) as $m) {
     273                                        if (isset($boucle->modificateur[$m]) OR isset($boucle->modificateur['criteres'][$m])) {
     274                                                $filtrer = false;
     275                                                break;
     276                                        }
     277                                }
     278                        }
     279
     280                        if ($filtrer) {
     281                                if (is_array($s['champ'])){
     282                                        $statut = preg_replace(',\W,','',array_pop($s['champ'])); // securite
     283                                        $jointures = array();
     284                                        foreach($s['champ'] as $j) {
     285                                                $jointures[] = array('',array($id=reset($j)),end($j));
     286                                        }
     287                                        $jointures[0][0] = $id_table;
     288                                        if (!array_search($id, $boucle->from)){
     289                                                fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table);
     290                                        }
     291                                        // trouver l'alias de la table d'arrivee qui porte le statut
     292                                        $id = array_search($id, $boucle->from);
     293                                }
     294                                else {
     295                                        $id = $id_table;
     296                                        $statut = preg_replace(',\W,','',$s['champ']); // securite
     297                                }
     298                                $mstatut = $id .'.'.$statut;
     299
     300                                if (!$GLOBALS['var_preview']) {
     301                                        if (isset($s['post_date']) AND $s['post_date']
     302                                                AND $GLOBALS['meta']["post_dates"] == 'non'){
     303                                                $date = $id.'.'.preg_replace(',\W,','',$s['post_date']); // securite
     304                                                array_unshift($boucle->where,"quete_condition_postdates('$date')");
     305                                        }
     306                                        array_unshift($boucle->where,calculer_where_statut($mstatut,$s['publie']));
     307                                }
     308                                else {
     309                                        array_unshift($boucle->where,calculer_where_statut($mstatut,$s['previsu']));
     310                                }
     311                        }
     312                }
     313        }
     314
     315
    200316
    201317        $boucles[$id_boucle] = pipeline('post_boucle', $boucles[$id_boucle]);
     
    243359        $t0 = "";
    244360        // REQUETE
    245         $result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect,
    246                  array(%s));
    247         if ($result) {
     361        $iter = IterFactory::create(
     362                "%s",
     363                %s,
     364                array(%s)
     365        );
     366        if (!$iter->err()) {
    248367        %s%s$SP++;
    249368        // RESULTATS
    250369        %s
    251         %s@sql_free($result%s);
     370        %s$iter->free();
    252371        }%s
    253372        return $t0;'
     
    273392
    274393        // La boucle doit-elle selectionner la langue ?
    275         // -. par defaut, les boucles suivantes le font
     394        // - par defaut, les boucles suivantes le font
    276395        //    (sauf si forcer_lang==true ou si le titre contient <multi>).
    277         // - . a moins d'une demande explicite via {!lang_select}
     396        // - a moins d'une demande explicite via {!lang_select}
    278397        if (!$constant && $boucle->lang_select != 'non' &&
    279398            (($boucle->lang_select == 'oui')  ||
     
    343462                . $corps;
    344463
    345         $serveur = !$boucle->sql_serveur ? ''
    346                 : (', ' . _q($boucle->sql_serveur));
    347 
    348464        // si le corps est une constante, ne pas appeler le serveur N fois!
    349465
     
    358474                        $corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);";
    359475                }
    360         } else $corps = "while (\$Pile[\$SP] = @sql_fetch(\$result$serveur)) {\n$corps\n        }";
     476        } else $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n       }";
    361477
    362478        $count = '';
     
    375491        if ($boucle->numrows OR $boucle->mode_partie) {
    376492                if ($count == 'count(*)')
    377                         $count = "array_shift(sql_fetch(\$result$serveur))";
    378                 else $count = "sql_count(\$result$serveur)";
     493                        $count = "array_shift(\$iter->next())";
     494                else $count = "\$iter->count()";
    379495                $nums .= "\$Numrows['$id_boucle']['total'] = @intval($count);"
    380496                . $boucle->mode_partie
     
    391507        $contexte = memoriser_contexte_compil($boucle);
    392508
    393         return sprintf(CODE_CORPS_BOUCLE, $init, $contexte, $nums, $init_lang, $corps, $fin_lang, $serveur, $trace);
     509        $a = sprintf(CODE_CORPS_BOUCLE,
     510                $init,
     511                $boucle->iterateur,
     512                "\$command",
     513                $contexte,
     514                $nums,
     515                $init_lang,
     516                $corps,
     517                $fin_lang,
     518                $trace
     519        );
     520
     521#       var_dump($a);exit;
     522        return $a;
    394523}
    395524
     
    401530          . $boucle->in
    402531          . $boucle->hash
    403           . calculer_dec('$table',  "'" . $boucle->id_table ."'")
    404           . calculer_dec('$id', "'" . $boucle->id_boucle ."'")
     532          . calculer_dec('table',  "'" . $boucle->id_table ."'")
     533          . calculer_dec('id', "'" . $boucle->id_boucle ."'")
    405534                # En absence de champ c'est un decompte :
    406           . calculer_dec('$from',  calculer_from($boucle))
    407           . calculer_dec('$type', calculer_from_type($boucle))
    408           . calculer_dec('$groupby', 'array(' . (($g=join("\",\n\t\t\"",$boucle->group))?'"'.$g.'"':'') . ")")
    409           . calculer_dec('$select', 'array("' . join("\",\n\t\t\"", $boucle->select).  "\")")
    410           . calculer_dec('$orderby', 'array(' . calculer_order($boucle) .       ")")
    411           . calculer_dec('$where', calculer_dump_array($boucle->where))
    412           . calculer_dec('$join', calculer_dump_join($boucle->join))
    413           . calculer_dec('$limit', (strpos($boucle->limit, 'intval') === false ?
     535          . calculer_dec('from',  calculer_from($boucle))
     536          . calculer_dec('type', calculer_from_type($boucle))
     537          . calculer_dec('groupby', 'array(' . (($g=join("\",\n\t\t\"",$boucle->group))?'"'.$g.'"':'') . ")")
     538          . calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select).  "\")")
     539          . calculer_dec('orderby', 'array(' . calculer_order($boucle) .        ")")
     540          . calculer_dec('where', calculer_dump_array($boucle->where))
     541          . calculer_dec('join', calculer_dump_join($boucle->join))
     542          . calculer_dec('limit', (strpos($boucle->limit, 'intval') === false ?
    414543                                    "'".$boucle->limit."'" :
    415544                                    $boucle->limit))
    416           . calculer_dec('$having', calculer_dump_array($boucle->having));
     545          . calculer_dec('having', calculer_dump_array($boucle->having));
    417546}
    418547
     
    442571function calculer_dec($nom, $val)
    443572{
    444         $static = "static ";
    445   if (
    446     strpos($val, '$') !== false
    447     OR strpos($val, 'sql_') !== false
    448     OR (
    449         $test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
    450         AND strpos($test,"(")!==FALSE // si pas de parenthese ouvrante, pas de fonction, on peut sortir
    451         AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
    452         AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
    453     )
    454     ){
    455     $static = "";
    456   }
    457   return "\n\t" . $static . $nom . ' = ' . $val . ';';
     573        $static = 'if (!isset($command[\''.$nom.'\'])) ';
     574        if (
     575                strpos($val, '$') !== false
     576                OR strpos($val, 'sql_') !== false
     577                OR (
     578                        $test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
     579                        AND strpos($test,"(")!==FALSE // si pas de parenthese ouvrante, pas de fonction, on peut sortir
     580                        AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
     581                        AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
     582                )
     583        )
     584                $static = "";
     585
     586        return "\n\t" . $static . '$command[\''.$nom.'\'] = ' . $val . ';';
    458587}
    459588
     
    835964                        // c'est peut etre une table qui necessite son connecteur dedie fourni
    836965                        // permet une ecriture allegee (GEO) -> (geo:GEO)
    837                         if (!$show AND $show=$trouver_table($type, strtolower($type)))
     966                        if (!$show
     967                        AND $show=$trouver_table($type, strtolower($type))) {
    838968                                $boucles[$id]->sql_serveur = strtolower($type);
    839                         if ($show) {
     969                        }
     970
     971                        // chercher dans les iterateurs du repertoire iterateur/
     972                        if ($g = charger_fonction(
     973                        preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true)) {
     974                                $boucles[$id] = $g($boucle);
     975
     976                        // sinon, en cas de requeteur "php" existe-t-il un iterateur PHP
     977                        } else if ($boucle->sql_serveur == 'php') {
     978                                if (class_exists($boucle->type_requete)) {
     979                                        $g = charger_fonction('php', 'iterateur');
     980                                        $boucles[$id] = $g($boucle, $boucle->type_requete);
     981                                } else {
     982                                        $x = $boucle->type_requete;
     983                                        $boucle->type_requete = false;
     984                                        $msg = array('zbug_iterateur_inconnu',
     985                                                        array('iterateur' => $x));
     986                                        erreur_squelette($msg, $boucle);
     987                                }
     988                        // utiliser la description des champs transmis
     989                        } else if ($show) {
    840990                                $boucles[$id]->show = $show;
    841991                                // recopie les infos les plus importantes
     
    843993                                $boucles[$id]->id_table = $x = $show['id_table'];
    844994                                $boucles[$id]->from[$x] = $nom_table = $show['table'];
     995                                $boucles[$id]->iterateur = 'SQL';
    845996
    846997                                $boucles[$id]->descr = &$descr;
     
    9401091                        if (!function_exists($f)) $f = 'boucle_DEFAUT';
    9411092                        if (!function_exists($f)) $f = 'boucle_DEFAUT_dist';
    942                         $req = "\n\n\tstatic \$connect = " .
     1093                        $req = "\n\n\tstatic \$command = array();\n\t\$command['connect'] = " .
    9431094                                _q($boucle->sql_serveur) .
    9441095                                ";" .
  • _plugins_/iterateurs/public/criteres.php

    r43154 r43155  
    928928                  if (!$table) return '';
    929929        }
    930         elseif (@!array_key_exists($col, $desc['field'])) {
     930        elseif (@!array_key_exists($col, $desc['field'])
     931        AND @!array_key_exists('*', $desc['field'])) {
    931932                $r = calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table);
    932933                if (!$r) return '';
  • _plugins_/iterateurs/public/interfaces.php

    r43154 r43155  
    1010 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
    1111\***************************************************************************/
    12 
    1312
    1413if (!defined('_ECRIRE_INC_VERSION')) return;
     
    8180        var $ligne = 0;
    8281        var $descr =  array(); # noms des fichiers source et but etc
     82        var $iterateur = ''; // type d'iterateur
    8383
    8484        var $modificateur = array(); // table pour stocker les modificateurs de boucle tels que tout, plat ..., utilisable par les plugins egalement
  • _plugins_/iterateurs/public/phraser_html.php

    r43154 r43155  
    3636
    3737define('SQL_ARGS', '(\([^)]*\))');
    38 define('CHAMP_SQL_PLUS_FONC', '`?([A-Z_][A-Z_0-9.]*)' . SQL_ARGS . '?`?');
     38define('CHAMP_SQL_PLUS_FONC', '`?([A-Z_\/][A-Z_\/0-9.]*)' . SQL_ARGS . '?`?');
    3939
    4040// http://doc.spip.org/@phraser_inclure
     
    448448// detecter comme on peut si c'est le critere implicite LIMIT debut, fin
    449449
    450                         if (($var->type != 'texte') ||
    451                             (strpos("0123456789-", $param[strlen($param)-1])
    452                              !== false)) {
     450                        if ($var->type != 'texte'
     451                        OR preg_match("/^(n|(n-)?\d+)$/S", $param)) {
    453452                          $op = ',';
    454453                          $not = "";
     
    462461                          // Recopier pour ne pas alterer le texte source
    463462                          // utile au debusqueur
    464 
    465463                          if ($m[3]) {
     464                            // une maniere tres sale de supprimer les "' autour de {critere "xxx","yyy"}
     465                            if (preg_match(',^(["\'])(.*)\1$,', $m[3])) {
     466                                $c = null;
     467                                eval ('$c = '.$m[3].';');
     468                                if (isset($c))
     469                                        $m[3] = $c;
     470                            }
    466471                            $texte = new Texte;
    467472                            $texte->texte = $m[3];
  • _plugins_/iterateurs/public/references.php

    r43154 r43155  
    8383                        $t = $boucles[$idb]->id_table;
    8484                        return array("$t.$nom_champ", $nom_champ);
     85                } else if (isset($desc['field']['*'])) {
     86                        $t = $boucles[$idb]->id_table;
     87                        return array($nom_champ, $nom_champ);
    8588                } else {
    8689                  if ($boucles[$idb]->jointures_explicites) {
Note: See TracChangeset for help on using the changeset viewer.