A first version of 'UserFilter' with implementation of promo filtering
[platal.git] / classes / userfilter.php
1 <?php
2 /***************************************************************************
3 * Copyright (C) 2003-2009 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
5 * *
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. *
10 * *
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. *
15 * *
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 *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
22 interface UserFilterCondition
23 {
24 /** Check that the given user matches the rule.
25 */
26 public function check(PlUser &$user);
27 }
28
29 abstract class UFC_OneChild implements UserFilterCondition
30 {
31 protected $child;
32
33 public function setChild(UserFilterCondition &$cond)
34 {
35 $this->child =& $cond;
36 }
37 }
38
39 abstract class UFC_NChildren implements UserFilterCondition
40 {
41 protected $children = array();
42
43 public function addChild(UserFilterCondition &$cond)
44 {
45 $this->children[] =& $cond;
46 }
47 }
48
49 class UFC_True implements UserFilterCondition
50 {
51 public function check(PlUser &$user)
52 {
53 return true;
54 }
55 }
56
57 class UFC_False implements UserFilterCondition
58 {
59 public function check(PlUser &$user)
60 {
61 return false;
62 }
63 }
64
65 class UFC_Not extends UFC_OneChild
66 {
67 public function check(PlUser &$user)
68 {
69 return !$this->child->child($user);
70 }
71 }
72
73 class UFC_And extends UFC_NChildren
74 {
75 public function check(PlUser &$user)
76 {
77 foreach ($this->children as &$cond) {
78 if (!$cond->check($user)) {
79 return false;
80 }
81 }
82 return true;
83 }
84 }
85
86 class UFC_Or extends UFC_NChildren
87 {
88 public function check(PlUser &$user)
89 {
90 foreach ($this->children as &$cond) {
91 if ($cond->check($user)) {
92 return true;
93 }
94 }
95 return false;
96 }
97 }
98
99 class UFC_Promo implements UserFilterCondition
100 {
101 const GRADE_ING = 'Ing.';
102 const GRADE_PHD = 'PhD';
103 const GRADE_MST = 'M%';
104
105 private $grade;
106 private $promo;
107 private $comparison;
108
109 public function __construct($comparison, $grade, $promo)
110 {
111 $this->grade = $grade;
112 $this->comparison = $comparison;
113 $this->promo = $promo;
114 }
115
116 public function check(PlUser &$user)
117 {
118 if (!$user->hasProfile()) {
119 return false;
120 }
121 // XXX: Definition of promotion for phds and masters might change in near future.
122 if ($this->grade == self::GRADE_ING) {
123 $promo_year = 'entry_year';
124 } else {
125 $promo_year = 'grad_year';
126 }
127 $req = XDB::fetchOneCell('SELECT COUNT(pe.id)
128 FROM profile_education AS pe
129 INNER JOIN profile_education_degree_enum AS pede ON (pe.degreeid = pede.id AND pede.abbreviation LIKE {?})
130 INNER JOIN profile_education_enum AS pee ON (pe.eduid = pee.id AND pee.abbreviation = \'X\')
131 WHERE pe.' . $promo_year . ' ' . $this->comparison . ' {?} AND pe.uid = {?}',
132 $this->grade, $this->promo, $user->profile()->id());
133 return intval($req) > 0;
134 }
135 }
136
137 class UserFilter
138 {
139 private $root;
140
141 /** Check that the user match the given rule.
142 */
143 public function checkUser(PlUser &$user)
144 {
145 return $this->root->check($user);
146 }
147
148 /** Filter a list of user to extract the users matching the rule.
149 */
150 public function filter(array $users)
151 {
152 $output = array();
153 foreach ($users as &$user) {
154 if ($this->checkUser($user)) {
155 $output[] = $user;
156 }
157 }
158 return $output;
159 }
160
161 public function setCondition(UserFilterCondition &$cond)
162 {
163 $this->root =& $cond;
164 }
165
166
167 static public function getLegacy($promo_min, $promo_max)
168 {
169 $min = null;
170 if ($promo_min != 0) {
171 $min = new UFC_Promo('>=', UFC_Promo::GRADE_ING, intval($promo_min));
172 }
173 $max = null;
174 if ($promo_max != 0) {
175 $max = new UFC_Promo('<=', UFC_Promo::GRADE_ING, intval($promo_max));
176 }
177 $uf = new UserFilter();
178 if (is_null($max) && is_null($min)) {
179 $uf->setCondition(new UFC_True());
180 } else if (is_null($max)) {
181 $uf->setCondition($min);
182 } else if (is_null($min)) {
183 $uf->setCondition($max);
184 } else {
185 $cond = new UFC_And();
186 $cond->addChild($min);
187 $cond->addChild($max);
188 $uf->setCondition($cond);
189 }
190 return $uf;
191 }
192 }
193
194 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
195 ?>