X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fuserfilter.php;h=050c6630b4f60a73c7dca834c30fee7ee2ca79e2;hb=2381efd034b0efc9a0a839d45086b47ccefccf89;hp=e9887936f3d0b94956444460dc164a4f1b7c29b7;hpb=1285cf5413df654ccac839b9d9a32c4df2cee95a;p=platal.git diff --git a/classes/userfilter.php b/classes/userfilter.php index e988793..050c663 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -129,7 +129,7 @@ class UFC_Comment implements UserFilterCondition public function buildCondition(PlFilter &$uf) { $uf->requireProfiles(); - return 'p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text); + return $uf->getVisibilityCondition('p.freetext_pub') . ' AND p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text); } } // }}} @@ -557,6 +557,10 @@ class UFC_Group implements UserFilterCondition public function buildCondition(PlFilter &$uf) { + // Groups have AX visibility. + if ($uf->getVisibilityLevel() == ProfileVisibility::VIS_PUBLIC) { + return PlFilter::COND_TRUE; + } $sub = $uf->addGroupFilter($this->group); $where = 'gpm' . $sub . '.perms IS NOT NULL'; if ($this->anim) { @@ -582,6 +586,10 @@ class UFC_Binet implements UserFilterCondition public function buildCondition(PlFilter &$uf) { + // Binets are private. + if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + return PlFilter::COND_TRUE; + } $sub = $uf->addBinetsFilter(); return XDB::format($sub . '.binet_id IN {?}', $this->val); } @@ -603,6 +611,10 @@ class UFC_Section implements UserFilterCondition public function buildCondition(PlFilter &$uf) { + // Sections are private. + if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + return PlFilter::COND_TRUE; + } $uf->requireProfiles(); return XDB::format('p.section IN {?}', $this->section); } @@ -707,9 +719,10 @@ abstract class UFC_Address implements UserFilterCondition $this->flags = $flags; } - protected function initConds($sub) + protected function initConds($sub, $vis_cond) { - $conds = array(); + $conds = array($vis_cond); + $types = array(); foreach (self::$typetexts as $flag => $type) { if ($flag & $this->type) { @@ -766,7 +779,7 @@ class UFC_AddressText extends UFC_Address public function buildCondition(PlFilter &$uf) { $sub = $uf->addAddressFilter(); - $conds = $this->initConds($sub); + $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub')); if ($this->text != null) { $conds[] = $sub . '.text' . $this->mkMatch($this->text); } @@ -823,7 +836,7 @@ class UFC_AddressField extends UFC_Address public function buildCondition(PlFilter &$uf) { $sub = $uf->addAddressFilter(); - $conds = $this->initConds($sub); + $conds = $this->initConds($sub, $uf->getVisibilityCondition($sub . '.pub')); switch ($this->fieldtype) { case self::FIELD_COUNTRY: @@ -879,6 +892,7 @@ class UFC_Corps implements UserFilterCondition */ $sub = $uf->addCorpsFilter($this->type); $cond = $sub . '.abbreviation = ' . $corps; + $cond .= ' AND ' . $uf->getVisibilityCondition($sub . '.corps_pub'); return $cond; } } @@ -899,10 +913,14 @@ class UFC_Corps_Rank implements UserFilterCondition public function buildCondition(PlFilter &$uf) { /** Tables shortcuts: + * pc for profile_corps * pcr for profile_corps_rank */ $sub = $uf->addCorpsRankFilter(); $cond = $sub . '.abbreviation = ' . $rank; + // XXX(x2006barrois): find a way to get rid of that hardcoded + // reference to 'pc'. + $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub'); return $cond; } } @@ -940,6 +958,8 @@ class UFC_Job_Company implements UserFilterCondition { $sub = $uf->addJobCompanyFilter(); $cond = $sub . '.' . $this->type . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value); + $jsub = $uf->addJobFilter(); + $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub'); return $cond; } } @@ -975,7 +995,41 @@ class UFC_Job_Sectorization implements UserFilterCondition public function buildCondition(PlFilter &$uf) { $sub = $uf->addJobSectorizationFilter($this->type); - return $sub . '.id = ' . XDB::format('{?}', $this->val); + $cond = $sub . '.id = ' . XDB::format('{?}', $this->val); + $jsub = $uf->addJobFilter(); + $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub'); + return $cond; + } +} +// }}} + +// {{{ class UFC_Job_Terms +/** Filters users based on the job terms they assigned to one of their + * jobs. + * @param $val The ID of the job term, or an array of such IDs + */ +class UFC_Job_Terms implements UserFilterCondition +{ + private $val; + + public function __construct($val) + { + if (!is_array($val)) { + $val = array($val); + } + $this->val = $val; + } + + public function buildCondition(PlFilter &$uf) + { + $sub = $uf->addJobTermsFilter(count($this->val)); + $conditions = array(); + foreach ($this->val as $i => $jtid) { + $conditions[] = $sub[$i] . ' = ' . XDB::escape($jtid); + } + $jsub = $uf->addJobFilter(); + $conditions[] = $uf->getVisibilityCondition($jsub . '.pub'); + return implode(' AND ', $conditions); } } // }}} @@ -1000,11 +1054,22 @@ class UFC_Job_Description implements UserFilterCondition public function buildCondition(PlFilter &$uf) { $conds = array(); + + $jsub = $uf->addJobFilter(); + // CV is private => if only CV requested, and not private, + // don't do anything. Otherwise restrict to standard job visibility. + if ($this->fields == UserFilter::JOB_CV) { + if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) { + return PlFilter::COND_TRUE; + } + } else { + $conds[] = $uf->getVisibilityCondition($jsub . '.pub'); + } + if ($this->fields & UserFilter::JOB_USERDEFINED) { - $sub = $uf->addJobFilter(); - $conds[] = $sub . '.description ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); + $conds[] = $jsub . '.description ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); } - if ($this->fields & UserFilter::JOB_CV) { + if ($this->fields & UserFilter::JOB_CV && $uf->getVisibilityLevel == ProfileVisibility::VIS_PRIVATE) { $uf->requireProfiles(); $conds[] = 'p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description); } @@ -1047,6 +1112,7 @@ class UFC_Networking implements UserFilterCondition { $sub = $uf->addNetworkingFilter(); $conds = array(); + $conds[] = $uf->getVisibilityCondition($sub . '.pub'); $conds[] = $sub . '.address ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value); if ($this->type != -1) { $conds[] = $sub . '.nwid = ' . XDB::format('{?}', $this->type); @@ -1080,16 +1146,20 @@ class UFC_Phone implements UserFilterCondition public function __construct($number, $num_type = self::NUM_ANY, $phone_type = self::PHONE_ANY) { - require_once('profil.func.inc.php'); - $this->number = $number; + $phone = new Phone(array('display' => $number)); + $phone->format(); + $this->number = $phone->search(); $this->num_type = $num_type; - $this->phone_type = format_phone_number($phone_type); + $this->phone_type = $phone_type; } public function buildCondition(PlFilter &$uf) { $sub = $uf->addPhoneFilter(); $conds = array(); + + $conds[] = $uf->getVisibilityCondition($sub . '.pub'); + $conds[] = $sub . '.search_tel = ' . XDB::format('{?}', $this->number); if ($this->num_type != self::NUM_ANY) { $conds[] = $sub . '.link_type = ' . XDB::format('{?}', $this->num_type); @@ -1121,7 +1191,12 @@ class UFC_Medal implements UserFilterCondition public function buildCondition(PlFilter &$uf) { $conds = array(); + + // This will require profiles => table 'p' will be available. $sub = $uf->addMedalFilter(); + + $conds[] = $uf->getVisibilityCondition('p.medals_pub'); + $conds[] = $sub . '.mid = ' . XDB::format('{?}', $this->medal); if ($this->grade != null) { $conds[] = $sub . '.gid = ' . XDB::format('{?}', $this->grade); @@ -1138,12 +1213,24 @@ class UFC_Photo implements UserFilterCondition { public function buildCondition(PlFilter &$uf) { - $uf->addPhotoFilter(); - return 'photo.attach IS NOT NULL'; + $sub = $uf->addPhotoFilter(); + return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityCondition($sub . '.pub'); + } +} +// }}} + +// {{{ class UFC_Mentor +class UFC_Mentor implements UserFilterCondition +{ + public function buildCondition(PlFilter &$uf) + { + $sub = $uf->addMentorFilter(UserFilter::MENTOR); + return $sub . '.expertise IS NOT NULL'; } } // }}} + // {{{ class UFC_Mentor_Expertise /** Filters users by mentoring expertise * @param $expertise Domain of expertise @@ -1186,6 +1273,27 @@ class UFC_Mentor_Country implements UserFilterCondition } // }}} +// {{{ class UFC_Mentor_Terms +/** Filters users based on the job terms they used in mentoring. + * @param $val The ID of the job term, or an array of such IDs + */ +class UFC_Mentor_Terms implements UserFilterCondition +{ + private $val; + + public function __construct($val) + { + $this->val = $val; + } + + public function buildCondition(PlFilter &$uf) + { + $sub = $uf->addMentorFilter(UserFilter::MENTOR_TERM); + return $sub . '.jtid_1 = ' . XDB::escape($this->val); + } +} +// }}} + // {{{ class UFC_Mentor_Sectorization /** Filters users based on mentoring (sub|)sector * @param $sector ID of (sub)sector @@ -1332,28 +1440,12 @@ class UFC_MarketingHash implements UserFilterCondition * ORDERS ******************/ -// {{{ class UserFilterOrder -/** Base class for ordering results of a query. - * Parameters for the ordering must be given to the constructor ($desc for a - * descending order). - * The getSortTokens function is used to get actual ordering part of the query. - */ -abstract class UserFilterOrder extends PlFilterOrder -{ - /** This function must return the tokens to use for ordering - * @param &$uf The UserFilter whose results must be ordered - * @return The name of the field to use for ordering results - */ -// abstract protected function getSortTokens(UserFilter &$uf); -} -// }}} - // {{{ class UFO_Promo /** Orders users by promotion * @param $grade Formation whose promotion users should be sorted by (restricts results to users of that formation) * @param $desc Whether sort is descending */ -class UFO_Promo extends UserFilterOrder +class UFO_Promo extends PlFilterGroupableOrder { private $grade; @@ -1383,7 +1475,7 @@ class UFO_Promo extends UserFilterOrder * @param $particle Set to true if particles should be included in the sorting order * @param $desc If sort order should be descending */ -class UFO_Name extends UserFilterOrder +class UFO_Name extends PlFilterOrder { private $type; private $variant; @@ -1401,7 +1493,13 @@ class UFO_Name extends UserFilterOrder { if (Profile::isDisplayName($this->type)) { $sub = $uf->addDisplayFilter(); - return 'pd' . $sub . '.' . $this->type; + $token = 'pd' . $sub . '.' . $this->type; + if ($uf->accountsRequired()) { + $account_token = Profile::getAccountEquivalentName($this->type); + return 'IFNULL(' . $token . ', a.' . $account_token . ')'; + } else { + return $token; + } } else { $sub = $uf->addNameFilter($this->type, $this->variant); if ($this->particle) { @@ -1415,7 +1513,7 @@ class UFO_Name extends UserFilterOrder // }}} // {{{ class UFO_Score -class UFO_Score extends UserFilterOrder +class UFO_Score extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1438,7 +1536,7 @@ class UFO_Score extends UserFilterOrder // {{{ class UFO_Registration /** Sorts users based on registration date */ -class UFO_Registration extends UserFilterOrder +class UFO_Registration extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1451,7 +1549,7 @@ class UFO_Registration extends UserFilterOrder // {{{ class UFO_Birthday /** Sorts users based on next birthday date */ -class UFO_Birthday extends UserFilterOrder +class UFO_Birthday extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1464,7 +1562,7 @@ class UFO_Birthday extends UserFilterOrder // {{{ class UFO_ProfileUpdate /** Sorts users based on last profile update */ -class UFO_ProfileUpdate extends UserFilterOrder +class UFO_ProfileUpdate extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1477,7 +1575,7 @@ class UFO_ProfileUpdate extends UserFilterOrder // {{{ class UFO_Death /** Sorts users based on death date */ -class UFO_Death extends UserFilterOrder +class UFO_Death extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1490,7 +1588,7 @@ class UFO_Death extends UserFilterOrder // {{{ class UFO_Uid /** Sorts users based on their uid */ -class UFO_Uid extends UserFilterOrder +class UFO_Uid extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1503,7 +1601,7 @@ class UFO_Uid extends UserFilterOrder // {{{ class UFO_Hruid /** Sorts users based on their hruid */ -class UFO_Hruid extends UserFilterOrder +class UFO_Hruid extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1516,7 +1614,7 @@ class UFO_Hruid extends UserFilterOrder // {{{ class UFO_Pid /** Sorts users based on their pid */ -class UFO_Pid extends UserFilterOrder +class UFO_Pid extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1529,7 +1627,7 @@ class UFO_Pid extends UserFilterOrder // {{{ class UFO_Hrpid /** Sorts users based on their hrpid */ -class UFO_Hrpid extends UserFilterOrder +class UFO_Hrpid extends PlFilterOrder { protected function getSortTokens(PlFilter &$uf) { @@ -1578,7 +1676,7 @@ class UFO_Hrpid extends UserFilterOrder * when referring to the joined table. * * For example, if data from profile_job must be available to filter results, - * the UFC object will call $uf-addJobFilter(), which will set the 'with_pj' var and + * the UFC object will call $uf-addJobFilter(), which will set the 'with_pj' var and * return 'pj', the short name to use when referring to profile_job; when building * the query, calling the jobJoins function will return an array containing a single * row: @@ -1598,9 +1696,13 @@ class UserFilter extends PlFilter private $root; private $sort = array(); + private $grouper = null; private $query = null; private $orderby = null; + // Store the current 'search' visibility. + private $profile_visibility = null; + private $lastusercount = null; private $lastprofilecount = null; @@ -1621,7 +1723,7 @@ class UserFilter extends PlFilter } } if (!is_null($sort)) { - if ($sort instanceof UserFilterOrder) { + if ($sort instanceof PlFilterOrder) { $this->addSort($sort); } else if (is_array($sort)) { foreach ($sort as $s) { @@ -1629,6 +1731,29 @@ class UserFilter extends PlFilter } } } + + // This will set the visibility to the default correct level. + $this->profile_visibility = new ProfileVisibility(); + } + + public function getVisibilityLevels() + { + return $this->profile_visibility->levels(); + } + + public function getVisibilityLevel() + { + return $this->profile_visibility->level(); + } + + public function restrictVisibilityTo($level) + { + $this->profile_visibility->setLevel($level); + } + + public function getVisibilityCondition($field) + { + return $field . ' IN ' . XDB::formatArray($this->getVisibilityLevels()); } private function buildQuery() @@ -1669,6 +1794,42 @@ class UserFilter extends PlFilter } } + public function hasGroups() + { + return $this->grouper != null; + } + + public function getGroups() + { + return $this->getUIDGroups(); + } + + public function getUIDGroups() + { + $this->requireAccounts(); + $this->buildQuery(); + $token = $this->grouper->getGroupToken($this); + + $groups = XDB::fetchAllRow('SELECT ' . $token . ', COUNT(a.uid) + ' . $this->query . ' + GROUP BY ' . $token, + 0); + return $groups; + } + + public function getPIDGroups() + { + $this->requireProfiles(); + $this->buildQuery(); + $token = $this->grouper->getGroupToken($this); + + $groups = XDB::fetchAllRow('SELECT ' . $token . ', COUNT(p.pid) + ' . $this->query . ' + GROUP BY ' . $token, + 0); + return $groups; + } + private function getUIDList($uids = null, PlLimit &$limit) { $this->requireAccounts(); @@ -1909,6 +2070,10 @@ class UserFilter extends PlFilter public function addSort(PlFilterOrder &$sort) { + if (count($this->sort) == 0 && $sort instanceof PlFilterGroupableOrder) + { + $this->grouper = $sort; + } $this->sort[] = $sort; $this->orderby = null; } @@ -1980,11 +2145,21 @@ class UserFilter extends PlFilter $this->with_accounts = true; } + public function accountsRequired() + { + return $this->with_accounts; + } + public function requireProfiles() { $this->with_profiles = true; } + public function profilesRequired() + { + return $this->with_profiles; + } + protected function accountJoins() { $joins = array(); @@ -2286,7 +2461,7 @@ class UserFilter extends PlFilter if (!is_array($key)) { $key = array($key); } - $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\' + $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\' AND $ME.email IN {?}', $key); } } @@ -2301,7 +2476,7 @@ class UserFilter extends PlFilter if (!is_array($key)) { $key = array($key); } - $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type IN (\'alias\', \'a_vie\') + $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type IN (\'alias\', \'a_vie\') AND $ME.alias IN {?}', $key); } } @@ -2431,6 +2606,7 @@ class UserFilter extends PlFilter * pjsse => profile_job_subsector_enum * pjssse => profile_job_subsubsector_enum * pja => profile_job_alternates + * pjt => profile_job_terms */ private $with_pj = false; private $with_pje = false; @@ -2438,6 +2614,7 @@ class UserFilter extends PlFilter private $with_pjsse = false; private $with_pjssse = false; private $with_pja = false; + private $with_pjt = 0; public function addJobFilter() { @@ -2471,6 +2648,22 @@ class UserFilter extends PlFilter } } + /** + * Adds a filter on job terms of profile. + * @param $nb the number of job terms to use + * @return an array of the fields to filter (one for each term). + * Code using this function should used returned field as is (contains table and field name). + */ + public function addJobTermsFilter($nb = 1) + { + $this->with_pjt = $nb; + $jobtermstable = array(); + for ($i = 1; $i <= $nb; ++$i) { + $jobtermstable[] = 'pjtr_'.$i.'.jtid_1'; + } + return $jobtermstable; + } + protected function jobJoins() { $joins = array(); @@ -2492,6 +2685,12 @@ class UserFilter extends PlFilter if ($this->with_pja) { $joins['pja'] = PlSqlJoin::left('profile_job_alternates', '$ME.subsubsectorid = pj.subsubsectorid'); } + if ($this->with_pjt > 0) { + for ($i = 1; $i <= $this->with_pjt; ++$i) { + $joins['pjt_'.$i] = PlSqlJoin::left('profile_job_term', '$ME.pid = $PID'); + $joins['pjtr_'.$i] = PlSqlJoin::left('profile_job_term_relation', '$ME.jtid_2 = pjt_'.$i.'.jtid'); + } + } return $joins; } @@ -2560,14 +2759,20 @@ class UserFilter extends PlFilter */ private $pms = array(); - const MENTOR_EXPERTISE = 1; - const MENTOR_COUNTRY = 2; - const MENTOR_SECTOR = 3; + private $mjtr = false; + const MENTOR = 1; + const MENTOR_EXPERTISE = 2; + const MENTOR_COUNTRY = 3; + const MENTOR_SECTOR = 4; + const MENTOR_TERM = 5; public function addMentorFilter($type) { $this->requireAccounts(); switch($type) { + case self::MENTOR: + $this->pms['pm'] = 'profile_mentor'; + return 'pm'; case self::MENTOR_EXPERTISE: $this->pms['pme'] = 'profile_mentor'; return 'pme'; @@ -2577,6 +2782,10 @@ class UserFilter extends PlFilter case self::MENTOR_SECTOR: $this->pms['pms'] = 'profile_mentor_sector'; return 'pms'; + case self::MENTOR_TERM: + $this->pms['pmt'] = 'profile_mentor_term'; + $this->mjtr = true; + return 'mjtr'; default: Platal::page()->killError("Undefined mentor filter."); } @@ -2588,6 +2797,9 @@ class UserFilter extends PlFilter foreach ($this->pms as $sub => $tab) { $joins[$sub] = PlSqlJoin::left($tab, '$ME.pid = $PID'); } + if ($this->mjtr) { + $joins['mjtr'] = PlSqlJoin::left('profile_job_term_relation', '$ME.jtid_2 = pmt.jtid'); + } return $joins; } @@ -2679,6 +2891,7 @@ class UserFilter extends PlFilter { $this->requireProfiles(); $this->with_photo = true; + return 'photo'; } protected function photoJoins() @@ -2728,6 +2941,11 @@ class ProfileFilter extends UserFilter { return $this->getTotalProfileCount(); } + + public function getGroups() + { + return $this->getPIDGroups(); + } } // }}}