<?php
/***************************************************************************
- * Copyright (C) 2003-2008 Polytechnique.org *
+ * Copyright (C) 2003-2011 Polytechnique.org *
* http://opensource.polytechnique.org/ *
* *
* This program is free software; you can redistribute it and/or modify *
}
}
+interface PlUserInterface
+{
+ public static function _default_user_callback($login, $results);
+
+ /**
+ * Determines if the @p login is an email address, and an email address not
+ * served locally by plat/al.
+ */
+ public static function isForeignEmailAddress($email);
+}
+
/**
* Represents an user of plat/al (without any further assumption), with a
* special focus on always-used properties (identification fields, display name,
* NOTE: each implementation of plat/al-code MUST subclass PlUser, and name it
* 'User'.
*/
-abstract class PlUser
+abstract class PlUser implements PlUserInterface
{
/**
+ * User data enumerations.
+ */
+ const GENDER_FEMALE = true;
+ const GENDER_MALE = false;
+ const FORMAT_HTML = "html";
+ const FORMAT_TEXT = "text";
+
+ /**
* User data storage.
* By convention, null means the information hasn't been fetched yet, and
* false means the information is not available.
*/
- protected $user_id = null;
+
+ // uid is internal user ID (potentially numeric), whereas hruid is a
+ // "human readable" unique ID
+ protected $uid = null;
protected $hruid = null;
// User main email aliases (forlife is the for-life email address, bestalias
- // is user-chosen preferred email address).
+ // is user-chosen preferred email address, email might be any email available
+ // for the user).
protected $forlife = null;
protected $bestalias = null;
+ protected $email = null;
// Display name is user-chosen name to display (eg. in "Welcome
// <display name> !"), while full name is the official full name.
protected $display_name = null;
protected $full_name = null;
- protected $promo = null;
+
+ // Other important parameters used when sending emails.
+ protected $gender = null; // Acceptable values are GENDER_MALE and GENDER_FEMALE
+ protected $email_format = null; // Acceptable values are FORMAT_HTML and FORMAT_TEXT
+
+ // Permissions
+ protected $perms = null;
+ protected $perm_flags = null;
// Other properties are listed in this key-value hash map.
protected $data = array();
// If the user id was not part of the known values, determines it from
// the login.
- if (!$this->user_id) {
- $this->user_id = $this->getLogin($login);
+ if (!$this->uid) {
+ $this->uid = $this->getLogin($login);
}
// Preloads main properties (assumes the loader will lazily get them
* Accessors to the main properties, ie. those available as top level
* object variables.
*/
- public function id() { return $this->user_id; }
- public function login() { return $this->hruid; }
+ public function id()
+ {
+ return $this->uid;
+ }
+
+ public function login()
+ {
+ return $this->hruid;
+ }
+
+ public function isMe($other)
+ {
+ if (!$other) {
+ return false;
+ } else if ($other instanceof PlUser) {
+ return $other->id() == $this->id();
+ } else {
+ return false;
+ }
+ }
+
+ public function bestEmail()
+ {
+ if (!empty($this->bestalias)) {
+ return $this->bestalias;
+ }
+ return $this->email;
+ }
+ public function forlifeEmail()
+ {
+ if (!empty($this->forlife)) {
+ return $this->forlife;
+ }
+ return $this->email;
+ }
- public function bestEmail() { return $this->bestalias; }
- public function forlifeEmail() { return $this->forlife; }
+ public function displayName()
+ {
+ return $this->display_name;
+ }
+ public function fullName()
+ {
+ return $this->full_name;
+ }
+
+ abstract public function password();
+
+ // Fallback value is GENDER_MALE.
+ public function isFemale()
+ {
+ return $this->gender == self::GENDER_FEMALE;
+ }
- public function displayName() { return $this->display_name; }
- public function fullName() { return $this->full_name; }
+ // Fallback value is FORMAT_TEXT.
+ public function isEmailFormatHtml()
+ {
+ return $this->email_format == self::FORMAT_HTML;
+ }
/**
* Other properties are available directly through the $data array, or as
* standard object variables, using a getter.
*/
- public function data() { return $this->data; }
+ public function data()
+ {
+ return $this->data;
+ }
public function __get($name)
{
- if (isset($this->$name)) {
+ if (property_exists($this, $name)) {
return $this->$name;
}
public function __isset($name)
{
- return isset($this->$name) || isset($this->data[$name]);
+ return property_exists($this, $name) || isset($this->data[$name]);
+ }
+
+ public function __unset($name)
+ {
+ if (property_exists($this, $name)) {
+ $this->$name = null;
+ } else {
+ unset($this->data[$name]);
+ }
}
/**
$this->data = array_merge($this->data, $values);
}
+ /**
+ * Adds properties to the object; this method does not allow the caller to
+ * update core properties (id, ...).
+ *
+ * @param $values An associative array of non-core properties.
+ */
+ public function addProperties(array $values)
+ {
+ foreach ($values as $key => $value) {
+ if (!property_exists($this, $key)) {
+ $this->data[$key] = $value;
+ }
+ }
+ }
+
+
+ /**
+ * Build the permissions flags for the user.
+ */
+ abstract protected function buildPerms();
+
+ /**
+ * Check wether the user got the given permission combination.
+ */
+ public function checkPerms($perms)
+ {
+ if (is_null($this->perm_flags)) {
+ $this->buildPerms();
+ }
+ if (is_null($this->perm_flags)) {
+ return false;
+ }
+ return $this->perm_flags->hasFlagCombination($perms);
+ }
+
/**
* Returns a valid User object built from the @p id and optionnal @p values,
}
}
+ public static function getWithUID($uid, $callback = false)
+ {
+ return User::getWithValues(null, array('uid' => $uid), $callback);
+ }
+
// Same as above, but using the silent callback as default.
public static function getSilent($login)
{
return User::getWithValues($login, $values, array('User', '_silent_user_callback'));
}
+ public static function getSilentWithUID($uid)
+ {
+ return User::getWithValues(null, array('uid' => $uid), array('User', '_silent_user_callback'));
+ }
+
/**
- * Returns forlife emails corresponding to the @p logins. If @p strict mode
- * is disabled, it also includes login for which no forlife was found (but
- * still call the callback for them).
+ * Retrieves User objects corresponding to the @p logins, and eventually
+ * extracts and returns the @p property. If @p strict mode is disabled, it
+ * also includes logins for which no forlife was found (but it still calls
+ * the callback for them).
* In all cases, email addresses which are not from the local domains are
* kept.
*
* @param $logins Array of user logins.
+ * @param $property Property to retrieve from the User objects.
* @param $strict Should unvalidated logins be returned as-is or discarded ?
* @param $callback Callback to call when a login is unknown to the system.
* @return Array of validated user forlife emails.
*/
- public static function getBulkForlifeEmails($logins, $strict = true, $callback = false)
+ private static function getBulkUserProperties($logins, $property, $strict, $callback)
{
if (!is_array($logins)) {
if (strlen(trim($logins)) == 0) {
return null;
}
- $logins = split("[; ,\r\n\|]+", $logins);
+ $logins = preg_split("/[; ,\r\n\|]+/", $logins);
}
if ($logins) {
}
if (($user = User::get($login, $callback))) {
- $list[$i] = $user->forlifeEmail();
- } else if (!$strict || User::isForeignEmailAddress($login)) {
+ $list[$i] = $user->$property();
+ } else if (!$strict || (User::isForeignEmailAddress($login) && isvalid_email($login))) {
$list[$i] = $login;
}
}
- return $list;
+ return array_unique($list);
}
return null;
}
/**
+ * Returns hruid corresponding to the @p logins. See getBulkUserProperties()
+ * for details.
+ */
+ public static function getBulkHruid($logins, $callback = false)
+ {
+ return self::getBulkUserProperties($logins, 'login', true, $callback);
+ }
+
+ /**
+ * Returns forlife emails corresponding to the @p logins. See
+ * getBulkUserProperties() for details.
+ */
+ public static function getBulkForlifeEmails($logins, $strict = true, $callback = false)
+ {
+ return self::getBulkUserProperties($logins, 'forlifeEmail', $strict, $callback);
+ }
+
+ /**
* Predefined callbacks for the user lookup; they are called when a given
* login is found not to be associated with any valid user. Silent callback
* does nothing; default callback is supposed to display an error message,
return;
}
- abstract public static function _default_user_callback($login, $results);
+ private static function stripBadChars($text)
+ {
+ return str_replace(array(' ', "'", '+'), array('-', '', '_'),
+ strtolower(stripslashes(replace_accent(trim($text)))));
+ }
+
+ /** Creates a username from a first and last name
+ * @param $firstname User's firstname
+ * @param $lasttname User's lastname
+ * return STRING the corresponding username
+ */
+ public static function makeUserName($firstname, $lastname)
+ {
+ return self::stripBadChars($firstname) . '.' . self::stripBadChars($lastname);
+ }
/**
- * Determines if the @p login is an email address, and an email address not
- * served locally by plat/al.
+ * Creates a user forlive identifier from:
+ * @param $firstname User's firstname
+ * @param $lasttname User's lastname
+ * @param $category User's promotion or type of account
*/
- abstract public static function isForeignEmailAddress($email);
+ public static function makeHrid($firstname, $lastname, $category)
+ {
+ $cat = self::stripBadChars($category);
+ if (!$cat) {
+ Platal::page()->kill("$category is not a suitable category.");
+ }
+
+ return self::makeUserName($firstname, $lastname) . '.' . $cat;
+ }
+
+ /** Reformats the firstname so that all letters are in lower case,
+ * except the first letter of each part of the name.
+ */
+ public static function fixFirstnameCase($firstname)
+ {
+ $firstname = strtolower($firstname);
+ $pieces = explode('-', $firstname);
+
+ foreach ($pieces as $piece) {
+ $subpieces = explode("'", $piece);
+ $usubpieces = '';
+
+ foreach ($subpieces as $subpiece) {
+ $usubpieces[] = ucwords($subpiece);
+ }
+ $upieces[] = implode("'", $usubpieces);
+ }
+ return implode('-', $upieces);
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: