All pastes #639312 Raw Edit

k4st

public php v1 · immutable
#639312 ·published 2007-07-30 14:21 UTC
rendered paste body
<?php/** * $header * @copyright Copyright 2007, Peter Goodman * @package valkyrie * @subpackage Libraries.user * @author Peter Goodman *//** * Library to easily manage a user system. This library lets the programmer * get a user login system up and running super quickly by having them configure * this class through a (pre) filter using User::configure(). The point of this * class is that it can sit on top of any database user table schema, and isn't * confined to any specific column names. */class User {		const COOKIE_KEY = 'vkua';	const SESSION_KEY = 'vkua';		/**	 * @internal	 */	protected $definition,			  $table_name,			  $as_name = '',			  $as_pass = '',			  $as_login_key = '',			  $pass_hash_func = 'md5';		/**	 * @internal	 */	private	  $dba,		 	  //$session,			  $model;		/**	 * @internal	 */	private   $is_logged = FALSE;		/**	 * Constructor.	 * @internal	 */	public function __construct(DatabaseDriver $dba, DatabaseModel $model) {				// need to do this because we overloaded the		// already overloaded methods. This will implicitly		// load the session library if it isn't already		$this->dba = $dba;		$this->model = $model;				// start the session if it hasn't been		start_session();				if(!isset($_SESSION[self::SESSION_KEY])) {			$_SESSION[self::SESSION_KEY] = array();		}				if(!empty($_SESSION[self::SESSION_KEY])) {			$this->is_logged = TRUE;		}	}		/**	 * Bring in the dependencies.	 */	static public function create(Registry $registry) {		return new User($registry->dba, $registry->models['database']);	}		/**	 * Destructor.	 * @internal	 */	public function __destruct() {		unset($this->dba, $_SESSION, $this->model);	}		/**	 * Because this is a library it can be cloned. We don't	 * want to let that so we will throw an exception if it	 * is ever tried.	 */	final public function __clone() {		throw new Exception("User library is not allowed to be cloned.");	}		/**	 * Is this user logged in or not?	 * @return bool	 */	public function isLogged() {		return $this->is_logged;	}		/**	 * Getter function useful when the user object is passed to the template	 * engine, eg: <cond:if isset="user.logged_in">	 */	public function getLoggedIn() {		return $this->isLogged() ? TRUE : NULL;	}		/**	 * Save any session info to the database. This is meant to emulate	 * DatabaseRecord::save	 */	public function save() {				if(!$this->isLogged()) {			return FALSE;		}				$args = array();		$pk = $this->definition->primary;				foreach($_SESSION[self::SESSION_KEY] as $key => $val) {						// make sure that the field exists in the definition and that			// we are also not trying to update the primary key			if($this->definition->hasField($key) && $key != $pk) {								// validate the field				try {					$this->validateField($key, $val);				} catch(FailedValidationException $e) {					return FALSE;				}								$args["{$key}=?"] = $val;			}		}				// we've got stuff to update!		if(!empty($args)) {						$vals = array_values($args);			$vals[] = $_SESSION[self::SESSION_KEY][$pk];						$this->dba->update("UPDATE {$this->table_name} SET ". implode(",", array_keys($args)) ." WHERE {$pk}=?", $vals);		}				return TRUE;	}		/**	 * Log a user in.	 */	public function login($as_name, $as_pass, $bool_autologin) {				// no need to log this user in twice		if($this->isLogged()) {			return FALSE;		}				$as_pass = $this->hash($as_pass);		$user = $this->dba->select("SELECT * FROM {$this->table_name} WHERE {$this->as_name}=? AND {$this->as_pass}=? LIMIT 1", array($as_name, $as_pass))->current();				if(empty($user)) {			return FALSE;		}				if($bool_autologin && !empty($this->as_login_key)) {						// unique login key			$login_key = md5(uniqid(rand(), TRUE));						// get PHP's default (or user overridden) cookie params			$cookie_params = session_get_cookie_params();						// expire in 30 days			setcookie(self::COOKIE_KEY, $login_key, time()+2592000, $cookie_params['path'], $cookie_params['domain'], TRUE, TRUE);						// update the user table			$this->dba->update("UPDATE {$this->table_name} SET {$this->as_login_key}=?", array($login_key));		}				$_SESSION[self::SESSION_KEY] = $user;		$this->is_logged = TRUE;				return TRUE;	}		/**	 * Log the user out.	 */	public function logout() {		unset($_SESSION[self::SESSION_KEY]);		$this->is_logged = FALSE;		$this->killCookie();	}		/**	 * Auto log in a user. This is best placed in a pre-filter.	 * @internal	 */	private function autologin() {				// user is logged in, don't bother		if($this->isLogged()) {			return FALSE;		}				// make sure the cookie even exists		if(isset($_COOKIE[self::COOKIE_KEY])) {						if(empty($this->as_login_key)) {				return $this->killCookie();			}						$user = $this->dba->select("SELECT * FROM {$this->table_name} WHERE {$this->as_login_key}=?", array($_COOKIE[self::COOKIE_KEY]))->current();						if(empty($user)) {				return $this->killCookie();			}						$_SESSION[self::SESSION_KEY] = $user;			$this->is_logged = TRUE;		}	}		/**	 * Kill any cookies asociated with this user.	 * @internal	 */	private function killCookie() {		unset($_COOKIE[self::COOKIE_KEY]);		setcookie(self::COOKIE_KEY, "", time()-1000, $cookie_params['path'], $cookie_params['domain'], TRUE, TRUE);				return FALSE;	}		/**	 * Hash the password.	 * @internal	 */	private function hash($pass) {				// an object callback has been passed		if(is_array($this->pass_hash_func)) {			list($obj, $fn) = $this->pass_hash_func;			$pass = $obj->$fn($pass);				// a string callback has been passed		} else {			$fn = $this->pass_hash_func;			$pass = $fn($pass);		}				return $pass;	}		/**	 * Configure the User library to accept login/out events and such.	 * @param string $definition_id The ID of the model definition for the users table.	 * @param string $as_name The name of the column that users will identify themselves with, eg: user name or email.	 * @param string $as_pass The name of the column that the password is stored in.	 * @param string $as_login_key The name of the column that the login key (for auto logging in) is stored in.	 * @param mixed $hash_method The callback function (either string or array) used to hash the password.	 */	public function configure($definition_id, $as_name, $as_pass, $as_login_key = FALSE, $hash_method = FALSE) {				// configure it		$this->definition = $this->model->getModelDefinition($definition_id);		$this->table_name = $this->definition->getTable('name');		$this->as_name = $as_name;		$this->as_pass = $as_pass;		$this->as_login_key = $as_login_key;		$this->pass_hash_func = !$hash_method ? 'md5' : $hash_method;				// auto log the user in, needs to be done in here, we can't put		// it in the constructor otherwise the object won't be configured		// for use to get any useful info from the db		$this->autologin();	}		/**	 * Overloaded methods. Because this class extends the registry we can	 * also access these methods through ArrayAccess	 */	public function __get($key = '') {		$ret = NULL;		if(isset($_SESSION[self::SESSION_KEY][$key])) {			$ret =& $_SESSION[self::SESSION_KEY][$key];		}				return $ret;	}		public function __set($key = '', $val) {		$_SESSION[self::SESSION_KEY][$key] = $val;	}		public function __isset($key = '') {		return $this->isLogged() && isset($_SESSION[self::SESSION_KEY][$key]);	}		public function __unset($key = '') {		if($this->isLogged()) {			unset($_SESSION[self::SESSION_KEY][$key]);		}	}}