interface UserFilterCondition
{
+ const COND_TRUE = 'TRUE';
+ const COND_FALSE = 'FALSE';
+
/** Check that the given user matches the rule.
*/
public function buildCondition(UserFilter &$uf);
{
protected $child;
+ public function __construct($child = null)
+ {
+ if (!is_null($child) && ($child instanceof UserFilterCondition)) {
+ $this->setChild($child);
+ }
+ }
+
public function setChild(UserFilterCondition &$cond)
{
$this->child =& $cond;
{
protected $children = array();
+ public function __construct()
+ {
+ $children = func_get_args();
+ foreach ($children as &$child) {
+ if (!is_null($child) && ($child instanceof UserFilterCondition)) {
+ $this->addChild($child);
+ }
+ }
+ }
+
public function addChild(UserFilterCondition &$cond)
{
$this->children[] =& $cond;
}
+
+ protected function catConds(array $cond, $op, $fallback)
+ {
+ if (count($cond) == 0) {
+ return $fallback;
+ } else if (count($cond) == 1) {
+ return $cond[0];
+ } else {
+ return '(' . implode(') ' . $op . ' (', $cond) . ')';
+ }
+ }
}
class UFC_True implements UserFilterCondition
{
public function buildCondition(UserFilter &$uf)
{
- return 'TRUE';
+ return self::COND_TRUE;
}
}
{
public function buildCondition(UserFilter &$uf)
{
- return 'FALSE';
+ return self::COND_FALSE;
}
}
{
public function buildCondition(UserFilter &$uf)
{
- return 'NOT (' . $this->child->buildCondition($uf) . ')';
+ $val = $this->child->buildCondition($uf);
+ if ($val == self::COND_TRUE) {
+ return self::COND_FALSE;
+ } else if ($val == self::COND_FALSE) {
+ return self::COND_TRUE;
+ } else {
+ return 'NOT (' . $val . ')';
+ }
}
}
public function buildCondition(UserFilter &$uf)
{
if (empty($this->children)) {
- return 'FALSE';
+ return self::COND_FALSE;
} else {
+ $true = self::COND_FALSE;
$conds = array();
foreach ($this->children as &$child) {
- $conds[] = $child->buildCondition($uf);
+ $val = $child->buildCondition($uf);
+ if ($val == self::COND_TRUE) {
+ $true = self::COND_TRUE;
+ } else if ($val == self::COND_FALSE) {
+ return self::COND_FALSE;
+ } else {
+ $conds[] = $val;
+ }
}
- return '(' . implode (') AND (', $conds) . ')';
+ return $this->catConds($conds, 'AND', $true);
}
}
}
public function buildCondition(UserFilter &$uf)
{
if (empty($this->children)) {
- return 'TRUE';
+ return self::COND_TRUE;
} else {
+ $true = self::COND_TRUE;
$conds = array();
foreach ($this->children as &$child) {
- $conds[] = $child->buildCondition($uf);
+ $val = $child->buildCondition($uf);
+ if ($val == self::COND_TRUE) {
+ return self::COND_TRUE;
+ } else if ($val == self::COND_FALSE) {
+ $true = self::COND_FALSE;
+ } else {
+ $conds[] = $val;
+ }
}
- return '(' . implode (') OR (', $conds) . ')';
+ return $this->catConds($conds, 'OR', $true);
}
}
}
}
}
+class UFC_Dead implements UserFilterCondition
+{
+ private $dead;
+ public function __construct($dead)
+ {
+ $this->dead = $dead;
+ }
+
+ public function buildCondition(UserFilter &$uf)
+ {
+ if ($this->dead) {
+ return 'p.deathdate IS NOT NULL';
+ } else {
+ return 'p.deathdate IS NULL';
+ }
+ }
+}
+
+class UFC_Registered implements UserFilterCondition
+{
+ private $active;
+ public function __construct($active = false)
+ {
+ $this->only_active = $active;
+ }
+
+ public function buildCondition(UserFilter &$uf)
+ {
+ if ($this->active) {
+ return 'a.uid IS NOT NULL AND a.state = \'active\'';
+ } else {
+ return 'a.uid IS NOT NULL AND a.state != \'pending\'';
+ }
+ }
+}
+
+class UFC_Sex implements UserFilterCondition
+{
+ private $sex;
+ public function __construct($sex)
+ {
+ $this->sex = $sex;
+ }
+
+ public function buildCondition(UserFilter &$uf)
+ {
+ if ($this->sex != User::GENDER_MALE && $this->sex != User::GENDER_FEMALE) {
+ return self::COND_FALSE;
+ } else {
+ return XDB::format('p.sex = {?}', $this->sex);
+ }
+ }
+}
+
+class UFC_Group implements UserFilterCondition
+{
+ private $group;
+ private $admin;
+ public function __construct($group, $admin = false)
+ {
+ $this->group = $group;
+ $this->admin = $admin;
+ }
+
+ public function buildCondition(UserFilter &$uf)
+ {
+ $sub = $uf->addGroupFilter($this->group);
+ $where = 'gpm' . $sub . '.perms IS NOT NULL';
+ if ($this->admin) {
+ $where .= ' AND gpm' . $sub . '.perms = \'admin\'';
+ }
+ return $where;
+ }
+}
+
class UserFilter
{
private $root;
private $query = null;
+ public function __construct($cond = null)
+ {
+ if (!is_null($cond)) {
+ if ($cond instanceof UserFilterCondition) {
+ $this->setCondition($cond);
+ }
+ }
+ }
+
private function buildQuery()
{
if (is_null($this->query)) {
}
$str .= $table . ' AS ' . $key;
if (isset($infos[2])) {
- $str .= ' ON (' . str_replace(array('$ME', '$PID'), array($key, 'p.pid'), $infos[2]) . ')';
+ $str .= ' ON (' . str_replace(array('$ME', '$PID', '$UID'), array($key, 'p.pid', 'a.uid'), $infos[2]) . ')';
}
$str .= "\n";
}
private function buildJoins()
{
- $joins = $this->educationJoins() + $this->nameJoins();
+ $joins = $this->educationJoins() + $this->nameJoins() + $this->groupJoins();
return $this->formatJoin($joins);
}
*/
public function filter(array $users)
{
+ $this->buildQuery();
+ $table = array();
+ $uids = array();
+ foreach ($users as $user) {
+ $uids[] = $user->id();
+ $table[$user->id()] = $user;
+ }
+ $fetched = XDB::fetchColumn('SELECT a.uid
+ ' . $this->query . ' AND a.uid IN (' . implode(', ', $uids) . ')
+ GROUP BY a.uid');
$output = array();
- foreach ($users as &$user) {
- if ($this->checkUser($user)) {
- $output[] = $user;
- }
+ foreach ($fetched as $uid) {
+ $output[] = $table[$uid];
}
return $output;
}
+ public function getUIDs()
+ {
+ $this->buildQuery();
+ return XDB::fetchColumn('SELECT a.uid
+ ' . $this->query . '
+ GROUP BY a.uid');
+ }
+
+ public function getUsers()
+ {
+ return User::getBuildUsersWithUIDs($this->getUIDs());
+ }
+
public function setCondition(UserFilterCondition &$cond)
{
$this->root =& $cond;
static public function getLegacy($promo_min, $promo_max)
{
- $min = null;
if ($promo_min != 0) {
$min = new UFC_Promo('>=', self::GRADE_ING, intval($promo_min));
+ } else {
+ $min = new UFC_True();
}
- $max = null;
if ($promo_max != 0) {
$max = new UFC_Promo('<=', self::GRADE_ING, intval($promo_max));
- }
- $uf = new UserFilter();
- if (is_null($max) && is_null($min)) {
- $uf->setCondition(new UFC_True());
- } else if (is_null($max)) {
- $uf->setCondition($min);
- } else if (is_null($min)) {
- $uf->setCondition($max);
} else {
- $cond = new UFC_And();
- $cond->addChild($min);
- $cond->addChild($max);
- $uf->setCondition($cond);
+ $max = new UFC_True();
}
- return $uf;
+ return new UserFilter(new UFC_And($min, $max));
}
}
return $joins;
}
+
+
+ /** GROUPS
+ */
+ private $gpm = array();
+ private $gpm_o = 0;
+ public function addGroupFilter($group = null)
+ {
+ if (!is_null($group)) {
+ if (ctype_digit($group)) {
+ $index = $sub = $group;
+ } else {
+ $index = $group;
+ $sub = preg_replace('/[^a-z0-9]/i', '', $group);
+ }
+ } else {
+ $sub = 'group_' . $this->gpm_o++;
+ $index = null;
+ }
+ $sub = '_' . $sub;
+ $this->gpm[$sub] = $index;
+ return $sub;
+ }
+
+ private function groupJoins()
+ {
+ $joins = array();
+ foreach ($this->gpm as $sub => $key) {
+ if (is_null($key)) {
+ $joins['gpa' . $sub] = array('inner', 'groupex.asso');
+ $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
+ } else if (ctype_digit($key)) {
+ $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = ' . $key);
+ } else {
+ $joins['gpa' . $sub] = array('inner', 'groupex.asso', XDB::format('$ME.diminutif = {?}', $key));
+ $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
+ }
+ }
+ return $joins;
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: