<?php
/***************************************************************************
- * Copyright (C) 2003-2010 Polytechnique.org *
+ * Copyright (C) 2003-2011 Polytechnique.org *
* http://opensource.polytechnique.org/ *
* *
* This program is free software; you can redistribute it and/or modify *
private $orderby = null;
// Store the current 'search' visibility.
- private $profile_visibility = null;
+ private $visibility = null;
+ // If the 'search' visibility should be based on a DB field instead.
+ private $visibility_field = null;
private $lastusercount = null;
private $lastprofilecount = null;
}
// This will set the visibility to the default correct level.
- $this->profile_visibility = new ProfileVisibility();
+ $this->visibility = Visibility::defaultForRead();
}
- 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);
+ /** Get the SQL condition to filter by visibility level for a field.
+ * This will return a SQL condition which evaluates to True if the given
+ * field display level is available from the current access level.
+ * @param $field Name of the field holding a display level
+ * @return string SQL condition, properly escaped, for that field.
+ */
+ public function getVisibilityConditionForField($field)
+ {
+ if ($this->visibility_field != null) {
+ // Use enum 'bit' arithmetic.
+ // Display levels are ordered as 'hidden, private, ax, public'
+ // Thus ax > private.
+ // The $sub.display_level cell will contain the 'most private' display
+ // level available based on $field. If it is 'ax' and $field is
+ // 'private','ax' <= 'private' is false.
+ $sub = $this->addVisibilityFieldFilter($this->visibility_field);
+ return $sub . '.best_display_level + 0 <= 0 + ' . $field;
+ } else {
+ $sub = $this->addVisibilityAbsoluteFilter($this->visibility->level());
+ return $sub . '.best_display_level + 0 <= 0 + ' . $field;
+ }
}
- public function getVisibilityCondition($field)
+ /** Get the SQL condition to filter by a given visibility level.
+ * @param $level One of Visibility::EXPORT_*
+ * @return string A SQL condition, properly escaped, which evaluates to 'true' if the $level can be viewed with the current access level.
+ */
+ public function getVisibilityConditionAbsolute($level)
{
- return $field . ' IN ' . XDB::formatArray($this->getVisibilityLevels());
+ if ($this->visibility_field != null) {
+ // The $sub.display_levels cell will contain allowed display levels
+ // for an access level of $this->visibility_field.
+ $sub = $this->addVisibilityFieldFilter($this->visibility_field);
+ return XDB::format('FIND_IN_SET({?}, ' . $sub . '.display_levels)', $level);
+ } else {
+ if ($this->visibility->isVisible($level)) {
+ return 'TRUE';
+ } else {
+ return 'FALSE';
+ }
+ }
}
private function buildQuery()
return $groups;
}
- private function getUIDList($uids = null, PlLimit &$limit)
+ private function getUIDList($uids = null, PlLimit $limit)
{
$this->requireAccounts();
$this->buildQuery();
return $fetched;
}
- private function getPIDList($pids = null, PlLimit &$limit)
+ private function getPIDList($pids = null, PlLimit $limit)
{
$this->requireProfiles();
$this->buildQuery();
/** Check that the user match the given rule.
*/
- public function checkUser(PlUser &$user)
+ public function checkUser(PlUser $user)
{
$this->requireAccounts();
$this->buildQuery();
/** Check that the profile match the given rule.
*/
- public function checkProfile(Profile &$profile)
+ public function checkProfile(Profile $profile)
{
$this->requireProfiles();
$this->buildQuery();
return $this->getUsers($limit);
}
+ public function getIds($limit = null)
+ {
+ return $this->getUIDs();
+ }
public function getTotalCount()
{
static public function sortByName()
{
- return array(new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME));
+ return array(new UFO_Name());
}
static public function sortByPromo()
{
- return array(new UFO_Promo(), new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME));
+ return array(new UFO_Promo(), new UFO_Name());
}
static private function getDBSuffix($string)
return $joins;
}
- /** NAMES
- */
-
- static public function assertName($name)
- {
- if (!DirEnum::getID(DirEnum::NAMETYPES, $name)) {
- Platal::page()->kill('Invalid name type: ' . $name);
- }
- }
-
- private $pn = array();
- public function addNameFilter($type, $variant = null)
- {
- $this->requireProfiles();
- if (!is_null($variant)) {
- $ft = $type . '_' . $variant;
- } else {
- $ft = $type;
- }
- $sub = '_' . $ft;
- self::assertName($ft);
-
- if (!is_null($variant) && $variant == 'other') {
- $sub .= $this->option++;
- }
- $this->pn[$sub] = DirEnum::getID(DirEnum::NAMETYPES, $ft);
- return $sub;
- }
-
- protected function nameJoins()
- {
- $joins = array();
- foreach ($this->pn as $sub => $type) {
- $joins['pn' . $sub] = PlSqlJoin::left('profile_name', '$ME.pid = $PID AND $ME.typeid = {?}', $type);
- }
- return $joins;
- }
-
/** NAMETOKENS
*/
private $name_tokens = array();
/** EDUCATION
*/
- const GRADE_ING = 'Ing.';
- const GRADE_PHD = 'PhD';
- const GRADE_MST = 'M%';
+ const GRADE_ING = Profile::DEGREE_X;
+ const GRADE_PHD = Profile::DEGREE_D;
+ const GRADE_MST = Profile::DEGREE_M;
static public function isGrade($grade)
{
return ($grade !== 0) && ($grade == self::GRADE_ING || $grade == self::GRADE_PHD || $grade == self::GRADE_MST);
foreach ($this->pepe as $grade => $sub) {
if ($this->isGrade($grade)) {
$joins['pe' . $sub] = PlSqlJoin::left('profile_education', '$ME.eduid = pee.id AND $ME.pid = $PID');
- $joins['pede' . $sub] = PlSqlJoin::inner('profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid AND $ME.abbreviation LIKE {?}', $grade);
+ $joins['pede' . $sub] = PlSqlJoin::inner('profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid AND $ME.degree LIKE {?}', $grade);
} else {
$joins['pe' . $sub] = PlSqlJoin::left('profile_education', '$ME.pid = $PID');
$joins['pee' . $sub] = PlSqlJoin::inner('profile_education_enum', '$ME.id = pe' . $sub . '.eduid');
return $sub;
}
+ private $gpfm = array();
+ public function addGroupFormerMemberFilter()
+ {
+ $this->requireAccounts();
+ $sub = '_' . $this->option++;
+ $this->gpfm[] = $sub;
+ return $sub;
+ }
+
protected function groupJoins()
{
$joins = array();
$joins['gpm' . $sub] = PlSqlJoin::left('group_members', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
}
}
+ foreach ($this->gpfm as $sub) {
+ $joins['gpfm' . $sub] = PlSqlJoin::left('group_former_members', '$ME.uid = $UID');
+ }
+ return $joins;
+ }
+
+ /** NLS
+ */
+ private $nls = array();
+ public function addNewsLetterFilter($nlid)
+ {
+ $this->requireAccounts();
+ $sub = 'nl_' . $nlid;
+ $this->nls[$nlid] = $sub;
+ return $sub;
+ }
+
+ protected function newsLetterJoins()
+ {
+ $joins = array();
+ foreach ($this->nls as $key => $sub) {
+ $joins[$sub] = PlSqlJoin::left('newsletter_ins', '$ME.nlid = {?} AND $ME.uid = $UID', $key);
+ }
return $joins;
}
/** EMAILS
*/
- private $e = array();
+ private $ra = array();
+ /** Allows filtering by redirection.
+ * @param $email If null, enable a left join on the email redirection table
+ * (email_redirect_account); otherwise, perform a left join on users having
+ * that email as a redirection.
+ * @return Suffix to use to access the adequate table.
+ */
public function addEmailRedirectFilter($email = null)
{
$this->requireAccounts();
- return $this->register_optional($this->e, $email);
- }
-
- private $ve = array();
- public function addVirtualEmailFilter($email = null)
+ return $this->register_optional($this->ra, $email);
+ }
+
+ const ALIAS_BEST = 'bestalias';
+ const ALIAS_FORLIFE = 'forlife';
+ const ALIAS_AUXILIARY = 'alias_aux';
+ private $sa = array();
+ /** Allows filtering by source email.
+ * @param $email If null, enable a left join on the email source table
+ * (email_source_account); otherwise, perform a left join on users having
+ * that email as a source email.
+ * @return Suffix to use to access the adequate table.
+ */
+ public function addAliasFilter($email = null)
{
- $this->addAliasFilter(self::ALIAS_FORLIFE);
- return $this->register_optional($this->ve, $email);
+ $this->requireAccounts();
+ return $this->register_optional($this->sa, $email);
}
- const ALIAS_BEST = 'bestalias';
- const ALIAS_FORLIFE = 'forlife';
- private $al = array();
- public function addAliasFilter($alias = null)
+ private $with_rf = false;
+ /** Allows filtering by active redirection.
+ * @return Suffix to use to access the adequate table.
+ */
+ public function addActiveEmailRedirectFilter($email = null)
{
$this->requireAccounts();
- return $this->register_optional($this->al, $alias);
+ $this->with_rf = true;
}
protected function emailJoins()
{
global $globals;
$joins = array();
- foreach ($this->e as $sub=>$key) {
- if (is_null($key)) {
- $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\'');
+ foreach ($this->ra as $sub => $redirections) {
+ if (is_null($redirections)) {
+ $joins['ra' . $sub] = PlSqlJoin::left('email_redirect_account', '$ME.uid = $UID AND $ME.type != \'imap\'');
} else {
- if (!is_array($key)) {
- $key = array($key);
+ if (!is_array($redirections)) {
+ $key = array($redirections);
}
- $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\'
- AND $ME.email IN {?}', $key);
+ $joins['ra' . $sub] = PlSqlJoin::left('email_redirect_account', '$ME.uid = $UID AND $ME.type != \'imap\'
+ AND $ME.redirect IN {?}', $redirections);
}
}
- foreach ($this->al as $sub=>$key) {
- if (is_null($key)) {
- $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type IN (\'alias\', \'a_vie\')');
- } else if ($key == self::ALIAS_BEST) {
- $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type IN (\'alias\', \'a_vie\') AND FIND_IN_SET(\'bestalias\', $ME.flags)');
- } else if ($key == self::ALIAS_FORLIFE) {
- $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type = \'a_vie\'');
+ foreach ($this->sa as $sub => $emails) {
+ if (is_null($emails)) {
+ $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID');
+ } else if ($sub == self::ALIAS_BEST) {
+ $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND FIND_IN_SET(\'bestalias\', $ME.flags)');
+ } else if ($sub == self::ALIAS_FORLIFE) {
+ $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'forlife\'');
+ } else if ($sub == self::ALIAS_AUXILIARY) {
+ $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'alias_aux\'');
} else {
- if (!is_array($key)) {
- $key = array($key);
+ if (!is_array($emails)) {
+ $key = array($emails);
}
- $joins['al' . $sub] = PlSqlJoin::left('aliases', '$ME.uid = $UID AND $ME.type IN (\'alias\', \'a_vie\')
- AND $ME.alias IN {?}', $key);
+ $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND $ME.email IN {?}', $emails);
}
}
- foreach ($this->ve as $sub=>$key) {
- if (is_null($key)) {
- $joins['v' . $sub] = PlSqlJoin::left('virtual', '$ME.type = \'user\'');
- } else {
- if (!is_array($key)) {
- $key = array($key);
- }
- $joins['v' . $sub] = PlSqlJoin::left('virtual', '$ME.type = \'user\' AND $ME.alias IN {?}', $key);
- }
- $joins['vr' . $sub] = PlSqlJoin::left('virtual_redirect',
- '$ME.vid = v' . $sub . '.vid
- AND ($ME.redirect IN (CONCAT(al_forlife.alias, \'@\', {?}),
- CONCAT(al_forlife.alias, \'@\', {?}),
- a.email))',
- $globals->mail->domain, $globals->mail->domain2);
+ if ($this->with_rf) {
+ $joins['rf'] = PlSqlJoin::left('email_redirect_account', '$ME.uid = $UID AND $ME.type != \'imap\' AND $ME.flags = \'active\'');;
}
return $joins;
}
/** ADDRESSES
*/
- private $with_pa = false;
- public function addAddressFilter()
+ private $types = array();
+ public function addAddressFilter($type)
{
$this->requireProfiles();
$this->with_pa = true;
- return 'pa';
- }
-
- private $with_pac = false;
- public function addAddressCountryFilter()
- {
- $this->requireProfiles();
- $this->addAddressFilter();
- $this->with_pac = true;
- return 'gc';
- }
- private $with_pal = false;
- public function addAddressLocalityFilter()
- {
- $this->requireProfiles();
- $this->addAddressFilter();
- $this->with_pal = true;
- return 'gl';
+ $sub = '_' . $this->option++;
+ $this->types[$type] = $sub;
+ return $sub;
}
protected function addressJoins()
{
$joins = array();
- if ($this->with_pa) {
- $joins['pa'] = PlSqlJoin::left('profile_addresses', '$ME.pid = $PID');
- }
- if ($this->with_pac) {
- $joins['gc'] = PlSqlJoin::left('geoloc_countries', '$ME.iso_3166_1_a2 = pa.countryID');
- }
- if ($this->with_pal) {
- $joins['gl'] = PlSqlJoin::left('geoloc_localities', '$ME.id = pa.localityID');
+ foreach ($this->types as $type => $sub) {
+ $joins['pa' . $sub] = PlSqlJoin::inner('profile_addresses', '$ME.pid = $PID');
+ $joins['pac' . $sub] = PlSqlJoin::inner('profile_addresses_components',
+ '$ME.pid = pa' . $sub . '.pid AND $ME.jobid = pa' . $sub . '.jobid AND $ME.groupid = pa' . $sub . '.groupid AND $ME.type = pa' . $sub . '.type AND $ME.id = pa' . $sub . '.id');
+ $joins['pace' . $sub] = PlSqlJoin::inner('profile_addresses_components_enum',
+ '$ME.id = pac' . $sub . '.component_id AND FIND_IN_SET({?}, $ME.types)', $type);
}
+
return $joins;
}
$this->requireProfiles();
$this->pc = true;
if ($type == UFC_Corps::CURRENT) {
- $pce['pcec'] = 'current_corpsid';
+ $this->pce['pcec'] = 'current_corpsid';
return 'pcec';
} else if ($type == UFC_Corps::ORIGIN) {
- $pce['pceo'] = 'original_corpsid';
+ $this->pce['pceo'] = 'original_corpsid';
return 'pceo';
}
}
return $joins;
}
+ /** DELTATEN
+ */
+ private $dts = array();
+ const DELTATEN = 1;
+ const DELTATEN_MESSAGE = 2;
+ // TODO: terms
+
+ public function addDeltaTenFilter($type)
+ {
+ $this->requireProfiles();
+ switch ($type) {
+ case self::DELTATEN:
+ $this->dts['pdt'] = 'profile_deltaten';
+ return 'pdt';
+ case self::DELTATEN_MESSAGE:
+ $this->dts['pdtm'] = 'profile_deltaten';
+ return 'pdtm';
+ default:
+ Platal::page()->killError("Undefined DeltaTen filter.");
+ }
+ }
+
+ protected function deltatenJoins()
+ {
+ $joins = array();
+ foreach ($this->dts as $sub => $tab) {
+ $joins[$sub] = PlSqlJoin::left($tab, '$ME.pid = $PID');
+ }
+ return $joins;
+ }
+
/** MENTORING
*/
public function addMentorFilter($type)
{
- $this->requireAccounts();
+ $this->requireProfiles();
switch($type) {
case self::MENTOR:
$this->pms['pm'] = 'profile_mentor';
return array();
}
}
+
+
+ /** PARTNER SHARING
+ */
+
+ // Lists partner shortnames in use, as a $partner_shortname => true map.
+ private $ppss = array();
+
+ /** Add a filter on user having settings for a given partner.
+ * @param $partner_id the ID of the partner
+ * @return the name of the table to use in joins (e.g ppss_$partner_id).
+ */
+ public function addPartnerSharingFilter($partner_id)
+ {
+ $this->requireProfiles();
+ $sub = "ppss_" . $partner_id;
+ $this->ppss[$sub] = $partner_id;
+ return $sub;
+ }
+
+ protected function partnerSharingJoins()
+ {
+ $joins = array();
+ foreach ($this->ppss as $sub => $partner_id) {
+ $joins[$sub] = PlSqlJoin::left('profile_partnersharing_settings', '$ME.pid = $PID AND $ME.partner_id = {?} AND $ME.sharing_level != \'none\'', $partner_id);
+ }
+ return $joins;
+ }
+
+ public function restrictVisibilityForPartner($partner_id)
+ {
+ $sub = $this->addPartnerSharingFilter($partner_id);
+ $this->visibility_field = $sub . '.sharing_level';
+ }
+
+ /** VISIBILITY
+ */
+ private $vlevels = array();
+ private $vfields = array();
+ public function addVisibilityAbsoluteFilter($level)
+ {
+ $sub = 'pvel_' . $level;
+ $this->vlevels[$level] = $sub;
+ return $sub;
+ }
+
+ public function addVisibilityFieldFilter($field)
+ {
+ $sub = 'pvef_' . self::getDBSuffix($field);
+ $this->vfields[$field] = $sub;
+ return $sub;
+ }
+
+ /** Since this method might perform inner joins on tables which have been
+ * joined previously (e.g when using addVisibilityFieldFilter), it has to
+ * come after the Joins() methods for those tables.
+ * This is due to the implementation logic for discovering joins and the
+ * ordering used by PHP introspection.
+ */
+ protected function visibilityJoins()
+ {
+ $joins = array();
+ foreach ($this->vlevels as $level => $sub) {
+ $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = {?}', $level);
+ }
+ foreach ($this->vfields as $field => $sub) {
+ $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = ' . $field);
+ }
+ return $joins;
+ }
+
}
// }}}
// {{{ class ProfileFilter
return $this->getProfiles($limit);
}
+ public function getIds($limit = null)
+ {
+ return $this->getPIDs();
+ }
+
public function filter(array $profiles, $limit = null)
{
return $this->filterProfiles($profiles, self::defaultLimit($limit));