From fbee4cf700e3f01b59c790595e2b5c2d84ef2fb0 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 13 Jul 2012 14:52:46 +0100 Subject: [PATCH 1/5] Restore NativeFileSessionHandler Partial revert "[HttpFoundation] Removed Native*Handler session save handler classes" This partially reverts commit b2cc580be7614e80d9009126937c7c24aa0741c6. --- .../Handler/NativeFileSessionHandler.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php new file mode 100644 index 0000000000..422e3a79a6 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * NativeFileSessionHandler. + * + * Native session handler using PHP's built in file storage. + * + * @author Drak + */ +class NativeFileSessionHandler extends NativeSessionHandler +{ + /** + * Constructor. + * + * @param string $savePath Path of directory to save session files. Default null will leave setting as defined by PHP. + */ + public function __construct($savePath = null) + { + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } + + if ($savePath && !is_dir($savePath)) { + mkdir($savePath, 0777, true); + } + + ini_set('session.save_handler', 'files'); + ini_set('session.save_path', $savePath); + } +} From 39813a0a05440013f80c1637a8151f127c2a21f6 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 13 Jul 2012 14:54:32 +0100 Subject: [PATCH 2/5] Revert "[FrameworkBundle] Refactor session file handler service name and update changelogs" This partially reverts commit 13a2c82f01a8d9c7885bd4afe268b2bd75a58e55. --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 +- .../Bundle/FrameworkBundle/Resources/config/session.xml | 5 ++--- src/Symfony/Component/HttpFoundation/CHANGELOG.md | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index da9db7ca3e..16039c92ee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -26,7 +26,7 @@ CHANGELOG * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', 'httponly' are now prefixed with cookie_ when dumped to the container * Added `handler_id` configuration under `session` key to represent `session.handler` - service, defaults to `session.handler.file`. + service, defaults to `session.handler.native_file`. * Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session configuration. This means session garbage collection has a `gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 27631583d1..871ea3ab9c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -10,7 +10,7 @@ Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage - Symfony\Component\HttpFoundation\Session\Storage\Handler\FileSessionHandler + Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler Symfony\Bundle\FrameworkBundle\EventListener\SessionListener @@ -34,7 +34,7 @@ %kernel.cache_dir%/sessions - + %session.save_path% @@ -45,6 +45,5 @@ - diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 5525f2b057..94f64815fb 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -22,7 +22,8 @@ CHANGELOG * [BC BREAK] Moved all session related classes and interfaces into own namespace, as `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. - * SessionHandlers must implement `\SessionHandlerInterface`. + * SessionHandlers must implement `\SessionHandlerInterface` or extend from the + `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. * Added internal storage driver proxy mechanism for forward compatibility with PHP 5.4 `\SessionHandler` class. * Added session handlers for custom Memcache, Memcached and Null session save handlers. From 345678786ef030b88c54dc33323eb0fe2a0c14b8 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 13 Jul 2012 14:58:58 +0100 Subject: [PATCH 3/5] Partially revert "[HttpFoundation][Sessions] Refactored tests" This partially reverts commit 3c8cc0a1a091d6adeab64e271b1b7cdb234c153b. --- .../Storage/Handler/NativeSessionHandler.php | 24 +++++++++ .../Storage/MockFileSessionStorage.php | 53 ++++++++++++------- .../Handler/NativeFileSessionHandlerTest.php | 49 +++++++++++++++++ .../Storage/MockFileSessionStorageTest.php | 12 ++--- .../Storage/NativeSessionStorageTest.php | 3 +- 5 files changed, 115 insertions(+), 26 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php new file mode 100644 index 0000000000..1260ad0d29 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Adds SessionHandler functionality if available. + * + * @see http://php.net/sessionhandler + */ + +if (version_compare(phpversion(), '5.4.0', '>=')) { + class NativeSessionHandler extends \SessionHandler {} +} else { + class NativeSessionHandler {} +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index 23b86b3b7f..80aa44b06b 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -11,9 +11,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\FileSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; - /** * MockFileSessionStorage is used to mock sessions for * functional testing when done in a single PHP process. @@ -28,27 +25,35 @@ use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; class MockFileSessionStorage extends MockArraySessionStorage { /** - * @var FileSessionHandler + * @var string */ - private $handler; + private $savePath; + + /** + * @var array + */ + private $sessionData; /** * Constructor. * - * @param string $savePath Path of directory to save session files. - * @param string $name Session name. - * @param FileSessionHandler $handler Save handler - * @param MetadataBag $metaData Metadatabag + * @param string $savePath Path of directory to save session files. + * @param string $name Session name. + * @param MetadataBag $metaBag MetadataBag instance. */ - public function __construct($savePath = null, $name = 'MOCKSESSID', FileSessionHandler $handler = null, MetadataBag $metaData = null) + public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null) { - if (null == $handler) { - $handler = new FileSessionHandler($savePath, 'mocksess_'); + if (null === $savePath) { + $savePath = sys_get_temp_dir(); } - $this->handler = $handler; + if (!is_dir($savePath)) { + mkdir($savePath, 0777, true); + } - parent::__construct($name, $metaData); + $this->savePath = $savePath; + + parent::__construct($name, $metaBag); } /** @@ -92,7 +97,7 @@ class MockFileSessionStorage extends MockArraySessionStorage */ public function save() { - $this->handler->write($this->id, serialize($this->data)); + file_put_contents($this->getFilePath(), serialize($this->data)); // this is needed for Silex, where the session object is re-used across requests // in functional tests. In Symfony, the container is rebooted, so we don't have @@ -106,7 +111,19 @@ class MockFileSessionStorage extends MockArraySessionStorage */ private function destroy() { - $this->handler->destroy($this->id); + if (is_file($this->getFilePath())) { + unlink($this->getFilePath()); + } + } + + /** + * Calculate path to file. + * + * @return string File path + */ + private function getFilePath() + { + return $this->savePath.'/'.$this->id.'.mocksess'; } /** @@ -114,8 +131,8 @@ class MockFileSessionStorage extends MockArraySessionStorage */ private function read() { - $data = $this->handler->read($this->id); - $this->data = $data ? unserialize($data) : array(); + $filePath = $this->getFilePath(); + $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); $this->loadSession(); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php new file mode 100644 index 0000000000..7bdf3a1e3f --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Test class for NativeFileSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeFileSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testConstruct() + { + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('files', ini_get('session.save_handler')); + } else { + $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); + $this->assertEquals('TESTING', ini_get('session.name')); + } + + public function testConstructDefault() + { + $path = ini_get('session.save_path'); + $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler()); + + $this->assertEquals($path, ini_get('session.save_path')); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php index 7bfe6a779d..f18089d92a 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php @@ -28,7 +28,7 @@ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase private $sessionDir; /** - * @var MockFileSessionStorage + * @var FileMockSessionStorage */ protected $storage; @@ -40,14 +40,12 @@ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase protected function tearDown() { - foreach (glob($this->sessionDir.'/mocksess_*') as $file) { - unlink($file); - } - - rmdir($this->sessionDir); - $this->sessionDir = null; $this->storage = null; + array_map('unlink', glob($this->sessionDir.'/*.session')); + if (is_dir($this->sessionDir)) { + rmdir($this->sessionDir); + } } public function testStart() diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 528a1d7b02..4b88a237a0 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; @@ -136,8 +137,8 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } - ini_set('session.save_handler', 'files'); $storage = $this->getStorage(); + $storage->setSaveHandler(new NativeFileSessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy', $storage->getSaveHandler()); } From 653821a11b68f2bdfd1829d5e5b89b5e9db668c8 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 13 Jul 2012 15:33:16 +0100 Subject: [PATCH 4/5] [HttpFoundation] Remove FileSessionHandler This driver is inferior to native handling --- .../Storage/Handler/FileSessionHandler.php | 116 ------------------ .../Handler/FileSessionHandlerTest.php | 106 ---------------- 2 files changed, 222 deletions(-) delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/FileSessionHandler.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/FileSessionHandlerTest.php diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/FileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/FileSessionHandler.php deleted file mode 100644 index 4c621256ec..0000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/FileSessionHandler.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * FileSessionHandler. - * - * @author Drak - */ -class FileSessionHandler implements \SessionHandlerInterface -{ - /** - * @var string - */ - private $savePath; - - /** - * @var string - */ - private $prefix; - - /** - * Constructor. - * - * @param string $savePath Path of directory to save session files. - * @param string $prefix - */ - public function __construct($savePath = null, $prefix = 'sess_') - { - if (null === $savePath) { - $savePath = sys_get_temp_dir(); - } - - $this->savePath = $savePath; - if (false === is_dir($this->savePath)) { - mkdir($this->savePath, 0777, true); - } - - $this->prefix = $prefix; - } - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function read($id) - { - $file = $this->getPath().$id; - - return is_readable($file) ? file_get_contents($file) : ''; - } - - /** - * {@inheritdoc} - */ - public function write($id, $data) - { - return false === file_put_contents($this->getPath().$id, $data) ? false : true; - } - - /** - * {@inheritdoc} - */ - public function destroy($id) - { - $file = $this->getPath().$id; - if (is_file($file)) { - unlink($file); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - foreach (glob($this->getPath().'*') as $file) { - if ((filemtime($file) + $maxlifetime) < time()) { - unlink($file); - } - } - - return true; - } - - private function getPath() - { - return $this->savePath.'/'.$this->prefix; - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/FileSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/FileSessionHandlerTest.php deleted file mode 100644 index d935b34bd2..0000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/FileSessionHandlerTest.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use Symfony\Component\HttpFoundation\Session\Storage\Handler\FileSessionHandler; - -/** - * Test class for FileSessionHandler. - * - * @author Drak - */ -class FileSessionStorageTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var FileSessionHandler - */ - private $handler; - - /** - * @var string - */ - private $path; - - public function setUp() - { - $this->path = sys_get_temp_dir().'/filesessionhandler'; - $this->handler = new FileSessionHandler($this->path, 'mocksess_'); - - parent::setUp(); - } - - public function tearDown() - { - foreach (glob($this->path.'/*') as $file) { - unlink($file); - } - - rmdir($this->path); - - $this->handler = null; - } - - public function test__construct() - { - $this->assertTrue(is_dir($this->path)); - } - - public function testOpen() - { - $this->assertTrue($this->handler->open('a', 'b')); - } - - public function testClose() - { - $this->assertTrue($this->handler->close()); - } - - public function testReadWrite() - { - $this->assertEmpty($this->handler->read('123')); - $this->assertTrue($this->handler->write('123', 'data')); - $this->assertEquals('data', $this->handler->read('123')); - } - - public function testDestroy() - { - $this->handler->write('456', 'data'); - $this->handler->destroy('123'); - $this->assertEquals('data', $this->handler->read('456')); - $this->handler->destroy('456'); - $this->assertEmpty($this->handler->read('456')); - } - - public function testGc() - { - $prefix = $this->path.'/mocksess_'; - $this->handler->write('1', 'data'); - touch($prefix.'1', time()-86400); - - $this->handler->write('2', 'data'); - touch($prefix.'2', time()-3600); - - $this->handler->write('3', 'data'); - touch($prefix.'3', time()-300); - - $this->handler->write('4', 'data'); - - $this->handler->gc(90000); - $this->assertEquals(4, count(glob($this->path.'/*'))); - - $this->handler->gc(4000); - $this->assertEquals(3, count(glob($this->path.'/*'))); - - $this->handler->gc(200); - $this->assertEquals(1, count(glob($this->path.'/*'))); - } -} From a351362f198553252aa78f1f5afdfbf8032c7ef0 Mon Sep 17 00:00:00 2001 From: Drak Date: Fri, 13 Jul 2012 17:30:53 +0100 Subject: [PATCH 5/5] [HttpFoundation] Add NativeSessionHandler tests --- .../Handler/NativeSessionHandlerTest.php | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php new file mode 100644 index 0000000000..7880615db0 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; + +/** + * Test class for NativeSessionHandler. + * + * @author Drak + * + * @runTestsInSeparateProcesses + */ +class NativeSessionHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testConstruct() + { + $handler = new NativeSessionHandler(); + + // note for PHPUnit optimisers - the use of assertTrue/False + // here is deliberate since the tests do not require the classes to exist - drak + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertFalse($handler instanceof \SessionHandler); + $this->assertTrue($handler instanceof NativeSessionHandler); + } else { + $this->assertTrue($handler instanceof \SessionHandler); + $this->assertTrue($handler instanceof NativeSessionHandler); + } + } +}