{
public function buildCondition(PlFilter &$uf)
{
+ $uf->requireProfiles();
return '$PID IS NOT NULL';
}
}
// }}}
+// {{{ class UFC_AccountType
+/** Filters users who have one of the given account types
+ */
+class UFC_AccountType implements UserFilterCondition
+{
+ private $types;
+
+ public function __construct()
+ {
+ $this->types = pl_flatten(func_get_args());
+ }
+
+ public function buildCondition(PlFilter &$uf)
+ {
+ $uf->requireAccounts();
+ return XDB::format('a.type IN {?}', $this->types);
+ }
+}
+// }}}
+
+// {{{ class UFC_AccountPerm
+/** Filters users who have one of the given permissions
+ */
+class UFC_AccountPerm implements UserFilterCondition
+{
+ private $perms;
+
+ public function __construct()
+ {
+ $this->perms = pl_flatten(func_get_args());
+ }
+
+ public function buildCondition(PlFilter &$uf)
+ {
+ $uf->requirePerms();
+ $conds = array();
+ foreach ($this->perms as $perm) {
+ $conds[] = XDB::format('FIND_IN_SET({?}, IF(a.user_perms IS NULL, at.perms,
+ CONCAT(at.perms, \',\', a.user_perms)))',
+ $perm);
+ }
+ if (empty($conds)) {
+ return self::COND_TRUE;
+ } else {
+ return implode(' OR ', $conds);
+ }
+ }
+}
+// }}}
+
// {{{ class UFC_Hruid
/** Filters users based on their hruid
* @param $val Either an hruid, or a list of those
{
private $hruids;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->hruids = $val;
+ $this->hruids = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
- $ufc->requireAccounts();
+ $uf->requireAccounts();
return XDB::format('a.hruid IN {?}', $this->hruids);
}
}
{
private $hrpids;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->hrpids = $val;
+ $this->hrpids = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
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);
}
}
// }}}
if ($this->grade != UserFilter::DISPLAY) {
UserFilter::assertGrade($this->grade);
}
+ if ($this->grade == UserFilter::DISPLAY && $this->comparison != '=') {
+ // XXX: we might try to guess the grade from the first char of the promo and forbid only '<= 2004', but allow '<= X2004'
+ Platal::page()->killError("Il n'est pas possible d'appliquer la comparaison '" . $this->comparison . "' aux promotions sans spécifier de formation (X/M/D)");
+ }
}
public function buildCondition(PlFilter &$uf)
* @param type Parameter type (Xorg, AX, School)
* @param value School id value
*/
-class UFC_SchooldId implements UserFilterCondition
+class UFC_SchoolId implements UserFilterCondition
{
const AX = 'ax';
const Xorg = 'xorg';
{
private $val;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->val = $val;
+ $this->val = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
private $diploma;
- public function __construct($diploma)
+ public function __construct()
{
- if (! is_array($diploma)) {
- $diploma = array($diploma);
- }
- $this->diploma = $diploma;
+ $this->diploma = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
$sub = $uf->addEducationFilter();
- return XDB::format('pee' . $sub . '.degreeid IN {?}', $this->val);
+ return XDB::format('pe' . $sub . '.degreeid IN {?}', $this->diploma);
}
}
// }}}
{
private $val;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->val = $val;
+ $this->val = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
$sub = $uf->addEducationFilter();
- return XDB::format('pee' . $sub . '.fieldid IN {?}', $this->val);
+ return XDB::format('pe' . $sub . '.fieldid IN {?}', $this->val);
}
}
// }}}
*/
class UFC_Name implements UserFilterCondition
{
- const PREFIX = XDB::WILDCARD_PREFIX; // 0x001
- const SUFFIX = XDB::WILDCARD_SUFFIX; // 0x002
+ const EXACT = XDB::WILDCARD_EXACT; // 0x000
+ const PREFIX = XDB::WILDCARD_PREFIX; // 0x001
+ const SUFFIX = XDB::WILDCARD_SUFFIX; // 0x002
const CONTAINS = XDB::WILDCARD_CONTAINS; // 0x003
- const PARTICLE = 0x007; // self::CONTAINS | 0x004
+ const PARTICLE = 0x004;
const VARIANTS = 0x008;
private $type;
public function __construct($tokens, $flags = array(), $soundex = false, $exact = false)
{
- $this->tokens = $tokens;
+ if (is_array($tokens)) {
+ $this->tokens = $tokens;
+ } else {
+ $this->tokens = array($tokens);
+ }
if (is_array($flags)) {
$this->flags = $flags;
} else {
public function buildCondition(PlFilter &$uf)
{
- $sub = $uf->addNameTokensFilter(!($this->exact || $this->soundex));
$conds = array();
- if ($this->soundex) {
- $conds[] = XDB::format($sub . '.soundex IN {?}', $this->tokens);
- } else if ($this->exact) {
- $conds[] = XDB::format($sub . '.token IN {?}', $this->tokens);
- } else {
- $tokconds = array();
- foreach ($this->tokens as $token) {
- $tokconds[] = $sub . '.token ' . XDB::formatWildcards(XDB::WILDCARD_PREFIX, $token);
+ foreach ($this->tokens as $i => $token) {
+ $sub = $uf->addNameTokensFilter($token);
+ if ($this->soundex) {
+ $c = XDB::format($sub . '.soundex = {?}', soundex_fr($token));
+ } else if ($this->exact) {
+ $c = XDB::format($sub . '.token = {?}', $token);
+ } else {
+ $c = $sub . '.token ' . XDB::formatWildcards(XDB::WILDCARD_PREFIX, $token);
}
- $conds[] = implode(' OR ', $tokconds);
- }
-
- if ($this->flags != null) {
- $conds[] = XDB::format($sub . '.flags IN {?}', $this->flags);
+ if ($this->flags != null) {
+ $c .= XDB::format(' AND ' . $sub . '.flags IN {?}', $this->flags);
+ }
+ $conds[] = $c;
}
return implode(' AND ', $conds);
{
private $val;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->val = $val;
+ $this->val = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
// {{{ class UFC_Dead
/** Filters users based on death date
* @param $comparison Comparison operator
- * @param $date Date to which death date should be compared
+ * @param $date Date to which death date should be compared (DateTime object, string or timestamp)
*/
class UFC_Dead implements UserFilterCondition
{
public function __construct($comparison = null, $date = null)
{
$this->comparison = $comparison;
- $this->date = $date;
+ $this->date = make_datetime($date);
}
public function buildCondition(PlFilter &$uf)
$uf->requireProfiles();
$str = 'p.deathdate IS NOT NULL';
if (!is_null($this->comparison)) {
- $str .= ' AND p.deathdate ' . $this->comparison . ' ' . XDB::format('{?}', date('Y-m-d', $this->date));
+ $str .= ' AND p.deathdate ' . $this->comparison . ' ' . XDB::format('{?}', $this->date->format('Y-m-d'));
}
return $str;
}
{
$this->active = $active;
$this->comparison = $comparison;
- $this->date = $date;
+ $this->date = make_datetime($date);
}
public function buildCondition(PlFilter &$uf)
{
$uf->requireAccounts();
if ($this->active) {
- $date = 'a.uid IS NOT NULL AND a.state = \'active\'';
+ $date = '$UID IS NOT NULL AND a.state = \'active\'';
} else {
- $date = 'a.uid IS NOT NULL AND a.state != \'pending\'';
+ $date = '$UID IS NOT NULL AND a.state != \'pending\'';
}
if (!is_null($this->comparison)) {
- $date .= ' AND a.registration_date ' . $this->comparison . ' ' . XDB::format('{?}', date('Y-m-d', $this->date));
+ $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'));
}
return $date;
}
public function buildCondition(PlFilter &$uf)
{
+ // Groups have AX visibility.
+ if ($uf->getVisibilityLevel() == ProfileVisibility::VIS_PUBLIC) {
+ return self::COND_TRUE;
+ }
$sub = $uf->addGroupFilter($this->group);
$where = 'gpm' . $sub . '.perms IS NOT NULL';
if ($this->anim) {
{
private $val;
- public function __construct($val)
+ public function __construct()
{
- if (!is_array($val)) {
- $val = array($val);
- }
- $this->val = $val;
+ $this->val = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
+ // Binets are private.
+ if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) {
+ return self::CONF_TRUE;
+ }
$sub = $uf->addBinetsFilter();
return XDB::format($sub . '.binet_id IN {?}', $this->val);
}
{
private $section;
- public function __construct($section)
+ public function __construct()
{
- $this->section = $section;
+ $this->section = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
+ // Sections are private.
+ if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) {
+ return self::CONF_TRUE;
+ }
$uf->requireProfiles();
- return 'p.section = ' . XDB::format('{?}', $this->section);
+ return XDB::format('p.section IN {?}', $this->section);
}
}
// }}}
private $emails;
public function __construct()
{
- $this->emails = func_get_args();
+ $this->emails = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
$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) {
}
}
if (count($types)) {
- $conds[] = XDB::foramt($sub . '.type IN {?}', $types);
+ $conds[] = XDB::format($sub . '.type IN {?}', $types);
}
if ($this->flags != self::FLAG_ANY) {
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);
}
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:
*/
$sub = $uf->addCorpsFilter($this->type);
$cond = $sub . '.abbreviation = ' . $corps;
+ $cond .= ' AND ' . $uf->getVisibilityCondition($sub . '.corps_pub');
return $cond;
}
}
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;
}
}
public function buildCondition(PlFilter &$uf)
{
$sub = $uf->addJobCompanyFilter();
- $cond = $sub . '.' . $this->type . ' = ' . XDB::format('{?}', $this->value);
+ $cond = $sub . '.' . $this->type . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value);
+ $jsub = $uf->addJobFilter();
+ $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub');
return $cond;
}
}
// }}}
-// {{{ class UFC_Job_Sectorization
-/** Filters users based on the ((sub)sub)sector they work in
- * @param $val The ID of the sector, or an array of such IDs
- * @param $type The kind of search (subsubsector/subsector/sector)
+// {{{ 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_Sectorization implements UserFilterCondition
+class UFC_Job_Terms implements UserFilterCondition
{
private $val;
- private $type;
- public function __construct($val, $type = UserFilter::JOB_SECTOR)
+ public function __construct($val)
{
- self::assertType($type);
if (!is_array($val)) {
$val = array($val);
}
$this->val = $val;
- $this->type = $type;
- }
-
- private static function assertType($type)
- {
- if ($type != UserFilter::JOB_SECTOR && $type != UserFilter::JOB_SUBSECTOR && $type != UserFilter::JOB_SUBSUBSECTOR) {
- Platal::page()->killError("Type de secteur non valide.");
- }
}
public function buildCondition(PlFilter &$uf)
{
- $sub = $uf->addJobSectorizationFilter($this->type);
- return $sub . '.id = ' . XDB::format('{?}', $this->val);
+ $sub = $uf->addJobTermsFilter(count($this->val));
+ $conditions = array();
+ foreach ($this->val as $i => $jtid) {
+ $conditions[] = $sub[$i] . '.jtid_1 = ' . XDB::escape($jtid);
+ }
+ $jsub = $uf->addJobFilter();
+ $conditions[] = $uf->getVisibilityCondition($jsub . '.pub');
+ return implode(' AND ', $conditions);
}
}
// }}}
// {{{ class UFC_Job_Description
/** Filters users based on their job description
* @param $description The text being searched for
- * @param $fields The fields to search for (user-defined, ((sub|)sub|)sector)
+ * @param $fields The fields to search for (CV, user-defined)
*/
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 self::CONF_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);
}
- if ($this->fields & UserFilter::JOB_SECTOR) {
- $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SECTOR);
- $conds[] = $sub . '.name ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
- }
- if ($this->fields & UserFilter::JOB_SUBSECTOR) {
- $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSECTOR);
- $conds[] = $sub . '.name ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
- }
- if ($this->fields & UserFilter::JOB_SUBSUBSECTOR) {
- $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSUBSECTOR);
- $conds[] = $sub . '.name ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
- $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_ALTERNATES);
- $conds[] = $sub . '.name ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
- }
return implode(' OR ', $conds);
}
}
{
$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 . '.network_type = ' . XDB::format('{?}', $this->type);
+ $conds[] = $sub . '.nwid = ' . XDB::format('{?}', $this->type);
}
return implode(' AND ', $conds);
}
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);
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);
}
// }}}
+// {{{ class UFC_Photo
+/** Filters profiles with photo
+ */
+class UFC_Photo implements UserFilterCondition
+{
+ public function buildCondition(PlFilter &$uf)
+ {
+ $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
{
private $country;
- public function __construct($country)
+ public function __construct()
{
- $this->country = $country;
+ $this->country = pl_flatten(func_get_args());
}
public function buildCondition(PlFilter &$uf)
{
$sub = $uf->addMentorFilter(UserFilter::MENTOR_COUNTRY);
- return $sub . '.country = ' . XDB::format('{?}', $this->country);
+ return $sub . '.country IN ' . XDB::format('{?}', $this->country);
}
}
// }}}
-// {{{ class UFC_Mentor_Sectorization
-/** Filters users based on mentoring (sub|)sector
- * @param $sector ID of (sub)sector
- * @param $type Whether we are looking for a sector or a subsector
+// {{{ 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_Sectorization implements UserFilterCondition
+class UFC_Mentor_Terms implements UserFilterCondition
{
- const SECTOR = 1;
- const SUBSECTOR = 2;
- private $sector;
- private $type;
+ private $val;
- public function __construct($sector, $type = self::SECTOR)
+ public function __construct($val)
{
- $this->sector = $sector;
- $this->type = $type;
+ $this->val = $val;
}
public function buildCondition(PlFilter &$uf)
{
- $sub = $uf->addMentorFilter(UserFilter::MENTOR_SECTOR);
- if ($this->type == self::SECTOR) {
- $field = 'sectorid';
- } else {
- $field = 'subsectorid';
- }
- return $sub . '.' . $field . ' = ' . XDB::format('{?}', $this->sector);
+ $sub = $uf->addMentorFilter(UserFilter::MENTOR_TERM);
+ return $sub . '.jtid_1 = ' . XDB::escape($this->val);
}
}
// }}}
* 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;
* @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;
{
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) {
// }}}
// {{{ class UFO_Score
-class UFO_Score extends UserFilterOrder
+class UFO_Score extends PlFilterOrder
{
protected function getSortTokens(PlFilter &$uf)
{
- $sub = $uf->addNameTokensFilter();
- return 'SUM(' . $sub . '.score)';
+ $toks = $uf->getNameTokens();
+ $scores = array();
+
+ // If there weren't any sort tokens, we shouldn't sort by score, sort by NULL instead
+ if (count($toks) == 0) {
+ return 'NULL';
+ }
+
+ foreach ($toks as $sub => $token) {
+ $scores[] = XDB::format('SUM(' . $sub . '.score + IF (' . $sub . '.token = {?}, 5, 0) )', $token);
+ }
+ return implode(' + ', $scores);
}
}
// }}}
// {{{ class UFO_Registration
/** Sorts users based on registration date
*/
-class UFO_Registration extends UserFilterOrder
+class UFO_Registration extends PlFilterOrder
{
protected function getSortTokens(PlFilter &$uf)
{
+ $uf->requireAccounts();
return 'a.registration_date';
}
}
// {{{ 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)
{
+ $uf->requireProfiles();
return 'p.next_birthday';
}
}
// {{{ 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)
{
+ $uf->requireProfiles();
return 'p.last_change';
}
}
// {{{ class UFO_Death
/** Sorts users based on death date
*/
-class UFO_Death extends UserFilterOrder
+class UFO_Death extends PlFilterOrder
{
protected function getSortTokens(PlFilter &$uf)
{
+ $uf->requireProfiles();
return 'p.deathdate';
}
}
// }}}
+// {{{ class UFO_Uid
+/** Sorts users based on their uid
+ */
+class UFO_Uid extends PlFilterOrder
+{
+ protected function getSortTokens(PlFilter &$uf)
+ {
+ $uf->requireAccounts();
+ return '$UID';
+ }
+}
+// }}}
+
+// {{{ class UFO_Hruid
+/** Sorts users based on their hruid
+ */
+class UFO_Hruid extends PlFilterOrder
+{
+ protected function getSortTokens(PlFilter &$uf)
+ {
+ $uf->requireAccounts();
+ return 'a.hruid';
+ }
+}
+// }}}
+
+// {{{ class UFO_Pid
+/** Sorts users based on their pid
+ */
+class UFO_Pid extends PlFilterOrder
+{
+ protected function getSortTokens(PlFilter &$uf)
+ {
+ $uf->requireProfiles();
+ return '$PID';
+ }
+}
+// }}}
+
+// {{{ class UFO_Hrpid
+/** Sorts users based on their hrpid
+ */
+class UFO_Hrpid extends PlFilterOrder
+{
+ protected function getSortTokens(PlFilter &$uf)
+ {
+ $uf->requireProfiles();
+ return 'p.hrpid';
+ }
+}
+// }}}
+
/***********************************
*********************************
* 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:
private $root;
private $sort = array();
+ private $grouper = null;
private $query = null;
private $orderby = null;
- private $lastcount = null;
+ // Store the current 'search' visibility.
+ private $profile_visibility = null;
+
+ private $lastusercount = null;
+ private $lastprofilecount = null;
public function __construct($cond = null, $sort = null)
{
}
}
if (!is_null($sort)) {
- if ($sort instanceof UserFilterOrder) {
+ if ($sort instanceof PlFilterOrder) {
$this->addSort($sort);
} else if (is_array($sort)) {
foreach ($sort as $s) {
}
}
}
+
+ // 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()
{
+ // The root condition is built first because some orders need info
+ // available only once all UFC have set their conditions (UFO_Score)
+ if (is_null($this->query)) {
+ $where = $this->root->buildCondition($this);
+ $where = str_replace(array_keys($this->joinMetas),
+ $this->joinMetas,
+ $where);
+ }
if (is_null($this->orderby)) {
$orders = array();
foreach ($this->sort as $sort) {
} else {
$this->orderby = 'ORDER BY ' . implode(', ', $orders);
}
+ $this->orderby = str_replace(array_keys($this->joinMetas),
+ $this->joinMetas,
+ $this->orderby);
}
if (is_null($this->query)) {
- $where = $this->root->buildCondition($this);
- if ($this->with_forced_sn) {
- $this->requireProfiles();
- $from = 'search_name AS sn';
- } else if ($this->with_accounts) {
+ if ($this->with_accounts) {
$from = 'accounts AS a';
} else {
$this->requireProfiles();
}
}
+ 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::rawFetchAllRow('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::rawFetchAllRow('SELECT ' . $token . ', COUNT(p.pid)
+ ' . $this->query . '
+ GROUP BY ' . $token,
+ 0);
+ return $groups;
+ }
+
private function getUIDList($uids = null, PlLimit &$limit)
{
$this->requireAccounts();
$this->buildQuery();
$lim = $limit->getSql();
$cond = '';
- if (!is_null($uids)) {
+ if (!empty($uids)) {
$cond = XDB::format(' AND a.uid IN {?}', $uids);
}
- $fetched = XDB::fetchColumn('SELECT SQL_CALC_FOUND_ROWS a.uid
- ' . $this->query . $cond . '
- GROUP BY a.uid
- ' . $this->orderby . '
- ' . $lim);
- $this->lastcount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
+ $fetched = XDB::rawFetchColumn('SELECT SQL_CALC_FOUND_ROWS a.uid
+ ' . $this->query . $cond . '
+ GROUP BY a.uid
+ ' . $this->orderby . '
+ ' . $lim);
+ $this->lastusercount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
return $fetched;
}
if (!is_null($pids)) {
$cond = XDB::format(' AND p.pid IN {?}', $pids);
}
- $fetched = XDB::fetchColumn('SELECT SQL_CALC_FOUND_ROWS p.pid
- ' . $this->query . $cond . '
- GROUP BY p.pid
- ' . $this->orderby . '
- ' . $lim);
- $this->lastcount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
+ $fetched = XDB::rawFetchColumn('SELECT SQL_CALC_FOUND_ROWS p.pid
+ ' . $this->query . $cond . '
+ GROUP BY p.pid
+ ' . $this->orderby . '
+ ' . $lim);
+ $this->lastprofilecount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
return $fetched;
}
{
$this->requireAccounts();
$this->buildQuery();
- $count = (int)XDB::fetchOneCell('SELECT COUNT(*)
- ' . $this->query . XDB::format(' AND a.uid = {?}', $user->id()));
+ $count = (int)XDB::rawFetchOneCell('SELECT COUNT(*)
+ ' . $this->query
+ . XDB::format(' AND a.uid = {?}', $user->id()));
return $count == 1;
}
{
$this->requireProfiles();
$this->buildQuery();
- $count = (int)XDB::fetchOneCell('SELECT COUNT(*)
- ' . $this->query . XDB::format(' AND p.pid = {?}', $profile->id()));
+ $count = (int)XDB::rawFetchOneCell('SELECT COUNT(*)
+ ' . $this->query
+ . XDB::format(' AND p.pid = {?}', $profile->id()));
return $count == 1;
}
public function getUID($pos = 0)
{
- $uids =$this->getUIDList(null, new PlFilter(1, $pos));
+ $uids =$this->getUIDList(null, new PlLimit(1, $pos));
if (count($uids) == 0) {
return null;
} else {
public function getPID($pos = 0)
{
- $pids =$this->getPIDList(null, new PlFilter(1, $pos));
+ $pids =$this->getPIDList(null, new PlLimit(1, $pos));
if (count($pids) == 0) {
return null;
} else {
return $this->getUsers($limit);
}
+
public function getTotalCount()
{
- if (is_null($this->lastcount)) {
+ return $this->getTotalUserCount();
+ }
+
+ public function getTotalUserCount()
+ {
+ if (is_null($this->lastusercount)) {
+ $this->requireAccounts();
$this->buildQuery();
- if ($this->with_accounts) {
- $field = 'a.uid';
- } else {
- $field = 'p.pid';
- }
- return (int)XDB::fetchOneCell('SELECT COUNT(DISTINCT ' . $field . ')
+ return (int)XDB::rawFetchOneCell('SELECT COUNT(DISTINCT a.uid)
' . $this->query);
} else {
- return $this->lastcount;
+ return $this->lastusercount;
+ }
+ }
+
+ public function getTotalProfileCount()
+ {
+ if (is_null($this->lastprofilecount)) {
+ $this->requireProfiles();
+ $this->buildQuery();
+ return (int)XDB::rawFetchOneCell('SELECT COUNT(DISTINCT p.pid)
+ ' . $this->query);
+ } else {
+ return $this->lastprofilecount;
}
}
public function addSort(PlFilterOrder &$sort)
{
+ if (count($this->sort) == 0 && $sort instanceof PlFilterGroupableOrder)
+ {
+ $this->grouper = $sort;
+ }
$this->sort[] = $sort;
$this->orderby = null;
}
*/
private $with_profiles = false;
private $with_accounts = false;
- private $with_forced_sn = false;
public function requireAccounts()
{
$this->with_accounts = true;
}
+ public function accountsRequired()
+ {
+ return $this->with_accounts;
+ }
+
public function requireProfiles()
{
$this->with_profiles = true;
}
- /** Forces the "FROM" to use search_name instead of accounts or profiles */
- public function forceSearchName()
+ public function profilesRequired()
{
- $this->with_forced_sn = true;
+ return $this->with_profiles;
}
protected function accountJoins()
{
$joins = array();
- /** Quick search is much more efficient with sn first and PID second */
- if ($this->with_forced_sn) {
- $joins['p'] = PlSqlJoin::left('profiles', '$PID = sn.pid');
- if ($this->with_accounts) {
- $joins['ap'] = PlSqlJoin::left('account_profiles', '$ME.pid = $PID');
- $joins['a'] = PlSqlJoin::left('accounts', '$UID = ap.uid');
- }
- } else if ($this->with_profiles && $this->with_accounts) {
+ if ($this->with_profiles && $this->with_accounts) {
$joins['ap'] = PlSqlJoin::left('account_profiles', '$ME.uid = $UID AND FIND_IN_SET(\'owner\', ap.perms)');
$joins['p'] = PlSqlJoin::left('profiles', '$PID = ap.pid');
}
return $joins;
}
+ /** PERMISSIONS
+ */
+ private $at = false;
+ public function requirePerms()
+ {
+ $this->requireAccounts();
+ $this->at = true;
+ return 'at';
+ }
+
+ protected function permJoins()
+ {
+ if ($this->at) {
+ return array('at' => PlSqlJoin::left('account_types', '$ME.type = a.type'));
+ } else {
+ return array();
+ }
+ }
+
/** DISPLAY
*/
const DISPLAY = 'display';
/** NAMETOKENS
*/
- private $with_sn = false;
- // Set $doingQuickSearch to true if you wish to optimize the query
- public function addNameTokensFilter($doingQuickSearch = false)
+ private $name_tokens = array();
+ private $nb_tokens = 0;
+
+ public function addNameTokensFilter($token)
{
$this->requireProfiles();
- $this->with_forced_sn = ($this->with_forced_sn || $doingQuickSearch);
- $this->with_sn = true;
- return 'sn';
+ $sub = 'sn' . (1 + $this->nb_tokens);
+ $this->nb_tokens++;
+ $this->name_tokens[$sub] = $token;
+ return $sub;
}
protected function nameTokensJoins()
{
/* We don't return joins, since with_sn forces the SELECT to run on search_name first */
- if ($this->with_sn && !$this->with_forced_sn) {
- return array(
- 'sn' => PlSqlJoin::left('search_name', '$ME.pid = $PID')
- );
- } else {
- return array();
+ $joins = array();
+ foreach ($this->name_tokens as $sub => $token) {
+ $joins[$sub] = PlSqlJoin::left('search_name', '$ME.pid = $PID');
}
+ return $joins;
+ }
+
+ public function getNameTokens()
+ {
+ return $this->name_tokens;
}
/** NATIONALITY
const GRADE_MST = 'M%';
static public function isGrade($grade)
{
- return $grade == self::GRADE_ING || $grade == self::GRADE_PHD || $grade == self::GRADE_MST;
+ return ($grade !== 0) && ($grade == self::GRADE_ING || $grade == self::GRADE_PHD || $grade == self::GRADE_MST);
}
static public function assertGrade($grade)
if (!is_array($key)) {
$key = array($key);
}
- $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\'
- AND $ME.email IN {?}' . $key);
+ $joins['e' . $sub] = PlSqlJoin::left('emails', '$ME.uid = $UID AND $ME.flags != \'filter\'
+ AND $ME.email IN {?}', $key);
}
}
foreach ($this->al as $sub=>$key) {
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);
}
}
/** JOBS
*/
- const JOB_SECTOR = 0x0001;
- const JOB_SUBSECTOR = 0x0002;
- const JOB_SUBSUBSECTOR = 0x0004;
- const JOB_ALTERNATES = 0x0008;
- const JOB_USERDEFINED = 0x0010;
- const JOB_CV = 0x0020;
-
- const JOB_SECTORIZATION = 0x000F;
- const JOB_ANY = 0x003F;
+ const JOB_USERDEFINED = 0x0001;
+ const JOB_CV = 0x0002;
+ const JOB_ANY = 0x0003;
/** Joins :
* pj => profile_job
* pje => profile_job_enum
- * pjse => profile_job_sector_enum
- * pjsse => profile_job_subsector_enum
- * pjssse => profile_job_subsubsector_enum
- * pja => profile_job_alternates
+ * pjt => profile_job_terms
*/
- private $with_pj = false;
+ private $with_pj = false;
private $with_pje = false;
- private $with_pjse = false;
- private $with_pjsse = false;
- private $with_pjssse = false;
- private $with_pja = false;
+ private $with_pjt = 0;
public function addJobFilter()
{
return 'pje';
}
- public function addJobSectorizationFilter($type)
+ /**
+ * 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).
+ */
+ public function addJobTermsFilter($nb = 1)
{
- $this->addJobFilter();
- if ($type == self::JOB_SECTOR) {
- $this->with_pjse = true;
- return 'pjse';
- } else if ($type == self::JOB_SUBSECTOR) {
- $this->with_pjsse = true;
- return 'pjsse';
- } else if ($type == self::JOB_SUBSUBSECTOR) {
- $this->with_pjssse = true;
- return 'pjssse';
- } else if ($type == self::JOB_ALTERNATES) {
- $this->with_pja = true;
- return 'pja';
+ $this->with_pjt = $nb;
+ $jobtermstable = array();
+ for ($i = 1; $i <= $nb; ++$i) {
+ $jobtermstable[] = 'pjtr_'.$i;
}
+ return $jobtermstable;
}
protected function jobJoins()
if ($this->with_pje) {
$joins['pje'] = PlSqlJoin::left('profile_job_enum', '$ME.id = pj.jobid');
}
- if ($this->with_pjse) {
- $joins['pjse'] = PlSqlJoin::left('profile_job_sector_enum', '$ME.id = pj.sectorid');
- }
- if ($this->with_pjsse) {
- $joins['pjsse'] = PlSqlJoin::left('profile_job_subsector_enum', '$ME.id = pj.subsectorid');
- }
- if ($this->with_pjssse) {
- $joins['pjssse'] = PlSqlJoin::left('profile_job_subsubsector_enum', '$ME.id = pj.subsubsectorid');
- }
- 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;
}
*/
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_TERM = 4;
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';
case self::MENTOR_COUNTRY:
$this->pms['pmc'] = 'profile_mentor_country';
return 'pmc';
- 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.");
}
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;
}
}
+ /** PHOTOS
+ */
+ private $with_photo;
+ public function addPhotoFilter()
+ {
+ $this->requireProfiles();
+ $this->with_photo = true;
+ return 'photo';
+ }
+
+ protected function photoJoins()
+ {
+ if ($this->with_photo) {
+ return array('photo' => PlSqlJoin::left('profile_photos', '$ME.pid = $PID'));
+ } else {
+ return array();
+ }
+ }
+
+
/** MARKETING
*/
private $with_rm;
{
return $this->getProfiles($limit);
}
+
+ public function filter(array $profiles, $limit = null)
+ {
+ return $this->filterProfiles($profiles, self::defaultLimit($limit));
+ }
+
+ public function getTotalCount()
+ {
+ return $this->getTotalProfileCount();
+ }
+
+ public function getGroups()
+ {
+ return $this->getPIDGroups();
+ }
}
// }}}