Creates a User class to handle user identification.
authorVincent Zanotti <vincent.zanotti@polytechnique.org>
Sun, 15 Jun 2008 14:37:42 +0000 (16:37 +0200)
committerVincent Zanotti <vincent.zanotti@polytechnique.org>
Sun, 15 Jun 2008 14:37:42 +0000 (16:37 +0200)
Signed-off-by: Vincent Zanotti <vincent.zanotti@polytechnique.org>
classes/coreuser.php [new file with mode: 0644]
classes/user.php [new file with mode: 0644]

diff --git a/classes/coreuser.php b/classes/coreuser.php
new file mode 100644 (file)
index 0000000..742b3a1
--- /dev/null
@@ -0,0 +1,269 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+// UserNotFound is raised when a given id cannot be linked to an existing user.
+// The @p results give the list hruids (useful when several users are found).
+class UserNotFoundException extends Exception
+{
+    public function __construct($results = array())
+    {
+        $this->results = $results;
+        parent::__construct();
+    }
+}
+
+// Represents an user of the system, with a special focus on its identification
+// (hruid, forlife, and bestalias).
+// Note: each implementation of platal-core MUST create a subclass 'User' of
+// this abstract CoreUser class.
+abstract class CoreUser
+{
+    // User's data storage. By convention, null means the information hasn't
+    // been fetched yet, and false means the information is not available.
+
+    // Main (unique) identifiers.
+    private $user_id = null;
+    private $hruid = null;
+
+    // User's emails (bestalias should be preferred when sending emails).
+    private $forlife = null;
+    private $bestalias = null;
+
+
+    // Constructs the object from an identifier (hruid/uid/email alias/email
+    // redirection) and an optionnal array of known user properties.
+    public function __construct($login, $values = array())
+    {
+        list($this->user_id, $this->hruid) = $this->getLogin($login);
+        $this->fillFromArray($values);
+    }
+
+
+    // Properties accessors.
+    public function id()
+    {
+        return $this->user_id;
+    }
+
+    public function login()
+    {
+        return $this->hruid;
+    }
+
+    public function bestEmail()
+    {
+        if (!isset($this->bestalias)) {
+            global $globals;
+            $res = XDB::query("SELECT  CONCAT(alias, '@{$globals->mail->domain}')
+                                 FROM  aliases
+                                WHERE  FIND_IN_SET('bestalias', flags)
+                                       AND id = {?}", $this->user_id);
+            $this->bestalias = $res->numRows() ? $res->fetchOneCell() : false;
+        }
+        return $this->bestalias;
+    }
+
+    public function forlifeEmail()
+    {
+        if (!isset($this->forlife)) {
+            global $globals;
+            $res = XDB::query("SELECT  CONCAT(alias, '@{$globals->mail->domain}')
+                                 FROM  aliases
+                                WHERE  type = 'a_vie' AND id = {?}", $this->user_id);
+            $this->forlife = $res->numRows() ? $res->fetchOneCell() : false;
+        }
+        return $this->forlife;
+    }
+
+
+    // Determines if the @p id is a valid identifier; if so, returns the user_id
+    // and the hruid. Otherwise raises UserNotFoundException.
+    private function getLogin($login)
+    {
+        global $globals;
+
+        // If $data is an integer, fetches directly the result.
+        if (is_numeric($login)) {
+            $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE user_id = {?}", $login);
+            if ($res->numRows()) {
+                return $res->fetchOneRow();
+            }
+
+            throw new UserNotFoundException();
+        }
+
+        // Checks whether $login is a valid hruid or not.
+        $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE hruid = {?}", $login);
+        if ($res->numRows()) {
+            return $res->fetchOneRow();
+        }
+
+        // From now, $login can only by an email alias, or an email redirection.
+        // If it doesn't look like a valid address, appends the plat/al's main domain.
+        $login = trim(strtolower($login));
+        if (strstr($login, '@') === false) {
+            $login = $login . '@' . $globals->mail->domain;
+        }
+
+        // Checks if $login is a valid alias on the main domains.
+        list($mbox, $fqdn) = explode('@', $login);
+        if ($fqdn == $globals->mail->domain || $fqdn == $globals->mail->domain2) {
+            $res = XDB::query("SELECT  u.user_id, u.hruid
+                                 FROM  auth_user_md5 AS u
+                           INNER JOIN  aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie'))
+                                WHERE  a.alias = {?}", $mbox);
+            if ($res->numRows()) {
+                return $res->fetchOneRow();
+            }
+
+            if (preg_match('/^(.*)\.([0-9]{4})$/u', $mbox, $matches)) {
+                $res = XDB::query("SELECT  u.user_id, u.hruid
+                                     FROM  auth_user_md5 AS u
+                               INNER JOIN  aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie'))
+                                    WHERE  a.alias = {?} AND u.promo = {?}", $matches[1], $matches[2]);
+                if ($res->numRows() == 1) {
+                    return $res->fetchOneRow();
+                }
+            }
+
+            throw new UserNotFoundException();
+        }
+
+        // Looks for $login as an email alias from the dedicated alias domain.
+        if ($fqdn == $globals->mail->alias_dom || $fqdn == $globals->mail->alias_dom2) {
+            $res = XDB::query("SELECT  redirect
+                                 FROM  virtual_redirect
+                           INNER JOIN  virtual USING(vid)
+                                WHERE  alias = {?}", $mbox . '@' . $globals->mail->alias_dom);
+            if ($redir = $res->fetchOneCell()) {
+                // We now have a valid alias, which has to be translated to an hruid.
+                list($alias, $alias_fqdn) = explode('@', $redir);
+                $res = XDB::query("SELECT  u.user_id, u.hruid
+                                     FROM  auth_user_md5 AS u
+                                LEFT JOIN  aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie'))
+                                    WHERE  a.alias = {?}", $alias);
+                if ($res->numRows()) {
+                    return $res->fetchOneRow();
+                }
+            }
+
+            throw new UserNotFoundException();
+        }
+
+        // Otherwise, we do suppose $login is an email redirection.
+        $res = XDB::query("SELECT  u.user_id, u.hruid
+                             FROM  auth_user_md5 AS u
+                        LEFT JOIN  emails AS e ON (e.uid = u.user_id)
+                            WHERE  e.email = {?}", $login);
+        if ($res->numRows() == 1) {
+            return $res->fetchOneRow();
+        }
+
+        throw new UserNotFoundException($res->fetchColumn(1));
+    }
+
+    // Fills the object from associative arrays containing our data.
+    // The use case is for arrays got directly from anoter SQL request.
+    private function fillFromArray(array $values)
+    {
+        foreach ($values as $key => $value) {
+            if (property_exists($this, $key) && !isset($this->$key)) {
+                $this->$key = $value;
+            }
+        }
+    }
+
+
+    // Returns a valid User object built from the @p id and optionnal @p values,
+    // or returns false and calls the callback if the @p id is not valid.
+    public static function get($login, $callback = false)
+    {
+        return User::getWithValues($login, array(), $callback);
+    }
+
+    public static function getWithValues($login, $values, $callback = false)
+    {
+        if (!$callback) {
+            $callback = array(__CLASS__, '_default_user_callback');
+        }
+
+        try {
+            return new User($login, $values);
+        } catch (UserNotFoundException $e) {
+            return call_user_func($callback, $login, $e->results);
+        }
+    }
+
+    // Alias on get() with the silent callback.
+    public static function getSilent($login)
+    {
+        return User::getWithValues($login, array(), array(__CLASS__, '_silent_user_callback'));
+    }
+
+    // Returns the forlife emails for @p members. If @p strict mode is enabled,
+    // it returns the list of validated forlife emails. If strict mode is not,
+    // it also returns unvalidated values (but still call the callback for them).
+    public static function getBulkForlifeEmails($logins, $strict = true, $callback = false)
+    {
+        if (!is_array($logins)) {
+            if (strlen(trim($logins)) == 0) {
+                return null;
+            }
+            $logins = explode(' ', $logins);
+        }
+
+        if ($logins) {
+            $list = array();
+            foreach ($logins as $i => $login) {
+                if (($user = User::get($login, $callback))) {
+                    $list[$i] = $user->forlifeEmail();
+                } else if(!$strict) {
+                    $list[$i] = $login;
+                }
+            }
+            return $list;
+        }
+        return null;
+    }
+
+    // Silent callback for the user lookup -- does nothing.
+    public static function _silent_user_callback($login, $results)
+    {
+        return;
+    }
+
+    // Default callback for user lookup -- displays an error message w.r.t. the
+    // number of matching users found.
+    public static function _default_user_callback($login, $results)
+    {
+        global $page;
+
+        $result_count = count($results);
+        if ($result_count == 0 || !S::has_perms()) {
+            $page->trigError("Il n'y a pas d'utilisateur avec l'identifiant : $login");
+        } else {
+            $page->trigError("Il y a $result_count utilisateurs avec cet identifiant : " . join(', ', $results));
+        }
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
diff --git a/classes/user.php b/classes/user.php
new file mode 100644 (file)
index 0000000..512eeca
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+class User extends CoreUser
+{
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>