2 /***************************************************************************
3 * Copyright (C) 2003-2011 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 require_once dirname(__FILE__
) . '/userfilter/conditions.inc.php';
23 require_once dirname(__FILE__
) . '/userfilter/orders.inc.php';
25 /***********************************
26 *********************************
28 *********************************
29 ***********************************/
31 // {{{ class UserFilter
32 /** This class provides a convenient and centralized way of filtering users.
35 * $uf = new UserFilter(new UFC_Blah($x, $y), new UFO_Coin($z, $t));
37 * Resulting UserFilter can be used to:
38 * - get a list of User objects matching the filter
39 * - get a list of UIDs matching the filter
40 * - get the number of users matching the filter
41 * - check whether a given User matches the filter
42 * - filter a list of User objects depending on whether they match the filter
44 * Usage for UFC and UFO objects:
45 * A UserFilter will call all private functions named XXXJoins.
46 * These functions must return an array containing the list of join
47 * required by the various UFC and UFO associated to the UserFilter.
48 * Entries in those returned array are of the following form:
49 * 'join_tablealias' => array('join_type', 'joined_table', 'join_criter')
50 * which will be translated into :
51 * join_type JOIN joined_table AS join_tablealias ON (join_criter)
54 * In the join_criter text, $ME is replaced with 'join_tablealias', $PID with
55 * profile.pid, and $UID with accounts.uid.
57 * For each kind of "JOIN" needed, a function named addXXXFilter() should be defined;
58 * its parameter will be used to set various private vars of the UserFilter describing
59 * the required joins ; such a function shall return the "join_tablealias" to use
60 * when referring to the joined table.
62 * For example, if data from profile_job must be available to filter results,
63 * the UFC object will call $uf-addJobFilter(), which will set the 'with_pj' var and
64 * return 'pj', the short name to use when referring to profile_job; when building
65 * the query, calling the jobJoins function will return an array containing a single
67 * 'pj' => array('left', 'profile_job', '$ME.pid = $UID');
69 * The 'register_optional' function can be used to generate unique table aliases when
70 * the same table has to be joined several times with different aliases.
72 class UserFilter
extends PlFilter
74 protected $joinMethods = array();
76 protected $joinMetas = array(
82 private $sort = array();
83 private $grouper = null
;
84 private $query = null
;
85 private $orderby = null
;
87 // Store the current 'search' visibility.
88 private $profile_visibility = null
;
90 private $lastusercount = null
;
91 private $lastprofilecount = null
;
93 public function __construct($cond = null
, $sort = null
)
95 if (empty($this->joinMethods
)) {
96 $class = new ReflectionClass('UserFilter');
97 foreach ($class->getMethods() as $method) {
98 $name = $method->getName();
99 if (substr($name, -5) == 'Joins' && $name != 'buildJoins') {
100 $this->joinMethods
[] = $name;
104 if (!is_null($cond)) {
105 if ($cond instanceof PlFilterCondition
) {
106 $this->setCondition($cond);
109 if (!is_null($sort)) {
110 if ($sort instanceof PlFilterOrder
) {
111 $this->addSort($sort);
112 } else if (is_array($sort)) {
113 foreach ($sort as $s) {
119 // This will set the visibility to the default correct level.
120 $this->profile_visibility
= new ProfileVisibility();
123 public function getVisibilityLevels()
125 return $this->profile_visibility
->levels();
128 public function getVisibilityLevel()
130 return $this->profile_visibility
->level();
133 public function restrictVisibilityTo($level)
135 $this->profile_visibility
->setLevel($level);
138 public function getVisibilityCondition($field)
140 return $field . ' IN ' . XDB
::formatArray($this->getVisibilityLevels());
143 private function buildQuery()
145 // The root condition is built first because some orders need info
146 // available only once all UFC have set their conditions (UFO_Score)
147 if (is_null($this->query
)) {
148 $where = $this->root
->buildCondition($this);
149 $where = str_replace(array_keys($this->joinMetas
),
153 if (is_null($this->orderby
)) {
155 foreach ($this->sort
as $sort) {
156 $orders = array_merge($orders, $sort->buildSort($this));
158 if (count($orders) == 0) {
161 $this->orderby
= 'ORDER BY ' . implode(', ', $orders);
163 $this->orderby
= str_replace(array_keys($this->joinMetas
),
167 if (is_null($this->query
)) {
168 if ($this->with_accounts
) {
169 $from = 'accounts AS a';
171 $this->requireProfiles();
172 $from = 'profiles AS p';
174 $joins = $this->buildJoins();
175 $this->query
= 'FROM ' . $from . '
177 WHERE (' . $where . ')';
181 public function hasGroups()
183 return $this->grouper
!= null
;
186 public function getGroups()
188 return $this->getUIDGroups();
191 public function getUIDGroups()
193 $this->requireAccounts();
195 $token = $this->grouper
->getGroupToken($this);
197 $groups = XDB
::rawFetchAllRow('SELECT ' . $token . ', COUNT(a.uid)
204 public function getPIDGroups()
206 $this->requireProfiles();
208 $token = $this->grouper
->getGroupToken($this);
210 $groups = XDB
::rawFetchAllRow('SELECT ' . $token . ', COUNT(p.pid)
217 private function getUIDList($uids = null
, PlLimit
$limit)
219 $this->requireAccounts();
221 $lim = $limit->getSql();
224 $cond = XDB
::format(' AND a.uid IN {?}', $uids);
226 $fetched = XDB
::rawFetchColumn('SELECT SQL_CALC_FOUND_ROWS a.uid
227 ' . $this->query
. $cond . '
229 ' . $this->orderby
. '
231 $this->lastusercount
= (int)XDB
::fetchOneCell('SELECT FOUND_ROWS()');
235 private function getPIDList($pids = null
, PlLimit
$limit)
237 $this->requireProfiles();
239 $lim = $limit->getSql();
241 if (!is_null($pids)) {
242 $cond = XDB
::format(' AND p.pid IN {?}', $pids);
244 $fetched = XDB
::rawFetchColumn('SELECT SQL_CALC_FOUND_ROWS p.pid
245 ' . $this->query
. $cond . '
247 ' . $this->orderby
. '
249 $this->lastprofilecount
= (int)XDB
::fetchOneCell('SELECT FOUND_ROWS()');
253 private static function defaultLimit($limit) {
254 if ($limit == null
) {
255 return new PlLimit();
261 /** Check that the user match the given rule.
263 public function checkUser(PlUser
$user)
265 $this->requireAccounts();
267 $count = (int)XDB
::rawFetchOneCell('SELECT COUNT(*)
269 . XDB
::format(' AND a.uid = {?}', $user->id()));
273 /** Check that the profile match the given rule.
275 public function checkProfile(Profile
$profile)
277 $this->requireProfiles();
279 $count = (int)XDB
::rawFetchOneCell('SELECT COUNT(*)
281 . XDB
::format(' AND p.pid = {?}', $profile->id()));
285 /** Default filter is on users
287 public function filter(array $users, $limit = null
)
289 return $this->filterUsers($users, self
::defaultLimit($limit));
292 /** Filter a list of users to extract the users matching the rule.
294 public function filterUsers(array $users, $limit = null
)
296 $limit = self
::defaultLimit($limit);
297 $this->requireAccounts();
301 foreach ($users as $user) {
302 if ($user instanceof PlUser
) {
308 $table[$uid] = $user;
310 $fetched = $this->getUIDList($uids, $limit);
312 foreach ($fetched as $uid) {
313 $output[] = $table[$uid];
318 /** Filter a list of profiles to extract the users matching the rule.
320 public function filterProfiles(array $profiles, $limit = null
)
322 $limit = self
::defaultLimit($limit);
323 $this->requireProfiles();
327 foreach ($profiles as $profile) {
328 if ($profile instanceof Profile
) {
329 $pid = $profile->id();
334 $table[$pid] = $profile;
336 $fetched = $this->getPIDList($pids, $limit);
338 foreach ($fetched as $pid) {
339 $output[] = $table[$pid];
344 public function getUIDs($limit = null
)
346 $limit = self
::defaultLimit($limit);
347 return $this->getUIDList(null
, $limit);
350 public function getUID($pos = 0)
352 $uids =$this->getUIDList(null
, new PlLimit(1, $pos));
353 if (count($uids) == 0) {
360 public function getPIDs($limit = null
)
362 $limit = self
::defaultLimit($limit);
363 return $this->getPIDList(null
, $limit);
366 public function getPID($pos = 0)
368 $pids =$this->getPIDList(null
, new PlLimit(1, $pos));
369 if (count($pids) == 0) {
376 public function getUsers($limit = null
)
378 return User
::getBulkUsersWithUIDs($this->getUIDs($limit));
381 public function getUser($pos = 0)
383 $uid = $this->getUID($pos);
387 return User
::getWithUID($uid);
391 public function iterUsers($limit = null
)
393 return User
::iterOverUIDs($this->getUIDs($limit));
396 public function getProfiles($limit = null
, $fields = 0x0000, $visibility = null
)
398 return Profile
::getBulkProfilesWithPIDs($this->getPIDs($limit), $fields, $visibility);
401 public function getProfile($pos = 0, $fields = 0x0000, $visibility = null
)
403 $pid = $this->getPID($pos);
407 return Profile
::get($pid, $fields, $visibility);
411 public function iterProfiles($limit = null
, $fields = 0x0000, $visibility = null
)
413 return Profile
::iterOverPIDs($this->getPIDs($limit), true
, $fields, $visibility);
416 public function get($limit = null
)
418 return $this->getUsers($limit);
421 public function getIds($limit = null
)
423 return $this->getUIDs();
426 public function getTotalCount()
428 return $this->getTotalUserCount();
431 public function getTotalUserCount()
433 if (is_null($this->lastusercount
)) {
434 $this->requireAccounts();
436 return (int)XDB
::rawFetchOneCell('SELECT COUNT(DISTINCT a.uid)
439 return $this->lastusercount
;
443 public function getTotalProfileCount()
445 if (is_null($this->lastprofilecount
)) {
446 $this->requireProfiles();
448 return (int)XDB
::rawFetchOneCell('SELECT COUNT(DISTINCT p.pid)
451 return $this->lastprofilecount
;
455 public function setCondition(PlFilterCondition
$cond)
457 $this->root
=& $cond;
461 public function addSort(PlFilterOrder
$sort)
463 if (count($this->sort
) == 0 && $sort instanceof PlFilterGroupableOrder
)
465 $this->grouper
= $sort;
467 $this->sort
[] = $sort;
468 $this->orderby
= null
;
471 public function export()
473 $export = array('conditions' => $this->root
->export());
474 if (!empty($this->sort
)) {
475 $export['sorts'] = array();
476 foreach ($this->sort
as $sort) {
477 $export['sorts'][] = $sort->export();
483 public function exportConditions()
485 return $this->root
->export();
488 public static function fromExport(array $export)
490 $export = new PlDict($export);
491 if (!$export->has('conditions')) {
492 throw new Exception("Cannot build a user filter without conditions");
494 $cond = UserFilterCondition
::fromExport($export->v('conditions'));
496 if ($export->has('sorts')) {
498 foreach ($export->v('sorts') as $sort) {
499 $sorts[] = UserFilterOrder
::fromExport($sort);
502 return new UserFilter($cond, $sorts);
505 public static function fromJSon($json)
507 $export = json_decode($json, true
);
508 if (is_null($export)) {
509 throw new Exception("Invalid json: $json");
511 return self
::fromExport($json);
514 public static function fromExportedConditions(array $export)
516 $cond = UserFilterCondition
::fromExport($export);
517 return new UserFilter($cond);
520 public static function fromJSonConditions($json)
522 $export = json_decode($json, true
);
523 if (is_null($export)) {
524 throw new Exception("Invalid json: $json");
526 return self
::fromExportedConditions($json);
529 static public function getLegacy($promo_min, $promo_max)
531 if ($promo_min != 0) {
532 $min = new UFC_Promo('>=', self
::GRADE_ING
, intval($promo_min));
534 $min = new PFC_True();
536 if ($promo_max != 0) {
537 $max = new UFC_Promo('<=', self
::GRADE_ING
, intval($promo_max));
539 $max = new PFC_True();
541 return new UserFilter(new PFC_And($min, $max));
544 static public function sortByName()
546 return array(new UFO_Name(Profile
::LASTNAME
), new UFO_Name(Profile
::FIRSTNAME
));
549 static public function sortByPromo()
551 return array(new UFO_Promo(), new UFO_Name(Profile
::LASTNAME
), new UFO_Name(Profile
::FIRSTNAME
));
554 static private function getDBSuffix($string)
556 if (is_array($string)) {
557 if (count($string) == 1) {
558 return self
::getDBSuffix(array_pop($string));
560 return md5(implode('|', $string));
562 return preg_replace('/[^a-z0-9]/i', '', $string);
567 /** Stores a new (and unique) table alias in the &$table table
568 * @param &$table Array in which the table alias must be stored
569 * @param $val Value which will then be used to build the join
570 * @return Name of the newly created alias
573 private function register_optional(array &$table, $val)
576 $sub = $this->option++
;
579 $sub = self
::getDBSuffix($val);
583 $table[$sub] = $index;
587 /** PROFILE VS ACCOUNT
589 private $with_profiles = false
;
590 private $with_accounts = false
;
591 public function requireAccounts()
593 $this->with_accounts
= true
;
596 public function accountsRequired()
598 return $this->with_accounts
;
601 public function requireProfiles()
603 $this->with_profiles
= true
;
606 public function profilesRequired()
608 return $this->with_profiles
;
611 protected function accountJoins()
614 if ($this->with_profiles
&& $this->with_accounts
) {
615 $joins['ap'] = PlSqlJoin
::left('account_profiles', '$ME.uid = $UID AND FIND_IN_SET(\'owner\', ap.perms)');
616 $joins['p'] = PlSqlJoin
::left('profiles', '$PID = ap.pid');
624 public function requirePerms()
626 $this->requireAccounts();
631 protected function permJoins()
634 return array('at' => PlSqlJoin
::left('account_types', '$ME.type = a.type'));
642 const DISPLAY
= 'display';
644 public function addDisplayFilter()
646 $this->requireProfiles();
651 protected function displayJoins()
654 return array('pd' => PlSqlJoin
::left('profile_display', '$ME.pid = $PID'));
663 private $with_logger = false
;
664 public function addLoggerFilter()
666 $this->with_logger
= true
;
667 $this->requireAccounts();
670 protected function loggerJoins()
673 if ($this->with_logger
) {
674 $joins['ls'] = PlSqlJoin
::left('log_sessions', '$ME.uid = $UID');
682 static public function assertName($name)
684 if (!DirEnum
::getID(DirEnum
::NAMETYPES
, $name)) {
685 Platal
::page()->kill('Invalid name type: ' . $name);
689 private $pn = array();
690 public function addNameFilter($type, $variant = null
)
692 $this->requireProfiles();
693 if (!is_null($variant)) {
694 $ft = $type . '_' . $variant;
699 self
::assertName($ft);
701 if (!is_null($variant) && $variant == 'other') {
702 $sub .= $this->option++
;
704 $this->pn
[$sub] = DirEnum
::getID(DirEnum
::NAMETYPES
, $ft);
708 protected function nameJoins()
711 foreach ($this->pn
as $sub => $type) {
712 $joins['pn' . $sub] = PlSqlJoin
::left('profile_name', '$ME.pid = $PID AND $ME.typeid = {?}', $type);
719 private $name_tokens = array();
720 private $nb_tokens = 0;
722 public function addNameTokensFilter($token)
724 $this->requireProfiles();
725 $sub = 'sn' . (1 +
$this->nb_tokens
);
727 $this->name_tokens
[$sub] = $token;
731 protected function nameTokensJoins()
733 /* We don't return joins, since with_sn forces the SELECT to run on search_name first */
735 foreach ($this->name_tokens
as $sub => $token) {
736 $joins[$sub] = PlSqlJoin
::left('search_name', '$ME.pid = $PID');
741 public function getNameTokens()
743 return $this->name_tokens
;
749 private $with_nat = false
;
750 public function addNationalityFilter()
752 $this->with_nat
= true
;
756 protected function nationalityJoins()
759 if ($this->with_nat
) {
760 $joins['ngc'] = PlSqlJoin
::left('geoloc_countries', '$ME.iso_3166_1_a2 = p.nationality1 OR $ME.iso_3166_1_a2 = p.nationality2 OR $ME.iso_3166_1_a2 = p.nationality3');
767 const GRADE_ING
= 'Ing.';
768 const GRADE_PHD
= 'PhD';
769 const GRADE_MST
= 'M%';
770 static public function isGrade($grade)
772 return ($grade !== 0) && ($grade == self
::GRADE_ING ||
$grade == self
::GRADE_PHD ||
$grade == self
::GRADE_MST
);
775 static public function assertGrade($grade)
777 if (!self
::isGrade($grade)) {
778 Platal
::page()->killError("Diplôme non valide: $grade");
782 static public function promoYear($grade)
784 // XXX: Definition of promotion for phds and masters might change in near future.
785 return ($grade == UserFilter
::GRADE_ING
) ?
'entry_year' : 'grad_year';
788 private $pepe = array();
789 private $with_pee = false
;
790 public function addEducationFilter($x = false
, $grade = null
)
792 $this->requireProfiles();
794 $index = $this->option
;
795 $sub = $this->option++
;
797 self
::assertGrade($grade);
800 $this->with_pee
= true
;
803 $this->pepe
[$index] = $sub;
807 protected function educationJoins()
810 if ($this->with_pee
) {
811 $joins['pee'] = PlSqlJoin
::inner('profile_education_enum', 'pee.abbreviation = \'X\'');
813 foreach ($this->pepe
as $grade => $sub) {
814 if ($this->isGrade($grade)) {
815 $joins['pe' . $sub] = PlSqlJoin
::left('profile_education', '$ME.eduid = pee.id AND $ME.pid = $PID');
816 $joins['pede' . $sub] = PlSqlJoin
::inner('profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid AND $ME.abbreviation LIKE {?}', $grade);
818 $joins['pe' . $sub] = PlSqlJoin
::left('profile_education', '$ME.pid = $PID');
819 $joins['pee' . $sub] = PlSqlJoin
::inner('profile_education_enum', '$ME.id = pe' . $sub . '.eduid');
820 $joins['pede' . $sub] = PlSqlJoin
::inner('profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid');
829 private $gpm = array();
830 public function addGroupFilter($group = null
)
832 $this->requireAccounts();
833 if (!is_null($group)) {
834 if (is_int($group) ||
ctype_digit($group)) {
835 $index = $sub = $group;
838 $sub = self
::getDBSuffix($group);
841 $sub = 'group_' . $this->option++
;
845 $this->gpm
[$sub] = $index;
849 protected function groupJoins()
852 foreach ($this->gpm
as $sub => $key) {
854 $joins['gpa' . $sub] = PlSqlJoin
::inner('groups');
855 $joins['gpm' . $sub] = PlSqlJoin
::left('group_members', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
856 } else if (is_int($key) ||
ctype_digit($key)) {
857 $joins['gpm' . $sub] = PlSqlJoin
::left('group_members', '$ME.uid = $UID AND $ME.asso_id = ' . $key);
859 $joins['gpa' . $sub] = PlSqlJoin
::inner('groups', '$ME.diminutif = {?}', $key);
860 $joins['gpm' . $sub] = PlSqlJoin
::left('group_members', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
868 private $nls = array();
869 public function addNewsLetterFilter($nlid)
871 $this->requireAccounts();
872 $sub = 'nl_' . $nlid;
873 $this->nls
[$nlid] = $sub;
877 protected function newsLetterJoins()
880 foreach ($this->nls
as $key => $sub) {
881 $joins[$sub] = PlSqlJoin
::left('newsletter_ins', '$ME.nlid = {?} AND $ME.uid = $UID', $key);
889 private $with_bi = false
;
890 private $with_bd = false
;
891 public function addBinetsFilter($with_enum = false
)
893 $this->requireProfiles();
894 $this->with_bi
= true
;
896 $this->with_bd
= true
;
903 protected function binetsJoins()
906 if ($this->with_bi
) {
907 $joins['bi'] = PlSqlJoin
::left('profile_binets', '$ME.pid = $PID');
909 if ($this->with_bd
) {
910 $joins['bd'] = PlSqlJoin
::left('profile_binet_enum', '$ME.id = bi.binet_id');
917 private $ra = array();
918 /** Allows filtering by redirection.
919 * @param $email If null, enable a left join on the email redirection table
920 * (email_redirect_account); otherwise, perform a left join on users having
921 * that email as a redirection.
922 * @return Suffix to use to access the adequate table.
924 public function addEmailRedirectFilter($email = null
)
926 $this->requireAccounts();
927 return $this->register_optional($this->ra
, $email);
930 const ALIAS_BEST
= 'bestalias';
931 const ALIAS_FORLIFE
= 'forlife';
932 const ALIAS_AUXILIARY
= 'alias_aux';
933 private $sa = array();
934 /** Allows filtering by source email.
935 * @param $email If null, enable a left join on the email source table
936 * (email_source_account); otherwise, perform a left join on users having
937 * that email as a source email.
938 * @return Suffix to use to access the adequate table.
940 public function addAliasFilter($email = null
)
942 $this->requireAccounts();
943 return $this->register_optional($this->sa
, $email);
946 protected function emailJoins()
950 foreach ($this->ra
as $sub => $redirections) {
951 if (is_null($redirections)) {
952 $joins['ra' . $sub] = PlSqlJoin
::left('email_redirect_account', '$ME.uid = $UID AND $ME.type != \'imap\'');
954 if (!is_array($redirections)) {
955 $key = array($redirections);
957 $joins['ra' . $sub] = PlSqlJoin
::left('email_redriect_account', '$ME.uid = $UID AND $ME.type != \'imap\'
958 AND $ME.redirect IN {?}', $redirections);
961 foreach ($this->sa
as $sub => $emails) {
962 if (is_null($emails)) {
963 $joins['sa' . $sub] = PlSqlJoin
::left('email_source_account', '$ME.uid = $UID');
964 } else if ($key == self
::ALIAS_BEST
) {
965 $joins['sa' . $sub] = PlSqlJoin
::left('email_source_account', '$ME.uid = $UID AND FIND_IN_SET(\'bestalias\', $ME.flags)');
966 } else if ($key == self
::ALIAS_FORLIFE
) {
967 $joins['sa' . $sub] = PlSqlJoin
::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'forlife\'');
968 } else if ($key == self
::ALIAS_AUXILiIARY
) {
969 $joins['sa' . $sub] = PlSqlJoin
::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'alias_aux\'');
971 if (!is_array($emails)) {
972 $key = array($emails);
974 $joins['sa' . $sub] = PlSqlJoin
::left('email_source_account', '$ME.uid = $UID AND $ME.email IN {?}', $emails);
983 private $with_pa = false
;
984 public function addAddressFilter()
986 $this->requireProfiles();
987 $this->with_pa
= true
;
991 private $with_pac = false
;
992 public function addAddressCountryFilter()
994 $this->requireProfiles();
995 $this->addAddressFilter();
996 $this->with_pac
= true
;
1000 private $with_pal = false
;
1001 public function addAddressLocalityFilter()
1003 $this->requireProfiles();
1004 $this->addAddressFilter();
1005 $this->with_pal
= true
;
1009 protected function addressJoins()
1012 if ($this->with_pa
) {
1013 $joins['pa'] = PlSqlJoin
::left('profile_addresses', '$ME.pid = $PID');
1015 if ($this->with_pac
) {
1016 $joins['gc'] = PlSqlJoin
::left('geoloc_countries', '$ME.iso_3166_1_a2 = pa.countryID');
1018 if ($this->with_pal
) {
1019 $joins['gl'] = PlSqlJoin
::left('geoloc_localities', '$ME.id = pa.localityID');
1028 private $pc = false
;
1029 private $pce = array();
1030 private $pcr = false
;
1031 public function addCorpsFilter($type)
1033 $this->requireProfiles();
1035 if ($type == UFC_Corps
::CURRENT
) {
1036 $pce['pcec'] = 'current_corpsid';
1038 } else if ($type == UFC_Corps
::ORIGIN
) {
1039 $pce['pceo'] = 'original_corpsid';
1044 public function addCorpsRankFilter()
1046 $this->requireProfiles();
1052 protected function corpsJoins()
1056 $joins['pc'] = PlSqlJoin
::left('profile_corps', '$ME.pid = $PID');
1059 $joins['pcr'] = PlSqlJoin
::left('profile_corps_rank_enum', '$ME.id = pc.rankid');
1061 foreach($this->pce
as $sub => $field) {
1062 $joins[$sub] = PlSqlJoin
::left('profile_corps_enum', '$ME.id = pc.' . $field);
1070 const JOB_USERDEFINED
= 0x0001;
1071 const JOB_CV
= 0x0002;
1072 const JOB_ANY
= 0x0003;
1076 * pje => profile_job_enum
1077 * pjt => profile_job_terms
1079 private $with_pj = false
;
1080 private $with_pje = false
;
1081 private $with_pjt = 0;
1083 public function addJobFilter()
1085 $this->requireProfiles();
1086 $this->with_pj
= true
;
1090 public function addJobCompanyFilter()
1092 $this->addJobFilter();
1093 $this->with_pje
= true
;
1098 * Adds a filter on job terms of profile.
1099 * @param $nb the number of job terms to use
1100 * @return an array of the fields to filter (one for each term).
1102 public function addJobTermsFilter($nb = 1)
1104 $this->with_pjt
= $nb;
1105 $jobtermstable = array();
1106 for ($i = 1; $i <= $nb; ++
$i) {
1107 $jobtermstable[] = 'pjtr_'.$i;
1109 return $jobtermstable;
1112 protected function jobJoins()
1115 if ($this->with_pj
) {
1116 $joins['pj'] = PlSqlJoin
::left('profile_job', '$ME.pid = $PID');
1118 if ($this->with_pje
) {
1119 $joins['pje'] = PlSqlJoin
::left('profile_job_enum', '$ME.id = pj.jobid');
1121 if ($this->with_pjt
> 0) {
1122 for ($i = 1; $i <= $this->with_pjt
; ++
$i) {
1123 $joins['pjt_'.$i] = PlSqlJoin
::left('profile_job_term', '$ME.pid = $PID');
1124 $joins['pjtr_'.$i] = PlSqlJoin
::left('profile_job_term_relation', '$ME.jtid_2 = pjt_'.$i.'.jtid');
1133 private $with_pnw = false
;
1134 public function addNetworkingFilter()
1136 $this->requireAccounts();
1137 $this->with_pnw
= true
;
1141 protected function networkingJoins()
1144 if ($this->with_pnw
) {
1145 $joins['pnw'] = PlSqlJoin
::left('profile_networking', '$ME.pid = $PID');
1153 private $with_ptel = false
;
1155 public function addPhoneFilter()
1157 $this->requireAccounts();
1158 $this->with_ptel
= true
;
1162 protected function phoneJoins()
1165 if ($this->with_ptel
) {
1166 $joins['ptel'] = PlSqlJoin
::left('profile_phones', '$ME.pid = $PID');
1174 private $with_pmed = false
;
1175 public function addMedalFilter()
1177 $this->requireProfiles();
1178 $this->with_pmed
= true
;
1182 protected function medalJoins()
1185 if ($this->with_pmed
) {
1186 $joins['pmed'] = PlSqlJoin
::left('profile_medals', '$ME.pid = $PID');
1194 private $pms = array();
1195 private $mjtr = false
;
1197 const MENTOR_EXPERTISE
= 2;
1198 const MENTOR_COUNTRY
= 3;
1199 const MENTOR_TERM
= 4;
1201 public function addMentorFilter($type)
1203 $this->requireAccounts();
1206 $this->pms
['pm'] = 'profile_mentor';
1208 case self
::MENTOR_EXPERTISE
:
1209 $this->pms
['pme'] = 'profile_mentor';
1211 case self
::MENTOR_COUNTRY
:
1212 $this->pms
['pmc'] = 'profile_mentor_country';
1214 case self
::MENTOR_TERM
:
1215 $this->pms
['pmt'] = 'profile_mentor_term';
1219 Platal
::page()->killError("Undefined mentor filter.");
1223 protected function mentorJoins()
1226 foreach ($this->pms
as $sub => $tab) {
1227 $joins[$sub] = PlSqlJoin
::left($tab, '$ME.pid = $PID');
1230 $joins['mjtr'] = PlSqlJoin
::left('profile_job_term_relation', '$ME.jtid_2 = pmt.jtid');
1237 private $cts = array();
1238 public function addContactFilter($uid = null
)
1240 $this->requireProfiles();
1241 return $this->register_optional($this->cts
, is_null($uid) ? null
: 'user_' . $uid);
1244 protected function contactJoins()
1247 foreach ($this->cts
as $sub=>$key) {
1248 if (is_null($key)) {
1249 $joins['c' . $sub] = PlSqlJoin
::left('contacts', '$ME.contact = $PID');
1251 $joins['c' . $sub] = PlSqlJoin
::left('contacts', '$ME.uid = {?} AND $ME.contact = $PID', substr($key, 5));
1260 private $wn = array();
1261 public function addWatchRegistrationFilter($uid = null
)
1263 $this->requireAccounts();
1264 return $this->register_optional($this->wn
, is_null($uid) ? null
: 'user_' . $uid);
1267 private $wp = array();
1268 public function addWatchPromoFilter($uid = null
)
1270 $this->requireAccounts();
1271 return $this->register_optional($this->wp
, is_null($uid) ? null
: 'user_' . $uid);
1274 private $w = array();
1275 public function addWatchFilter($uid = null
)
1277 $this->requireAccounts();
1278 return $this->register_optional($this->w
, is_null($uid) ? null
: 'user_' . $uid);
1281 protected function watchJoins()
1284 foreach ($this->w
as $sub=>$key) {
1285 if (is_null($key)) {
1286 $joins['w' . $sub] = PlSqlJoin
::left('watch');
1288 $joins['w' . $sub] = PlSqlJoin
::left('watch', '$ME.uid = {?}', substr($key, 5));
1291 foreach ($this->wn
as $sub=>$key) {
1292 if (is_null($key)) {
1293 $joins['wn' . $sub] = PlSqlJoin
::left('watch_nonins', '$ME.ni_id = $UID');
1295 $joins['wn' . $sub] = PlSqlJoin
::left('watch_nonins', '$ME.uid = {?} AND $ME.ni_id = $UID', substr($key, 5));
1298 foreach ($this->wn
as $sub=>$key) {
1299 if (is_null($key)) {
1300 $joins['wn' . $sub] = PlSqlJoin
::left('watch_nonins', '$ME.ni_id = $UID');
1302 $joins['wn' . $sub] = PlSqlJoin
::left('watch_nonins', '$ME.uid = {?} AND $ME.ni_id = $UID', substr($key, 5));
1305 foreach ($this->wp
as $sub=>$key) {
1306 if (is_null($key)) {
1307 $joins['wp' . $sub] = PlSqlJoin
::left('watch_promo');
1309 $joins['wp' . $sub] = PlSqlJoin
::left('watch_promo', '$ME.uid = {?}', substr($key, 5));
1318 private $with_photo;
1319 public function addPhotoFilter()
1321 $this->requireProfiles();
1322 $this->with_photo
= true
;
1326 protected function photoJoins()
1328 if ($this->with_photo
) {
1329 return array('photo' => PlSqlJoin
::left('profile_photos', '$ME.pid = $PID'));
1339 public function addMarketingHash()
1341 $this->requireAccounts();
1342 $this->with_rm
= true
;
1345 protected function marketingJoins()
1347 if ($this->with_rm
) {
1348 return array('rm' => PlSqlJoin
::left('register_marketing', '$ME.uid = $UID'));
1355 // {{{ class ProfileFilter
1356 class ProfileFilter
extends UserFilter
1358 public function get($limit = null
)
1360 return $this->getProfiles($limit);
1363 public function getIds($limit = null
)
1365 return $this->getPIDs();
1368 public function filter(array $profiles, $limit = null
)
1370 return $this->filterProfiles($profiles, self
::defaultLimit($limit));
1373 public function getTotalCount()
1375 return $this->getTotalProfileCount();
1378 public function getGroups()
1380 return $this->getPIDGroups();
1385 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: