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 ***************************************************************************/
22 // {{{ abstract class UserFilterCondition
23 /** This class describe objects which filter users based
24 * on various parameters.
25 * The parameters of the filter must be given to the constructor.
26 * The buildCondition function is called by UserFilter when
27 * actually building the query. That function must call
28 * $uf->addWheteverFilter so that the UserFilter makes
29 * adequate joins. It must return the 'WHERE' condition to use
32 abstract class UserFilterCondition
implements PlFilterCondition
34 public function export()
36 throw new Exception("This class is not exportable");
41 // {{{ class UFC_HasProfile
42 /** Filters users who have a profile
44 class UFC_HasProfile
extends UserFilterCondition
46 public function buildCondition(PlFilter
$uf)
48 $uf->requireProfiles();
49 return '$PID IS NOT NULL';
54 // {{{ class UFC_AccountType
55 /** Filters users who have one of the given account types
57 class UFC_AccountType
extends UserFilterCondition
61 public function __construct()
63 $this->types
= pl_flatten(func_get_args());
66 public function buildCondition(PlFilter
$uf)
68 $uf->requireAccounts();
69 return XDB
::format('a.type IN {?}', $this->types
);
74 // {{{ class UFC_AccountPerm
75 /** Filters users who have one of the given permissions
77 class UFC_AccountPerm
extends UserFilterCondition
81 public function __construct()
83 $this->perms
= pl_flatten(func_get_args());
86 public function buildCondition(PlFilter
$uf)
90 foreach ($this->perms
as $perm) {
91 $conds[] = XDB
::format('FIND_IN_SET({?}, IF(a.user_perms IS NULL, at.perms,
92 CONCAT(at.perms, \',\', a.user_perms)))',
96 return self
::COND_TRUE
;
98 return implode(' OR ', $conds);
104 // {{{ class UFC_Hruid
105 /** Filters users based on their hruid
106 * @param $val Either an hruid, or a list of those
108 class UFC_Hruid
extends UserFilterCondition
112 public function __construct()
114 $this->hruids
= pl_flatten(func_get_args());
117 public function buildCondition(PlFilter
$uf)
119 $uf->requireAccounts();
120 return XDB
::format('a.hruid IN {?}', $this->hruids
);
125 // {{{ class UFC_Hrpid
126 /** Filters users based on the hrpid of their profiles
127 * @param $val Either an hrpid, or a list of those
129 class UFC_Hrpid
extends UserFilterCondition
133 public function __construct()
135 $this->hrpids
= pl_flatten(func_get_args());
138 public function buildCondition(PlFilter
$uf)
140 $uf->requireProfiles();
141 return XDB
::format('p.hrpid IN {?}', $this->hrpids
);
147 /** Filters users based on one of their last IPs
148 * @param $ip IP from which connection are checked
150 class UFC_Ip
extends UserFilterCondition
154 public function __construct($ip)
159 public function buildCondition(PlFilter
$uf)
161 $sub = $uf->addLoggerFilter();
162 $ip = ip_to_uint($this->ip
);
163 return XDB
::format($sub . '.ip = {?} OR ' . $sub . '.forward_ip = {?}', $ip, $ip);
168 // {{{ class UFC_Comment
169 class UFC_Comment
extends UserFilterCondition
173 public function __construct($text)
178 public function buildCondition(PlFilter
$uf)
180 $uf->requireProfiles();
181 return $uf->getVisibilityCondition('p.freetext_pub') . ' AND p.freetext ' . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->text
);
186 // {{{ class UFC_Promo
187 /** Filters users based on promotion
188 * @param $comparison Comparison operator (>, =, ...)
189 * @param $grade Formation on which to restrict, UserFilter::DISPLAY for "any formation"
190 * @param $promo Promotion on which the filter is based
192 class UFC_Promo
extends UserFilterCondition
199 public function __construct($comparison, $grade, $promo)
201 $this->grade
= $grade;
202 $this->comparison
= $comparison;
203 $this->promo
= $promo;
204 if ($this->grade
!= UserFilter
::DISPLAY
) {
205 UserFilter
::assertGrade($this->grade
);
207 if ($this->grade
== UserFilter
::DISPLAY
&& $this->comparison
!= '=') {
208 // XXX: we might try to guess the grade from the first char of the promo and forbid only '<= 2004', but allow '<= X2004'
209 Platal
::page()->killError("Il n'est pas possible d'appliquer la comparaison '" . $this->comparison
. "' aux promotions sans spécifier de formation (X/M/D)");
213 public function buildCondition(PlFilter
$uf)
215 if ($this->grade
== UserFilter
::DISPLAY
) {
216 $sub = $uf->addDisplayFilter();
217 return XDB
::format('pd' . $sub . '.promo ' . $this->comparison
. ' {?}', $this->promo
);
219 $sub = $uf->addEducationFilter(true
, $this->grade
);
220 $field = 'pe' . $sub . '.' . UserFilter
::promoYear($this->grade
);
221 return $field . ' IS NOT NULL AND ' . $field . ' ' . $this->comparison
. ' ' . XDB
::format('{?}', $this->promo
);
227 // {{{ class UFC_SchoolId
228 /** Filters users based on their shoold identifier
229 * @param type Parameter type (Xorg, AX, School)
230 * @param value School id value
232 class UFC_SchoolId
extends UserFilterCondition
236 const School
= 'school';
241 static public function assertType($type)
243 if ($type != self
::AX
&& $type != self
::Xorg
&& $type != self
::School
) {
244 Platal
::page()->killError("Type de matricule invalide: $type");
248 public function __construct($type, $id)
252 self
::assertType($type);
255 public function buildCondition(PlFilter
$uf)
257 $uf->requireProfiles();
260 if ($type == self
::School
) {
262 $id = Profile
::getXorgId($id);
264 return XDB
::format('p.' . $type . '_id = {?}', $id);
269 // {{{ class UFC_EducationSchool
270 /** Filters users by formation
271 * @param $val The formation to search (either ID or array of IDs)
273 class UFC_EducationSchool
extends UserFilterCondition
277 public function __construct()
279 $this->val
= pl_flatten(func_get_args());
282 public function buildCondition(PlFilter
$uf)
284 $sub = $uf->addEducationFilter();
285 return XDB
::format('pe' . $sub . '.eduid IN {?}', $this->val
);
290 // {{{ class UFC_EducationDegree
291 class UFC_EducationDegree
extends UserFilterCondition
295 public function __construct()
297 $this->diploma
= pl_flatten(func_get_args());
300 public function buildCondition(PlFilter
$uf)
302 $sub = $uf->addEducationFilter();
303 return XDB
::format('pe' . $sub . '.degreeid IN {?}', $this->diploma
);
308 // {{{ class UFC_EducationField
309 class UFC_EducationField
extends UserFilterCondition
313 public function __construct()
315 $this->val
= pl_flatten(func_get_args());
318 public function buildCondition(PlFilter
$uf)
320 $sub = $uf->addEducationFilter();
321 return XDB
::format('pe' . $sub . '.fieldid IN {?}', $this->val
);
326 // {{{ class UFC_Name
327 /** Filters users based on name
328 * @param $type Type of name field on which filtering is done (firstname, lastname...)
329 * @param $text Text on which to filter
330 * @param $mode Flag indicating search type (prefix, suffix, with particule...)
332 class UFC_Name
extends UserFilterCondition
334 const EXACT
= XDB
::WILDCARD_EXACT
; // 0x000
335 const PREFIX
= XDB
::WILDCARD_PREFIX
; // 0x001
336 const SUFFIX
= XDB
::WILDCARD_SUFFIX
; // 0x002
337 const CONTAINS
= XDB
::WILDCARD_CONTAINS
; // 0x003
338 const PARTICLE
= 0x004;
339 const VARIANTS
= 0x008;
345 public function __construct($type, $text, $mode)
352 private function buildNameQuery($type, $variant, $where, UserFilter
$uf)
354 $sub = $uf->addNameFilter($type, $variant);
355 return str_replace('$ME', 'pn' . $sub, $where);
358 public function buildCondition(PlFilter
$uf)
361 if (($this->mode
& self
::PARTICLE
) == self
::PARTICLE
) {
362 $left = 'CONCAT($ME.particle, \' \', $ME.name)';
364 $right = XDB
::formatWildcards($this->mode
& self
::CONTAINS
, $this->text
);
366 $cond = $left . $right;
367 $conds = array($this->buildNameQuery($this->type
, null
, $cond, $uf));
368 if (($this->mode
& self
::VARIANTS
) != 0 && isset(Profile
::$name_variants[$this->type
])) {
369 foreach (Profile
::$name_variants[$this->type
] as $var) {
370 $conds[] = $this->buildNameQuery($this->type
, $var, $cond, $uf);
373 return implode(' OR ', $conds);
378 // {{{ class UFC_NameTokens
379 /** Selects users based on tokens in their name (for quicksearch)
380 * @param $tokens An array of tokens to search
381 * @param $flags Flags the tokens must have (e.g 'public' for public search)
382 * @param $soundex (bool) Whether those tokens are fulltext or soundex
384 class UFC_NameTokens
extends UserFilterCondition
387 const FLAG_PUBLIC
= 'public';
394 public function __construct($tokens, $flags = array(), $soundex = false
, $exact = false
)
396 if (is_array($tokens)) {
397 $this->tokens
= $tokens;
399 $this->tokens
= array($tokens);
401 if (is_array($flags)) {
402 $this->flags
= $flags;
404 $this->flags
= array($flags);
406 $this->soundex
= $soundex;
407 $this->exact
= $exact;
410 public function buildCondition(PlFilter
$uf)
413 foreach ($this->tokens
as $i => $token) {
414 $sub = $uf->addNameTokensFilter($token);
415 if ($this->soundex
) {
416 $c = XDB
::format($sub . '.soundex = {?}', soundex_fr($token));
417 } else if ($this->exact
) {
418 $c = XDB
::format($sub . '.token = {?}', $token);
420 $c = $sub . '.token ' . XDB
::formatWildcards(XDB
::WILDCARD_PREFIX
, $token);
422 if ($this->flags
!= null
) {
423 $c .= XDB
::format(' AND ' . $sub . '.flags IN {?}', $this->flags
);
428 return implode(' AND ', $conds);
433 // {{{ class UFC_Nationality
434 class UFC_Nationality
extends UserFilterCondition
438 public function __construct()
440 $this->val
= pl_flatten(func_get_args());
443 public function buildCondition(PlFilter
$uf)
445 $uf->requireProfiles();
446 $nat = XDB
::formatArray($this->val
);
448 'p.nationality1 IN ' . $nat,
449 'p.nationality2 IN ' . $nat,
450 'p.nationality3 IN ' . $nat,
452 return implode(' OR ', $conds);
457 // {{{ class UFC_Dead
458 /** Filters users based on death date
459 * @param $comparison Comparison operator
460 * @param $date Date to which death date should be compared (DateTime object, string or timestamp)
462 class UFC_Dead
extends UserFilterCondition
467 public function __construct($comparison = null
, $date = null
)
469 $this->comparison
= $comparison;
470 $this->date
= make_datetime($date);
473 public function buildCondition(PlFilter
$uf)
475 $uf->requireProfiles();
476 $str = 'p.deathdate IS NOT NULL';
477 if (!is_null($this->comparison
)) {
478 $str .= ' AND p.deathdate ' . $this->comparison
. ' ' . XDB
::format('{?}', $this->date
->format('Y-m-d'));
485 // {{{ class UFC_Registered
486 /** Filters users based on registration state
487 * @param $active Whether we want to use only "active" users (i.e with a valid redirection)
488 * @param $comparison Comparison operator
489 * @param $date Date to which users registration date should be compared
491 class UFC_Registered
extends UserFilterCondition
497 public function __construct($active = false
, $comparison = null
, $date = null
)
499 $this->active
= $active;
500 $this->comparison
= $comparison;
501 $this->date
= make_datetime($date);
504 public function buildCondition(PlFilter
$uf)
506 $uf->requireAccounts();
508 $date = '$UID IS NOT NULL AND a.state = \'active\'';
510 $date = '$UID IS NOT NULL AND a.state != \'pending\'';
512 if (!is_null($this->comparison
)) {
513 $date .= ' AND a.registration_date != \'0000-00-00 00:00:00\' AND a.registration_date ' . $this->comparison
. ' ' . XDB
::format('{?}', $this->date
->format('Y-m-d'));
520 // {{{ class UFC_ProfileUpdated
521 /** Filters users based on profile update date
522 * @param $comparison Comparison operator
523 * @param $date Date to which profile update date must be compared
525 class UFC_ProfileUpdated
extends UserFilterCondition
530 public function __construct($comparison = null
, $date = null
)
532 $this->comparison
= $comparison;
536 public function buildCondition(PlFilter
$uf)
538 $uf->requireProfiles();
539 return 'p.last_change ' . $this->comparison
. XDB
::format(' {?}', date('Y-m-d H:i:s', $this->date
));
544 // {{{ class UFC_Birthday
545 /** Filters users based on next birthday date
546 * @param $comparison Comparison operator
547 * @param $date Date to which users next birthday date should be compared
549 class UFC_Birthday
extends UserFilterCondition
554 public function __construct($comparison = null
, $date = null
)
556 $this->comparison
= $comparison;
560 public function buildCondition(PlFilter
$uf)
562 $uf->requireProfiles();
563 return 'p.next_birthday ' . $this->comparison
. XDB
::format(' {?}', date('Y-m-d', $this->date
));
569 /** Filters users based on sex
570 * @parm $sex One of User::GENDER_MALE or User::GENDER_FEMALE, for selecting users
572 class UFC_Sex
extends UserFilterCondition
575 public function __construct($sex)
580 public function buildCondition(PlFilter
$uf)
582 if ($this->sex
!= User
::GENDER_MALE
&& $this->sex
!= User
::GENDER_FEMALE
) {
583 return self
::COND_FALSE
;
585 $uf->requireProfiles();
586 return XDB
::format('p.sex = {?}', $this->sex
== User
::GENDER_FEMALE ?
'female' : 'male');
592 // {{{ class UFC_Group
593 /** Filters users based on group membership
594 * @param $group Group whose members we are selecting
595 * @param $anim Whether to restrict selection to animators of that group
597 class UFC_Group
extends UserFilterCondition
601 public function __construct($group, $anim = false
)
603 $this->group
= $group;
607 public function buildCondition(PlFilter
$uf)
609 // Groups have AX visibility.
610 if ($uf->getVisibilityLevel() == ProfileVisibility
::VIS_PUBLIC
) {
611 return self
::COND_TRUE
;
613 $sub = $uf->addGroupFilter($this->group
);
614 $where = 'gpm' . $sub . '.perms IS NOT NULL';
616 $where .= ' AND gpm' . $sub . '.perms = \'admin\'';
623 // {{{ class UFC_Binet
624 /** Selects users based on their belonging to a given (list of) binet
625 * @param $binet either a binet_id or an array of binet_ids
627 class UFC_Binet
extends UserFilterCondition
631 public function __construct()
633 $this->val
= pl_flatten(func_get_args());
636 public function buildCondition(PlFilter
$uf)
638 // Binets are private.
639 if ($uf->getVisibilityLevel() != ProfileVisibility
::VIS_PRIVATE
) {
640 return self
::CONF_TRUE
;
642 $sub = $uf->addBinetsFilter();
643 return XDB
::format($sub . '.binet_id IN {?}', $this->val
);
648 // {{{ class UFC_Section
649 /** Selects users based on section
650 * @param $section ID of the section
652 class UFC_Section
extends UserFilterCondition
656 public function __construct()
658 $this->section
= pl_flatten(func_get_args());
661 public function buildCondition(PlFilter
$uf)
663 // Sections are private.
664 if ($uf->getVisibilityLevel() != ProfileVisibility
::VIS_PRIVATE
) {
665 return self
::CONF_TRUE
;
667 $uf->requireProfiles();
668 return XDB
::format('p.section IN {?}', $this->section
);
673 // {{{ class UFC_Email
674 /** Filters users based on an email or a list of emails
675 * @param $emails List of emails whose owner must be selected
677 class UFC_Email
extends UserFilterCondition
680 public function __construct()
682 $this->emails
= pl_flatten(func_get_args());
685 public function buildCondition(PlFilter
$uf)
692 if (count($this->emails
) == 0) {
693 return PlFilterCondition
::COND_TRUE
;
696 foreach ($this->emails
as $entry) {
697 if (User
::isForeignEmailAddress($entry)) {
699 } else if (User
::isVirtualEmailAddress($entry)) {
702 @list
($user, $domain) = explode('@', $entry);
707 if (count($foreign) > 0) {
708 $sub = $uf->addEmailRedirectFilter($foreign);
709 $cond[] = XDB
::format('e' . $sub . '.email IS NOT NULL OR a.email IN {?}', $foreign);
711 if (count($virtual) > 0) {
712 $sub = $uf->addVirtualEmailFilter($virtual);
713 $cond[] = 'vr' . $sub . '.redirect IS NOT NULL';
715 if (count($aliases) > 0) {
716 $sub = $uf->addAliasFilter($aliases);
717 $cond[] = 'al' . $sub . '.alias IS NOT NULL';
719 return '(' . implode(') OR (', $cond) . ')';
724 // {{{ class UFC_Address
725 abstract class UFC_Address
extends UserFilterCondition
727 /** Valid address type ('hq' is reserved for company addresses)
733 /** Text for these types
735 protected static $typetexts = array(
736 self
::TYPE_HOME
=> 'home',
737 self
::TYPE_PRO
=> 'pro',
742 /** Flags for addresses
744 const FLAG_CURRENT
= 0x0001;
745 const FLAG_TEMP
= 0x0002;
746 const FLAG_SECOND
= 0x0004;
747 const FLAG_MAIL
= 0x0008;
748 const FLAG_CEDEX
= 0x0010;
750 // Binary OR of those flags
751 const FLAG_ANY
= 0x001F;
753 /** Text of these flags
755 protected static $flagtexts = array(
756 self
::FLAG_CURRENT
=> 'current',
757 self
::FLAG_TEMP
=> 'temporary',
758 self
::FLAG_SECOND
=> 'secondary',
759 self
::FLAG_MAIL
=> 'mail',
760 self
::FLAG_CEDEX
=> 'cedex',
765 public function __construct($type = null
, $flags = null
)
768 $this->flags
= $flags;
771 protected function initConds($sub, $vis_cond)
773 $conds = array($vis_cond);
776 foreach (self
::$typetexts as $flag => $type) {
777 if ($flag & $this->type
) {
782 $conds[] = XDB
::format($sub . '.type IN {?}', $types);
785 if ($this->flags
!= self
::FLAG_ANY
) {
786 foreach(self
::$flagtexts as $flag => $text) {
787 if ($flag & $this->flags
) {
788 $conds[] = 'FIND_IN_SET(' . XDB
::format('{?}', $text) . ', ' . $sub . '.flags)';
798 // {{{ class UFC_AddressText
799 /** Select users based on their address, using full text search
800 * @param $text Text for filter in fulltext search
801 * @param $textSearchMode Mode for search (one of XDB::WILDCARD_*)
802 * @param $type Filter on address type
803 * @param $flags Filter on address flags
804 * @param $country Filter on address country
805 * @param $locality Filter on address locality
807 class UFC_AddressText
extends UFC_Address
811 private $textSearchMode;
813 public function __construct($text = null
, $textSearchMode = XDB
::WILDCARD_CONTAINS
,
814 $type = null
, $flags = self
::FLAG_ANY
, $country = null
, $locality = null
)
816 parent
::__construct($type, $flags);
818 $this->textSearchMode
= $textSearchMode;
819 $this->country
= $country;
820 $this->locality
= $locality;
823 private function mkMatch($txt)
825 return XDB
::formatWildcards($this->textSearchMode
, $txt);
828 public function buildCondition(PlFilter
$uf)
830 $sub = $uf->addAddressFilter();
831 $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub'));
832 if ($this->text
!= null
) {
833 $conds[] = $sub . '.text' . $this->mkMatch($this->text
);
836 if ($this->country
!= null
) {
837 $subc = $uf->addAddressCountryFilter();
839 $subconds[] = $subc . '.country' . $this->mkMatch($this->country
);
840 $subconds[] = $subc . '.countryFR' . $this->mkMatch($this->country
);
841 $conds[] = implode(' OR ', $subconds);
844 if ($this->locality
!= null
) {
845 $subl = $uf->addAddressLocalityFilter();
846 $conds[] = $subl . '.name' . $this->mkMatch($this->locality
);
849 return implode(' AND ', $conds);
854 // {{{ class UFC_AddressField
855 /** Filters users based on their address,
856 * @param $val Either a code for one of the fields, or an array of such codes
857 * @param $fieldtype The type of field to look for
858 * @param $type Filter on address type
859 * @param $flags Filter on address flags
861 class UFC_AddressField
extends UFC_Address
863 const FIELD_COUNTRY
= 1;
864 const FIELD_ADMAREA
= 2;
865 const FIELD_SUBADMAREA
= 3;
866 const FIELD_LOCALITY
= 4;
867 const FIELD_ZIPCODE
= 5;
869 /** Data of the filter
874 public function __construct($val, $fieldtype, $type = null
, $flags = self
::FLAG_ANY
)
876 parent
::__construct($type, $flags);
878 if (!is_array($val)) {
882 $this->fieldtype
= $fieldtype;
885 public function buildCondition(PlFilter
$uf)
887 $sub = $uf->addAddressFilter();
888 $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub'));
890 switch ($this->fieldtype
) {
891 case self
::FIELD_COUNTRY
:
892 $field = 'countryId';
894 case self
::FIELD_ADMAREA
:
895 $field = 'administrativeAreaId';
897 case self
::FIELD_SUBADMAREA
:
898 $field = 'subAdministrativeAreaId';
900 case self
::FIELD_LOCALITY
:
901 $field = 'localityId';
903 case self
::FIELD_ZIPCODE
:
904 $field = 'postalCode';
907 Platal
::page()->killError('Invalid address field type: ' . $this->fieldtype
);
909 $conds[] = XDB
::format($sub . '.' . $field . ' IN {?}', $this->val
);
911 return implode(' AND ', $conds);
916 // {{{ class UFC_Corps
917 /** Filters users based on the corps they belong to
918 * @param $corps Corps we are looking for (abbreviation)
919 * @param $type Whether we search for original or current corps
921 class UFC_Corps
extends UserFilterCondition
929 public function __construct($corps, $type = self
::CURRENT
)
931 $this->corps
= $corps;
935 public function buildCondition(PlFilter
$uf)
937 /** Tables shortcuts:
938 * pc for profile_corps,
939 * pceo for profile_corps_enum - orginal
940 * pcec for profile_corps_enum - current
942 $sub = $uf->addCorpsFilter($this->type
);
943 $cond = $sub . '.abbreviation = ' . $corps;
944 $cond .= ' AND ' . $uf->getVisibilityCondition($sub . '.corps_pub');
950 // {{{ class UFC_Corps_Rank
951 /** Filters users based on their rank in the corps
952 * @param $rank Rank we are looking for (abbreviation)
954 class UFC_Corps_Rank
extends UserFilterCondition
957 public function __construct($rank)
962 public function buildCondition(PlFilter
$uf)
964 /** Tables shortcuts:
965 * pc for profile_corps
966 * pcr for profile_corps_rank
968 $sub = $uf->addCorpsRankFilter();
969 $cond = $sub . '.abbreviation = ' . $rank;
970 // XXX(x2006barrois): find a way to get rid of that hardcoded
971 // reference to 'pc'.
972 $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub');
978 // {{{ class UFC_Job_Company
979 /** Filters users based on the company they belong to
980 * @param $type The field being searched (self::JOBID, self::JOBNAME or self::JOBACRONYM)
981 * @param $value The searched value
983 class UFC_Job_Company
extends UserFilterCondition
986 const JOBNAME
= 'name';
987 const JOBACRONYM
= 'acronym';
992 public function __construct($type, $value)
994 $this->assertType($type);
996 $this->value
= $value;
999 private function assertType($type)
1001 if ($type != self
::JOBID
&& $type != self
::JOBNAME
&& $type != self
::JOBACRONYM
) {
1002 Platal
::page()->killError("Type de recherche non valide.");
1006 public function buildCondition(PlFilter
$uf)
1008 $sub = $uf->addJobCompanyFilter();
1009 $cond = $sub . '.' . $this->type
. XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->value
);
1010 $jsub = $uf->addJobFilter();
1011 $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub');
1017 // {{{ class UFC_Job_Terms
1018 /** Filters users based on the job terms they assigned to one of their
1020 * @param $val The ID of the job term, or an array of such IDs
1022 class UFC_Job_Terms
extends UserFilterCondition
1026 public function __construct($val)
1028 if (!is_array($val)) {
1034 public function buildCondition(PlFilter
$uf)
1036 $sub = $uf->addJobTermsFilter(count($this->val
));
1037 $conditions = array();
1038 foreach ($this->val
as $i => $jtid) {
1039 $conditions[] = $sub[$i] . '.jtid_1 = ' . XDB
::escape($jtid);
1041 $jsub = $uf->addJobFilter();
1042 $conditions[] = $uf->getVisibilityCondition($jsub . '.pub');
1043 return implode(' AND ', $conditions);
1048 // {{{ class UFC_Job_Description
1049 /** Filters users based on their job description
1050 * @param $description The text being searched for
1051 * @param $fields The fields to search for (CV, user-defined)
1053 class UFC_Job_Description
extends UserFilterCondition
1056 private $description;
1059 public function __construct($description, $fields)
1061 $this->fields
= $fields;
1062 $this->description
= $description;
1065 public function buildCondition(PlFilter
$uf)
1069 $jsub = $uf->addJobFilter();
1070 // CV is private => if only CV requested, and not private,
1071 // don't do anything. Otherwise restrict to standard job visibility.
1072 if ($this->fields
== UserFilter
::JOB_CV
) {
1073 if ($uf->getVisibilityLevel() != ProfileVisibility
::VIS_PRIVATE
) {
1074 return self
::CONF_TRUE
;
1077 $conds[] = $uf->getVisibilityCondition($jsub . '.pub');
1080 if ($this->fields
& UserFilter
::JOB_USERDEFINED
) {
1081 $conds[] = $jsub . '.description ' . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->description
);
1083 if ($this->fields
& UserFilter
::JOB_CV
&& $uf->getVisibilityLevel() == ProfileVisibility
::VIS_PRIVATE
) {
1084 $uf->requireProfiles();
1085 $conds[] = 'p.cv ' . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->description
);
1087 return implode(' OR ', $conds);
1092 // {{{ class UFC_Networking
1093 /** Filters users based on network identity (IRC, ...)
1094 * @param $type Type of network (-1 for any)
1095 * @param $value Value to search
1097 class UFC_Networking
extends UserFilterCondition
1102 public function __construct($type, $value)
1104 $this->type
= $type;
1105 $this->value
= $value;
1108 public function buildCondition(PlFilter
$uf)
1110 $sub = $uf->addNetworkingFilter();
1112 $conds[] = $uf->getVisibilityCondition($sub . '.pub');
1113 $conds[] = $sub . '.address ' . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->value
);
1114 if ($this->type
!= -1) {
1115 $conds[] = $sub . '.nwid = ' . XDB
::format('{?}', $this->type
);
1117 return implode(' AND ', $conds);
1122 // {{{ class UFC_Phone
1123 /** Filters users based on their phone number
1124 * @param $num_type Type of number (pro/user/home)
1125 * @param $phone_type Type of phone (fixed/mobile/fax)
1126 * @param $number Phone number
1128 class UFC_Phone
extends UserFilterCondition
1130 const NUM_PRO
= 'pro';
1131 const NUM_USER
= 'user';
1132 const NUM_HOME
= 'address';
1133 const NUM_ANY
= 'any';
1135 const PHONE_FIXED
= 'fixed';
1136 const PHONE_MOBILE
= 'mobile';
1137 const PHONE_FAX
= 'fax';
1138 const PHONE_ANY
= 'any';
1141 private $phone_type;
1144 public function __construct($number, $num_type = self
::NUM_ANY
, $phone_type = self
::PHONE_ANY
)
1146 $phone = new Phone(array('display' => $number));
1148 $this->number
= $phone->search();
1149 $this->num_type
= $num_type;
1150 $this->phone_type
= $phone_type;
1153 public function buildCondition(PlFilter
$uf)
1155 $sub = $uf->addPhoneFilter();
1158 $conds[] = $uf->getVisibilityCondition($sub . '.pub');
1160 $conds[] = $sub . '.search_tel = ' . XDB
::format('{?}', $this->number
);
1161 if ($this->num_type
!= self
::NUM_ANY
) {
1162 $conds[] = $sub . '.link_type = ' . XDB
::format('{?}', $this->num_type
);
1164 if ($this->phone_type
!= self
::PHONE_ANY
) {
1165 $conds[] = $sub . '.tel_type = ' . XDB
::format('{?}', $this->phone_type
);
1167 return implode(' AND ', $conds);
1172 // {{{ class UFC_Medal
1173 /** Filters users based on their medals
1174 * @param $medal ID of the medal
1175 * @param $grade Grade of the medal (null for 'any')
1177 class UFC_Medal
extends UserFilterCondition
1182 public function __construct($medal, $grade = null
)
1184 $this->medal
= $medal;
1185 $this->grade
= $grade;
1188 public function buildCondition(PlFilter
$uf)
1192 // This will require profiles => table 'p' will be available.
1193 $sub = $uf->addMedalFilter();
1195 $conds[] = $uf->getVisibilityCondition('p.medals_pub');
1197 $conds[] = $sub . '.mid = ' . XDB
::format('{?}', $this->medal
);
1198 if ($this->grade
!= null
) {
1199 $conds[] = $sub . '.gid = ' . XDB
::format('{?}', $this->grade
);
1201 return implode(' AND ', $conds);
1206 // {{{ class UFC_Photo
1207 /** Filters profiles with photo
1209 class UFC_Photo
extends UserFilterCondition
1211 public function buildCondition(PlFilter
$uf)
1213 $sub = $uf->addPhotoFilter();
1214 return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityCondition($sub . '.pub');
1219 // {{{ class UFC_Mentor
1220 class UFC_Mentor
extends UserFilterCondition
1222 public function buildCondition(PlFilter
$uf)
1224 $sub = $uf->addMentorFilter(UserFilter
::MENTOR
);
1225 return $sub . '.expertise IS NOT NULL';
1231 // {{{ class UFC_Mentor_Expertise
1232 /** Filters users by mentoring expertise
1233 * @param $expertise Domain of expertise
1235 class UFC_Mentor_Expertise
extends UserFilterCondition
1239 public function __construct($expertise)
1241 $this->expertise
= $expertise;
1244 public function buildCondition(PlFilter
$uf)
1246 $sub = $uf->addMentorFilter(UserFilter
::MENTOR_EXPERTISE
);
1247 return $sub . '.expertise ' . XDB
::formatWildcards(XDB
::WILDCARD_CONTAINS
, $this->expertise
);
1252 // {{{ class UFC_Mentor_Country
1253 /** Filters users by mentoring country
1254 * @param $country Two-letters code of country being searched
1256 class UFC_Mentor_Country
extends UserFilterCondition
1260 public function __construct()
1262 $this->country
= pl_flatten(func_get_args());
1265 public function buildCondition(PlFilter
$uf)
1267 $sub = $uf->addMentorFilter(UserFilter
::MENTOR_COUNTRY
);
1268 return $sub . '.country IN ' . XDB
::format('{?}', $this->country
);
1273 // {{{ class UFC_Mentor_Terms
1274 /** Filters users based on the job terms they used in mentoring.
1275 * @param $val The ID of the job term, or an array of such IDs
1277 class UFC_Mentor_Terms
extends UserFilterCondition
1281 public function __construct($val)
1286 public function buildCondition(PlFilter
$uf)
1288 $sub = $uf->addMentorFilter(UserFilter
::MENTOR_TERM
);
1289 return $sub . '.jtid_1 = ' . XDB
::escape($this->val
);
1294 // {{{ class UFC_UserRelated
1295 /** Filters users based on a relation toward a user
1296 * @param $user User to which searched users are related
1298 abstract class UFC_UserRelated
extends UserFilterCondition
1301 public function __construct(PlUser
&$user)
1303 $this->user
=& $user;
1308 // {{{ class UFC_Contact
1309 /** Filters users who belong to selected user's contacts
1311 class UFC_Contact
extends UFC_UserRelated
1313 public function buildCondition(PlFilter
$uf)
1315 $sub = $uf->addContactFilter($this->user
->id());
1316 return 'c' . $sub . '.contact IS NOT NULL';
1321 // {{{ class UFC_WatchRegistration
1322 /** Filters users being watched by selected user
1324 class UFC_WatchRegistration
extends UFC_UserRelated
1326 public function buildCondition(PlFilter
$uf)
1328 if (!$this->user
->watchType('registration')) {
1329 return PlFilterCondition
::COND_FALSE
;
1331 $uids = $this->user
->watchUsers();
1332 if (count($uids) == 0) {
1333 return PlFilterCondition
::COND_FALSE
;
1335 return XDB
::format('$UID IN {?}', $uids);
1341 // {{{ class UFC_WatchPromo
1342 /** Filters users belonging to a promo watched by selected user
1343 * @param $user Selected user (the one watching promo)
1344 * @param $grade Formation the user is watching
1346 class UFC_WatchPromo
extends UFC_UserRelated
1349 public function __construct(PlUser
&$user, $grade = UserFilter
::GRADE_ING
)
1351 parent
::__construct($user);
1352 $this->grade
= $grade;
1355 public function buildCondition(PlFilter
$uf)
1357 $promos = $this->user
->watchPromos();
1358 if (count($promos) == 0) {
1359 return PlFilterCondition
::COND_FALSE
;
1361 $sube = $uf->addEducationFilter(true
, $this->grade
);
1362 $field = 'pe' . $sube . '.' . UserFilter
::promoYear($this->grade
);
1363 return XDB
::format($field . ' IN {?}', $promos);
1369 // {{{ class UFC_WatchContact
1370 /** Filters users watched by selected user
1372 class UFC_WatchContact
extends UFC_Contact
1374 public function buildCondition(PlFilter
$uf)
1376 if (!$this->user
->watchContacts()) {
1377 return PlFilterCondition
::COND_FALSE
;
1379 return parent
::buildCondition($uf);
1384 // {{{ class UFC_MarketingHash
1385 /** Filters users using the hash generated
1386 * to send marketing emails to him.
1388 class UFC_MarketingHash
extends UserFilterCondition
1392 public function __construct($hash)
1394 $this->hash
= $hash;
1397 public function buildCondition(PlFilter
$uf)
1399 $table = $uf->addMarketingHash();
1400 return XDB
::format('rm.hash = {?}', $this->hash
);
1405 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: