From 23267077ff3c9f85e21bf972b7e84d0bfa91357b Mon Sep 17 00:00:00 2001 From: Drak Date: Sat, 3 Mar 2012 08:39:20 +0545 Subject: [PATCH] [HttpFoundation] Split session handler callbacks to separate object. --- .../PdoSessionHandler.php} | 6 +- .../Storage/MockArraySessionStorage.php | 14 ++- .../Storage/MockFileSessionStorage.php | 2 +- ...tSessionStorage.php => SessionStorage.php} | 99 ++++++++++++------- 4 files changed, 77 insertions(+), 44 deletions(-) rename src/Symfony/Component/HttpFoundation/Session/Storage/{PdoSessionStorage.php => Handler/PdoSessionHandler.php} (97%) rename src/Symfony/Component/HttpFoundation/Session/Storage/{AbstractSessionStorage.php => SessionStorage.php} (75%) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php similarity index 97% rename from src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 6465231912..8175090da0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/PdoSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpFoundation\Session\Storage; +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * PdoSessionStorage. @@ -17,7 +17,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * @author Fabien Potencier * @author Michael Williams */ -class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandlerInterface +class PdoSessionHandler implements \SessionHandlerInterface { /** * PDO instance. @@ -58,8 +58,6 @@ class PdoSessionStorage extends AbstractSessionStorage implements \SessionHandle 'db_data_col' => 'sess_data', 'db_time_col' => 'sess_time', ), $dbOptions); - - parent::__construct($options); } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index 2447418c84..077fa0f14e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; + /** * MockArraySessionStorage mocks the session for unit tests. * @@ -23,7 +25,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; * @author Bulat Shakirzyanov * @author Drak */ -class MockArraySessionStorage extends AbstractSessionStorage +class MockArraySessionStorage extends SessionStorage { /** * @var string @@ -35,6 +37,16 @@ class MockArraySessionStorage extends AbstractSessionStorage */ 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) { $this->sessionData = $array; diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index c7c74ddd99..184f76e747 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -33,7 +33,7 @@ class MockFileSessionStorage extends MockArraySessionStorage * @param string $savePath Path of directory to save session files. * @param array $options Session options. * - * @see AbstractSessionStorage::__construct() + * @see SessionStorage::__construct() */ public function __construct($savePath = null, array $options = array()) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorage.php similarity index 75% rename from src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php rename to src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorage.php index 4f8fde308f..f34f5bccf0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/AbstractSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorage.php @@ -12,20 +12,16 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; 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 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 */ -abstract class AbstractSessionStorage implements SessionStorageInterface +class SessionStorage implements SessionStorageInterface { /** * Array of SessionBagInterface @@ -49,6 +45,11 @@ abstract class AbstractSessionStorage implements SessionStorageInterface */ protected $closed = false; + /** + * @var AbstractProxy + */ + protected $saveHandler; + /** * Constructor. * @@ -75,7 +76,6 @@ abstract class AbstractSessionStorage implements SessionStorageInterface * hash_function, "0" * name, "PHPSESSID" * referer_check, "" - * save_path, "" * serialize_handler, "php" * use_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=" * * @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->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(); + if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { + $this->saveHandler->setActive(false); + } + $this->started = true; $this->closed = false; @@ -149,6 +164,11 @@ abstract class AbstractSessionStorage implements SessionStorageInterface public function save() { session_write_close(); + + if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) { + $this->saveHandler->setActive(false); + } + $this->closed = true; } @@ -230,7 +250,7 @@ abstract class AbstractSessionStorage implements SessionStorageInterface 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'name', 'referer_check', - 'save_path', 'serialize_handler', 'use_cookies', + 'serialize_handler', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', '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 * 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/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'); - // so long as ini_set() is called before the session is started. - if ($this instanceof \SessionHandlerInterface) { - session_set_save_handler( - array($this, 'open'), - array($this, 'close'), - array($this, 'read'), - array($this, 'write'), - array($this, 'destroy'), - array($this, 'gc') - ); + // Wrap $saveHandler in proxy + if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { + $saveHandler = new SessionHandlerProxy($saveHandler); + } else { + $saveHandler = new NativeProxy($saveHandler); } - } - /** - * Registers PHP shutdown function. - * - * This method is required to avoid strange issues when using PHP objects as - * session save handlers. - * - * @see http://php.net/register-shutdown-function - */ - protected function registerShutdownFunction() - { - register_shutdown_function('session_write_close'); + $this->saveHandler = $saveHandler; + + if ($this->saveHandler instanceof \SessionHandlerInterface) { + if (version_compare(phpversion(), '5.4.0', '>=')) { + session_set_save_handler($this->saveHandler, true); + } else { + session_set_save_handler( + array($this->saveHandler, 'open'), + array($this->saveHandler, 'close'), + array($this->saveHandler, 'read'), + array($this->saveHandler, 'write'), + array($this->saveHandler, 'destroy'), + array($this->saveHandler, 'gc') + ); + + register_shutdown_function('session_write_close'); + } + } } /**