Commit | Line | Data |
---|---|---|
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 | ||
22 | require_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 |
eaf30d86 | 41 | if (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 | 48 | else |
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 | // }}} | |
0337d704 | 72 | // {{{ class ThrowError |
73 | ||
74 | /** handle errors for end-users queries | |
75 | * assign the error message and runs the templates | |
76 | * | |
77 | * @author Jean-Sebastien Bedo | |
78 | */ | |
79 | class ThrowError | |
80 | { | |
a2aa8436 | 81 | public static $throwHook = array('ThrowError', 'defaultHandler'); |
82 | ||
0337d704 | 83 | /** constuctor |
84 | * @param $explain string the error (in natural language) | |
85 | */ | |
92432704 | 86 | public function __construct($explain) |
0337d704 | 87 | { |
a2aa8436 | 88 | call_user_func(ThrowError::$throwHook, $explain); |
89 | } | |
90 | ||
91 | /** defaut error handler | |
92 | */ | |
93 | private static function defaultHandler($explain) | |
94 | { | |
bc67c37c | 95 | global $page, $globals; |
96 | $page->changeTpl('search/index.tpl'); | |
97 | $page->assign('xorg_title','Polytechnique.org - Annuaire'); | |
98 | $page->assign('baseurl', $globals->baseurl); | |
c9110c6c | 99 | $page->trig('Erreur : '.$explain); |
100 | $page->run(); | |
0337d704 | 101 | } |
102 | } | |
103 | ||
104 | // }}} | |
105 | // {{{ class SField [Base class] | |
106 | ||
a7de4ef7 | 107 | /** classe de base représentant un champ de recherche |
108 | * (correspond à un champ du formulaire mais peut être à plusieurs champs de la bdd) | |
109 | * interface étendue pour chaque type de champ particulier | |
0337d704 | 110 | */ |
111 | class SField | |
112 | { | |
113 | // {{{ properties | |
94f6c381 | 114 | |
0337d704 | 115 | /** le nom du champ dans le formulaire HTML */ |
116 | var $fieldFormName; | |
a7de4ef7 | 117 | /** champs de la bdd correspondant à ce champ sous forme d'un tableau */ |
0337d704 | 118 | var $fieldDbName; |
a7de4ef7 | 119 | /** champ résultat dans la requête MySQL correspondant à ce champ |
120 | * (alias utilisé pour la clause ORDER BY) */ | |
0337d704 | 121 | var $fieldResultName; |
a7de4ef7 | 122 | /** valeur du champ instanciée par l'utilisateur */ |
0337d704 | 123 | var $value; |
124 | ||
125 | // }}} | |
126 | // {{{ constructor | |
127 | ||
128 | /** constructeur | |
a7de4ef7 | 129 | * (récupère la requête de l'utilisateur pour ce champ) */ |
0337d704 | 130 | function SField($_fieldFormName, $_fieldDbName='', $_fieldResultName='') |
131 | { | |
132 | $this->fieldFormName = $_fieldFormName; | |
133 | $this->fieldDbName = $_fieldDbName; | |
134 | $this->fieldResultName = $_fieldResultName; | |
135 | $this->get_request(); | |
136 | } | |
137 | ||
138 | // }}} | |
139 | // {{{ function get_request() | |
140 | ||
eaf30d86 | 141 | /** récupérer la requête de l'utilisateur |
a7de4ef7 | 142 | * on met une chaîne vide si le champ n'a pas été complété */ |
0337d704 | 143 | function get_request() |
144 | { | |
5e2307dc | 145 | $this->value = trim(Env::v($this->fieldFormName)); |
0337d704 | 146 | } |
147 | ||
148 | // }}} | |
149 | // {{{ function get_where_statement() | |
94f6c381 | 150 | |
a7de4ef7 | 151 | /** récupérer la clause correspondant au champ dans la clause WHERE de la requête |
eaf30d86 | 152 | * on parcourt l'ensemble des champs de la bdd de $fieldDbName et on associe |
a7de4ef7 | 153 | * à chacun d'entre eux une clause spécifique |
154 | * la clause totale et la disjonction de ces clauses spécifiques */ | |
0337d704 | 155 | function get_where_statement() |
156 | { | |
157 | if ($this->value=='') { | |
158 | return false; | |
159 | } | |
160 | $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_where_statement'), $this->fieldDbName))); | |
161 | return empty($res) ? '' : "($res)"; | |
162 | } | |
163 | ||
164 | // }}} | |
165 | // {{{ function get_order_statement() | |
94f6c381 | 166 | |
a7de4ef7 | 167 | /** récupérer la clause correspondant au champ dans la clause ORDER BY de la requête |
168 | * utilisé par exemple pour placer d'abord le nom égal à la requête avant les approximations */ | |
0337d704 | 169 | function get_order_statement() |
170 | { | |
171 | return false; | |
172 | } | |
173 | ||
174 | // }}} | |
175 | // {{{ function get_select_statement() | |
176 | ||
177 | function get_select_statement() | |
178 | { | |
179 | return false; | |
180 | } | |
181 | ||
182 | // }}} | |
183 | // {{{ function get_url() | |
184 | ||
a7de4ef7 | 185 | /** récupérer le bout d'URL correspondant aux paramètres permettant d'imiter une requête d'un |
186 | * utilisateur assignant la valeur $this->value à ce champ */ | |
0337d704 | 187 | function get_url() |
188 | { | |
189 | if (empty($this->value)) { | |
190 | return false; | |
191 | } else { | |
192 | return $this->fieldFormName.'='.urlencode($this->value); | |
193 | } | |
194 | } | |
195 | ||
196 | // }}} | |
197 | } | |
198 | ||
199 | // }}} | |
200 | // {{{ class QuickSearch [Google Like] | |
201 | ||
202 | class QuickSearch extends SField | |
203 | { | |
204 | // {{{ properties | |
94f6c381 | 205 | |
0337d704 | 206 | /** stores tokens */ |
207 | var $strings; | |
208 | /** stores numerical ranges */ | |
209 | var $ranges; | |
bbf610b8 | 210 | /** stores admin searches */ |
211 | var $email; | |
212 | var $ip; | |
0337d704 | 213 | |
214 | // }}} | |
215 | // {{{ constructor | |
94f6c381 | 216 | |
0337d704 | 217 | function QuickSearch($_fieldFormName) |
218 | { | |
219 | $this->fieldFormName = $_fieldFormName; | |
220 | $this->get_request(); | |
a14159bf | 221 | if (preg_match(":[\]\[{}~/§_`|%$^=+]|\*\*:u", $this->value)) { |
a7de4ef7 | 222 | new ThrowError('Un champ contient un caractère interdit rendant la recherche impossible.'); |
0337d704 | 223 | } |
224 | } | |
225 | ||
226 | // }}} | |
227 | // {{{ function isempty() | |
228 | ||
229 | function isempty() | |
230 | { | |
bbf610b8 | 231 | return empty($this->strings) && empty($this->ranges) && empty($this->email) && empty($this->ip); |
0337d704 | 232 | } |
233 | ||
234 | // }}} | |
235 | // {{{ function get_request() | |
94f6c381 | 236 | |
0337d704 | 237 | function get_request() |
238 | { | |
94f6c381 | 239 | parent::get_request(); |
240 | $s = replace_accent(trim($this->value)); | |
bbf610b8 | 241 | $r = $s = str_replace('*','%',$s); |
242 | ||
243 | if (S::has_perms() && strpos($s, '@') !== false) { | |
244 | $this->email = $s; | |
245 | } else if (S::has_perms() && preg_match('/[0-9]+\.([0-9]+|%)\.([0-9]+|%)\.([0-9]+|%)/', $s)) { | |
246 | $this->ip = $s; | |
247 | } | |
248 | if ($this->email || $this->ip) { | |
249 | $this->strings = $this->ranges = array(); | |
250 | return; | |
251 | } | |
252 | ||
94f6c381 | 253 | $s = preg_replace('!\d+!', ' ', $s); |
94f6c381 | 254 | $this->strings = preg_split("![^a-zA-Z%]+!",$s, -1, PREG_SPLIT_NO_EMPTY); |
8b035281 FB |
255 | if (count($this->strings) > 5) { |
256 | global $page; | |
257 | $page->trig("Tu as indiqué trop d'éléments dans ta recherche, seuls les 5 premiers seront pris en compte"); | |
258 | $this->strings = array_slice($this->strings, 0, 5); | |
259 | } | |
94f6c381 | 260 | |
bbf610b8 | 261 | $s = preg_replace('! *- *!', '-', $r); |
94f6c381 | 262 | $s = preg_replace('!([<>]) *!', ' \1', $s); |
263 | $s = preg_replace('![^0-9\-><]!', ' ', $s); | |
264 | $s = preg_replace('![<>\-] !', '', $s); | |
265 | $ranges = preg_split('! +!', $s, -1, PREG_SPLIT_NO_EMPTY); | |
266 | $this->ranges=Array(); | |
267 | foreach ($ranges as $r) { | |
268 | if (preg_match('!^([<>]\d{4}|\d{4}(-\d{4})?)$!', $r)) $this->ranges[] = $r; | |
269 | } | |
0337d704 | 270 | } |
271 | ||
272 | // }}} | |
273 | // {{{ function get_where_statement() | |
94f6c381 | 274 | |
0337d704 | 275 | function get_where_statement() |
276 | { | |
94f6c381 | 277 | $where = Array(); |
278 | foreach ($this->strings as $i => $s) { | |
c16b5562 | 279 | if (Env::i('with_soundex') && strlen($s) > 1) { |
94f6c381 | 280 | $t = soundex_fr($s); |
281 | $where[] = "sn$i.soundex = '$t'"; | |
282 | } else { | |
283 | $t = str_replace('*', '%', $s).'%'; | |
284 | $t = str_replace('%%', '%', $t); | |
285 | $where[] = "sn$i.token LIKE '$t'"; | |
286 | } | |
287 | } | |
288 | ||
289 | $wherep = Array(); | |
290 | foreach ($this->ranges as $r) { | |
291 | if (preg_match('!^\d{4}$!', $r)) { | |
292 | $wherep[] = "u.promo=$r"; | |
293 | } elseif (preg_match('!^(\d{4})-(\d{4})$!', $r, $matches)) { | |
294 | $p1=min(intval($matches[1]), intval($matches[2])); | |
295 | $p2=max(intval($matches[1]), intval($matches[2])); | |
296 | $wherep[] = "(u.promo>=$p1 AND u.promo<=$p2)"; | |
297 | } elseif (preg_match('!^<(\d{4})!', $r, $matches)) { | |
298 | $wherep[] = "u.promo<={$matches[1]}"; | |
299 | } elseif (preg_match('!^>(\d{4})!', $r, $matches)) { | |
300 | $wherep[] = "u.promo>={$matches[1]}"; | |
301 | } | |
302 | } | |
303 | if (!empty($wherep)) { | |
0337d704 | 304 | $where[] = '('.join(' OR ',$wherep).')'; |
305 | } | |
bbf610b8 | 306 | if (!empty($this->email)) { |
307 | $where[] = 'ems.email = ' . XDB::escape($this->email); | |
308 | } | |
309 | if (!empty($this->ip)) { | |
310 | $ip = XDB::escape($this->ip); | |
311 | $where[] = "( ls.ip = $ip OR ls.forward_ip = $ip )"; | |
312 | } | |
3b2f9d11 | 313 | |
94f6c381 | 314 | return join(" AND ", $where); |
0337d704 | 315 | } |
316 | ||
317 | // }}} | |
318 | // {{{ get_select_statement | |
319 | function get_select_statement() | |
320 | { | |
321 | $join = ""; | |
c0c9f772 | 322 | $and = ''; |
c16b5562 | 323 | $uniq = ''; |
94f6c381 | 324 | foreach ($this->strings as $i => $s) { |
c0c9f772 | 325 | if (!S::logged()) { |
326 | $and = "AND FIND_IN_SET('public', sn$i.flags)"; | |
c16b5562 | 327 | } |
328 | $myu = str_replace('snv', "sn$i", $uniq); | |
329 | $join .= "INNER JOIN search_name AS sn$i ON (u.user_id = sn$i.uid $and$myu)\n"; | |
330 | $uniq .= " AND sn$i.token != snv.token"; | |
0337d704 | 331 | } |
bbf610b8 | 332 | if (!empty($this->email)) { |
333 | $join .= "LEFT JOIN emails AS ems ON (ems.uid = u.user_id)"; | |
334 | } | |
335 | if (!empty($this->ip)) { | |
336 | $join .= "INNER JOIN logger.sessions AS ls ON (ls.uid = u.user_id)\n"; | |
337 | } | |
0337d704 | 338 | return $join; |
339 | } | |
340 | // }}} | |
341 | // {{{ function get_order_statement() | |
94f6c381 | 342 | |
0337d704 | 343 | function get_order_statement() |
344 | { | |
345 | return false; | |
346 | } | |
347 | ||
348 | // }}} | |
349 | // {{{ function get_score_statement | |
94f6c381 | 350 | |
0337d704 | 351 | function get_score_statement() |
352 | { | |
353 | $sum = array('0'); | |
94f6c381 | 354 | foreach ($this->strings as $i => $s) { |
0337d704 | 355 | $sum[] .= "SUM(sn$i.score + IF('$s'=sn$i.token,5,0))"; |
356 | } | |
357 | return join('+', $sum).' AS score'; | |
358 | } | |
359 | ||
360 | // }}} | |
361 | } | |
362 | ||
363 | // }}} | |
364 | // {{{ class NumericSField [Integer fields] | |
365 | ||
a7de4ef7 | 366 | /** classe de champ numérique entier (offset par exemple) |
0337d704 | 367 | */ |
368 | class NumericSField extends SField | |
369 | { | |
370 | // {{{ constructor | |
94f6c381 | 371 | |
0337d704 | 372 | /** constructeur |
a7de4ef7 | 373 | * (récupère la requête de l'utilisateur pour ce champ) */ |
0337d704 | 374 | function NumericSField($_fieldFormName) |
375 | { | |
376 | $this->fieldFormName = $_fieldFormName; | |
377 | $this->get_request(); | |
378 | } | |
379 | ||
380 | // }}} | |
381 | // {{{ function get_request() | |
94f6c381 | 382 | |
a7de4ef7 | 383 | /** récupère la requête de l'utilisateur et échoue s'il ne s'agit pas d'un entier */ |
0337d704 | 384 | function get_request() |
385 | { | |
386 | parent::get_request(); | |
387 | if (empty($this->value)) { | |
388 | $this->value = 0; | |
389 | } | |
390 | if (!preg_match("/^[0-9]+$/", $this->value)) { | |
a7de4ef7 | 391 | new ThrowError('Un champ numérique contient des caractères alphanumériques.'); |
0337d704 | 392 | } |
393 | } | |
94f6c381 | 394 | |
0337d704 | 395 | // }}} |
396 | } | |
397 | ||
398 | // }}} | |
399 | // {{{ class RefSField [ ??? ] | |
400 | ||
401 | class RefSField extends SField | |
402 | { | |
403 | // {{{ properties | |
94f6c381 | 404 | |
0337d704 | 405 | var $refTable; |
406 | var $refAlias; | |
407 | var $refCondition; | |
408 | var $exact = true; | |
409 | ||
410 | // }}} | |
411 | // {{{ constructor | |
412 | ||
413 | function RefSField($_fieldFormName, $_fieldDbName='', $_refTable, $_refAlias, $_refCondition, $_exact=true) | |
414 | { | |
415 | $this->fieldFormName = $_fieldFormName; | |
416 | $this->fieldDbName = $_fieldDbName; | |
417 | $this->refTable = $_refTable; | |
418 | $this->refAlias = $_refAlias; | |
419 | $this->refCondition = $_refCondition; | |
420 | $this->exact = $_exact; | |
421 | $this->get_request(); | |
422 | } | |
423 | ||
424 | // }}} | |
425 | // {{{ function get_request() | |
94f6c381 | 426 | |
0337d704 | 427 | function get_request() { |
428 | parent::get_request(); | |
429 | if ($this->value=='00' || $this->value=='0') { | |
430 | $this->value=''; | |
431 | } | |
432 | } | |
433 | ||
434 | // }}} | |
435 | // {{{ function too_large() | |
436 | ||
437 | function too_large() | |
438 | { | |
439 | return ($this->value==''); | |
440 | } | |
441 | ||
442 | // }}} | |
443 | // {{{ function compare() | |
444 | ||
445 | function compare() | |
446 | { | |
447 | $val = addslashes($this->value); | |
448 | return $this->exact ? "='$val'" : " LIKE '%$val%'"; | |
449 | } | |
450 | ||
451 | // }}} | |
452 | // {{{ function get_single_match_statement() | |
453 | ||
454 | function get_single_match_statement($field) | |
455 | { | |
456 | return $field.$this->compare(); | |
457 | } | |
458 | ||
459 | // }}} | |
460 | // {{{ function get_single_where_statement() | |
461 | ||
462 | function get_single_where_statement($field) | |
463 | { | |
464 | return $this->refTable=='' ? $this->get_single_match_statement($field) : false; | |
465 | } | |
466 | ||
467 | // }}} | |
468 | // {{{ function get_select_statement() | |
469 | ||
470 | function get_select_statement() | |
471 | { | |
472 | if ($this->value=='' || $this->refTable=='') { | |
473 | return false; | |
474 | } | |
475 | $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_match_statement'), $this->fieldDbName))); | |
476 | return "INNER JOIN {$this->refTable} AS {$this->refAlias} ON ({$this->refCondition} AND ($res) )"; | |
477 | } | |
478 | ||
479 | // }}} | |
480 | } | |
481 | ||
482 | // }}} | |
56670b6a | 483 | |
484 | // {{{ class RefSFieldMultipleTable | |
485 | class MapSField extends RefSField | |
486 | { | |
94f6c381 | 487 | var $mapId; |
488 | ||
56670b6a | 489 | function MapSField($_fieldFormName, $_fieldDbName='', $_refTable, $_refAlias, $_refCondition, $_mapId=false) |
490 | { | |
350e6926 | 491 | if ($_mapId === false) |
5e2307dc | 492 | $this->mapId = Env::v($_fieldFormName, ''); |
350e6926 | 493 | else |
494 | $this->mapId = $_mapId; | |
a2aa8436 | 495 | $this->value = $this->mapId; |
350e6926 | 496 | $this->RefSField($_fieldFormName, $_fieldDbName, $_refTable, $_refAlias, $_refCondition, true, false); |
56670b6a | 497 | } |
eaf30d86 | 498 | |
56670b6a | 499 | function get_select_statement() |
500 | { | |
350e6926 | 501 | if ($this->mapId === '') return false; |
56670b6a | 502 | $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_match_statement'), $this->fieldDbName))); |
503 | foreach ($this->refTable as $i => $refT) | |
504 | $last = $i; | |
505 | $inner = ""; | |
506 | foreach ($this->refTable as $i => $refT) | |
507 | $inner .= " INNER JOIN {$refT} AS {$this->refAlias[$i]} ON ({$this->refCondition[$i]} ".(($i == $last)?"AND ($res) ":"").")"; | |
508 | return $inner; | |
509 | } | |
510 | function get_request() | |
511 | { | |
350e6926 | 512 | $this->value = $this->mapId; |
56670b6a | 513 | } |
514 | } | |
515 | ||
0337d704 | 516 | // {{{ class RefWithSoundexSField [ ??? ] |
517 | ||
518 | class RefWithSoundexSField extends RefSField | |
519 | { | |
520 | // {{{ function compare() | |
94f6c381 | 521 | |
0337d704 | 522 | function compare() |
523 | { | |
94f6c381 | 524 | return "='".soundex_fr($this->value)."'"; |
0337d704 | 525 | } |
526 | ||
527 | // }}} | |
528 | } | |
529 | ||
530 | // }}} | |
531 | // {{{ class StringSField [String fields] | |
532 | ||
533 | /** classe de champ texte (nom par exemple) | |
534 | */ | |
535 | class StringSField extends SField | |
536 | { | |
537 | // {{{ function get_request() | |
94f6c381 | 538 | |
a7de4ef7 | 539 | /** récupère la requête de l'utilisateur et échoue si la chaîne contient des caractères |
0337d704 | 540 | * interdits */ |
541 | function get_request() | |
542 | { | |
543 | parent::get_request(); | |
a14159bf | 544 | if (preg_match(":[\]\[<>{}~/§_`|%$^=+]|\*\*:u", $this->value)) { |
a7de4ef7 | 545 | new ThrowError('Un champ contient un caractère interdit rendant la recherche impossible.'); |
0337d704 | 546 | } |
547 | } | |
548 | ||
549 | // }}} | |
550 | // {{{ function length() | |
551 | ||
a7de4ef7 | 552 | /** donne la longueur de la requête de l'utilisateur |
553 | * (au sens strict i.e. pas d'* ni d'espace ou de trait d'union -> les contraintes réellement | |
554 | * imposées par l'utilisateur) */ | |
0337d704 | 555 | function length() |
556 | { | |
a14159bf | 557 | $cleaned = replace_accent(strtolower($this->value)); |
558 | $length = strlen(ereg_replace('[a-z0-9]', '', $cleaned)); | |
559 | return strlen($this->value) - $length; | |
0337d704 | 560 | } |
561 | ||
562 | // }}} | |
563 | // {{{ function too_large() | |
564 | ||
565 | function too_large() | |
566 | { | |
567 | return ($this->length()<2); | |
568 | } | |
569 | ||
570 | // }}} | |
571 | // {{{ function get_single_where_statement() | |
572 | ||
a7de4ef7 | 573 | /** clause WHERE correspondant à un champ de la bdd et à ce champ de formulaire |
574 | * @param field nom de champ de la bdd concerné par la clause */ | |
0337d704 | 575 | function get_single_where_statement($field) |
576 | { | |
577 | $regexp = strtr(addslashes($this->value), '-*', '_%'); | |
578 | return "$field LIKE '$regexp%'"; | |
579 | } | |
580 | ||
581 | // }}} | |
582 | // {{{ function get_order_statement() | |
583 | ||
a7de4ef7 | 584 | /** clause ORDER BY correspondant à ce champ de formulaire */ |
0337d704 | 585 | function get_order_statement() |
586 | { | |
587 | if ($this->value!='' && $this->fieldResultName!='') { | |
588 | return "{$this->fieldResultName}!='".addslashes($this->value)."'"; | |
589 | } else { | |
590 | return false; | |
591 | } | |
592 | } | |
593 | ||
594 | // }}} | |
595 | } | |
596 | ||
597 | // }}} | |
598 | // {{{ class NameSField [Names : serach 'n%' + '% b'] | |
599 | ||
600 | /** classe pour les noms : on cherche en plus du like 'foo%' le like '% foo' (particules) | |
601 | +*/ | |
602 | class NameSField extends StringSField | |
603 | { | |
604 | // {{{ function get_single_where_statement() | |
94f6c381 | 605 | |
0337d704 | 606 | function get_single_where_statement($field) |
607 | { | |
608 | $regexp = strtr(addslashes($this->value), '-*', '_%'); | |
609 | return "$field LIKE '$regexp%' OR $field LIKE '% $regexp%' OR $field LIKE '%-$regexp%'"; | |
610 | } | |
611 | ||
612 | // }}} | |
613 | // {{{ function get_order_statement() | |
94f6c381 | 614 | |
0337d704 | 615 | function get_order_statement() |
616 | { | |
617 | if ($this->value!='' && $this->fieldResultName!='') { | |
618 | return "{$this->fieldResultName} NOT LIKE '".addslashes($this->value)."'"; | |
619 | } else { | |
620 | return false; | |
621 | } | |
622 | } | |
623 | ||
624 | // }}} | |
625 | } | |
626 | ||
627 | // }}} | |
628 | // {{{ class StringWithSoundexSField [Strings + soundex] | |
629 | ||
630 | /** classe de champ texte avec soundex (nom par exemple) | |
631 | */ | |
632 | class StringWithSoundexSField extends StringSField | |
633 | { | |
634 | // {{{ function get_single_where_statement() | |
635 | ||
a7de4ef7 | 636 | /** clause WHERE correspondant à un champ de la bdd et à ce champ de formulaire |
637 | * @param field nom de champ de la bdd concerné par la clause */ | |
0337d704 | 638 | function get_single_where_statement($field) { |
639 | return $field.'="'.soundex_fr($this->value).'"'; | |
640 | } | |
641 | ||
642 | // }}} | |
643 | } | |
644 | ||
645 | // }}} | |
646 | // {{{ class PromoSField [Prom field] | |
647 | ||
648 | /** classe de champ de promotion */ | |
649 | class PromoSField extends SField | |
650 | { | |
651 | // {{{ properties | |
94f6c381 | 652 | |
a7de4ef7 | 653 | /** opérateur de comparaison (<,>,=) de la promo utilisé pour ce champ de formulaire */ |
0337d704 | 654 | var $compareField; |
655 | ||
656 | // }}} | |
657 | // {{{ constructor | |
658 | ||
eaf30d86 | 659 | /** constructeur |
a7de4ef7 | 660 | * compareField est un champ de formulaire très simple qui ne sert qu'à la construction de la |
0337d704 | 661 | * clause WHERE de la promo */ |
662 | function PromoSField($_fieldFormName, $_compareFieldFormName, $_fieldDbName, $_fieldResultName) | |
663 | { | |
664 | parent::SField($_fieldFormName, $_fieldDbName, $_fieldResultName); | |
665 | $this->compareField = new SField($_compareFieldFormName); | |
666 | } | |
667 | ||
668 | // }}} | |
669 | // {{{ function get_request() | |
670 | ||
a7de4ef7 | 671 | /** récupère la requête utilisateur et échoue si le champ du formulaire ne représente pas une |
672 | * promotion (nombre à 4 chiffres) */ | |
0337d704 | 673 | function get_request() |
674 | { | |
675 | parent::get_request(); | |
676 | if (preg_match('/^[0-9]{2}$/', $this->value)){ | |
677 | $this->value = intval($this->value) + 1900; | |
678 | } | |
679 | if (!(empty($this->value) or preg_match('/^[0-9]{4}$/', $this->value))) { | |
a7de4ef7 | 680 | new ThrowError('La promotion est une année à quatre chiffres.'); |
0337d704 | 681 | } |
682 | } | |
683 | ||
684 | // }}} | |
685 | // {{{ function is_a_single_promo() | |
686 | ||
a7de4ef7 | 687 | /** teste si la requête est de la forme =promotion -> contrainte forte imposée -> elle suffit |
688 | * pour autoriser un affichage des résultats alors que <promotion est insuffisant */ | |
0337d704 | 689 | function is_a_single_promo() |
690 | { | |
691 | return ($this->compareField->value=='=' && $this->value!=''); | |
692 | } | |
693 | ||
694 | // }}} | |
695 | // {{{ function too_large() | |
696 | ||
697 | function too_large() | |
698 | { | |
699 | return !$this->is_a_single_promo(); | |
700 | } | |
701 | ||
702 | // }}} | |
703 | // {{{ function get_single_where_statement() | |
704 | ||
a7de4ef7 | 705 | /** clause WHERE correspondant à ce champ */ |
0337d704 | 706 | function get_single_where_statement($field) |
707 | { | |
708 | return $field.$this->compareField->value.$this->value; | |
709 | } | |
710 | ||
711 | // }}} | |
712 | // {{{ function get_url() | |
713 | ||
a7de4ef7 | 714 | /** récupérer le bout d'URL correspondant aux paramètres permettant d'imiter une requête |
715 | * d'un utilisateur assignant la valeur $this->value à ce champ et assignant l'opérateur de | |
716 | * comparaison adéquat */ | |
0337d704 | 717 | function get_url() |
718 | { | |
719 | if (!($u=parent::get_url())) { | |
720 | return false; | |
721 | } | |
722 | return $u.'&'.$this->compareField->get_url(); | |
723 | } | |
724 | ||
725 | // }}} | |
726 | } | |
727 | ||
728 | // }}} | |
729 | // {{{ class SFieldGroup [Group fields] | |
730 | ||
731 | /** classe groupant des champs de formulaire de recherche */ | |
732 | class SFieldGroup | |
733 | { | |
734 | // {{{ properties | |
94f6c381 | 735 | |
a7de4ef7 | 736 | /** tableau des classes correspondant aux champs groupés */ |
0337d704 | 737 | var $fields; |
738 | /** type de groupe : ET ou OU */ | |
739 | var $and; | |
740 | ||
741 | // }}} | |
742 | // {{{ constuctor | |
743 | ||
744 | /** constructeur */ | |
745 | function SFieldGroup($_and, $_fields) | |
746 | { | |
747 | $this->fields = $_fields; | |
748 | $this->and = $_and; | |
749 | } | |
750 | ||
751 | // }}} | |
752 | // {{{ function too_large() | |
753 | ||
754 | function too_large() | |
755 | { | |
756 | $b = true; | |
a2aa8436 | 757 | for ($i=0 ; $b && $i<count($this->fields) ; $i++) { |
758 | $b = $b && $this->fields[$i]->too_large(); | |
0337d704 | 759 | } |
760 | return $b; | |
761 | } | |
762 | ||
763 | // }}} | |
764 | // {{{ function field_get_select() | |
765 | ||
766 | function field_get_select($f) | |
767 | { | |
768 | return $f->get_select_statement(); | |
769 | } | |
770 | ||
771 | // }}} | |
772 | // {{{ function field_get_where() | |
773 | ||
a7de4ef7 | 774 | /** récupérer la clause WHERE d'un objet champ de recherche */ |
0337d704 | 775 | function field_get_where($f) |
776 | { | |
777 | return $f->get_where_statement(); | |
778 | } | |
779 | ||
780 | // }}} | |
781 | // {{{ function field_get_order() | |
782 | ||
a7de4ef7 | 783 | /** récupérer la clause ORDER BY d'un objet champ de recherche */ |
0337d704 | 784 | function field_get_order($f) |
785 | { | |
786 | return $f->get_order_statement(); | |
787 | } | |
788 | ||
789 | // }}} | |
790 | // {{{ function field_get_url() | |
791 | ||
a7de4ef7 | 792 | /** récupérer le bout d'URL correspondant à un objet champ de recherche */ |
0337d704 | 793 | function field_get_url($f) |
794 | { | |
795 | return $f->get_url(); | |
796 | } | |
94f6c381 | 797 | |
0337d704 | 798 | // }}} |
799 | // {{{ function get_select_statement() | |
800 | ||
801 | function get_select_statement() | |
802 | { | |
803 | return implode(' ', array_filter(array_map(array($this, 'field_get_select'), $this->fields))); | |
804 | } | |
805 | ||
806 | // }}} | |
807 | // {{{ function get_where_statement() | |
808 | ||
a7de4ef7 | 809 | /** récupérer la clause WHERE du groupe de champs = conjonction (ET) ou disjonction (OU) de |
810 | * clauses des champs élémentaires */ | |
0337d704 | 811 | function get_where_statement() |
812 | { | |
813 | $joinText = $this->and ? ' AND ' : ' OR '; | |
814 | $res = implode($joinText, array_filter(array_map(array($this, 'field_get_where'), $this->fields))); | |
815 | return $res == '' ? '' : "($res)"; | |
816 | } | |
817 | ||
818 | // }}} | |
819 | // {{{ function get_order_statement() | |
820 | ||
a7de4ef7 | 821 | /** récupérer la clause ORDER BY du groupe de champs = conjonction (ET) ou disjonction (OU) de |
822 | * clauses des champs élémentaires */ | |
0337d704 | 823 | function get_order_statement() |
824 | { | |
825 | $order = array_filter(array_map(array($this, 'field_get_order'), $this->fields)); | |
826 | return count($order)>0 ? implode(',', $order) : false; | |
827 | } | |
828 | ||
829 | // }}} | |
830 | // {{{ function get_url() | |
831 | ||
a7de4ef7 | 832 | /** récupérer le bout d'URL correspondant à ce groupe de champs = concaténation des bouts d'URL |
833 | * des champs élémentaires */ | |
0337d704 | 834 | function get_url($others=Array()) |
835 | { | |
836 | $url = array_filter(array_map(array($this, 'field_get_url'), $this->fields)); | |
837 | foreach ($url as $key=>$val) { | |
838 | if (empty($val)) { | |
839 | unset($url[$key]); | |
840 | } | |
841 | } | |
842 | foreach ($others as $key=>$val) { | |
843 | if (!empty($val)) { | |
844 | $url[] = "$key=$val"; | |
845 | } | |
846 | } | |
847 | return count($url)>0 ? implode('&', $url) : false; | |
848 | } | |
849 | ||
850 | // }}} | |
851 | } | |
852 | ||
853 | // }}} | |
854 | ||
a7de4ef7 | 855 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: |
0337d704 | 856 | ?> |