[Solar-svn] Revision 2983
pmjones at solarphp.com
pmjones at solarphp.com
Tue Mar 4 21:20:15 CST 2008
Solar_Session: [ADD] Session object now fully supports save-session-handler adapters. Includes a native adapter and an SQL adapter. Thanks, Antti Holvikari, for these additions.
Added: trunk/Solar/Session/Handler/Adapter/Native.php
===================================================================
--- trunk/Solar/Session/Handler/Adapter/Native.php (rev 0)
+++ trunk/Solar/Session/Handler/Adapter/Native.php 2008-03-05 03:20:15 UTC (rev 2983)
@@ -0,0 +1,131 @@
+<?php
+/**
+ *
+ * Session adapter for native PHP sessions
+ *
+ * This adapter does **not** set any save-handler or ini-settings.
+ *
+ * @category Solar
+ *
+ * @package Solar_Session
+ *
+ * @author Antti Holvikari <anttih at gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+class Solar_Session_Handler_Adapter_Native extends Solar_Session_Handler_Adapter {
+
+ /**
+ *
+ * Sets the session save handler.
+ *
+ * This doesn't actually do anything, because we're using the native PHP
+ * handler, not the methods in this class.
+ *
+ * @return void
+ *
+ */
+ protected function _setSaveHandler()
+ {
+ // do nothing
+ }
+
+ /**
+ *
+ * Opens the session handler.
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @return bool
+ *
+ */
+ public function open()
+ {
+ return true;
+ }
+
+ /**
+ *
+ * Closes session handler.
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @return bool
+ *
+ */
+ public function close()
+ {
+ return true;
+ }
+
+ /**
+ *
+ * Reads session data.
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @param string $id The session ID.
+ *
+ * @return string The serialized session data.
+ *
+ */
+ public function read($id)
+ {
+ return null;
+ }
+
+ /**
+ *
+ * Writes session data.
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @param string $id The session ID.
+ *
+ * @param string $data The serialized session data.
+ *
+ * @return bool
+ *
+ */
+ public function write($id, $data)
+ {
+ return true;
+ }
+
+ /**
+ *
+ * Destroys session data.
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @param string $id The session ID.
+ *
+ * @return bool
+ *
+ */
+ public function destroy($id)
+ {
+ return true;
+ }
+
+ /**
+ *
+ * Removes old session data (garbage collection).
+ *
+ * Provided only to override abstract method, never actually called.
+ *
+ * @param int $lifetime Removes session data not updated since this many
+ * seconds ago. E.g., a lifetime of 86400 removes all session data not
+ * updated in the past 24 hours.
+ *
+ * @return bool
+ *
+ */
+ public function gc($lifetime)
+ {
+ return true;
+ }
+}
\ No newline at end of file
Added: trunk/Solar/Session/Handler/Adapter/Sql.php
===================================================================
--- trunk/Solar/Session/Handler/Adapter/Sql.php (rev 0)
+++ trunk/Solar/Session/Handler/Adapter/Sql.php 2008-03-05 03:20:15 UTC (rev 2983)
@@ -0,0 +1,251 @@
+<?php
+/**
+ *
+ * Session adapter for SQL based data store.
+ *
+ * @category Solar
+ *
+ * @package Solar_Session
+ *
+ * @author Antti Holvikari <anttih at gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+class Solar_Session_Handler_Adapter_Sql extends Solar_Session_Handler_Adapter {
+
+ /**
+ *
+ * Solar_Sql object to connect to the database.
+ *
+ * @var Solar_Sql_Adapter
+ *
+ */
+ protected $_sql;
+
+ /**
+ *
+ * Default configuration values.
+ *
+ * Keys are ...
+ *
+ * `sql`
+ * : (dependency) A Solar_Sql dependency injection.
+ *
+ * `table`
+ * : (string) Table where the session data will be stored, default
+ * 'sessions'.
+ *
+ * `created_col`
+ * : (string) Column name where time of creation is to be stored, default
+ * 'created'.
+ *
+ * `id_col`
+ * : (string) Column name of the session id, default 'id'.
+ *
+ * `data_col`
+ * : (string) Column name where the actual session data will be stored,
+ * default 'data'.
+ *
+ * @var array
+ *
+ */
+ protected $_Solar_Session_Handler_Adapter_Sql = array(
+ 'sql' => 'sql',
+ 'table' => 'sessions',
+ 'id_col' => 'id',
+ 'created_col' => 'created',
+ 'updated_col' => 'updated',
+ 'data_col' => 'data',
+ );
+
+ /**
+ *
+ * Open session handler
+ *
+ * @return bool
+ *
+ */
+ public function open()
+ {
+ if (! $this->_sql) {
+ $this->_sql = Solar::dependency(
+ 'Solar_Sql',
+ $this->_config['sql']
+ );
+ }
+
+ return true;
+ }
+
+ /**
+ *
+ * Reads session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @return string The serialized session data.
+ *
+ */
+ public function read($id)
+ {
+ $sel = Solar::factory(
+ 'Solar_Sql_Select',
+ array('sql' => $this->_sql)
+ );
+
+ $sel->from($this->_config['table'])
+ ->cols($this->_config['data_col'])
+ ->where("{$this->_config['id_col']} = ?", $id);
+
+ return $sel->fetchValue();
+ }
+
+ /**
+ *
+ * Writes session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @param string $data The serialized session data.
+ *
+ * @return bool
+ *
+ */
+ public function write($id, $data)
+ {
+ $sel = Solar::factory(
+ 'Solar_Sql_Select',
+ array('sql' => $this->_sql)
+ );
+
+ // select up to 2 records from the database
+ $sel->from($this->_config['table'])
+ ->cols($this->_config['id_col'])
+ ->where("{$this->_config['id_col']} = ?", $id)
+ ->limit(2);
+
+ // use fetchCol() instead of countPages() for speed reasons.
+ // count on some DBs is pretty slow, so this will fetch only
+ // the rows we need.
+ $rows = $sel->fetchCol();
+ $count = count((array) $rows);
+
+ // insert or update?
+ if ($count == 0) {
+ // no data yet, insert
+ return $this->_insert($data);
+ } elseif ($count == 1) {
+ // existing data, update
+ return $this->_update($data);
+ } else {
+ // more than one row means an ID collision
+ // @todo log this somehow?
+ return false;
+ }
+ }
+
+ /**
+ *
+ * Destroys session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @return bool
+ *
+ */
+ public function destroy($id)
+ {
+ $this->_sql->delete(
+ $this->_config['table'],
+ array("{$this->_config['id_col']} = ?" => $id)
+ );
+
+ return true;
+ }
+
+ /**
+ *
+ * Removes old session data (garbage collection).
+ *
+ * @param int $lifetime Removes session data not updated since this many
+ * seconds ago. E.g., a lifetime of 86400 removes all session data not
+ * updated in the past 24 hours.
+ *
+ * @return bool
+ *
+ */
+ public function gc($lifetime)
+ {
+ // timestamp is current time minus session.gc_maxlifetime
+ $timestamp = date(
+ 'Y-m-d H:i:s',
+ mktime(date('H'), date('i'), date('s') - $lifetime)
+ );
+
+ // delete all sessions last updated before the timestamp
+ $this->_sql->delete($this->_config['table'], array(
+ "{$this->_config['updated_col']} < ?" => $timestamp,
+ ));
+
+ return true;
+ }
+
+ /**
+ *
+ * Inserts a new session-data row in the database.
+ *
+ * @param string $data The serialized session data.
+ *
+ * @return bool
+ *
+ */
+ protected function _insert($data)
+ {
+ $now = date('Y-m-d H:i:s');
+
+ $cols = array(
+ $this->_config['created_col'] => $now,
+ $this->_config['updated_col'] => $now,
+ $this->_config['id_col'] => $id,
+ $this->_config['data_col'] => $data,
+ );
+
+ try {
+ $this->_sql->insert($this->_config['table'], $values);
+ } catch (Solar_Sql_Exception $e) {
+ // @todo log this somehow?
+ return false;
+ }
+ }
+
+ /**
+ *
+ * Updates an existing session-data row in the database.
+ *
+ * @param string $data The serialized session data.
+ *
+ * @return bool
+ *
+ * @todo Should we log caught exceptions?
+ *
+ */
+ protected function _update($data)
+ {
+ $cols = array(
+ $this->_config['updated_col'] => date('Y-m-d H:i:s'),
+ $this->_config['data_col'] => $data,
+ );
+
+ $where = array("{$this->_config['id_col']} = ?" => $id);
+
+ try {
+ $this->_sql->update($this->_config['table'], $cols, $where);
+ } catch (Solar_Sql_Exception $e) {
+ // @todo log this somehow?
+ return false;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/Solar/Session/Handler/Adapter.php
===================================================================
--- trunk/Solar/Session/Handler/Adapter.php (rev 0)
+++ trunk/Solar/Session/Handler/Adapter.php 2008-03-05 03:20:15 UTC (rev 2983)
@@ -0,0 +1,129 @@
+<?php
+/**
+ *
+ * Abstract class for session adapters.
+ *
+ * @category Solar
+ *
+ * @package Solar_Session
+ *
+ * @author Antti Holvikari <anttih at gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+abstract class Solar_Session_Handler_Adapter extends Solar_Base {
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param array $config User-defined configuration values.
+ *
+ */
+ public function __construct($config = null)
+ {
+ parent::__construct($config);
+ $this->_setSaveHandler();
+ }
+
+ /**
+ *
+ * Destructor; calls session_write_close() so that the session gets
+ * written before the object is destroyed.
+ *
+ * @return void
+ *
+ */
+ public function __destruct()
+ {
+ session_write_close();
+ }
+
+ /**
+ *
+ * Sets session save handler to use the methods in this class.
+ *
+ * @return void
+ *
+ */
+ protected function _setSaveHandler()
+ {
+ session_set_save_handler(
+ array($this, 'open'),
+ array($this, 'close'),
+ array($this, 'read'),
+ array($this, 'write'),
+ array($this, 'destroy'),
+ array($this, 'gc')
+ );
+ }
+
+ /**
+ *
+ * Opens the session handler.
+ *
+ * @return bool
+ *
+ */
+ abstract public function open();
+
+ /**
+ *
+ * Closes the session handler.
+ *
+ * @return bool
+ *
+ */
+ abstract public function close();
+
+ /**
+ *
+ * Reads session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @return string The serialized session data.
+ *
+ */
+ abstract public function read($id);
+
+ /**
+ *
+ * Writes session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @param string $data The serialized session data.
+ *
+ * @return bool
+ *
+ */
+ abstract public function write($id, $data);
+
+ /**
+ *
+ * Destroys session data.
+ *
+ * @param string $id The session ID.
+ *
+ * @return bool
+ *
+ */
+ abstract public function destroy($id);
+
+ /**
+ *
+ * Removes old session data (garbage collection).
+ *
+ * @param int $lifetime Removes session data not updated since this many
+ * seconds ago. E.g., a lifetime of 86400 removes all session data not
+ * updated in the past 24 hours.
+ *
+ * @return bool
+ *
+ */
+ abstract public function gc($lifetime);
+}
Added: trunk/Solar/Session/Handler.php
===================================================================
--- trunk/Solar/Session/Handler.php (rev 0)
+++ trunk/Solar/Session/Handler.php 2008-03-05 03:20:15 UTC (rev 2983)
@@ -0,0 +1,53 @@
+<?php
+/**
+ *
+ * Factory class for session save-handlers.
+ *
+ * @category Solar
+ *
+ * @package Solar_Session
+ *
+ * @author Antti Holvikari <anttih at gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+class Solar_Session_Handler extends Solar_Base {
+
+ /**
+ *
+ * User-provided configuration.
+ *
+ * Keys are ...
+ *
+ * `adapter`
+ * : (string) The class to factory, for example
+ * 'Solar_Session_Handler_Adapter_Native'.
+ *
+ * @var array
+ *
+ */
+ protected $_Solar_Session_Handler = array(
+ 'adapter' => 'Solar_Session_Handler_Adapter_Native',
+ );
+
+ /**
+ *
+ * Factory method to create session adapter objects.
+ *
+ * @return Solar_Session_Handler_Adapter
+ *
+ */
+ public function solarFactory()
+ {
+ // bring in the config and get the adapter class.
+ $config = $this->_config;
+ $class = $config['adapter'];
+ unset($config['adapter']);
+
+ // return the factoried adapter object
+ return Solar::factory($class, $config);
+ }
+}
Modified: trunk/Solar/Session.php
===================================================================
--- trunk/Solar/Session.php 2008-03-04 13:54:02 UTC (rev 2982)
+++ trunk/Solar/Session.php 2008-03-05 03:20:15 UTC (rev 2983)
@@ -19,10 +19,12 @@
*
* @category Solar
*
- * @package Solar
+ * @package Solar_Session
*
* @author Paul M. Jones <pmjones at solarphp.com>
*
+ * @author Antti Holvikari <anttih at gmail.com>
+ *
* @license http://opensource.org/licenses/bsd-license.php BSD
*
* @version $Id$
@@ -163,19 +165,18 @@
*/
protected $_Solar_Session = array(
'class' => 'Solar',
- 'handler' => 'php',
+ 'handler' => null,
'P3P' => 'CP="CAO COR CURa ADMa DEVa TAIa OUR BUS IND UNI COM NAV INT STA"',
);
/**
*
- * The session save handler object, or a string 'php' to use the native
- * PHP session handler instead.
+ * The session save handler object.
*
- * @param Solar_Session_Handler|string
+ * @param Solar_Session_Handler_Adapter
*
*/
- static public $handler = 'php';
+ static public $handler;
/**
*
@@ -227,11 +228,11 @@
// only set up the handler if it doesn't exist yet.
if (! self::$handler) {
- self::setHandler($this->_config['handler']);
+ $this->_setHandler($this->_config['handler']);
}
// start a session if one does not exist, but not if we're at
- // the command line.
+ // the command line. at the command line, you need to start it yourself.
if (session_id() === '' && PHP_SAPI != 'cli') {
if ($this->_config['P3P']) {
header('P3P: ' . $this->_config['P3P']);
@@ -250,16 +251,16 @@
/**
*
- * Sets the save-handler for **all** session objecs.
+ * Sets the save-handler for **all** session objects.
*
* Once a session is started, the handler cannot be changed.
*
- * @param dependency $hander A Solar_Sesssion_Handler dependency injection..
+ * @param dependency $handler A Solar_Sesssion_Handler dependency injection..
*
* @return void
*
*/
- static public function setHandler($handler)
+ protected function _setHandler($handler)
{
if (session_id() === '' && self::$handler) {
// if the handler is set and the session is already running,
@@ -272,15 +273,7 @@
);
}
- // use native php sessions?
- if (is_string($handler) && strtolower($handler) == 'php') {
- // set the handler to a non-object, so that we know we're
- // asking for the native php session handler.
- $handler = 'php';
- return;
- }
-
- // build the handler up from a dependency otherwise
+ // session handler dependency
self::$handler = Solar::dependency(
'Solar_Session_Handler',
$handler
@@ -506,4 +499,4 @@
session_regenerate_id(true);
}
}
-}
+}
\ No newline at end of file
More information about the Solar-svn
mailing list