Commit | Line | Data |
---|---|---|
9f8ebb9f VZ |
1 | <?php |
2 | /*************************************************************************** | |
3 | * Copyright (C) 2003-2008 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 | ||
2d96cf7b | 22 | // PlUserNotFound is raised when a given id cannot be linked to an existing user. |
9f8ebb9f VZ |
23 | // The @p results give the list hruids (useful when several users are found). |
24 | class UserNotFoundException extends Exception | |
25 | { | |
26 | public function __construct($results = array()) | |
27 | { | |
28 | $this->results = $results; | |
29 | parent::__construct(); | |
30 | } | |
31 | } | |
32 | ||
33 | // Represents an user of the system, with a special focus on its identification | |
34 | // (hruid, forlife, and bestalias). | |
35 | // Note: each implementation of platal-core MUST create a subclass 'User' of | |
2d96cf7b VZ |
36 | // this abstract PlUser class. |
37 | abstract class PlUser | |
9f8ebb9f VZ |
38 | { |
39 | // User's data storage. By convention, null means the information hasn't | |
40 | // been fetched yet, and false means the information is not available. | |
41 | ||
42 | // Main (unique) identifiers. | |
43 | private $user_id = null; | |
44 | private $hruid = null; | |
45 | ||
46 | // User's emails (bestalias should be preferred when sending emails). | |
47 | private $forlife = null; | |
48 | private $bestalias = null; | |
49 | ||
50 | ||
51 | // Constructs the object from an identifier (hruid/uid/email alias/email | |
52 | // redirection) and an optionnal array of known user properties. | |
53 | public function __construct($login, $values = array()) | |
54 | { | |
55 | list($this->user_id, $this->hruid) = $this->getLogin($login); | |
56 | $this->fillFromArray($values); | |
57 | } | |
58 | ||
59 | ||
60 | // Properties accessors. | |
61 | public function id() | |
62 | { | |
63 | return $this->user_id; | |
64 | } | |
65 | ||
66 | public function login() | |
67 | { | |
68 | return $this->hruid; | |
69 | } | |
70 | ||
71 | public function bestEmail() | |
72 | { | |
73 | if (!isset($this->bestalias)) { | |
74 | global $globals; | |
75 | $res = XDB::query("SELECT CONCAT(alias, '@{$globals->mail->domain}') | |
76 | FROM aliases | |
77 | WHERE FIND_IN_SET('bestalias', flags) | |
78 | AND id = {?}", $this->user_id); | |
79 | $this->bestalias = $res->numRows() ? $res->fetchOneCell() : false; | |
80 | } | |
81 | return $this->bestalias; | |
82 | } | |
83 | ||
84 | public function forlifeEmail() | |
85 | { | |
86 | if (!isset($this->forlife)) { | |
87 | global $globals; | |
88 | $res = XDB::query("SELECT CONCAT(alias, '@{$globals->mail->domain}') | |
89 | FROM aliases | |
90 | WHERE type = 'a_vie' AND id = {?}", $this->user_id); | |
91 | $this->forlife = $res->numRows() ? $res->fetchOneCell() : false; | |
92 | } | |
93 | return $this->forlife; | |
94 | } | |
95 | ||
96 | ||
97 | // Determines if the @p id is a valid identifier; if so, returns the user_id | |
98 | // and the hruid. Otherwise raises UserNotFoundException. | |
99 | private function getLogin($login) | |
100 | { | |
101 | global $globals; | |
102 | ||
103 | // If $data is an integer, fetches directly the result. | |
104 | if (is_numeric($login)) { | |
105 | $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE user_id = {?}", $login); | |
106 | if ($res->numRows()) { | |
107 | return $res->fetchOneRow(); | |
108 | } | |
109 | ||
110 | throw new UserNotFoundException(); | |
111 | } | |
112 | ||
113 | // Checks whether $login is a valid hruid or not. | |
114 | $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE hruid = {?}", $login); | |
115 | if ($res->numRows()) { | |
116 | return $res->fetchOneRow(); | |
117 | } | |
118 | ||
119 | // From now, $login can only by an email alias, or an email redirection. | |
120 | // If it doesn't look like a valid address, appends the plat/al's main domain. | |
121 | $login = trim(strtolower($login)); | |
122 | if (strstr($login, '@') === false) { | |
123 | $login = $login . '@' . $globals->mail->domain; | |
124 | } | |
125 | ||
126 | // Checks if $login is a valid alias on the main domains. | |
127 | list($mbox, $fqdn) = explode('@', $login); | |
128 | if ($fqdn == $globals->mail->domain || $fqdn == $globals->mail->domain2) { | |
129 | $res = XDB::query("SELECT u.user_id, u.hruid | |
130 | FROM auth_user_md5 AS u | |
131 | INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) | |
132 | WHERE a.alias = {?}", $mbox); | |
133 | if ($res->numRows()) { | |
134 | return $res->fetchOneRow(); | |
135 | } | |
136 | ||
137 | if (preg_match('/^(.*)\.([0-9]{4})$/u', $mbox, $matches)) { | |
138 | $res = XDB::query("SELECT u.user_id, u.hruid | |
139 | FROM auth_user_md5 AS u | |
140 | INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) | |
141 | WHERE a.alias = {?} AND u.promo = {?}", $matches[1], $matches[2]); | |
142 | if ($res->numRows() == 1) { | |
143 | return $res->fetchOneRow(); | |
144 | } | |
145 | } | |
146 | ||
147 | throw new UserNotFoundException(); | |
148 | } | |
149 | ||
150 | // Looks for $login as an email alias from the dedicated alias domain. | |
151 | if ($fqdn == $globals->mail->alias_dom || $fqdn == $globals->mail->alias_dom2) { | |
152 | $res = XDB::query("SELECT redirect | |
153 | FROM virtual_redirect | |
154 | INNER JOIN virtual USING(vid) | |
155 | WHERE alias = {?}", $mbox . '@' . $globals->mail->alias_dom); | |
156 | if ($redir = $res->fetchOneCell()) { | |
157 | // We now have a valid alias, which has to be translated to an hruid. | |
158 | list($alias, $alias_fqdn) = explode('@', $redir); | |
159 | $res = XDB::query("SELECT u.user_id, u.hruid | |
160 | FROM auth_user_md5 AS u | |
161 | LEFT JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) | |
162 | WHERE a.alias = {?}", $alias); | |
163 | if ($res->numRows()) { | |
164 | return $res->fetchOneRow(); | |
165 | } | |
166 | } | |
167 | ||
168 | throw new UserNotFoundException(); | |
169 | } | |
170 | ||
171 | // Otherwise, we do suppose $login is an email redirection. | |
172 | $res = XDB::query("SELECT u.user_id, u.hruid | |
173 | FROM auth_user_md5 AS u | |
174 | LEFT JOIN emails AS e ON (e.uid = u.user_id) | |
175 | WHERE e.email = {?}", $login); | |
176 | if ($res->numRows() == 1) { | |
177 | return $res->fetchOneRow(); | |
178 | } | |
179 | ||
180 | throw new UserNotFoundException($res->fetchColumn(1)); | |
181 | } | |
182 | ||
183 | // Fills the object from associative arrays containing our data. | |
184 | // The use case is for arrays got directly from anoter SQL request. | |
185 | private function fillFromArray(array $values) | |
186 | { | |
187 | foreach ($values as $key => $value) { | |
188 | if (property_exists($this, $key) && !isset($this->$key)) { | |
189 | $this->$key = $value; | |
190 | } | |
191 | } | |
192 | } | |
193 | ||
194 | ||
195 | // Returns a valid User object built from the @p id and optionnal @p values, | |
196 | // or returns false and calls the callback if the @p id is not valid. | |
197 | public static function get($login, $callback = false) | |
198 | { | |
199 | return User::getWithValues($login, array(), $callback); | |
200 | } | |
201 | ||
202 | public static function getWithValues($login, $values, $callback = false) | |
203 | { | |
204 | if (!$callback) { | |
205 | $callback = array(__CLASS__, '_default_user_callback'); | |
206 | } | |
207 | ||
208 | try { | |
209 | return new User($login, $values); | |
210 | } catch (UserNotFoundException $e) { | |
211 | return call_user_func($callback, $login, $e->results); | |
212 | } | |
213 | } | |
214 | ||
215 | // Alias on get() with the silent callback. | |
216 | public static function getSilent($login) | |
217 | { | |
218 | return User::getWithValues($login, array(), array(__CLASS__, '_silent_user_callback')); | |
219 | } | |
220 | ||
221 | // Returns the forlife emails for @p members. If @p strict mode is enabled, | |
222 | // it returns the list of validated forlife emails. If strict mode is not, | |
223 | // it also returns unvalidated values (but still call the callback for them). | |
224 | public static function getBulkForlifeEmails($logins, $strict = true, $callback = false) | |
225 | { | |
226 | if (!is_array($logins)) { | |
227 | if (strlen(trim($logins)) == 0) { | |
228 | return null; | |
229 | } | |
230 | $logins = explode(' ', $logins); | |
231 | } | |
232 | ||
233 | if ($logins) { | |
234 | $list = array(); | |
235 | foreach ($logins as $i => $login) { | |
236 | if (($user = User::get($login, $callback))) { | |
237 | $list[$i] = $user->forlifeEmail(); | |
238 | } else if(!$strict) { | |
239 | $list[$i] = $login; | |
240 | } | |
241 | } | |
242 | return $list; | |
243 | } | |
244 | return null; | |
245 | } | |
246 | ||
247 | // Silent callback for the user lookup -- does nothing. | |
248 | public static function _silent_user_callback($login, $results) | |
249 | { | |
250 | return; | |
251 | } | |
252 | ||
253 | // Default callback for user lookup -- displays an error message w.r.t. the | |
254 | // number of matching users found. | |
255 | public static function _default_user_callback($login, $results) | |
256 | { | |
257 | global $page; | |
258 | ||
259 | $result_count = count($results); | |
260 | if ($result_count == 0 || !S::has_perms()) { | |
261 | $page->trigError("Il n'y a pas d'utilisateur avec l'identifiant : $login"); | |
262 | } else { | |
263 | $page->trigError("Il y a $result_count utilisateurs avec cet identifiant : " . join(', ', $results)); | |
264 | } | |
265 | } | |
266 | } | |
267 | ||
268 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: | |
269 | ?> |