2 /***************************************************************************
3 * Copyright (C) 2003-2010 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
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. *
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. *
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 *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
23 /** This class stores all data for the different kinds of fields.
24 * It is only a dispatcher for the various DirEnum_XXX classes.
28 /** Name of availables Enumerations
29 * Each of these consts contains the basename of the class (its full name
30 * being DE_$basename).
32 const BINETS
= 'binets';
33 const SECTIONS
= 'sections';
34 const SCHOOLS
= 'schools';
35 const DEGREES
= 'degrees';
36 const STUDIESDOMAINS
= 'studiesdomains';
37 const NATIONALITIES
= 'nationalities';
38 const COUNTRIES
= 'countries';
39 const GROUPESX
= 'groupesx';
40 const SECTORS
= 'sectors';
41 const NETWORKS
= 'networking';
42 const ADMINAREAS
= 'adminareas';
43 const LOCALITIES
= 'localities'; // TODO
44 const COMPANIES
= 'companies'; // TODO
45 const JOBDESCRIPTION
= 'jobdescription'; // TODO
47 static private $enumerations = array();
49 static private function init($type)
51 $cls = "DE_" . ucfirst($type);
52 self
::$enumerations[$type] = new $cls();
55 /** Retrieves all options for a given type
56 * @param $type Type of enum for which options are requested
57 * @return XorgDbIterator over the results
58 * TODO : Find a way to get either an array, or the adequate PlIterator
60 static public function getOptions()
62 $args = func_get_args();
63 $type = array_shift($args);
64 if (!array_key_exists($type, self
::$enumerations)) {
67 $obj = self
::$enumerations[$type];
68 return call_user_func_array(array($obj, 'getOptions'), $args);
71 /** Retrieves all options with number of profiles for autocompletion
72 * @param $type Type of enum for which options are requested
73 * @param $text Text to autocomplete
74 * @return XorgDbIterator over the results
76 static public function getAutoComplete()
78 $args = func_get_args();
79 $type = array_shift($args);
80 if (!array_key_exists($type, self
::$enumerations)) {
83 $obj = self
::$enumerations[$type];
84 return call_user_func_array(array($obj, 'getAutoComplete'), $args);
87 /** Retrieves a list of IDs for a given type
88 * @param $type Type of enum for which IDs are requested
89 * @param $text Text to search in enum valuees
90 * @param $mode Mode of search for those IDs (prefix/suffix/infix)
92 static public function getIDs()
94 $args = func_get_args();
95 $type = array_shift($args);
96 if (!array_key_exists($type, self
::$enumerations)) {
99 $obj = self
::$enumerations[$type];
100 return call_user_func_array(array($obj, 'getIDs'), $args);
105 // {{{ class DirEnumeration
106 abstract class DirEnumeration
108 /** Modes for LIKE searches
110 const MODE_EXACT
= 0x000;
111 const MODE_PREFIX
= 0x001;
112 const MODE_SUFFIX
= 0x002;
113 const MODE_CONTAINS
= 0x003;
115 /** An internal array of ID => optionTxt
119 /** Description of the MySQL storage of the fields
121 protected $idfield = 'id';
122 protected $valfield = 'text';
123 protected $valfield2 = null
;
125 protected $join = '';
126 protected $where = '';
128 /** Fields for autocompletion
130 protected $ac_join = ''; // Additional joins
131 protected $ac_where = null
; // Additional where
132 protected $ac_beginwith = true
; // Whether to search for 'x%' or for '%x%'
133 protected $ac_unique; // Which field is to be taken as unique
134 protected $ac_distinct = true
; // Whether we want to keep only distinct valfield value
135 protected $ac_withid = true
; // Do we want to fetch id too ?
137 public function __construct() {
138 $this->loadOptions();
141 public function getOptions()
143 return $this->options
;
146 // {{{ function getIDs
147 /** Retrieves possible IDs for given text
148 * @param $text Text to search for IDs
149 * @param $mode Mode of search (PREFIX, SUFFIX, CONTAINS)
150 * @return An array of matching IDs ; if empty, input should be considered invalid
152 public function getIDs($text, $mode)
154 if ($mode == self
::MODE_EXACT
) {
155 $options = $this->getOptions();
156 return array_keys($options, $text);
158 if ($this->where
== null
) {
161 $where = $this->where
. ' AND ';
164 $conds[] = $this->valfield
. self
::makeSqlConcat($text, $mode);
165 if ($this->valfield2
!= null
) {
166 $conds[] = $this->valfield2
. self
::makeSqlConcat($text, $mode);
168 $where .= '(' . implode(' OR ', $conds) . ')';
170 return XDB
::fetchColumn('SELECT ' . $this->idfield
. '
171 FROM ' . $this->from
. '
174 GROUP BY ' . $this->idfield
);
179 private function mkTests($field, $text)
182 $tests[] = $field . self
::makeSqlConcat($text, self
::MODE_PREFIX
);
183 if (!$this->ac_beginwith
) {
184 $tests[] = $field . self
::makeSqlConcat(' ' . $text, self
::MODE_CONTAINS
);
185 $tests[] = $field . self
::makeSqlConcat('-' . $text, self
::MODE_CONTAINS
);
190 // {{{ function getAutoComplete
191 public function getAutoComplete($text)
193 $text = str_replace(array('%', '_'), '', $text);
195 if (is_null($this->ac_where
) ||
$this->ac_where
== '') {
198 $where = $this->ac_where
. ' AND ';
201 $tests = $this->mkTests($this->valfield
, $text);
202 if (!is_null($this->valfield2
)) {
203 $tests = array_merge($tests, $this->mkTests($this->valfield2
, $text));
206 $where .= '(' . implode(' OR ', $tests) . ')';
208 return XDB
::iterator('SELECT ' . $this->valfield
. ' AS field'
209 . ($this->ac_distinct ?
(', COUNT(DISTINCT ' . $this->ac_unique
. ') AS nb') : '')
210 . ($this->ac_withid ?
(', ' . $this->idfield
. ' AS id') : '') . '
211 FROM ' . $this->from
. '
212 ' . $this->ac_join
. '
214 GROUP BY ' . $this->valfield
. '
215 ORDER BY ' . ($this->ac_distinct ?
'nb DESC' : $this->valfield
) . '
220 // {{{ function makeSqlConcat
221 static protected function makeSqlConcat($text, $mode)
223 if ($mode == self
::MODE_EXACT
) {
224 return ' = ' . XDB
::format('{?}', $text);
226 if ($mode == self
::MODE_PREFIX
) {
227 $right = XDB
::format('CONCAT({?}, \'%\')', $text);
228 } else if ($mode == self
::MODE_SUFFIX
) {
229 $right = XDB
::format('CONCAT(\'%\', {?})', $text);
231 $right = XDB
::format('CONCAT(\'%\', {?}, \'%\')', $text);
233 return ' LIKE ' . $right;
237 // {{{ function loadOptions
238 /** The function used to load options
240 protected function loadOptions()
242 $this->options
= XDB
::iterator('SELECT ' . $this->valfield
. ' AS field,
243 ' . $this->idfield
. ' AS id
244 FROM ' . $this->from
. '
247 GROUP BY ' . $this->valfield
. '
248 ORDER BY ' . $this->valfield
);
254 // {{{ class DE_Binets
255 class DE_Binets
extends DirEnumeration
257 protected $from = 'binets_def';
259 protected $ac_join = 'INNER JOIN binets_ins ON (binets_def.id = binets_ins.binet_id)';
260 protected $ac_unique = 'binets_ins.user_id';
264 // {{{ class DE_Sections
265 class DE_Sections
extends DirEnumeration
267 protected $from = 'sections';
269 protected $ac_join = 'INNER JOIN profiles ON (profiles.section = sections.id)';
270 protected $ac_unique = 'profiles.pid';
274 // {{{ class DE_Schools
275 class DE_Schools
extends DirEnumeration
277 protected $valfield = 'name';
278 protected $valfield2 = 'abbreviation';
279 protected $from = 'profile_education_enum';
281 protected $ac_join = 'INNER JOIN profile_education ON (profile_education.eduid = profile_education_enum.id)';
282 protected $ac_unique = 'profile_education.uid';
286 // {{{ class DE_Degrees
287 class DE_Degrees
extends DirEnumeration
289 protected $from = 'profile_education_degree_enum';
290 protected $valfield = 'degree';
292 protected $suboptions = array();
294 protected function loadOptions()
296 $res = XDB
::query('SELECT ped.eduid, ped.degreeid, pede.degree
297 FROM profile_education_enum AS pee
298 LEFT JOIN profile_education_degree AS ped ON (pee.id = ped.eduid)
299 LEFT JOIN profile_education_degree_enum AS pede ON (ped.degreeid = pede.id)
300 ORDER BY pede.degree');
301 foreach($res->fetchAllRow() as $row) {
302 list($eduid, $degreeid, $name) = $row;
303 $this->options
[$degreeid] = array('id' => $degreeid, 'field' => $name);
304 if (!array_key_exists($eduid, $this->suboptions
)) {
305 $this->suboptions
[$eduid] = array();
307 $this->suboptions
[$eduid][] = array('id' => $degreeid, 'field' => $name);
311 public function getOptions($eduid = null
)
313 if ($eduid == null
) {
314 return PlIteratorUtils
::fromArray($this->options
, 1, true
);
316 if (array_key_exists($eduid, $this->suboptions
)) {
317 return PlIteratorUtils
::fromArray($this->suboptions
[$eduid], 1, true
);
323 public function getIDs($text, $mode, $eduid = null
)
325 if ($eduid == null
) {
326 return XDB
::fetchColumn('SELECT id
327 FROM profile_education_degree_enum
328 WHERE degree ' . self
::makeSqlConcat($text, $mode));
330 return XDB
::fetchColumn('SELECT pede.id
331 FROM profile_education_degree AS ped
332 LEFT JOIN profile_education_degree_enum AS pede ON (ped.degreeid = pede.id)
333 WHERE ped.eduid = {?} AND pede.degree ' . self
::makeSqlConcat($text, $mode), $eduid);
339 // {{{ class DE_StudiesSector
340 class DE_StudiesSector
extends DirEnumeration
342 protected $valfield = 'field';
343 protected $from = 'profile_education_field_enum';
345 protected $ac_join = 'INNER JOIN profile_education ON (profile_education.fieldid = profile_education_field_enum.id)';
346 protected $ac_unique = 'profile_education.uid';
350 // {{{ class DE_Nationalities
351 class DE_Nationalities
extends DirEnumeration
353 protected $idfield = 'iso_3166_1_a2';
354 protected $valfield = 'nationalityFR';
355 protected $valfield2 = 'nationality';
356 protected $from = 'geoloc_countries AS gc';
357 protected $join = 'INNER JOIN profiles AS p ON (gc.iso_3166_1_a2 IN (p.nationality1, p.nationality2, p.nationality3))';
359 protected $ac_join = 'INNER JOIN profiles AS p ON (gc.iso_3166_1_a2 IN (p.nationality1, p.nationality2, p.nationality3))';
360 protected $ac_unique = 'profiles.pid';
364 // {{{ class DE_Countries
365 class DE_Countries
extends DirEnumeration
367 protected $idfield = 'iso_3166_1_a2';
368 protected $valfield = 'countryFR';
369 protected $valfield2 = 'country';
370 protected $from = 'geoloc_countries';
372 protected $ac_join = 'INNER JOIN profile_addresses ON (geoloc_countries.iso_3166_1_a2 = profile_addresses.countryFR';
373 protected $ac_unique = 'profile_addresses.pid';
377 // {{{ class DE_AdminAreas
378 class DE_AdminAreas
extends DirEnumeration
380 protected $suboptions = array();
382 protected function loadOptions()
384 $res = XDB
::query('SELECT id, name AS field, country
385 FROM geoloc_administrativeareas
388 foreach($res->fetchAllRow() as $row) {
389 list($id, $field, $country) = $row;
390 $this->options
[] = array('id' => $id, 'field' => $field);
391 if (!array_key_exists($country, $this->suboptions
)) {
392 $this->suboptions
[$country] = array();
394 $this->suboptions
[$country][] = array('id' => $id, 'field' => $field);
398 public function getOptions($country = null
)
400 if ($country == null
) {
401 return PlIteratorUtils
::fromArray($this->options
, 1, true
);
403 if (array_key_exists($country, $this->suboptions
)) {
404 return PlIteratorUtils
::fromArray($this->suboptions
[$country], 1, true
);
410 public function getIDs($text, $mode, $country = null
)
412 if ($country == null
) {
413 return XDB
::fetchColumn('SELECT id
414 FROM geoloc_administrativeareas
415 WHERE name ' . self
::makeSqlConcat($text, $mode));
417 return XDB
::fetchColumn('SELECT id
418 FROM geoloc_administrativeareas
419 WHERE country = {?} AND name' . self
::makeSqlConcat($text, $mode), $country);
425 // {{{ class DE_GroupesX
426 class DE_GroupesX
extends DirEnumeration
428 protected $idfield = 'asso.id';
429 protected $valfield = 'asso.nom';
430 protected $valfield2 = 'asso.diminutif';
431 protected $from = '#groupex#.asso AS asso';
432 protected $where = 'WHERE (cat = \'GroupesX\' OR cat = \'Institutions\') AND pub = \'public\'';
434 protected $ac_join = "INNER JOIN #groupex#.membres AS memb ON (asso.id = memb.asso_id
435 AND (asso.cat = 'GroupesX' OR asso.cat = 'Institutions')
436 AND asso.pub = 'public')";
437 protected $ac_unique = 'memb.uid';
441 // {{{ class DE_Sectors
442 class DE_Sectors
extends DirEnumeration
444 protected $valfield = 'name';
445 protected $from = 'profile_job_sector_enum';
447 protected $ac_join = 'INNER JOIN profile_job ON (profile_job_sector_enum.id = profile_job.sectorid)';
448 protected $ac_unique = 'profile_job.uid';
452 // {{{ class DE_Networking
453 class DE_Networking
extends DirEnumeration
455 protected $idfield = 'profile_networking_enum.network_type';
456 protected $valfield = 'profile_networking_enum.name';
457 protected $from = 'profile_networking_enum';
460 protected $ac_join = 'INNER JOIN profile_networking ON (profile_networking.network_type = profile_networking_enum.network_type';
461 protected $ac_unique = 'profile_networking.uid';