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.
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/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);
+ }
+}
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/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.'/*')));
- }
-}
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/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);
+ }
+ }
+}
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());
}