Commit f610527a by Qiang Xue

finished session components.

parent a8a3e1a9
<?php <?php
/** /**
* DbSession class file. * CacheSession class file.
* *
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC * @copyright Copyright &copy; 2008 Yii Software LLC
...@@ -9,61 +9,69 @@ ...@@ -9,61 +9,69 @@
namespace yii\web; namespace yii\web;
use Yii;
use yii\caching\Cache;
use yii\base\InvalidConfigException;
/** /**
* CacheSession implements a session component using cache as storage medium. * CacheSession implements a session component using cache as storage medium.
* *
* The cache being used can be any cache application component implementing {@link ICache} interface. * The cache being used can be any cache application component.
* The ID of the cache application component is specified via {@link cacheID}, which defaults to 'cache'. * The ID of the cache application component is specified via [[cacheID]], which defaults to 'cache'.
* *
* Beware, by definition cache storage are volatile, which means the data stored on them * Beware, by definition cache storage are volatile, which means the data stored on them
* may be swapped out and get lost. Therefore, you must make sure the cache used by this component * may be swapped out and get lost. Therefore, you must make sure the cache used by this component
* is NOT volatile. If you want to use {@link CDbCache} as storage medium, use {@link CDbHttpSession} * is NOT volatile. If you want to use database as storage medium, use [[DbSession]] is a better choice.
* is a better choice.
*
* @property boolean $useCustomStorage Whether to use custom storage.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @package system.web * @since 2.0
* @since 1.0
*/ */
class CacheSession extends Session class CacheSession extends Session
{ {
/** /**
* Prefix to the keys for storing cached data
*/
const CACHE_KEY_PREFIX = 'Yii.CacheSession.';
/**
* @var string the ID of the cache application component. Defaults to 'cache' (the primary cache application component.) * @var string the ID of the cache application component. Defaults to 'cache' (the primary cache application component.)
*/ */
public $cacheID = 'cache'; public $cacheID = 'cache';
/** /**
* @var ICache the cache component * @var Cache the cache component
*/ */
private $_cache; private $_cache;
/** /**
* Initializes the application component. * Returns a value indicating whether to use custom session storage.
* This method overrides the parent implementation by checking if cache is available. * This method overrides the parent implementation and always returns true.
* @return boolean whether to use custom storage.
*/
public function getUseCustomStorage()
{
return true;
}
/**
* Returns the cache instance used for storing session data.
* @return Cache the cache instance
* @throws InvalidConfigException if [[cacheID]] does not point to a valid application component.
*/ */
public function init() public function getCache()
{ {
$this->_cache = Yii::app()->getComponent($this->cacheID); if ($this->_cache === null) {
if (!($this->_cache instanceof ICache)) { $cache = Yii::$app->getComponent($this->cacheID);
throw new CException(Yii::t('yii', 'CacheSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', if ($cache instanceof Cache) {
array('{id}' => $this->cacheID))); $this->_cache = $cache;
} else {
throw new InvalidConfigException('CacheSession::cacheID must refer to the ID of a cache application component.');
}
} }
parent::init(); return $this->_cache;
} }
/** /**
* Returns a value indicating whether to use custom session storage. * Sets the cache instance used by the session component.
* This method overrides the parent implementation and always returns true. * @param Cache $value the cache instance
* @return boolean whether to use custom storage.
*/ */
public function getUseCustomStorage() public function setCache($value)
{ {
return true; $this->_cache = $value;
} }
/** /**
...@@ -74,7 +82,7 @@ class CacheSession extends Session ...@@ -74,7 +82,7 @@ class CacheSession extends Session
*/ */
public function readSession($id) public function readSession($id)
{ {
$data = $this->_cache->get($this->calculateKey($id)); $data = $this->getCache()->get($this->calculateKey($id));
return $data === false ? '' : $data; return $data === false ? '' : $data;
} }
...@@ -87,7 +95,7 @@ class CacheSession extends Session ...@@ -87,7 +95,7 @@ class CacheSession extends Session
*/ */
public function writeSession($id, $data) public function writeSession($id, $data)
{ {
return $this->_cache->set($this->calculateKey($id), $data, $this->getTimeout()); return $this->getCache()->set($this->calculateKey($id), $data, $this->getTimeout());
} }
/** /**
...@@ -98,7 +106,7 @@ class CacheSession extends Session ...@@ -98,7 +106,7 @@ class CacheSession extends Session
*/ */
public function destroySession($id) public function destroySession($id)
{ {
return $this->_cache->delete($this->calculateKey($id)); return $this->getCache()->delete($this->calculateKey($id));
} }
/** /**
...@@ -108,6 +116,6 @@ class CacheSession extends Session ...@@ -108,6 +116,6 @@ class CacheSession extends Session
*/ */
protected function calculateKey($id) protected function calculateKey($id)
{ {
return self::CACHE_KEY_PREFIX . $id; return $this->getCache()->buildKey(__CLASS__, $id);
} }
} }
...@@ -47,7 +47,7 @@ class Cookie extends \yii\base\Object ...@@ -47,7 +47,7 @@ class Cookie extends \yii\base\Object
* By setting this property to true, the cookie will not be accessible by scripting languages, * By setting this property to true, the cookie will not be accessible by scripting languages,
* such as JavaScript, which can effectively help to reduce identity theft through XSS attacks. * such as JavaScript, which can effectively help to reduce identity theft through XSS attacks.
*/ */
public $httpOnly = false; public $httponly = false;
/** /**
* Magic method to turn a cookie object into a string without having to explicitly access [[value]]. * Magic method to turn a cookie object into a string without having to explicitly access [[value]].
......
...@@ -111,7 +111,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ ...@@ -111,7 +111,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \
{ {
if (isset($this->_cookies[$cookie->name])) { if (isset($this->_cookies[$cookie->name])) {
$c = $this->_cookies[$cookie->name]; $c = $this->_cookies[$cookie->name];
setcookie($c->name, '', 0, $c->path, $c->domain, $c->secure, $c->httpOnly); setcookie($c->name, '', 0, $c->path, $c->domain, $c->secure, $c->httponly);
} }
$value = $cookie->value; $value = $cookie->value;
...@@ -124,7 +124,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ ...@@ -124,7 +124,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \
$value = SecurityHelper::hashData(serialize($value), $key); $value = SecurityHelper::hashData(serialize($value), $key);
} }
setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly);
$this->_cookies[$cookie->name] = $cookie; $this->_cookies[$cookie->name] = $cookie;
} }
...@@ -138,7 +138,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ ...@@ -138,7 +138,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \
$cookie = $this->_cookies[$cookie]; $cookie = $this->_cookies[$cookie];
} }
if ($cookie instanceof Cookie) { if ($cookie instanceof Cookie) {
setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly);
unset($this->_cookies[$cookie->name]); unset($this->_cookies[$cookie->name]);
} }
} }
...@@ -149,7 +149,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \ ...@@ -149,7 +149,7 @@ class CookieCollection extends \yii\base\Object implements \IteratorAggregate, \
public function removeAll() public function removeAll()
{ {
foreach ($this->_cookies as $cookie) { foreach ($this->_cookies as $cookie) {
setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); setcookie($cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httponly);
} }
$this->_cookies = array(); $this->_cookies = array();
} }
......
...@@ -9,39 +9,42 @@ ...@@ -9,39 +9,42 @@
namespace yii\web; namespace yii\web;
use Yii;
use yii\db\Connection;
use yii\db\Query;
use yii\base\InvalidConfigException;
/** /**
* DbSession extends {@link CHttpSession} by using database as session data storage. * DbSession extends [[Session]] by using database as session data storage.
* *
* DbSession stores session data in a DB table named 'YiiSession'. The table name * DbSession uses a DB application component to perform DB operations. The ID of the DB application
* can be changed by setting {@link sessionTableName}. If the table does not exist, * component is specified via [[connectionID]] which defaults to 'db'.
* it will be automatically created if {@link autoCreateSessionTable} is set true.
* *
* The following is the table structure: * By default, DbSession stores session data in a DB table named 'tbl_session'. This table
* must be pre-created. The table name can be changed by setting [[sessionTableName]].
* The table should have the following structure:
* *
* <pre> * ~~~
* CREATE TABLE YiiSession * CREATE TABLE tbl_session
* ( * (
* id CHAR(32) PRIMARY KEY, * id CHAR(32) PRIMARY KEY,
* expire INTEGER, * expire INTEGER,
* data BLOB * data BLOB
* ) * )
* </pre> * ~~~
* Where 'BLOB' refers to the BLOB-type of your preffered database.
*
* DbSession relies on {@link http://www.php.net/manual/en/ref.pdo.php PDO} to access database.
* *
* By default, it will use an SQLite3 database named 'session-YiiVersion.db' under the application runtime directory. * where 'BLOB' refers to the BLOB-type of your preferred database. Below are the BLOB type
* You can also specify {@link connectionID} so that it makes use of a DB application component to access database. * that can be used for some popular databases:
* *
* When using DbSession in a production server, we recommend you pre-create the session DB table * - MySQL: LONGBLOB
* and set {@link autoCreateSessionTable} to be false. This will greatly improve the performance. * - PostgreSQL: BYTEA
* You may also create a DB index for the 'expire' column in the session table to further improve the performance. * - MSSQL: BLOB
* *
* @property boolean $useCustomStorage Whether to use custom storage. * When using DbSession in a production server, we recommend you create a DB index for the 'expire'
* column in the session table to improve the performance.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @package system.web * @since 2.0
* @since 1.0
*/ */
class DbSession extends Session class DbSession extends Session
{ {
...@@ -60,14 +63,9 @@ class DbSession extends Session ...@@ -60,14 +63,9 @@ class DbSession extends Session
* </pre> * </pre>
* @see autoCreateSessionTable * @see autoCreateSessionTable
*/ */
public $sessionTableName = 'YiiSession'; public $sessionTableName = 'tbl_session';
/** /**
* @var boolean whether the session DB table should be automatically created if not exists. Defaults to true. * @var Connection the DB connection instance
* @see sessionTableName
*/
public $autoCreateSessionTable = true;
/**
* @var CDbConnection the DB connection instance
*/ */
private $_db; private $_db;
...@@ -83,10 +81,9 @@ class DbSession extends Session ...@@ -83,10 +81,9 @@ class DbSession extends Session
} }
/** /**
* Updates the current session id with a newly generated one. * Updates the current session ID with a newly generated one .
* Please refer to {@link http://php.net/session_regenerate_id} for more details. * Please refer to [[http://php.net/session_regenerate_id]] for more details.
* @param boolean $deleteOldSession Whether to delete the old associated session file or not. * @param boolean $deleteOldSession Whether to delete the old associated session file or not.
* @since 1.1.8
*/ */
public function regenerateID($deleteOldSession = false) public function regenerateID($deleteOldSession = false)
{ {
...@@ -99,93 +96,56 @@ class DbSession extends Session ...@@ -99,93 +96,56 @@ class DbSession extends Session
parent::regenerateID(false); parent::regenerateID(false);
$newID = session_id(); $newID = session_id();
$db = $this->getDbConnection(); $db = $this->getDb();
$row = $db->createCommand() $query = new Query;
->select() $row = $query->from($this->sessionTableName)
->from($this->sessionTableName) ->where(array('id' => $oldID))
->where('id=:id', array(':id' => $oldID)) ->createCommand($db)
->queryRow(); ->queryRow();
if ($row !== false) { if ($row !== false) {
if ($deleteOldSession) { if ($deleteOldSession) {
$db->createCommand()->update($this->sessionTableName, array( $db->createCommand()->update($this->sessionTableName, array(
'id' => $newID 'id' => $newID
), 'id=:oldID', array(':oldID' => $oldID)); ), array('id' => $oldID))->execute();
} else { } else {
$row['id'] = $newID; $row['id'] = $newID;
$db->createCommand()->insert($this->sessionTableName, $row); $db->createCommand()->insert($this->sessionTableName, $row)->execute();
} }
} else { } else {
// shouldn't reach here normally // shouldn't reach here normally
$db->createCommand()->insert($this->sessionTableName, array( $db->createCommand()->insert($this->sessionTableName, array(
'id' => $newID, 'id' => $newID,
'expire' => time() + $this->getTimeout(), 'expire' => time() + $this->getTimeout(),
)); ))->execute();
}
}
/**
* Creates the session DB table.
* @param CDbConnection $db the database connection
* @param string $tableName the name of the table to be created
*/
protected function createSessionTable($db, $tableName)
{
$driver = $db->getDriverName();
if ($driver === 'mysql') {
$blob = 'LONGBLOB';
} elseif ($driver === 'pgsql') {
$blob = 'BYTEA';
} else {
$blob = 'BLOB';
} }
$db->createCommand()->createTable($tableName, array(
'id' => 'CHAR(32) PRIMARY KEY',
'expire' => 'integer',
'data' => $blob,
));
} }
/** /**
* @return CDbConnection the DB connection instance * Returns the DB connection instance used for storing session data.
* @throws CException if {@link connectionID} does not point to a valid application component. * @return Connection the DB connection instance
* @throws InvalidConfigException if [[connectionID]] does not point to a valid application component.
*/ */
protected function getDbConnection() public function getDb()
{ {
if ($this->_db !== null) { if ($this->_db === null) {
return $this->_db; $db = Yii::$app->getComponent($this->connectionID);
} elseif (($id = $this->connectionID) !== null) { if ($db instanceof Connection) {
if (($this->_db = Yii::app()->getComponent($id)) instanceof CDbConnection) { $this->_db = $db;
return $this->_db;
} else { } else {
throw new CException(Yii::t('yii', 'DbSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.', throw new InvalidConfigException("DbSession::connectionID must refer to the ID of a DB application component.");
array('{id}' => $id)));
} }
} else {
$dbFile = Yii::app()->getRuntimePath() . DIRECTORY_SEPARATOR . 'session-' . Yii::getVersion() . '.db';
return $this->_db = new CDbConnection('sqlite:' . $dbFile);
} }
return $this->_db;
} }
/** /**
* Session open handler. * Sets the DB connection used by the session component.
* Do not call this method directly. * @param Connection $value the DB connection instance
* @param string $savePath session save path
* @param string $sessionName session name
* @return boolean whether session is opened successfully
*/ */
public function openSession($savePath, $sessionName) public function setDb($value)
{ {
if ($this->autoCreateSessionTable) { $this->_db = $value;
$db = $this->getDbConnection();
$db->setActive(true);
try {
$db->createCommand()->delete($this->sessionTableName, 'expire<:expire', array(':expire' => time()));
} catch (Exception $e) {
$this->createSessionTable($db, $this->sessionTableName);
}
}
return true;
} }
/** /**
...@@ -196,10 +156,11 @@ class DbSession extends Session ...@@ -196,10 +156,11 @@ class DbSession extends Session
*/ */
public function readSession($id) public function readSession($id)
{ {
$data = $this->getDbConnection()->createCommand() $query = new Query;
->select('data') $data = $query->select(array('data'))
->from($this->sessionTableName) ->from($this->sessionTableName)
->where('expire>:expire AND id=:id', array(':expire' => time(), ':id' => $id)) ->where('expire>:expire AND id=:id', array(':expire' => time(), ':id' => $id))
->createCommand($this->getDb())
->queryScalar(); ->queryScalar();
return $data === false ? '' : $data; return $data === false ? '' : $data;
} }
...@@ -217,20 +178,26 @@ class DbSession extends Session ...@@ -217,20 +178,26 @@ class DbSession extends Session
// http://us.php.net/manual/en/function.session-set-save-handler.php // http://us.php.net/manual/en/function.session-set-save-handler.php
try { try {
$expire = time() + $this->getTimeout(); $expire = time() + $this->getTimeout();
$db = $this->getDbConnection(); $db = $this->getDb();
if ($db->createCommand()->select('id')->from($this->sessionTableName)->where('id=:id', array(':id' => $id))->queryScalar() === false) { $query = new Query;
$exists = $query->select(array('id'))
->from($this->sessionTableName)
->where(array('id' => $id))
->createCommand($db)
->queryScalar();
if ($exists === false) {
$db->createCommand()->insert($this->sessionTableName, array( $db->createCommand()->insert($this->sessionTableName, array(
'id' => $id, 'id' => $id,
'data' => $data, 'data' => $data,
'expire' => $expire, 'expire' => $expire,
)); ))->execute();
} else { } else {
$db->createCommand()->update($this->sessionTableName, array( $db->createCommand()->update($this->sessionTableName, array(
'data' => $data, 'data' => $data,
'expire' => $expire 'expire' => $expire
), 'id=:id', array(':id' => $id)); ), array('id' => $id))->execute();
} }
} catch (Exception $e) { } catch (\Exception $e) {
if (YII_DEBUG) { if (YII_DEBUG) {
echo $e->getMessage(); echo $e->getMessage();
} }
...@@ -248,8 +215,9 @@ class DbSession extends Session ...@@ -248,8 +215,9 @@ class DbSession extends Session
*/ */
public function destroySession($id) public function destroySession($id)
{ {
$this->getDbConnection()->createCommand() $this->getDb()->createCommand()
->delete($this->sessionTableName, 'id=:id', array(':id' => $id)); ->delete($this->sessionTableName, array('id' => $id))
->execute();
return true; return true;
} }
...@@ -261,8 +229,9 @@ class DbSession extends Session ...@@ -261,8 +229,9 @@ class DbSession extends Session
*/ */
public function gcSession($maxLifetime) public function gcSession($maxLifetime)
{ {
$this->getDbConnection()->createCommand() $this->getDb()->createCommand()
->delete($this->sessionTableName, 'expire<:expire', array(':expire' => time())); ->delete($this->sessionTableName, 'expire<:expire', array(':expire' => time()))
->execute();
return true; return true;
} }
} }
...@@ -9,60 +9,47 @@ ...@@ -9,60 +9,47 @@
namespace yii\web; namespace yii\web;
use Yii;
use yii\base\Component; use yii\base\Component;
use yii\base\InvalidParamException; use yii\base\InvalidParamException;
/** /**
* Session provides session-level data management and the related configurations. * Session provides session-level data management and the related configurations.
* *
* To start the session, call {@link open()}; To complete and send out session data, call {@link close()}; * To start the session, call [[open()]]; To complete and send out session data, call [[close()]];
* To destroy the session, call {@link destroy()}. * To destroy the session, call [[destroy()]].
* *
* If {@link autoStart} is set true, the session will be started automatically * If [[autoStart]] is set true, the session will be started automatically
* when the application component is initialized by the application. * when the application component is initialized by the application.
* *
* Session can be used like an array to set and get session data. For example, * Session can be used like an array to set and get session data. For example,
* <pre>
* $session=new Session;
* $session->open();
* $value1=$session['name1']; // get session variable 'name1'
* $value2=$session['name2']; // get session variable 'name2'
* foreach($session as $name=>$value) // traverse all session variables
* $session['name3']=$value3; // set session variable 'name3'
* </pre>
* *
* The following configurations are available for session: * ~~~
* <ul> * $session = new Session;
* <li>{@link setSessionID sessionID};</li> * $session->open();
* <li>{@link setSessionName sessionName};</li> * $value1 = $session['name1']; // get session variable 'name1'
* <li>{@link autoStart};</li> * $value2 = $session['name2']; // get session variable 'name2'
* <li>{@link setSavePath savePath};</li> * foreach ($session as $name => $value) // traverse all session variables
* <li>{@link setCookieParams cookieParams};</li> * $session['name3'] = $value3; // set session variable 'name3'
* <li>{@link setGCProbability gcProbability};</li> * ~~~
* <li>{@link setCookieMode cookieMode};</li>
* <li>{@link setUseTransparentSessionID useTransparentSessionID};</li>
* <li>{@link setTimeout timeout}.</li>
* </ul>
* See the corresponding setter and getter documentation for more information.
* Note, these properties must be set before the session is started.
* *
* Session can be extended to support customized session storage. * Session can be extended to support customized session storage.
* Override {@link openSession}, {@link closeSession}, {@link readSession}, * To do so, override [[useCustomStorage()]] so that it returns true, and
* {@link writeSession}, {@link destroySession} and {@link gcSession} * override these methods with the actual logic about using custom storage:
* and set [[useCustomStorage]] to true. * [[openSession()]], [[closeSession()]], [[readSession()]], [[writeSession()]],
* Then, the session data will be stored and retrieved using the above methods. * [[destroySession()]] and [[gcSession()]].
* *
* Session is a Web application component that can be accessed via * Session is a Web application component that can be accessed via
* {@link CWebApplication::getSession()}. * `Yii::$app->session`.
* *
* @property boolean $useCustomStorage Whether to use custom storage. * @property boolean $useCustomStorage read-only. Whether to use custom storage.
* @property boolean $isStarted Whether the session has started. * @property boolean $isActive Whether the session has started.
* @property string $sessionID The current session ID. * @property string $id The current session ID.
* @property string $sessionName The current session name. * @property string $name The current session name.
* @property string $savePath The current session save path, defaults to '/tmp'. * @property string $savePath The current session save path, defaults to '/tmp'.
* @property array $cookieParams The session cookie parameters. * @property array $cookieParams The session cookie parameters.
* @property string $cookieMode How to use cookie to store session ID. Defaults to 'Allow'. * @property string $cookieMode How to use cookie to store session ID. Defaults to 'Allow'.
* @property float $gCProbability The probability (percentage) that the gc (garbage collection) process is started on every session initialization, defaults to 1 meaning 1% chance. * @property float $gcProbability The probability (percentage) that the gc (garbage collection) process is started on every session initialization.
* @property boolean $useTransparentSessionID Whether transparent sid support is enabled or not, defaults to false. * @property boolean $useTransparentSessionID Whether transparent sid support is enabled or not, defaults to false.
* @property integer $timeout The number of seconds after which data will be seen as 'garbage' and cleaned up, defaults to 1440 seconds. * @property integer $timeout The number of seconds after which data will be seen as 'garbage' and cleaned up, defaults to 1440 seconds.
* @property SessionIterator $iterator An iterator for traversing the session variables. * @property SessionIterator $iterator An iterator for traversing the session variables.
...@@ -94,11 +81,9 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -94,11 +81,9 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Returns a value indicating whether to use custom session storage. * Returns a value indicating whether to use custom session storage.
* To use custom session storage, override this method and return This method should be overridden to return true if custom session storage handler should be used. * This method should be overridden to return true by child classes that implement custom session storage.
* If returning true, make sure the methods {@link openSession}, {@link closeSession}, {@link readSession}, * To implement custom session storage, override these methods: [[openSession()]], [[closeSession()]],
* {@link writeSession}, {@link destroySession}, and {@link gcSession} are overridden in child * [[readSession()]], [[writeSession()]], [[destroySession()]] and [[gcSession()]].
* class, because they will be used as the callback handlers.
* The default implementation always return false.
* @return boolean whether to use custom storage. * @return boolean whether to use custom storage.
*/ */
public function getUseCustomStorage() public function getUseCustomStorage()
...@@ -107,24 +92,34 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -107,24 +92,34 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
} }
/** /**
* Starts the session if it has not started yet. * Starts the session.
*/ */
public function open() public function open()
{ {
// this is available in PHP 5.4.0+
if (function_exists('session_status')) {
if (session_status() == PHP_SESSION_ACTIVE) {
return;
}
}
if ($this->getUseCustomStorage()) { if ($this->getUseCustomStorage()) {
@session_set_save_handler(array($this, 'openSession'), array($this, 'closeSession'), array($this, 'readSession'), array($this, 'writeSession'), array($this, 'destroySession'), array($this, 'gcSession')); @session_set_save_handler(
array($this, 'openSession'),
array($this, 'closeSession'),
array($this, 'readSession'),
array($this, 'writeSession'),
array($this, 'destroySession'),
array($this, 'gcSession')
);
} }
@session_start(); @session_start();
if (YII_DEBUG && session_id() == '') {
$message = Yii::t('yii', 'Failed to start session.'); if (session_id() == '') {
if (function_exists('error_get_last')) { $error = error_get_last();
$error = error_get_last(); $message = isset($error['message']) ? $error['message'] : 'Failed to start session.';
if (isset($error['message'])) { Yii::warning($message, __CLASS__);
$message = $error['message'];
}
}
Yii::log($message, CLogger::LEVEL_WARNING, 'system.web.Session');
} }
} }
...@@ -152,15 +147,21 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -152,15 +147,21 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* @return boolean whether the session has started * @return boolean whether the session has started
*/ */
public function getIsStarted() public function getIsActive()
{ {
return session_id() !== ''; if (function_exists('session_status')) {
// available in PHP 5.4.0+
return session_status() == PHP_SESSION_ACTIVE;
} else {
// this is not very reliable
return session_id() !== '';
}
} }
/** /**
* @return string the current session ID * @return string the current session ID
*/ */
public function getSessionID() public function getId()
{ {
return session_id(); return session_id();
} }
...@@ -168,16 +169,15 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -168,16 +169,15 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* @param string $value the session ID for the current session * @param string $value the session ID for the current session
*/ */
public function setSessionID($value) public function setId($value)
{ {
session_id($value); session_id($value);
} }
/** /**
* Updates the current session id with a newly generated one . * Updates the current session ID with a newly generated one .
* Please refer to {@link http://php.net/session_regenerate_id} for more details. * Please refer to [[http://php.net/session_regenerate_id]] for more details.
* @param boolean $deleteOldSession Whether to delete the old associated session file or not. * @param boolean $deleteOldSession Whether to delete the old associated session file or not.
* @since 1.1.8
*/ */
public function regenerateID($deleteOldSession = false) public function regenerateID($deleteOldSession = false)
{ {
...@@ -187,15 +187,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -187,15 +187,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* @return string the current session name * @return string the current session name
*/ */
public function getSessionName() public function getName()
{ {
return session_name(); return session_name();
} }
/** /**
* @param string $value the session name for the current session, must be an alphanumeric string, defaults to PHPSESSID * @param string $value the session name for the current session, must be an alphanumeric string.
* It defaults to "PHPSESSID".
*/ */
public function setSessionName($value) public function setName($value)
{ {
session_name($value); session_name($value);
} }
...@@ -209,16 +210,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -209,16 +210,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
} }
/** /**
* @param string $value the current session save path * @param string $value the current session save path. This can be either a directory name or a path alias.
* @throws CException if the path is not a valid directory * @throws InvalidParamException if the path is not a valid directory
*/ */
public function setSavePath($value) public function setSavePath($value)
{ {
if (is_dir($value)) { $path = Yii::getAlias($value);
session_save_path($value); if ($path !== false && is_dir($path)) {
session_save_path($path);
} else { } else {
throw new CException(Yii::t('yii', 'Session.savePath "{path}" is not a valid directory.', throw new InvalidParamException("Session save path is not a valid directory: $value");
array('{path}' => $value)));
} }
} }
...@@ -235,7 +236,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -235,7 +236,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
* Sets the session cookie parameters. * Sets the session cookie parameters.
* The effect of this method only lasts for the duration of the script. * The effect of this method only lasts for the duration of the script.
* Call this method before the session starts. * Call this method before the session starts.
* @param array $value cookie parameters, valid keys include: lifetime, path, domain, secure. * @param array $value cookie parameters, valid keys include: lifetime, path, domain, secure and httponly.
* @throws InvalidParamException if the parameters are incomplete.
* @see http://us2.php.net/manual/en/function.session-set-cookie-params.php * @see http://us2.php.net/manual/en/function.session-set-cookie-params.php
*/ */
public function setCookieParams($value) public function setCookieParams($value)
...@@ -243,10 +245,10 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -243,10 +245,10 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
$data = session_get_cookie_params(); $data = session_get_cookie_params();
extract($data); extract($data);
extract($value); extract($value);
if (isset($httponly)) { if (isset($lifetime, $path, $domain, $secure, $httponly)) {
session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly); session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
} else { } else {
session_set_cookie_params($lifetime, $path, $domain, $secure); throw new InvalidParamException('Please make sure these parameters are provided: lifetime, path, domain, secure and httponly.');
} }
} }
...@@ -348,7 +350,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -348,7 +350,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session open handler. * Session open handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @param string $savePath session save path * @param string $savePath session save path
* @param string $sessionName session name * @param string $sessionName session name
...@@ -361,7 +363,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -361,7 +363,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session close handler. * Session close handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @return boolean whether session is closed successfully * @return boolean whether session is closed successfully
*/ */
...@@ -372,7 +374,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -372,7 +374,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session read handler. * Session read handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @param string $id session ID * @param string $id session ID
* @return string the session data * @return string the session data
...@@ -384,7 +386,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -384,7 +386,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session write handler. * Session write handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @param string $id session ID * @param string $id session ID
* @param string $data session data * @param string $data session data
...@@ -397,7 +399,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -397,7 +399,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session destroy handler. * Session destroy handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @param string $id session ID * @param string $id session ID
* @return boolean whether session is destroyed successfully * @return boolean whether session is destroyed successfully
...@@ -409,7 +411,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -409,7 +411,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
/** /**
* Session GC (garbage collection) handler. * Session GC (garbage collection) handler.
* This method should be overridden if [[useCustomStorage]] is set true. * This method should be overridden if [[useCustomStorage()]] returns true.
* Do not call this method directly. * Do not call this method directly.
* @param integer $maxLifetime the number of seconds after which data will be seen as 'garbage' and cleaned up. * @param integer $maxLifetime the number of seconds after which data will be seen as 'garbage' and cleaned up.
* @return boolean whether session is GCed successfully * @return boolean whether session is GCed successfully
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment