d44a111c3c45e83023a9cefd9f2b85de69990252
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 NAMETYPES
= 'nametypes';
34 const BINETS
= 'binets';
35 const GROUPESX
= 'groupesx';
36 const SECTIONS
= 'sections';
38 const EDUSCHOOLS
= 'educationschools';
39 const EDUDEGREES
= 'educationdegrees';
40 const EDUFIELDS
= 'educationfields';
42 const NATIONALITIES
= 'nationalities';
43 const COUNTRIES
= 'countries';
44 const ADMINAREAS
= 'adminareas';
45 const LOCALITIES
= 'localities';
47 const COMPANIES
= 'companies';
48 const SECTORS
= 'sectors';
49 const JOBDESCRIPTION
= 'jobdescription';
51 const NETWORKS
= 'networking';
53 static private $enumerations = array();
55 static private function init($type)
57 $cls = "DE_" . ucfirst($type);
58 self
::$enumerations[$type] = new $cls();
61 /** Retrieves all options for a given type
62 * @param $type Type of enum for which options are requested
63 * @return Array of the results
65 static public function getOptions()
67 $args = func_get_args();
68 $type = array_shift($args);
69 if (!array_key_exists($type, self
::$enumerations)) {
72 $obj = self
::$enumerations[$type];
73 if ($obj->capabilities
& DirEnumeration
::HAS_OPTIONS
) {
74 return call_user_func_array(array($obj, 'getOptions'), $args);
80 /** Retrieves all options for a given type
81 * @param $type Type of enum for which options are requested
82 * @return PlIterator over the results
84 static public function getOptionsIter()
86 $args = func_get_args();
87 $type = array_shift($args);
88 if (!array_key_exists($type, self
::$enumerations)) {
91 $obj = self
::$enumerations[$type];
92 if ($obj->capabilities
& DirEnumeration
::HAS_OPTIONS
) {
93 return call_user_func_array(array($obj, 'getOptionsIter'), $args);
95 return PlIteratorUtils
::fromArray(array());
99 /** Retrieves all options with number of profiles for autocompletion
100 * @param $type Type of enum for which options are requested
101 * @param $text Text to autocomplete
102 * @return PlIterator over the results
104 static public function getAutoComplete()
106 $args = func_get_args();
107 $type = array_shift($args);
108 if (!array_key_exists($type, self
::$enumerations)) {
111 $obj = self
::$enumerations[$type];
112 if ($obj->capabilities
& DirEnumeration
::HAS_AUTOCOMP
) {
113 return call_user_func_array(array($obj, 'getAutoComplete'), $args);
115 return PlIteratorUtils
::fromArray(array());
119 /** Retrieves a list of IDs for a given type
120 * @param $type Type of enum for which IDs are requested
121 * @param $text Text to search in enum valuees
122 * @param $mode Mode of search for those IDs (prefix/suffix/infix)
124 static public function getIDs()
126 $args = func_get_args();
127 $type = array_shift($args);
128 if (!array_key_exists($type, self
::$enumerations)) {
131 $obj = self
::$enumerations[$type];
132 if ($obj->capabilities
& DirEnumeration
::HAS_OPTIONS
) {
133 return call_user_func_array(array($obj, 'getIDs'), $args);
141 // {{{ class DirEnumeration
142 abstract class DirEnumeration
144 const AUTOCOMPLETE_LIMIT
= 11;
146 const HAS_OPTIONS
= 0x001;
147 const HAS_AUTOCOMP
= 0x002;
149 public $capabilities = 0x003; // self::HAS_OPTIONS | self::HAS_AUTOCOMP;
151 /** An internal array of ID => optionTxt
153 protected $options = null
;
155 /** Description of the MySQL storage of the fields
157 protected $idfield = 'id';
158 protected $valfield = 'text';
159 protected $valfield2 = null
;
161 protected $join = '';
162 protected $where = '';
164 /** Fields for autocompletion
166 protected $ac_join = ''; // Additional joins
167 protected $ac_where = null
; // Additional where
168 protected $ac_beginwith = true
; // Whether to search for 'x%' or for '%x%'
169 protected $ac_unique; // Which field is to be taken as unique
170 protected $ac_distinct = true
; // Whether we want to keep only distinct valfield value
171 protected $ac_withid = true
; // Do we want to fetch id too ?
173 protected function _fetchOptions()
175 if (is_null($this->options
)) {
176 $this->loadOptions();
180 public function getOptions()
182 $this->_fetchOptions();
183 return $this->options
;
186 public function getOptionsIter()
188 return PlIteratorUtils
::fromArray(self
::expandArray($this->getOptions()), 1, true
);
191 // {{{ function getIDs
192 /** Retrieves possible IDs for given text
193 * @param $text Text to search for IDs
194 * @param $mode Mode of search (PREFIX, SUFFIX, CONTAINS)
195 * @return An array of matching IDs ; if empty, input should be considered invalid
197 public function getIDs($text, $mode)
199 if ($mode == XDB
::WILDCARD_EXACT
) {
200 $options = $this->getOptions();
201 return array_keys($options, $text);
203 if ($this->where
== null
) {
206 $where = $this->where
. ' AND ';
209 $conds[] = $this->valfield
. XDB
::formatWildcards($mode, $text);
210 if ($this->valfield2
!= null
) {
211 $conds[] = $this->valfield2
. XDB
::formatWildcards($mode, $text);
213 $where .= '(' . implode(' OR ', $conds) . ')';
215 return XDB
::fetchColumn('SELECT ' . $this->idfield
. '
216 FROM ' . $this->from
. '
219 GROUP BY ' . $this->idfield
);
224 private function mkTests($field, $text)
227 $tests[] = $field . XDB
::formatWildcards(XDB
::WILDCARD_PREFIX
, $text);
228 if (!$this->ac_beginwith
) {
229 $tests[] = $field . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, ' ' . $text);
230 $tests[] = $field . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, '-' . $text);
235 static protected function expandArray(array $tab, $keyname = 'id', $valname = 'field')
238 foreach ($tab as $key => $val) {
247 // {{{ function getAutoComplete
248 public function getAutoComplete($text)
250 $text = str_replace(array('%', '_'), '', $text);
252 if (is_null($this->ac_where
) ||
$this->ac_where
== '') {
255 $where = $this->ac_where
. ' AND ';
258 $tests = $this->mkTests($this->valfield
, $text);
259 if (!is_null($this->valfield2
)) {
260 $tests = array_merge($tests, $this->mkTests($this->valfield2
, $text));
263 $where .= '(' . implode(' OR ', $tests) . ')';
265 return XDB
::iterator('SELECT ' . $this->valfield
. ' AS field'
266 . ($this->ac_distinct ?
(', COUNT(DISTINCT ' . $this->ac_unique
. ') AS nb') : '')
267 . ($this->ac_withid ?
(', ' . $this->idfield
. ' AS id') : '') . '
268 FROM ' . $this->from
. '
269 ' . $this->ac_join
. '
271 GROUP BY ' . $this->valfield
. '
272 ORDER BY ' . ($this->ac_distinct ?
'nb DESC' : $this->valfield
) . '
273 LIMIT ' . self
::AUTOCOMPLETE_LIMIT
);
277 // {{{ function loadOptions
278 /** The function used to load options
280 protected function loadOptions()
282 $this->options
= XDB
::fetchAllAssoc('id', 'SELECT ' . $this->valfield
. ' AS field,
283 ' . $this->idfield
. ' AS id
284 FROM ' . $this->from
. '
287 GROUP BY ' . $this->valfield
. '
288 ORDER BY ' . $this->valfield
);
294 // {{{ class DE_WithSuboption
295 /** A class for DirEnum with possibility to select only suboptions for a given parameter (country, school, ...)
297 abstract class DE_WithSuboption
extends DirEnumeration
301 protected $suboptions = null
;
303 protected function loadOptions()
305 $opts = XDB
::fetchAllAssoc('id', 'SELECT ' . $this->valfield
. ' AS field,
306 ' . $this->optfield
. ' AS subid,
307 ' . $this->idfield
. ' AS id
308 FROM ' . $this->from
. '
311 GROUP BY ' . $this->valfield
. '
312 ORDER BY ' . $this->valfield
);
313 $this->options
= array();
314 $this->suboptions
= array();
315 foreach ($opts as $id => $opt) {
316 $this->options
[$id] = $opt['field'];
317 if (!array_key_exists($opt['subid'], $this->suboptions
)) {
318 $this->suboptions
[$opt['subid']] = array();
320 $this->suboptions
[$opt['subid']][$id] = $opt['field'];
324 public function getOptions($subid = null
)
326 $this->_fetchOptions();
327 if ($subid == null
) {
328 return $this->options
;
329 } else if (array_key_exists($subid, $this->suboptions
)) {
330 return $this->suboptions
[$subid];
336 public function getOptionsIter($subid = null
)
338 return PlIteratorUtils
::fromArray(self
::expandArray($this->getOptions($subid)), 1, true
);
341 public function getIDs($text, $mode, $subid = null
)
343 if ($mode == XDB
::WILDCARD_EXACT
) {
344 $options = $this->getOptions($subid);
345 return array_keys($options, $text);
347 if ($this->where
== null
) {
350 $where = $this->where
. ' AND ';
352 if ($subid != null
&& array_key_exists($subid, $this->suboptions
)) {
353 $where .= XDB
::format($this->optfield
. ' = {?} AND ', $subid);
357 $conds[] = $this->valfield
. XDB
::formatWildcards($mode, $text);
358 if ($this->valfield2
!= null
) {
359 $conds[] = $this->valfield2
. XDB
::formatWildcards($mode, $text);
361 $where .= '(' . implode(' OR ', $conds) . ')';
363 return XDB
::fetchColumn('SELECT ' . $this->idfield
. '
364 FROM ' . $this->from
. '
367 GROUP BY ' . $this->idfield
);
371 public function getAutoComplete($text, $subid = null
)
373 $text = str_replace(array('%', '_'), '', $text);
375 if (is_null($this->ac_where
) ||
$this->ac_where
== '') {
378 $where = $this->ac_where
. ' AND ';
381 if ($subid != null
&& array_key_exists($subid, $this->suboptions
)) {
382 $where .= XDB
::format($this->optfield
. ' = {?} AND ', $subid);
385 $tests = $this->mkTests($this->valfield
, $text);
386 if (!is_null($this->valfield2
)) {
387 $tests = array_merge($tests, $this->mkTests($this->valfield2
, $text));
390 $where .= '(' . implode(' OR ', $tests) . ')';
392 return XDB
::iterator('SELECT ' . $this->valfield
. ' AS field'
393 . ($this->ac_distinct ?
(', COUNT(DISTINCT ' . $this->ac_unique
. ') AS nb') : '')
394 . ($this->ac_withid ?
(', ' . $this->idfield
. ' AS id') : '') . '
395 FROM ' . $this->from
. '
396 ' . $this->ac_join
. '
398 GROUP BY ' . $this->valfield
. '
399 ORDER BY ' . ($this->ac_distinct ?
'nb DESC' : $this->valfield
) . '
400 LIMIT ' . self
::AUTOCOMPLETE_LIMIT
);
405 // {{{ class DE_NameTypes
406 // returns 'system' names ('lastname', 'lastname_marital', ...)
407 class DE_NameTypes
extends DirEnumeration
409 public $capabilities = self
::HAS_OPTIONS
;
411 protected $from = 'profile_name_enum';
412 protected $valfield = 'type';
418 // {{{ class DE_Binets
419 class DE_Binets
extends DirEnumeration
421 protected $from = 'profile_binet_enum';
423 protected $ac_join = 'INNER JOIN profile_binets ON (profile_binet_enum.id = profile_binets.binet_id)';
424 protected $ac_unique = 'profile_binets.user_id';
428 // {{{ class DE_Sections
429 class DE_Sections
extends DirEnumeration
431 protected $from = 'profile_section_enum';
433 protected $ac_join = 'INNER JOIN profiles ON (profiles.section = profile_section_enum.id)';
434 protected $ac_unique = 'profiles.pid';
438 // {{{ class DE_GroupesX
439 class DE_GroupesX
extends DirEnumeration
441 protected $idfield = 'groups.id';
442 protected $valfield = 'groups.nom';
443 protected $valfield2 = 'groups.diminutif';
444 protected $from = 'groups';
445 protected $where = 'WHERE (cat = \'GroupesX\' OR cat = \'Institutions\') AND pub = \'public\'';
447 protected $ac_join = "INNER JOIN group_members ON (groups.id = memb.asso_id
448 AND (groups.cat = 'GroupesX' OR groups.cat = 'Institutions')
449 AND groups.pub = 'public')";
450 protected $ac_unique = 'group_members.uid';
456 // {{{ class DE_EducationSchools
457 class DE_EducationSchools
extends DirEnumeration
459 protected $valfield = 'profile_education_enum.name';
460 protected $valfield2 = 'profile_education_enum.abbreviation';
461 protected $from = 'profile_education_enum';
463 protected $ac_join = 'INNER JOIN profile_education ON (profile_education.eduid = profile_education_enum.id)';
464 protected $ac_unique = 'profile_education.pid';
468 // {{{ class DE_EducationDegrees
469 class DE_EducationDegrees
extends DirEnumeration
471 public $capabilities = self
::HAS_OPTIONS
;
473 protected $idfield = 'profile_education_degree.degreeid';
474 protected $optfield = 'profile_education_degree.eduid';
475 protected $valfield = 'profile_education_degree_enum.degree';
476 protected $from = 'profile_education_degree_enum';
477 protected $join = 'INNER JOIN profile_education_degree ON (profile_education_degree.degreeid = profile_education_degree_enum.id)';
482 // {{{ class DE_EducationFields
483 class DE_EducationFields
extends DirEnumeration
485 protected $valfield = 'profile_education_field_enum.field';
486 protected $from = 'profile_education_field_enum';
488 protected $ac_join = 'INNER JOIN profile_education ON (profile_education.fieldid = profile_education_field_enum.id)';
489 protected $ac_unique = 'profile_education.pid';
495 // {{{ class DE_Nationalities
496 class DE_Nationalities
extends DirEnumeration
498 protected $idfield = 'geoloc_countries.iso_3166_1_a2';
499 protected $valfield = 'geoloc_countries.nationalityFR';
500 protected $valfield2 = 'geoloc_countries.nationality';
501 protected $from = 'geoloc_countries';
502 protected $join = 'INNER JOIN profiles ON (geoloc_countries.iso_3166_1_a2 IN (profiles.nationality1, profiles.nationality2, profiles.nationality3))';
504 protected $ac_join = 'INNER JOIN profiles ON (geoloc_countries.iso_3166_1_a2 IN (profiles.nationality1, profiles.nationality2, profiles.nationality3))';
505 protected $ac_unique = 'profiles.pid';
509 // {{{ class DE_Countries
510 class DE_Countries
extends DirEnumeration
512 protected $idfield = 'geoloc_countries.iso_3166_1_a2';
513 protected $valfield = 'geoloc_countries.countryFR';
514 protected $valfield2 = 'geoloc_countries.country';
515 protected $from = 'geoloc_countries';
517 protected $ac_join = 'INNER JOIN profile_addresses ON (geoloc_countries.iso_3166_1_a2 = profile_addresses.countryFR';
518 protected $ac_unique = 'profile_addresses.pid';
522 // {{{ class DE_AdminAreas
523 class DE_AdminAreas
extends DE_WithSuboption
525 protected $idfield = 'geoloc_administrativeareas.id';
526 protected $optfield = 'geoloc_administrativeareas.country';
527 protected $valfield = 'geoloc_administrativeareas.name';
528 protected $from = 'geoloc_administrativeareas';
530 protected $ac_join = 'INNER JOIN profile_addresses ON (profile_addresses.administrativeAreaId = geoloc_administrativeareas.id)';
531 protected $ac_unique = 'profile_addresses.pid';
535 // {{{ class DE_Localities
536 class DE_Localities
extends DirEnumeration
538 protected $valfield = 'geoloc_localities.name';
539 protected $from = 'geoloc_localities';
541 protected $ac_join = 'profile_addresses ON (profile_addresses.localityID = geoloc_localities.id)';
542 protected $ac_unique = 'profile_addresses.pid';
548 // {{{ class DE_Companies
549 class DE_Companies
extends DirEnumeration
551 protected $valfield = 'profile_job_enum.name';
552 protected $valfield2 = 'profile_job_enum.acronym';
553 protected $from = 'profile_job_enum';
555 protected $ac_join = 'INNER JOIN profile_job ON (profile_job.jobid = profile_job_enum.id)';
556 protected $ac_unique = 'profile_job.pid';
560 // {{{ class DE_Sectors
561 class DE_Sectors
extends DirEnumeration
563 protected $valfield = 'profile_job_sector_enum.name';
564 protected $from = 'profile_job_sector_enum';
566 protected $ac_join = 'INNER JOIN profile_job ON (profile_job_sector_enum.id = profile_job.sectorid)';
567 protected $ac_unique = 'profile_job.pid';
571 // {{{ class DE_JobDescription
572 class DE_JobDescription
574 protected $valfield = 'profile_job.description';
575 protected $from = 'profile_job';
576 protected $idfield = 'profile_job.pid';
578 protected $ac_unique = 'profile_job.pid';
584 // {{{ class DE_Networking
585 class DE_Networking
extends DirEnumeration
587 protected $idfield = 'profile_networking_enum.network_type';
588 protected $valfield = 'profile_networking_enum.name';
589 protected $from = 'profile_networking_enum';
592 protected $ac_join = 'INNER JOIN profile_networking ON (profile_networking.network_type = profile_networking_enum.network_type';
593 protected $ac_unique = 'profile_networking.pid';