Renames CoreUser to PlUser to comply with platal-core coding rules.
[platal.git] / classes / pluser.php
CommitLineData
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).
24class 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.
37abstract 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?>