[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / spip-bonux / req / array.php
1 <?php
2 /**
3 * Plugin Spip 2.0 Reloaded
4 * Ce que vous ne trouverez pas dans Spip 2.0
5 * (c) 2008 Cedric Morin
6 * Licence GPL
7 *
8 */
9
10 if (!defined("_ECRIRE_INC_VERSION")) return;
11
12
13 global $array_server;
14
15 // fonction pour la premiere connexion a un serveur array
16 function req_array_dist($host, $port, $login, $pass, $db='', $prefixe='', $ldap='') {
17 $GLOBALS['array_rappel_nom_base'] = false;
18 # spip_log("Connexion vers $host, base $db, prefixe $prefixe "
19 # . ($ok ? "operationnelle sur $link" : 'impossible'));
20
21 return array(
22 'db' => $db,
23 'prefixe' => 'spip',
24 'link' => false,
25 'ldap' => '',
26 );
27 }
28
29 function array_get_var($table){
30 if (is_string($table) AND $t = unserialize($table))
31 $table = $t;
32 if(is_string($table) AND strpos($table,':')!==FALSE){
33 $iter = explode(':',$table);
34 if (count($iter)==2 AND is_numeric($iter[0]) AND is_numeric($iter[1]))
35 $var = range($iter[0],$iter[1]);
36 if (count($iter)==3 AND is_numeric($iter[0]) AND is_numeric($iter[1]) AND is_numeric($iter[2]))
37 $var = range($iter[0],$iter[2],$iter[1]);
38 return $var; // pas de copie necessaire
39 }
40 // $table doit toujours etre un array
41 if (!is_array($table)) return null;
42 // faisons une copie, sans le sous tableau recursif GLOBALS eventuel
43 $var = array();
44 foreach($table as $k=>$v)
45 if ($k !== 'GLOBALS')
46 $var[$k] = $v;
47 return $var;
48 }
49
50 function array_where_sql2php($where){
51 $where = preg_replace(",(^|\()([\w.]+)\s*REGEXP\s*(.+)($|\)),Uims","\\1preg_match('/'.str_replace('/','\/',\\3).'/Uims',\\2)\\4",$where); // == -> preg_match
52 $where = preg_replace(",([\w.]+)\s*=,Uims","\\1==",$where); // = -> ==
53 $where = preg_replace(";^FIELD\(([^,]+),(.*)$;Uims","in_array(\\1,array(\\2)",$where); // IN -> FIELD -> in_array()
54 $where = preg_replace(";(^|\(|\(\()([\w.]+)\s*IN\s*(.+)($|\)|\)\));Uims","in_array(\\2,array\\3",$where); // IN -> in_array()
55 return $where;
56 }
57
58 function array_where_teste($cle,$valeur,$table,$where){
59 if (is_array($valeur))
60 $valeur = serialize($valeur);
61 $where = preg_replace(array(
62 ",(\W)$table\.cle(\W),i",
63 ",(\W)cle(\W),i",
64 ",(\W)$table\.valeur(\W),i",
65 ",(\W)valeur(\W),i",
66 ',NOT\(,i'
67 ),
68 array(
69 "\\1'".addslashes($cle)."'\\2",
70 "\\1'".addslashes($cle)."'\\2",
71 "\\1'".addslashes($valeur)."'\\2",
72 "\\1'".addslashes($valeur)."'\\2",
73 "\\1!("
74 ),$where);
75 return eval("if ($where) return true; else return false;");
76 }
77
78
79 function calculer_array_where($v)
80 {
81 if (!is_array($v))
82 return array_where_sql2php($v) ;
83
84 $op = array_shift($v);
85 if (!($n=count($v)))
86 return $op;
87 else {
88 $arg = calculer_array_where(array_shift($v));
89 if ($n==1) {
90 return "$op($arg)";
91 } else {
92 $arg2 = calculer_array_where(array_shift($v));
93 if ($n==2) {
94 return array_where_sql2php("($arg $op $arg2)");
95 } else return "($arg $op ($arg2) : $v[0])";
96 }
97 }
98 }
99
100
101 function array_query_filter($cle,$valeur,$table,$where){
102 static $wherec = array();
103 $hash = md5(serialize($where));
104 if (!isset($wherec[$hash])){
105 if (is_array($where))
106 $wherec[$hash] = implode("AND ",array_map('calculer_array_where',$where));
107 else
108 $wherec[$hash] = calculer_array_where($where);
109 }
110 return array_where_teste($cle,$valeur,$table,$wherec[$hash]);
111 }
112
113 function array_results($hash,$store='get',$arg=null){
114 static $array_results = array();
115 if($store=='get'){
116 if (isset($array_results[$hash]['res'])){
117 return each($array_results[$hash]['res']);
118 }
119 if (isset($array_results[$hash]['iter'])) {
120 $pas = $array_results[$hash]['iter']['pas'];
121 $valeur = $array_results[$hash]['iter']['debut']+$array_results[$hash]['iter']['i']*$pas;
122 if (($valeur>$array_results[$hash]['iter']['fin'] AND $pas>0)
123 OR ($valeur<$array_results[$hash]['iter']['fin'] AND $pas<0))
124 return false;
125 return array(++$array_results[$hash]['iter']['i'],$valeur);
126 }
127 return false;
128 }
129 elseif($store=='seek'){
130 if (isset($array_results[$hash]['res'])){
131 // pas de seek sur les tableaux, on emule avec reset+n each
132 reset($array_results[$hash]['res']);
133 $i=0;
134 while ($i++<intval($arg))
135 each($array_results[$hash]['res']);
136 return true;
137 }
138 if (isset($array_results[$hash]['iter'])) {
139 $array_results[$hash]['iter']['i'] = intval($arg);
140 return true;
141 }
142 return false;
143 }
144 elseif($store=='count'){
145 if (isset($array_results[$hash]['res']))
146 return count($array_results[$hash]['res']);
147 if (isset($array_results[$hash]['iter']))
148 return floor(($array_results[$hash]['iter']['fin']-$array_results[$hash]['iter']['debut'])/$array_results[$hash]['iter']['pas'])+1;
149 return false;
150 }
151 elseif($store=='free')
152 unset($array_results[$hash]);
153 else {
154 $hash = count($array_results)?max(array_keys($array_results))+1:1; // pas de 0 svp
155 // un tableau direct
156 if (is_array($store)){
157 $array_results[$hash]['res'] = $store;
158 reset($array_results[$hash]['res']);
159 }
160 elseif(is_string($store) AND strpos($store,':')!==FALSE){
161 $iter = explode(':',$store);
162 if (count($iter)==2 OR count($iter)==3)
163 $array_results[$hash]['iter']=array('debut'=>reset($iter),'fin'=>end($iter),'pas'=>count($iter)==2?1:$iter[1],'i'=>0);
164 }
165 return $hash;
166 }
167 }
168
169 // emulations array
170 function array_query($query){
171 // pas de jointure, que des requetes simples
172 // trouver le tableau de base, fourni en condition having
173 // c'est un hack ...
174 $table = null;
175 if (!is_array($query['having'])) return -1; // on arrive pas ici par une boucle !
176 foreach($query['having'] as $k=>$w){
177 if (reset($w)=='tableau')
178 $table = end($w);
179 }
180 // recuperer le pseudo nom de la table pour la condition where
181 if (is_array($query['from']))
182 if (count($query['from'])!==1)
183 return false;
184 else
185 $query['from'] = reset($query['from']);
186
187 $res = array_get_var($table); // recuperer la table
188 if (!$res OR !is_array($res))
189 $res = array();
190 // filtrons les resultats
191 if ($query['where']){
192 foreach($res as $k=>$v){
193 if (!array_query_filter($k,$v,$query['from'],$query['where']))
194 unset($res[$k]);
195 }
196 }
197 if ($query['orderby']){
198 // on ne prend que le premier critere
199 $sort = is_array($query['orderby'])?reset($query['orderby']):$query['orderby'];
200 $sort = str_replace($query['from'].".","",$sort);
201 $sort = explode(',',$sort);
202 $sort = reset($sort);
203
204 // (POUR){par cle}
205 if (preg_match(',^cle,',$sort)){
206 if (preg_match(',DESC$,i',$sort))
207 krsort($res);
208 else
209 ksort($res);
210 }
211 // (POUR){par valeur}
212 else if (preg_match(',^valeur,',$sort)){
213 if (preg_match(',DESC$,i',$sort))
214 arsort($res);
215 else
216 asort($res);
217 }
218 // (POUR) {par XXX} : on considere que la valeur est un array,
219 // et on trie nos array sur leur valeur XXX ; si ce sont des objets
220 // on les caste en array
221 else {
222 preg_match(',^(.*)( DESC)?$,Ui', $sort, $tri);
223 $sens = $tri[2] ? '<' : '>';
224 uasort($res,
225 create_function('$a, $b',
226 'return ((is_string($a["'.$tri[1].'"]) AND is_string($b["'.$tri[1].'"]))?
227 (strcasecmp($a["'.$tri[1].'"],$b["'.$tri[1].'"])'.$sens.'0)
228 :((array)$a["'.$tri[1].'"] '.$sens.' (array) $b["'.$tri[1].'"]))
229 ? 1 : -1;'
230 )
231 );
232 }
233 }
234 if ($query['limit']){
235 $limit = explode(',',$query['limit']);
236 $res = array_slice($res,$limit[0],$limit[1],true);
237 }
238 // regarder si il y a un count dans select
239 foreach($query['select'] as $s){
240 if (preg_match(',^count\(,i',$s)) {
241 $res = array(0=>count($res));
242 continue;
243 }
244 }
245 // ici calculer un vrai res si la variable existe
246 if (count($res)) {
247 $hash = array_results(false,$res);
248 return $hash;
249 }
250 return -1; // pas de resultats mais pas false non plus
251 }
252
253 // -----
254
255 $GLOBALS['spip_array_functions_1'] = array(
256 'count' => 'spip_array_count',
257 'countsel' => 'spip_array_countsel',
258 'errno' => 'spip_array_errno',
259 'error' => 'spip_array_error',
260 'explain' => 'spip_array_explain',
261 'fetch' => 'spip_array_fetch',
262 'seek' => 'spip_array_seek',
263 'free' => 'spip_array_free',
264 'hex' => 'spip_array_hex',
265 'in' => 'spip_array_in',
266 'listdbs' => 'spip_array_listdbs',
267 'multi' => 'spip_array_multi',
268 'optimize' => 'spip_array_optimize',
269 'query' => 'spip_array_query',
270 'quote' => 'spip_array_quote',
271 'select' => 'spip_array_select',
272 'selectdb' => 'spip_array_selectdb',
273 'set_charset' => 'spip_array_set_charset',
274 'get_charset' => 'spip_array_get_charset',
275 'showbase' => 'spip_array_showbase',
276 'showtable' => 'spip_array_showtable',
277
278 );
279
280 function spip_array_set_charset($charset, $serveur=''){
281 #spip_log("changement de charset sql : "."SET NAMES "._q($charset));
282 return true;
283 }
284
285 function spip_array_get_charset($charset=array(), $serveur=''){
286 return false;
287 }
288
289 // Fonction de requete generale, munie d'une trace a la demande
290 function spip_array_query($query, $serveur='') {
291
292 $connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
293 $prefixe = $connexion['prefixe'];
294 $link = $connexion['link'];
295 $db = $connexion['db'];
296
297 $t = !isset($_GET['var_profile']) ? 0 : trace_query_start();
298 $r = array_query($query,$db);
299
300 if ($e = spip_array_errno()) // Log de l'erreur eventuelle
301 $e .= spip_array_error($query); // et du fautif
302 return $t ? trace_query_end(var_export($query,true), $t, $r, $e) : $r;
303 }
304
305
306 // fonction instance de sql_select, voir ses specs dans abstract.php
307 // Les \n et \t sont utiles au debusqueur.
308
309 function spip_array_select($select, $from, $where='',
310 $groupby='', $orderby='', $limit='', $having='',
311 $serveur='',$requeter=true) {
312
313 $from = (!is_array($from) ? $from : spip_array_select_as($from));
314
315 // pas de prefixage par nom de table dans array, une seule table a la fois !
316 $clean_prefix = trim($from).".";
317
318 $query = array(
319 'select'=>$select,
320 'from'=>$from,
321 'where'=>$where,
322 'groupby'=>$groupby,
323 'orderby'=>$orderby,
324 'limit'=>$limit);
325 $querydump = var_export($query,1);
326 $query['having'] = $having;
327
328 // Erreur ? C'est du debug de squelette, ou une erreur du serveur
329 if (isset($GLOBALS['var_mode'])
330 AND $GLOBALS['var_mode'] == 'debug'
331 AND function_exists('boucle_debug_requete')) {
332 include_spip('public/debug');
333 boucle_debug_requete($querydump);
334 }
335
336 $res = spip_array_query($query, $serveur);
337
338 if (!$res AND function_exists('boucle_debug_requete')) {
339 include_spip('public/debug');
340 erreur_requete_boucle($querydump,
341 spip_array_errno(),
342 spip_array_error($query) );
343 }
344
345 // renvoyer la requete inerte si demandee
346 if ($requeter === false) return $querydump;
347 return $res ? $res : $querydump;
348 }
349
350 // 0+x avec un champ x commencant par des chiffres est converti par array
351 // en le nombre qui commence x.
352 // Pas portable malheureusement, on laisse pour le moment.
353
354
355 function spip_array_order($orderby)
356 {
357 return (is_array($orderby)) ? join(", ", $orderby) : $orderby;
358 }
359
360
361 function spip_array_select_as($args)
362 {
363 $argsas = "";
364 foreach($args as $k => $v) {
365 if (strpos($v, 'JOIN') === false) $argsas .= ', ';
366 $argsas .= $v;// PAS de AS en array : . (is_numeric($k) ? '' : " AS `$k`");
367 }
368 return substr($argsas,2);
369 }
370
371
372 function spip_array_selectdb($db) {
373 return true;
374 }
375
376
377 // Retourne les bases accessibles
378 // Attention on n'a pas toujours les droits
379
380
381 function spip_array_listdbs($serveur='') {
382 return false;
383 }
384
385
386
387 function spip_array_showbase($match, $serveur='')
388 {
389 $res = array('pour'=>array('table'=>'pour'),'condition'=>array('table'=>'condition'));
390 $match = str_replace('_','.',$match);
391 $match = str_replace('%','.*',$match);
392 $match = str_replace('\.*','%',$match);
393 $match = str_replace('\.','_',$match);
394 $match = ",^$match$,i";
395 foreach(array_keys($res) as $k)
396 if (!preg_match($match,$k))
397 unset($res[$k]);
398
399 $hash = array_results(false,$res);
400 return $hash;
401 }
402
403
404 // pas fe SHOW en array, on renvoie une declaration type si la variable existe
405 function spip_array_showtable($nom_table, $serveur='')
406 {
407 if (in_array(strtolower($nom_table),array('pour')))
408 return array('field'=>array('cle'=>'text','valeur'=>'text'),'key'=>array('PRIMARY KEY'=>'cle'));
409 if (in_array(strtolower($nom_table),array('condition')))
410 return array('field'=>array('valeur'=>'text'),'key'=>array());
411 return false;
412 }
413
414 //
415 // Recuperation des resultats
416 //
417
418
419 function spip_array_fetch($r, $t='', $serveur='') {
420 if ($r AND $each = array_results($r)) {
421 list($cle,$valeur) = $each;
422 return array('valeur'=>$valeur,'cle'=>$cle);
423 }
424 return false;
425 }
426
427 function spip_array_seek($r, $row_number, $serveur='',$requeter=true) {
428 return array_results($r,'seek',$row_number);
429 }
430
431
432 function spip_array_error($query='') {
433 spip_log("Erreur - $query", 'array');
434 return false;
435 }
436
437 // A transposer dans les portages
438
439 function spip_array_errno() {
440 return false;
441 }
442
443 function spip_array_explain($query, $serveur='',$requeter=true){
444 return $query;
445 }
446
447 // Interface de abstract_sql
448
449 function spip_array_count($r, $serveur='') {
450 return array_results($r,'count');
451 }
452
453 function spip_array_countsel($from = array(), $where = array(),
454 $groupby = '', $limit = '', $sousrequete = '', $having = array(), $serveur='',$requeter=true)
455 {
456 $r = spip_array_select("*", $from, $where,'', '', $limit, $having, $serveur, $requeter);
457 if (!$requeter) return $r;
458 if (!$r) return 0;
459 list($c) = spip_array_count($r,$serveur);
460 spip_array_free($r,$serveur);
461 return $c;
462 }
463
464 function spip_array_free($r, $serveur='') {
465 array_results($r,'free');
466 return true;
467 }
468
469
470 function spip_array_multi ($objet, $lang) {
471 $retour = "(TRIM(IF(INSTR(".$objet.", '<multi>') = 0 , ".
472 " TRIM(".$objet."), ".
473 " CONCAT( ".
474 " LEFT(".$objet.", INSTR(".$objet.", '<multi>')-1), ".
475 " IF( ".
476 " INSTR(TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))),'[".$lang."]') = 0, ".
477 " IF( ".
478 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))) REGEXP '^\\[[a-z\_]{2,}\\]', ".
479 " INSERT( ".
480 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))), ".
481 " 1, ".
482 " INSTR(TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))), ']'), ".
483 " '' ".
484 " ), ".
485 " TRIM(RIGHT(".$objet.", LENGTH(".$objet.") -(6+INSTR(".$objet.", '<multi>')))) ".
486 " ), ".
487 " TRIM(RIGHT(".$objet.", ( LENGTH(".$objet.") - (INSTR(".$objet.", '[".$lang."]')+ LENGTH('[".$lang."]')-1) ) )) ".
488 " ) ".
489 " ) ".
490 "))) AS multi ";
491
492 return $retour;
493 }
494
495 function spip_array_hex($v)
496 {
497 return "0x" . $v;
498 }
499
500 function spip_array_quote($v)
501 {
502 return _q($v);
503 }
504
505 // pour compatibilite
506 function spip_array_in($val, $valeurs, $not='', $serveur='') {
507 return calcul_array_in($val, $valeurs, $not);
508 }
509
510 //
511 // IN (...) est limite a 255 elements, d'ou cette fonction assistante
512 //
513
514 function calcul_array_in($val, $valeurs, $not='') {
515 if (is_array($valeurs))
516 $valeurs = join(',', array_map('_q', $valeurs));
517 if (!strlen(trim($valeurs))) return ($not ? "0=0" : '0=1');
518
519 $n = $i = 0;
520 $in_sql ="";
521 while ($n = strpos($valeurs, ',', $n+1)) {
522 if ((++$i) >= 255) {
523 $in_sql .= "($val $not IN (" .
524 substr($valeurs, 0, $n) .
525 "))\n" .
526 ($not ? "AND\t" : "OR\t");
527 $valeurs = substr($valeurs, $n+1);
528 $i = $n = 0;
529 }
530 }
531 $in_sql .= "($val $not IN ($valeurs))";
532
533 return "($in_sql)";
534 }
535
536
537 function spip_array_cite($v, $type) {
538 if (sql_test_date($type) AND preg_match('/^\w+\(/', $v)
539 OR (sql_test_int($type)
540 AND (is_numeric($v)
541 OR (ctype_xdigit(substr($v,2))
542 AND $v[0]=='0' AND $v[1]=='x'))))
543 return $v;
544 else return ("'" . addslashes($v) . "'");
545 }
546
547 ?>