X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=modules%2Fsearch%2Fclasses.inc.php;h=f6922bd67278fd1d9e2ec0daa68dad23ad97a612;hb=9797734d81089ee75f6fa3e855d48b9a9bc5523a;hp=2ab47329dc70fd08587627d7b1ad468cf94f72df;hpb=a14159bffdc1ea08c97e6634dc1480619bdc478a;p=platal.git diff --git a/modules/search/classes.inc.php b/modules/search/classes.inc.php index 2ab4732..f6922bd 100644 --- a/modules/search/classes.inc.php +++ b/modules/search/classes.inc.php @@ -1,6 +1,6 @@ search->result_fields = ' - u.user_id, u.promo, u.matricule, u.matricule_ax, - if(u.nom_usage=\'\', u.nom, u.nom_usage) AS NomSortKey, - u.nom_usage,u.date, - u.deces!=0 AS dcd,u.deces, - u.perms IN (\'admin\',\'user\', \'disabled\') AS inscrit, - u.perms != \'pending\' AS wasinscrit, - FIND_IN_SET(\'femme\', u.flags) AS sexe, - a.alias AS forlife, - ad0.text AS app0text, ad0.url AS app0url, ai0.type AS app0type, - ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type, - es.label AS secteur, ef.fonction_fr AS fonction, - IF(n.nat=\'\',n.pays,n.nat) AS nat, n.a2 AS iso3166, - COUNT(em.email) > 0 AS actif,'; +@$globals->search->result_fields = ' + u.user_id, u.promo, u.matricule, u.matricule_ax, + if(u.nom_usage=\'\', u.nom, u.nom_usage) AS NomSortKey, + u.nom_usage,u.date, + u.deces!=0 AS dcd,u.deces, + u.perms IN (\'admin\',\'user\', \'disabled\') AS inscrit, + u.perms != \'pending\' AS wasinscrit, + FIND_IN_SET(\'femme\', u.flags) AS sexe, + a.alias AS forlife, + ad0.text AS app0text, ad0.url AS app0url, ai0.type AS app0type, + ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type, + es.label AS secteur, ef.fonction_fr AS fonction, + IF(n.nat=\'\',n.pays,n.nat) AS nat, n.a2 AS iso3166, + COUNT(em.email) > 0 AS actif,'; // hide private information if not logged -if (S::logged()) - $globals->search->result_fields .=' - q.profile_web AS web, - q.profile_mobile AS mobile, - q.profile_freetext AS freetext, - adr.city, gp.pays AS countrytxt, gr.name AS region, - e.entreprise,'; +if (S::logged()) + $globals->search->result_fields .=' + q.profile_web AS web, + q.profile_mobile AS mobile, + q.profile_freetext AS freetext, + adr.city, gp.pays AS countrytxt, gr.name AS region, + e.entreprise,'; else - $globals->search->result_fields .=" - IF(q.profile_web_pub='public', q.profile_web, '') AS web, - IF(q.profile_mobile_pub='public', q.profile_mobile, '') AS mobile, - IF(q.profile_freetext_pub='public', q.profile_freetext, '') AS freetext, - IF(adr.pub='public', adr.city, '') AS city, - IF(adr.pub='public', gp.pays, '') AS countrytxt, - IF(adr.pub='public', gr.name, '') AS region, - IF(e.pub='public', e.entreprise, '') AS entreprise,"; -$globals->search->result_where_statement = ' - LEFT JOIN applis_ins AS ai0 ON (u.user_id = ai0.uid AND ai0.ordre = 0) - LEFT JOIN applis_def AS ad0 ON (ad0.id = ai0.aid) - LEFT JOIN applis_ins AS ai1 ON (u.user_id = ai1.uid AND ai1.ordre = 1) - LEFT JOIN applis_def AS ad1 ON (ad1.id = ai1.aid) - LEFT JOIN entreprises AS e ON (e.entrid = 0 AND e.uid = u.user_id) - LEFT JOIN emploi_secteur AS es ON (e.secteur = es.id) - LEFT JOIN fonctions_def AS ef ON (e.fonction = ef.id) - LEFT JOIN geoloc_pays AS n ON (u.nationalite = n.a2) - LEFT JOIN adresses AS adr ON (u.user_id = adr.uid AND FIND_IN_SET(\'active\',adr.statut)) - LEFT JOIN geoloc_pays AS gp ON (adr.country = gp.a2) - LEFT JOIN geoloc_region AS gr ON (adr.country = gr.a2 AND adr.region = gr.region) - LEFT JOIN emails AS em ON (em.uid = u.user_id AND em.flags = \'active\')'; - -// }}} -// {{{ function display_lines() - -/** - * This function is a heuristic that approximatively tells - * how many lines of output the contact list will use. - */ -function display_lines($text) -{ - $n = 0; - $tokens = Array('', '
'); - foreach ($tokens as $t) { - $i = -1; - while ( ($i = strpos($text,$t,$i+1))!==false) { $n++; } - } - return $n; -} + $globals->search->result_fields .=" + IF(q.profile_web_pub='public', q.profile_web, '') AS web, + IF(q.profile_mobile_pub='public', q.profile_mobile, '') AS mobile, + IF(q.profile_freetext_pub='public', q.profile_freetext, '') AS freetext, + IF(adr.pub='public', adr.city, '') AS city, + IF(adr.pub='public', gp.pays, '') AS countrytxt, + IF(adr.pub='public', gr.name, '') AS region, + IF(e.pub='public', e.entreprise, '') AS entreprise,"; +@$globals->search->result_where_statement = ' + LEFT JOIN applis_ins AS ai0 ON (u.user_id = ai0.uid AND ai0.ordre = 0) + LEFT JOIN applis_def AS ad0 ON (ad0.id = ai0.aid) + LEFT JOIN applis_ins AS ai1 ON (u.user_id = ai1.uid AND ai1.ordre = 1) + LEFT JOIN applis_def AS ad1 ON (ad1.id = ai1.aid) + LEFT JOIN entreprises AS e ON (e.entrid = 0 AND e.uid = u.user_id) + LEFT JOIN emploi_secteur AS es ON (e.secteur = es.id) + LEFT JOIN fonctions_def AS ef ON (e.fonction = ef.id) + LEFT JOIN geoloc_pays AS n ON (u.nationalite = n.a2) + LEFT JOIN adresses AS adr ON (u.user_id = adr.uid AND FIND_IN_SET(\'active\',adr.statut)) + LEFT JOIN geoloc_pays AS gp ON (adr.country = gp.a2) + LEFT JOIN geoloc_region AS gr ON (adr.country = gr.a2 AND adr.region = gr.region) + LEFT JOIN emails AS em ON (em.uid = u.user_id AND em.flags = \'active\')'; // }}} // {{{ class ThrowError @@ -96,12 +78,24 @@ function display_lines($text) */ class ThrowError { + public static $throwHook = array('ThrowError', 'defaultHandler'); + /** constuctor * @param $explain string the error (in natural language) */ - function ThrowError($explain) + public function __construct($explain) { - global $page; + call_user_func(ThrowError::$throwHook, $explain); + } + + /** defaut error handler + */ + private static function defaultHandler($explain) + { + global $page, $globals; + $page->changeTpl('search/index.tpl'); + $page->assign('xorg_title','Polytechnique.org - Annuaire'); + $page->assign('baseurl', $globals->baseurl); $page->trig('Erreur : '.$explain); $page->run(); } @@ -117,7 +111,7 @@ class ThrowError class SField { // {{{ properties - + /** le nom du champ dans le formulaire HTML */ var $fieldFormName; /** champs de la bdd correspondant à ce champ sous forme d'un tableau */ @@ -144,7 +138,7 @@ class SField // }}} // {{{ function get_request() - /** récupérer la requête de l'utilisateur + /** récupérer la requête de l'utilisateur * on met une chaîne vide si le champ n'a pas été complété */ function get_request() { @@ -153,9 +147,9 @@ class SField // }}} // {{{ function get_where_statement() - + /** récupérer la clause correspondant au champ dans la clause WHERE de la requête - * on parcourt l'ensemble des champs de la bdd de $fieldDbName et on associe + * on parcourt l'ensemble des champs de la bdd de $fieldDbName et on associe * à chacun d'entre eux une clause spécifique * la clause totale et la disjonction de ces clauses spécifiques */ function get_where_statement() @@ -169,7 +163,7 @@ class SField // }}} // {{{ function get_order_statement() - + /** récupérer la clause correspondant au champ dans la clause ORDER BY de la requête * utilisé par exemple pour placer d'abord le nom égal à la requête avant les approximations */ function get_order_statement() @@ -208,15 +202,18 @@ class SField class QuickSearch extends SField { // {{{ properties - + /** stores tokens */ var $strings; /** stores numerical ranges */ var $ranges; + /** stores admin searches */ + var $email; + var $ip; // }}} // {{{ constructor - + function QuickSearch($_fieldFormName) { $this->fieldFormName = $_fieldFormName; @@ -231,62 +228,90 @@ class QuickSearch extends SField function isempty() { - return empty($this->strings) && empty($this->ranges); + return empty($this->strings) && empty($this->ranges) && empty($this->email) && empty($this->ip); } // }}} // {{{ function get_request() - + function get_request() { - parent::get_request(); - $s = replace_accent(trim($this->value)); - $s = preg_replace('!\d+!', ' ', $s); - $s = str_replace('*','%',$s); - $this->strings = preg_split("![^a-zA-Z%]+!",$s, -1, PREG_SPLIT_NO_EMPTY); + parent::get_request(); + $s = replace_accent(trim($this->value)); + $r = $s = str_replace('*','%',$s); - $s = trim($this->value); - $s = preg_replace('! *- *!', '-', $s); - $s = preg_replace('!([<>]) *!', ' \1', $s); - $s = preg_replace('![^0-9\-><]!', ' ', $s); - $s = preg_replace('![<>\-] !', '', $s); - $ranges = preg_split('! +!', $s, -1, PREG_SPLIT_NO_EMPTY); - $this->ranges=Array(); - foreach ($ranges as $r) { - if (preg_match('!^([<>]\d{4}|\d{4}(-\d{4})?)$!', $r)) $this->ranges[] = $r; - } + if (S::has_perms() && strpos($s, '@') !== false) { + $this->email = $s; + } else if (S::has_perms() && preg_match('/[0-9]+\.([0-9]+|%)\.([0-9]+|%)\.([0-9]+|%)/', $s)) { + $this->ip = $s; + } + if ($this->email || $this->ip) { + $this->strings = $this->ranges = array(); + return; + } + + $s = preg_replace('!\d+!', ' ', $s); + $this->strings = preg_split("![^a-zA-Z%]+!",$s, -1, PREG_SPLIT_NO_EMPTY); + if (count($this->strings) > 5) { + global $page; + $page->trig("Tu as indiqué trop d'éléments dans ta recherche, seuls les 5 premiers seront pris en compte"); + $this->strings = array_slice($this->strings, 0, 5); + } + + $s = preg_replace('! *- *!', '-', $r); + $s = preg_replace('!([<>]) *!', ' \1', $s); + $s = preg_replace('![^0-9\-><]!', ' ', $s); + $s = preg_replace('![<>\-] !', '', $s); + $ranges = preg_split('! +!', $s, -1, PREG_SPLIT_NO_EMPTY); + $this->ranges=Array(); + foreach ($ranges as $r) { + if (preg_match('!^([<>]\d{4}|\d{4}(-\d{4})?)$!', $r)) $this->ranges[] = $r; + } } // }}} // {{{ function get_where_statement() - + function get_where_statement() { - $where = Array(); - foreach ($this->strings as $i => $s) { - $t = str_replace('*', '%', $s).'%'; - $t = str_replace('%%', '%', $t); - $where[] = "sn$i.token LIKE '$t'"; - } - - $wherep = Array(); - foreach ($this->ranges as $r) { - if (preg_match('!^\d{4}$!', $r)) { - $wherep[] = "u.promo=$r"; - } elseif (preg_match('!^(\d{4})-(\d{4})$!', $r, $matches)) { - $p1=min(intval($matches[1]), intval($matches[2])); - $p2=max(intval($matches[1]), intval($matches[2])); - $wherep[] = "(u.promo>=$p1 AND u.promo<=$p2)"; - } elseif (preg_match('!^<(\d{4})!', $r, $matches)) { - $wherep[] = "u.promo<={$matches[1]}"; - } elseif (preg_match('!^>(\d{4})!', $r, $matches)) { - $wherep[] = "u.promo>={$matches[1]}"; - } - } - if (!empty($wherep)) { + $where = Array(); + foreach ($this->strings as $i => $s) { + if (Env::i('with_soundex') && strlen($s) > 1) { + $t = soundex_fr($s); + $where[] = "sn$i.soundex = '$t'"; + } else { + $t = str_replace('*', '%', $s).'%'; + $t = str_replace('%%', '%', $t); + $where[] = "sn$i.token LIKE '$t'"; + } + } + + $wherep = Array(); + foreach ($this->ranges as $r) { + if (preg_match('!^\d{4}$!', $r)) { + $wherep[] = "u.promo=$r"; + } elseif (preg_match('!^(\d{4})-(\d{4})$!', $r, $matches)) { + $p1=min(intval($matches[1]), intval($matches[2])); + $p2=max(intval($matches[1]), intval($matches[2])); + $wherep[] = "(u.promo>=$p1 AND u.promo<=$p2)"; + } elseif (preg_match('!^<(\d{4})!', $r, $matches)) { + $wherep[] = "u.promo<={$matches[1]}"; + } elseif (preg_match('!^>(\d{4})!', $r, $matches)) { + $wherep[] = "u.promo>={$matches[1]}"; + } + } + if (!empty($wherep)) { $where[] = '('.join(' OR ',$wherep).')'; } - return join(" AND ", $where); + if (!empty($this->email)) { + $where[] = 'ems.email = ' . XDB::escape($this->email); + } + if (!empty($this->ip)) { + $ip = ip_to_uint($this->ip); + $where[] = "( ls.ip = $ip OR ls.forward_ip = $ip )"; + } + + return join(" AND ", $where); } // }}} @@ -294,14 +319,27 @@ class QuickSearch extends SField function get_select_statement() { $join = ""; - foreach ($this->strings as $i => $s) { - $join .= "INNER JOIN search_name AS sn$i ON (u.user_id = sn$i.uid)\n"; + $and = ''; + $uniq = ''; + foreach ($this->strings as $i => $s) { + if (!S::logged()) { + $and = "AND FIND_IN_SET('public', sn$i.flags)"; + } + $myu = str_replace('snv', "sn$i", $uniq); + $join .= "INNER JOIN search_name AS sn$i ON (u.user_id = sn$i.uid $and$myu)\n"; + $uniq .= " AND sn$i.token != snv.token"; + } + if (!empty($this->email)) { + $join .= "LEFT JOIN emails AS ems ON (ems.uid = u.user_id)"; + } + if (!empty($this->ip)) { + $join .= "INNER JOIN logger.sessions AS ls ON (ls.uid = u.user_id)\n"; } return $join; } // }}} // {{{ function get_order_statement() - + function get_order_statement() { return false; @@ -309,11 +347,11 @@ class QuickSearch extends SField // }}} // {{{ function get_score_statement - + function get_score_statement() { $sum = array('0'); - foreach ($this->strings as $i => $s) { + foreach ($this->strings as $i => $s) { $sum[] .= "SUM(sn$i.score + IF('$s'=sn$i.token,5,0))"; } return join('+', $sum).' AS score'; @@ -330,7 +368,7 @@ class QuickSearch extends SField class NumericSField extends SField { // {{{ constructor - + /** constructeur * (récupère la requête de l'utilisateur pour ce champ) */ function NumericSField($_fieldFormName) @@ -341,7 +379,7 @@ class NumericSField extends SField // }}} // {{{ function get_request() - + /** récupère la requête de l'utilisateur et échoue s'il ne s'agit pas d'un entier */ function get_request() { @@ -353,7 +391,7 @@ class NumericSField extends SField new ThrowError('Un champ numérique contient des caractères alphanumériques.'); } } - + // }}} } @@ -363,7 +401,7 @@ class NumericSField extends SField class RefSField extends SField { // {{{ properties - + var $refTable; var $refAlias; var $refCondition; @@ -385,7 +423,7 @@ class RefSField extends SField // }}} // {{{ function get_request() - + function get_request() { parent::get_request(); if ($this->value=='00' || $this->value=='0') { @@ -435,7 +473,16 @@ class RefSField extends SField return false; } $res = implode(' OR ', array_filter(array_map(array($this, 'get_single_match_statement'), $this->fieldDbName))); - return "INNER JOIN {$this->refTable} AS {$this->refAlias} ON ({$this->refCondition} AND ($res) )"; + if (is_array($this->refTable)) { + foreach ($this->refTable as $i => $refT) + $last = $i; + $inner = ""; + foreach ($this->refTable as $i => $refT) + $inner .= " INNER JOIN {$refT} AS {$this->refAlias[$i]} ON ({$this->refCondition[$i]} ".(($i == $last)?"AND ($res) ":"").")\n"; + return $inner; + } else { + return "INNER JOIN {$this->refTable} AS {$this->refAlias} ON ({$this->refCondition} AND ($res) )"; + } } // }}} @@ -446,16 +493,18 @@ class RefSField extends SField // {{{ class RefSFieldMultipleTable class MapSField extends RefSField { - var $mapId; - + var $mapId; + function MapSField($_fieldFormName, $_fieldDbName='', $_refTable, $_refAlias, $_refCondition, $_mapId=false) { if ($_mapId === false) $this->mapId = Env::v($_fieldFormName, ''); else $this->mapId = $_mapId; + $this->value = $this->mapId; $this->RefSField($_fieldFormName, $_fieldDbName, $_refTable, $_refAlias, $_refCondition, true, false); } + function get_select_statement() { if ($this->mapId === '') return false; @@ -478,10 +527,10 @@ class MapSField extends RefSField class RefWithSoundexSField extends RefSField { // {{{ function compare() - + function compare() { - return "='".soundex_fr($this->value)."'"; + return "='".soundex_fr($this->value)."'"; } // }}} @@ -495,7 +544,7 @@ class RefWithSoundexSField extends RefSField class StringSField extends SField { // {{{ function get_request() - + /** récupère la requête de l'utilisateur et échoue si la chaîne contient des caractères * interdits */ function get_request() @@ -562,7 +611,7 @@ class StringSField extends SField class NameSField extends StringSField { // {{{ function get_single_where_statement() - + function get_single_where_statement($field) { $regexp = strtr(addslashes($this->value), '-*', '_%'); @@ -571,7 +620,7 @@ class NameSField extends StringSField // }}} // {{{ function get_order_statement() - + function get_order_statement() { if ($this->value!='' && $this->fieldResultName!='') { @@ -609,14 +658,14 @@ class StringWithSoundexSField extends StringSField class PromoSField extends SField { // {{{ properties - + /** opérateur de comparaison (<,>,=) de la promo utilisé pour ce champ de formulaire */ var $compareField; // }}} // {{{ constructor - /** constructeur + /** constructeur * compareField est un champ de formulaire très simple qui ne sert qu'à la construction de la * clause WHERE de la promo */ function PromoSField($_fieldFormName, $_compareFieldFormName, $_fieldDbName, $_fieldResultName) @@ -692,7 +741,7 @@ class PromoSField extends SField class SFieldGroup { // {{{ properties - + /** tableau des classes correspondant aux champs groupés */ var $fields; /** type de groupe : ET ou OU */ @@ -706,6 +755,11 @@ class SFieldGroup { $this->fields = $_fields; $this->and = $_and; + foreach ($this->fields as $key=>&$field) { + if (is_null($field)) { + unset($this->fields[$key]); + } + } } // }}} @@ -714,8 +768,10 @@ class SFieldGroup function too_large() { $b = true; - for ($i=0; $b && $ifields); $i++) { - $b &= $this->fields[$i]->too_large(); + for ($i=0 ; $b && $ifields) ; $i++) { + if (!is_null($this->fields[$i])) { + $b = $b && $this->fields[$i]->too_large(); + } } return $b; } @@ -754,7 +810,7 @@ class SFieldGroup { return $f->get_url(); } - + // }}} // {{{ function get_select_statement()