2 /***************************************************************************
3 * Copyright (C) 2003-2008 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
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. *
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. *
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 *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 // PlUserNotFound is raised when a given id cannot be linked to an existing user.
23 // The @p results give the list hruids (useful when several users are found).
24 class UserNotFoundException
extends Exception
26 public function __construct($results = array())
28 $this->results
= $results;
29 parent
::__construct();
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
36 // this abstract PlUser class.
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.
42 // Main (unique) identifiers.
43 private $user_id = null
;
44 private $hruid = null
;
46 // User's emails (bestalias should be preferred when sending emails).
47 private $forlife = null
;
48 private $bestalias = null
;
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())
55 list($this->user_id
, $this->hruid
) = $this->getLogin($login);
56 $this->fillFromArray($values);
60 // Properties accessors.
63 return $this->user_id
;
66 public function login()
71 public function bestEmail()
73 if (!isset($this->bestalias
)) {
75 $res = XDB
::query("SELECT CONCAT(alias, '@{$globals->mail->domain}')
77 WHERE FIND_IN_SET('bestalias', flags)
78 AND id = {?}", $this->user_id
);
79 $this->bestalias
= $res->numRows() ?
$res->fetchOneCell() : false
;
81 return $this->bestalias
;
84 public function forlifeEmail()
86 if (!isset($this->forlife
)) {
88 $res = XDB
::query("SELECT CONCAT(alias, '@{$globals->mail->domain}')
90 WHERE type = 'a_vie' AND id = {?}", $this->user_id
);
91 $this->forlife
= $res->numRows() ?
$res->fetchOneCell() : false
;
93 return $this->forlife
;
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)
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();
110 throw new UserNotFoundException();
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();
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
;
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();
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();
147 throw new UserNotFoundException();
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();
168 throw new UserNotFoundException();
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();
180 throw new UserNotFoundException($res->fetchColumn(1));
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)
187 foreach ($values as $key => $value) {
188 if (property_exists($this, $key) && !isset($this->$key)) {
189 $this->$key = $value;
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
)
199 return User
::getWithValues($login, array(), $callback);
202 public static function getWithValues($login, $values, $callback = false
)
205 $callback = array(__CLASS__
, '_default_user_callback');
209 return new User($login, $values);
210 } catch (UserNotFoundException
$e) {
211 return call_user_func($callback, $login, $e->results
);
215 // Alias on get() with the silent callback.
216 public static function getSilent($login)
218 return User
::getWithValues($login, array(), array(__CLASS__
, '_silent_user_callback'));
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
)
226 if (!is_array($logins)) {
227 if (strlen(trim($logins)) == 0) {
230 $logins = explode(' ', $logins);
235 foreach ($logins as $i => $login) {
236 if (($user = User
::get($login, $callback))) {
237 $list[$i] = $user->forlifeEmail();
238 } else if(!$strict) {
247 // Silent callback for the user lookup -- does nothing.
248 public static function _silent_user_callback($login, $results)
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)
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");
263 $page->trigError("Il y a $result_count utilisateurs avec cet identifiant : " . join(', ', $results));
268 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: