autocomplete improvements: can find pierre-yves when looking for yves
[platal.git] / modules / search / classes.inc.php
CommitLineData
0337d704 1<?php
2/***************************************************************************
5ddeb07c 3 * Copyright (C) 2003-2007 Polytechnique.org *
0337d704 4 * http://opensource.polytechnique.org/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
22require_once("xorg.misc.inc.php");
23
24// {{{ Global variables used for the search Queries
25
35fa92e8 26@$globals->search->result_fields = '
94f6c381 27 u.user_id, u.promo, u.matricule, u.matricule_ax,
28 if(u.nom_usage=\'\', u.nom, u.nom_usage) AS NomSortKey,
29 u.nom_usage,u.date,
30 u.deces!=0 AS dcd,u.deces,
31 u.perms IN (\'admin\',\'user\', \'disabled\') AS inscrit,
32 u.perms != \'pending\' AS wasinscrit,
33 FIND_IN_SET(\'femme\', u.flags) AS sexe,
34 a.alias AS forlife,
35 ad0.text AS app0text, ad0.url AS app0url, ai0.type AS app0type,
36 ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type,
37 es.label AS secteur, ef.fonction_fr AS fonction,
38 IF(n.nat=\'\',n.pays,n.nat) AS nat, n.a2 AS iso3166,
39 COUNT(em.email) > 0 AS actif,';
0337d704 40// hide private information if not logged
cab08090 41if (S::logged())
94f6c381 42 $globals->search->result_fields .='
43 q.profile_web AS web,
44 q.profile_mobile AS mobile,
45 q.profile_freetext AS freetext,
46 adr.city, gp.pays AS countrytxt, gr.name AS region,
47 e.entreprise,';
0337d704 48else
94f6c381 49 $globals->search->result_fields .="
50 IF(q.profile_web_pub='public', q.profile_web, '') AS web,
51 IF(q.profile_mobile_pub='public', q.profile_mobile, '') AS mobile,
52 IF(q.profile_freetext_pub='public', q.profile_freetext, '') AS freetext,
53 IF(adr.pub='public', adr.city, '') AS city,
54 IF(adr.pub='public', gp.pays, '') AS countrytxt,
55 IF(adr.pub='public', gr.name, '') AS region,
56 IF(e.pub='public', e.entreprise, '') AS entreprise,";
35fa92e8 57@$globals->search->result_where_statement = '
94f6c381 58 LEFT JOIN applis_ins AS ai0 ON (u.user_id = ai0.uid AND ai0.ordre = 0)
59 LEFT JOIN applis_def AS ad0 ON (ad0.id = ai0.aid)
60 LEFT JOIN applis_ins AS ai1 ON (u.user_id = ai1.uid AND ai1.ordre = 1)
61 LEFT JOIN applis_def AS ad1 ON (ad1.id = ai1.aid)
62 LEFT JOIN entreprises AS e ON (e.entrid = 0 AND e.uid = u.user_id)
63 LEFT JOIN emploi_secteur AS es ON (e.secteur = es.id)
64 LEFT JOIN fonctions_def AS ef ON (e.fonction = ef.id)
65 LEFT JOIN geoloc_pays AS n ON (u.nationalite = n.a2)
66 LEFT JOIN adresses AS adr ON (u.user_id = adr.uid AND FIND_IN_SET(\'active\',adr.statut))
67 LEFT JOIN geoloc_pays AS gp ON (adr.country = gp.a2)
68 LEFT JOIN geoloc_region AS gr ON (adr.country = gr.a2 AND adr.region = gr.region)
69 LEFT JOIN emails AS em ON (em.uid = u.user_id AND em.flags = \'active\')';
0337d704 70
71// }}}
72// {{{ function display_lines()
73
74/**
75 * This function is a heuristic that approximatively tells
76 * how many lines of output the contact list will use.
77 */
78function display_lines($text)
79{
80 $n = 0;
81 $tokens = Array('<tr>', '<div class="nom">');
82 foreach ($tokens as $t) {
83 $i = -1;
84 while ( ($i = strpos($text,$t,$i+1))!==false) { $n++; }
85 }
86 return $n;
87}
88
89// }}}
90// {{{ class ThrowError
91
92/** handle errors for end-users queries
93 * assign the error message and runs the templates
94 *
95 * @author Jean-Sebastien Bedo
96 */
97class ThrowError
98{
99 /** constuctor
100 * @param $explain string the error (in natural language)
101 */
102 function ThrowError($explain)
103 {
bc67c37c 104 global $page, $globals;
105 $page->changeTpl('search/index.tpl');
106 $page->assign('xorg_title','Polytechnique.org - Annuaire');
107 $page->assign('baseurl', $globals->baseurl);
108 $page->register_modifier('display_lines', 'display_lines');
c9110c6c 109 $page->trig('Erreur : '.$explain);
110 $page->run();
0337d704 111 }
112}
113
114// }}}
115// {{{ class SField [Base class]
116
a7de4ef7 117/** classe de base représentant un champ de recherche
118 * (correspond à un champ du formulaire mais peut être à plusieurs champs de la bdd)
119 * interface étendue pour chaque type de champ particulier
0337d704 120 */
121class SField
122{
123 // {{{ properties
94f6c381 124
0337d704 125 /** le nom du champ dans le formulaire HTML */
126 var $fieldFormName;
a7de4ef7 127 /** champs de la bdd correspondant à ce champ sous forme d'un tableau */
0337d704 128 var $fieldDbName;
a7de4ef7 129 /** champ résultat dans la requête MySQL correspondant à ce champ
130 * (alias utilisé pour la clause ORDER BY) */
0337d704 131 var $fieldResultName;
a7de4ef7 132 /** valeur du champ instanciée par l'utilisateur */
0337d704 133 var $value;
134
135 // }}}
136 // {{{ constructor
137
138 /** constructeur
a7de4ef7 139 * (récupère la requête de l'utilisateur pour ce champ) */
0337d704 140 function SField($_fieldFormName, $_fieldDbName='', $_fieldResultName='')
141 {
142 $this->fieldFormName = $_fieldFormName;
143 $this->fieldDbName = $_fieldDbName;
144 $this->fieldResultName = $_fieldResultName;
145 $this->get_request();
146 }
147
148 // }}}
149 // {{{ function get_request()
150
a7de4ef7 151 /** récupérer la requête de l'utilisateur
152 * on met une chaîne vide si le champ n'a pas été complété */
0337d704 153 function get_request()
154 {
5e2307dc 155 $this->value = trim(Env::v($this->fieldFormName));
0337d704 156 }
157
158 // }}}
159 // {{{ function get_where_statement()
94f6c381 160
a7de4ef7 161 /** récupérer la clause correspondant au champ dans la clause WHERE de la requête
0337d704 162 * on parcourt l'ensemble des champs de la bdd de $fieldDbName et on associe
a7de4ef7 163 * à chacun d'entre eux une clause spécifique
164 * la clause totale et la disjonction de ces clauses spécifiques */
0337d704 165 function get_where_statement()
166 {
167 if ($this->value=='') {
168 return false;
169 }
170 $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_where_statement'), $this->fieldDbName)));
171 return empty($res) ? '' : "($res)";
172 }
173
174 // }}}
175 // {{{ function get_order_statement()
94f6c381 176
a7de4ef7 177 /** récupérer la clause correspondant au champ dans la clause ORDER BY de la requête
178 * utilisé par exemple pour placer d'abord le nom égal à la requête avant les approximations */
0337d704 179 function get_order_statement()
180 {
181 return false;
182 }
183
184 // }}}
185 // {{{ function get_select_statement()
186
187 function get_select_statement()
188 {
189 return false;
190 }
191
192 // }}}
193 // {{{ function get_url()
194
a7de4ef7 195 /** récupérer le bout d'URL correspondant aux paramètres permettant d'imiter une requête d'un
196 * utilisateur assignant la valeur $this->value à ce champ */
0337d704 197 function get_url()
198 {
199 if (empty($this->value)) {
200 return false;
201 } else {
202 return $this->fieldFormName.'='.urlencode($this->value);
203 }
204 }
205
206 // }}}
207}
208
209// }}}
210// {{{ class QuickSearch [Google Like]
211
212class QuickSearch extends SField
213{
214 // {{{ properties
94f6c381 215
0337d704 216 /** stores tokens */
217 var $strings;
218 /** stores numerical ranges */
219 var $ranges;
220
221 // }}}
222 // {{{ constructor
94f6c381 223
0337d704 224 function QuickSearch($_fieldFormName)
225 {
226 $this->fieldFormName = $_fieldFormName;
227 $this->get_request();
a14159bf 228 if (preg_match(":[\]\[{}~/§_`|%$^=+]|\*\*:u", $this->value)) {
a7de4ef7 229 new ThrowError('Un champ contient un caractère interdit rendant la recherche impossible.');
0337d704 230 }
231 }
232
233 // }}}
234 // {{{ function isempty()
235
236 function isempty()
237 {
94f6c381 238 return empty($this->strings) && empty($this->ranges);
0337d704 239 }
240
241 // }}}
242 // {{{ function get_request()
94f6c381 243
0337d704 244 function get_request()
245 {
94f6c381 246 parent::get_request();
247 $s = replace_accent(trim($this->value));
248 $s = preg_replace('!\d+!', ' ', $s);
0337d704 249 $s = str_replace('*','%',$s);
94f6c381 250 $this->strings = preg_split("![^a-zA-Z%]+!",$s, -1, PREG_SPLIT_NO_EMPTY);
251
252 $s = trim($this->value);
253 $s = preg_replace('! *- *!', '-', $s);
254 $s = preg_replace('!([<>]) *!', ' \1', $s);
255 $s = preg_replace('![^0-9\-><]!', ' ', $s);
256 $s = preg_replace('![<>\-] !', '', $s);
257 $ranges = preg_split('! +!', $s, -1, PREG_SPLIT_NO_EMPTY);
258 $this->ranges=Array();
259 foreach ($ranges as $r) {
260 if (preg_match('!^([<>]\d{4}|\d{4}(-\d{4})?)$!', $r)) $this->ranges[] = $r;
261 }
0337d704 262 }
263
264 // }}}
265 // {{{ function get_where_statement()
94f6c381 266
0337d704 267 function get_where_statement()
268 {
94f6c381 269 $where = Array();
270 foreach ($this->strings as $i => $s) {
271 if (Env::i('with_soundex')) {
272 $t = soundex_fr($s);
273 $where[] = "sn$i.soundex = '$t'";
274 } else {
275 $t = str_replace('*', '%', $s).'%';
276 $t = str_replace('%%', '%', $t);
277 $where[] = "sn$i.token LIKE '$t'";
278 }
279 }
280
281 $wherep = Array();
282 foreach ($this->ranges as $r) {
283 if (preg_match('!^\d{4}$!', $r)) {
284 $wherep[] = "u.promo=$r";
285 } elseif (preg_match('!^(\d{4})-(\d{4})$!', $r, $matches)) {
286 $p1=min(intval($matches[1]), intval($matches[2]));
287 $p2=max(intval($matches[1]), intval($matches[2]));
288 $wherep[] = "(u.promo>=$p1 AND u.promo<=$p2)";
289 } elseif (preg_match('!^<(\d{4})!', $r, $matches)) {
290 $wherep[] = "u.promo<={$matches[1]}";
291 } elseif (preg_match('!^>(\d{4})!', $r, $matches)) {
292 $wherep[] = "u.promo>={$matches[1]}";
293 }
294 }
295 if (!empty($wherep)) {
0337d704 296 $where[] = '('.join(' OR ',$wherep).')';
297 }
94f6c381 298 return join(" AND ", $where);
0337d704 299 }
300
301 // }}}
302 // {{{ get_select_statement
303 function get_select_statement()
304 {
305 $join = "";
94f6c381 306 foreach ($this->strings as $i => $s) {
0337d704 307 $join .= "INNER JOIN search_name AS sn$i ON (u.user_id = sn$i.uid)\n";
308 }
309 return $join;
310 }
311 // }}}
312 // {{{ function get_order_statement()
94f6c381 313
0337d704 314 function get_order_statement()
315 {
316 return false;
317 }
318
319 // }}}
320 // {{{ function get_score_statement
94f6c381 321
0337d704 322 function get_score_statement()
323 {
324 $sum = array('0');
94f6c381 325 foreach ($this->strings as $i => $s) {
0337d704 326 $sum[] .= "SUM(sn$i.score + IF('$s'=sn$i.token,5,0))";
327 }
328 return join('+', $sum).' AS score';
329 }
330
331 // }}}
332}
333
334// }}}
335// {{{ class NumericSField [Integer fields]
336
a7de4ef7 337/** classe de champ numérique entier (offset par exemple)
0337d704 338 */
339class NumericSField extends SField
340{
341 // {{{ constructor
94f6c381 342
0337d704 343 /** constructeur
a7de4ef7 344 * (récupère la requête de l'utilisateur pour ce champ) */
0337d704 345 function NumericSField($_fieldFormName)
346 {
347 $this->fieldFormName = $_fieldFormName;
348 $this->get_request();
349 }
350
351 // }}}
352 // {{{ function get_request()
94f6c381 353
a7de4ef7 354 /** récupère la requête de l'utilisateur et échoue s'il ne s'agit pas d'un entier */
0337d704 355 function get_request()
356 {
357 parent::get_request();
358 if (empty($this->value)) {
359 $this->value = 0;
360 }
361 if (!preg_match("/^[0-9]+$/", $this->value)) {
a7de4ef7 362 new ThrowError('Un champ numérique contient des caractères alphanumériques.');
0337d704 363 }
364 }
94f6c381 365
0337d704 366 // }}}
367}
368
369// }}}
370// {{{ class RefSField [ ??? ]
371
372class RefSField extends SField
373{
374 // {{{ properties
94f6c381 375
0337d704 376 var $refTable;
377 var $refAlias;
378 var $refCondition;
379 var $exact = true;
380
381 // }}}
382 // {{{ constructor
383
384 function RefSField($_fieldFormName, $_fieldDbName='', $_refTable, $_refAlias, $_refCondition, $_exact=true)
385 {
386 $this->fieldFormName = $_fieldFormName;
387 $this->fieldDbName = $_fieldDbName;
388 $this->refTable = $_refTable;
389 $this->refAlias = $_refAlias;
390 $this->refCondition = $_refCondition;
391 $this->exact = $_exact;
392 $this->get_request();
393 }
394
395 // }}}
396 // {{{ function get_request()
94f6c381 397
0337d704 398 function get_request() {
399 parent::get_request();
400 if ($this->value=='00' || $this->value=='0') {
401 $this->value='';
402 }
403 }
404
405 // }}}
406 // {{{ function too_large()
407
408 function too_large()
409 {
410 return ($this->value=='');
411 }
412
413 // }}}
414 // {{{ function compare()
415
416 function compare()
417 {
418 $val = addslashes($this->value);
419 return $this->exact ? "='$val'" : " LIKE '%$val%'";
420 }
421
422 // }}}
423 // {{{ function get_single_match_statement()
424
425 function get_single_match_statement($field)
426 {
427 return $field.$this->compare();
428 }
429
430 // }}}
431 // {{{ function get_single_where_statement()
432
433 function get_single_where_statement($field)
434 {
435 return $this->refTable=='' ? $this->get_single_match_statement($field) : false;
436 }
437
438 // }}}
439 // {{{ function get_select_statement()
440
441 function get_select_statement()
442 {
443 if ($this->value=='' || $this->refTable=='') {
444 return false;
445 }
446 $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_match_statement'), $this->fieldDbName)));
447 return "INNER JOIN {$this->refTable} AS {$this->refAlias} ON ({$this->refCondition} AND ($res) )";
448 }
449
450 // }}}
451}
452
453// }}}
56670b6a 454
455// {{{ class RefSFieldMultipleTable
456class MapSField extends RefSField
457{
94f6c381 458 var $mapId;
459
56670b6a 460 function MapSField($_fieldFormName, $_fieldDbName='', $_refTable, $_refAlias, $_refCondition, $_mapId=false)
461 {
350e6926 462 if ($_mapId === false)
5e2307dc 463 $this->mapId = Env::v($_fieldFormName, '');
350e6926 464 else
465 $this->mapId = $_mapId;
466 $this->RefSField($_fieldFormName, $_fieldDbName, $_refTable, $_refAlias, $_refCondition, true, false);
56670b6a 467 }
468 function get_select_statement()
469 {
350e6926 470 if ($this->mapId === '') return false;
56670b6a 471 $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_match_statement'), $this->fieldDbName)));
472 foreach ($this->refTable as $i => $refT)
473 $last = $i;
474 $inner = "";
475 foreach ($this->refTable as $i => $refT)
476 $inner .= " INNER JOIN {$refT} AS {$this->refAlias[$i]} ON ({$this->refCondition[$i]} ".(($i == $last)?"AND ($res) ":"").")";
477 return $inner;
478 }
479 function get_request()
480 {
350e6926 481 $this->value = $this->mapId;
56670b6a 482 }
483}
484
0337d704 485// {{{ class RefWithSoundexSField [ ??? ]
486
487class RefWithSoundexSField extends RefSField
488{
489 // {{{ function compare()
94f6c381 490
0337d704 491 function compare()
492 {
94f6c381 493 return "='".soundex_fr($this->value)."'";
0337d704 494 }
495
496 // }}}
497}
498
499// }}}
500// {{{ class StringSField [String fields]
501
502/** classe de champ texte (nom par exemple)
503 */
504class StringSField extends SField
505{
506 // {{{ function get_request()
94f6c381 507
a7de4ef7 508 /** récupère la requête de l'utilisateur et échoue si la chaîne contient des caractères
0337d704 509 * interdits */
510 function get_request()
511 {
512 parent::get_request();
a14159bf 513 if (preg_match(":[\]\[<>{}~/§_`|%$^=+]|\*\*:u", $this->value)) {
a7de4ef7 514 new ThrowError('Un champ contient un caractère interdit rendant la recherche impossible.');
0337d704 515 }
516 }
517
518 // }}}
519 // {{{ function length()
520
a7de4ef7 521 /** donne la longueur de la requête de l'utilisateur
522 * (au sens strict i.e. pas d'* ni d'espace ou de trait d'union -> les contraintes réellement
523 * imposées par l'utilisateur) */
0337d704 524 function length()
525 {
a14159bf 526 $cleaned = replace_accent(strtolower($this->value));
527 $length = strlen(ereg_replace('[a-z0-9]', '', $cleaned));
528 return strlen($this->value) - $length;
0337d704 529 }
530
531 // }}}
532 // {{{ function too_large()
533
534 function too_large()
535 {
536 return ($this->length()<2);
537 }
538
539 // }}}
540 // {{{ function get_single_where_statement()
541
a7de4ef7 542 /** clause WHERE correspondant à un champ de la bdd et à ce champ de formulaire
543 * @param field nom de champ de la bdd concerné par la clause */
0337d704 544 function get_single_where_statement($field)
545 {
546 $regexp = strtr(addslashes($this->value), '-*', '_%');
547 return "$field LIKE '$regexp%'";
548 }
549
550 // }}}
551 // {{{ function get_order_statement()
552
a7de4ef7 553 /** clause ORDER BY correspondant à ce champ de formulaire */
0337d704 554 function get_order_statement()
555 {
556 if ($this->value!='' && $this->fieldResultName!='') {
557 return "{$this->fieldResultName}!='".addslashes($this->value)."'";
558 } else {
559 return false;
560 }
561 }
562
563 // }}}
564}
565
566// }}}
567// {{{ class NameSField [Names : serach 'n%' + '% b']
568
569/** classe pour les noms : on cherche en plus du like 'foo%' le like '% foo' (particules)
570+*/
571class NameSField extends StringSField
572{
573 // {{{ function get_single_where_statement()
94f6c381 574
0337d704 575 function get_single_where_statement($field)
576 {
577 $regexp = strtr(addslashes($this->value), '-*', '_%');
578 return "$field LIKE '$regexp%' OR $field LIKE '% $regexp%' OR $field LIKE '%-$regexp%'";
579 }
580
581 // }}}
582 // {{{ function get_order_statement()
94f6c381 583
0337d704 584 function get_order_statement()
585 {
586 if ($this->value!='' && $this->fieldResultName!='') {
587 return "{$this->fieldResultName} NOT LIKE '".addslashes($this->value)."'";
588 } else {
589 return false;
590 }
591 }
592
593 // }}}
594}
595
596// }}}
597// {{{ class StringWithSoundexSField [Strings + soundex]
598
599/** classe de champ texte avec soundex (nom par exemple)
600 */
601class StringWithSoundexSField extends StringSField
602{
603 // {{{ function get_single_where_statement()
604
a7de4ef7 605 /** clause WHERE correspondant à un champ de la bdd et à ce champ de formulaire
606 * @param field nom de champ de la bdd concerné par la clause */
0337d704 607 function get_single_where_statement($field) {
608 return $field.'="'.soundex_fr($this->value).'"';
609 }
610
611 // }}}
612}
613
614// }}}
615// {{{ class PromoSField [Prom field]
616
617/** classe de champ de promotion */
618class PromoSField extends SField
619{
620 // {{{ properties
94f6c381 621
a7de4ef7 622 /** opérateur de comparaison (<,>,=) de la promo utilisé pour ce champ de formulaire */
0337d704 623 var $compareField;
624
625 // }}}
626 // {{{ constructor
627
628 /** constructeur
a7de4ef7 629 * compareField est un champ de formulaire très simple qui ne sert qu'à la construction de la
0337d704 630 * clause WHERE de la promo */
631 function PromoSField($_fieldFormName, $_compareFieldFormName, $_fieldDbName, $_fieldResultName)
632 {
633 parent::SField($_fieldFormName, $_fieldDbName, $_fieldResultName);
634 $this->compareField = new SField($_compareFieldFormName);
635 }
636
637 // }}}
638 // {{{ function get_request()
639
a7de4ef7 640 /** récupère la requête utilisateur et échoue si le champ du formulaire ne représente pas une
641 * promotion (nombre à 4 chiffres) */
0337d704 642 function get_request()
643 {
644 parent::get_request();
645 if (preg_match('/^[0-9]{2}$/', $this->value)){
646 $this->value = intval($this->value) + 1900;
647 }
648 if (!(empty($this->value) or preg_match('/^[0-9]{4}$/', $this->value))) {
a7de4ef7 649 new ThrowError('La promotion est une année à quatre chiffres.');
0337d704 650 }
651 }
652
653 // }}}
654 // {{{ function is_a_single_promo()
655
a7de4ef7 656 /** teste si la requête est de la forme =promotion -> contrainte forte imposée -> elle suffit
657 * pour autoriser un affichage des résultats alors que <promotion est insuffisant */
0337d704 658 function is_a_single_promo()
659 {
660 return ($this->compareField->value=='=' && $this->value!='');
661 }
662
663 // }}}
664 // {{{ function too_large()
665
666 function too_large()
667 {
668 return !$this->is_a_single_promo();
669 }
670
671 // }}}
672 // {{{ function get_single_where_statement()
673
a7de4ef7 674 /** clause WHERE correspondant à ce champ */
0337d704 675 function get_single_where_statement($field)
676 {
677 return $field.$this->compareField->value.$this->value;
678 }
679
680 // }}}
681 // {{{ function get_url()
682
a7de4ef7 683 /** récupérer le bout d'URL correspondant aux paramètres permettant d'imiter une requête
684 * d'un utilisateur assignant la valeur $this->value à ce champ et assignant l'opérateur de
685 * comparaison adéquat */
0337d704 686 function get_url()
687 {
688 if (!($u=parent::get_url())) {
689 return false;
690 }
691 return $u.'&amp;'.$this->compareField->get_url();
692 }
693
694 // }}}
695}
696
697// }}}
698// {{{ class SFieldGroup [Group fields]
699
700/** classe groupant des champs de formulaire de recherche */
701class SFieldGroup
702{
703 // {{{ properties
94f6c381 704
a7de4ef7 705 /** tableau des classes correspondant aux champs groupés */
0337d704 706 var $fields;
707 /** type de groupe : ET ou OU */
708 var $and;
709
710 // }}}
711 // {{{ constuctor
712
713 /** constructeur */
714 function SFieldGroup($_and, $_fields)
715 {
716 $this->fields = $_fields;
717 $this->and = $_and;
718 }
719
720 // }}}
721 // {{{ function too_large()
722
723 function too_large()
724 {
725 $b = true;
726 for ($i=0; $b && $i<count($this->fields); $i++) {
727 $b &= $this->fields[$i]->too_large();
728 }
729 return $b;
730 }
731
732 // }}}
733 // {{{ function field_get_select()
734
735 function field_get_select($f)
736 {
737 return $f->get_select_statement();
738 }
739
740 // }}}
741 // {{{ function field_get_where()
742
a7de4ef7 743 /** récupérer la clause WHERE d'un objet champ de recherche */
0337d704 744 function field_get_where($f)
745 {
746 return $f->get_where_statement();
747 }
748
749 // }}}
750 // {{{ function field_get_order()
751
a7de4ef7 752 /** récupérer la clause ORDER BY d'un objet champ de recherche */
0337d704 753 function field_get_order($f)
754 {
755 return $f->get_order_statement();
756 }
757
758 // }}}
759 // {{{ function field_get_url()
760
a7de4ef7 761 /** récupérer le bout d'URL correspondant à un objet champ de recherche */
0337d704 762 function field_get_url($f)
763 {
764 return $f->get_url();
765 }
94f6c381 766
0337d704 767 // }}}
768 // {{{ function get_select_statement()
769
770 function get_select_statement()
771 {
772 return implode(' ', array_filter(array_map(array($this, 'field_get_select'), $this->fields)));
773 }
774
775 // }}}
776 // {{{ function get_where_statement()
777
a7de4ef7 778 /** récupérer la clause WHERE du groupe de champs = conjonction (ET) ou disjonction (OU) de
779 * clauses des champs élémentaires */
0337d704 780 function get_where_statement()
781 {
782 $joinText = $this->and ? ' AND ' : ' OR ';
783 $res = implode($joinText, array_filter(array_map(array($this, 'field_get_where'), $this->fields)));
784 return $res == '' ? '' : "($res)";
785 }
786
787 // }}}
788 // {{{ function get_order_statement()
789
a7de4ef7 790 /** récupérer la clause ORDER BY du groupe de champs = conjonction (ET) ou disjonction (OU) de
791 * clauses des champs élémentaires */
0337d704 792 function get_order_statement()
793 {
794 $order = array_filter(array_map(array($this, 'field_get_order'), $this->fields));
795 return count($order)>0 ? implode(',', $order) : false;
796 }
797
798 // }}}
799 // {{{ function get_url()
800
a7de4ef7 801 /** récupérer le bout d'URL correspondant à ce groupe de champs = concaténation des bouts d'URL
802 * des champs élémentaires */
0337d704 803 function get_url($others=Array())
804 {
805 $url = array_filter(array_map(array($this, 'field_get_url'), $this->fields));
806 foreach ($url as $key=>$val) {
807 if (empty($val)) {
808 unset($url[$key]);
809 }
810 }
811 foreach ($others as $key=>$val) {
812 if (!empty($val)) {
813 $url[] = "$key=$val";
814 }
815 }
816 return count($url)>0 ? implode('&amp;', $url) : false;
817 }
818
819 // }}}
820}
821
822// }}}
823
a7de4ef7 824// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
0337d704 825?>