Code: Select all
<?php
/**
* Registry class for storing just about anything
*
* This class is basically just a wrapper for an associative array. It
* can be used to store any type of data that an associative array can.
* The most common use for this class is to extend it to allow storage
* in almost any type of class that needs to store data such as
* a session class, an object registry, etc.
*
* @abstract
* @author Luke Visinoni <luke.visinoni@gmail.com>
* @copyright Luke Visinoni August 20th 2006
*/
class Registry{
/**
* Container for all registered data passed to this class
* @access protected
*/
protected $entries = array();
/**
* Add a value to registry data
* @access public
* @param string $key Associative data array key
* @param mixed $value Associative data array value
*/
public function register($key, $value){
$this->entries[$key] = $value;
}
/**
* Remove a value from registry data
* @access public
* @param string $key Associative data array key
*/
public function unregister($key){
unset($this->entries[$key]);
}
/**
* Retrieve a value from registry data
* @access public
* @param string $key Associative data array key
* @return mixed
*/
public function get($key){
return isset($this->entries[$key]) ? $this->entries[$key] : null;
}
/**
* Check that a key exists within registry data
* @access public
* @param string $key Associative data array key
* @return bool
*/
public function has($key){
return $name ? isset($this->entries[$key]) : false;
}
/**
* Destroy all information stored in this registry
* @access public
*/
public function flush(){
$this->entries = array();
}
/**
* Magic wrapper for get()
* @access public
* @param string $key Associative data array key
* @return mixed
*/
/*
public function __get($key){
return $this->get($key);
}*/
/**
* Magic wrapper for register()
* @access public
* @param string $key Associative data array key
* @param string $value Associative data array value
*/
/*
public function __set($key, $value){
$this->register($key, $value);
}*/
}
/**
* Session handler
*
* A class for working with a session. This class is extended
* to provide a particular object or area of an application with its
* own namespace within the session data. This allows for different
* classes to play nicely together and not overwrite or delete session
* data they aren't supposed to.
*
* @author Luke Visinoni <luke.visinoni@gmail.com>
* @copyright Luke Visinoni August 20th 2006
*/
class Session extends Registry{
/**
* Container for session id
* @access protected
* @var string
* @static
*/
protected static $id = null;
/**
* This particular instance's namespace
* @access public
* @var string
*/
protected $namespace;
/**
* Set to true if you would like for session's id to be regenerated
* @access protected
* @var bool
*/
protected $regenerate;
/**
* Constructor
* @param string $namespace
* @param bool $regenerate
*/
public function __construct($namespace='Session', $regenerate=null) {
$this->namespace = $namespace;
$this->regenerate = $regenerate;
$this->start();
}
/**
* Initialize the session
*
* This method starts the session. Once the session is started, it tries to correct
* a known IE problem. (Need to find out more about this problem). Now it checks
* regenerates the session id, if specefied, and associates entries with our session.
*
* @access public
* @todo research ie problem that the session_cache_limiter is supposed to fix
*/
public function start(){
if(session_id() == ''){
session_start();
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')){
session_cache_limiter('must-revalidate');
}
self::$id = session_id();
}
if ($this->regenerate){
session_regenerate_id();
}
$this->entries =& $_SESSION[$this->namespace];
}
//public function __destruct(){
// session_write_close();
//}
public function __get($key){
return $this->get($key);
}
public function __set($key, $value){
$this->register($key, $value);
}
}
interface SessionSaveHandler{
public static function open();
public static function close();
public static function read($id);
public static function write($id, $data);
public static function destroy($id);
public static function clean($max);
}
/**
* Session Handler for storing data in a mysql database
*
* @author Luke Visinoni <luke.visinoni@gmail.com>
* @copyright Luke Visinoni August 20th 2006
* @todo adjust session_set_save_handler methods so that database type and other factors may be dealt with before write/read/etc.
* @todo Allow for use with other than mysql
*/
class MysqlSession extends Session implements SessionSaveHandler{
/**
* Holds a mysql connection resource link
* @access private
* @var mysql connection resource link
* @todo Set up error handling to use exceptions
*/
private static $db;
public function __construct($namespace, $regenerate, $db){
if(is_null($namespace)) $namespace = 'Session';
if(is_null($regenerate)) $regenerate = false;
if(!is_resource($db)){
// I still need to learn exception handling, but this works for now.
die('Third parameter must be a valid mysql resource link.');
}
self::$db = $db;
session_set_save_handler(array(&$this,"open"),
array(&$this,"close"),
array(&$this,"read"),
array(&$this,"write"),
array(&$this,"destroy"),
array(&$this,"clean"));
//register_shutdown_function('session_write_close');
parent::__construct($namespace, $regenerate);
}
public static function open(){
return self::$db;
}
public static function close(){
// No need to close my database connection, since it is shared with the rest of the app
return true;
}
/**
* Reads data from the data source
* @access public
* @static
* @returns string
*/
public static function read($id){
$id = mysql_real_escape_string($id, self::$db);
$sql = "SELECT `data`
FROM `session`
WHERE `session_id` = '" . $id . "'";
if ($result = mysql_query($sql, self::$db)) {
if (mysql_num_rows($result)) {
$record = mysql_fetch_assoc($result);
return $record['data'];
}
}
return '';
}
/**
* Writes serialized data to data source
* @access public
* @static
* @returns bool
*/
public static function write($id, $data){
$access = time();
$id = mysql_real_escape_string($id, self::$db);
$access = mysql_real_escape_string($access, self::$db);
$data = mysql_real_escape_string($data, self::$db);
$sql = "REPLACE
INTO `session` (`session_id`, `access`, `data`)
VALUES('" . $id . "', " . $access . ", '" . $data . "')";
return mysql_query($sql, self::$db);
}
/**
* Delete session data associated with this id
* @access public
* @static
* @returns bool
*/
public static function destroy($id){
$id = mysql_real_escape_string($id, self::$db);
$sql = "DELETE
FROM `session`
WHERE `session_id` = '" . $id . "'";
return mysql_query($sql, self::$db);
}
/**
* Delete old session data
* @access public
* @static
* @returns bool
*/
public static function clean($max){
$old = time() - $max;
$old = mysql_real_escape_string($old, self::$db);
$sql = "DELETE
FROM `session`
WHERE `access` < '" . $old . "'";
return mysql_query($sql, self::$db);
}
}
// Usage
$DB = new Database('mysql://user:xxxx@localhost/my_database');
// This is kind of a fix for the optional params problem... 90% of the time, I would supply the first argument anyway, so I think this will work just fine
$Session = new MysqlSession(null, null, $DB->getLink());
$Session->register('foo', 'bar');
$Session->magic = "This variable was magically registered";
?>