[HttpFoundation] Split session handler callbacks to separate object.

This commit is contained in:
Drak 2012-03-03 08:39:20 +05:45
parent bb30a447c5
commit 23267077ff
4 changed files with 77 additions and 44 deletions

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Symfony\Component\HttpFoundation\Session\Storage; namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/** /**
* PdoSessionStorage. * PdoSessionStorage.
@ -17,7 +17,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage;
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
* @author Michael Williams <michael.williams@funsational.com> * @author Michael Williams <michael.williams@funsational.com>
*/ */
class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface class PdoSessionHandler implements \SessionHandlerInterface
{ {
/** /**
* PDO instance. * PDO instance.
@ -58,8 +58,6 @@ class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandle
'db_data_col' => 'sess_data', 'db_data_col' => 'sess_data',
'db_time_col' => 'sess_time', 'db_time_col' => 'sess_time',
), $dbOptions); ), $dbOptions);
parent::__construct($options);
} }
/** /**

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\HttpFoundation\Session\Storage; namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
/** /**
* MockArraySessionStorage mocks the session for unit tests. * MockArraySessionStorage mocks the session for unit tests.
* *
@ -23,7 +25,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage;
* @author Bulat Shakirzyanov <mallluhuct@gmail.com> * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
* @author Drak <drak@zikula.org> * @author Drak <drak@zikula.org>
*/ */
class MockArraySessionStorage extends AbstractSessionStorage class MockArraySessionStorage extends SessionStorage
{ {
/** /**
* @var string * @var string
@ -35,6 +37,16 @@ class MockArraySessionStorage extends AbstractSessionStorage
*/ */
protected $sessionData = array(); protected $sessionData = array();
public function __construct(array $options = array())
{
parent::__construct($options, new NullSessionHandler());
}
/**
* Sets the session data.
*
* @param array $array
*/
public function setSessionData(array $array) public function setSessionData(array $array)
{ {
$this->sessionData = $array; $this->sessionData = $array;

View File

@ -33,7 +33,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
* @param string $savePath Path of directory to save session files. * @param string $savePath Path of directory to save session files.
* @param array $options Session options. * @param array $options Session options.
* *
* @see AbstractSessionStorage::__construct() * @see SessionStorage::__construct()
*/ */
public function __construct($savePath = null, array $options = array()) public function __construct($savePath = null, array $options = array())
{ {

View File

@ -12,20 +12,16 @@
namespace Symfony\Component\HttpFoundation\Session\Storage; namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
/** /**
* This provides a base class for session attribute storage. * This provides a base class for session attribute storage.
* *
* This can be used to implement internal PHP session handlers
* provided by PHP extensions or custom session save handlers
* implementing the \SessionHandlerInterface
*
* @see http://php.net/session.customhandler
* @see http://php.net/sessionhandlerinterface
*
* @author Drak <drak@zikula.org> * @author Drak <drak@zikula.org>
*/ */
abstract class AbstractSessionStorage implements SessionStorageInterface class SessionStorage implements SessionStorageInterface
{ {
/** /**
* Array of SessionBagInterface * Array of SessionBagInterface
@ -49,6 +45,11 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
*/ */
protected $closed = false; protected $closed = false;
/**
* @var AbstractProxy
*/
protected $saveHandler;
/** /**
* Constructor. * Constructor.
* *
@ -75,7 +76,6 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
* hash_function, "0" * hash_function, "0"
* name, "PHPSESSID" * name, "PHPSESSID"
* referer_check, "" * referer_check, ""
* save_path, ""
* serialize_handler, "php" * serialize_handler, "php"
* use_cookies, "1" * use_cookies, "1"
* use_only_cookies, "1" * use_only_cookies, "1"
@ -89,12 +89,23 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
* *
* @param array $options Session configuration options. * @param array $options Session configuration options.
* @param $handler SessionHandlerInterface.
*/ */
public function __construct(array $options = array()) public function __construct(array $options = array(), $handler = null)
{ {
$this->setOptions($options); $this->setOptions($options);
$this->registerSaveHandlers();
$this->registerShutdownFunction(); $this->setSaveHandler($handler);
}
/**
* Gets the save handler instance.
*
* @return AbstractProxy
*/
public function getSaveHandler()
{
return $this->saveHandler;
} }
/** /**
@ -117,6 +128,10 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
$this->loadSession(); $this->loadSession();
if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
$this->saveHandler->setActive(false);
}
$this->started = true; $this->started = true;
$this->closed = false; $this->closed = false;
@ -149,6 +164,11 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
public function save() public function save()
{ {
session_write_close(); session_write_close();
if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
$this->saveHandler->setActive(false);
}
$this->closed = true; $this->closed = true;
} }
@ -230,7 +250,7 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
'entropy_file', 'entropy_length', 'gc_divisor', 'entropy_file', 'entropy_length', 'gc_divisor',
'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
'hash_function', 'name', 'referer_check', 'hash_function', 'name', 'referer_check',
'save_path', 'serialize_handler', 'use_cookies', 'serialize_handler', 'use_cookies',
'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) { 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) {
@ -240,7 +260,7 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
} }
/** /**
* Registers this storage device as a PHP session handler. * Registers save handler as a PHP session handler.
* *
* To use internal PHP session save handlers, override this method using ini_set with * To use internal PHP session save handlers, override this method using ini_set with
* session.save_handlers and session.save_path e.g. * session.save_handlers and session.save_path e.g.
@ -250,34 +270,37 @@ abstract class AbstractSessionStorage implements SessionStorageInterface
* *
* @see http://php.net/session-set-save-handler * @see http://php.net/session-set-save-handler
* @see http://php.net/sessionhandlerinterface * @see http://php.net/sessionhandlerinterface
* @see http://php.net/sessionhandler
*
* @param object $saveHandler
*/ */
protected function registerSaveHandlers() public function setSaveHandler($saveHandler)
{ {
// note this can be reset to PHP's control using ini_set('session.save_handler', 'files'); // Wrap $saveHandler in proxy
// so long as ini_set() is called before the session is started. if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
if ($this instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler);
session_set_save_handler( } else {
array($this, 'open'), $saveHandler = new NativeProxy($saveHandler);
array($this, 'close'),
array($this, 'read'),
array($this, 'write'),
array($this, 'destroy'),
array($this, 'gc')
);
} }
}
/** $this->saveHandler = $saveHandler;
* Registers PHP shutdown function.
* if ($this->saveHandler instanceof \SessionHandlerInterface) {
* This method is required to avoid strange issues when using PHP objects as if (version_compare(phpversion(), '5.4.0', '>=')) {
* session save handlers. session_set_save_handler($this->saveHandler, true);
* } else {
* @see http://php.net/register-shutdown-function session_set_save_handler(
*/ array($this->saveHandler, 'open'),
protected function registerShutdownFunction() array($this->saveHandler, 'close'),
{ array($this->saveHandler, 'read'),
register_shutdown_function('session_write_close'); array($this->saveHandler, 'write'),
array($this->saveHandler, 'destroy'),
array($this->saveHandler, 'gc')
);
register_shutdown_function('session_write_close');
}
}
} }
/** /**